Skip to content

[HA] swbus: replace stale peer connection on reconnect#209

Merged
vivekrnv merged 1 commit into
sonic-net:masterfrom
BYGX-wcr:fix/swbus-replace-stale-peer-connection
Jul 22, 2026
Merged

[HA] swbus: replace stale peer connection on reconnect#209
vivekrnv merged 1 commit into
sonic-net:masterfrom
BYGX-wcr:fix/swbus-replace-stale-peer-connection

Conversation

@BYGX-wcr

Copy link
Copy Markdown
Contributor

Description of PR

Summary:

After an HA peer NPU reboot, SWBus can retain a half-open incoming connection and continue routing HA messages through it even after the peer establishes a new connection. Messages appear locally queued but never reach the peer, which can leave HAMgrd stuck waiting for a vote reply and prevent publication of the activate_role pending operation.

This change replaces older accepted connections when the same logical peer reconnects and refreshes the send proxy when an equal next-hop identity is registered again.

Reviewer entry points:

  • crates/swbus-core/src/mux/conn_store.rs
  • crates/swbus-core/src/mux/multiplexer.rs
  • crates/swbus-core/src/mux/conn.rs

No new dependencies are required.

Fixes sonic-net/sonic-buildimage#28481

Type of change

  • Bug fix
  • New feature
  • Refactor / cleanup
  • Documentation update
  • Test improvement

Approach

What is the motivation for this PR?

Server-side connection IDs include the peer ephemeral source port. After a peer reboot, the new connection therefore has a different ID while the old half-open connection can remain in the connection store and routing table until the system TCP timeout expires.

During that interval, SWBus can select the stale next hop. Queueing succeeds locally, so alternate routes are not attempted, but the peer never receives the message.

How did you do it?

  • Serialize connection replacement and registration to avoid concurrent reconnect races.
  • When a new server-side connection is accepted, identify older server connections with the same remote service path and connection type.
  • Unregister all routes learned through each stale connection, then cancel its worker.
  • Preserve independently owned client-mode swbs-to connections.
  • Use BTreeSet::replace when updating an equal next hop so the new send proxy replaces the stale proxy retained by insert.
  • Add regression tests for stale server replacement, client-path preservation, and equal next-hop proxy refresh.

How did you verify/test it?

Automated validation:

cargo fmt --check --all
cargo test -p swbus-core
cargo clippy -p swbus-core --all-targets --all-features --no-deps -- --deny warnings
cargo test -p swbus-edge
  • swbus-core: 36 tests passed, 0 failed.
  • swbus-edge: 2 tests passed, 0 failed.
  • Strict Clippy completed with warnings denied.

Package and deployment validation:

  • Built dash-ha and dash-ha-dbgsym Debian packages.
  • Deployed both packages to dash-hadpu0 through dash-hadpu3 on two NVIDIA SN4280 SmartSwitches.
  • Verified all eight swbusd and hamgrd processes run the new payload.
  • Verified bidirectional SWBus connectivity with 3/3 successful pings in each direction.

The repeated physical NPU reboot reproduction test for sonic-net/sonic-buildimage#28481 remains to be run.

Any platform specific information?

No. The connection identity and routing changes are generic SWBus behavior. Physical deployment validation was performed on NVIDIA SN4280 SmartSwitches.

Documentation

No documentation update is required. This change corrects internal connection lifecycle and route replacement behavior without changing configuration or public interfaces.

Signed-off-by: BYGX-wcr <wcr@live.cn>
Copilot AI review requested due to automatic review settings July 20, 2026 21:01
@mssonicbld

Copy link
Copy Markdown

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

Copilot AI 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.

Pull request overview

This PR fixes a SWBus failure mode after an HA peer reboot where a half-open/stale accepted (server-mode) connection can remain routable and cause messages to be queued locally but never delivered. The change ensures stale peer connections are replaced on reconnect and that equal next-hop identities refresh their stored send proxy so routing uses the latest live connection.

Changes:

  • Replace older accepted server-mode connections for the same logical peer (by remote service path + connection type), unregistering stale routes and canceling the stale worker.
  • Refresh the stored proxy for an equal next-hop identity by using BTreeSet::replace rather than insert in route updates.
  • Add regression tests covering stale server replacement, preservation of independently owned client-mode connections, and proxy refresh for equal next-hops.

Reviewed changes

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

File Description
crates/swbus-core/src/mux/multiplexer.rs Refresh equal next-hop proxies via BTreeSet::replace and add a regression test ensuring the new proxy is used for routing.
crates/swbus-core/src/mux/conn.rs Add a synchronous cancel() used by connection replacement to stop the worker after route cleanup.
crates/swbus-core/src/mux/conn_store.rs Serialize connection replacement/registration, remove stale server-mode connections for the same peer, and add tests for stale replacement + client-path preservation.

Comment on lines 89 to +92
pub fn conn_established(&self, conn: SwbusConn) {
// A single critical section prevents two reconnects from each preserving the other as stale.
let _guard = self.connection_update_lock.lock().unwrap();
self.replace_stale_server_connections(conn.info());
@vivekrnv

Copy link
Copy Markdown
Contributor

LGTM


pub fn conn_established(&self, conn: SwbusConn) {
// A single critical section prevents two reconnects from each preserving the other as stale.
let _guard = self.connection_update_lock.lock().unwrap();

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.

Just to confirm, locking is only during connection create and delete.

For sending any data on a live connection, this path is not hit right.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes

@vivekrnv
vivekrnv merged commit 1ec418c into sonic-net:master Jul 22, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: [HA] SWBus retains stale peer connection after NPU reboot, blocking HA activation

5 participants