Skip to content

Add state duration to DDM FSM#689

Open
taspelund wants to merge 4 commits intomainfrom
trey/ddm-track-session-duration
Open

Add state duration to DDM FSM#689
taspelund wants to merge 4 commits intomainfrom
trey/ddm-track-session-duration

Conversation

@taspelund
Copy link
Copy Markdown
Contributor

@taspelund taspelund commented Mar 30, 2026

At its heart, this is a re-implementation of #180 which has been updated for the modern codebase and offers some cleanup in addition to timestamps.

First and foremost, this PR adds duration tracking for DDM FSM states. It does so by updating the FSM state enum variants to hold a std::time::Instant representing the timestamp when the FSM entered that state, and calculating a Duration using .elapsed() when the FSM state is queried (i.e. when ddmadm get-peers is called).

Part of this work was to cleanup the implementation of peer tracking: namely getting rid of the Db.peers table and instead tracking a peer in each FSM. Since the FSMs are instantiated per interface, this naturally gives us the interface-to-peer mapping structure so we don't actually need to maintain a separate table for the peers. Instead, we update/query the peers directly from the FSMs.

There are also a couple quality of life improvements: putting the state duration in a separate column and sorting the output of ddmadm get-peers.

Fixes: #54

Db.peers was only used as a cache for reporting peers to ddm-api clients
calling GET /peers, and the contents of the cache were a bit misleading.
For example, there is no such thing as a peer state in DDM. DDM FSMs
have states, but they are instantiated per interface not per peer. Not
only does the state reported by GET /peers not actually map to a peer,
but it doesn't even directly map to the FSM of the peer's interface.
Instead, that state was populated by manual db updates scattered
throughout the FSM implementation. This removes Db.peers and introduces
a new shared InterfaceState struct that consolidates peer/FSM info for a
given interface. GET /peers now reads from each InterfaceState and
passes along any peers it finds along with interface state.

Also fixes a pre-existing bug in oxstats where interface names
were always empty due to reading from a stale SmContext clone.
After adding PeerIdentity, the peer_address field of SessionStats is now
redundant (and also isn't a stat) so this removes it. The peer address
is tracked in PeerIdentity, so we can just rely on that field behind a
single mutex instead of locking/juggling both stats and identity.
Also adds a couple helper methods for transitioning FSM state and
updating the peer state.
@taspelund taspelund requested a review from rcgoodfellow March 30, 2026 15:58
@taspelund taspelund self-assigned this Mar 30, 2026
@taspelund taspelund added ddm Delay Driven Multipath rust Pull requests that update rust code labels Mar 30, 2026
@taspelund
Copy link
Copy Markdown
Contributor Author

I've manually tested this in a4x2 and proven that everything still works as expected. I've also manually verified that ddmadm expire-peer still works as expected as well.

The open question that I still have here: is PeerStatus::Expired worth keeping or should I remove it?
We do not maintain state for Expired peers (setting the Option to None when peer expires) and right now it's only really referenced in a From impl. I think we can safely remove it, but I didn't want to yank it out without discussion in case there were plans for it.

@taspelund
Copy link
Copy Markdown
Contributor Author

One other thing: I am also happy to add an FSM history buffer for DDM that mirrors what we have in BGP, especially if we don't believe that this PR fully addresses the visibility issue described in #54

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ddm Delay Driven Multipath rust Pull requests that update rust code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ddm: track peer establishment time

1 participant