From 1d1fbdb1f23d3590cd0a22e7cfd47b616be0ff9d Mon Sep 17 00:00:00 2001 From: Luuk Hendriks Date: Wed, 9 Oct 2024 15:48:14 +0200 Subject: [PATCH] Introduce OwnedPathAttributes (#59) --- src/bgp/message/open.rs | 12 ++++---- src/bgp/message/update.rs | 16 +++++------ src/bgp/path_attributes.rs | 59 ++++++++++++++++++++++++++++++++++++++ src/bgp/path_selection.rs | 2 +- 4 files changed, 74 insertions(+), 15 deletions(-) diff --git a/src/bgp/message/open.rs b/src/bgp/message/open.rs index 6c993a4..43303c9 100644 --- a/src/bgp/message/open.rs +++ b/src/bgp/message/open.rs @@ -29,13 +29,13 @@ pub struct OpenMessage { /// ## Convenience methods /// /// * [`my_asn()`][`OpenMessage::my_asn`]: returns the 32bit ASN if present, -/// otherwise falls back to the conventional 16bit ASN (though represented as -/// the 32bit [`inetnum::asn::Asn`][`Asn`]); +/// otherwise falls back to the conventional 16bit ASN (though represented +/// as the 32bit [`inetnum::asn::Asn`][`Asn`]); /// * [`multiprotocol_ids()`][`OpenMessage::multiprotocol_ids`]: returns an -/// iterator over all the AFI/SAFI combinations listed as Capability in the -/// Optional Parameters. If this yields an empty iterator, one can assume the -/// default (IPv4/Unicast) can be used, but it is up to the user to handle as -/// such. +/// iterator over all the AFI/SAFI combinations listed as Capability in the +/// Optional Parameters. If this yields an empty iterator, one can assume +/// the default (IPv4/Unicast) can be used, but it is up to the user to +/// handle as such. // // 0 1 2 3 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 diff --git a/src/bgp/message/update.rs b/src/bgp/message/update.rs index fadabfe..79188ba 100644 --- a/src/bgp/message/update.rs +++ b/src/bgp/message/update.rs @@ -94,12 +94,12 @@ impl AsRef<[u8]> for UpdateMessage { /// To accommodate for these hassles, the following methods are provided: /// /// * [`nlris()`][`UpdateMessage::nlris`] and -/// [`withdrawals()`][`UpdateMessage::withdrawals`], -/// providing iterators over announced and withdrawn prefixes ; +/// [`withdrawals()`][`UpdateMessage::withdrawals`], +/// providing iterators over announced and withdrawn prefixes ; /// * [`next_hop()`][`UpdateMessage::next_hop`], returning the [`NextHop`] ; /// * [`all_communities()`][`UpdateMessage::all_communities`], returning an -/// optional `Vec` containing all conventional, Extended and Large -/// Communities, wrapped in the [`Community`] enum. +/// optional `Vec` containing all conventional, Extended and Large +/// Communities, wrapped in the [`Community`] enum. /// /// For the mandatory path attributes, we have: /// @@ -1154,12 +1154,12 @@ impl Default for PduParseInfo { /// and non AddPath enabled withdrawals, this struct holds booleans for all /// three sections where AddPath PathIds might or might not occur: /// -/// * the conventional IPv4 Unicast sections in the PDU, which are either -/// both AddPath enabled or not, and, +/// * the conventional IPv4 Unicast sections in the PDU, which are either +/// both AddPath enabled or not, and, /// /// * the MP_REACH and MP_UNREACH path attributes, which might carry NLRI for -/// different address families and (thus) might differ in being AddPath -/// enabled or not. +/// different address families and (thus) might differ in being AddPath +/// enabled or not. #[derive(Copy, Clone, Default, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[cfg_attr(feature = "serde", derive(serde::Serialize))] diff --git a/src/bgp/path_attributes.rs b/src/bgp/path_attributes.rs index 8cb3b45..8fc5113 100644 --- a/src/bgp/path_attributes.rs +++ b/src/bgp/path_attributes.rs @@ -99,6 +99,65 @@ pub trait AttributeHeader { } +//------------ OwnedPathAttributes ------------------------------------------- + + +#[derive(Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize))] +pub struct OwnedPathAttributes { + ppi: PduParseInfo, + raw: Vec +} + +impl OwnedPathAttributes { + pub fn new(ppi: PduParseInfo, raw: Vec) -> Self { + Self { ppi, raw } + } + + pub fn iter(&self) -> PathAttributes> { + let parser = Parser::from_ref(&self.raw); + PathAttributes::new(parser, self.ppi) + } + + pub fn pdu_parse_info(&self) -> PduParseInfo { + self.ppi + } + + pub fn into_vec(self) -> Vec { + self.raw + } + + pub fn get(&self) -> Option { + if let Some(attr_type) = A::attribute_type() { + self.iter().get(attr_type) + .and_then(|a| a.to_owned().ok()) + .and_then(|a| A::from_attribute(a)) + } else { + None + } + } +} + +impl<'a, O> From> for OwnedPathAttributes +where + O: AsRef<[u8]> +{ + fn from(value: PathAttributes<'a, O>) -> Self { + OwnedPathAttributes { + ppi: value.pdu_parse_info, + raw: value.parser.as_slice().to_owned() + } + } +} + +impl From<(PduParseInfo, Vec)> for OwnedPathAttributes { + fn from(value: (PduParseInfo, Vec)) -> Self { + Self::new(value.0, value.1) + } +} + + + //------------ PathAttributesBuilder ----------------------------------------- pub type AttributesMap = BTreeMap; diff --git a/src/bgp/path_selection.rs b/src/bgp/path_selection.rs index b254a4b..6639179 100644 --- a/src/bgp/path_selection.rs +++ b/src/bgp/path_selection.rs @@ -18,7 +18,7 @@ use super::{ /// Comparing two `OrdRoute`s, wrapping two routes with different sets of path /// attributes, might still yield 'equal'. Instead, consider comparing on the /// `PaMap` and/or `Tiebreakerinfo` directly (or [`fn inner`]). -#[derive(Copy, Clone, Debug, Hash)] +#[derive(Copy, Clone, Debug)] pub struct OrdRoute<'a, OS> { pa_map: &'a PaMap, tiebreakers: TiebreakerInfo,