From 22b9eeacdc716840be8782de044e6a0eaa84cf62 Mon Sep 17 00:00:00 2001 From: Rayhaan Jaufeerally Date: Thu, 1 Oct 2026 20:51:15 +0200 Subject: [PATCH] Count multiprotocol prefixes in the UPDATE log lines The 'Sending UPDATE' and 'Received UPDATE' lines counted only the IPv4 fields of the message body, so every IPv6 UPDATE logged announced=0. Co-Authored-By: Claude Fable 5.1 --- crates/server/src/fsm.rs | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/crates/server/src/fsm.rs b/crates/server/src/fsm.rs index 9fcb6a1..a7a404f 100644 --- a/crates/server/src/fsm.rs +++ b/crates/server/src/fsm.rs @@ -260,12 +260,8 @@ async fn established_loop( } Message::Update(update) => { hold_timer.as_mut().reset(Instant::now() + hold_duration); - info!( - peer = %peer_id, - withdrawn = update.withdrawn_routes.len(), - announced = update.announced_routes.len(), - "Received UPDATE", - ); + let (withdrawn, announced) = prefix_counts(&update); + info!(peer = %peer_id, withdrawn, announced, "Received UPDATE"); apply_update(adj_rib_in, peer_id, &update.path_attributes, &update.withdrawn_routes, &update.announced_routes).await; } @@ -286,12 +282,8 @@ async fn established_loop( } Some(msg) = outbound.recv() => { if let Message::Update(update) = &msg { - info!( - peer = %peer_id, - withdrawn = update.withdrawn_routes.len(), - announced = update.announced_routes.len(), - "Sending UPDATE", - ); + let (withdrawn, announced) = prefix_counts(update); + info!(peer = %peer_id, withdrawn, announced, "Sending UPDATE"); } send_message(writer, &msg, ctx).await?; // A NOTIFICATION from our side ends the session (RFC 4271 ยง6). @@ -390,6 +382,21 @@ async fn close_for_collision( // RIB helpers // --------------------------------------------------------------------------- +/// Prefixes withdrawn and announced by an UPDATE, across the IPv4 fields in +/// the message body and the multiprotocol attributes (where IPv6 travels). +fn prefix_counts(update: &bgp_packet::message::UpdateMessage) -> (usize, usize) { + let mut withdrawn = update.withdrawn_routes.len(); + let mut announced = update.announced_routes.len(); + for attr in &update.path_attributes { + match attr { + PathAttribute::MpReachNlri(mp) => announced += mp.prefixes.len(), + PathAttribute::MpUnreachNlri(mp) => withdrawn += mp.prefixes.len(), + _ => {} + } + } + (withdrawn, announced) +} + /// Applies a received UPDATE to the Adj-RIB-In. /// /// Handles both the legacy IPv4 NLRI fields and the MP_REACH/MP_UNREACH path