Skip to content

Commit

Permalink
bgp: introduce deterministic attribute set indexes for testing
Browse files Browse the repository at this point in the history
By default, attribute sets are assigned indexes in sequential
order. The problem with this approach is that those indexes are
non-deterministic, whereas the data-driven testing framework requires
deterministic operational data.

To address this issue, introduce the "deterministic" feature. This
feature calculates attribute set indexes based on a hash of their
contents, ensuring determinism in testing scenarios. Since the hash
values and attribute indexes use `u64`, the likelihood of collisions
is virtually non-existent, especially considering that test topologies
are normally small and simple. In normal operation, sequential indexes
will continue to be used.

The topology tests data have been update accordingly.

Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
  • Loading branch information
rwestphal committed Apr 24, 2024
1 parent a271a01 commit 864e9f3
Show file tree
Hide file tree
Showing 31 changed files with 604 additions and 759 deletions.
3 changes: 2 additions & 1 deletion holo-bgp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ holo-yang = { path = "../holo-yang" }
[dev-dependencies]
criterion.workspace = true

holo-bgp = { path = ".", features = ["testing"] }
holo-bgp = { path = ".", features = ["testing", "deterministic"] }
holo-protocol = { path = "../holo-protocol", features = ["testing"] }
holo-utils = { path = "../holo-utils", features = ["testing"] }

Expand All @@ -46,6 +46,7 @@ workspace = true
[features]
default = []
testing = []
deterministic = []

[[bench]]
name = "msg_encoding"
Expand Down
14 changes: 7 additions & 7 deletions holo-bgp/src/packet/attribute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ pub struct Attrs {
pub unknown: Option<Box<[UnknownAttr]>>,
}

#[derive(Clone, Debug, Default, Eq, Ord, PartialEq, PartialOrd)]
#[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[skip_serializing_none]
#[derive(Deserialize, Serialize)]
pub struct BaseAttrs {
Expand All @@ -60,27 +60,27 @@ pub struct BaseAttrs {
pub cluster_list: Option<ClusterList>,
}

#[derive(Clone, Debug, Default, Eq, Ord, PartialEq, PartialOrd)]
#[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[derive(Deserialize, Serialize)]
pub struct AsPath {
pub segments: VecDeque<AsPathSegment>,
}

#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[derive(Deserialize, Serialize)]
pub struct AsPathSegment {
pub seg_type: AsPathSegmentType,
pub members: VecDeque<u32>,
}

#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[derive(Deserialize, Serialize)]
pub struct Aggregator {
pub asn: u32,
pub identifier: Ipv4Addr,
}

#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[derive(Deserialize, Serialize)]
pub struct ClusterList(pub BTreeSet<Ipv4Addr>);

Expand All @@ -90,12 +90,12 @@ pub type ExtComm = holo_utils::bgp::ExtComm;
pub type Extv6Comm = holo_utils::bgp::Extv6Comm;
pub type LargeComm = holo_utils::bgp::LargeComm;

#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[derive(Deserialize, Serialize)]
pub struct CommList<T: CommType>(pub BTreeSet<T>);

pub trait CommType:
Clone + std::fmt::Debug + Eq + Ord + PartialEq + PartialOrd
Clone + std::fmt::Debug + Eq + std::hash::Hash + Ord + PartialEq + PartialOrd
{
const TYPE: AttrType;
const LENGTH: usize;
Expand Down
2 changes: 1 addition & 1 deletion holo-bgp/src/packet/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ pub enum AttrType {
// BGP Origin.
pub type Origin = holo_utils::bgp::Origin;

#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[derive(FromPrimitive, ToPrimitive)]
#[derive(Deserialize, Serialize)]
pub enum AsPathSegmentType {
Expand Down
19 changes: 16 additions & 3 deletions holo-bgp/src/rib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -570,15 +570,28 @@ impl AttrSetsCxt {

impl<T> AttrSets<T>
where
T: Clone + Eq + Ord + PartialEq + PartialOrd,
T: Clone + Eq + std::hash::Hash + Ord + PartialEq + PartialOrd,
{
fn get(&mut self, attr: &T) -> Arc<AttrSet<T>> {
if let Some(attr_set) = self.tree.get(attr) {
Arc::clone(attr_set)
} else {
self.next_index += 1;
let index = {
#[cfg(not(feature = "deterministic"))]
{
self.next_index += 1;
self.next_index
}
#[cfg(feature = "deterministic")]
{
use std::hash::{DefaultHasher, Hasher};
let mut hasher = DefaultHasher::new();
attr.hash(&mut hasher);
hasher.finish()
}
};
let attr_set = Arc::new(AttrSet {
index: self.next_index,
index,
value: attr.clone(),
});
self.tree.insert(attr.clone(), Arc::clone(&attr_set));
Expand Down
29 changes: 13 additions & 16 deletions holo-bgp/tests/conformance/topologies/topo1-1/rt1/events.jsonl
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,27 @@
{"Protocol":{"PolicyResult":{"Redistribute":{"afi_safi":"Ipv4Unicast","prefix":"10.0.1.0/24","result":"Reject"}}}}
{"Protocol":{"PolicyResult":{"Redistribute":{"afi_safi":"Ipv4Unicast","prefix":"10.0.2.0/24","result":"Reject"}}}}
{"Protocol":{"TriggerDecisionProcess":null}}
{"Protocol":{"TcpAccept":{"conn_info":{"local_addr":"10.0.1.1","local_port":179,"remote_addr":"10.0.1.2","remote_port":39828}}}}
{"Protocol":{"NbrTimer":{"nbr_addr":"10.0.2.3","timer":"AutoStart"}}}
{"Protocol":{"TcpAccept":{"conn_info":{"local_addr":"10.0.1.1","local_port":179,"remote_addr":"10.0.1.2","remote_port":39674}}}}
{"Protocol":{"NbrTimer":{"nbr_addr":"10.0.1.2","timer":"AutoStart"}}}
{"Protocol":{"TcpConnect":{"conn_info":{"local_addr":"10.0.1.1","local_port":40492,"remote_addr":"10.0.1.2","remote_port":179}}}}
{"Protocol":{"TcpConnect":{"conn_info":{"local_addr":"10.0.1.1","local_port":51452,"remote_addr":"10.0.1.2","remote_port":179}}}}
{"Protocol":{"NbrTimer":{"nbr_addr":"10.0.2.3","timer":"AutoStart"}}}
{"Protocol":{"NbrRx":{"nbr_addr":"10.0.1.2","msg":{"Err":{"TcpConnClosed":"10.0.1.2"}}}}}
{"Protocol":{"TriggerDecisionProcess":null}}
{"Protocol":{"TcpAccept":{"conn_info":{"local_addr":"10.0.1.1","local_port":179,"remote_addr":"10.0.1.2","remote_port":39836}}}}
{"Protocol":{"TcpAccept":{"conn_info":{"local_addr":"10.0.2.1","local_port":179,"remote_addr":"10.0.2.3","remote_port":43240}}}}
{"Protocol":{"NbrRx":{"nbr_addr":"10.0.2.3","msg":{"Err":{"TcpConnClosed":"10.0.2.3"}}}}}
{"Protocol":{"TriggerDecisionProcess":null}}
{"Protocol":{"TcpAccept":{"conn_info":{"local_addr":"10.0.1.1","local_port":179,"remote_addr":"10.0.1.2","remote_port":39684}}}}
{"Protocol":{"NbrRx":{"nbr_addr":"10.0.1.2","msg":{"Ok":{"Open":{"version":4,"my_as":65101,"holdtime":90,"identifier":"2.2.2.2","capabilities":[{"MultiProtocol":{"afi":"Ipv4","safi":"Unicast"}},{"FourOctetAsNumber":{"asn":65101}},"RouteRefresh"]}}}}}}
{"Protocol":{"NbrRx":{"nbr_addr":"10.0.1.2","msg":{"Ok":{"Keepalive":{}}}}}}
{"Protocol":{"NbrRx":{"nbr_addr":"10.0.1.2","msg":{"Ok":{"Update":{"reach":{"prefixes":["2.2.2.2/32"],"nexthop":"10.0.1.2"},"attrs":{"base":{"origin":"Incomplete","as_path":{"segments":[{"seg_type":"Sequence","members":[65101]}]}}}}}}}}}
{"Protocol":{"PolicyResult":{"Neighbor":{"policy_type":"Export","nbr_addr":"10.0.1.2","afi_safi":"Ipv4Unicast","routes":[["1.1.1.1/32",{"Accept":{"origin":{"Protocol":"direct"},"route_type":"Internal","attrs":{"base":{"origin":"Incomplete","as_path":{"segments":[]}}}}}]]}}}}
{"Protocol":{"NbrRx":{"nbr_addr":"10.0.1.2","msg":{"Ok":{"Update":{"reach":{"prefixes":["2.2.2.2/32"],"nexthop":"10.0.1.2"},"attrs":{"base":{"origin":"Incomplete","as_path":{"segments":[{"seg_type":"Sequence","members":[65101]}]}}}}}}}}}
{"Protocol":{"PolicyResult":{"Neighbor":{"policy_type":"Import","nbr_addr":"10.0.1.2","afi_safi":"Ipv4Unicast","routes":[["2.2.2.2/32",{"Accept":{"origin":{"Neighbor":{"identifier":"2.2.2.2","remote_addr":"10.0.1.2"}},"route_type":"External","attrs":{"base":{"origin":"Incomplete","as_path":{"segments":[{"seg_type":"Sequence","members":[65101]}]},"nexthop":"10.0.1.2"}}}}]]}}}}
{"Ibus":{"NexthopTrack":"10.0.1.2"}}
{"Ibus":{"NexthopUpd":{"addr":"10.0.1.2","metric":0}}}
{"Protocol":{"TriggerDecisionProcess":null}}
{"Ibus":{"RouteIpAdd":{"protocol":"bgp","prefix":"2.2.2.2/32","distance":20,"metric":0,"tag":null,"nexthops":[{"Recursive":{"addr":"10.0.1.2","labels":[],"resolved":[]}}]}}}
{"Ibus":{"RouteRedistributeAdd":{"protocol":"bgp","prefix":"2.2.2.2/32","distance":20,"metric":0,"tag":null,"nexthops":[{"Recursive":{"addr":"10.0.1.2","labels":[],"resolved":[{"Address":{"ifindex":3,"addr":"10.0.1.2","labels":[]}}]}}]}}}
{"Protocol":{"TcpConnect":{"conn_info":{"local_addr":"10.0.2.1","local_port":52856,"remote_addr":"10.0.2.3","remote_port":179}}}}
{"Protocol":{"NbrRx":{"nbr_addr":"10.0.2.3","msg":{"Err":{"TcpConnClosed":"10.0.2.3"}}}}}
{"Protocol":{"TriggerDecisionProcess":null}}
{"Protocol":{"PolicyResult":{"Neighbor":{"policy_type":"Export","nbr_addr":"10.0.1.2","afi_safi":"Ipv4Unicast","routes":[["1.1.1.1/32",{"Accept":{"origin":{"Protocol":"direct"},"route_type":"Internal","attrs":{"base":{"origin":"Incomplete","as_path":{"segments":[]}}}}}]]}}}}
{"Protocol":{"TcpAccept":{"conn_info":{"local_addr":"10.0.2.1","local_port":179,"remote_addr":"10.0.2.3","remote_port":54870}}}}
{"Protocol":{"TcpAccept":{"conn_info":{"local_addr":"10.0.2.1","local_port":179,"remote_addr":"10.0.2.3","remote_port":43250}}}}
{"Protocol":{"NbrRx":{"nbr_addr":"10.0.2.3","msg":{"Ok":{"Open":{"version":4,"my_as":65000,"holdtime":90,"identifier":"3.3.3.3","capabilities":[{"MultiProtocol":{"afi":"Ipv4","safi":"Unicast"}},{"FourOctetAsNumber":{"asn":65000}},"RouteRefresh"]}}}}}}
{"Protocol":{"NbrRx":{"nbr_addr":"10.0.2.3","msg":{"Ok":{"Keepalive":{}}}}}}
{"Protocol":{"PolicyResult":{"Neighbor":{"policy_type":"Export","nbr_addr":"10.0.2.3","afi_safi":"Ipv4Unicast","routes":[["1.1.1.1/32",{"Accept":{"origin":{"Protocol":"direct"},"route_type":"Internal","attrs":{"base":{"origin":"Incomplete","as_path":{"segments":[]}}}}}],["2.2.2.2/32",{"Accept":{"origin":{"Neighbor":{"identifier":"2.2.2.2","remote_addr":"10.0.1.2"}},"route_type":"External","attrs":{"base":{"origin":"Incomplete","as_path":{"segments":[{"seg_type":"Sequence","members":[65101]}]},"nexthop":"10.0.1.2"}}}}]]}}}}
Expand All @@ -42,8 +41,8 @@
{"Ibus":{"NexthopTrack":"10.0.2.3"}}
{"Ibus":{"NexthopUpd":{"addr":"10.0.2.3","metric":0}}}
{"Protocol":{"TriggerDecisionProcess":null}}
{"Protocol":{"PolicyResult":{"Neighbor":{"policy_type":"Export","nbr_addr":"10.0.1.2","afi_safi":"Ipv4Unicast","routes":[["3.3.3.3/32",{"Accept":{"origin":{"Neighbor":{"identifier":"3.3.3.3","remote_addr":"10.0.2.3"}},"route_type":"External","attrs":{"base":{"origin":"Incomplete","as_path":{"segments":[{"seg_type":"Sequence","members":[65000]}]},"nexthop":"10.0.2.3"}}}}]]}}}}
{"Ibus":{"RouteIpAdd":{"protocol":"bgp","prefix":"3.3.3.3/32","distance":20,"metric":0,"tag":null,"nexthops":[{"Recursive":{"addr":"10.0.2.3","labels":[],"resolved":[]}}]}}}
{"Protocol":{"PolicyResult":{"Neighbor":{"policy_type":"Export","nbr_addr":"10.0.1.2","afi_safi":"Ipv4Unicast","routes":[["3.3.3.3/32",{"Accept":{"origin":{"Neighbor":{"identifier":"3.3.3.3","remote_addr":"10.0.2.3"}},"route_type":"External","attrs":{"base":{"origin":"Incomplete","as_path":{"segments":[{"seg_type":"Sequence","members":[65000]}]},"nexthop":"10.0.2.3"}}}}]]}}}}
{"Ibus":{"RouteRedistributeAdd":{"protocol":"bgp","prefix":"3.3.3.3/32","distance":20,"metric":0,"tag":null,"nexthops":[{"Recursive":{"addr":"10.0.2.3","labels":[],"resolved":[{"Address":{"ifindex":5,"addr":"10.0.2.3","labels":[]}}]}}]}}}
{"Protocol":{"NbrRx":{"nbr_addr":"10.0.1.2","msg":{"Ok":{"Update":{"reach":{"prefixes":["4.4.4.4/32"],"nexthop":"10.0.1.2"},"attrs":{"base":{"origin":"Incomplete","as_path":{"segments":[{"seg_type":"Sequence","members":[65101,65000]}]}}}}}}}}}
{"Protocol":{"PolicyResult":{"Neighbor":{"policy_type":"Import","nbr_addr":"10.0.1.2","afi_safi":"Ipv4Unicast","routes":[["4.4.4.4/32",{"Accept":{"origin":{"Neighbor":{"identifier":"2.2.2.2","remote_addr":"10.0.1.2"}},"route_type":"External","attrs":{"base":{"origin":"Incomplete","as_path":{"segments":[{"seg_type":"Sequence","members":[65101,65000]}]},"nexthop":"10.0.1.2"}}}}]]}}}}
Expand All @@ -52,13 +51,11 @@
{"Ibus":{"RouteRedistributeAdd":{"protocol":"bgp","prefix":"4.4.4.4/32","distance":20,"metric":0,"tag":null,"nexthops":[{"Recursive":{"addr":"10.0.1.2","labels":[],"resolved":[{"Address":{"ifindex":3,"addr":"10.0.1.2","labels":[]}}]}}]}}}
{"Protocol":{"NbrRx":{"nbr_addr":"10.0.2.3","msg":{"Ok":{"Update":{"reach":{"prefixes":["4.4.4.4/32"],"nexthop":"10.0.2.3"},"attrs":{"base":{"origin":"Incomplete","as_path":{"segments":[{"seg_type":"Sequence","members":[65000]}]}}}}}}}}}
{"Protocol":{"PolicyResult":{"Neighbor":{"policy_type":"Import","nbr_addr":"10.0.2.3","afi_safi":"Ipv4Unicast","routes":[["4.4.4.4/32",{"Accept":{"origin":{"Neighbor":{"identifier":"3.3.3.3","remote_addr":"10.0.2.3"}},"route_type":"External","attrs":{"base":{"origin":"Incomplete","as_path":{"segments":[{"seg_type":"Sequence","members":[65000]}]},"nexthop":"10.0.2.3"}}}}]]}}}}
{"Protocol":{"TriggerDecisionProcess":null}}
{"Ibus":{"RouteIpAdd":{"protocol":"bgp","prefix":"4.4.4.4/32","distance":20,"metric":0,"tag":null,"nexthops":[{"Recursive":{"addr":"10.0.2.3","labels":[],"resolved":[]}}]}}}
{"Protocol":{"PolicyResult":{"Neighbor":{"policy_type":"Export","nbr_addr":"10.0.1.2","afi_safi":"Ipv4Unicast","routes":[["4.4.4.4/32",{"Accept":{"origin":{"Neighbor":{"identifier":"3.3.3.3","remote_addr":"10.0.2.3"}},"route_type":"External","attrs":{"base":{"origin":"Incomplete","as_path":{"segments":[{"seg_type":"Sequence","members":[65000]}]},"nexthop":"10.0.2.3"}}}}]]}}}}
{"Ibus":{"RouteRedistributeAdd":{"protocol":"bgp","prefix":"4.4.4.4/32","distance":20,"metric":0,"tag":null,"nexthops":[{"Recursive":{"addr":"10.0.2.3","labels":[],"resolved":[{"Address":{"ifindex":5,"addr":"10.0.2.3","labels":[]}}]}}]}}}
{"Protocol":{"NbrRx":{"nbr_addr":"10.0.1.2","msg":{"Ok":{"Update":{"reach":{"prefixes":["3.3.3.3/32"],"nexthop":"10.0.1.2"},"attrs":{"base":{"origin":"Incomplete","as_path":{"segments":[{"seg_type":"Sequence","members":[65101,65000]}]}}}}}}}}}
{"Protocol":{"PolicyResult":{"Neighbor":{"policy_type":"Import","nbr_addr":"10.0.1.2","afi_safi":"Ipv4Unicast","routes":[["3.3.3.3/32",{"Accept":{"origin":{"Neighbor":{"identifier":"2.2.2.2","remote_addr":"10.0.1.2"}},"route_type":"External","attrs":{"base":{"origin":"Incomplete","as_path":{"segments":[{"seg_type":"Sequence","members":[65101,65000]}]},"nexthop":"10.0.1.2"}}}}]]}}}}
{"Protocol":{"TriggerDecisionProcess":null}}
{"Protocol":{"PolicyResult":{"Neighbor":{"policy_type":"Export","nbr_addr":"10.0.1.2","afi_safi":"Ipv4Unicast","routes":[["3.3.3.3/32",{"Accept":{"origin":{"Neighbor":{"identifier":"3.3.3.3","remote_addr":"10.0.2.3"}},"route_type":"External","attrs":{"base":{"origin":"Incomplete","as_path":{"segments":[{"seg_type":"Sequence","members":[65000]}]},"nexthop":"10.0.2.3"}}}}]]}}}}
{"Ibus":{"RouteIpAdd":{"protocol":"bgp","prefix":"4.4.4.4/32","distance":20,"metric":0,"tag":null,"nexthops":[{"Recursive":{"addr":"10.0.2.3","labels":[],"resolved":[]}}]}}}
{"Protocol":{"PolicyResult":{"Neighbor":{"policy_type":"Export","nbr_addr":"10.0.1.2","afi_safi":"Ipv4Unicast","routes":[["3.3.3.3/32",{"Accept":{"origin":{"Neighbor":{"identifier":"3.3.3.3","remote_addr":"10.0.2.3"}},"route_type":"External","attrs":{"base":{"origin":"Incomplete","as_path":{"segments":[{"seg_type":"Sequence","members":[65000]}]},"nexthop":"10.0.2.3"}}}}],["4.4.4.4/32",{"Accept":{"origin":{"Neighbor":{"identifier":"3.3.3.3","remote_addr":"10.0.2.3"}},"route_type":"External","attrs":{"base":{"origin":"Incomplete","as_path":{"segments":[{"seg_type":"Sequence","members":[65000]}]},"nexthop":"10.0.2.3"}}}}]]}}}}
{"Ibus":{"RouteRedistributeAdd":{"protocol":"bgp","prefix":"4.4.4.4/32","distance":20,"metric":0,"tag":null,"nexthops":[{"Recursive":{"addr":"10.0.2.3","labels":[],"resolved":[{"Address":{"ifindex":5,"addr":"10.0.2.3","labels":[]}}]}}]}}}
{"Protocol":{"NbrRx":{"nbr_addr":"10.0.1.2","msg":{"Ok":{"Keepalive":{}}}}}}
{"Protocol":{"NbrRx":{"nbr_addr":"10.0.2.3","msg":{"Ok":{"Keepalive":{}}}}}}

0 comments on commit 864e9f3

Please sign in to comment.