use super::{
message::{Attribute, LinkMessage, RouteAttrMap, RouteAttrs},
IFLA_VXLAN_AGEING, IFLA_VXLAN_FLOWBASED, IFLA_VXLAN_GBP, IFLA_VXLAN_GROUP, IFLA_VXLAN_GROUP6,
IFLA_VXLAN_ID, IFLA_VXLAN_L2MISS, IFLA_VXLAN_L3MISS, IFLA_VXLAN_LEARNING, IFLA_VXLAN_LIMIT,
IFLA_VXLAN_LINK, IFLA_VXLAN_LOCAL, IFLA_VXLAN_LOCAL6, IFLA_VXLAN_PORT, IFLA_VXLAN_PORT_RANGE,
IFLA_VXLAN_PROXY, IFLA_VXLAN_RSC, IFLA_VXLAN_TOS, IFLA_VXLAN_TTL, IFLA_VXLAN_UDP_CSUM,
IFLA_VXLAN_UDP_ZERO_CSUM6_RX, IFLA_VXLAN_UDP_ZERO_CSUM6_TX,
};
pub const IFLA_BR_HELLO_TIME: u16 = 0x2;
pub const IFLA_BR_AGEING_TIME: u16 = 0x4;
pub const IFLA_BR_VLAN_FILTERING: u16 = 0x7;
pub const IFLA_BR_MCAST_SNOOPING: u16 = 0x17;
#[derive(Debug)]
pub enum Namespace {
Pid(i32),
Fd(i32),
}
#[derive(Default, Debug)]
pub struct VxlanAttrs {
pub id: u32,
pub group: Option<Vec<u8>>,
pub vtep_index: Option<u32>,
pub src_addr: Option<Vec<u8>>,
pub ttl: u8,
pub tos: u8,
pub learning: bool,
pub ageing: Option<u32>,
pub limit: Option<u32>,
pub port_range: Option<(u16, u16)>,
pub proxy: bool,
pub rsc: bool,
pub l2miss: bool,
pub l3miss: bool,
pub port: Option<u16>,
pub udp_csum: bool,
pub udp_zero_csum6_tx: bool,
pub udp_zero_csum6_rx: bool,
pub gbp: bool,
pub flow_based: bool,
}
#[derive(Debug)]
pub enum Kind {
Dummy(LinkAttrs),
Bridge {
attrs: LinkAttrs,
hello_time: Option<u32>,
ageing_time: Option<u32>,
vlan_filtering: Option<bool>,
multicast_snooping: Option<bool>,
},
Veth {
attrs: LinkAttrs,
peer_name: String,
peer_hw_addr: Option<Vec<u8>>,
peer_ns: Option<Namespace>,
},
Vxlan {
attrs: LinkAttrs,
vxlan_attrs: VxlanAttrs,
},
Wireguard(LinkAttrs),
GenericLink {
attrs: LinkAttrs,
link_type: String,
},
}
impl From<&[u8]> for Kind {
fn from(buf: &[u8]) -> Self {
let link_msg: LinkMessage = bincode::deserialize(buf).unwrap();
let attrs = RouteAttrs::from(&buf[link_msg.len()..]);
let mut base = LinkAttrs::from(link_msg);
let mut data = RouteAttrs::default();
for attr in attrs {
match attr.header.rta_type {
libc::IFLA_LINKINFO => {
for a in RouteAttrs::from(attr.payload.as_slice()) {
match a.header.rta_type {
libc::IFLA_INFO_KIND => base.link_type = a.payload.to_string().unwrap(),
libc::IFLA_INFO_DATA => data = RouteAttrs::from(a.payload.as_slice()),
_ => {}
}
}
}
libc::IFLA_ADDRESS => base.hw_addr = (*attr.payload).to_vec(),
libc::IFLA_IFNAME => base.name = attr.payload.to_string().unwrap(),
libc::IFLA_MTU => base.mtu = attr.payload.to_u32().unwrap(),
libc::IFLA_LINK => base.parent_index = attr.payload.to_i32().unwrap(),
libc::IFLA_MASTER => base.master_index = attr.payload.to_i32().unwrap(),
libc::IFLA_TXQLEN => base.tx_queue_len = attr.payload.to_i32().unwrap(),
libc::IFLA_IFALIAS => base.alias = attr.payload.to_string().unwrap(),
libc::IFLA_OPERSTATE => base.oper_state = attr.payload[0],
libc::IFLA_PHYS_SWITCH_ID => base.phys_switch_id = attr.payload.to_i32().unwrap(),
libc::IFLA_LINK_NETNSID => base.netns_id = attr.payload.to_i32().unwrap(),
libc::IFLA_GSO_MAX_SIZE => base.gso_max_size = attr.payload.to_u32().unwrap(),
libc::IFLA_GSO_MAX_SEGS => base.gso_max_segs = attr.payload.to_u32().unwrap(),
libc::IFLA_GRO_MAX_SIZE => base.gro_max_size = attr.payload.to_u32().unwrap(),
libc::IFLA_NUM_TX_QUEUES => base.num_tx_queues = attr.payload.to_i32().unwrap(),
libc::IFLA_NUM_RX_QUEUES => base.num_rx_queues = attr.payload.to_i32().unwrap(),
libc::IFLA_GROUP => base.group = attr.payload.to_u32().unwrap(),
_ => {}
}
}
match &base.link_type[..] {
"bridge" => {
let map = RouteAttrMap::from(&data);
Kind::Bridge {
attrs: base,
hello_time: map.get_u32(&IFLA_BR_HELLO_TIME),
ageing_time: map.get_u32(&IFLA_BR_AGEING_TIME),
vlan_filtering: map.get_bool(&IFLA_BR_VLAN_FILTERING),
multicast_snooping: map.get_bool(&IFLA_BR_MCAST_SNOOPING),
}
}
"veth" => Kind::Veth {
attrs: base,
peer_name: Default::default(),
peer_hw_addr: None,
peer_ns: None,
},
"vxlan" => {
let map = RouteAttrMap::from(&data);
Kind::Vxlan {
attrs: base,
vxlan_attrs: VxlanAttrs {
id: map.get_u32(&IFLA_VXLAN_ID).unwrap(),
group: map
.get_vec(&IFLA_VXLAN_GROUP)
.or(map.get_vec(&IFLA_VXLAN_GROUP6)),
vtep_index: map.get_u32(&IFLA_VXLAN_LINK),
src_addr: map
.get_vec(&IFLA_VXLAN_LOCAL)
.or(map.get_vec(&IFLA_VXLAN_LOCAL6)),
ttl: map.get_u8(&IFLA_VXLAN_TTL).unwrap_or_default(),
tos: map.get_u8(&IFLA_VXLAN_TOS).unwrap_or_default(),
learning: map.get_bool(&IFLA_VXLAN_LEARNING).unwrap(),
ageing: map.get_u32(&IFLA_VXLAN_AGEING),
limit: map.get_u32(&IFLA_VXLAN_LIMIT),
port_range: map.get_u16_tuple(&IFLA_VXLAN_PORT_RANGE),
proxy: map.get_bool(&IFLA_VXLAN_PROXY).unwrap_or_default(),
rsc: map.get_bool(&IFLA_VXLAN_RSC).unwrap_or_default(),
l2miss: map.get_bool(&IFLA_VXLAN_L2MISS).unwrap_or_default(),
l3miss: map.get_bool(&IFLA_VXLAN_L3MISS).unwrap_or_default(),
port: map.get_u16(&IFLA_VXLAN_PORT),
udp_csum: map.get_bool(&IFLA_VXLAN_UDP_CSUM).unwrap_or_default(),
udp_zero_csum6_tx: map
.get_bool(&IFLA_VXLAN_UDP_ZERO_CSUM6_TX)
.unwrap_or_default(),
udp_zero_csum6_rx: map
.get_bool(&IFLA_VXLAN_UDP_ZERO_CSUM6_RX)
.unwrap_or_default(),
gbp: map.get_bool(&IFLA_VXLAN_GBP).unwrap_or_default(),
flow_based: map.get_bool(&IFLA_VXLAN_FLOWBASED).unwrap_or_default(),
},
}
}
"wireguard" => Kind::Wireguard(base),
"dummy" => Kind::Dummy(base),
_ => Kind::GenericLink {
link_type: base.link_type.clone(),
attrs: base,
},
}
}
}
impl Kind {
pub fn into_boxed(self) -> Box<dyn Link> {
Box::new(self)
}
}
pub trait Link: Send {
fn link_type(&self) -> &str;
fn attrs(&self) -> &LinkAttrs;
fn attrs_mut(&mut self) -> &mut LinkAttrs;
fn kind(&self) -> &Kind;
}
impl<T: Link + ?Sized> Link for Box<T> {
fn link_type(&self) -> &str {
(**self).link_type()
}
fn attrs(&self) -> &LinkAttrs {
(**self).attrs()
}
fn attrs_mut(&mut self) -> &mut LinkAttrs {
(**self).attrs_mut()
}
fn kind(&self) -> &Kind {
(**self).kind()
}
}
#[derive(Debug, Default, Clone)]
pub struct LinkAttrs {
pub link_type: String,
pub index: i32,
pub name: String,
pub hw_addr: Vec<u8>,
pub mtu: u32,
pub flags: u32,
pub raw_flags: u32,
pub parent_index: i32,
pub master_index: i32,
pub tx_queue_len: i32,
pub alias: String,
pub prot_info: String,
pub oper_state: u8,
pub phys_switch_id: i32,
pub netns_id: i32,
pub gso_max_size: u32,
pub gso_max_segs: u32,
pub gro_max_size: u32,
pub vfs: String,
pub num_tx_queues: i32,
pub num_rx_queues: i32,
pub group: u32,
pub statistics: String,
}
impl LinkAttrs {
pub fn new(name: &str) -> Self {
Self {
name: name.to_string(),
..Default::default()
}
}
fn from(link_msg: LinkMessage) -> Self {
Self {
index: link_msg.index,
raw_flags: link_msg.flags,
..Default::default()
}
}
}
impl Link for Kind {
fn link_type(&self) -> &str {
match self {
Kind::Dummy(_) => "dummy",
Kind::Bridge { .. } => "bridge",
Kind::Veth { .. } => "veth",
Kind::Vxlan { .. } => "vxlan",
Kind::Wireguard(_) => "wireguard",
Kind::GenericLink {
attrs: _,
link_type,
} => link_type,
}
}
fn attrs(&self) -> &LinkAttrs {
match self {
Kind::Dummy(attrs) => attrs,
Kind::Bridge { attrs, .. } => attrs,
Kind::Veth { attrs, .. } => attrs,
Kind::Vxlan { attrs, .. } => attrs,
Kind::Wireguard(attrs) => attrs,
Kind::GenericLink { attrs, .. } => attrs,
}
}
fn attrs_mut(&mut self) -> &mut LinkAttrs {
match self {
Kind::Dummy(attrs) => attrs,
Kind::Bridge { attrs, .. } => attrs,
Kind::Veth { attrs, .. } => attrs,
Kind::Vxlan { attrs, .. } => attrs,
Kind::Wireguard(attrs) => attrs,
Kind::GenericLink { attrs, .. } => attrs,
}
}
fn kind(&self) -> &Kind {
self
}
}
impl Kind {
pub fn new_bridge(name: &str) -> Self {
Self::Bridge {
attrs: LinkAttrs::new(name),
hello_time: None,
ageing_time: None,
vlan_filtering: None,
multicast_snooping: None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
static NETLINK_MSG: [u8; 1752] = [
0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0C, 0x00, 0x03, 0x00, 0x64, 0x6F, 0x63, 0x6B, 0x65, 0x72, 0x30, 0x00, 0x08, 0x00,
0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05,
0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0xDC, 0x05, 0x00, 0x00,
0x08, 0x00, 0x32, 0x00, 0x44, 0x00, 0x00, 0x00, 0x08, 0x00, 0x33, 0x00, 0xFF, 0xFF, 0x00,
0x00, 0x08, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x1E, 0x00, 0x00, 0x00,
0x00, 0x00, 0x08, 0x00, 0x1F, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x28, 0x00, 0xFF,
0xFF, 0x00, 0x00, 0x08, 0x00, 0x29, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x20, 0x00,
0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x06,
0x00, 0x6E, 0x6F, 0x71, 0x75, 0x65, 0x75, 0x65, 0x00, 0x08, 0x00, 0x23, 0x00, 0x01, 0x00,
0x00, 0x00, 0x08, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x30, 0x00, 0x01,
0x00, 0x00, 0x00, 0x05, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x0E, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0A, 0x00, 0x01, 0x00, 0x02, 0x42, 0x3B, 0x14, 0xA7, 0x98, 0x00, 0x00, 0x0A,
0x00, 0x02, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xC4, 0x00, 0x17, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x07,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x2B, 0x00, 0x05, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00, 0xAC, 0x01, 0x12, 0x00, 0x0B, 0x00, 0x01, 0x00, 0x62, 0x72, 0x69,
0x64, 0x67, 0x65, 0x00, 0x00, 0x9C, 0x01, 0x02, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0C, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0C, 0x00, 0x13, 0x00, 0x71, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01,
0x00, 0xDC, 0x05, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x08, 0x00,
0x03, 0x00, 0xD0, 0x07, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x30, 0x75, 0x00, 0x00, 0x08,
0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x80, 0x00, 0x00,
0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0C, 0x00, 0x0B, 0x00, 0x80, 0x00, 0x02, 0x42, 0x3B, 0x14, 0xA7, 0x98, 0x0C, 0x00,
0x0A, 0x00, 0x80, 0x00, 0x02, 0x42, 0x3B, 0x14, 0xA7, 0x98, 0x06, 0x00, 0x0C, 0x00, 0x00,
0x00, 0x00, 0x00, 0x08, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x0E, 0x00,
0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x14,
0x00, 0x01, 0x80, 0xC2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x2E, 0x00, 0x00, 0x00,
0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x81, 0x00, 0x00, 0x00, 0x06,
0x00, 0x27, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00,
0x05, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x16, 0x00, 0x01, 0x00, 0x00,
0x00, 0x05, 0x00, 0x17, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x05, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00,
0x00, 0x00, 0x00, 0x08, 0x00, 0x1A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x1B, 0x00,
0x00, 0x10, 0x00, 0x00, 0x08, 0x00, 0x1C, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x1D,
0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x2B, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00,
0x2C, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x1E, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0C, 0x00, 0x1F, 0x00, 0x90, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0C, 0x00, 0x20, 0x00, 0x9C, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x21,
0x00, 0xD4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x22, 0x00, 0xE8, 0x03,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x23, 0x00, 0x34, 0x0C, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x05, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x25, 0x00,
0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x03, 0x1A,
0x00, 0x88, 0x00, 0x02, 0x00, 0x84, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x27, 0x00, 0x00, 0xE8, 0x03, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x80, 0x02, 0x0A, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14,
0x00, 0x05, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xC2, 0xC5, 0x77, 0x00, 0x0C, 0x89, 0x00, 0x00,
0xE8, 0x03, 0x00, 0x00, 0xE4, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
0x00, 0xDC, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xA0, 0x0F, 0x00, 0x00, 0xE8,
0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x80, 0x3A, 0x09, 0x00, 0x80, 0x51, 0x01, 0x00,
0x03, 0x00, 0x00, 0x00, 0x58, 0x02, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x60, 0xEA,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x27, 0x00, 0x00, 0xE8, 0x03, 0x00,
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, 0xEE, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x2C, 0x01, 0x03, 0x00, 0x25, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14,
0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
];
#[test]
fn test_link_deserialize() {
let link = Kind::from(NETLINK_MSG.as_slice());
assert_eq!(link.link_type(), "bridge");
let attrs = link.attrs();
assert_eq!(attrs.index, 4);
assert_eq!(attrs.name, "docker0");
assert_eq!(attrs.mtu, 1500);
assert_eq!(attrs.raw_flags, 0x1003);
match link.kind() {
Kind::Bridge {
attrs: _,
hello_time,
ageing_time,
vlan_filtering,
multicast_snooping,
} => {
assert_eq!(hello_time.unwrap(), 200);
assert_eq!(ageing_time.unwrap(), 30000);
assert!(!vlan_filtering.unwrap());
assert!(multicast_snooping.unwrap());
}
_ => panic!("Expected bridge link"),
}
}
}