Skip to content

track bgp session state in dataplane - #1645

Merged
Fredi-raspall merged 14 commits into
mainfrom
pr/fredi/bgp_sess_change_record
Jul 23, 2026
Merged

track bgp session state in dataplane#1645
Fredi-raspall merged 14 commits into
mainfrom
pr/fredi/bgp_sess_change_record

Conversation

@Fredi-raspall

@Fredi-raspall Fredi-raspall commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

This goes on top of #1643

Log (info) events for BGP session changes

2026-07-18T15:40:24.800367Z  INFO                 routerIO dataplane_routing::router::ctl: 284: BGP session with 7.0.0.2 (ASN 65002) changed Idle -> Established

Generate events so that all changes get recorded independently of logging and that these include:

  • reason for reset / down
  • downtime
dataplane(✔)# show router events
 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ROUTER_EVENTS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 generated: 13 stored: 13 capacity: 2000

 0    2026-07-19T 12:08:40: Started!
 1    2026-07-19T 12:08:40: Connected to frr-agent
 2    2026-07-19T 12:08:46: Router config request received for generation 1
 3    2026-07-19T 12:08:46: Router config request for generation 1 SUCCEEDED
 4    2026-07-19T 12:08:46: Requested FRR configuration for generation 1
 5    2026-07-19T 12:08:46: CPI status changed to Connected
 6    2026-07-19T 12:08:47: FRR configuration for generation 1 SUCCEEDED
 7    2026-07-19T 12:08:57: Status of BGP peer 10.0.0.13 (id:7.0.0.2 ASN:65002) changed: Unset -> Established
 8    2026-07-19T 12:08:57: Status of BGP peer 10.0.1.13 (id:7.0.0.6 ASN:65006) changed: Unset -> Established
 9    2026-07-19T 12:09:08: Status of BGP peer 10.0.0.13 (id:7.0.0.2 ASN:65002) changed: Established -> Idle reason: Remote system closed
 10   2026-07-19T 12:09:10: Status of BGP peer 10.0.0.13 (id:7.0.0.2 ASN:65002) changed: Idle -> Established (downtime: 00:00:02)
 11   2026-07-19T 12:09:50: Status of BGP peer 10.0.1.13 (id:7.0.0.6 ASN:65006) changed: Established -> Idle reason: Local system closed
 12   2026-07-19T 12:10:01: Status of BGP peer 10.0.1.13 (id:7.0.0.6 ASN:65006) changed: Idle -> Established (downtime: 00:00:11)

@Fredi-raspall
Fredi-raspall requested a review from a team as a code owner July 18, 2026 15:54
@coderabbitai

coderabbitai Bot commented Jul 18, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Changes

BGP neighbor status contracts now preserve optional reset metadata and require message counters. BMP peer transitions update dataplane state, emit router-control events, and render router events. BMP mirroring is enabled and startup now occurs after router initialization with immutable control-sender access.

BGP neighbor event propagation and BMP mirroring

Layer / File(s) Summary
Status and event contracts
config/src/internal/status/mod.rs, routing/src/bmp/bmp_render.rs, routing/src/cli/*, routing/src/router/revent.rs
Neighbor status fields, session-state formatting, BGP event data, duration formatting, and router-event rendering are updated.
BMP event generation and routing
routing/src/bmp/*, routing/src/router/ctl.rs
BMP peer-up and peer-down handling updates status, creates events for changed sessions, and forwards them through router control.
BMP mirroring and status conversion
config/src/converters/k8s/status/bgp.rs, config/src/internal/routing/bmp.rs, routing/src/bmp/bmp_render.rs, routing/src/frr/renderer/bgp.rs, dataplane/src/runtime.rs
Message counters use required fields, Kubernetes conversion populates counters and optional reset metadata, and BMP mirroring is configured and counted.
Runtime wiring and shared control access
dataplane/src/runtime.rs, mgmt/src/processor/*, routing/src/frr/test.rs
BMP startup moves after router initialization and receives router control; callers use immutable control-sender borrows.

Possibly related PRs

Suggested reviewers: copilot, daniel-noland, sergeymatov, qmonnet

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 53.49% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title accurately summarizes the main change: tracking BGP session state in the dataplane.
Description check ✅ Passed The description matches the change and mentions session-change logging and event generation with reason and downtime.

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds BGP neighbor session state change tracking to the dataplane by propagating BMP peer up/down notifications into the router control loop, emitting both info logs and persistent router events.

Changes:

  • Introduce BgpNeighEvent generation from BMP PeerUp/PeerDown and forward it to the router via RouterCtlSender.
  • Add a new RouterEvent::BgpNeighStateChange variant and expand the router event log capacity (1000 → 2000).
  • Make RouterCtlSender APIs take &self (not &mut self) and thread the sender into the BMP server/handler.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
routing/src/router/revent.rs Adds BGP neighbor state-change router events + increases event log capacity.
routing/src/router/ctl.rs Adds ctl message for BGP neighbor status changes; makes sender methods take &self.
routing/src/frr/test.rs Updates test to reflect RouterCtlSender no longer requiring mut.
routing/src/bmp/mod.rs Threads RouterCtlSender into BMP server spawn path.
routing/src/bmp/handler.rs Calls BMP render logic with router ctl sender to emit events.
routing/src/bmp/bmp_render.rs Generates BGP neighbor state-change events from BMP messages.
mgmt/src/processor/proc.rs Updates call sites to use &RouterCtlSender APIs.
mgmt/src/processor/launch.rs Updates interface-event notifier to use non-mutable router ctl sender.
dataplane/src/runtime.rs Starts BMP server after router so BMP handler can send router events.
config/src/internal/status/mod.rs Adds Display for BGP session state; makes last_reset_reason optional.
config/src/converters/k8s/status/bgp.rs Adjusts k8s status conversion/tests for optional last_reset_reason.

Comment thread routing/src/bmp/handler.rs Outdated
@Fredi-raspall Fredi-raspall mentioned this pull request Jul 18, 2026
@Fredi-raspall
Fredi-raspall force-pushed the pr/fredi/bgp_sess_change_record branch from f6c954b to 357d5a0 Compare July 19, 2026 10:54
@Fredi-raspall Fredi-raspall self-assigned this Jul 19, 2026
Base automatically changed from pr/fredi/bmp_simplify to main July 20, 2026 12:50
@Fredi-raspall
Fredi-raspall force-pushed the pr/fredi/bgp_sess_change_record branch from 49819bc to 0ca0ef1 Compare July 20, 2026 14:55

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@routing/src/bmp/bmp_render.rs`:
- Around line 306-309: Update the PeerDown handling around
set_neighbor_session_state so last_reset_reason and last_reset_time are assigned
only when the previous neighbor state is not Idle. Preserve the existing
duplicate-message behavior and connection counter, while retaining the original
downtime start across repeated PeerDown notifications.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b77fc23b-f416-4325-8bc4-1d58b261a5c7

📥 Commits

Reviewing files that changed from the base of the PR and between c3cd8ed and 0ca0ef1.

📒 Files selected for processing (13)
  • config/src/converters/k8s/status/bgp.rs
  • config/src/internal/status/mod.rs
  • dataplane/src/runtime.rs
  • mgmt/src/processor/launch.rs
  • mgmt/src/processor/proc.rs
  • routing/src/bmp/bmp_render.rs
  • routing/src/bmp/handler.rs
  • routing/src/bmp/mod.rs
  • routing/src/cli/display.rs
  • routing/src/cli/mod.rs
  • routing/src/frr/test.rs
  • routing/src/router/ctl.rs
  • routing/src/router/revent.rs

Comment thread routing/src/bmp/bmp_render.rs Outdated
@Fredi-raspall Fredi-raspall added the ci:+release Enable VLAB release tests label Jul 21, 2026
Copilot AI review requested due to automatic review settings July 21, 2026 13:08
@Fredi-raspall
Fredi-raspall force-pushed the pr/fredi/bgp_sess_change_record branch from 0ca0ef1 to c7fc043 Compare July 21, 2026 13:08

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 3 comments.

Comment thread routing/src/router/revent.rs
Comment thread routing/src/router/revent.rs
Comment thread routing/src/cli/display.rs
Signed-off-by: Fredi Raspall <fredi@githedgehog.com>
BgpNeighEvent represents a status change of a BGP session.

Signed-off-by: Fredi Raspall <fredi@githedgehog.com>
Propagate a RouterCtlSender to the BMP server so that it can send
events on BGP peer changes.

Signed-off-by: Fredi Raspall <fredi@githedgehog.com>
Mutability is not required by most methods of RouterCtlSender.
Replace &mut by &self.

Signed-off-by: Fredi Raspall <fredi@githedgehog.com>
Signed-off-by: Fredi Raspall <fredi@githedgehog.com>
We were not populating the last reset reason when parsing a
peer down message. Fix this and make the field Option<String>
instead of String.

Also, enlarge the event buffer to 2000 events.

Signed-off-by: Fredi Raspall <fredi@githedgehog.com>
Reorganize the handling of peer up/down messages so that if a
BGP neighbor event needs to be sent, the RwLock guard on the status
has been released before attempting to send on the channel as,
otherwise, the lock would unnecessarily be held if the channel
was full and blocked us.

Signed-off-by: Fredi Raspall <fredi@githedgehog.com>
Instead of using the bgp router id, use the peer's key (address)
in events. The router id is also kept.

Signed-off-by: Fredi Raspall <fredi@githedgehog.com>
Compute BGP session downtime and include it in the bgp events.

Signed-off-by: Fredi Raspall <fredi@githedgehog.com>
Add some sanity on bgp peer down to ensure that we only account
for transitions from established. With FRR0s bmp implementation,
we should only see peer downs when established state is left.

Signed-off-by: Fredi Raspall <fredi@githedgehog.com>
Copilot AI review requested due to automatic review settings July 23, 2026 08:29

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

routing/src/router/revent.rs:104

confidence: 9
tags: [style]

The router event message uses "(downtime of …)", which reads awkwardly and doesn’t match the example output in the PR description ("downtime: …"). Consider using a consistent "downtime:" label.
            } else if let Some(downtime) = &bgp_ev.last_downtime {
                let downtime = PrettyDuration::new(*downtime);
                write!(f, " (downtime of {downtime})")?;
            }
</details>

Comment thread routing/src/bmp/bmp_render.rs
@Fredi-raspall
Fredi-raspall enabled auto-merge July 23, 2026 09:54
Making them optional overcomplicates the code for no real benefit.

Signed-off-by: Fredi Raspall <fredi@githedgehog.com>
Process route mirrored packets to provide better message stats.
This comes with limitations due to FRR's incomplete BMP
implementation.

Signed-off-by: Fredi Raspall <fredi@githedgehog.com>
This is needed for the msg stats to be populated.

Signed-off-by: Fredi Raspall <fredi@githedgehog.com>
Signed-off-by: Fredi Raspall <fredi@githedgehog.com>
Copilot AI review requested due to automatic review settings July 23, 2026 09:54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 3 comments.

Comments suppressed due to low confidence (1)

routing/src/bmp/bmp_render.rs:39

confidence: 8
tags: [other]

`BgpNeighEvent::new` is `pub`, which allows external crates to construct this internal event type. If this is only intended for intra-crate use (as suggested by `pub(crate)` fields), make the constructor `pub(crate)` as well.
pub fn new(
</details>


/// A struct representing a status change of a BGP peering. Most of the information here
/// comes from `BgpNeighborStatus`.
pub struct BgpNeighEvent {
Comment thread routing/src/router/ctl.rs
let msg = RouterCtlMsg::IfEvent(ev);
self.send_and_wake(msg).await
}
pub async fn send_bgp_neigh_change(&self, ev: BgpNeighEvent) -> Result<(), RouterError> {
Comment on lines +247 to 252
if let BgpMessage::Open(_open) = pu.received_message() {
// amend FRR's limitation by increasing the count of opens received
// FIXME: this seems to over count the messages received.
// TODO: investigate if it is needed
// neigh.messages.received.open = neigh.messages.received.open.saturating_add(1);
}

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
routing/src/bmp/bmp_render.rs (1)

308-320: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Preserve the current reset reason in non-established PeerDown events.

For Connect, Active, Open, or Unset sessions, this code transitions to Idle and emits an event, but leaves last_reset_reason and last_reset_time unchanged. The event therefore contains no reason or stale downtime metadata. Record reset metadata for every state-changing PeerDown while keeping connections_dropped limited to Established sessions.

Proposed fix
                 let prev_state = neigh.session_state;
                 let prev_dropped = neigh.connections_dropped;
+                let state_changed = prev_state != BgpNeighborSessionState::Idle;

                 set_neighbor_session_state(neigh, BgpNeighborSessionState::Idle);
+                if state_changed {
+                    neigh.last_reset_reason = Some(pretty(pd.reason().get_type()));
+                    neigh.last_reset_time = Some(std::time::Instant::now());
+                }
                 if prev_state == BgpNeighborSessionState::Established {
                     neigh.connections_dropped = neigh.connections_dropped.saturating_add(1);
-                    neigh.last_reset_reason = Some(pretty(pd.reason().get_type()));
-                    neigh.last_reset_time = Some(std::time::Instant::now());
                 } else {

As per coding guidelines, this is a logic-error finding; as per PR objectives, BGP state events include the reset/down reason.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@routing/src/bmp/bmp_render.rs` around lines 308 - 320, Update the PeerDown
handling around the prev_state check so every state-changing event records
last_reset_reason from pd.reason().get_type() and refreshes last_reset_time,
including non-Established sessions. Keep connections_dropped.saturating_add(1)
restricted to the Established branch, while preserving the existing
non-Established diagnostic logging.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@routing/src/bmp/bmp_render.rs`:
- Around line 308-320: Update the PeerDown handling around the prev_state check
so every state-changing event records last_reset_reason from
pd.reason().get_type() and refreshes last_reset_time, including non-Established
sessions. Keep connections_dropped.saturating_add(1) restricted to the
Established branch, while preserving the existing non-Established diagnostic
logging.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7e6e1b3f-3916-4a9b-8755-7e8fd72fb221

📥 Commits

Reviewing files that changed from the base of the PR and between 3cf343a and 1b24972.

📒 Files selected for processing (6)
  • config/src/converters/k8s/status/bgp.rs
  • config/src/internal/routing/bmp.rs
  • config/src/internal/status/mod.rs
  • dataplane/src/runtime.rs
  • routing/src/bmp/bmp_render.rs
  • routing/src/frr/renderer/bgp.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • dataplane/src/runtime.rs

@Fredi-raspall
Fredi-raspall added this pull request to the merge queue Jul 23, 2026
Merged via the queue into main with commit d7e6f47 Jul 23, 2026
50 of 52 checks passed
@Fredi-raspall
Fredi-raspall deleted the pr/fredi/bgp_sess_change_record branch July 23, 2026 16:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci:+release Enable VLAB release tests ci:+vlab Enable VLAB tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants