Packet: the wire format's shared pieces in one module
What the parsers and writers of messages, attributes and capabilities had each written for themselves is one module (wire.rs): the shape of a parser's result and its error, reading a list to the end, checking that nothing was left over, a non-empty list of fixed-size records (the community attributes and CLUSTER_LIST, which now fail alike), an AS number at the session's width, an AFI/SAFI pair, and a length written before what it counts. open.rs loses its fail! macro and attributes.rs its own copies of the same. Tests for what had none: AS4_AGGREGATOR kept opaque and discarded when malformed; IPv4 routes with IPv6 next hops (RFC 8950) in the property tests; and what a part-level parser accepts re-encodes to what it read, but for the fields the decoders normalise. Nlri::wire_len had no callers; the mask of a prefix's last octet is one function; a test's name is spelled right; a comment is on the test it describes. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
b467b136e4
commit
e5341ea639
8 files changed
+479
-290
No files matched your search
@@ -64,7 +64,7 @@ impl IpPrefix {
|
||||
let mut address = [0u8; 16];
|
||||
address[..needed].copy_from_slice(&prefix[..needed]);
|
||||
if let (Some(last), rem @ 1..) = (address[..needed].last_mut(), length % 8) {
|
||||
*last &= u8::MAX << (8 - rem);
|
||||
*last &= high_bits_mask(rem);
|
||||
}
|
||||
Ok(Self {
|
||||
address_family,
|
||||
@@ -98,7 +98,7 @@ impl IpPrefix {
|
||||
let whole = usize::from(length / 8);
|
||||
address[..whole].copy_from_slice(&self.address[..whole]);
|
||||
if !length.is_multiple_of(8) {
|
||||
address[whole] = self.address[whole] & (u8::MAX << (8 - length % 8));
|
||||
address[whole] = self.address[whole] & high_bits_mask(length % 8);
|
||||
}
|
||||
Self {
|
||||
address_family: self.address_family,
|
||||
@@ -122,11 +122,18 @@ impl IpPrefix {
|
||||
if rem_bits == 0 {
|
||||
return true;
|
||||
}
|
||||
let mask = u8::MAX << (8 - rem_bits);
|
||||
let mask = high_bits_mask(rem_bits);
|
||||
(self.address[full_bytes] & mask) == (other.address[full_bytes] & mask)
|
||||
}
|
||||
}
|
||||
|
||||
/// The mask that keeps the first `bits` bits of an octet and clears the
|
||||
/// rest, for `bits` from 1 to 7: what the last octet of a prefix whose
|
||||
/// length is not a whole number of octets is masked with.
|
||||
fn high_bits_mask(bits: u8) -> u8 {
|
||||
u8::MAX << (8 - bits)
|
||||
}
|
||||
|
||||
/// A prefix as an UPDATE names it: the prefix and, on a session where
|
||||
/// ADD-PATH is in use for the address family (RFC 7911), the identifier
|
||||
/// that tells apart the several routes a peer may announce for it.
|
||||
@@ -144,11 +151,6 @@ impl Nlri {
|
||||
pub fn plain(prefixes: impl IntoIterator<Item = IpPrefix>) -> Vec<Self> {
|
||||
prefixes.into_iter().map(Self::from).collect()
|
||||
}
|
||||
|
||||
/// The bytes this takes on the wire, with or without its identifier.
|
||||
pub fn wire_len(&self, with_path_id: bool) -> usize {
|
||||
1 + self.prefix.bytes().len() + if with_path_id { 4 } else { 0 }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<IpPrefix> for Nlri {
|
||||
|
||||
Reference in new issue
Block a user