pub struct IfaceMap { /* private fields */ }Expand description
Refreshable cache of IPv4 interfaces.
Cheap to clone (Arc-shared internal state). Spawned tasks share a
single map and refresh on demand via IfaceMap::refresh_if_stale.
Implementations§
Source§impl IfaceMap
impl IfaceMap
Sourcepub fn new() -> Result<Self>
pub fn new() -> Result<Self>
Build a fresh map by enumerating interfaces now.
Fails when the OS enumeration fails, so an empty map means exactly
one thing — the host reported no IPv4 interfaces. It used to mean
that or that getifaddrs had errored, and every caller that asks
“is there an external NIC here?” read the two as the same answer.
Sourcepub fn refresh(&self) -> Result<()>
pub fn refresh(&self) -> Result<()>
Force-refresh the snapshot.
The single writer of Inner.ifaces, and it writes only what a
successful enumeration returned: on failure the previous snapshot
stands rather than being replaced by an empty one, so a transient
getifaddrs error cannot blank the fanout list under a running
sender.
Sourcepub fn refresh_if_stale(&self, max_age: Duration) -> Result<Duration>
pub fn refresh_if_stale(&self, max_age: Duration) -> Result<Duration>
Refresh if the snapshot is older than max_age. Returns the
snapshot age before any refresh.
Sourcepub fn spawn_refresh(
&self,
reactor: &Reactor,
period: Duration,
) -> TaskHandle<()>
pub fn spawn_refresh( &self, reactor: &Reactor, period: Duration, ) -> TaskHandle<()>
Spawn a background tokio task that refreshes the snapshot
every period until the returned tokio::task::JoinHandle
is aborted. Mirrors pvxs IfMapDaemon (evhelper.cpp:715-758)
which polls every 15 s.
Returns the handle so callers that own the runtime can store it for shutdown; dropping it does NOT cancel the task — abort it explicitly. Idempotent: multiple background refreshers on the same map cost extra wakeups but are harmless.
Without this, dynamic infrastructure (DHCP renewals changing the broadcast address; K8s pod network re-attach; VM live migration; cable hot-plug) leaves the snapshot stale, and any sender that derives a broadcast destination from the snapshot ends up sending to the wrong subnet.
Sourcepub fn all(&self) -> Vec<IfaceInfo>
pub fn all(&self) -> Vec<IfaceInfo>
Snapshot of all IPv4 interfaces. Includes loopback unless
callers filter via IfaceInfo::up_non_loopback.
Sourcepub fn up_non_loopback(&self) -> Vec<IfaceInfo>
pub fn up_non_loopback(&self) -> Vec<IfaceInfo>
Snapshot of up, non-loopback IPv4 interfaces — the typical fanout target list for SEARCH/beacon traffic.
Sourcepub fn by_index(&self, index: u32) -> Option<IfaceInfo>
pub fn by_index(&self, index: u32) -> Option<IfaceInfo>
Look up an interface by its kernel index. Returns None when
the index isn’t known to this snapshot — caller may want to
refresh() and retry once.
Sourcepub fn route_to(&self, dest: Ipv4Addr) -> Option<IfaceInfo>
pub fn route_to(&self, dest: Ipv4Addr) -> Option<IfaceInfo>
Pick the interface index that should originate traffic
destined for dest. The selection rules (in priority order):
- Subnet match —
destfalls within an interface’s(ip, netmask). Returned when present. - Broadcast match —
destequals an interface’s subnet broadcast. - Loopback —
127.0.0.0/8→ loopback interface. - Default route — an interface with a
0.0.0.0netmask matches any destination; used only as a fallback so it never shadows a specific subnet match. - Otherwise
None— caller treats this as “no per-NIC pinning, let the OS route”. For limited broadcast and multicast destinations the caller fanouts across all interfaces explicitly.