Skip to content

Commit

Permalink
Merge pull request #4 from bgpkit/bgp-elem
Browse files Browse the repository at this point in the history
Add `BgpElem` to crate
  • Loading branch information
digizeph authored Nov 24, 2021
2 parents 2101c91 + 69fb5df commit 96f6e06
Show file tree
Hide file tree
Showing 12 changed files with 289 additions and 112 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/target
Cargo.lock
.idea
.DS_Store
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "bgp-models"
version = "0.3.5"
version = "0.4.0"
edition = "2018"
authors = ["Mingwei Zhang <mingwei@bgpkit.com>"]
readme = "README.md"
Expand Down
101 changes: 99 additions & 2 deletions src/bgp/attributes.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! BGP attribute structs
use std::fmt::{Display, Formatter};
use std::net::IpAddr;
use itertools::Itertools;
use crate::network::*;

/// The high-order bit (bit 0) of the Attribute Flags octet is the
Expand Down Expand Up @@ -173,7 +175,6 @@ impl AsPath {
self.segments.iter().map(AsPathSegment::count_asns).sum()
}


/// Construct AsPath from AS_PATH and AS4_PATH
///
/// https://datatracker.ietf.org/doc/html/rfc6793#section-4.2.3
Expand Down Expand Up @@ -326,6 +327,88 @@ impl MpUnreachableNlri {
}
}

///////////////////
// DISPLAY IMPLS //
///////////////////

impl Display for Origin {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let s = match self {
Origin::IGP => {"IGP"}
Origin::EGP => {"EGP"}
Origin::INCOMPLETE => {"INCOMPLETE"}
};
write!(f, "{}", s)
}
}

impl Display for AtomicAggregate {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", match self {
AtomicAggregate::NAG => {"NAG"}
AtomicAggregate::AG => {"AG"}
})
}
}

const NOEXPORT: &str ="no-export";

impl Display for Community {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", match self {
Community::NoExport => {
"no-export".to_string()
}
Community::NoAdvertise => {
"no-advertise".to_string()
}
Community::NoExportSubConfed => {
"no-export-sub-confed".to_string()
}
Community::Custom(asn, value) => {
format!("{}:{}", asn, value)
}
}
)
}
}

impl Display for NextHopAddress {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}",
match self {
NextHopAddress::Ipv4(v) => {v.to_string()}
NextHopAddress::Ipv6(v) => {v.to_string()}
NextHopAddress::Ipv6LinkLocal(v1, _v2) => {v1.to_string()}
}
)
}
}

impl Display for AsPath {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
write!(f, "{}",
self
.segments()
.iter()
.map(|seg| match seg {
AsPathSegment::AsSequence(v) | AsPathSegment::ConfedSequence(v) => v
.iter()
.join(" "),
AsPathSegment::AsSet(v) | AsPathSegment::ConfedSet(v) => {
format!(
"{{{}}}",
v.iter()
.join(",")
)
}
})
.join(" ")
)
}
}



#[cfg(test)]
mod tests {
Expand Down Expand Up @@ -364,4 +447,18 @@ mod tests {
assert!(origins.is_some());
assert_eq!(origins.unwrap(), vec![7,8]);
}
}

#[test]
fn test_aspath_display() {
let aspath = AsPath{
segments: vec![AsPathSegment::AsSequence([1,2,3,5].to_vec())]
};
let mut paths = vec![];
for _ in 0..1000000{
paths.push(aspath.clone());
}
for p in paths{
p.to_string();
}
}
}
102 changes: 0 additions & 102 deletions src/bgp/display.rs

This file was deleted.

131 changes: 131 additions & 0 deletions src/bgp/elem.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
use std::fmt::{Display, Formatter};
use std::net::IpAddr;
use std::str::FromStr;
use itertools::Itertools;
use crate::bgp::attributes::{AsPath, AtomicAggregate, Community, Origin};
use crate::network::{Asn, NetworkPrefix};

/// Element type.
///
/// - ANNOUNCE: announcement/reachable prefix
/// - WITHDRAW: withdrawn/unreachable prefix
#[derive(Debug, Clone, Copy)]
pub enum ElemType {
ANNOUNCE,
WITHDRAW,
}

/// BgpElem represents per-prefix BGP element.
///
/// The information is for per announced/withdrawn prefix.
///
/// Note: it consumes more memory to construct BGP elements due to duplicate information
/// shared between multiple elements of one MRT record.
#[derive(Debug, Clone)]
pub struct BgpElem {
pub timestamp: f64,
pub elem_type: ElemType,
pub peer_ip: IpAddr,
pub peer_asn: Asn,
pub prefix: NetworkPrefix,
pub next_hop: Option<IpAddr>,
pub as_path: Option<AsPath>,
pub origin_asns: Option<Vec<Asn>>,
pub origin: Option<Origin>,
pub local_pref: Option<u32>,
pub med: Option<u32>,
pub communities: Option<Vec<Community>>,
pub atomic: Option<AtomicAggregate>,
pub aggr_asn: Option<Asn>,
pub aggr_ip: Option<IpAddr>,
}

impl Default for BgpElem {
fn default() -> Self {
BgpElem {
timestamp: 0.0,
elem_type: ElemType::ANNOUNCE,
peer_ip: IpAddr::from_str("0.0.0.0").unwrap(),
peer_asn: 0,
prefix: NetworkPrefix::from_str("0.0.0.0/0").unwrap(),
next_hop: None,
as_path: None,
origin_asns: None,
origin: None,
local_pref: None,
med: None,
communities: None,
atomic: None,
aggr_asn: None,
aggr_ip: None
}
}
}

#[inline(always)]
pub fn option_to_string<T>(o: &Option<T>) -> String
where
T: Display,
{
if let Some(v) = o {
v.to_string()
} else {
String::new()
}
}

#[inline(always)]
pub fn option_to_string_communities(o: &Option<Vec<Community>>) -> String {
if let Some(v) = o {
v.iter()
.join(" ")
} else {
String::new()
}
}

impl Display for BgpElem {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let t = match self.elem_type {
ElemType::ANNOUNCE => "A",
ElemType::WITHDRAW => "W",
};
let format = format!(
"{}|{}|{}|{}|{}|{}|{}|{}|{}|{}|{}|{}|{}|{}",
t, &self.timestamp,
&self.peer_ip,
&self.peer_asn,
&self.prefix,
option_to_string(&self.as_path),
option_to_string(&self.origin),
option_to_string(&self.next_hop),
option_to_string(&self.local_pref),
option_to_string(&self.med),
option_to_string_communities(&self.communities),
option_to_string(&self.atomic),
option_to_string(&self.aggr_asn),
option_to_string(&self.aggr_ip),
);
write!(f, "{}", format)
}
}

#[cfg(test)]
mod tests {
use std::str::FromStr;
use std::default::Default;
use super::*;

#[test]
fn test_default() {
let elem = BgpElem{
timestamp: 0.0,
elem_type: ElemType::ANNOUNCE,
peer_ip: IpAddr::from_str("192.168.1.1").unwrap(),
peer_asn: 0,
prefix: NetworkPrefix::from_str("8.8.8.0/24").unwrap(),
..Default::default()
};
dbg!(elem);
}
}
7 changes: 5 additions & 2 deletions src/bgp.rs → src/bgp/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
//! BGP messages and relevant structs.
pub mod attributes;
pub mod display;
pub mod elem;

pub use crate::bgp::attributes::*;
pub use crate::bgp::elem::*;

use std::net::Ipv4Addr;
use crate::bgp::attributes::Attributes;
use crate::network::*;

#[derive(Debug, Primitive, Copy, Clone)]
Expand Down Expand Up @@ -77,3 +79,4 @@ pub struct BgpNotificationMessage {
pub struct BgpKeepAliveMessage {

}

Loading

0 comments on commit 96f6e06

Please sign in to comment.