mirror of
https://github.com/threefoldtech/mycelium.git
synced 2026-06-07 00:01:40 +00:00
update packet structure and codec to be more in line with Babel protocol
This commit is contained in:
+69
-43
@@ -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
@@ -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 },
|
||||
|
||||
Reference in New Issue
Block a user