[OVN] External ports: Account for VNIC_DIRECT_PHYSICAL / VNIC_MACVTAP

Prior to this patch, the OVN driver wasn't account for the VNIC types
VNIC_DIRECT_PHYSICAL and VNIC_MACVTAP. These types should work the same
way as the VNIC_DIRECT type in the OVN driver perspective.

Closes-Bug: #1874065
Change-Id: Idb596b5a80a3155bc9cdee1e082506701e730f00
Signed-off-by: Lucas Alvares Gomes <lucasagomes@gmail.com>
This commit is contained in:
Lucas Alvares Gomes 2020-04-21 09:36:35 +01:00
parent 41835d8462
commit 2697341846
5 changed files with 70 additions and 15 deletions

View File

@ -210,3 +210,7 @@ METADATA_PORT = 80
# OVN igmp options
MCAST_SNOOP = 'mcast_snoop'
MCAST_FLOOD_UNREGISTERED = 'mcast_flood_unregistered'
EXTERNAL_PORT_TYPES = (portbindings.VNIC_DIRECT,
portbindings.VNIC_DIRECT_PHYSICAL,
portbindings.VNIC_MACVTAP)

View File

@ -146,7 +146,9 @@ class OVNMechanismDriver(api.MechanismDriver):
def _setup_vif_port_bindings(self):
self.supported_vnic_types = [portbindings.VNIC_NORMAL,
portbindings.VNIC_DIRECT]
portbindings.VNIC_DIRECT,
portbindings.VNIC_DIRECT_PHYSICAL,
portbindings.VNIC_MACVTAP]
self.vif_details = {
portbindings.VIF_TYPE_OVS: {
portbindings.CAP_PORT_FILTER: self.sg_enabled
@ -687,10 +689,10 @@ class OVNMechanismDriver(api.MechanismDriver):
return
capabilities = ovn_utils.get_port_capabilities(port)
if (vnic_type == portbindings.VNIC_DIRECT and
if (vnic_type in ovn_const.EXTERNAL_PORT_TYPES and
ovn_const.PORT_CAP_SWITCHDEV not in capabilities):
LOG.debug("Refusing to bind port due to unsupported vnic_type: %s "
"with no switchdev capability", portbindings.VNIC_DIRECT)
"with no switchdev capability", vnic_type)
return
# OVN chassis information is needed to ensure a valid port bind.

View File

@ -263,7 +263,7 @@ class OVNClient(object):
capabilities = utils.get_port_capabilities(port)
vnic_type = port.get(portbindings.VNIC_TYPE,
portbindings.VNIC_NORMAL)
if (vnic_type == portbindings.VNIC_DIRECT and
if (vnic_type in ovn_const.EXTERNAL_PORT_TYPES and
ovn_const.PORT_CAP_SWITCHDEV not in capabilities):
if self.is_external_ports_supported():
port_type = ovn_const.LSP_TYPE_EXTERNAL

View File

@ -460,11 +460,11 @@ class TestExternalPorts(base.TestOVNFunctionalBase):
rows = cmd.execute(check_error=True)
return rows[0] if rows else None
def test_external_port_create(self):
def _test_external_port_create(self, vnic_type):
port_data = {
'port': {'network_id': self.n1['network']['id'],
'tenant_id': self._tenant_id,
portbindings.VNIC_TYPE: portbindings.VNIC_DIRECT}}
portbindings.VNIC_TYPE: vnic_type}}
port_req = self.new_create_request('ports', port_data, self.fmt)
port_res = port_req.get_response(self.api)
@ -476,7 +476,16 @@ class TestExternalPorts(base.TestOVNFunctionalBase):
self.assertEqual(str(self.default_ch_grp.uuid),
str(ovn_port.ha_chassis_group[0].uuid))
def test_external_port_update(self):
def test_external_port_create_vnic_direct(self):
self._test_external_port_create(portbindings.VNIC_DIRECT)
def test_external_port_create_vnic_direct_physical(self):
self._test_external_port_create(portbindings.VNIC_DIRECT_PHYSICAL)
def test_external_port_create_vnic_macvtap(self):
self._test_external_port_create(portbindings.VNIC_MACVTAP)
def _test_external_port_update(self, vnic_type):
port_data = {
'port': {'network_id': self.n1['network']['id'],
'tenant_id': self._tenant_id}}
@ -490,7 +499,7 @@ class TestExternalPorts(base.TestOVNFunctionalBase):
self.assertEqual([], ovn_port.ha_chassis_group)
port_upt_data = {
'port': {portbindings.VNIC_TYPE: portbindings.VNIC_DIRECT}}
'port': {portbindings.VNIC_TYPE: vnic_type}}
port_req = self.new_update_request(
'ports', port_upt_data, port['id'], self.fmt)
port_res = port_req.get_response(self.api)
@ -502,11 +511,20 @@ class TestExternalPorts(base.TestOVNFunctionalBase):
self.assertEqual(str(self.default_ch_grp.uuid),
str(ovn_port.ha_chassis_group[0].uuid))
def test_external_port_create_switchdev(self):
def test_external_port_update_vnic_direct(self):
self._test_external_port_update(portbindings.VNIC_DIRECT)
def test_external_port_update_vnic_direct_physical(self):
self._test_external_port_update(portbindings.VNIC_DIRECT_PHYSICAL)
def test_external_port_update_vnic_macvtap(self):
self._test_external_port_update(portbindings.VNIC_MACVTAP)
def _test_external_port_create_switchdev(self, vnic_type):
port_data = {
'port': {'network_id': self.n1['network']['id'],
'tenant_id': self._tenant_id,
portbindings.VNIC_TYPE: portbindings.VNIC_DIRECT,
portbindings.VNIC_TYPE: vnic_type,
ovn_const.OVN_PORT_BINDING_PROFILE: {
'capabilities': [ovn_const.PORT_CAP_SWITCHDEV]}}}
@ -521,13 +539,23 @@ class TestExternalPorts(base.TestOVNFunctionalBase):
# Assert the poer hasn't been added to any HA Chassis Group either
self.assertEqual(0, len(ovn_port.ha_chassis_group))
def test_external_port_update_switchdev(self):
def test_external_port_create_switchdev_vnic_direct(self):
self._test_external_port_create_switchdev(portbindings.VNIC_DIRECT)
def test_external_port_create_switchdev_vnic_direct_physical(self):
self._test_external_port_create_switchdev(
portbindings.VNIC_DIRECT_PHYSICAL)
def test_external_port_create_switchdev_vnic_macvtap(self):
self._test_external_port_create_switchdev(portbindings.VNIC_MACVTAP)
def _test_external_port_update_switchdev(self, vnic_type):
port_data = {
'port': {'network_id': self.n1['network']['id'],
'tenant_id': self._tenant_id,
portbindings.VNIC_TYPE: portbindings.VNIC_DIRECT}}
portbindings.VNIC_TYPE: vnic_type}}
# Create a VNIC_DIRECT type port without the "switchdev"
# Create a VNIC_DIRECT[_PHYSICAL] type port without the "switchdev"
# capability and assert that it's an "external" port
port_req = self.new_create_request('ports', port_data, self.fmt)
port_res = port_req.get_response(self.api)
@ -556,3 +584,13 @@ class TestExternalPorts(base.TestOVNFunctionalBase):
self.assertEqual("", ovn_port.type)
# Assert the poer hasn't been added to any HA Chassis Group either
self.assertEqual(0, len(ovn_port.ha_chassis_group))
def test_external_port_update_switchdev_vnic_direct(self):
self._test_external_port_update_switchdev(portbindings.VNIC_DIRECT)
def test_external_port_update_switchdev_vnic_direct_physical(self):
self._test_external_port_update_switchdev(
portbindings.VNIC_DIRECT_PHYSICAL)
def test_external_port_update_switchdev_vnic_macvtap(self):
self._test_external_port_update_switchdev(portbindings.VNIC_MACVTAP)

View File

@ -2592,7 +2592,7 @@ class TestOVNMechanismDriverSecurityGroup(
@mock.patch('neutron.plugins.ml2.drivers.ovn.mech_driver.ovsdb.'
'ovn_client.OVNClient.is_external_ports_supported',
lambda *_: True)
def test_create_port_with_vnic_direct(self):
def _test_create_port_with_vnic_type(self, vnic_type):
fake_grp = 'fake-default-ha-group-uuid'
row = fakes.FakeOvsdbRow.create_one_ovsdb_row(attrs={'uuid': fake_grp})
self.mech_driver._nb_ovn.ha_chassis_group_get.return_value.\
@ -2602,7 +2602,7 @@ class TestOVNMechanismDriverSecurityGroup(
self._create_port(
self.fmt, n['network']['id'],
arg_list=(portbindings.VNIC_TYPE,),
**{portbindings.VNIC_TYPE: portbindings.VNIC_DIRECT})
**{portbindings.VNIC_TYPE: vnic_type})
# Assert create_lswitch_port was called with the relevant
# parameters
@ -2612,6 +2612,17 @@ class TestOVNMechanismDriverSecurityGroup(
self.assertEqual(ovn_const.LSP_TYPE_EXTERNAL, kwargs['type'])
self.assertEqual(fake_grp, kwargs['ha_chassis_group'])
def test_create_port_with_vnic_direct(self):
self._test_create_port_with_vnic_type(portbindings.VNIC_DIRECT)
def test_create_port_with_vnic_direct_physical(self):
self._test_create_port_with_vnic_type(
portbindings.VNIC_DIRECT_PHYSICAL)
def test_create_port_with_vnic_macvtap(self):
self._test_create_port_with_vnic_type(
portbindings.VNIC_MACVTAP)
def test_update_port_with_sgs(self):
with self.network() as n, self.subnet(n):
sg1 = self._create_empty_sg('sg1')