use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
use crate::netlink::error::{Error, Result};
#[repr(C)]
#[derive(Debug, Clone, Copy, Default, FromBytes, IntoBytes, Immutable, KnownLayout)]
pub struct NhMsg {
pub nh_family: u8,
pub nh_scope: u8,
pub nh_protocol: u8,
pub resvd: u8,
pub nh_flags: u32,
}
impl NhMsg {
pub const SIZE: usize = std::mem::size_of::<Self>();
pub fn new() -> Self {
Self::default()
}
pub fn with_family(mut self, family: u8) -> Self {
self.nh_family = family;
self
}
pub fn with_scope(mut self, scope: u8) -> Self {
self.nh_scope = scope;
self
}
pub fn with_protocol(mut self, protocol: u8) -> Self {
self.nh_protocol = protocol;
self
}
pub fn with_flags(mut self, flags: u32) -> Self {
self.nh_flags = flags;
self
}
pub fn as_bytes(&self) -> &[u8] {
<Self as IntoBytes>::as_bytes(self)
}
pub fn from_bytes(data: &[u8]) -> Result<&Self> {
Self::ref_from_prefix(data)
.map(|(r, _)| r)
.map_err(|_| Error::Truncated {
expected: Self::SIZE,
actual: data.len(),
})
}
}
#[repr(C)]
#[derive(Debug, Clone, Copy, Default, FromBytes, IntoBytes, Immutable, KnownLayout)]
pub struct NexthopGrp {
pub id: u32,
pub weight: u8,
pub resvd1: u8,
pub resvd2: u16,
}
impl NexthopGrp {
pub const SIZE: usize = std::mem::size_of::<Self>();
pub fn new(id: u32, weight: u8) -> Self {
Self {
id,
weight,
resvd1: 0,
resvd2: 0,
}
}
pub fn as_bytes(&self) -> &[u8] {
<Self as IntoBytes>::as_bytes(self)
}
pub fn from_bytes(data: &[u8]) -> Option<&Self> {
Self::ref_from_prefix(data).map(|(r, _)| r).ok()
}
}
pub mod nha {
pub const UNSPEC: u16 = 0;
pub const ID: u16 = 1;
pub const GROUP: u16 = 2;
pub const GROUP_TYPE: u16 = 3;
pub const BLACKHOLE: u16 = 4;
pub const OIF: u16 = 5;
pub const GATEWAY: u16 = 6;
pub const ENCAP_TYPE: u16 = 7;
pub const ENCAP: u16 = 8;
pub const GROUPS: u16 = 9;
pub const MASTER: u16 = 10;
pub const FDB: u16 = 11;
pub const RES_GROUP: u16 = 12;
pub const RES_BUCKET: u16 = 13;
}
pub mod nhg_type {
pub const MPATH: u16 = 0;
pub const RES: u16 = 1;
}
pub mod nhf {
pub const ONLINK: u32 = 1;
pub const DEAD: u32 = 2;
pub const LINKDOWN: u32 = 4;
}
pub mod nha_res_group {
pub const UNSPEC: u16 = 0;
pub const BUCKETS: u16 = 1;
pub const IDLE_TIMER: u16 = 2;
pub const UNBALANCED_TIMER: u16 = 3;
pub const UNBALANCED_TIME: u16 = 4;
}
pub mod nha_res_bucket {
pub const UNSPEC: u16 = 0;
pub const PAD: u16 = 1;
pub const INDEX: u16 = 2;
pub const IDLE_TIME: u16 = 3;
pub const NH_ID: u16 = 4;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_nhmsg_size() {
assert_eq!(NhMsg::SIZE, 8);
}
#[test]
fn test_nexthop_grp_size() {
assert_eq!(NexthopGrp::SIZE, 8);
}
#[test]
fn test_nhmsg_builder() {
let msg = NhMsg::new()
.with_family(libc::AF_INET as u8)
.with_protocol(4) .with_flags(nhf::ONLINK);
assert_eq!(msg.nh_family, libc::AF_INET as u8);
assert_eq!(msg.nh_protocol, 4);
assert_eq!(msg.nh_flags, nhf::ONLINK);
}
#[test]
fn test_nexthop_grp() {
let grp = NexthopGrp::new(42, 10);
assert_eq!(grp.id, 42);
assert_eq!(grp.weight, 10);
assert_eq!(grp.resvd1, 0);
assert_eq!(grp.resvd2, 0);
}
}