Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions scripts/nvx_tools/microvm_test_scripts/ipv6-egress-policy.sh.in
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ if [ -n "$dns" ]; then
fi
echo "NVX-IPV6-EGRESS-DNS ${dns:-none}"

# The probes keep their results in TMPDIR, or else in the guest's private
# /tmp. The host's /tmp is shared, so the tests that run this script in the
# host's shell give each run a TMPDIR of its own (#1007).
probe_dir=${TMPDIR:-/tmp}

probe_tcp() {
if response=$(wget -T 2 -qO- "$2" 2>/dev/null); then
if [ "$response" = "NVX-EGRESS-PROBE-$1" ]; then
Expand All @@ -29,7 +34,7 @@ probe_tcp() {
fi
else
echo blocked
fi >"/tmp/nvx-egress-$1"
fi >"$probe_dir/nvx-egress-$1"
}

# Only the host can observe UDP delivery. A denied flow may return 1; sender
Expand All @@ -41,27 +46,27 @@ probe_udp() {
case "$status" in
0 | 1) echo sent ;;
*) echo "failed-$status" ;;
esac >"/tmp/nvx-egress-$1"
esac >"$probe_dir/nvx-egress-$1"
}

probe_icmp() {
if ping -c 1 -W 2 "$2" >/dev/null 2>&1; then
echo reached
else
echo blocked
fi >"/tmp/nvx-egress-$1"
fi >"$probe_dir/nvx-egress-$1"
}

rm -f /tmp/nvx-egress-*
rm -f "$probe_dir"/nvx-egress-*
probe_tcp tcp6-named 'http://[@GATEWAY_IPV6@]:@NAMED_PORT@/tcp6-named' &
probe_tcp tcp6-other 'http://[@GATEWAY_IPV6@]:@OTHER_PORT@/tcp6-other' &
probe_udp udp6-named @GATEWAY_IPV6@ @NAMED_PORT@ &
probe_icmp icmp6 @GATEWAY_IPV6@ &
probe_tcp tcp4-named 'http://@GATEWAY_IPV4@:@NAMED_PORT@/tcp4-named' &
wait
for probe in tcp6-named tcp6-other udp6-named icmp6 tcp4-named; do
[ -s "/tmp/nvx-egress-$probe" ] || fail 70
echo "NVX-L3-L4-PROBE $probe=$(cat "/tmp/nvx-egress-$probe")"
[ -s "$probe_dir/nvx-egress-$probe" ] || fail 70
echo "NVX-L3-L4-PROBE $probe=$(cat "$probe_dir/nvx-egress-$probe")"
done

echo NVX-IPV6-EGRESS-OK
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ fail() {
exit "$code"
}

# The probes keep their results in TMPDIR, or else in the guest's private
# /tmp. The host's /tmp is shared, so the tests that run this script in the
# host's shell give each run a TMPDIR of its own (#1007).
probe_dir=${TMPDIR:-/tmp}

probe_tcp() {
if response=$(wget -T 2 -qO- "http://@GATEWAY_IPV4@:$2/$1" 2>/dev/null); then
if [ "$response" = "NVX-EGRESS-PROBE-$1" ]; then
Expand All @@ -15,7 +20,7 @@ probe_tcp() {
fi
else
echo blocked
fi >"/tmp/nvx-egress-$1"
fi >"$probe_dir/nvx-egress-$1"
}

# Only the host can observe UDP delivery. A denied flow may return 1; sender
Expand All @@ -27,10 +32,10 @@ probe_udp() {
case "$status" in
0 | 1) echo sent ;;
*) echo "failed-$status" ;;
esac >"/tmp/nvx-egress-$1"
esac >"$probe_dir/nvx-egress-$1"
}

rm -f /tmp/nvx-egress-*
rm -f "$probe_dir"/nvx-egress-*
probe_tcp tcp-below @BELOW_PORT@ &
probe_tcp tcp-first @FIRST_PORT@ &
probe_tcp tcp-inside @INSIDE_PORT@ &
Expand All @@ -44,8 +49,8 @@ probe_udp udp-above @ABOVE_PORT@ &
wait
for probe in tcp-below tcp-first tcp-inside tcp-last tcp-above \
udp-below udp-first udp-inside udp-last udp-above; do
[ -s "/tmp/nvx-egress-$probe" ] || fail 70
echo "NVX-L3-L4-PROBE $probe=$(cat "/tmp/nvx-egress-$probe")"
[ -s "$probe_dir/nvx-egress-$probe" ] || fail 70
echo "NVX-L3-L4-PROBE $probe=$(cat "$probe_dir/nvx-egress-$probe")"
done

echo NVX-L3-L4-EGRESS-PORT-RANGES-OK
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ fail() {
exit "$code"
}

# The probes keep their results in TMPDIR, or else in the guest's private
# /tmp. The host's /tmp is shared, so the tests that run this script in the
# host's shell give each run a TMPDIR of its own (#1007).
probe_dir=${TMPDIR:-/tmp}

probe_tcp() {
if response=$(wget -T 2 -qO- "http://@GATEWAY_IPV4@:$2/$1" 2>/dev/null); then
if [ "$response" = "NVX-EGRESS-PROBE-$1" ]; then
Expand All @@ -15,7 +20,7 @@ probe_tcp() {
fi
else
echo blocked
fi >"/tmp/nvx-egress-$1"
fi >"$probe_dir/nvx-egress-$1"
}

# Only the host can observe UDP delivery. A denied flow may return 1; sender
Expand All @@ -27,27 +32,27 @@ probe_udp() {
case "$status" in
0 | 1) echo sent ;;
*) echo "failed-$status" ;;
esac >"/tmp/nvx-egress-$1"
esac >"$probe_dir/nvx-egress-$1"
}

probe_icmp() {
if ping -c 1 -W 2 @GATEWAY_IPV4@ >/dev/null 2>&1; then
echo reached
else
echo blocked
fi >/tmp/nvx-egress-icmp
fi >"$probe_dir/nvx-egress-icmp"
}

rm -f /tmp/nvx-egress-*
rm -f "$probe_dir"/nvx-egress-*
probe_tcp tcp-named @NAMED_PORT@ &
probe_tcp tcp-other @OTHER_PORT@ &
probe_udp udp-named @NAMED_PORT@ &
probe_udp udp-other @OTHER_PORT@ &
probe_icmp &
wait
for probe in tcp-named tcp-other udp-named udp-other icmp; do
[ -s "/tmp/nvx-egress-$probe" ] || fail 70
echo "NVX-L3-L4-PROBE $probe=$(cat "/tmp/nvx-egress-$probe")"
[ -s "$probe_dir/nvx-egress-$probe" ] || fail 70
echo "NVX-L3-L4-PROBE $probe=$(cat "$probe_dir/nvx-egress-$probe")"
done

echo NVX-L3-L4-EGRESS-PROTOCOLS-OK
Expand Down
95 changes: 79 additions & 16 deletions scripts/test_microvm_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,16 @@ def _posix_shell() -> str | None:
return shell


def _probe_environment(probe_dir: Path) -> dict[str, str]:
"""Return the environment of a run of an egress script in the host's
shell, which then keeps its probes' results in `probe_dir`.

The scripts keep the results in TMPDIR, or else in /tmp, which is private
to a guest but shared on the host: runs there at once would delete and
overwrite each other's results (#1007)."""
return {**os.environ, "TMPDIR": str(probe_dir)}


def _bdi_stats(dirty: int, io: int = 0, more_io: int = 0) -> str:
"""Return a backing device's debugfs statistics whose writeback lists hold
`dirty`, `io`, and `more_io` inodes, in the kernel's layout."""
Expand Down Expand Up @@ -8441,6 +8451,26 @@ def test_l3_l4_egress_protocols_reject_leaks_and_missed_traffic(self):
(output_dir / "l3-l4-egress-protocols-results.json").exists()
)

def _run_egress_script(
self, shell: str, script: str
) -> tuple[subprocess.CompletedProcess[str], list[str]]:
"""Run an L3/L4 egress script in the host's shell with a TMPDIR of its
own, which holds a stale result, and return the shell's result and the
names of the files that the run left in that TMPDIR."""
with tempfile.TemporaryDirectory() as temporary:
probe_dir = Path(temporary)
(probe_dir / "nvx-egress-stale").write_text("stale\n", encoding="utf-8")
result = subprocess.run(
[shell],
input=script,
text=True,
capture_output=True,
timeout=10,
check=False,
env=_probe_environment(probe_dir),
)
return result, sorted(path.name for path in probe_dir.iterdir())

def test_l3_l4_egress_protocol_script_reports_each_probe(self):
shell = _posix_shell()
if shell is None:
Expand Down Expand Up @@ -8468,14 +8498,7 @@ def test_l3_l4_egress_protocol_script_reports_each_probe(self):
"}\n"
"ping() { return 1; }\n"
)
result = subprocess.run(
[shell],
input=stubs + script,
text=True,
capture_output=True,
timeout=10,
check=False,
)
result, probes = self._run_egress_script(shell, stubs + script)

self.assertEqual(result.returncode, 0, result.stderr)
self.assertEqual(
Expand All @@ -8490,6 +8513,17 @@ def test_l3_l4_egress_protocol_script_reports_each_probe(self):
"NVX-EXIT 0",
],
)
# The run replaced the stale result in its TMPDIR with its probes'.
self.assertEqual(
probes,
[
"nvx-egress-icmp",
"nvx-egress-tcp-named",
"nvx-egress-tcp-other",
"nvx-egress-udp-named",
"nvx-egress-udp-other",
],
)

def test_egress_probe_server_records_only_matching_probes(self):
tcp, udp = microvm_tests._bind_dual_protocol_ports(2, "127.0.0.1")
Expand Down Expand Up @@ -9085,14 +9119,7 @@ def test_l3_l4_egress_port_range_script_reports_each_probe(self):
" esac\n"
"}\n"
)
result = subprocess.run(
[shell],
input=stubs + script,
text=True,
capture_output=True,
timeout=10,
check=False,
)
result, probes = self._run_egress_script(shell, stubs + script)

self.assertEqual(result.returncode, 0, result.stderr)
self.assertEqual(
Expand All @@ -9112,6 +9139,22 @@ def test_l3_l4_egress_port_range_script_reports_each_probe(self):
"NVX-EXIT 0",
],
)
# The run replaced the stale result in its TMPDIR with its probes'.
self.assertEqual(
probes,
[
"nvx-egress-tcp-above",
"nvx-egress-tcp-below",
"nvx-egress-tcp-first",
"nvx-egress-tcp-inside",
"nvx-egress-tcp-last",
"nvx-egress-udp-above",
"nvx-egress-udp-below",
"nvx-egress-udp-first",
"nvx-egress-udp-inside",
"nvx-egress-udp-last",
],
)

def test_runner_dispatches_l3_l4_egress_port_ranges(self):
def require(path: Path, _description: str) -> Path:
Expand Down Expand Up @@ -9638,6 +9681,9 @@ def _run_ipv6_guest_script(
.replace("/proc/", f"{root.as_posix()}/proc/")
.replace("/etc/resolv.conf", f"{root.as_posix()}/etc/resolv.conf")
)
# The root's tmp stands for the guest's /tmp, where the probes keep
# their results.
(root / "tmp").mkdir(exist_ok=True)
return subprocess.run(
[shell],
input="record_exit() { printf 'NVX-EXIT %s\\n' \"$1\"; }\n"
Expand All @@ -9647,6 +9693,7 @@ def _run_ipv6_guest_script(
capture_output=True,
timeout=10,
check=False,
env=_probe_environment(root / "tmp"),
)

def test_ipv6_egress_script_checks_the_identity_and_reports_each_probe(self):
Expand Down Expand Up @@ -9705,6 +9752,10 @@ def test_ipv6_egress_script_checks_the_identity_and_reports_each_probe(self):
root = Path(temporary)
(root / "proc" / "net").mkdir(parents=True)
(root / "etc").mkdir()
(root / "tmp").mkdir()
(root / "tmp" / "nvx-egress-stale").write_text(
"stale\n", encoding="utf-8"
)
(root / "proc" / "cmdline").write_text(
"quiet virtnet_ip=192.0.2.2 virtnet_mask=255.255.255.0 "
f"virtnet_gw=192.0.2.1{dns} virtnet_ip6=fd00::c000:202/120 "
Expand Down Expand Up @@ -9741,6 +9792,18 @@ def test_ipv6_egress_script_checks_the_identity_and_reports_each_probe(self):
"NVX-EXIT 0",
],
)
# The run replaced the stale result in the root's tmp with its
# probes'.
self.assertEqual(
sorted(path.name for path in (root / "tmp").iterdir()),
[
"nvx-egress-icmp6",
"nvx-egress-tcp4-named",
"nvx-egress-tcp6-named",
"nvx-egress-tcp6-other",
"nvx-egress-udp6-named",
],
)

def test_ipv6_egress_snapshot_script_probes_across_the_snapshot(self):
shell = _posix_shell()
Expand Down
Loading