diff --git a/netstack/src/link/ethernet.rs b/netstack/src/link/ethernet.rs index fb6b06c828..89d1ea5361 100644 --- a/netstack/src/link/ethernet.rs +++ b/netstack/src/link/ethernet.rs @@ -87,6 +87,10 @@ pub struct EthernetLink { ip_address: Option, qdisc_config: QdiscConfig, stats: Stats, + arp_requests: u64, + arp_replies: u64, + arp_cache_hits: u64, + arp_cache_misses: u64, } impl EthernetLink { @@ -119,6 +123,10 @@ impl EthernetLink { qdisc_config: QdiscConfig::default(), stats: Stats::default(), neighbor_cache: Default::default(), + arp_requests: 0, + arp_replies: 0, + arp_cache_hits: 0, + arp_cache_misses: 0, } } @@ -205,6 +213,7 @@ impl EthernetLink { expires_at: now + Self::NEIGHBOR_LIVE_TIME, }, ); + self.arp_replies += 1; if let ArpOperation::Request = operation { let response = ArpRepr::EthernetIpv4 { @@ -398,6 +407,7 @@ impl EthernetLink { } fn send_arp(&mut self, now: Instant) { + self.arp_requests += 1; let Some(hardware_address) = self.hardware_address else { return; }; @@ -721,12 +731,17 @@ impl LinkDevice for EthernetLink { } match self.neighbor_cache.entry(next_hop) { - Entry::Vacant(_) => self.handle_missing_neighbor(next_hop, &packet, now), + Entry::Vacant(_) => { + self.arp_cache_misses += 1; + self.handle_missing_neighbor(next_hop, &packet, now) + } Entry::Occupied(e) => { if e.get().expires_at < now { e.remove(); + self.arp_cache_misses += 1; self.handle_missing_neighbor(next_hop, &packet, now) } else { + self.arp_cache_hits += 1; let mac = e.get().hardware_address; self.send_to( mac, @@ -849,6 +864,17 @@ impl LinkDevice for EthernetLink { self.neighbor_cache.clear(); } + fn arp_stats(&self) -> String { + format!( + "requests={} replies={} hits={} misses={} entries={}\n", + self.arp_requests, + self.arp_replies, + self.arp_cache_hits, + self.arp_cache_misses, + self.neighbor_cache.len(), + ) + } + fn statistics(&self) -> Stats { self.stats } diff --git a/netstack/src/link/mod.rs b/netstack/src/link/mod.rs index 11e9f1255f..fdff2467f2 100644 --- a/netstack/src/link/mod.rs +++ b/netstack/src/link/mod.rs @@ -45,6 +45,10 @@ pub trait LinkDevice { fn flush_arp(&mut self) {} + fn arp_stats(&self) -> String { + String::new() + } + fn mtu(&self) -> usize { 1500 } diff --git a/netstack/src/scheme/netcfg/mod.rs b/netstack/src/scheme/netcfg/mod.rs index 0e8da29785..3a59fbef26 100644 --- a/netstack/src/scheme/netcfg/mod.rs +++ b/netstack/src/scheme/netcfg/mod.rs @@ -360,6 +360,14 @@ fn mk_root_node( } } }, + "stats" => { + ro [devices] || { + match devices.borrow().get("eth0") { + Some(dev) => dev.arp_stats(), + None => "Device not found\n".into(), + } + } + }, "flush" => { wo [devices] (Option<()>, None) |_cur_value, _line| {