Skip to content

Commit bbefe17

Browse files
authored
Merge pull request #58 from NLnetLabs/release-0.5.0-rc1
Released 2024-06-10. This release features a lot of changes, big and small. The list below is not exhaustive but tries to highlight and describe the bigger (and perhaps, more important) ones. Breaking changes * Several common basic types (e.g. `Asn` and `Prefix`) are moved out of _routecore_ to the new _inetnum_ crate. * Refactor of PathAttributes The introduction of `PaMap` and `RouteWorkshop` (see below) required refactoring of the `PathAttributes` enum and related types. Most significantly, an entire layer in the enum was removed, changing how one matches on variants. Furthermore some of the types in those variants slightly changed. * Overhaul of address family related code The types describing address families, and related traits to parse and compose NLRI of such families, have severely changed. This eliminates any possible ambiguity regarding the address family of announcements/withdrawals in UPDATE messages at compile time. * Supported address families are now explicitly and exhaustively enumerated in the `AfiSafiType` enum. As a SAFI by itself does not carry much meaning, the separate `SAFI` enum is removed. Almost all of the code now works based on the more descriptive `AfiSafiType`. * ADD-PATH is now supported on all supported address families, i.e. the `AfiSafiType` includes `~AddPath` variants for every single AFI+SAFI combination. * This now allows for e.g. efficient iterators over NLRI that are generic over the `AfiSafiType`. But, as a possible downside, this moves the task of determining what address family a set of NLRI holds to the caller in order to then use the correctly typed iterator. The less efficient, 'easier to use' iterators returning an enum instead of a distinct NLRI type are therefore still available. New * RouteWorkshop / PaMap This release introduces the `RouteWorkshop` to create UPDATE messages based on an NLRI and a set of attributes. For creation, inspection and manipulation of those attributes, the `PaMap` is introduced. These new types work in conjunction with the existing `UpdateBuilder`. * BGP FSM (absorbed from _rotonda-fsm_) _routecore_ now contains the code to enable for actual BGP sessions, i.e. the BGP FSM and related machinery. By pulling this in into _routecore_ allows for less dependency juggling, easier development iterations and more sensible code in all parts. All of this has some rough edges and is prone to changes on the near future. The _rotonda-fsm_ crate for now is left as-is. * Route Selection fundamentals This release introduces a first attempt at providing handles to perform the BGP Decision Process as described in RFC4271, colloquially known as 'route selection' or 'best path selection'. Most of the heavy-lifting for this comes from implementing `Ord` on a wrapper struct holding a 'route' (i.e., `PaMap`) and additional information to allow tie-breaking as described in the RFC. As the tie-breaking in RFC4271 is actually broken and not totally ordered, we aim to provide a certain degree of flexibility in the tie-breaking process by means of different `OrdStrat` ordering strategies. Other changes * Feature flags After splitting of parts of _routecore_ into the _inetnum_ crate, the default features set resulted in an almost empty library. Therefore the `bgp` flag is now on by default, and we introduced an `fsm` flag to enable the BGP FSM code absorbed from _rotonda-fsm_. Known limitations * Constructed UPDATE messages are MultiProtocol-only With regards to announcing and withdrawing NLRI, the `UpdateBuilder` is currently limited to putting everything in the MultiProtocol path attributes (MP_REACH_NLRI, MP_UNREACH_NLRI), so even for IPv4 Unicast. Note that this behaviour is considered preferable as it leads to somewhat more flexibility/resilience on the protocol level. But in case one of the peers does not signal the capability of doing IPv4 Unicast in MultiProtocol attributes, we should allow creation of PDUs in the traditional form anyway, so we plan to reintroduce this functionality.
2 parents ad05adf + 909ba27 commit bbefe17

File tree

5 files changed

+396
-88
lines changed

5 files changed

+396
-88
lines changed

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "routecore"
3-
version = "0.5.0-rc1-dev"
3+
version = "0.5.0-rc1"
44
authors = ["NLnet Labs <[email protected]>"]
55
categories = ["network-programming"]
66
description = "A Library with Building Blocks for BGP Routing"

Changelog.md

+91-4
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,104 @@
1-
## 0.5.0-rc0
1+
## 0.5.0-rc1
22

3-
Released 2024-05-29.
3+
Released 2024-06-10.
4+
5+
This release features a lot of changes, big and small. The list below is not
6+
exhaustive but tries to highlight and describe the bigger (and perhaps, more
7+
important) ones.
48

5-
TODO
69

710
Breaking changes
811

12+
* Several common basic types (e.g. `Asn` and `Prefix`) are moved out of
13+
_routecore_ to the new _inetnum_ crate.
14+
15+
* Refactor of PathAttributes
16+
17+
The introduction of `PaMap` and `RouteWorkshop` (see below) required refactoring
18+
of the `PathAttributes` enum and related types. Most significantly, an entire
19+
layer in the enum was removed, changing how one matches on variants.
20+
Furthermore some of the types in those variants slightly changed.
21+
22+
* Overhaul of address family related code
23+
24+
The types describing address families, and related traits to parse and compose
25+
NLRI of such families, have severely changed. This eliminates any possible
26+
ambiguity regarding the address family of announcements/withdrawals in UPDATE
27+
messages at compile time.
28+
29+
* Supported address families are now explicitly and exhaustively enumerated
30+
in the `AfiSafiType` enum. As a SAFI by itself does not carry much meaning,
31+
the separate `SAFI` enum is removed. Almost all of the code now works
32+
based on the more descriptive `AfiSafiType`.
33+
* ADD-PATH is now supported on all supported address families, i.e. the
34+
`AfiSafiType` includes `~AddPath` variants for every single AFI+SAFI
35+
combination.
36+
* This now allows for e.g. efficient iterators over NLRI that are generic
37+
over the `AfiSafiType`.
38+
But, as a possible downside, this moves the task of determining what
39+
address family a set of NLRI holds to the caller in order to then use the
40+
correctly typed iterator. The less efficient, 'easier to use' iterators
41+
returning an enum instead of a distinct NLRI type are therefore still
42+
available.
43+
944
New
1045

11-
Bug fixes
46+
* RouteWorkshop / PaMap
47+
48+
This release introduces the `RouteWorkshop` to create UPDATE messages based on
49+
an NLRI and a set of attributes. For creation, inspection and manipulation of
50+
those attributes, the `PaMap` is introduced. These new types work in
51+
conjunction with the existing `UpdateBuilder`.
52+
53+
* BGP FSM (absorbed from _rotonda-fsm_)
54+
55+
_routecore_ now contains the code to enable for actual BGP sessions, i.e. the
56+
BGP FSM and related machinery. By pulling this in into _routecore_ allows for
57+
less dependency juggling, easier development iterations and more sensible code
58+
in all parts. All of this has some rough edges and is prone to changes on the
59+
near future.
60+
61+
The _rotonda-fsm_ crate for now is left as-is.
62+
63+
64+
* Route Selection fundamentals
65+
66+
This release introduces a first attempt at providing handles to perform the
67+
BGP Decision Process as described in RFC4271, colloquially known as 'route
68+
selection' or 'best path selection'.
69+
70+
Most of the heavy-lifting for this comes from implementing `Ord` on a wrapper
71+
struct holding a 'route' (i.e., `PaMap`) and additional information to allow
72+
tie-breaking as described in the RFC.
73+
74+
As the tie-breaking in RFC4271 is actually broken and not totally ordered, we
75+
aim to provide a certain degree of flexibility in the tie-breaking process by
76+
means of different `OrdStrat` ordering strategies.
77+
1278

1379
Other changes
1480

81+
* Feature flags
82+
83+
After splitting of parts of _routecore_ into the _inetnum_ crate, the default
84+
features set resulted in an almost empty library. Therefore the `bgp` flag is
85+
now on by default, and we introduced an `fsm` flag to enable the BGP FSM code
86+
absorbed from _rotonda-fsm_.
87+
88+
89+
Known limitations
90+
91+
* Constructed UPDATE messages are MultiProtocol-only
92+
93+
With regards to announcing and withdrawing NLRI, the `UpdateBuilder` is currently
94+
limited to putting everything in the MultiProtocol path attributes
95+
(MP_REACH_NLRI, MP_UNREACH_NLRI), so even for IPv4 Unicast.
96+
97+
Note that this behaviour is considered preferable as it leads to somewhat more
98+
flexibility/resilience on the protocol level. But in case one of the peers
99+
does not signal the capability of doing IPv4 Unicast in MultiProtocol
100+
attributes, we should allow creation of PDUs in the traditional form anyway,
101+
so we plan to reintroduce this functionality.
15102

16103

17104
## 0.4.0

fuzz/Cargo.lock

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

fuzz/fuzz_targets/path_selection.rs

+74-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
#![no_main]
22

33
use std::cmp::Ordering::*;
4+
use std::fmt::Debug;
45
use libfuzzer_sys::fuzz_target;
5-
use routecore::bgp::{path_attributes::PaMap, path_selection::{OrdRoute, Rfc4271, SkipMed, TiebreakerInfo}};
6+
use routecore::bgp::{
7+
path_attributes::PaMap,
8+
path_selection::{OrdStrat, OrdRoute, Rfc4271, SkipMed, TiebreakerInfo,
9+
best_backup, best_backup_generic, best
10+
}
11+
};
612

713
fn verify_ord<T>(a: &T, b: &T, c: &T)
814
where T: Ord
@@ -36,6 +42,71 @@ fn verify_ord<T>(a: &T, b: &T, c: &T)
3642
}
3743
}
3844

45+
fn verify_path_selection<'a, T, OS, I>(candidates: I)
46+
where
47+
I: Clone + Iterator<Item = T>,
48+
T: Debug + Ord + core::borrow::Borrow<OrdRoute<'a, OS>>,
49+
OS: Debug + OrdStrat,
50+
{
51+
let best1 = best(candidates.clone()).unwrap();
52+
let (best2, backup2) = best_backup(candidates.clone());
53+
let best2 = best2.unwrap();
54+
55+
assert_eq!(best1.borrow(), best2.borrow());
56+
assert_eq!(best1.borrow().pa_map(), best2.borrow().pa_map());
57+
assert_eq!(best1.borrow().tiebreakers(), best2.borrow().tiebreakers());
58+
59+
let backup2 = match backup2 {
60+
Some(route) => route,
61+
None => {
62+
let mut iter = candidates.clone();
63+
let mut cur = iter.next().unwrap();
64+
for c in iter {
65+
assert_eq!(cur.borrow().inner(), c.borrow().inner());
66+
cur = c;
67+
}
68+
return;
69+
}
70+
};
71+
72+
assert_ne!(
73+
(best2.borrow().tiebreakers(), best2.borrow().pa_map()),
74+
(backup2.borrow().tiebreakers(), backup2.borrow().pa_map()),
75+
);
76+
77+
let (best_gen, backup_gen) = verify_path_selection_generic(candidates);
78+
let (best_gen, _backup_gen) = (best_gen.unwrap(), backup_gen.unwrap());
79+
80+
assert_eq!(best2, best_gen);
81+
82+
// Because best_backup_generic can't deal with duplicates, this won't
83+
// always hold:
84+
//assert_eq!(backup2, backup_gen);
85+
86+
}
87+
88+
fn verify_path_selection_generic<I, T>(candidates: I) -> (Option<T>, Option<T>)
89+
where
90+
I: Iterator<Item = T>,
91+
T: Debug + Ord
92+
{
93+
94+
let (best, backup) = best_backup_generic(
95+
// create tuples of the OrdRoute and a unique 'id'
96+
candidates.enumerate().map(|(idx, c)| (c, idx))
97+
);
98+
// because the returned values are tuples as well, we can now compare
99+
// those (instead of comparing the OrdRoute). With the unique IDs
100+
// attached, we can check whether `best` and `backup` are not equal in
101+
// terms of content.
102+
assert!(best.is_some());
103+
assert!(backup.is_some());
104+
assert_ne!(best, backup);
105+
106+
107+
(best.map(|t| t.0), backup.map(|t| t.0))
108+
}
109+
39110
// XXX while doing fuzz_target!(|data: &[u8]| ... and then creating an
40111
// Unstructured from `data` can be useful, the Debug output becomes quite
41112
// useless. It'll be just a bunch of bytes without any structure.
@@ -65,8 +136,9 @@ fuzz_target!(|data: (
65136
Err(_) => return,
66137
};
67138

68-
//dbg!("skipmed");
69139
verify_ord(&a, &b, &c);
140+
verify_path_selection([&a, &b, &c, &b, &c, &a].into_iter());
141+
//verify_path_selection_generic([&a, &b, &c].into_iter());
70142

71143
//dbg!("rfc4271");
72144
/*

0 commit comments

Comments
 (0)