diff options
| author | Denys Fedoryshchenko <denys.f@collabora.com> | 2026-08-31 18:30:54 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-08-31 18:30:54 +0300 |
| commit | 40575b78b7bb043c7a0ff4dd29a048be056dee9f (patch) | |
| tree | bcc6a4eecbf71b0f79580f2fcf91d6bf573e9a40 /tests/accel-pppd | |
| parent | 89637ee2417fc7f42e4213d417da38aa814047e4 (diff) | |
| parent | 2b46f1c69ca77efc317673b080d4773db09a4a3e (diff) | |
| download | accel-ppp-40575b78b7bb043c7a0ff4dd29a048be056dee9f.tar.gz accel-ppp-40575b78b7bb043c7a0ff4dd29a048be056dee9f.zip | |
Merge pull request #346 from nuclearcat/ipoe-stale-session-flush
Ipoe stale session flush fixes
Diffstat (limited to 'tests/accel-pppd')
| -rw-r--r-- | tests/accel-pppd/ipoe/test_ipoe_link_ops.py | 82 | ||||
| -rw-r--r-- | tests/accel-pppd/ipoe/test_ipoe_stale_cleanup.py | 97 |
2 files changed, 179 insertions, 0 deletions
diff --git a/tests/accel-pppd/ipoe/test_ipoe_link_ops.py b/tests/accel-pppd/ipoe/test_ipoe_link_ops.py new file mode 100644 index 00000000..00d06af4 --- /dev/null +++ b/tests/accel-pppd/ipoe/test_ipoe_link_ops.py @@ -0,0 +1,82 @@ +import pytest +from common import process, ipoe_iface + + +@pytest.fixture() +def accel_pppd_config(veth_pair_netns): + return ( + """ + [modules] + connlimit + radius + ipoe + ippool + + [ip-pool] + gw-ip-address=192.0.2.1 + 192.0.2.2-255 + + [cli] + tcp=127.0.0.1:2001 + + [core] + log-error=/dev/stderr + + [log] + log-debug=/dev/stdout + log-file=/dev/stdout + log-emerg=/dev/stderr + level=5 + + [radius] + + [ipoe] + noauth=1 + shared=1 + gw-ip-address=192.0.2.1/24 + interface=re:.""" + + veth_pair_netns["veth_a"][1:] + ) + + +# sessions carry private state set up over generic netlink, a device made by +# rtnetlink would have none of it +@pytest.mark.dependency(depends=["ipoe_driver_loaded"], scope="session") +@pytest.mark.ipoe_driver +def test_ipoe_interface_cannot_be_created_by_iproute(): + (exit_code, out, err) = process.run( + ["ip", "link", "add", "ipoetest0", "type", "ipoe"] + ) + print("ip link add: exit=%d out=%s err=%s" % (exit_code, out, err)) + + # remove it again in case it got created anyway, so that the rest of the + # suite is not affected + process.run(["ip", "link", "del", "ipoetest0"]) + + assert exit_code != 0 + + +# stale interfaces have to be removable without restarting accel-pppd, which +# would drop every remaining session +@pytest.mark.dependency(depends=["ipoe_driver_loaded"], scope="session") +@pytest.mark.ipoe_driver +def test_ipoe_interface_can_be_deleted_by_iproute( + accel_pppd_instance, dhclient_instance, accel_cmd, veth_pair_netns +): + assert accel_pppd_instance, "accel-pppd did not start" + assert dhclient_instance["is_started"] + assert ipoe_iface.wait_for_session(accel_cmd, veth_pair_netns["veth_a"]) + + before = ipoe_iface.list_ipoe() + print("ipoe interfaces: " + str(before)) + assert len(before) > 0 + + (ifindex, name) = before[0] + + (exit_code, out, err) = process.run(["ip", "link", "del", name]) + print("ip link del %s: exit=%d out=%s err=%s" % (name, exit_code, out, err)) + assert exit_code == 0 + + after = ipoe_iface.list_ipoe() + print("ipoe interfaces after delete: " + str(after)) + assert (ifindex, name) not in after diff --git a/tests/accel-pppd/ipoe/test_ipoe_stale_cleanup.py b/tests/accel-pppd/ipoe/test_ipoe_stale_cleanup.py new file mode 100644 index 00000000..b7cfd533 --- /dev/null +++ b/tests/accel-pppd/ipoe/test_ipoe_stale_cleanup.py @@ -0,0 +1,97 @@ +import pytest +from common import accel_pppd_process, ipoe_iface + + +@pytest.fixture() +def accel_pppd_config(veth_pair_netns): + return ( + """ + [modules] + connlimit + radius + ipoe + ippool + + [ip-pool] + gw-ip-address=192.0.2.1 + 192.0.2.2-255 + + [cli] + tcp=127.0.0.1:2001 + + [core] + log-error=/dev/stderr + + [log] + log-debug=/dev/stdout + log-file=/dev/stdout + log-emerg=/dev/stderr + level=5 + + [radius] + + [ipoe] + noauth=1 + shared=1 + gw-ip-address=192.0.2.1/24 + interface=re:.""" + + veth_pair_netns["veth_a"][1:] + ) + + +# accel-pppd killed with SIGKILL has no chance to remove the session +# interfaces it created, so they are left in the kernel. The next instance is +# supposed to drop them while starting up. +@pytest.mark.dependency(depends=["ipoe_driver_loaded"], scope="session") +@pytest.mark.ipoe_driver +def test_ipoe_stale_interfaces_removed_after_sigkill( + accel_pppd_instance, + dhclient_instance, + accel_cmd, + accel_pppd, + accel_pppd_config_file, + veth_pair_netns, + pytestconfig, +): + assert accel_pppd_instance, "accel-pppd did not start" + assert dhclient_instance["is_started"] + assert ipoe_iface.wait_for_session(accel_cmd, veth_pair_netns["veth_a"]) + + # the session must have created an interface, otherwise there is nothing + # for this test to check + before = ipoe_iface.list_ipoe() + print("ipoe interfaces before the crash: " + str(before)) + assert len(before) > 0 + + assert ipoe_iface.kill_accel_pppd() > 0 + + # nothing removes them while no accel-pppd is running (not asserted, the + # kernel module is free to start doing it on its own one day) + print("ipoe interfaces after the crash: " + str(ipoe_iface.list_ipoe())) + + # start again, it replies to 'show version' only once the startup flush is + # done, so there is no need to wait for anything else + (is_started, thread, control) = accel_pppd_process.start( + accel_pppd, + ["-c" + accel_pppd_config_file], + accel_cmd, + pytestconfig.getoption("accel_pppd_max_wait_time"), + ) + + try: + assert is_started + + after = ipoe_iface.list_ipoe() + print("ipoe interfaces after the restart: " + str(after)) + + # compared by ifindex: dhclient may get a new session in the meantime, + # and the fresh interface would reuse the ipoe0 name + stale = set(before) & set(after) + assert not stale, "interfaces left over from the killed instance: " + str(stale) + finally: + accel_pppd_process.end( + thread, + control, + accel_cmd, + pytestconfig.getoption("accel_pppd_max_finish_time"), + ) |
