From c8f8a73ad3fe2a14d7bd81749c61b076d25f82e5 Mon Sep 17 00:00:00 2001 From: Lee Smet Date: Mon, 24 Mar 2025 16:35:12 +0100 Subject: [PATCH] Add generation to route request packet Signed-off-by: Lee Smet --- mycelium/src/babel.rs | 11 +++-- mycelium/src/babel/route_request.rs | 74 +++++++++++++++++++---------- mycelium/src/router.rs | 2 +- 3 files changed, 57 insertions(+), 30 deletions(-) diff --git a/mycelium/src/babel.rs b/mycelium/src/babel.rs index 30a5e01..ca04ec0 100644 --- a/mycelium/src/babel.rs +++ b/mycelium/src/babel.rs @@ -299,10 +299,13 @@ mod tests { let mut sender = Framed::new(tx, super::Codec::new()); let mut receiver = Framed::new(rx, super::Codec::new()); - let rr = super::RouteRequest::new(Some( - Subnet::new(Ipv6Addr::new(0x400, 1, 2, 3, 0, 0, 0, 0).into(), 64) - .expect("64 is a valid IPv6 prefix size; qed"), - )); + let rr = super::RouteRequest::new( + Some( + Subnet::new(Ipv6Addr::new(0x400, 1, 2, 3, 0, 0, 0, 0).into(), 64) + .expect("64 is a valid IPv6 prefix size; qed"), + ), + 13, + ); sender .send(rr.clone().into()) diff --git a/mycelium/src/babel/route_request.rs b/mycelium/src/babel/route_request.rs index 4e4f165..86cb7ad 100644 --- a/mycelium/src/babel/route_request.rs +++ b/mycelium/src/babel/route_request.rs @@ -8,13 +8,15 @@ use crate::subnet::Subnet; use super::{AE_IPV4, AE_IPV6, AE_IPV6_LL, AE_WILDCARD}; /// Base wire size of a [`RouteRequest`] without variable length address encoding. -const ROUTE_REQUEST_BASE_WIRE_SIZE: u8 = 2; +const ROUTE_REQUEST_BASE_WIRE_SIZE: u8 = 3; /// Seqno request TLV body as defined in https://datatracker.ietf.org/doc/html/rfc8966#name-route-request #[derive(Debug, Clone, PartialEq)] pub struct RouteRequest { /// The prefix being requested prefix: Option, + /// The requests' generation + generation: u8, } impl RouteRequest { @@ -22,8 +24,8 @@ impl RouteRequest { /// route table dumb in requested. /// /// [`prefix`]: Subnet - pub fn new(prefix: Option) -> Self { - Self { prefix } + pub fn new(prefix: Option, generation: u8) -> Self { + Self { prefix, generation } } /// Return the [`prefix`](Subnet) associated with this `RouteRequest`. @@ -31,6 +33,12 @@ impl RouteRequest { self.prefix } + /// Return the generation of the `RouteRequest`, which is the amount of times it has been + /// forwarded already. + pub fn generation(&self) -> u8 { + self.generation + } + /// Calculates the size on the wire of this `RouteRequest`. pub fn wire_size(&self) -> u8 { ROUTE_REQUEST_BASE_WIRE_SIZE @@ -48,6 +56,7 @@ impl RouteRequest { /// This function will panic if there are insufficient bytes present in the provided buffer to /// decode a complete `RouteRequest`. pub fn from_bytes(src: &mut bytes::BytesMut, len: u8) -> Option { + let generation = src.get_u8(); let ae = src.get_u8(); let plen = src.get_u8(); @@ -87,7 +96,7 @@ impl RouteRequest { _ => { // Invalid AE type, skip reamining data and ignore trace!("Invalid AE type in route_request packet, drop packet"); - src.advance(len as usize - 2); + src.advance(len as usize - 3); return None; } }; @@ -96,11 +105,12 @@ impl RouteRequest { trace!("Read route_request tlv body"); - Some(RouteRequest { prefix }) + Some(RouteRequest { prefix, generation }) } /// Encode this `RouteRequest` tlv as part of a packet. pub fn write_bytes(&self, dst: &mut bytes::BytesMut) { + dst.put_u8(self.generation); if let Some(prefix) = self.prefix { dst.put_u8(match prefix.address() { IpAddr::V4(_) => AE_IPV4, @@ -137,12 +147,13 @@ mod tests { Subnet::new(Ipv6Addr::new(512, 25, 26, 27, 28, 0, 0, 29).into(), 64) .expect("64 is a valid IPv6 prefix size; qed"), ), + generation: 2, }; rr.write_bytes(&mut buf); - assert_eq!(buf.len(), 10); - assert_eq!(buf[..10], [2, 64, 2, 0, 0, 25, 0, 26, 0, 27]); + assert_eq!(buf.len(), 11); + assert_eq!(buf[..11], [2, 2, 64, 2, 0, 0, 25, 0, 26, 0, 27]); let mut buf = bytes::BytesMut::new(); @@ -151,28 +162,35 @@ mod tests { Subnet::new(Ipv4Addr::new(10, 101, 4, 1).into(), 32) .expect("32 is a valid IPv4 prefix size; qed"), ), + generation: 3, }; rr.write_bytes(&mut buf); - assert_eq!(buf.len(), 6); - assert_eq!(buf[..6], [1, 32, 10, 101, 4, 1]); + assert_eq!(buf.len(), 7); + assert_eq!(buf[..7], [3, 1, 32, 10, 101, 4, 1]); let mut buf = bytes::BytesMut::new(); - let rr = super::RouteRequest { prefix: None }; + let rr = super::RouteRequest { + prefix: None, + generation: 0, + }; rr.write_bytes(&mut buf); - assert_eq!(buf.len(), 2); - assert_eq!(buf[..2], [0, 0]); + assert_eq!(buf.len(), 3); + assert_eq!(buf[..3], [0, 0, 0]); } #[test] fn decoding() { - let mut buf = bytes::BytesMut::from(&[0, 0][..]); + let mut buf = bytes::BytesMut::from(&[12, 0, 0][..]); - let rr = super::RouteRequest { prefix: None }; + let rr = super::RouteRequest { + prefix: None, + generation: 12, + }; let buf_len = buf.len(); assert_eq!( @@ -181,13 +199,14 @@ mod tests { ); assert_eq!(buf.remaining(), 0); - let mut buf = bytes::BytesMut::from(&[1, 24, 10, 15, 19][..]); + let mut buf = bytes::BytesMut::from(&[24, 1, 24, 10, 15, 19][..]); let rr = super::RouteRequest { prefix: Some( Subnet::new(Ipv4Addr::new(10, 15, 19, 0).into(), 24) .expect("24 is a valid IPv4 prefix size; qed"), ), + generation: 24, }; let buf_len = buf.len(); @@ -197,13 +216,14 @@ mod tests { ); assert_eq!(buf.remaining(), 0); - let mut buf = bytes::BytesMut::from(&[2, 64, 0, 10, 0, 20, 0, 30, 0, 40][..]); + let mut buf = bytes::BytesMut::from(&[7, 2, 64, 0, 10, 0, 20, 0, 30, 0, 40][..]); let rr = super::RouteRequest { prefix: Some( Subnet::new(Ipv6Addr::new(10, 20, 30, 40, 0, 0, 0, 0).into(), 64) .expect("64 is a valid IPv6 prefix size; qed"), ), + generation: 7, }; let buf_len = buf.len(); @@ -213,13 +233,14 @@ mod tests { ); assert_eq!(buf.remaining(), 0); - let mut buf = bytes::BytesMut::from(&[3, 64, 0, 10, 0, 20, 0, 30, 0, 40][..]); + let mut buf = bytes::BytesMut::from(&[4, 3, 64, 0, 10, 0, 20, 0, 30, 0, 40][..]); let rr = super::RouteRequest { prefix: Some( Subnet::new(Ipv6Addr::new(0xfe80, 0, 0, 0, 10, 20, 30, 40).into(), 64) .expect("64 is a valid IPv6 prefix size; qed"), ), + generation: 4, }; let buf_len = buf.len(); @@ -236,7 +257,7 @@ mod tests { // test to fail if we forget to update something let mut buf = bytes::BytesMut::from( &[ - 4, 64, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 0, 4, 64, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, ][..], ); @@ -255,13 +276,16 @@ mod tests { fn roundtrip() { let mut buf = bytes::BytesMut::new(); - let seqno_src = super::RouteRequest::new(Some( - Subnet::new( - Ipv6Addr::new(0x21f, 0x4025, 0xabcd, 0xdead, 0, 0, 0, 0).into(), - 64, - ) - .expect("64 is a valid IPv6 prefix size; qed"), - )); + let seqno_src = super::RouteRequest::new( + Some( + Subnet::new( + Ipv6Addr::new(0x21f, 0x4025, 0xabcd, 0xdead, 0, 0, 0, 0).into(), + 64, + ) + .expect("64 is a valid IPv6 prefix size; qed"), + ), + 27, + ); seqno_src.write_bytes(&mut buf); let buf_len = buf.len(); let decoded = super::RouteRequest::from_bytes(&mut buf, buf_len as u8); diff --git a/mycelium/src/router.rs b/mycelium/src/router.rs index 45f5d58..d7503d9 100644 --- a/mycelium/src/router.rs +++ b/mycelium/src/router.rs @@ -203,7 +203,7 @@ where "Requesting route table dump from {}", peer.connection_identifier() ); - if let Err(e) = peer.send_control_packet(RouteRequest::new(None).into()) { + if let Err(e) = peer.send_control_packet(RouteRequest::new(None, 0).into()) { error!( "Failed to request route table dump from {}: {e}", peer.connection_identifier()