Merge "[OVN] Set MTU of the VETH interfaces between OVS and metadata"
This commit is contained in:
@@ -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()
|
||||||
|
@@ -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
|
||||||
|
|
||||||
|
@@ -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(
|
||||||
|
Reference in New Issue
Block a user