Merge "Ensure that ARP/NDP is enabled for vlan devices"

This commit is contained in:
Zuul
2025-07-30 18:20:10 +00:00
committed by Gerrit Code Review
9 changed files with 61 additions and 28 deletions

View File

@@ -169,9 +169,12 @@ class OVNBGPDriver(driver_api.AgentDriverBase):
linux_net.ensure_vlan_device_for_network(bridge, linux_net.ensure_vlan_device_for_network(bridge,
vlan_tag) vlan_tag)
linux_net.ensure_arp_ndp_enabled_for_bridge(bridge,
bridge_index,
vlan_tag)
linux_net.ensure_arp_ndp_enabled_for_bridge(bridge, linux_net.ensure_arp_ndp_enabled_for_bridge(bridge,
bridge_index, bridge_index)
vlan_tags)
if self.ovs_flows.get(bridge): if self.ovs_flows.get(bridge):
continue continue

View File

@@ -232,7 +232,7 @@ class VlanDev:
# Add 169.254.x.x address to veth_vrf for ipv4 and ipv6 # Add 169.254.x.x address to veth_vrf for ipv4 and ipv6
linux_net.ensure_arp_ndp_enabled_for_bridge( linux_net.ensure_arp_ndp_enabled_for_bridge(
self.veth_vrf, offset=int(self.vlan_tag), vlan_tag=self.vlan_tag self.veth_vrf, offset=int(self.vlan_tag)
) )
# Configure mac on the veth interface to be the same on all hosts # Configure mac on the veth interface to be the same on all hosts

View File

@@ -65,9 +65,13 @@ def _ensure_base_wiring_config_underlay(idl, ovs_idl, routing_tables):
linux_net.ensure_vlan_device_for_network(bridge, linux_net.ensure_vlan_device_for_network(bridge,
vlan_tag) vlan_tag)
linux_net.ensure_arp_ndp_enabled_for_bridge(bridge,
bridge_index,
vlan_tag)
linux_net.ensure_arp_ndp_enabled_for_bridge(bridge, linux_net.ensure_arp_ndp_enabled_for_bridge(bridge,
bridge_index, bridge_index)
vlan_tags)
if not flows_info.get(bridge): if not flows_info.get(bridge):
mac = linux_net.get_interface_address(bridge) mac = linux_net.get_interface_address(bridge)
flows_info[bridge] = {'mac': mac, 'in_port': set()} flows_info[bridge] = {'mac': mac, 'in_port': set()}

View File

@@ -208,8 +208,10 @@ class TestNBOVNBGPDriver(test_base.TestCase):
mock_ensure_br.assert_has_calls(expected_calls) mock_ensure_br.assert_has_calls(expected_calls)
expected_calls = [mock.call('bridge0', 10), mock.call('bridge1', 11)] expected_calls = [mock.call('bridge0', 10), mock.call('bridge1', 11)]
mock_ensure_vlan_network.assert_has_calls(expected_calls) mock_ensure_vlan_network.assert_has_calls(expected_calls)
expected_calls = [mock.call('bridge0', 1, [10]), expected_calls = [mock.call('bridge0', 1, 10),
mock.call('bridge1', 2, [11])] mock.call('bridge0', 1),
mock.call('bridge1', 2, 11),
mock.call('bridge1', 2)]
mock_ensure_arp.assert_has_calls(expected_calls) mock_ensure_arp.assert_has_calls(expected_calls)
expected_calls = [ expected_calls = [
mock.call('bridge0'), mock.call('bridge1')] mock.call('bridge0'), mock.call('bridge1')]

View File

@@ -145,8 +145,10 @@ class TestOVNBGPDriver(test_base.TestCase):
self.bgp_driver.sync() self.bgp_driver.sync()
expected_calls = [mock.call('bridge0', 1, [10]), expected_calls = [mock.call('bridge0', 1, 10),
mock.call('bridge1', 2, [11])] mock.call('bridge0', 1),
mock.call('bridge1', 2, 11),
mock.call('bridge1', 2)]
mock_ensure_arp.assert_has_calls(expected_calls) mock_ensure_arp.assert_has_calls(expected_calls)
expected_calls = [mock.call('bridge0'), mock.call('bridge1')] expected_calls = [mock.call('bridge0'), mock.call('bridge1')]

View File

@@ -302,7 +302,7 @@ class TestEVPN(test_base.TestCase):
linux_net.set_master_for_device.assert_called_once_with(self.veth_vrf, linux_net.set_master_for_device.assert_called_once_with(self.veth_vrf,
self.vrf_name) self.vrf_name)
linux_net.ensure_arp_ndp_enabled_for_bridge.assert_called_once_with( linux_net.ensure_arp_ndp_enabled_for_bridge.assert_called_once_with(
self.veth_vrf, offset=vlan_tag, vlan_tag=vlan_tag_str) self.veth_vrf, offset=vlan_tag)
linux_net.enable_routing_for_interfaces.assert_called_once_with( linux_net.enable_routing_for_interfaces.assert_called_once_with(
self.veth_vrf, 'br-100') self.veth_vrf, 'br-100')

View File

@@ -160,8 +160,8 @@ class TestLinuxNet(test_base.TestCase):
linux_net.ensure_arp_ndp_enabled_for_bridge('fake-bridge', 511) linux_net.ensure_arp_ndp_enabled_for_bridge('fake-bridge', 511)
# NOTE(ltomasbo): hardoced starting ipv4 is 192.168.0.0, and ipv6 is # NOTE(ltomasbo): hardoced starting ipv4 is 192.168.0.0, and ipv6 is
# fd53:d91e:400:7f17::0 # fd53:d91e:400:7f17::0
ipv4 = '169.254.1.255' # base + 511 offset ipv4 = '169.254.255.255' # base + 511 offset
ipv6 = 'fd53:d91e:400:7f17::1ff' # base + 5122 offset (to hex) ipv6 = 'fd53:d91e:400:7f17::1ff:1ff' # base + 5122 offset (to hex)
calls = [mock.call(ipv4, 'fake-bridge'), calls = [mock.call(ipv4, 'fake-bridge'),
mock.call(ipv6, 'fake-bridge')] mock.call(ipv6, 'fake-bridge')]
mock_add_ip_to_dev.assert_has_calls(calls) mock_add_ip_to_dev.assert_has_calls(calls)
@@ -176,13 +176,13 @@ class TestLinuxNet(test_base.TestCase):
linux_net.ensure_arp_ndp_enabled_for_bridge('fake-bridge', 511, 11) linux_net.ensure_arp_ndp_enabled_for_bridge('fake-bridge', 511, 11)
# NOTE(ltomasbo): hardoced starting ipv4 is 192.168.0.0, and ipv6 is # NOTE(ltomasbo): hardoced starting ipv4 is 192.168.0.0, and ipv6 is
# fd53:d91e:400:7f17::0 # fd53:d91e:400:7f17::0
ipv4 = '169.254.1.255' # base + 511 offset ipv4 = '169.254.255.11' # base + 511 offset
ipv6 = 'fd53:d91e:400:7f17::1ff' # base + 5122 offset (to hex) ipv6 = 'fd53:d91e:400:7f17::1ff:b' # base + 5122 offset (to hex)
calls = [mock.call(ipv4, 'fake-bridge'), calls = [mock.call(ipv4, 'fake-bridg.11'),
mock.call(ipv6, 'fake-bridge')] mock.call(ipv6, 'fake-bridg.11')]
mock_add_ip_to_dev.assert_has_calls(calls) mock_add_ip_to_dev.assert_has_calls(calls)
mock_ndp.assert_called_once_with('fake-bridge') mock_ndp.assert_called_once_with('fake-bridg/11')
mock_arp.assert_called_once_with('fake-bridge') mock_arp.assert_called_once_with('fake-bridg/11')
@mock.patch.object(linux_net, 'enable_proxy_arp') @mock.patch.object(linux_net, 'enable_proxy_arp')
@mock.patch.object(linux_net, 'enable_proxy_ndp') @mock.patch.object(linux_net, 'enable_proxy_ndp')

View File

@@ -136,25 +136,37 @@ def delete_device(device):
def ensure_arp_ndp_enabled_for_bridge(bridge, offset, vlan_tag=None): def ensure_arp_ndp_enabled_for_bridge(bridge, offset, vlan_tag=None):
if vlan_tag:
device_name = '{}.{}'.format(
bridge[:constants.OVN_VLAN_DEVICE_MAX_LENGTH],
vlan_tag
)
device_index = vlan_tag % constants.IPV4_OCTET_RANGE
else:
device_name = bridge[:n_const.DEVICE_NAME_MAX_LEN]
device_index = offset
ipv4 = "%s%d.%s" % ( ipv4 = "%s%d.%s" % (
constants.ARP_IPV4_PREFIX, offset / constants.IPV4_OCTET_RANGE, constants.ARP_IPV4_PREFIX, offset % constants.IPV4_OCTET_RANGE,
offset % constants.IPV4_OCTET_RANGE) device_index % constants.IPV4_OCTET_RANGE)
ipv6 = "%s%x" % (constants.NDP_IPV6_PREFIX, offset) ipv6 = "%s%x:%x" % (constants.NDP_IPV6_PREFIX, offset, device_index)
for ip in (ipv4, ipv6): for ip in (ipv4, ipv6):
try: try:
ovn_bgp_agent.privileged.linux_net.add_ip_to_dev(ip, bridge) ovn_bgp_agent.privileged.linux_net.add_ip_to_dev(ip, device_name)
except agent_exc.IpAddressAlreadyExists: except agent_exc.IpAddressAlreadyExists:
LOG.debug("IP %s already added on bridge %s", ip, bridge) LOG.debug("IP %s already added on device %s", ip, device_name)
except KeyError as e: except KeyError as e:
if "object exists" not in str(e): if "object exists" not in str(e):
LOG.error("Unable to add IP on bridge %s to enable arp/ndp. " LOG.error("Unable to add IP on device %s to enable arp/ndp. "
"Exception: %s", bridge, e) "Exception: %s", device_name, e)
raise raise
# also enable the arp/ndp on the bridge in case there are flat networks # also enable the arp/ndp on the device
enable_proxy_arp(bridge) enable_proxy_arp(device_name.replace('.', '/'))
enable_proxy_ndp(bridge) enable_proxy_ndp(device_name.replace('.', '/'))
def ensure_anycast_mac_for_interface(intf, offset): def ensure_anycast_mac_for_interface(intf, offset):

View File

@@ -0,0 +1,10 @@
---
upgrade:
- |
Loopback IP addresses for provider bridge interfaces will be changed
with upgrade. This should have no impact on environments.
fixes:
- |
ARP/NDP are now will be enabled not only for the provider bridge itself,
but also for VLAN interfaces in case VLANs are being used as provider
networks instead of FLAT.