Merge "[OVN] Set MTU of the VETH interfaces between OVS and metadata"

This commit is contained in:
Zuul
2024-03-05 09:48:42 +00:00
committed by Gerrit Code Review
3 changed files with 54 additions and 56 deletions

View File

@@ -109,7 +109,7 @@ class PortBindingEvent(row_event.RowEvent):
with _SYNC_STATE_LOCK.read_lock(): with _SYNC_STATE_LOCK.read_lock():
self.log_row(row) self.log_row(row)
try: try:
self.agent.provision_datapath(row.datapath) self.agent.provision_datapath(row)
except ConfigException: except ConfigException:
# We're now in the reader lock mode, we need to exit the # We're now in the reader lock mode, we need to exit the
# context and then use writer lock # context and then use writer lock
@@ -463,13 +463,13 @@ class MetadataAgent(object):
"br-int instead.") "br-int instead.")
return 'br-int' return 'br-int'
def get_networks_datapaths(self): def get_networks_port_bindings(self):
"""Return a set of datapath objects of the VIF ports on the current """Return a set of Port_Binding objects of the VIF ports on the current
chassis. chassis.
""" """
ports = self.sb_idl.get_ports_on_chassis( ports = self.sb_idl.get_ports_on_chassis(
self.chassis, include_additional_chassis=True) self.chassis, include_additional_chassis=True)
return set(p.datapath for p in self._vif_ports(ports)) return list(self._vif_ports(ports))
@_sync_lock @_sync_lock
def sync(self, provision=True): def sync(self, provision=True):
@@ -484,12 +484,12 @@ class MetadataAgent(object):
system_namespaces = tuple( system_namespaces = tuple(
ns.decode('utf-8') if isinstance(ns, bytes) else ns ns.decode('utf-8') if isinstance(ns, bytes) else ns
for ns in ip_lib.list_network_namespaces()) for ns in ip_lib.list_network_namespaces())
net_datapaths = self.get_networks_datapaths() net_port_bindings = self.get_networks_port_bindings()
metadata_namespaces = [ metadata_namespaces = set(
self._get_namespace_name( self._get_namespace_name(
ovn_utils.get_network_name_from_datapath(datapath)) ovn_utils.get_network_name_from_datapath(datapath))
for datapath in net_datapaths for datapath in (pb.datapath for pb in net_port_bindings)
] )
unused_namespaces = [ns for ns in system_namespaces if unused_namespaces = [ns for ns in system_namespaces if
ns.startswith(NS_PREFIX) and ns.startswith(NS_PREFIX) and
ns not in metadata_namespaces] ns not in metadata_namespaces]
@@ -503,8 +503,8 @@ class MetadataAgent(object):
# even those that are already running. This is to make sure # even those that are already running. This is to make sure
# everything within each namespace is up to date. # everything within each namespace is up to date.
if provision: if provision:
for datapath in net_datapaths: for port_binding in net_port_bindings:
self.provision_datapath(datapath) self.provision_datapath(port_binding)
@staticmethod @staticmethod
def _get_veth_name(datapath): def _get_veth_name(datapath):
@@ -675,7 +675,7 @@ class MetadataAgent(object):
return net_name, datapath_ports_ips, metadata_port_info return net_name, datapath_ports_ips, metadata_port_info
def provision_datapath(self, datapath): def provision_datapath(self, port_binding):
"""Provision the datapath so that it can serve metadata. """Provision the datapath so that it can serve metadata.
This function will create the namespace and VETH pair if needed This function will create the namespace and VETH pair if needed
@@ -683,11 +683,13 @@ class MetadataAgent(object):
metadata port of the network. It will also remove existing IP from metadata port of the network. It will also remove existing IP from
the namespace if they are no longer needed. the namespace if they are no longer needed.
:param datapath: datapath object. :param port_binding: Port_Binding object.
:return: The metadata namespace name for the datapath or None :return: The metadata namespace name for the Port_Binding.datapath or
if namespace was not provisioned None if namespace was not provisioned
""" """
datapath = port_binding.datapath
mtu = int(port_binding.external_ids.get(
ovn_const.OVN_NETWORK_MTU_EXT_ID_KEY) or '0')
provision_params = self._get_provision_params(datapath) provision_params = self._get_provision_params(datapath)
if not provision_params: if not provision_params:
return return
@@ -716,6 +718,11 @@ class MetadataAgent(object):
# Configure the MAC address. # Configure the MAC address.
ip2.link.set_address(metadata_port_info.mac) ip2.link.set_address(metadata_port_info.mac)
# Set VETH ports MTU.
if mtu:
ip1.link.set_mtu(mtu)
ip2.link.set_mtu(mtu)
# Make sure both ends of the VETH are up # Make sure both ends of the VETH are up
ip1.link.set_up() ip1.link.set_up()
ip2.link.set_up() ip2.link.set_up()

View File

@@ -82,6 +82,7 @@ OvnPortInfo = collections.namedtuple(
"address6_scope_id", "address6_scope_id",
"vnic_type", "vnic_type",
"capabilities", "capabilities",
"mtu",
], ],
) )
@@ -340,6 +341,7 @@ class OVNClient(object):
address6_scope_id = "" address6_scope_id = ""
dhcpv4_options = self._get_port_dhcp_options(port, const.IP_VERSION_4) dhcpv4_options = self._get_port_dhcp_options(port, const.IP_VERSION_4)
dhcpv6_options = self._get_port_dhcp_options(port, const.IP_VERSION_6) dhcpv6_options = self._get_port_dhcp_options(port, const.IP_VERSION_6)
mtu = ''
if vtep_physical_switch: if vtep_physical_switch:
vtep_logical_switch = bp_info.bp_param.get('vtep-logical-switch') vtep_logical_switch = bp_info.bp_param.get('vtep-logical-switch')
port_type = 'vtep' port_type = 'vtep'
@@ -433,10 +435,10 @@ class OVNClient(object):
ovn_const.VIF_DETAILS_PF_MAC_ADDRESS in bp_info.bp_param): ovn_const.VIF_DETAILS_PF_MAC_ADDRESS in bp_info.bp_param):
port_net = self._plugin.get_network( port_net = self._plugin.get_network(
context, port['network_id']) context, port['network_id'])
mtu = str(port_net['mtu'])
options.update({ options.update({
ovn_const.LSP_OPTIONS_VIF_PLUG_TYPE_KEY: 'representor', ovn_const.LSP_OPTIONS_VIF_PLUG_TYPE_KEY: 'representor',
ovn_const.LSP_OPTIONS_VIF_PLUG_MTU_REQUEST_KEY: str( ovn_const.LSP_OPTIONS_VIF_PLUG_MTU_REQUEST_KEY: mtu,
port_net['mtu']),
ovn_const.LSP_OPTIONS_VIF_PLUG_REPRESENTOR_PF_MAC_KEY: ( ovn_const.LSP_OPTIONS_VIF_PLUG_REPRESENTOR_PF_MAC_KEY: (
bp_info.bp_param.get( bp_info.bp_param.get(
ovn_const.VIF_DETAILS_PF_MAC_ADDRESS)), ovn_const.VIF_DETAILS_PF_MAC_ADDRESS)),
@@ -477,7 +479,7 @@ class OVNClient(object):
parent_name, tag, dhcpv4_options, dhcpv6_options, parent_name, tag, dhcpv4_options, dhcpv6_options,
cidrs.strip(), device_owner, sg_ids, cidrs.strip(), device_owner, sg_ids,
address4_scope_id, address6_scope_id, address4_scope_id, address6_scope_id,
bp_info.vnic_type, bp_info.capabilities bp_info.vnic_type, bp_info.capabilities, mtu
) )
def update_port_dhcp_options(self, port_info, txn): def update_port_dhcp_options(self, port_info, txn):
@@ -518,6 +520,7 @@ class OVNClient(object):
ovn_const.OVN_PORT_VNIC_TYPE_KEY: port_info.vnic_type, ovn_const.OVN_PORT_VNIC_TYPE_KEY: port_info.vnic_type,
ovn_const.OVN_PORT_BP_CAPABILITIES_KEY: ovn_const.OVN_PORT_BP_CAPABILITIES_KEY:
';'.join(port_info.capabilities), ';'.join(port_info.capabilities),
ovn_const.OVN_NETWORK_MTU_EXT_ID_KEY: port_info.mtu,
} }
return port_info, external_ids return port_info, external_ids

View File

@@ -103,14 +103,8 @@ class TestMetadataAgent(base.BaseTestCase):
self.agent.sync() self.agent.sync()
pdp.assert_has_calls( pdp.assert_has_calls([mock.call(p) for p in self.ports],
[ any_order=True)
mock.call(p.datapath)
for p in self.ports
],
any_order=True
)
lnn.assert_called_once_with() lnn.assert_called_once_with()
tdp.assert_not_called() tdp.assert_not_called()
@@ -129,13 +123,8 @@ class TestMetadataAgent(base.BaseTestCase):
self.agent.sync() self.agent.sync()
pdp.assert_has_calls( pdp.assert_has_calls([mock.call(p) for p in self.ports],
[ any_order=True)
mock.call(p.datapath)
for p in self.ports
],
any_order=True
)
lnn.assert_called_once_with() lnn.assert_called_once_with()
tdp.assert_called_once_with('3') tdp.assert_called_once_with('3')
@@ -154,27 +143,23 @@ class TestMetadataAgent(base.BaseTestCase):
side_effect=Exception()) as tdp: side_effect=Exception()) as tdp:
self.agent.sync() self.agent.sync()
pdp.assert_has_calls( pdp.assert_has_calls([mock.call(p) for p in self.ports],
[ any_order=True)
mock.call(p.datapath)
for p in self.ports
],
any_order=True
)
lnn.assert_called_once_with() lnn.assert_called_once_with()
tdp.assert_called_once_with('3') tdp.assert_called_once_with('3')
def test_get_networks_datapaths(self): def test_get_networks_port_bindings(self):
"""Test get_networks_datapaths returns only datapath objects for the """Test get_networks_port_bindings returns only the port binding
networks containing vif ports of type ''(blank) and 'external'. objects for ports with VIF type empty ('') or 'external'.
This test simulates that this chassis has the following ports: This test simulates that this chassis has the following ports:
* datapath '1': 1 port type '' , 1 port 'external' and * port0: datapath 1, type ''
1 port 'unknown' * port1: datapath 1, type 'external'
* datapath '2': 1 port type '' * port2: datapath 1, type 'unknown'
* datapath '3': 1 port with type 'external' * port3: datapath 2, type ''
* datapath '4': 1 port with type 'unknown' * port4: datapath 3, type 'external'
* port5: datapath 4, type 'unknown'
It is expected that only datapaths '1', '2' and '3' are returned Only port bindings from ports 0, 1, 3, and 4 are expected.
""" """
datapath_1 = DatapathInfo(uuid='uuid1', datapath_1 = DatapathInfo(uuid='uuid1',
@@ -197,11 +182,8 @@ class TestMetadataAgent(base.BaseTestCase):
with mock.patch.object(self.agent.sb_idl, 'get_ports_on_chassis', with mock.patch.object(self.agent.sb_idl, 'get_ports_on_chassis',
return_value=ports): return_value=ports):
expected_datapaths = set([datapath_1, datapath_2, datapath_3]) self.assertEqual([ports[0], ports[1], ports[3], ports[4]],
self.assertSetEqual( self.agent.get_networks_port_bindings())
expected_datapaths,
self.agent.get_networks_datapaths()
)
def test_teardown_datapath(self): def test_teardown_datapath(self):
"""Test teardown datapath. """Test teardown datapath.
@@ -444,7 +426,8 @@ class TestMetadataAgent(base.BaseTestCase):
mock.patch.object(agent.MetadataAgent, '_get_namespace_name', mock.patch.object(agent.MetadataAgent, '_get_namespace_name',
return_value=nemaspace_name),\ return_value=nemaspace_name),\
mock.patch.object(ip_link, 'set_up') as link_set_up,\ mock.patch.object(ip_link, 'set_up') as link_set_up,\
mock.patch.object(ip_link, 'set_address') as link_set_addr,\ mock.patch.object(ip_link, 'set_address') as link_set_addr, \
mock.patch.object(ip_link, 'set_mtu') as link_set_mtu, \
mock.patch.object(ip_addr, 'list', return_value=[]),\ mock.patch.object(ip_addr, 'list', return_value=[]),\
mock.patch.object( mock.patch.object(
ip_addr, 'add_multiple') as ip_addr_add_multiple,\ ip_addr, 'add_multiple') as ip_addr_add_multiple,\
@@ -464,7 +447,11 @@ class TestMetadataAgent(base.BaseTestCase):
# We need to assert that it was deleted first. # We need to assert that it was deleted first.
self.agent.ovs_idl.list_br.return_value.execute.return_value = ( self.agent.ovs_idl.list_br.return_value.execute.return_value = (
['br-int', 'br-fake']) ['br-int', 'br-fake'])
self.agent.provision_datapath('fake_datapath') mtu = 1500
port_binding = mock.Mock(
datapath='fake_datapath',
external_ids={ovn_const.OVN_NETWORK_MTU_EXT_ID_KEY: str(mtu)})
self.agent.provision_datapath(port_binding)
# Check that the port was deleted from br-fake # Check that the port was deleted from br-fake
self.agent.ovs_idl.del_port.assert_called_once_with( self.agent.ovs_idl.del_port.assert_called_once_with(
@@ -474,6 +461,7 @@ class TestMetadataAgent(base.BaseTestCase):
nemaspace_name) nemaspace_name)
# Make sure that the two ends of the VETH pair have been set as up. # Make sure that the two ends of the VETH pair have been set as up.
self.assertEqual(2, link_set_up.call_count) self.assertEqual(2, link_set_up.call_count)
link_set_mtu.assert_has_calls([mock.call(mtu), mock.call(mtu)])
link_set_addr.assert_called_once_with('aa:bb:cc:dd:ee:ff') link_set_addr.assert_called_once_with('aa:bb:cc:dd:ee:ff')
# Make sure that the port has been added to OVS. # Make sure that the port has been added to OVS.
self.agent.ovs_idl.add_port.assert_called_once_with( self.agent.ovs_idl.add_port.assert_called_once_with(