use zerocopy::{U32, FromBytes};
use volatile::Volatile;
use byteorder::BigEndian;
use core::fmt;
use num_enum::TryFromPrimitive;
#[derive(Debug, TryFromPrimitive)]
#[repr(u8)]
pub(crate) enum FlowTableType {
NicRx = 0x0,
NicTx = 0x1
}
#[derive(FromBytes, Default)]
#[repr(C, packed)]
pub(crate) struct FlowTableContext {
pub(crate) log_size: Volatile<U32<BigEndian>>,
}
const _: () = assert!(core::mem::size_of::<FlowTableContext>() == 4);
impl fmt::Debug for FlowTableContext {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("FlowTableContext")
.field("log_size", &self.log_size.read().get())
.finish()
}
}
impl FlowTableContext {
pub(crate) fn init(num_entries: u32) -> FlowTableContext {
let mut ctxt = FlowTableContext::default();
let log_size = libm::log2(num_entries as f64) as u32;
ctxt.log_size.write(U32::new(log_size));
ctxt
}
pub(crate) fn mailbox_offset() -> usize { 0x8 }
}
#[derive(Debug, TryFromPrimitive)]
#[repr(u8)]
pub(crate) enum MatchCriteriaEnable {
None = 0,
OuterHeaders = 1 << 0,
MiscParameters = 1 << 1,
InnerHeader = 1 << 2
}
#[derive(FromBytes, Default)]
#[repr(C, packed)]
pub(crate) struct FlowGroupInput {
pub(crate) table_type: Volatile<U32<BigEndian>>,
pub(crate) table_id: Volatile<U32<BigEndian>>,
_padding1: u32,
pub(crate) start_flow_index: Volatile<U32<BigEndian>>,
_padding2: u32,
pub(crate) end_flow_index: Volatile<U32<BigEndian>>,
_padding3: [u8; 20],
pub(crate) match_criteria_enable: Volatile<U32<BigEndian>>,
}
const _: () = assert!(core::mem::size_of::<FlowGroupInput>() == 48);
impl FlowGroupInput {
pub(crate) fn init(
table_type: FlowTableType,
table_id: u32,
start_flow_index: u32,
end_flow_index: u32,
match_criteria_enable: MatchCriteriaEnable
) -> FlowGroupInput {
let mut fgi = FlowGroupInput::default();
fgi.table_type.write(U32::new((table_type as u32) << 24));
fgi.table_id.write(U32::new(table_id & 0xFF_FFFF));
fgi.start_flow_index.write(U32::new(start_flow_index));
fgi.end_flow_index.write(U32::new(end_flow_index));
fgi.match_criteria_enable.write(U32::new(match_criteria_enable as u32));
fgi
}
pub(crate) fn mailbox_offset() -> usize { 0 }
}
impl fmt::Debug for FlowGroupInput {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("FlowTableContext")
.field("table_type", &self.table_type.read().get())
.field("table_id", &self.table_id.read().get())
.field("start_flow_index", &self.start_flow_index.read().get())
.field("end_flow_index", &self.end_flow_index.read().get())
.field("match_criteria_enable", &self.match_criteria_enable.read().get())
.finish()
}
}
#[derive(FromBytes, Default)]
#[repr(C, packed)]
pub(crate) struct FlowEntryInput {
pub(crate) table_type: Volatile<U32<BigEndian>>,
pub(crate) table_id: Volatile<U32<BigEndian>>,
_padding1: [u8; 8],
pub(crate) flow_index: Volatile<U32<BigEndian>>,
_padding2: [u8; 28]
}
const _: () = assert!(core::mem::size_of::<FlowEntryInput>() == 48);
impl FlowEntryInput {
pub(crate) fn init(table_type: FlowTableType, table_id: u32, flow_index: u32) -> FlowEntryInput {
let mut fei = FlowEntryInput::default();
fei.table_type.write(U32::new((table_type as u32) << 24));
fei.table_id.write(U32::new(table_id & 0xFF_FFFF));
fei.flow_index.write(U32::new(flow_index));
fei
}
pub(crate) fn mailbox_offset() -> usize { 0 }
}
#[derive(Debug, TryFromPrimitive)]
#[repr(u32)]
pub(crate) enum FlowContextAction {
None = 0,
Allow = 1 << 0,
Drop = 1 << 1,
FwdDest = 1 << 2,
Count = 1 << 3,
Reformat = 1 << 4,
Decap = 1 << 5,
}
#[derive(FromBytes)]
#[repr(C, packed)]
pub(crate) struct FlowContext {
_padding1: u32,
pub(crate) group_id: Volatile<U32<BigEndian>>,
_padding2: u32,
pub(crate) action: Volatile<U32<BigEndian>>,
pub(crate) dest_list_size: Volatile<U32<BigEndian>>,
_padding3: [u8; 20]
}
const _: () = assert!(core::mem::size_of::<FlowContext>() == 40);
impl Default for FlowContext {
fn default() -> FlowContext {
FlowContext {
_padding1: 0,
group_id: Volatile::new(U32::new(0)),
_padding2: 0,
action: Volatile::new(U32::new(0)),
dest_list_size: Volatile::new(U32::new(0)),
_padding3: [0; 20]
}
}
}
impl FlowContext {
pub(crate) fn init(group_id: u32, action: FlowContextAction, dest_list_size: u32) -> FlowContext {
let mut ctxt = FlowContext::default();
ctxt.group_id.write(U32::new(group_id));
ctxt.action.write(U32::new(action as u32));
ctxt.dest_list_size.write(U32::new(dest_list_size));
ctxt
}
pub(crate) fn mailbox_offset() -> usize { 0x30 }
}
#[derive(Debug, TryFromPrimitive)]
#[repr(u8)]
pub(crate) enum DestinationType {
VPort = 0x0,
FlowTable = 0x1,
Tir = 0x2,
Qp = 0x3,
FlowSampler = 0x6,
}
#[derive(FromBytes, Default)]
#[repr(C, packed)]
pub(crate) struct DestinationEntry {
pub(crate) id_and_type: Volatile<U32<BigEndian>>,
pub(crate) packet_reformat: Volatile<U32<BigEndian>>,
}
const _: () = assert!(core::mem::size_of::<DestinationEntry>() == 8);
impl DestinationEntry {
pub(crate) fn init(dest_type: DestinationType, dest_id: u32) -> DestinationEntry {
let mut entry = DestinationEntry::default();
entry.id_and_type.write(U32::new((dest_type as u32) << 24 | (dest_id & 0xFF_FFFF)));
entry
}
}