Skip to content
Open
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
9 changes: 9 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ kstat-rs = "0.2.4"
lazy_static = "1.5"
libc = "0.2"
mockall = "0.14.0"
nonempty = "0.12.0"
omicron-zone-package = "0.12"
openssl = "0.10"
oxide-tokio-rt = "0.1.2"
Expand Down
6 changes: 3 additions & 3 deletions aal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,11 @@ pub enum AsicError {
Synthetic(String),
/// A general indication that a caller is trying to create something that
/// already exists.
#[error("Already exists")]
Exists,
#[error("Already exists: {}", .0)]
Exists(String),
/// A general indication that a caller is trying to modify something that
/// is not present.
#[error("Missing")]
#[error("Missing: {}", .0)]
Missing(String),
}

Expand Down
10 changes: 5 additions & 5 deletions asic/src/chaos/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ impl Chaos {

/// Return a chaos error according to the underlying probability value.
pub fn unfurled(&self, log: &Logger, message: &str) -> AsicResult<()> {
if self.value >= random() {
if self.value > random() {
slog::error!(log, "chaos error: {}", message);
return Err(AsicError::Synthetic(message.into()));
}
Expand Down Expand Up @@ -143,7 +143,7 @@ impl TableChaos {
message: &str,
) -> AsicResult<()> {
if let Some(value) = self.values.get(&id)
&& *value >= random()
&& *value > random()
{
slog::error!(log, "chaos table error: {}", message);
return Err(AsicError::Synthetic(message.into()));
Expand Down Expand Up @@ -407,7 +407,7 @@ impl AsicMulticastOps for Handle {
_level1_excl_id: u16,
) -> AsicResult<()> {
unfurl_mc!(self, mc_port_add);
Err(AsicError::OperationUnsupported)
Ok(())
}

fn mc_port_remove(&self, _group_id: u16, _port: u16) -> AsicResult<()> {
Expand All @@ -417,7 +417,7 @@ impl AsicMulticastOps for Handle {

fn mc_group_create(&self, _group_id: u16) -> AsicResult<()> {
unfurl_mc!(self, mc_group_create);
Err(AsicError::OperationUnsupported)
Ok(())
}

fn mc_group_destroy(&self, _group_id: u16) -> AsicResult<()> {
Expand Down Expand Up @@ -552,7 +552,7 @@ impl AsicOps for Handle {
// and use it as before.
let port_hdl = PortHdl::new(connector, 0);
if ports.contains_key(&port_hdl) {
return Err(AsicError::Exists);
return Err(AsicError::Exists(format!("port {port_hdl} exists")));
}
ports.insert(port_hdl, Port { enabled: true });
self.port_to_asic_id(port_hdl).map(|id| (port_hdl, id))
Expand Down
42 changes: 27 additions & 15 deletions asic/src/chaos/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,28 @@
//
// Copyright 2026 Oxide Computer Company

use std::collections::HashSet;
use std::collections::HashMap;
use std::collections::hash_map::DefaultHasher;
use std::hash::Hash;
use std::hash::Hasher;
use std::sync::Mutex;

use crate::chaos::{Handle, table_unfurl};
use aal::{
ActionParse, AsicError, AsicResult, CounterData, MatchParse, TableOps,
ActionData, ActionParse, AsicError, AsicResult, CounterData, MatchData,
MatchParse, TableOps,
};
use common::table::TableType;

pub struct Table {
type_: TableType,
keys: Mutex<HashSet<u64>>,
keys: Mutex<HashMap<u64, (MatchData, ActionData)>>,
}

impl TableOps<Handle> for Table {
fn new(hdl: &Handle, type_: TableType) -> AsicResult<Table> {
table_unfurl!(hdl, type_, table_new);
Ok(Table { type_, keys: Mutex::new(HashSet::new()) })
Ok(Table { type_, keys: Mutex::new(HashMap::new()) })
}

fn size(&self) -> usize {
Expand All @@ -39,46 +40,50 @@ impl TableOps<Handle> for Table {
fn clear(&self, hdl: &Handle) -> AsicResult<()> {
table_unfurl!(hdl, self.type_, table_clear);
let mut keys = self.keys.lock().unwrap();
*keys = HashSet::new();
*keys = HashMap::new();
Ok(())
}

fn entry_add<M: MatchParse + Hash, A: ActionParse>(
&self,
hdl: &Handle,
key: &M,
_data: &A,
data: &A,
) -> AsicResult<()> {
let mut hasher = DefaultHasher::new();
key.hash(&mut hasher);
let x: u64 = hasher.finish();

let mut keys = self.keys.lock().unwrap();
if keys.contains(&x) {
return Err(AsicError::Exists);
if keys.contains_key(&x) {
return Err(AsicError::Exists(format!(
"entry already in table {}",
self.type_
)));
}
table_unfurl!(hdl, self.type_, table_entry_add);
keys.insert(x);
keys.insert(x, (key.key_to_ir()?, data.action_to_ir()?));
Ok(())
}

fn entry_update<M: MatchParse + Hash, A: ActionParse>(
&self,
hdl: &Handle,
key: &M,
_data: &A,
data: &A,
) -> AsicResult<()> {
let mut hasher = DefaultHasher::new();
key.hash(&mut hasher);
let x: u64 = hasher.finish();

let keys = self.keys.lock().unwrap();
if !keys.contains(&x) {
let mut keys = self.keys.lock().unwrap();
let Some((_, action)) = keys.get_mut(&x) else {
return Err(AsicError::Missing(
"table entry not found".to_string(),
));
}
};
table_unfurl!(hdl, self.type_, table_entry_update);
*action = data.action_to_ir()?;
Ok(())
}

Expand All @@ -92,7 +97,7 @@ impl TableOps<Handle> for Table {
let x: u64 = hasher.finish();

let mut keys = self.keys.lock().unwrap();
if !keys.contains(&x) {
if !keys.contains_key(&x) {
return Err(AsicError::Missing(
"table entry not found".to_string(),
));
Expand All @@ -107,7 +112,14 @@ impl TableOps<Handle> for Table {
_hdl: &Handle,
_from_hardware: bool,
) -> AsicResult<Vec<(M, A)>> {
Err(AsicError::OperationUnsupported)
self.keys
.lock()
.unwrap()
.values()
.map(|(key, action)| {
Ok((M::ir_to_key(key)?, A::ir_to_action(action)?))
})
.collect()
}

fn get_counters<M: MatchParse>(
Expand Down
6 changes: 2 additions & 4 deletions asic/src/softnpu/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -338,9 +338,7 @@ impl AsicOps for Handle {
// and use it as before.
let port_hdl = PortHdl::new(connector, 0);
if ports.contains_key(&port_hdl) {
return Err(AsicError::InvalidArg(format!(
"Port {port_hdl:?} exists"
)));
return Err(AsicError::Exists(format!("Port {port_hdl:?} exists")));
}
ports.insert(port_hdl, Port { enabled: true, tx_eq: 0 });
self.port_to_asic_id(port_hdl).map(|id| (port_hdl, id))
Expand All @@ -349,7 +347,7 @@ impl AsicOps for Handle {
fn port_delete(&self, port_hdl: PortHdl) -> AsicResult<()> {
let mut ports = self.ports.lock().unwrap();
if !ports.contains_key(&port_hdl) {
return Err(AsicError::InvalidArg(format!(
return Err(AsicError::Missing(format!(
"Port {port_hdl:?} does not exist"
)));
}
Expand Down
1 change: 1 addition & 0 deletions asic/src/tofino_asic/imported_bf_functions
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ bf_mc_mgrp_destroy
bf_mc_mgrp_get_count
bf_mc_node_create
bf_mc_node_destroy
bf_mc_node_get_association
bf_mc_node_update
bf_mc_associate_node
bf_mc_dissociate_node
Expand Down
Loading
Loading