mirror of
https://github.com/threefoldtech/mycelium.git
synced 2026-06-07 08:11:39 +00:00
Start refactoring to use new babel types
Signed-off-by: Lee Smet <lee.smet@hotmail.com>
This commit is contained in:
+21
-200
@@ -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
@@ -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
@@ -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
@@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user