use bytemuck::{Pod, Zeroable};
pub mod mask {
pub const VER: u32 = 0xf000_0000;
pub const VLAN: u32 = 0x0fff_0000;
pub const COS: u32 = 0x0000_e000;
pub const EN: u32 = 0x0000_1800;
pub const T: u32 = 0x0000_0400;
pub const SESS: u32 = 0x0000_03ff;
pub const RSVD: u32 = 0xfff0_0000;
pub const INDX: u32 = 0x000f_ffff;
}
pub mod shift {
pub const VER: u32 = 28;
pub const VLAN: u32 = 16;
pub const COS: u32 = 13;
pub const EN: u32 = 11;
pub const T: u32 = 10;
pub const RSVD: u32 = 20;
}
pub mod version {
pub const ERSPAN2: u8 = 1;
}
#[derive(Default, Debug, Copy, Clone)]
pub enum Encap {
NoVlan = 0,
IslStripped = 1,
VlanStripped = 2,
#[default]
TagPreserved = 3,
}
#[repr(C, packed(1))]
#[derive(Debug, Copy, Clone)]
pub struct Erspan2 {
ver: u8,
vlan: u16,
cos: u8,
en: Encap,
t: bool,
sess_id: u16,
rsvd: u16,
index: u32,
}
impl Default for Erspan2 {
fn default() -> Self {
Self {
ver: version::ERSPAN2,
vlan: 0,
cos: 0,
en: Encap::default(),
t: false,
sess_id: 0,
rsvd: 0,
index: 0,
}
}
}
impl Erspan2 {
pub fn ver(mut self, ver: u8) -> Self {
self.ver = ver;
self
}
pub fn session_id(mut self, sess_id: u16) -> Self {
self.sess_id = sess_id;
self
}
pub fn port_index(mut self, port_index: u32) -> Self {
self.index = port_index;
self
}
pub fn build(self) -> erspan2_hdr {
self.into()
}
pub fn flags_word(&self) -> u32 {
(self.sess_id as u32 & mask::SESS)
| ((self.t as u32) << shift::T) & mask::T
| ((self.en as u32) << shift::EN) & mask::EN
| ((self.cos as u32) << shift::COS) & mask::COS
| ((self.vlan as u32) << shift::VLAN) & mask::VLAN
| ((self.ver as u32) << shift::VER) & mask::VER
}
pub fn index_word(&self) -> u32 {
(self.index & mask::INDX) | ((self.rsvd as u32) << shift::RSVD) & mask::RSVD
}
}
#[repr(C, packed(1))]
#[derive(Pod, Zeroable, Default, Debug, Copy, Clone)]
pub struct erspan2_hdr {
pub flags: u32,
pub index: u32,
}
impl From<Erspan2> for erspan2_hdr {
fn from(s: Erspan2) -> Self {
Self::new(s.flags_word(), s.index_word())
}
}
impl erspan2_hdr {
pub fn new(flags: u32, index: u32) -> Self {
Self {
flags: flags.to_be(),
index: index.to_be(),
}
}
pub fn init(&mut self) -> &mut Self {
*self = Default::default();
self
}
pub fn flags(&mut self, flags: u32) -> &mut Self {
self.flags = flags.to_be();
self
}
pub fn get_flags(&self) -> u32 {
u32::from_be(self.flags)
}
pub fn index(&mut self, index: u32) -> &mut Self {
self.flags = index.to_be();
self
}
pub fn get_index(&self) -> u32 {
u32::from_be(self.index)
}
}