diff --git a/octavia/amphorae/backends/agent/api_server/osutils.py b/octavia/amphorae/backends/agent/api_server/osutils.py index d4c881ce99..821cf41871 100644 --- a/octavia/amphorae/backends/agent/api_server/osutils.py +++ b/octavia/amphorae/backends/agent/api_server/osutils.py @@ -100,6 +100,7 @@ class BaseOS(object): broadcast=broadcast, netmask=netmask, gateway=gateway, + network=utils.ip_netmask_to_cidr(vip, netmask), mtu=mtu, vrrp_ip=vrrp_ip, vrrp_ipv6=vrrp_version is 6, @@ -385,7 +386,7 @@ class RH(BaseOS): self.write_static_routes_interface_file( routes_interface_file_path, primary_interface, - render_host_routes, template_routes, gateway, vip) + render_host_routes, template_routes, gateway, vip, netmask) route_rules_interface_file_path = ( self.get_route_rules_interface_file(primary_interface)) @@ -393,11 +394,12 @@ class RH(BaseOS): self.write_static_routes_interface_file( route_rules_interface_file_path, primary_interface, - render_host_routes, template_rules, gateway, vip) + render_host_routes, template_rules, gateway, vip, netmask) def write_static_routes_interface_file(self, interface_file_path, interface, host_routes, - template_routes, gateway, vip): + template_routes, gateway, + vip, netmask): # write static routes interface file mode = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH @@ -414,6 +416,7 @@ class RH(BaseOS): interface=interface, host_routes=host_routes, gateway=gateway, + network=utils.ip_netmask_to_cidr(vip, netmask), vip=vip, ) text_file.write(text) @@ -441,7 +444,7 @@ class RH(BaseOS): self.write_static_routes_interface_file( routes_interface_file_path, netns_interface, - host_routes, template_routes, None, None) + host_routes, template_routes, None, None, None) def bring_interfaces_up(self, ip, primary_interface, secondary_interface): if ip.version == 4: diff --git a/octavia/amphorae/backends/agent/api_server/templates/plug_vip_ethX.conf.j2 b/octavia/amphorae/backends/agent/api_server/templates/plug_vip_ethX.conf.j2 index 9b1ab4f286..6aa78f426c 100644 --- a/octavia/amphorae/backends/agent/api_server/templates/plug_vip_ethX.conf.j2 +++ b/octavia/amphorae/backends/agent/api_server/templates/plug_vip_ethX.conf.j2 @@ -42,8 +42,10 @@ broadcast {{ broadcast }} netmask {{ netmask }} # Add a source routing table to allow members to access the VIP {%- if gateway %} +post-up /sbin/ip {{ '-6 ' if vip_ipv6 }}route add {{ network }} dev {{ interface }} src {{ vip }} scope link table 1 post-up /sbin/ip {{ '-6 ' if vip_ipv6 }}route add default via {{ gateway }} dev {{ interface }} onlink table 1 post-down /sbin/ip {{ '-6 ' if vip_ipv6 }}route del default via {{ gateway }} dev {{ interface }} onlink table 1 +post-down /sbin/ip {{ '-6 ' if vip_ipv6 }}route del {{ network }} dev {{ interface }} src {{ vip }} scope link table 1 {%- endif %} {%- for hr in host_routes %} post-up /sbin/ip {{ '-6 ' if vip_ipv6 }}route add {{ hr.network }} via {{ hr.gw }} dev {{ interface }} onlink table 1 diff --git a/octavia/amphorae/backends/agent/api_server/templates/rh_route_ethX.conf.j2 b/octavia/amphorae/backends/agent/api_server/templates/rh_route_ethX.conf.j2 index 52418b6de8..140bed2d0c 100644 --- a/octavia/amphorae/backends/agent/api_server/templates/rh_route_ethX.conf.j2 +++ b/octavia/amphorae/backends/agent/api_server/templates/rh_route_ethX.conf.j2 @@ -19,6 +19,7 @@ {%- endfor %} # Add a source routing table to allow members to access the VIP {%- if gateway %} +{{ network }} dev {{ interface }} src {{ vip }} scope link table 1 default table 1 via {{ gateway }} dev {{ interface }} {%- endif %} {%- for hr in host_routes %} diff --git a/octavia/common/utils.py b/octavia/common/utils.py index 73f3f85ec2..2aa005f816 100644 --- a/octavia/common/utils.py +++ b/octavia/common/utils.py @@ -78,6 +78,15 @@ def netmask_to_prefix(netmask): return netaddr.IPAddress(netmask).netmask_bits() +def ip_netmask_to_cidr(ip, netmask): + net = netaddr.IPNetwork("0.0.0.0/0") + if ip and netmask: + net = netaddr.IPNetwork( + "{ip}/{netmask}".format(ip=ip, netmask=netmask) + ) + return "{ip}/{netmask}".format(ip=net.network, netmask=net.prefixlen) + + class exception_logger(object): """Wrap a function and log raised exception diff --git a/octavia/tests/functional/amphorae/backend/agent/api_server/test_server.py b/octavia/tests/functional/amphorae/backend/agent/api_server/test_server.py index 94f6cb57be..6de55833ef 100644 --- a/octavia/tests/functional/amphorae/backend/agent/api_server/test_server.py +++ b/octavia/tests/functional/amphorae/backend/agent/api_server/test_server.py @@ -1707,10 +1707,14 @@ class TestServerTestCase(base.TestCase): 'netmask 255.255.255.0\n' '# Add a source routing table to allow members to ' 'access the VIP\n' + 'post-up /sbin/ip route add 203.0.113.0/24 ' + 'dev eth1 src 203.0.113.2 scope link table 1\n' 'post-up /sbin/ip route add default via 203.0.113.1 ' 'dev eth1 onlink table 1\n' 'post-down /sbin/ip route del default via 203.0.113.1 ' 'dev eth1 onlink table 1\n' + 'post-down /sbin/ip route del 203.0.113.0/24 ' + 'dev eth1 src 203.0.113.2 scope link table 1\n' 'post-up /sbin/ip route add 203.0.114.0/24 ' 'via 203.0.113.5 dev eth1 onlink table 1\n' 'post-down /sbin/ip route del 203.0.114.0/24 ' @@ -1804,10 +1808,14 @@ class TestServerTestCase(base.TestCase): 'netmask 255.255.255.0\n' '# Add a source routing table to allow members to ' 'access the VIP\n' + 'post-up /sbin/ip route add 203.0.113.0/24 ' + 'dev eth1 src 203.0.113.2 scope link table 1\n' 'post-up /sbin/ip route add default via 203.0.113.1 ' 'dev eth1 onlink table 1\n' 'post-down /sbin/ip route del default via 203.0.113.1 ' 'dev eth1 onlink table 1\n' + 'post-down /sbin/ip route del 203.0.113.0/24 ' + 'dev eth1 src 203.0.113.2 scope link table 1\n' 'post-up /sbin/ip rule add from 203.0.113.2/32 table 1 ' 'priority 100\n' 'post-down /sbin/ip rule del from 203.0.113.2/32 table 1 ' @@ -2037,10 +2045,16 @@ class TestServerTestCase(base.TestCase): 'netmask 32\n' '# Add a source routing table to allow members to access ' 'the VIP\n' + 'post-up /sbin/ip -6 route add 2001:db8::/32 ' + 'dev eth1 src 2001:0db8:0000:0000:0000:0000:0000:0002 ' + 'scope link table 1\n' 'post-up /sbin/ip -6 route add default via 2001:db8::1 ' 'dev eth1 onlink table 1\n' 'post-down /sbin/ip -6 route del default via 2001:db8::1 ' 'dev eth1 onlink table 1\n' + 'post-down /sbin/ip -6 route del 2001:db8::/32 ' + 'dev eth1 src 2001:0db8:0000:0000:0000:0000:0000:0002 ' + 'scope link table 1\n' 'post-up /sbin/ip -6 route add 2001:db9::/32 via ' '2001:db8::5 dev eth1 onlink table 1\n' 'post-down /sbin/ip -6 route del 2001:db9::/32 ' @@ -2137,10 +2151,16 @@ class TestServerTestCase(base.TestCase): 'netmask 32\n' '# Add a source routing table to allow members to access ' 'the VIP\n' + 'post-up /sbin/ip -6 route add 2001:db8::/32 ' + 'dev eth1 src 2001:0db8:0000:0000:0000:0000:0000:0002 ' + 'scope link table 1\n' 'post-up /sbin/ip -6 route add default via 2001:db8::1 ' 'dev eth1 onlink table 1\n' 'post-down /sbin/ip -6 route del default via 2001:db8::1 ' 'dev eth1 onlink table 1\n' + 'post-down /sbin/ip -6 route del 2001:db8::/32 ' + 'dev eth1 src 2001:0db8:0000:0000:0000:0000:0000:0002 ' + 'scope link table 1\n' 'post-up /sbin/ip -6 rule add from ' '2001:0db8:0000:0000:0000:0000:0000:0002/32 table 1 ' 'priority 100\n' diff --git a/octavia/tests/unit/common/test_utils.py b/octavia/tests/unit/common/test_utils.py index f76c961191..832f6ee6f8 100644 --- a/octavia/tests/unit/common/test_utils.py +++ b/octavia/tests/unit/common/test_utils.py @@ -48,3 +48,15 @@ class TestConfig(base.TestCase): self.assertEqual(utils.netmask_to_prefix('255.255.0.0'), 16) self.assertEqual(utils.netmask_to_prefix('255.255.255.0'), 24) self.assertEqual(utils.netmask_to_prefix('255.255.255.128'), 25) + + def test_ip_netmask_to_cidr(self): + self.assertEqual('10.0.0.0/8', + utils.ip_netmask_to_cidr('10.0.0.1', '255.0.0.0')) + self.assertEqual('10.0.0.0/9', + utils.ip_netmask_to_cidr('10.0.0.1', '255.128.0.0')) + self.assertEqual('10.0.0.0/16', + utils.ip_netmask_to_cidr('10.0.0.1', '255.255.0.0')) + self.assertEqual('10.0.0.0/20', + utils.ip_netmask_to_cidr('10.0.0.1', '255.255.240.0')) + self.assertEqual('10.0.0.0/30', utils.ip_netmask_to_cidr( + '10.0.0.1', '255.255.255.252')) diff --git a/releasenotes/notes/fix-route-table-b2ec0aa7b92d2abc.yaml b/releasenotes/notes/fix-route-table-b2ec0aa7b92d2abc.yaml new file mode 100644 index 0000000000..7a49fbd6f8 --- /dev/null +++ b/releasenotes/notes/fix-route-table-b2ec0aa7b92d2abc.yaml @@ -0,0 +1,5 @@ +--- +fixes: + - | + Fixes an issue where VIP return traffic was always routed, if a gateway + was defined, through the gateway address even if it was local traffic.