update packet structure and codec to be more in line with Babel protocol

This commit is contained in:
Maxime Van Hees
2023-04-27 11:31:38 +00:00
parent 1e9d39c8c3
commit f3dd56af22
2 changed files with 116 additions and 57 deletions
+69 -43
View File
@@ -1,7 +1,7 @@
use std::{io, net::{IpAddr, Ipv4Addr}};
use bytes::{BufMut, BytesMut, Buf};
use tokio_util::codec::{Encoder, Decoder};
use crate::packet::{Packet, ControlPacket, DataPacket, PacketType, ControlPacketBody, ControlPacketType};
use crate::packet::{Packet, ControlPacket, DataPacket, PacketType, ControlPacketBody, ControlPacketType, BabelTLVType, BabelPacketBody, BabelTLV, BabelPacketHeader};
/* ********************************PAKCET*********************************** */
pub struct PacketCodec {
@@ -194,58 +194,78 @@ impl Decoder for ControlPacketCodec {
type Error = std::io::Error;
fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
if buf.is_empty() {
if buf.remaining() < 4 {
return Ok(None);
}
let message_type = match ControlPacketType::from_u8(buf.get_u8()) {
Some(t) => t,
None => return Err(io::Error::new(io::ErrorKind::InvalidData, "Invalid message type")),
};
if message_type == ControlPacketType::Pad1 {
return Ok(Some(ControlPacket {
message_type,
body_length: 0,
body: Some(ControlPacketBody::Pad1),
}));
}
let body_length = buf.get_u8();
let magic = buf.get_u8();
let version = buf.get_u8();
let body_length = buf.get_u16();
if buf.remaining() < body_length as usize {
return Ok(None);
}
let body = match message_type {
ControlPacketType::PadN => {
buf.advance(usize::from(body_length));
Some(ControlPacketBody::PadN(body_length))
let header = BabelPacketHeader {
magic,
version,
body_length,
};
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")),
};
if tlv_type == BabelTLVType::Pad1 {
return Ok(Some(ControlPacket {
header,
body: Some(BabelPacketBody {
tlv_type,
length: 0,
body: BabelTLV::Pad1,
}),
}));
}
let length = buf.get_u8();
let body = match tlv_type {
BabelTLVType::PadN => {
buf.advance(usize::from(length));
Some(BabelPacketBody {
tlv_type,
length,
body: BabelTLV::PadN(length),
})
}
ControlPacketType::Hello => {
BabelTLVType::Hello => {
let flags = buf.get_u16();
let seqno = buf.get_u16();
let interval = buf.get_u16();
Some(ControlPacketBody::Hello { flags, seqno, interval })
Some(BabelPacketBody {
tlv_type,
length,
body: BabelTLV::Hello { flags, seqno, interval },
})
}
ControlPacketType::IHU => {
BabelTLVType::IHU => {
let _address_encoding = buf.get_u8();
// todo: based on address_encoding, we should decode the address on a different way
let _reserved = buf.get_u8();
let rxcost = buf.get_u16();
let interval = buf.get_u16();
let address = IpAddr::V4(Ipv4Addr::new(buf.get_u8(), buf.get_u8(), buf.get_u8(), buf.get_u8()));
Some(ControlPacketBody::IHU { rxcost, interval, address })
Some(BabelPacketBody {
tlv_type,
length,
body: BabelTLV::IHU { rxcost, interval, address },
})
}
// Add decoding logic for other message types.
// Add decoding logic for other TLV types.
_ => None,
};
Ok(Some(ControlPacket {
message_type,
body_length,
body,
}))
Ok(Some(ControlPacket { header, body }))
}
}
@@ -253,23 +273,29 @@ impl Encoder<ControlPacket> for ControlPacketCodec {
type Error = io::Error;
fn encode(&mut self, message: ControlPacket, buf: &mut BytesMut) -> Result<(), Self::Error> {
buf.put_u8(message.message_type as u8);
buf.put_u8(message.body_length);
// Write BabelPacketHeader
buf.put_u8(message.header.magic);
buf.put_u8(message.header.version);
buf.put_u16(message.header.body_length);
if let Some(body) = message.body {
match body {
ControlPacketBody::Pad1 => {}
ControlPacketBody::PadN(padding_length) => {
// Write BabelPacketBody
buf.put_u8(body.tlv_type as u8);
buf.put_u8(body.length);
match body.body {
BabelTLV::Pad1 => {}
BabelTLV::PadN(padding_length) => {
buf.put_slice(&vec![0; usize::from(padding_length)]);
}
ControlPacketBody::Hello { flags, seqno, interval } => {
BabelTLV::Hello { flags, seqno, interval } => {
buf.put_u16(flags);
buf.put_u16(seqno);
buf.put_u16(interval);
}
ControlPacketBody::IHU { rxcost, interval, address } => {
buf.put_u8(0); // temp static address encoding
buf.put_u8(0); // reserved field should be set to 0 and MUST be ignored on recpetion
BabelTLV::IHU { rxcost, interval, address } => {
buf.put_u8(0); // Temporary static address encoding
buf.put_u8(0); // Reserved field should be set to 0 and MUST be ignored on reception
buf.put_u16(rxcost);
buf.put_u16(interval);
match address {
@@ -280,15 +306,15 @@ impl Encoder<ControlPacket> for ControlPacketCodec {
buf.put_u8(ipv4.octets()[3]);
}
IpAddr::V6(_ipv6) => {
println!("IPv6 not supported yet");
println!("IPv6 not supported yet");
}
}
}
// Add encoding logic for other message types.
// Add encoding logic for other TLV types.
_ => {}
}
}
Ok(())
}
}
}
+47 -14
View File
@@ -1,6 +1,9 @@
use std::net::{IpAddr, Ipv4Addr};
use tokio::sync::mpsc;
pub const BABEL_MAGIC: u8 = 42;
pub const BABEL_VERSION: u8 = 2;
/* ********************************PAKCET*********************************** */
#[derive(Debug, Clone)]
pub enum Packet {
@@ -33,6 +36,29 @@ pub struct ControlStruct {
pub src_overlay_ip: IpAddr,
}
#[derive(Debug, PartialEq, Clone)]
pub struct ControlPacket {
pub header: BabelPacketHeader,
pub body: Option<BabelPacketBody>,
// pub trailer: Option<BabelPacketTrailer>,
}
#[derive(Debug, PartialEq, Clone)]
pub struct BabelPacketHeader {
pub magic: u8,
pub version: u8,
pub body_length: u16,
}
// A BabelPacketBody describes exactly one TLV
// According to the protocol the body of a Babel packet can contain multiple subsequent TLV's --> TODO
#[derive(Debug, PartialEq, Clone)]
pub struct BabelPacketBody {
pub tlv_type: BabelTLVType,
pub length: u8,
pub body: BabelTLV,
}
impl ControlStruct {
pub fn reply(self, control_packet: ControlPacket) {
if let Err(e) = self.control_reply_tx.send(control_packet) {
@@ -41,29 +67,36 @@ impl ControlStruct {
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct ControlPacket {
pub message_type: ControlPacketType,
pub body_length: u8,
pub body: Option<ControlPacketBody>,
impl BabelPacketHeader {
pub fn new(body_length: u16) -> Self {
Self {
magic: BABEL_MAGIC,
version: BABEL_VERSION,
body_length,
}
}
}
impl ControlPacket {
pub fn new_ihu(rxcost: u16, interval: u16, dest_address: IpAddr) -> Self {
Self {
message_type: ControlPacketType::IHU,
body_length: 10,
body: Some(ControlPacketBody::IHU {
rxcost,
interval,
address: dest_address,
header: BabelPacketHeader::new(10),
body: Some(BabelPacketBody {
tlv_type: BabelTLVType::IHU,
length: 8,
body: BabelTLV::IHU {
rxcost,
interval,
address: dest_address,
}
}),
}
}
}
#[derive(Debug, PartialEq, Clone)]
pub enum ControlPacketType {
pub enum BabelTLVType {
Pad1 = 0,
PadN = 1,
AckReq = 2,
@@ -77,7 +110,7 @@ pub enum ControlPacketType {
SeqnoReq = 10,
}
impl ControlPacketType {
impl BabelTLVType {
pub fn from_u8(value: u8) -> Option<Self> {
match value {
0 => Some(Self::Pad1),
@@ -97,7 +130,7 @@ impl ControlPacketType {
}
#[derive(Debug, Clone, PartialEq)]
pub enum ControlPacketBody {
pub enum BabelTLV {
Pad1,
PadN(u8),
AckReq { nonce: u16, interval: u16 },