From 5418912b705393b165c455507bc7b09cb9141f58 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 (cherry picked from commit 19375b3e78ad6b635793b716e5ecabd53dc73a76) --- 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 135df6afb6a..ff1fb55d33a 100644 --- a/neutron/agent/l3/dvr_local_router.py +++ b/neutron/agent/l3/dvr_local_router.py @@ -365,12 +365,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 5f5a17e817c..1ef66466153 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(