From 1c7856294d9eeb138a8e4b2d80fc2f48033a6de1 Mon Sep 17 00:00:00 2001 From: Denys Fedoryshchenko Date: Wed, 9 Sep 2026 11:05:56 +0300 Subject: tests: give the veth pair fixed MAC addresses The tests create the veth pair with 'ip link add ... type veth peer name ...' and let the kernel pick random hardware addresses, then start accel-pppd right away. On distributions where systemd-udevd rewrites the address of a freshly created veth (MACAddressPolicy in its .link rules, seen on Ubuntu 22.04) this is a race: accel-pppd reads the address of the interface it serves once, at startup, and when udev wins it advertises an address the interface no longer has. Discovery still completes - the client copies the advertised address into its kernel PPPoE session as the peer address - but from then on the two ends disagree about it, no PPP frame is exchanged in either direction, and the session dies on LCP timeouts. Every PPPoE session test can fail this way; test_pppoe_ccp_ipcp_race failed 8 times out of 12 runs in one qemu Ubuntu-22.04 job. Create the pair with fixed, locally administered addresses derived from the name the pair already gets, so udev has nothing to change. The same job passes 12 out of 12 with this. This only removes the trigger in the tests. accel-pppd not following the address of the interface it serves is tracked in #363 and needs a fix of its own. --- tests/common/veth.py | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'tests') diff --git a/tests/common/veth.py b/tests/common/veth.py index c9d3006c..9d51ab7a 100644 --- a/tests/common/veth.py +++ b/tests/common/veth.py @@ -2,11 +2,16 @@ from common import process, netns, vlan, iface import time import math -# creates veth pair. if ok returns 0 -def create_pair(name_a, name_b): - veth, out, err = process.run( - ["ip", "link", "add", name_a, "type", "veth", "peer", "name", name_b] - ) +# creates veth pair, optionally with fixed hardware addresses. if ok returns 0 +def create_pair(name_a, name_b, mac_a=None, mac_b=None): + command = ["ip", "link", "add", name_a] + if mac_a: + command += ["address", mac_a] + command += ["type", "veth", "peer", "name", name_b] + if mac_b: + command += ["address", mac_b] + + veth, out, err = process.run(command) print("veth.create: exit=%d out=%s err=%s" % (veth, out, err)) return veth @@ -32,7 +37,16 @@ def create_veth_pair_netns(veth_pair_vlans_config): veth_a = "A" + name veth_b = "B" + name - pair_status = create_pair(veth_a, veth_b) + + # fixed addresses: a veth pair created without them gets random ones, which + # systemd-udevd may replace right after creation (MACAddressPolicy in its + # .link rules). accel-pppd reads the address of the interface it serves once + # at startup, so when udev wins that race the daemon advertises an address + # the interface no longer has and the session never passes a frame. + # See https://github.com/accel-ppp/accel-ppp/issues/363 + num = int(name) + mac = "02:00:%02x:%02x:%02x:" % ((num >> 16) & 0xFF, (num >> 8) & 0xFF, num & 0xFF) + pair_status = create_pair(veth_a, veth_b, mac + "0a", mac + "0b") print("create_veth_pair_netns: pair_status=%d" % pair_status) iface.up(veth_a, None) -- cgit v1.2.3