Skip to content

Commit

Permalink
vrrp: restructure of network call.
Browse files Browse the repository at this point in the history
Restructure the network calls for VRRP advert
to come down to layer 2 giving us more control
over how the header is defined.

We also reshape the `NetTxPacketMsg` in tasks to
carry the VrrpPacket instead of having a Vec<u8>
value.

Signed-off-by: Paul Wekesa <[email protected]>
  • Loading branch information
Paul-weqe committed Oct 9, 2024
1 parent d44da8a commit 6c849b3
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 82 deletions.
6 changes: 3 additions & 3 deletions holo-vrrp/src/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ use std::net::IpAddr;

use tracing::{debug, debug_span};

use crate::packet::VrrpPacket;
use crate::packet::VrrpHdr;

// VRRP debug messages.
#[derive(Debug)]
pub enum Debug<'a> {
InstanceCreate,
InstanceDelete,
// Network
PacketRx(&'a IpAddr, &'a VrrpPacket),
PacketTx(&'a IpAddr, &'a VrrpPacket),
PacketRx(&'a IpAddr, &'a VrrpHdr),
PacketTx(&'a IpAddr, &'a VrrpHdr),
}

// ===== impl Debug =====
Expand Down
12 changes: 6 additions & 6 deletions holo-vrrp/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,21 @@ use std::time::Duration;
use crate::error::{Error, IoError};
use crate::instance::State;
use crate::interface::Interface;
use crate::packet::{DecodeResult, VrrpPacket};
use crate::packet::{DecodeResult, VrrpHdr};
use crate::tasks;

// To collect actions to be executed later
enum VrrpAction {
Initialize(Ipv4Addr, VrrpPacket),
Backup(Ipv4Addr, VrrpPacket),
Master(Ipv4Addr, VrrpPacket),
Initialize(Ipv4Addr, VrrpHdr),
Backup(Ipv4Addr, VrrpHdr),
Master(Ipv4Addr, VrrpHdr),
}

// ===== Vrrp Network packet receipt =====
pub(crate) fn process_vrrp_packet(
interface: &mut Interface,
src_ip: Ipv4Addr,
packet: DecodeResult<VrrpPacket>,
packet: DecodeResult<VrrpHdr>,
) -> Result<(), Error> {
// Handle packet decoding errors
let pkt = match packet {
Expand Down Expand Up @@ -53,7 +53,7 @@ pub(crate) fn process_vrrp_packet(
fn get_vrrp_action(
interface: &mut Interface,
src_ip: Ipv4Addr,
packet: VrrpPacket,
packet: VrrpHdr,
) -> Result<VrrpAction, Error> {
// Handle missing instance
let instance = match interface.instances.get_mut(&packet.vrid) {
Expand Down
14 changes: 7 additions & 7 deletions holo-vrrp/src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use holo_utils::task::{IntervalTask, TimeoutTask};

use crate::interface::MacVlanInterface;
use crate::northbound::configuration::InstanceCfg;
use crate::packet::{ArpPacket, EthernetFrame, Ipv4Packet, VrrpPacket};
use crate::packet::{ArpPacket, EthernetHdr, Ipv4Packet, VrrpHdr};
use crate::tasks::messages::output::NetTxPacketMsg;

#[derive(Debug)]
Expand Down Expand Up @@ -146,13 +146,13 @@ impl Instance {
self.state.master_down_interval = master_down;
}

pub(crate) fn adver_vrrp_pkt(&self) -> VrrpPacket {
pub(crate) fn adver_vrrp_pkt(&self) -> VrrpHdr {
let mut ip_addresses: Vec<Ipv4Addr> = vec![];
for addr in self.config.virtual_addresses.clone() {
ip_addresses.push(addr.ip());
}

let mut packet = VrrpPacket {
let mut packet = VrrpHdr {
version: 2,
hdr_type: 1,
vrid: self.vrid,
Expand Down Expand Up @@ -195,8 +195,8 @@ impl Instance {
}
}

pub(crate) fn advert_ether_frame(&self) -> EthernetFrame {
EthernetFrame::vrrp(self.vrid)
pub(crate) fn advert_ether_frame(&self) -> EthernetHdr {
EthernetHdr::vrrp(self.vrid)
}

pub(crate) fn send_gratuitous_arp(&self) {
Expand All @@ -219,15 +219,15 @@ impl Instance {
target_proto_address: addr.ip().octets(),
};

let eth_frame = EthernetFrame {
let eth_hdr = EthernetHdr {
ethertype: 0x806,
dst_mac: [0xff; 6],
src_mac: self.mac_vlan.system.mac_address,
};

let msg = NetTxPacketMsg::Arp {
name: self.mac_vlan.name.clone(),
eth_frame,
eth_frame: eth_hdr,
arp_packet,
};

Expand Down
22 changes: 10 additions & 12 deletions holo-vrrp/src/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use tracing::{debug, debug_span, error_span};

use crate::error::{Error, IoError};
use crate::instance::{Instance, State};
use crate::packet::VrrpPacket;
use crate::tasks::messages::input::{MasterDownTimerMsg, VrrpNetRxPacketMsg};
use crate::tasks::messages::output::NetTxPacketMsg;
use crate::tasks::messages::{ProtocolInputMsg, ProtocolOutputMsg};
Expand Down Expand Up @@ -233,21 +234,18 @@ impl Interface {
{
let mut buf = BytesMut::new();

// ethernet frame
let eth_frame: &[u8] = &instance.advert_ether_frame().encode();
buf.put(eth_frame);

// ip packet
let ip_pkt: &[u8] = &instance.adver_ipv4_pkt(addr.ip()).encode();
buf.put(ip_pkt);

// vrrp packet
let vrrp_pkt: &[u8] = &instance.adver_vrrp_pkt().encode();
buf.put(vrrp_pkt);
let eth_hdr = instance.advert_ether_frame();
let ip_hdr = instance.adver_ipv4_pkt(addr.ip());
let vrrp_hdr = instance.adver_vrrp_pkt();
let pkt = VrrpPacket {
eth: eth_hdr,
ip: ip_hdr,
vrrp: vrrp_hdr,
};

let msg = NetTxPacketMsg::Vrrp {
ifname: instance.mac_vlan.name.clone(),
buf: buf.to_vec(),
pkt,
};
if let Some(net) = &instance.mac_vlan.net {
let _ = net.net_tx_packetp.send(msg);
Expand Down
42 changes: 12 additions & 30 deletions holo-vrrp/src/network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ use tracing::{debug, debug_span};

use crate::error::IoError;
use crate::interface::Interface;
use crate::packet::{ArpPacket, EthernetFrame, Ipv4Packet, VrrpPacket};
use crate::packet::VrrpPacket;
use crate::packet::{ArpPacket, EthernetHdr, Ipv4Packet, VrrpHdr};
use crate::tasks::messages::input::VrrpNetRxPacketMsg;
use crate::tasks::messages::output::NetTxPacketMsg;

Expand All @@ -37,24 +38,6 @@ pub fn socket_vrrp_tx(

capabilities::raise(|| sock.set_nonblocking(true))?;

// to be uncommented in due time.
//if let Some(addr) = instance.mac_vlan.system.addresses.first() {
// capabilities::raise(|| {
// match sock.set_multicast_if_v4(&addr.ip()) {
// Ok(_res) => {
// debug_span!("socket-vrrp").in_scope(|| {
// debug!("successfully joined multicast interface");
// });
// }
// Err(err) => {
// debug_span!("socket-vrrp").in_scope(|| {
// debug!(%addr, %err, "unable to join multicast interface");
// });
// }
// }
// });
//}

// Confirm if we should bind to the primary interface's address...
// bind it to the primary interface's name
capabilities::raise(|| {
Expand Down Expand Up @@ -118,15 +101,14 @@ pub fn socket_arp(ifname: &str) -> Result<Socket, std::io::Error> {
pub(crate) async fn send_packet_vrrp(
sock: &AsyncFd<Socket>,
ifname: &str,
buf: &[u8],
pkt: VrrpPacket,
) -> Result<usize, IoError> {
let c_ifname = CString::new(ifname).unwrap();

unsafe {
let ifindex = libc::if_nametoindex(c_ifname.as_ptr());
let mut sa = libc::sockaddr_ll {
sll_family: libc::AF_INET as u16,
sll_protocol: (ETH_P_IP as u16).to_be(),
sll_family: libc::AF_PACKET as u16,
sll_protocol: (112 as u16).to_be(),
sll_ifindex: ifindex as i32,
sll_hatype: 0,
sll_pkttype: 0,
Expand All @@ -138,6 +120,7 @@ pub(crate) async fn send_packet_vrrp(
*mut libc::sockaddr_ll,
*mut libc::sockaddr,
>(&mut sa);
let buf: &[u8] = &pkt.encode();

match libc::sendto(
sock.as_raw_fd(),
Expand All @@ -157,12 +140,12 @@ pub(crate) async fn send_packet_vrrp(
pub async fn send_packet_arp(
sock: &AsyncFd<Socket>,
ifname: &str,
eth_frame: EthernetFrame,
eth_frame: EthernetHdr,
arp_packet: ArpPacket,
) -> Result<usize, IoError> {
use std::ffi::CString;

use libc::{c_void, sendto, sockaddr, sockaddr_ll};
use libc::{c_void, sendto, sockaddr, sockaddr_ll, AF_INET};

use crate::packet::ARPframe;
let mut arpframe = ARPframe::new(eth_frame, arp_packet);
Expand All @@ -179,7 +162,7 @@ pub async fn send_packet_arp(
let ifindex = unsafe { libc::if_nametoindex(c_ifname.as_ptr()) };

let mut sa = sockaddr_ll {
sll_family: AF_PACKET as u16,
sll_family: AF_INET as u16,
sll_protocol: 0x806_u16.to_be(),
sll_ifindex: ifindex as i32,
sll_hatype: 0,
Expand Down Expand Up @@ -229,9 +212,9 @@ pub(crate) async fn write_loop(
) {
while let Some(msg) = net_tx_packetc.recv().await {
match msg {
NetTxPacketMsg::Vrrp { ifname, buf } => {
NetTxPacketMsg::Vrrp { ifname, pkt } => {
if let Err(error) =
send_packet_vrrp(&socket_vrrp, &ifname, &buf[..]).await
send_packet_vrrp(&socket_vrrp, &ifname, pkt).await
{
error.log();
}
Expand Down Expand Up @@ -277,8 +260,7 @@ pub(crate) async fn vrrp_read_loop(
let ip_pkt =
Ipv4Packet::decode(&data[0..ip_header_len])
.unwrap();
let vrrp_pkt =
VrrpPacket::decode(&data[ip_header_len..]);
let vrrp_pkt = VrrpHdr::decode(&data[ip_header_len..]);
Ok((ip_pkt.src_address, vrrp_pkt))
}
Err(errno) => Err(errno.into()),
Expand Down
28 changes: 23 additions & 5 deletions holo-vrrp/src/packet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ pub type DecodeResult<T> = Result<T, DecodeError>;
//
#[derive(Clone, Debug, Eq, PartialEq)]
#[derive(Deserialize, Serialize)]
pub struct VrrpPacket {
pub struct VrrpHdr {
pub version: u8,
pub hdr_type: u8,
pub vrid: u8,
Expand Down Expand Up @@ -113,7 +113,7 @@ pub struct ARPframe {
}

impl ARPframe {
pub fn new(eth_pkt: EthernetFrame, arp_pkt: ArpPacket) -> Self {
pub fn new(eth_pkt: EthernetHdr, arp_pkt: ArpPacket) -> Self {
Self {
dst_mac: eth_pkt.dst_mac,
src_mac: eth_pkt.src_mac,
Expand All @@ -135,7 +135,7 @@ impl ARPframe {

#[derive(Clone, Debug, Eq, PartialEq)]
#[derive(Deserialize, Serialize)]
pub struct EthernetFrame {
pub struct EthernetHdr {
pub dst_mac: [u8; 6],
pub src_mac: [u8; 6],
pub ethertype: u16,
Expand All @@ -155,6 +155,14 @@ pub struct ArpPacket {
pub target_proto_address: [u8; 4], // src ip
}

#[derive(Clone, Debug, Eq, PartialEq)]
#[derive(Deserialize, Serialize)]
pub struct VrrpPacket {
pub eth: EthernetHdr,
pub ip: Ipv4Packet,
pub vrrp: VrrpHdr,
}

#[derive(Debug, Eq, PartialEq)]
#[derive(Deserialize, Serialize)]
pub enum DecodeError {
Expand Down Expand Up @@ -185,7 +193,7 @@ impl DecodeError {

// ===== impl Packet =====

impl VrrpPacket {
impl VrrpHdr {
const MIN_PKT_LENGTH: usize = 16;
const MAX_PKT_LENGTH: usize = 80;
const MAX_IP_COUNT: usize = 16;
Expand Down Expand Up @@ -373,7 +381,7 @@ impl Ipv4Packet {
}
}

impl EthernetFrame {
impl EthernetHdr {
pub fn encode(&self) -> BytesMut {
let mut buf = BytesMut::new();
self.dst_mac.iter().for_each(|i| buf.put_u8(*i));
Expand Down Expand Up @@ -410,6 +418,16 @@ impl EthernetFrame {
}
}

impl VrrpPacket {
pub fn encode(&self) -> BytesMut {
let mut buf = BytesMut::with_capacity(130);
buf.put(self.eth.encode());
buf.put(self.ip.encode());
buf.put(self.vrrp.encode());
buf
}
}

impl ArpPacket {
pub fn encode(&self) -> BytesMut {
let mut buf = BytesMut::with_capacity(28);
Expand Down
Loading

0 comments on commit 6c849b3

Please sign in to comment.