refactor(ebpf/maps_libbpf): drop ConnKey::new IpAddr ctor + both unreachable!() arms#309
Open
0xghost42 wants to merge 1 commit into
Open
refactor(ebpf/maps_libbpf): drop ConnKey::new IpAddr ctor + both unreachable!() arms#3090xghost42 wants to merge 1 commit into
ConnKey::new IpAddr ctor + both unreachable!() arms#3090xghost42 wants to merge 1 commit into
Conversation
…reachable!() arms
`ConnKey::new` and `ConnKey::new_icmp` both accepted `IpAddr`, matched
`(src_ip, dst_ip)` and panicked on the mixed-family arm via
`unreachable!("Mixed IPv4/IPv6 addresses not supported")`. In practice
every in-repo caller of `new` already went through the typed
`new_v4(Ipv4Addr, Ipv4Addr, ...)` / `new_v6(Ipv6Addr, Ipv6Addr, ...)`
wrappers, so the mixed arm in `new` was unreachable by construction —
it existed only because the inner constructor lost the family
information by widening to `IpAddr`.
Restructure so the type system carries the guarantee:
- Replace `pub fn new(IpAddr, IpAddr, ...)` with two small private
helpers `empty_v4` / `empty_v6` (build a zeroed key with the right
`family` and `proto`) plus `fill_v4` / `fill_v6` (write the address
slots in the family-specific endianness). `new_v4` / `new_v6` call
these directly — there is no longer a shared `IpAddr`-typed seam.
- Replace `pub fn new_icmp(IpAddr, IpAddr, u16)` with concrete
`new_icmp_v4(Ipv4Addr, Ipv4Addr, u16)` and
`new_icmp_v6(Ipv6Addr, Ipv6Addr, u16)`, built on the same helpers.
- Pull the family numbers and `IPPROTO_*` byte values out as named
constants (`AF_INET` = 2, `AF_INET6` = 10, `IPPROTO_TCP` = 6,
`IPPROTO_UDP` = 17, `IPPROTO_ICMP` = 1, `IPPROTO_ICMPV6` = 58) so
the constructors read at the level the kernel headers use.
`tracker_libbpf::lookup_icmp` now dispatches on `(src_ip, dst_ip)` at
the entry point (matching the shape `lookup` already used for the
TCP/UDP path) and forwards to private `lookup_icmp_v4` /
`lookup_icmp_v6` helpers, which pass concrete address types into the
new `new_icmp_v4` / `new_icmp_v6` constructors. The mixed-family case
is now handled exactly like the TCP/UDP path: a `log::warn!` plus
`None` return, no `unreachable!()` panic.
Net effect: both `unreachable!()` arms are gone, the wire-format byte
layout of `ConnKey` is unchanged, and the public surface
(`new_v4` / `new_v6` / new `new_icmp_v4` / new `new_icmp_v6`) is now
typesafe — passing mismatched address families is a compile error
rather than a runtime panic.
Local checks:
- `cargo check` on the macOS host — clean.
- `cargo clippy --all-targets -- -D warnings` — clean.
- `cargo fmt --check` — clean.
- `cargo test --lib` — 361 passed (the Linux-only `#[cfg(test)] mod`
is exercised on the CI Linux runner; five new cases lock the byte
layout of `new_v4` / `new_v6` / `new_icmp_v4` / `new_icmp_v6`
against the previous behaviour).
Closes domcyrus#306
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
ConnKey::newandConnKey::new_icmpboth acceptedIpAddr, matched(src_ip, dst_ip)and panicked on the mixed-family arm viaunreachable!("Mixed IPv4/IPv6 addresses not supported"). In practice every in-repo caller ofnewalready went through the typednew_v4(Ipv4Addr, Ipv4Addr, ...)/new_v6(Ipv6Addr, Ipv6Addr, ...)wrappers, so the mixed arm innewwas unreachable by construction — it existed only because the inner constructor lost the family information by widening toIpAddr. Same shape as the recently merged stun fix in #289.This goes with option 2 from #306 (you noted you would defer to my call): drop the
IpAddrentry points entirely so the typed surface is the only way in.What changed
src/network/platform/linux/ebpf/maps_libbpf.rs:pub fn new(IpAddr, IpAddr, ...)with two small private helpersempty_v4/empty_v6(build a zeroed key with the rightfamilyandproto) plusfill_v4/fill_v6(write the address slots in the family-specific endianness).new_v4/new_v6call these directly — there is no longer a sharedIpAddr-typed seam.pub fn new_icmp(IpAddr, IpAddr, u16)with concretenew_icmp_v4(Ipv4Addr, Ipv4Addr, u16)andnew_icmp_v6(Ipv6Addr, Ipv6Addr, u16), built on the same helpers.IPPROTO_*byte values out as named constants (AF_INET= 2,AF_INET6= 10,IPPROTO_TCP= 6,IPPROTO_UDP= 17,IPPROTO_ICMP= 1,IPPROTO_ICMPV6= 58) so the constructors read at the level the kernel headers use.src/network/platform/linux/ebpf/tracker_libbpf.rs:lookup_icmpnow dispatches on(src_ip, dst_ip)at the entry point (matching the shapelookupalready used for the TCP/UDP path) and forwards to privatelookup_icmp_v4/lookup_icmp_v6helpers, which pass concrete address types into the newnew_icmp_v4/new_icmp_v6constructors.log::warn!plusNonereturn, nounreachable!()panic.Net effect
unreachable!()arms are gone.ConnKeyis unchanged.new_v4/new_v6/ newnew_icmp_v4/ newnew_icmp_v6) is now typesafe — passing mismatched address families is a compile error rather than a runtime panic.Tests
Five new
#[cfg(test)] mod testscases inmaps_libbpf.rslock the byte layout ofnew_v4/new_v6/new_icmp_v4/new_icmp_v6against the previous behaviour:new_v4_writes_little_endian_addrs_and_tcp_proto— full IPv4 key shape with TCP.new_v4_marks_udp_when_not_tcp— locks theis_tcp=false→IPPROTO_UDPbranch.new_v6_writes_big_endian_addrs_across_all_four_slots— IPv6 key compared against the same per-slotu32::from_be_bytesformula the old code used.new_icmp_v4_uses_icmp_proto_and_zero_dport— locksIPPROTO_ICMP,dport=0,icmp_idlives insport.new_icmp_v6_uses_icmpv6_proto_and_zero_dport— same for IPv6 /IPPROTO_ICMPV6.The test module is inside the existing
cfg(target_os = "linux")/feature = "ebpf"gating of the file, so it runs on the Linux CI runner.Local checks (macOS host):
cargo check— clean.cargo clippy --all-targets -- -D warnings— clean.cargo fmt --check— clean.cargo test --lib— 361 passed.Closes #306