ci(interop-netem): adopt nsenter for improved network namespace operations
Rust CI / cargo fmt (push) Successful in 17s
Rust CI / cargo clippy (push) Successful in 28s
Rust CI / cargo check (x86_64-unknown-linux-gnu) (push) Successful in 26s
Rust CI / cargo check (x86_64-unknown-linux-musl) (push) Successful in 31s
Rust CI / cargo test (x86_64-unknown-linux-gnu) (push) Successful in 1m12s
Rust CI / cargo doc (push) Successful in 29s
Rust CI / cargo test (x86_64-unknown-linux-musl) (push) Successful in 1m20s
Fuzz Smoke / cargo fuzz smoke (push) Successful in 1m38s
Netem Interop / netem interop (push) Successful in 1m20s
Supply chain / cargo-deny advisories (push) Successful in 18s
Supply chain / cargo-deny bans licenses sources (push) Successful in 17s
Supply chain / actionlint (push) Successful in 2s
Build binaries / Build (arm-musleabi) (push) Successful in 4m37s
Build binaries / Build (aarch64-musl) (push) Successful in 4m50s
Build binaries / Build (arm-musleabihf) (push) Successful in 4m9s
Build binaries / Build (armv7-musleabi) (push) Successful in 4m7s
Build binaries / Build (armv7-musleabihf) (push) Successful in 4m19s
Build binaries / Build (i686-musl) (push) Successful in 4m24s
Build binaries / Build (mips-musl) (push) Successful in 3m58s
Build binaries / Build (mips64-muslabi64) (push) Successful in 4m4s
Build binaries / Build (mips64el-muslabi64) (push) Successful in 4m1s
Build binaries / Build (mipsel-musl) (push) Successful in 4m2s
Build binaries / Build (riscv64gc-musl) (push) Successful in 4m13s
Build binaries / Build (x86_64-musl) (push) Successful in 4m8s
Rust CI / cargo fmt (push) Successful in 17s
Rust CI / cargo clippy (push) Successful in 28s
Rust CI / cargo check (x86_64-unknown-linux-gnu) (push) Successful in 26s
Rust CI / cargo check (x86_64-unknown-linux-musl) (push) Successful in 31s
Rust CI / cargo test (x86_64-unknown-linux-gnu) (push) Successful in 1m12s
Rust CI / cargo doc (push) Successful in 29s
Rust CI / cargo test (x86_64-unknown-linux-musl) (push) Successful in 1m20s
Fuzz Smoke / cargo fuzz smoke (push) Successful in 1m38s
Netem Interop / netem interop (push) Successful in 1m20s
Supply chain / cargo-deny advisories (push) Successful in 18s
Supply chain / cargo-deny bans licenses sources (push) Successful in 17s
Supply chain / actionlint (push) Successful in 2s
Build binaries / Build (arm-musleabi) (push) Successful in 4m37s
Build binaries / Build (aarch64-musl) (push) Successful in 4m50s
Build binaries / Build (arm-musleabihf) (push) Successful in 4m9s
Build binaries / Build (armv7-musleabi) (push) Successful in 4m7s
Build binaries / Build (armv7-musleabihf) (push) Successful in 4m19s
Build binaries / Build (i686-musl) (push) Successful in 4m24s
Build binaries / Build (mips-musl) (push) Successful in 3m58s
Build binaries / Build (mips64-muslabi64) (push) Successful in 4m4s
Build binaries / Build (mips64el-muslabi64) (push) Successful in 4m1s
Build binaries / Build (mipsel-musl) (push) Successful in 4m2s
Build binaries / Build (riscv64gc-musl) (push) Successful in 4m13s
Build binaries / Build (x86_64-musl) (push) Successful in 4m8s
This commit is contained in:
2 files changed
+27
-28
No files matched your search
@@ -43,12 +43,13 @@ jobs:
|
|||||||
- name: Install netem dependencies
|
- name: Install netem dependencies
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install -y --no-install-recommends iproute2 python3
|
sudo apt-get install -y --no-install-recommends iproute2 python3 util-linux
|
||||||
|
|
||||||
- name: Check host tools and network administration access
|
- name: Check host tools and network administration access
|
||||||
run: |
|
run: |
|
||||||
ip -V
|
ip -V
|
||||||
tc -V
|
tc -V
|
||||||
|
nsenter --version
|
||||||
go version
|
go version
|
||||||
# Exercise the namespace, veth, and qdisc operations the harness needs.
|
# Exercise the namespace, veth, and qdisc operations the harness needs.
|
||||||
# sudo/NET_ADMIN alone do not establish mount/namespace permissions.
|
# sudo/NET_ADMIN alone do not establish mount/namespace permissions.
|
||||||
@@ -56,9 +57,10 @@ jobs:
|
|||||||
probe_ns="irtt-preflight-$$"
|
probe_ns="irtt-preflight-$$"
|
||||||
ip netns add "$probe_ns"
|
ip netns add "$probe_ns"
|
||||||
trap 'ip netns delete "$probe_ns"' EXIT
|
trap 'ip netns delete "$probe_ns"' EXIT
|
||||||
ip netns exec "$probe_ns" sh -ec '
|
nsenter --net="/run/netns/$probe_ns" -- sh -ec '
|
||||||
ip link add probe0 type veth peer name probe1
|
ip link add probe0 type veth peer name probe1
|
||||||
tc qdisc add dev probe0 root netem delay 1ms
|
tc qdisc add dev probe0 root netem delay 1ms
|
||||||
|
tc qdisc show dev probe0
|
||||||
'
|
'
|
||||||
SH
|
SH
|
||||||
|
|
||||||
|
|||||||
@@ -215,7 +215,7 @@ def select_scenarios(args: argparse.Namespace) -> list[Scenario]:
|
|||||||
def preflight(args: argparse.Namespace) -> None:
|
def preflight(args: argparse.Namespace) -> None:
|
||||||
if platform.system() != "Linux":
|
if platform.system() != "Linux":
|
||||||
raise RuntimeError("netem interop requires Linux network namespaces and tc netem")
|
raise RuntimeError("netem interop requires Linux network namespaces and tc netem")
|
||||||
for binary in ["ip", "tc"]:
|
for binary in ["ip", "tc", "nsenter"]:
|
||||||
if shutil.which(binary) is None:
|
if shutil.which(binary) is None:
|
||||||
raise RuntimeError(f"required command not found in PATH: {binary}")
|
raise RuntimeError(f"required command not found in PATH: {binary}")
|
||||||
if args.sudo and shutil.which(args.sudo) is None:
|
if args.sudo and shutil.which(args.sudo) is None:
|
||||||
@@ -256,7 +256,7 @@ def sudo_prefix(args: argparse.Namespace) -> list[str]:
|
|||||||
|
|
||||||
|
|
||||||
def netns(args: argparse.Namespace, namespace: str, command: list[str]) -> list[str]:
|
def netns(args: argparse.Namespace, namespace: str, command: list[str]) -> list[str]:
|
||||||
return [*sudo_prefix(args), "ip", "netns", "exec", namespace, *command]
|
return [*sudo_prefix(args), "nsenter", f"--net=/run/netns/{namespace}", "--", *command]
|
||||||
|
|
||||||
|
|
||||||
def run_checked(
|
def run_checked(
|
||||||
@@ -300,12 +300,12 @@ def setup_namespaces(args: argparse.Namespace, run_dir: Path) -> None:
|
|||||||
[*sudo_prefix(args), "ip", "link", "add", CLIENT_VETH, "type", "veth", "peer", "name", SERVER_VETH],
|
[*sudo_prefix(args), "ip", "link", "add", CLIENT_VETH, "type", "veth", "peer", "name", SERVER_VETH],
|
||||||
[*sudo_prefix(args), "ip", "link", "set", CLIENT_VETH, "netns", CLIENT_NS],
|
[*sudo_prefix(args), "ip", "link", "set", CLIENT_VETH, "netns", CLIENT_NS],
|
||||||
[*sudo_prefix(args), "ip", "link", "set", SERVER_VETH, "netns", SERVER_NS],
|
[*sudo_prefix(args), "ip", "link", "set", SERVER_VETH, "netns", SERVER_NS],
|
||||||
[*sudo_prefix(args), "ip", "-n", CLIENT_NS, "addr", "add", CLIENT_ADDR, "dev", CLIENT_VETH],
|
netns(args, CLIENT_NS, ["ip", "addr", "add", CLIENT_ADDR, "dev", CLIENT_VETH]),
|
||||||
[*sudo_prefix(args), "ip", "-n", SERVER_NS, "addr", "add", SERVER_ADDR, "dev", SERVER_VETH],
|
netns(args, SERVER_NS, ["ip", "addr", "add", SERVER_ADDR, "dev", SERVER_VETH]),
|
||||||
[*sudo_prefix(args), "ip", "-n", CLIENT_NS, "link", "set", "lo", "up"],
|
netns(args, CLIENT_NS, ["ip", "link", "set", "lo", "up"]),
|
||||||
[*sudo_prefix(args), "ip", "-n", SERVER_NS, "link", "set", "lo", "up"],
|
netns(args, SERVER_NS, ["ip", "link", "set", "lo", "up"]),
|
||||||
[*sudo_prefix(args), "ip", "-n", CLIENT_NS, "link", "set", CLIENT_VETH, "up"],
|
netns(args, CLIENT_NS, ["ip", "link", "set", CLIENT_VETH, "up"]),
|
||||||
[*sudo_prefix(args), "ip", "-n", SERVER_NS, "link", "set", SERVER_VETH, "up"],
|
netns(args, SERVER_NS, ["ip", "link", "set", SERVER_VETH, "up"]),
|
||||||
]
|
]
|
||||||
for index, command in enumerate(commands):
|
for index, command in enumerate(commands):
|
||||||
run_checked(command, run_dir / "setup" / f"{index:02d}")
|
run_checked(command, run_dir / "setup" / f"{index:02d}")
|
||||||
@@ -409,12 +409,7 @@ def apply_netem(args: argparse.Namespace, scenario: Scenario, scenario_dir: Path
|
|||||||
for namespace, dev, setting in commands:
|
for namespace, dev, setting in commands:
|
||||||
if not setting:
|
if not setting:
|
||||||
continue
|
continue
|
||||||
command = [
|
command = netns(args, namespace, [
|
||||||
*sudo_prefix(args),
|
|
||||||
"ip",
|
|
||||||
"netns",
|
|
||||||
"exec",
|
|
||||||
namespace,
|
|
||||||
"tc",
|
"tc",
|
||||||
"qdisc",
|
"qdisc",
|
||||||
"replace",
|
"replace",
|
||||||
@@ -423,25 +418,20 @@ def apply_netem(args: argparse.Namespace, scenario: Scenario, scenario_dir: Path
|
|||||||
"root",
|
"root",
|
||||||
"netem",
|
"netem",
|
||||||
*shlex.split(setting),
|
*shlex.split(setting),
|
||||||
]
|
])
|
||||||
run_checked(command, scenario_dir / "netem" / f"{namespace}-{dev}")
|
run_checked(command, scenario_dir / "netem" / f"{namespace}-{dev}")
|
||||||
|
|
||||||
|
|
||||||
def delete_qdiscs(args: argparse.Namespace, log_dir: Path) -> None:
|
def delete_qdiscs(args: argparse.Namespace, log_dir: Path) -> None:
|
||||||
for namespace, dev in [(CLIENT_NS, CLIENT_VETH), (SERVER_NS, SERVER_VETH)]:
|
for namespace, dev in [(CLIENT_NS, CLIENT_VETH), (SERVER_NS, SERVER_VETH)]:
|
||||||
command = [
|
command = netns(args, namespace, [
|
||||||
*sudo_prefix(args),
|
|
||||||
"ip",
|
|
||||||
"netns",
|
|
||||||
"exec",
|
|
||||||
namespace,
|
|
||||||
"tc",
|
"tc",
|
||||||
"qdisc",
|
"qdisc",
|
||||||
"del",
|
"del",
|
||||||
"dev",
|
"dev",
|
||||||
dev,
|
dev,
|
||||||
"root",
|
"root",
|
||||||
]
|
])
|
||||||
run_checked(
|
run_checked(
|
||||||
command,
|
command,
|
||||||
log_dir / "qdisc-cleanup" / f"{namespace}-{dev}",
|
log_dir / "qdisc-cleanup" / f"{namespace}-{dev}",
|
||||||
@@ -698,12 +688,19 @@ def cleanup(args: argparse.Namespace, quiet: bool) -> None:
|
|||||||
return
|
return
|
||||||
if args.sudo and shutil.which(args.sudo) is None:
|
if args.sudo and shutil.which(args.sudo) is None:
|
||||||
return
|
return
|
||||||
commands = [
|
commands = []
|
||||||
[*sudo_prefix(args), "ip", "netns", "exec", CLIENT_NS, "tc", "qdisc", "del", "dev", CLIENT_VETH, "root"],
|
if shutil.which("nsenter") is not None:
|
||||||
[*sudo_prefix(args), "ip", "netns", "exec", SERVER_NS, "tc", "qdisc", "del", "dev", SERVER_VETH, "root"],
|
commands.extend([
|
||||||
|
netns(args, CLIENT_NS, ["tc", "qdisc", "del", "dev", CLIENT_VETH, "root"]),
|
||||||
|
netns(args, SERVER_NS, ["tc", "qdisc", "del", "dev", SERVER_VETH, "root"]),
|
||||||
|
])
|
||||||
|
commands.extend([
|
||||||
[*sudo_prefix(args), "ip", "netns", "delete", CLIENT_NS],
|
[*sudo_prefix(args), "ip", "netns", "delete", CLIENT_NS],
|
||||||
[*sudo_prefix(args), "ip", "netns", "delete", SERVER_NS],
|
[*sudo_prefix(args), "ip", "netns", "delete", SERVER_NS],
|
||||||
]
|
# A setup failure can leave either end of the pair in the host namespace.
|
||||||
|
[*sudo_prefix(args), "ip", "link", "delete", CLIENT_VETH],
|
||||||
|
[*sudo_prefix(args), "ip", "link", "delete", SERVER_VETH],
|
||||||
|
])
|
||||||
for command in commands:
|
for command in commands:
|
||||||
completed = subprocess.run(
|
completed = subprocess.run(
|
||||||
command,
|
command,
|
||||||
|
|||||||
Reference in new issue
Block a user