diff --git a/vmware_nsx/plugins/nsx_v3/plugin.py b/vmware_nsx/plugins/nsx_v3/plugin.py index 8d67ee4b48..7fe1f6b075 100644 --- a/vmware_nsx/plugins/nsx_v3/plugin.py +++ b/vmware_nsx/plugins/nsx_v3/plugin.py @@ -2523,10 +2523,10 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, raise n_exc.InvalidInput(error_message=err_msg) def _assert_on_port_sec_change(self, port_data, device_owner): - """Do not allow enabling port security of some ports + """Do not allow enabling port security/mac learning of some ports - Trusted ports are created with port security disabled in neutron, - and it should not change. + Trusted ports are created with port security and mac learning disabled + in neutron, and it should not change. """ if nlib_net.is_port_trusted({'device_owner': device_owner}): if port_data.get(psec.PORTSECURITY) is True: @@ -2535,6 +2535,13 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin, LOG.warning(err_msg) raise n_exc.InvalidInput(error_message=err_msg) + mac_learning = port_data.get(mac_ext.MAC_LEARNING) + if (validators.is_attr_set(mac_learning) and mac_learning is True): + err_msg = _("mac_learning_enabled=True is not supported for " + "trusted ports") + LOG.warning(err_msg) + raise n_exc.InvalidInput(error_message=err_msg) + def _assert_on_vpn_port_change(self, port_data): if port_data['device_owner'] == ipsec_utils.VPN_PORT_OWNER: msg = _('Can not update/delete VPNaaS port %s') % port_data['id'] diff --git a/vmware_nsx/tests/unit/nsx_v3/test_plugin.py b/vmware_nsx/tests/unit/nsx_v3/test_plugin.py index 58f56a7fed..e84f05efb3 100644 --- a/vmware_nsx/tests/unit/nsx_v3/test_plugin.py +++ b/vmware_nsx/tests/unit/nsx_v3/test_plugin.py @@ -1117,6 +1117,43 @@ class TestPortsV2(test_plugin.TestPortsV2, NsxV3PluginTestCaseMixin, self.plugin.update_port, self.ctx, port['id'], data) + def test_update_port_with_mac_learning(self): + with self.network() as network: + data = {'port': { + 'network_id': network['network']['id'], + 'tenant_id': self._tenant_id, + 'name': 'qos_port', + 'admin_state_up': True, + 'device_id': 'fake_device', + 'device_owner': 'fake_owner', + 'fixed_ips': [], + 'port_security_enabled': False, + 'mac_address': '00:00:00:00:00:01'} + } + port = self.plugin.create_port(self.ctx, data) + data['port']['mac_learning_enabled'] = True + update_res = self.plugin.update_port(self.ctx, port['id'], data) + self.assertTrue(update_res['mac_learning_enabled']) + + def test_update_port_with_mac_learning_failes(self): + with self.network() as network: + data = {'port': { + 'network_id': network['network']['id'], + 'tenant_id': self._tenant_id, + 'name': 'qos_port', + 'admin_state_up': True, + 'device_id': 'fake_device', + 'device_owner': constants.DEVICE_OWNER_FLOATINGIP, + 'fixed_ips': [], + 'port_security_enabled': False, + 'mac_address': '00:00:00:00:00:01'} + } + port = self.plugin.create_port(self.ctx, data) + data['port']['mac_learning_enabled'] = True + self.assertRaises( + n_exc.InvalidInput, + self.plugin.update_port, self.ctx, port['id'], data) + def test_create_router_port_with_qos_fail(self): self._test_create_illegal_port_with_qos_fail( 'network:router_interface')