Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add counters #40

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
648 changes: 302 additions & 346 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion book/code/src/bin/hello-world.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#![allow(clippy::needless_update)]
use std::sync::{Arc, Mutex};
use tests::expect_frames;
use tests::softnpu::{RxFrame, SoftNpu, TxFrame};

Expand All @@ -8,7 +9,8 @@ p4_macro::use_p4!(
);

fn main() -> Result<(), anyhow::Error> {
let mut npu = SoftNpu::new(2, main_pipeline::new(2), false);
let mut npu =
SoftNpu::new(2, Arc::new(Mutex::new(main_pipeline::new(2))), false);
let phy1 = npu.phy(0);
let phy2 = npu.phy(1);

Expand Down
3 changes: 2 additions & 1 deletion book/code/src/bin/vlan-switch.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#![allow(clippy::needless_update)]
use std::sync::{Arc, Mutex};
use tests::expect_frames;
use tests::softnpu::{RxFrame, SoftNpu, TxFrame};

Expand Down Expand Up @@ -50,7 +51,7 @@ fn run_test(
m3: [u8; 6],
) -> Result<(), anyhow::Error> {
// create and run the softnpu instance
let mut npu = SoftNpu::new(2, pipeline, false);
let mut npu = SoftNpu::new(2, Arc::new(Mutex::new(pipeline)), false);
let phy1 = npu.phy(0);
let phy2 = npu.phy(1);
npu.run();
Expand Down
50 changes: 47 additions & 3 deletions codegen/rust/src/control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ impl<'a> ControlGenerator<'a> {

fn generate_top_level_control(&mut self, control: &Control) {
let tables = control.tables(self.ast);

for (cs, t) in tables {
let qtn = qualified_table_function_name(Some(control), &cs, t);
let qtfn = qualified_table_function_name(Some(control), &cs, t);
Expand Down Expand Up @@ -324,10 +325,32 @@ impl<'a> ControlGenerator<'a> {
>
};

let mut externs = quote! {};

for var in &control.variables {
if let Type::UserDefined(typename) = &var.ty {
if self.ast.get_extern(typename).is_some() {
let extern_name = format_ident!("{}", var.name);
let extern_type = format_ident!("{}", typename);
externs.extend(quote! {
let #extern_name = p4rs::externs::#extern_type::new();
})
}
}
}

let mut tokens = quote! {
#externs
let mut #table_name: #table_type = #table_type::new();
};

if let Some(lval) = &table.counter {
let counter_name = format_ident!("{}", lval.name);
tokens.extend(quote! {
#table_name.counter = Some(#counter_name);
});
}

if table.const_entries.is_empty() {
tokens.extend(quote! { #table_name });
return (table_type, tokens);
Expand Down Expand Up @@ -400,6 +423,15 @@ impl<'a> ControlGenerator<'a> {
action_fn_args.push(quote! { #a });
}

for var in &control.variables {
if let Type::UserDefined(typename) = &var.ty {
if self.ast.get_extern(typename).is_some() {
let name = format_ident!("{}", var.name);
action_fn_args.push(quote! { #name });
}
}
}

let action_fn_name =
format_ident!("{}_action_{}", control.name, entry.action.name);
for (i, expr) in entry.action.parameters.iter().enumerate() {
Expand Down Expand Up @@ -451,6 +483,15 @@ impl<'a> ControlGenerator<'a> {
closure_params.push(quote! { #name });
}

for var in &control.variables {
if let Type::UserDefined(typename) = &var.ty {
if self.ast.get_extern(typename).is_some() {
let name = format_ident!("{}", var.name);
closure_params.push(quote! { #name });
}
}
}

tokens.extend(quote! {

let action: std::sync::Arc<dyn Fn(#(#control_param_types),*)> =
Expand Down Expand Up @@ -494,9 +535,12 @@ impl<'a> ControlGenerator<'a> {
if self.ast.get_extern(typename).is_some() {
let name = format_ident!("{}", var.name);
let extern_type = format_ident!("{}", typename);
tokens.extend(quote! {
let #name = p4rs::externs::#extern_type::new();
})
//FIXME terrible hack
if typename == "Checksum" {
tokens.extend(quote! {
let #name = p4rs::externs::#extern_type::new();
})
}
}
}
}
Expand Down
67 changes: 67 additions & 0 deletions codegen/rust/src/pipeline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,16 @@ impl<'a> PipelineGenerator<'a> {

let add_table_entry_method =
self.add_table_entry_method(ingress, egress);

let remove_table_entry_method =
self.remove_table_entry_method(ingress, egress);

let get_table_entries_method =
self.get_table_entries_method(ingress, egress);

let get_table_counters_method =
self.get_table_counters_method(ingress, egress);

let get_table_ids_method = self.get_table_ids_method(ingress, egress);

let table_modifiers = self.table_modifiers(ingress, egress);
Expand Down Expand Up @@ -156,6 +162,7 @@ impl<'a> PipelineGenerator<'a> {
#add_table_entry_method
#remove_table_entry_method
#get_table_entries_method
#get_table_counters_method
#get_table_ids_method
}

Expand Down Expand Up @@ -654,6 +661,43 @@ impl<'a> PipelineGenerator<'a> {
}
}

fn get_table_counters_method(
&mut self,
ingress: &Control,
egress: &Control,
) -> TokenStream {
let mut body = TokenStream::new();
for control in &[ingress, egress] {
let tables = control.tables(self.ast);
for (cs, table) in tables.iter() {
if table.counter.is_none() {
continue;
}
let qtn = qualified_table_name(Some(control), cs, table);
let qtfn =
qualified_table_function_name(Some(control), cs, table);
let call = format_ident!("get_{}_counters", qtfn);
body.extend(quote! {
#qtn => Some(self.#call()),
});
}
}
body.extend(quote! {
x => None,
});

quote! {
fn get_table_counters(
&self,
table_id: &str,
) -> Option<p4rs::externs::TableEntryCounter> {
match table_id {
#body
}
}
}
}

fn table_modifiers(
&mut self,
ingress: &Control,
Expand Down Expand Up @@ -689,6 +733,13 @@ impl<'a> PipelineGenerator<'a> {
table_control,
&qtfn,
));
if table.counter.is_some() {
tokens.extend(self.get_table_counters_function(
table,
table_control,
&qtfn,
));
}
}
}

Expand Down Expand Up @@ -1046,6 +1097,22 @@ impl<'a> PipelineGenerator<'a> {
}
}

fn get_table_counters_function(
&mut self,
_table: &Table,
_control: &Control,
qtfn: &str,
) -> TokenStream {
let name = format_ident!("get_{}_counters", qtfn);
let tname = format_ident!("{}", qtfn);

quote! {
pub fn #name(&self) -> p4rs::externs::TableEntryCounter {
self.#tname.counter.clone().unwrap()
}
}
}

pub(crate) fn parse_entrypoint(
&mut self,
parser: &Parser,
Expand Down
24 changes: 23 additions & 1 deletion codegen/rust/src/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -495,11 +495,24 @@ impl<'a> StatementGenerator<'a> {
let name = format_ident!("{}", var.name);
if let Type::UserDefined(typename) = &var.ty {
if self.ast.get_extern(typename).is_some() {
action_args.push(quote! { &#name });
//FIXME terrible hack
if typename == "Checksum" {
action_args.push(quote! { &#name });
}
}
}
}

if table.counter.is_some() {
action_args.push(quote! {
&#table_name
.counter
.as_ref()
.unwrap()
.set_key(matches[0].key_bytes())
});
}

let mut selector_components = Vec::new();
for (lval, _match_kind) in &table.key {
let lvref: Vec<TokenStream> = lval
Expand Down Expand Up @@ -542,6 +555,15 @@ impl<'a> StatementGenerator<'a> {
}
});
if table.default_action != "NoAction" {
if table.counter.is_some() {
action_args.pop();
action_args.push(quote! {
&#table_name
.counter
.as_ref()
.unwrap()
});
}
tokens.extend(quote! {
else {
softnpu_provider::control_table_miss!(||#table_name_str);
Expand Down
19 changes: 19 additions & 0 deletions dtrace/drop-monitor.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
::parser_accepted {
printf("%s", copyinstr(arg0));
}

::control_table_miss {
printf("%s", copyinstr(arg0));
}

::match_miss {
printf("%s", copyinstr(arg0));
}

::parser_dropped {
printf("parser dropped\n");
}

::ingress_dropped {
printf("ingress dropped\n");
}
5 changes: 0 additions & 5 deletions lang/p4rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,7 @@ edition = "2021"

[dependencies]
num = { version = "0.4", features = ["serde"] }
slog = { version = "2.7", features = ["max_level_trace"] }
slog-term = "2.9"
slog-async = "2.7"
slog-envlogger = "2.2"
bitvec = "1.0"
colored = "2.0"
usdt.workspace = true
serde = "1.0"
serde_json = "1.0"
Expand Down
58 changes: 29 additions & 29 deletions lang/p4rs/src/checksum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,35 @@ pub fn udp6_checksum(data: &[u8]) -> u16 {
csum.result()
}

pub trait Checksum {
fn csum(&self) -> BitVec<u8, Msb0>;
}

fn bvec_csum(bv: &BitVec<u8, Msb0>) -> BitVec<u8, Msb0> {
let x: u128 = bv.load();
let buf = x.to_be_bytes();
let mut c: u16 = 0;
for i in (0..16).step_by(2) {
c += u16::from_be_bytes([buf[i], buf[i + 1]])
}
let c = !c;
let mut result = bitvec![u8, Msb0; 0u8, 16];
result.store(c);
result
}

impl Checksum for BitVec<u8, Msb0> {
fn csum(&self) -> BitVec<u8, Msb0> {
bvec_csum(self)
}
}

impl Checksum for &BitVec<u8, Msb0> {
fn csum(&self) -> BitVec<u8, Msb0> {
bvec_csum(self)
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down Expand Up @@ -126,32 +155,3 @@ mod tests {
assert_eq!(x, y);
}
}

pub trait Checksum {
fn csum(&self) -> BitVec<u8, Msb0>;
}

fn bvec_csum(bv: &BitVec<u8, Msb0>) -> BitVec<u8, Msb0> {
let x: u128 = bv.load();
let buf = x.to_be_bytes();
let mut c: u16 = 0;
for i in (0..16).step_by(2) {
c += u16::from_be_bytes([buf[i], buf[i + 1]])
}
let c = !c;
let mut result = bitvec![u8, Msb0; 0u8, 16];
result.store(c);
result
}

impl Checksum for BitVec<u8, Msb0> {
fn csum(&self) -> BitVec<u8, Msb0> {
bvec_csum(self)
}
}

impl Checksum for &BitVec<u8, Msb0> {
fn csum(&self) -> BitVec<u8, Msb0> {
bvec_csum(self)
}
}
Loading