diff options
Diffstat (limited to 'tests/common')
| -rw-r--r-- | tests/common/ipoe_iface.py | 84 | ||||
| -rw-r--r-- | tests/common/veth.py | 26 |
2 files changed, 104 insertions, 6 deletions
diff --git a/tests/common/ipoe_iface.py b/tests/common/ipoe_iface.py new file mode 100644 index 00000000..62b26355 --- /dev/null +++ b/tests/common/ipoe_iface.py @@ -0,0 +1,84 @@ +from common import process +import os +import signal +import time + + +# (ifindex, name) of every ipoe session interface currently in the kernel. +# Matched by name rather than by 'ip link show type ipoe' so that the helper +# keeps working with a module that does not register rtnl_link_ops. +def list_ipoe(): + (exit_code, out, err) = process.run(["ip", "-o", "link", "show"]) + assert exit_code == 0, "ip link show failed: " + err + + ifaces = [] + for line in out.splitlines(): + fields = line.split(":") + if len(fields) < 2: + continue + try: + ifindex = int(fields[0].strip()) + except ValueError: + continue + name = fields[1].strip().split("@")[0] + if name.startswith("ipoe"): + ifaces.append((ifindex, name)) + + return ifaces + + +# pids of the running accel-pppd processes +def accel_pppd_pids(): + pids = [] + for entry in os.listdir("/proc"): + if not entry.isdigit(): + continue + try: + with open("/proc/" + entry + "/comm") as comm: + if comm.read().strip() == "accel-pppd": + pids.append(int(entry)) + except OSError: # process is gone, or not ours to look at + pass + + return pids + + +# SIGKILL every accel-pppd and wait until they are really gone. +# Returns the number of processes that were killed. +def kill_accel_pppd(max_wait_time=10.0): + pids = accel_pppd_pids() + for pid in pids: + print("kill_accel_pppd: SIGKILL to pid " + str(pid)) + try: + os.kill(pid, signal.SIGKILL) + except OSError: + pass + + sleep_time = 0.0 + while sleep_time < max_wait_time: + if not accel_pppd_pids(): + print("kill_accel_pppd: gone in (sec): " + str(sleep_time)) + break + time.sleep(0.1) + sleep_time += 0.1 + + return len(pids) + + +# wait until accel-pppd reports an active ipoe session on the given interface +def wait_for_session(accel_cmd, called_sid, max_wait_time=10.0): + sleep_time = 0.0 + out = "" + while sleep_time < max_wait_time: + (exit_code, out, err) = process.run( + [accel_cmd, "show sessions called-sid,ip,state"] + ) + assert exit_code == 0, "accel-cmd failed: " + err + if called_sid in out and "192.0.2." in out and "active" in out: + print("wait_for_session: session found in (sec): " + str(sleep_time)) + return True + time.sleep(0.1) + sleep_time += 0.1 + + print("wait_for_session: last accel-cmd out: " + out) + return False 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) |
