diff --git a/holo-interface/src/interface.rs b/holo-interface/src/interface.rs index f28329bd..6f4adbbf 100644 --- a/holo-interface/src/interface.rs +++ b/holo-interface/src/interface.rs @@ -38,7 +38,7 @@ pub struct Interface { pub mtu: Option, pub flags: InterfaceFlags, pub addresses: BTreeMap, - pub mac_address: Vec, + pub mac_address: [u8; 6], pub owner: Owner, pub vrrp: Option, } @@ -141,7 +141,7 @@ impl Interfaces { ifindex: u32, mtu: u32, flags: InterfaceFlags, - mac_address: Vec, + mac_address: [u8; 6], netlink_handle: &rtnetlink::Handle, ibus_tx: Option<&IbusSender>, ) { diff --git a/holo-interface/src/netlink.rs b/holo-interface/src/netlink.rs index a353ffe4..64e72e5b 100644 --- a/holo-interface/src/netlink.rs +++ b/holo-interface/src/netlink.rs @@ -45,7 +45,7 @@ async fn process_newlink_msg( let ifindex = msg.header.index; let mut ifname = None; let mut mtu = None; - let mut mac_address: Vec = Vec::default(); + let mut mac_address: [u8; 6] = [0u8; 6]; let mut flags = InterfaceFlags::empty(); if msg.header.link_layer_type == ARPHRD_LOOPBACK { @@ -58,7 +58,12 @@ async fn process_newlink_msg( match nla { Nla::IfName(nla_ifname) => ifname = Some(nla_ifname), Nla::Mtu(nla_mtu) => mtu = Some(nla_mtu), - Nla::Address(addr) => mac_address = addr, + Nla::Address(addr) => { + mac_address = match addr.try_into() { + Ok(a) => a, + Err(e) => [0u8; 6] + }; + }, _ => (), } } diff --git a/holo-utils/src/southbound.rs b/holo-utils/src/southbound.rs index 4d579e69..3b22880a 100644 --- a/holo-utils/src/southbound.rs +++ b/holo-utils/src/southbound.rs @@ -71,7 +71,7 @@ pub struct InterfaceUpdateMsg { pub ifindex: u32, pub mtu: u32, pub flags: InterfaceFlags, - pub mac_address: Vec, + pub mac_address: [u8; 6], } #[derive(Clone, Debug)] diff --git a/holo-vrrp/src/error.rs b/holo-vrrp/src/error.rs index 6d7e2588..54cae245 100644 --- a/holo-vrrp/src/error.rs +++ b/holo-vrrp/src/error.rs @@ -14,6 +14,7 @@ use tracing::{warn, warn_span}; pub enum Error { // I/O errors IoError(IoError), + InterfaceError(String), // vrrp-ietf-yang-2018-03-13 specific errors GlobalError(GlobalError), @@ -54,6 +55,9 @@ impl Error { Error::IoError(error) => { error.log(); } + Error::InterfaceError(error) => { + warn_span!("vrrp_interface_error").in_scope(|| warn!(error)); + } Error::GlobalError(error) => { match error { GlobalError::ChecksumError => { @@ -91,6 +95,7 @@ impl std::fmt::Display for Error { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Error::IoError(error) => std::fmt::Display::fmt(error, f), + Error::InterfaceError(error) => write!(f, "{}", error), Error::GlobalError(error) => std::fmt::Display::fmt(error, f), Error::VirtualRouterError(error) => { std::fmt::Display::fmt(error, f) diff --git a/holo-vrrp/src/events.rs b/holo-vrrp/src/events.rs index 5cdb6bdb..8c04724e 100644 --- a/holo-vrrp/src/events.rs +++ b/holo-vrrp/src/events.rs @@ -5,77 +5,93 @@ use std::borrow::{Borrow, BorrowMut}; use std::net::IpAddr; +use libc::wait; + use crate::error::Error; use crate::instance::{Instance, InstanceState, State}; use crate::interface::Interface; use crate::packet::{DecodeResult, VrrpPacket}; use crate::tasks; +// To collect actions to be executed later +enum Action { + SendVrrpAdvert(u8), + SendGratuitousArp(u8), + ChangeState(u8, State), + SetMasterDownTimer(u8, u64), + ResetTimer(u8), +} + // ===== Network packet receipt ===== -// pub(crate) fn process_packet( interface: &mut Interface, packet: DecodeResult, ) -> Result<(), Error> { // Handle packet decoding errors - let pkt = match packet { - Ok(p) => p, - Err(e) => return Ok(()), // or handle the error appropriately + let pkt = packet.unwrap(); + + // collect the actions that are required + let mut actions = match get_actions(interface, pkt) { + Ok(a) => a, + Err(e) => return Err(e) }; + + // execute all collected actions + handle_actions(interface, actions); + Ok(()) +} - // To collect actions to be executed later - enum Action { - SendVrrpAdvert(u8), - SendGratuitousArp(u8), - ChangeState(u8, State), - SetMasterDownTimer(u8, u64), - ResetTimer(u8), - } +// gets all the actions that are required to be done bacsed on the interface +// configs and incoming packet +fn get_actions(interface: &mut Interface, packet: VrrpPacket) -> Result, Error> { let mut actions = Vec::new(); - { - // Handle missing instance - let instance = match interface.instances.get_mut(&pkt.vrid) { - Some(inst) => inst, - None => return Ok(()), // or handle the error appropriately - }; + // Handle missing instance + let instance = match interface.instances.get_mut(&packet.vrid) { + Some(inst) => inst, + None => return Err( + Error::InterfaceError(String::from("unable to fetch VRRP instance from interface")) + ), + }; - // Update statistics - instance.state.statistics.adv_rcvd += 1; + // Update statistics + instance.state.statistics.adv_rcvd += 1; - // Handle the current state - match instance.state.state { - State::Initialize => { - if instance.config.priority == 255 { - actions.push(Action::SendVrrpAdvert(pkt.vrid)); - actions.push(Action::SendGratuitousArp(pkt.vrid)); - actions.push(Action::ChangeState(pkt.vrid, State::Master)); - } + // Handle the current state + match instance.state.state { + State::Initialize => { + if instance.config.priority == 255 { + actions.push(Action::SendVrrpAdvert(packet.vrid)); + actions.push(Action::SendGratuitousArp(packet.vrid)); + actions.push(Action::ChangeState(packet.vrid, State::Master)); } - State::Backup => { - if pkt.priority == 0 { - actions.push(Action::SetMasterDownTimer(pkt.vrid, instance.state.skew_time as u64)); - } else if !instance.config.preempt - || pkt.priority >= instance.config.priority - { - actions.push(Action::ResetTimer(pkt.vrid)); - } + } + State::Backup => { + if packet.priority == 0 { + actions.push(Action::SetMasterDownTimer(packet.vrid, instance.state.skew_time as u64)); + } else if !instance.config.preempt + || packet.priority >= instance.config.priority + { + actions.push(Action::ResetTimer(packet.vrid)); } - State::Master => { - if pkt.priority == 0 { - actions.push(Action::ResetTimer(pkt.vrid)); - } else if pkt.priority > instance.config.priority - || (pkt.priority == instance.config.priority - // && check if primary IP of sender is greater than the local primary IP - ) { - actions.push(Action::ChangeState(pkt.vrid, State::Backup)); - } + } + State::Master => { + if packet.priority == 0 { + actions.push(Action::ResetTimer(packet.vrid)); + } else if packet.priority > instance.config.priority + || (packet.priority == instance.config.priority + // && check if primary IP of sender is greater than the local primary IP + ) { + actions.push(Action::ChangeState(packet.vrid, State::Backup)); } } } + return Ok(actions) +} + - // Execute collected actions +fn handle_actions(interface: &mut Interface, actions: Vec) { for action in actions { match action { Action::SendVrrpAdvert(vrid) => interface.send_vrrp_advert(vrid), @@ -84,7 +100,6 @@ pub(crate) fn process_packet( .build() .unwrap() .block_on(interface.send_gratuitous_arp(vrid)); - //interface.send_gratuitous_arp(vrid).await }, Action::ChangeState(vrid, state) => { if let Some(instance) = interface.instances.get_mut(&vrid) { @@ -103,6 +118,4 @@ pub(crate) fn process_packet( } } } - - Ok(()) } diff --git a/holo-vrrp/src/interface.rs b/holo-vrrp/src/interface.rs index f245afdb..84e9aeb2 100644 --- a/holo-vrrp/src/interface.rs +++ b/holo-vrrp/src/interface.rs @@ -54,7 +54,7 @@ pub struct InterfaceSys { // Interface IPv4 addresses. pub addresses: BTreeSet, // interface Mac Address - pub mac_address: Vec, + pub mac_address: [u8; 6], } #[derive(Debug)] @@ -135,14 +135,11 @@ impl Interface { target_proto_address: addr.ip().octets() }; - let mut mac_addr: &mut [u8; 6] = &mut [0u8; 6]; - for (idx, item) in self.system.mac_address.iter().enumerate() { - mac_addr[idx] = *item; - } + let mut mac_addr = self.system.mac_address.clone(); let eth_frame = EthernetFrame { ethertype: 0x806, dst_mac: [0xff; 6], - src_mac: *mac_addr + src_mac: mac_addr }; let _ = network::send_packet_arp( &self.net.socket_arp,