Start refactoring to use new babel types

Signed-off-by: Lee Smet <lee.smet@hotmail.com>
This commit is contained in:
Lee Smet
2023-08-03 11:55:42 +02:00
parent 844891f06c
commit 7b38b0bf6b
4 changed files with 65 additions and 317 deletions
+21 -200
View File
@@ -1,9 +1,10 @@
use crate::{
babel::{self, Tlv},
crypto::PublicKey,
metric::Metric,
packet::{
BabelPacketBody, BabelPacketHeader, BabelTLV, BabelTLVType, ControlPacket, DataPacket,
Packet, PacketType,
BabelPacketBody, BabelPacketHeader, BabelTLVType, ControlPacket, DataPacket, Packet,
PacketType,
},
};
use bytes::{Buf, BufMut, BytesMut};
@@ -221,12 +222,15 @@ impl Encoder<DataPacket> for DataPacketCodec {
/* ****************************CONTROL PACKET******************************** */
pub struct ControlPacketCodec {
header: Option<BabelPacketHeader>,
// TODO: wrapper to make it easier to deserialize
codec: babel::Codec,
}
impl ControlPacketCodec {
pub fn new() -> Self {
ControlPacketCodec { header: None }
ControlPacketCodec {
codec: babel::Codec::new(),
}
}
}
@@ -235,134 +239,22 @@ impl Decoder for ControlPacketCodec {
type Error = std::io::Error;
fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
let header = if let Some(header) = self.header.take() {
header
} else {
if buf.remaining() < 4 {
return Ok(None);
}
let magic = buf.get_u8();
let version = buf.get_u8();
let body_length = buf.get_u16();
BabelPacketHeader {
magic,
version,
body_length,
}
let tlv = match self.codec.decode(buf)? {
None => return Ok(None),
Some(res) => res,
};
if buf.remaining() < header.body_length as usize {
// here the self.header is actually always None (due to take function)
// so assign it again to Some(header)
self.header = Some(header);
return Ok(None);
}
let tlv_type = match BabelTLVType::from_u8(buf.get_u8()) {
Some(t) => t,
None => {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"Invalid TLV type",
))
}
let body = BabelPacketBody {
tlv_type: match tlv {
babel::Tlv::Hello(_) => BabelTLVType::Hello,
babel::Tlv::Ihu(_) => BabelTLVType::IHU,
babel::Tlv::Update(_) => BabelTLVType::Update,
},
length: tlv.wire_size(),
tlv,
};
let length = buf.get_u8();
let body = match tlv_type {
BabelTLVType::Hello => {
let seqno = buf.get_u16().into();
let interval = buf.get_u16();
BabelPacketBody {
tlv_type,
length,
tlv: BabelTLV::Hello { seqno, interval },
}
}
BabelTLVType::IHU => {
let interval = buf.get_u16();
let address = IpAddr::V6(Ipv6Addr::new(
buf.get_u16(),
buf.get_u16(),
buf.get_u16(),
buf.get_u16(),
buf.get_u16(),
buf.get_u16(),
buf.get_u16(),
buf.get_u16(),
));
BabelPacketBody {
tlv_type,
length,
tlv: BabelTLV::IHU { interval, address },
}
}
BabelTLVType::Update => {
let ae = buf.get_u8();
let plen = buf.get_u8();
let interval = buf.get_u16();
let seqno = buf.get_u16().into();
let metric = buf.get_u16();
// based on the remaining bytes (ip + router_id) we can check if it's IPv4 or v6
let prefix = match ae {
0 => {
warn!("IPv4 ae, this should be removed!!");
// 4 bytes IP + 4 bytes router_id
IpAddr::V4(Ipv4Addr::new(
buf.get_u8(),
buf.get_u8(),
buf.get_u8(),
buf.get_u8(),
))
}
1 => {
// 16 bytes IP + 4 bytes router_id
IpAddr::V6(Ipv6Addr::new(
buf.get_u16(),
buf.get_u16(),
buf.get_u16(),
buf.get_u16(),
buf.get_u16(),
buf.get_u16(),
buf.get_u16(),
buf.get_u16(),
))
}
_ => {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"Invalid address length",
))
}
};
let mut router_id_bytes = [0u8; 32];
router_id_bytes.copy_from_slice(&buf[..32]);
buf.advance(32);
let router_id = PublicKey::from(router_id_bytes);
BabelPacketBody {
tlv_type,
length,
tlv: BabelTLV::Update {
plen,
interval,
seqno,
metric: Metric::from(metric),
prefix,
router_id,
},
}
}
};
Ok(Some(ControlPacket { header, body }))
Ok(Some(ControlPacket { body }))
}
}
@@ -370,77 +262,6 @@ impl Encoder<ControlPacket> for ControlPacketCodec {
type Error = io::Error;
fn encode(&mut self, message: ControlPacket, buf: &mut BytesMut) -> Result<(), Self::Error> {
// Write BabelPacketHeader
buf.put_u8(message.header.magic);
buf.put_u8(message.header.version);
buf.put_u16(message.header.body_length);
// Write BabelPacketBody
buf.put_u8(message.body.tlv_type as u8);
buf.put_u8(message.body.length);
match message.body.tlv {
BabelTLV::Hello { seqno, interval } => {
buf.put_u16(seqno.into());
buf.put_u16(interval);
}
BabelTLV::IHU { interval, address } => {
buf.put_u16(interval);
match address {
IpAddr::V4(ipv4) => {
buf.put_u8(ipv4.octets()[0]);
buf.put_u8(ipv4.octets()[1]);
buf.put_u8(ipv4.octets()[2]);
buf.put_u8(ipv4.octets()[3]);
}
IpAddr::V6(ipv6) => {
buf.put_u16(ipv6.segments()[0]);
buf.put_u16(ipv6.segments()[1]);
buf.put_u16(ipv6.segments()[2]);
buf.put_u16(ipv6.segments()[3]);
buf.put_u16(ipv6.segments()[4]);
buf.put_u16(ipv6.segments()[5]);
buf.put_u16(ipv6.segments()[6]);
buf.put_u16(ipv6.segments()[7]);
}
}
}
BabelTLV::Update {
plen,
interval,
seqno,
metric,
prefix,
router_id,
} => {
buf.put_u8(if prefix.is_ipv4() { 0 } else { 1 });
buf.put_u8(plen);
buf.put_u16(interval);
buf.put_u16(seqno.into());
buf.put_u16(metric.into());
match prefix {
IpAddr::V4(ipv4) => {
buf.put_u8(ipv4.octets()[0]);
buf.put_u8(ipv4.octets()[1]);
buf.put_u8(ipv4.octets()[2]);
buf.put_u8(ipv4.octets()[3]);
}
IpAddr::V6(_ipv6) => {
buf.put_u16(_ipv6.segments()[0]);
buf.put_u16(_ipv6.segments()[1]);
buf.put_u16(_ipv6.segments()[2]);
buf.put_u16(_ipv6.segments()[3]);
buf.put_u16(_ipv6.segments()[4]);
buf.put_u16(_ipv6.segments()[5]);
buf.put_u16(_ipv6.segments()[6]);
buf.put_u16(_ipv6.segments()[7]);
}
}
buf.put_slice(&router_id.to_bytes());
}
}
Ok(())
self.codec.encode(message.body.tlv, buf)
}
}
+13 -63
View File
@@ -1,6 +1,6 @@
use std::net::{IpAddr, Ipv6Addr};
use crate::{crypto::PublicKey, metric::Metric, peer::Peer, sequence_number::SeqNo};
use crate::{babel, crypto::PublicKey, metric::Metric, peer::Peer, sequence_number::SeqNo};
pub const BABEL_MAGIC: u8 = 42;
pub const BABEL_VERSION: u8 = 2;
@@ -39,7 +39,6 @@ pub struct ControlStruct {
#[derive(Debug, PartialEq, Clone)]
pub struct ControlPacket {
pub header: BabelPacketHeader,
pub body: BabelPacketBody,
}
@@ -55,7 +54,7 @@ pub struct BabelPacketHeader {
pub struct BabelPacketBody {
pub tlv_type: BabelTLVType,
pub length: u8, // length of the tlv (only the tlv, not tlv_type and length itself)
pub tlv: BabelTLV,
pub tlv: babel::Tlv,
}
impl BabelPacketHeader {
@@ -70,33 +69,25 @@ impl BabelPacketHeader {
impl ControlPacket {
pub fn new_hello(dest_peer: &mut Peer, interval: u16) -> Self {
let header_length = (BabelTLVType::Hello.get_tlv_length(false) + 2) as u16;
let tlv: babel::Tlv = babel::Hello::new_unicast(dest_peer.hello_seqno(), interval).into();
dest_peer.increment_hello_seqno();
Self {
header: BabelPacketHeader::new(header_length),
body: BabelPacketBody {
tlv_type: BabelTLVType::Hello,
length: BabelTLVType::Hello.get_tlv_length(false),
tlv: BabelTLV::Hello {
seqno: dest_peer.hello_seqno(),
interval,
},
length: tlv.wire_size(),
tlv,
},
}
}
pub fn new_ihu(interval: u16, dest_address: IpAddr) -> Self {
let uses_ipv6 = dest_address.is_ipv6();
let header_length = (BabelTLVType::IHU.get_tlv_length(uses_ipv6) + 2) as u16;
// TODO: Set rx metric
let tlv: babel::Tlv = babel::Ihu::new(Metric::from(0), interval, Some(dest_address)).into();
Self {
header: BabelPacketHeader::new(header_length),
body: BabelPacketBody {
tlv_type: BabelTLVType::IHU,
length: BabelTLVType::IHU.get_tlv_length(uses_ipv6),
tlv: BabelTLV::IHU {
interval,
address: dest_address,
},
length: tlv.wire_size(),
tlv,
},
}
}
@@ -109,21 +100,13 @@ impl ControlPacket {
prefix: IpAddr,
router_id: PublicKey,
) -> Self {
let uses_ipv6 = prefix.is_ipv6();
let header_length = (BabelTLVType::Update.get_tlv_length(uses_ipv6) + 2) as u16;
let tlv: babel::Tlv =
babel::Update::new(plen, 0, interval, seqno, metric, prefix, router_id).into();
Self {
header: BabelPacketHeader::new(header_length),
body: BabelPacketBody {
tlv_type: BabelTLVType::Update,
length: BabelTLVType::Update.get_tlv_length(uses_ipv6),
tlv: BabelTLV::Update {
plen,
interval,
seqno,
metric,
prefix,
router_id,
},
length: tlv.wire_size(),
tlv,
},
}
}
@@ -145,37 +128,4 @@ impl BabelTLVType {
_ => None,
}
}
pub fn get_tlv_length(self, uses_ipv6: bool) -> u8 {
let (ipv6, ipv4) = match self {
Self::Hello => (4, 4),
Self::IHU => (18, 6),
Self::Update => (31 + 1, 19 + 1), // +1 for ae
};
if uses_ipv6 {
ipv6
} else {
ipv4
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum BabelTLV {
Hello {
seqno: SeqNo,
interval: u16,
},
IHU {
interval: u16,
address: IpAddr,
},
Update {
plen: u8,
interval: u16,
seqno: SeqNo,
metric: Metric,
prefix: IpAddr,
router_id: PublicKey,
},
}
+22 -23
View File
@@ -1,7 +1,8 @@
use crate::{
babel,
crypto::{PublicKey, SecretKey},
metric::Metric,
packet::{BabelTLV, BabelTLVType, ControlPacket, ControlStruct, DataPacket},
packet::{BabelTLVType, ControlPacket, ControlStruct, DataPacket},
peer::Peer,
routing_table::{RouteEntry, RouteKey, RoutingTable},
sequence_number::SeqNo,
@@ -297,16 +298,15 @@ impl Router {
}
}
fn handle_incoming_update(&self, update: ControlStruct) {
match update.control_packet.body.tlv {
BabelTLV::Update {
plen,
interval: _,
seqno,
metric,
prefix,
router_id,
} => {
fn handle_incoming_update(&self, update_packet: ControlStruct) {
match update_packet.control_packet.body.tlv {
babel::Tlv::Update(update) => {
let metric = update.metric();
let plen = update.plen();
let router_id = update.router_id();
let prefix = update.prefix();
let seqno = update.seqno();
// convert prefix to ipv6 address
if let IpAddr::V6(prefix_as_ipv6addr) = prefix {
// add it the mapping
@@ -315,7 +315,7 @@ impl Router {
// create route key from incoming update control struct
// we need the address of the neighbour; this corresponds to the source ip of the control struct as the update is received from the neighbouring peer
let neighbor_ip = update.src_overlay_ip;
let neighbor_ip = update_packet.src_overlay_ip;
let route_key_from_update = RouteKey::new(prefix, plen, neighbor_ip);
// used later to filter out static route
if self.route_key_is_from_static_route(&route_key_from_update) {
@@ -813,17 +813,16 @@ impl RouterInner {
matching_peer.map(Clone::clone)
}
fn send_update(&mut self, peer: &Peer, update: ControlPacket) {
fn send_update(&mut self, peer: &Peer, update_packet: ControlPacket) {
// before sending an update, the source table might need to be updated
match update.body.tlv {
BabelTLV::Update {
plen,
interval: _,
seqno,
metric,
prefix,
router_id,
} => {
match update_packet.body.tlv {
babel::Tlv::Update(ref update) => {
let plen = update.plen();
let seqno = update.seqno();
let metric = update.metric();
let prefix = update.prefix();
let router_id = update.router_id();
let source_key = SourceKey::new(prefix, plen, router_id);
if let Some(source_entry) = self.source_table.get(&source_key) {
@@ -847,7 +846,7 @@ impl RouterInner {
}
// send the update to the peer
if let Err(e) = peer.send_control_packet(update) {
if let Err(e) = peer.send_control_packet(update_packet) {
error!("Error sending update to peer: {:?}", e);
}
}
+9 -31
View File
@@ -1,13 +1,6 @@
use std::{collections::HashMap, net::IpAddr};
use log::error;
use crate::{
crypto::PublicKey,
metric::Metric,
packet::{BabelTLV, ControlStruct},
sequence_number::SeqNo,
};
use crate::{babel, crypto::PublicKey, metric::Metric, sequence_number::SeqNo};
#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)]
pub struct SourceKey {
@@ -95,33 +88,18 @@ impl SourceTable {
}
/// Indicates if an update is feasible in the context of the current `SoureTable`.
pub fn is_update_feasible(&self, update: &ControlStruct) -> bool {
pub fn is_update_feasible(&self, update: &babel::Update) -> bool {
// Before an update is accepted it should be checked against the feasbility condition
// If an entry in the source table with the same source key exists, we perform the feasbility check
// If no entry exists yet, the update is accepted as there is no better alternative available (yet)
match update.control_packet.body.tlv {
BabelTLV::Update {
plen,
interval: _,
seqno,
metric,
prefix,
router_id,
} => {
let source_key = SourceKey::new(prefix, plen, router_id);
match self.get(&source_key) {
Some(&entry) => {
(!seqno.lt(&entry.seqno()))
|| (seqno == entry.seqno() && metric < entry.metric())
|| metric.is_infinite()
}
None => true,
}
}
_ => {
error!("Error accepting update, control struct did not match update packet");
false
let source_key = SourceKey::new(update.prefix(), update.plen(), update.router_id());
match self.get(&source_key) {
Some(entry) => {
(!update.seqno().lt(&entry.seqno()))
|| (update.seqno() == entry.seqno() && update.metric() < entry.metric())
|| update.metric().is_infinite()
}
None => true,
}
}
}