-
Notifications
You must be signed in to change notification settings - Fork 0
Switch to existing collections to heapless, hide other non-embedded f… #76
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
ada2553
a36af2f
7d3da6e
540899d
d6cca3a
951b02d
073ee80
34e1a05
97eca58
cea2204
5a804cf
bceae77
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,5 +1,12 @@ | ||||||||||||||||||||||
| use crate::protocol::sd::RebootFlag; | ||||||||||||||||||||||
| use std::{collections::HashMap, net::SocketAddr}; | ||||||||||||||||||||||
| use heapless::index_map::FnvIndexMap; | ||||||||||||||||||||||
| use std::net::SocketAddr; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| /// Max number of distinct `(sender, transport, service, instance)` tuples tracked | ||||||||||||||||||||||
| /// for reboot detection. Must be a power of two (heapless `FnvIndexMap` | ||||||||||||||||||||||
| /// requirement). Sized for a small fleet of peers each offering several | ||||||||||||||||||||||
| /// services; bare-metal builds with more peers may need to edit this constant. | ||||||||||||||||||||||
| const SESSION_CAP: usize = 64; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| /// Distinguishes multicast vs unicast transport for per-sender session tracking. | ||||||||||||||||||||||
| /// The AUTOSAR spec requires separate session ID tracking per transport. | ||||||||||||||||||||||
|
|
@@ -45,14 +52,57 @@ pub enum SessionVerdict { | |||||||||||||||||||||
| /// Tracking per service instance (rather than per sender) avoids false | ||||||||||||||||||||||
| /// positives when a sensor interleaves SD offers for multiple services | ||||||||||||||||||||||
| /// with independent session counters on the same source address. | ||||||||||||||||||||||
| #[derive(Debug, Default)] | ||||||||||||||||||||||
| /// | ||||||||||||||||||||||
| /// Capacity is bounded at compile time by [`SESSION_CAP`]. | ||||||||||||||||||||||
| /// When the map is full, new sender entries are dropped with a `warn!` log | ||||||||||||||||||||||
| /// and reboot detection for those senders is disabled. | ||||||||||||||||||||||
| /// | ||||||||||||||||||||||
| /// # Security posture | ||||||||||||||||||||||
| /// | ||||||||||||||||||||||
| /// The backing map uses FNV hashing rather than the DoS-resistant hasher used | ||||||||||||||||||||||
| /// by `std::collections::HashMap`. For SOME/IP on isolated automotive or | ||||||||||||||||||||||
| /// sensor networks this is not a concern. Deployments where `SessionKey` | ||||||||||||||||||||||
| /// inputs (notably `SocketAddr`) are adversary-controlled should be aware | ||||||||||||||||||||||
| /// that an attacker can craft keys to force collisions and degrade lookup | ||||||||||||||||||||||
| /// cost; the blast radius is bounded by [`SESSION_CAP`]. | ||||||||||||||||||||||
| #[derive(Debug)] | ||||||||||||||||||||||
| pub struct SessionTracker { | ||||||||||||||||||||||
| state: HashMap<SessionKey, SessionState>, | ||||||||||||||||||||||
| state: FnvIndexMap<SessionKey, SessionState, SESSION_CAP>, | ||||||||||||||||||||||
| /// Set after the first saturation warning. Prevents the saturated-map | ||||||||||||||||||||||
| /// log from firing on every `check()` for every new key once capacity | ||||||||||||||||||||||
| /// is reached — which would spam the log at the packet rate. | ||||||||||||||||||||||
| saturation_warned: bool, | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| impl Default for SessionTracker { | ||||||||||||||||||||||
| fn default() -> Self { | ||||||||||||||||||||||
| Self { | ||||||||||||||||||||||
| state: FnvIndexMap::new(), | ||||||||||||||||||||||
| saturation_warned: false, | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| impl SessionTracker { | ||||||||||||||||||||||
| /// Check the session ID and reboot flag for a specific service instance | ||||||||||||||||||||||
| /// and return a verdict. Always updates the stored state after the check. | ||||||||||||||||||||||
| /// and return a verdict. | ||||||||||||||||||||||
| /// | ||||||||||||||||||||||
| /// On the normal (non-saturated) path, the stored state is updated | ||||||||||||||||||||||
| /// after the check so subsequent calls see the latest session id and | ||||||||||||||||||||||
| /// reboot flag for the key. | ||||||||||||||||||||||
| /// | ||||||||||||||||||||||
| /// # Capacity behavior | ||||||||||||||||||||||
| /// | ||||||||||||||||||||||
| /// The tracker is backed by a `heapless::FnvIndexMap` bounded by | ||||||||||||||||||||||
| /// [`SESSION_CAP`]. If the map is already full and the incoming key | ||||||||||||||||||||||
| /// is new, the insert fails and stored state is **not** updated for | ||||||||||||||||||||||
| /// that key — subsequent `check()` calls with the same new key will | ||||||||||||||||||||||
| /// continue to return [`SessionVerdict::Initial`] until an existing | ||||||||||||||||||||||
| /// key is evicted or capacity is raised. A single `warn!` fires the | ||||||||||||||||||||||
| /// first time saturation is hit (further saturation drops are | ||||||||||||||||||||||
| /// suppressed to avoid log spam at the packet rate). For existing | ||||||||||||||||||||||
| /// keys under saturation the update still succeeds, because | ||||||||||||||||||||||
|
Comment on lines
+100
to
+104
|
||||||||||||||||||||||
| /// continue to return [`SessionVerdict::Initial`] until an existing | |
| /// key is evicted or capacity is raised. A single `warn!` fires the | |
| /// first time saturation is hit (further saturation drops are | |
| /// suppressed to avoid log spam at the packet rate). For existing | |
| /// keys under saturation the update still succeeds, because | |
| /// continue to return [`SessionVerdict::Initial`] unless capacity is | |
| /// increased or the tracker state is explicitly reset/cleared. A single | |
| /// `warn!` fires the first time saturation is hit (further saturation | |
| /// drops are suppressed to avoid log spam at the packet rate). For | |
| /// existing keys under saturation the update still succeeds, because |
Uh oh!
There was an error while loading. Please reload this page.