From 19375b3e78ad6b635793b716e5ecabd53dc73a76 Mon Sep 17 00:00:00 2001 From: Slawek Kaplonski Date: Thu, 8 Jul 2021 15:53:39 +0200 Subject: [PATCH] [DVR] Set arp entries only for single IPs given as allowed addr pair In allowed address pairs of the port there can be given not single IP address but whole CIDR. In such case ARP entries for IPs from such cidr will not be added in the DVR router namespace. Closes-Bug: #1934912 Change-Id: I7bdefea943379125f93b116bb899446b874d9505 --- neutron/agent/l3/dvr_local_router.py | 18 +++++++++++------ .../functional/agent/l3/test_dvr_router.py | 20 +++++++++++++++---- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/neutron/agent/l3/dvr_local_router.py b/neutron/agent/l3/dvr_local_router.py index 4f753685cdb..3889adb0cc4 100644 --- a/neutron/agent/l3/dvr_local_router.py +++ b/neutron/agent/l3/dvr_local_router.py @@ -330,12 +330,18 @@ class DvrLocalRouter(dvr_router_base.DvrRouterBase): device=device, device_exists=device_exists) for allowed_address_pair in p.get('allowed_address_pairs', []): - self._update_arp_entry(allowed_address_pair['ip_address'], - allowed_address_pair['mac_address'], - subnet_id, - 'add', - device=device, - device_exists=device_exists) + if ('/' not in str(allowed_address_pair['ip_address']) or + common_utils.is_cidr_host( + allowed_address_pair['ip_address'])): + ip_address = common_utils.cidr_to_ip( + allowed_address_pair['ip_address']) + self._update_arp_entry( + ip_address, + allowed_address_pair['mac_address'], + subnet_id, + 'add', + device=device, + device_exists=device_exists) # subnet_ports does not have snat port if the port is still unbound # by the time this function is called. So ensure to add arp entry diff --git a/neutron/tests/functional/agent/l3/test_dvr_router.py b/neutron/tests/functional/agent/l3/test_dvr_router.py index e250f86961c..7720ed2e401 100644 --- a/neutron/tests/functional/agent/l3/test_dvr_router.py +++ b/neutron/tests/functional/agent/l3/test_dvr_router.py @@ -1005,13 +1005,18 @@ class TestDvrRouter(DvrRouterTestFramework, framework.L3AgentTestFramework): # cache is properly populated. self.agent.conf.agent_mode = 'dvr_snat' router_info = self.generate_dvr_router_info(enable_snat=True) - expected_neighbors = ['35.4.1.10', '10.0.0.10'] + expected_neighbors = ['35.4.1.10', '10.0.0.10', '10.200.0.3'] + allowed_address_net = netaddr.IPNetwork('10.100.0.0/30') port_data = { 'fixed_ips': [{'ip_address': expected_neighbors[0]}], 'mac_address': 'fa:3e:aa:bb:cc:dd', 'device_owner': DEVICE_OWNER_COMPUTE, 'allowed_address_pairs': [ {'ip_address': expected_neighbors[1], + 'mac_address': 'fa:3e:aa:bb:cc:dd'}, + {'ip_address': '10.200.0.3/32', + 'mac_address': 'fa:3e:aa:bb:cc:dd'}, + {'ip_address': str(allowed_address_net), 'mac_address': 'fa:3e:aa:bb:cc:dd'}] } self.agent.plugin_rpc.get_ports_by_subnet.return_value = [port_data] @@ -1019,11 +1024,18 @@ class TestDvrRouter(DvrRouterTestFramework, framework.L3AgentTestFramework): internal_device = router1.get_internal_device_name( router_info['_interfaces'][0]['id']) for expected_neighbor in expected_neighbors: - neighbor = ip_lib.dump_neigh_entries(4, internal_device, - router1.ns_name, - dst=expected_neighbor) + neighbor = ip_lib.dump_neigh_entries( + lib_constants.IP_VERSION_4, internal_device, + router1.ns_name, + dst=expected_neighbor) self.assertNotEqual([], neighbor) self.assertEqual(expected_neighbor, neighbor[0]['dst']) + for not_expected_neighbor in allowed_address_net: + neighbor = ip_lib.dump_neigh_entries( + lib_constants.IP_VERSION_4, internal_device, + router1.ns_name, + dst=str(not_expected_neighbor)) + self.assertEqual([], neighbor) def _assert_rfp_fpr_mtu(self, router, expected_mtu=1500): dev_mtu = self.get_device_mtu(