diff options
| author | Nataliia Solomko <natalirs1985@gmail.com> | 2026-07-16 15:16:02 +0300 |
|---|---|---|
| committer | Nataliia Solomko <natalirs1985@gmail.com> | 2026-07-20 12:02:54 +0300 |
| commit | e72de7eb3e4a6ef67a6836367f43ef363bf77e40 (patch) | |
| tree | d991699275715c7014524d06d7f4ae4369303173 /smoketest/scripts/cli | |
| parent | fb6f19f186296f42057cd1685d6f3bb63a5dae39 (diff) | |
| download | vyos-1x-e72de7eb3e4a6ef67a6836367f43ef363bf77e40.tar.gz vyos-1x-e72de7eb3e4a6ef67a6836367f43ef363bf77e40.zip | |
vpp: T8367: Fix identical default MAC on bridged loopback interfaces
VPP assigns loopback interfaces a default MAC address derived only from
the interface instance number (de:ad:00:00:00:<instance>), with no
host-specific entropy. Two independent VPP nodes configuring the same
loopback instance (e.g. as a bridge BVI over VXLAN) therefore end up with
an identical MAC address.
When that MAC arrives from a peer over the shared L2 segment, VPP's L2
learning logic rejects it as a `mac move violation` - it's statically
pinned to the local BVI and cannot legitimately appear on another port.
This silently drops ARP traffic between the loopbacks while ordinary
bridged client traffic (unique MACs) is unaffected, breaking
loopback-to-loopback connectivity.
Add a mac-address option to the VPP loopback interface, and fall back to
a deterministic, host-unique MAC (derived from host UUID/hostname, same
scheme already used for container interfaces) whenever none is
configured, so the collision can no longer occur by default.
Also fix a related bug found while reproducing the above: a loopback is
fully deleted and recreated in VPP on every apply, receiving a new
`sw_if_index` each time. The loopback conf_mode script never registered
the bridge it's a BVI member of as a dependent, so the bridge kept its
L2 membership bound to the stale, deleted index instead of reattaching
the current one. Register the bridge dependency and reuse the existing
`verify_vpp_remove_bridge_interface()` check to block deleting a
loopback still in use as a BVI.
Diffstat (limited to 'smoketest/scripts/cli')
| -rwxr-xr-x | smoketest/scripts/cli/test_vpp.py | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/smoketest/scripts/cli/test_vpp.py b/smoketest/scripts/cli/test_vpp.py index f78052f68..bda2da0f9 100755 --- a/smoketest/scripts/cli/test_vpp.py +++ b/smoketest/scripts/cli/test_vpp.py @@ -34,6 +34,7 @@ from vyos.utils.process import rc_cmd from vyos.utils.system import sysctl_read from vyos.utils.network import interface_exists from vyos.system import image +from vyos.ifconfig import Interface from vyos.vpp import VPPControl from vyos.vpp.utils import vpp_ip_addresses_by_index from vyos.vpp.utils import vpp_iface_name_transform @@ -401,6 +402,7 @@ class TestVPP(VyOSUnitTestSHIM.TestCase): loopback_path = interfaces_path + ['loopback'] interface_loopback = 'vpplo11' address = '192.0.2.54' + mac = '00:50:00:00:00:11' self.cli_set(loopback_path + [interface_loopback]) self.cli_set(loopback_path + [interface_loopback, 'address', f'{address}/25']) @@ -418,6 +420,14 @@ class TestVPP(VyOSUnitTestSHIM.TestCase): required_str = 'loop11' self.assertIn(required_str, out) + # check explicit MAC + self.cli_set(loopback_path + [interface_loopback, 'mac', mac]) + self.cli_commit() + + _, out = rc_cmd('sudo vppctl show hardware-interfaces loop11') + self.assertIn(f'Ethernet address {mac}', out) + self.assertEqual(mac, Interface(interface_loopback).get_mac()) + # delete loopback interface self.cli_delete(loopback_path + [interface_loopback]) self.cli_commit() @@ -624,6 +634,25 @@ class TestVPP(VyOSUnitTestSHIM.TestCase): self.assertRegex(normalized_out, r'10 1 \d+ off') self.assertRegex(out, r'\bloop23\s+\d+\s+\d+\s+\d+\s+\*\s+') + # A loopback is fully deleted and recreated in VPP on every apply, + # getting a new sw_if_index - reconfiguring it must reattach it to + # the bridge as BVI rather than leaving the bridge pointing at the + # stale, now-deleted interface + self.cli_set( + interfaces_path + ['loopback', f'vpplo{vni}', 'mac', '00:50:00:00:00:23'] + ) + self.cli_commit() + + _, out = rc_cmd('sudo vppctl show bridge-domain 10 detail') + normalized_out = re.sub(r'\s+', ' ', out) + self.assertRegex(normalized_out, r'10 1 \d+ off') + self.assertRegex(out, r'\bloop23\s+\d+\s+\d+\s+\d+\s+\*\s+') + + # cannot remove loopback interface while it is used as BVI + self.cli_delete(interfaces_path + ['loopback', f'vpplo{vni}']) + with self.assertRaises(ConfigSessionError): + self.cli_commit() + def test_07_vpp_ipip(self): ipip_path = interfaces_path + ['ipip'] interface_ipip = 'vppipip12' |
