From 85ebf88afa04986cd0e5d65f20c9f286820d87a5 Mon Sep 17 00:00:00 2001 From: leejian0612 Date: Wed, 5 Aug 2015 16:00:35 +0800 Subject: [PATCH] Broadcast service port's arp in DVR When creating VMs, DVR router will broadcast VM's arp details to all the l3 agents hosting it. that enable dvr can forwarding networking traffic in link layer, but when the port is attached to the service liking lbaas, their arp will not be broadcast, so the dvr do not know its mac, and will cause that vms in other subnet can not reach the service port through the dvr router. Change-Id: Ia78a35f39981d6659fc220e02fb10917bda74e04 Closes-Bug: #1481613 --- neutron/db/l3_dvr_db.py | 6 ++-- neutron/tests/unit/db/test_l3_dvr_db.py | 41 +++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/neutron/db/l3_dvr_db.py b/neutron/db/l3_dvr_db.py index ff20cbb224c..f332a6db7dc 100644 --- a/neutron/db/l3_dvr_db.py +++ b/neutron/db/l3_dvr_db.py @@ -661,9 +661,9 @@ class L3_NAT_with_dvr_db_mixin(l3_db.L3_NAT_db_mixin, router. """ - # Check this is a valid VM port - if ("compute:" not in port_dict['device_owner'] or - not port_dict['fixed_ips']): + # Check this is a valid VM or service port + if not (n_utils.is_dvr_serviced(port_dict['device_owner']) and + port_dict['fixed_ips']): return ip_address = port_dict['fixed_ips'][0]['ip_address'] subnet = port_dict['fixed_ips'][0]['subnet_id'] diff --git a/neutron/tests/unit/db/test_l3_dvr_db.py b/neutron/tests/unit/db/test_l3_dvr_db.py index 419e168fb7a..b10ee8d9c3d 100644 --- a/neutron/tests/unit/db/test_l3_dvr_db.py +++ b/neutron/tests/unit/db/test_l3_dvr_db.py @@ -551,3 +551,44 @@ class L3DvrTestCase(testlib_api.SqlTestCase): kwargs = {'context': self.ctx, 'router': router_db} mock_notify.assert_called_once_with( 'router', 'before_update', self.mixin, **kwargs) + + def _test_dvr_vmarp_table_update(self, device_owner, action): + with mock.patch.object(manager.NeutronManager, 'get_plugin') as gp,\ + mock.patch.object(self.mixin, '_get_router') as grtr: + plugin = mock.Mock() + dvr_router = mock.Mock() + l3_notify = self.mixin.l3_rpc_notifier = mock.Mock() + gp.return_value = plugin + port = { + 'id': 'my_port_id', + 'fixed_ips': [{ + 'ip_address': 'my_ip', + 'subnet_id': 'my_subnet_id', + }], + 'mac_address': 'my_mac', + 'device_owner': device_owner + } + dvr_port = { + 'id': 'dvr_port_id', + 'fixed_ips': mock.ANY, + 'device_owner': l3_const.DEVICE_OWNER_DVR_INTERFACE, + 'device_id': 'dvr_router_id' + } + plugin.get_ports.return_value = [port, dvr_port] + grtr.return_value = dvr_router + dvr_router.extra_attributes.distributed = True + self.mixin.dvr_vmarp_table_update(self.ctx, port, action) + if action == 'add': + self.assertTrue(l3_notify.add_arp_entry.called) + elif action == 'del': + self.assertTrue(l3_notify.del_arp_entry.called) + + def test_dvr_vmarp_table_update_with_service_port_added(self): + action = 'add' + device_owner = l3_const.DEVICE_OWNER_LOADBALANCER + self._test_dvr_vmarp_table_update(device_owner, action) + + def test_dvr_vmarp_table_update_with_service_port_deleted(self): + action = 'del' + device_owner = l3_const.DEVICE_OWNER_LOADBALANCER + self._test_dvr_vmarp_table_update(device_owner, action)