Skip to content

Commit df62508

Browse files
[feature] ASIC-focused 1st draft of multicast PRE
Includes: * Multicast Group API management: add, modify, delete, reset, SSM handling * sidecar.p4 tofino_asic updates to integrate multicast packet replication * Table mangagement for ASIC switch tables for multicast * integration tests and test utility additions
1 parent 0dcd325 commit df62508

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+9515
-2793
lines changed

Cargo.lock

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ omicron-common = { git = "https://github.com/oxidecomputer/omicron", branch= "ma
3939
oximeter = { git = "https://github.com/oxidecomputer/omicron", branch = "main" }
4040
oximeter-producer = { git = "https://github.com/oxidecomputer/omicron", branch = "main" }
4141
oximeter-instruments = { git = "https://github.com/oxidecomputer/omicron", branch = "main", default-features = false, features = ["kstat"] }
42-
oxnet = { version = "0.1.0", default-features = false, features = ["schemars", "serde"] }
42+
oxnet = { version = "0.1.1", default-features = false, features = ["schemars", "serde"] }
4343
propolis = { git = "https://github.com/oxidecomputer/propolis" }
4444
sled-agent-client = { git = "https://github.com/oxidecomputer/omicron", branch = "main" }
4545
smf = { git = "https://github.com/illumos/smf-rs" }

aal/src/lib.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,21 @@ pub trait AsicOps {
200200
/// Destroy a multicast group.
201201
fn mc_group_destroy(&self, group_id: u16) -> AsicResult<()>;
202202

203+
/// Check if a multicast group exists.
204+
fn mc_group_exists(&self, group_id: u16) -> bool {
205+
self.mc_domains().contains(&group_id)
206+
}
207+
208+
/// Get the total number of multicast groups.
209+
fn mc_groups_count(&self) -> AsicResult<usize>;
210+
211+
/// Set the maximum number of multicast nodes.
212+
fn mc_set_max_nodes(
213+
&self,
214+
max_nodes: u32,
215+
max_link_aggregated_nodes: u32,
216+
) -> AsicResult<()>;
217+
203218
/// Get sidecar identifiers of the device being managed.
204219
fn get_sidecar_identifiers(&self) -> AsicResult<impl SidecarIdentifiers>;
205220

aal/src/match_action.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ impl MatchData {
7272
/// The MatchParse trait defines the behavior needed to convert a high-level
7373
/// Match field into our intermediate representation.
7474
pub trait MatchParse {
75-
/// Return all the name sand values of the key fields as strings
75+
/// Return all the names and values of the key fields as strings
7676
fn key_values(&self) -> BTreeMap<String, String>;
7777
/// Convert the key Struct to a MatchData struct
7878
fn key_to_ir(&self) -> AsicResult<MatchData>;

asic/src/chaos/mod.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,9 @@ impl TableChaos {
9494
(table::SWITCH_IPV4_ADDR, v),
9595
(table::SWITCH_IPV6_ADDR, v),
9696
(table::NAT_INGRESS_IPV4, v),
97-
(table::NAT_INGRESS_IPV6, v)
97+
(table::NAT_INGRESS_IPV6, v),
98+
(table::MCAST_IPV4_TABLE_NAME, v),
99+
(table::MCAST_IPV6_TABLE_NAME, v)
98100
)
99101
}
100102

@@ -141,6 +143,8 @@ pub struct AsicConfig {
141143
pub mc_port_remove: Chaos,
142144
pub mc_group_create: Chaos,
143145
pub mc_group_destroy: Chaos,
146+
pub mc_groups_count: Chaos,
147+
pub mc_set_max_nodes: Chaos,
144148
pub get_sidecar_identifiers: Chaos,
145149
pub table_new: TableChaos,
146150
pub table_clear: TableChaos,
@@ -177,6 +181,8 @@ impl AsicConfig {
177181
mc_port_remove: Chaos::new(v),
178182
mc_group_create: Chaos::new(v),
179183
mc_group_destroy: Chaos::new(v),
184+
mc_groups_count: Chaos::new(v),
185+
mc_set_max_nodes: Chaos::new(v),
180186
get_sidecar_identifiers: Chaos::new(v),
181187
table_new: TableChaos::uniform(v),
182188
table_clear: TableChaos::uniform(v),
@@ -203,6 +209,7 @@ impl AsicConfig {
203209
port_enable_get: Chaos::new(v),
204210
connector_avail_channels: Chaos::new(v),
205211
mc_port_count: Chaos::new(v),
212+
mc_groups_count: Chaos::new(v),
206213
get_sidecar_identifiers: Chaos::new(v),
207214
..Default::default()
208215
}
@@ -224,6 +231,7 @@ impl AsicConfig {
224231
mc_port_remove: Chaos::new(v),
225232
mc_group_create: Chaos::new(v),
226233
mc_group_destroy: Chaos::new(v),
234+
mc_set_max_nodes: Chaos::new(v),
227235
// TODO this can cause dpd to fail to start
228236
//table_clear: TableChaos::uniform(v),
229237
table_default_set: TableChaos::uniform(v),
@@ -496,6 +504,20 @@ impl AsicOps for Handle {
496504
Ok(())
497505
}
498506

507+
fn mc_groups_count(&self) -> AsicResult<usize> {
508+
unfurl!(self, mc_groups_count);
509+
Ok(self.ports.lock().unwrap().len())
510+
}
511+
512+
fn mc_set_max_nodes(
513+
&self,
514+
_max_nodes: u32,
515+
_max_link_aggregated_nodes: u32,
516+
) -> AsicResult<()> {
517+
unfurl!(self, mc_set_max_nodes);
518+
Ok(())
519+
}
520+
499521
fn get_sidecar_identifiers(&self) -> AsicResult<impl SidecarIdentifiers> {
500522
unfurl!(self, get_sidecar_identifiers);
501523
Ok(Identifiers::default())

asic/src/chaos/table.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ pub const SWITCH_IPV4_ADDR: &str = "pipe.Ingress.filter.switch_ipv4_addr";
2525
pub const SWITCH_IPV6_ADDR: &str = "pipe.Ingress.filter.switch_ipv6_addr";
2626
pub const NAT_INGRESS_IPV4: &str = "pipe.Ingress.nat_ingress.ingress_ipv4";
2727
pub const NAT_INGRESS_IPV6: &str = "pipe.Ingress.nat_ingress.ingress_ipv6";
28+
pub const MCAST_IPV4_TABLE_NAME: &str =
29+
"pipe.Ingress.multicast.mcast_route_ipv4";
30+
pub const MCAST_IPV6_TABLE_NAME: &str =
31+
"pipe.Ingress.multicast.mcast_route_ipv6";
2832

2933
pub struct Table {
3034
name: String,

asic/src/softnpu/mod.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,18 @@ impl AsicOps for Handle {
365365
Ok(())
366366
}
367367

368+
fn mc_groups_count(&self) -> AsicResult<usize> {
369+
Ok(self.ports.lock().unwrap().len())
370+
}
371+
372+
fn mc_set_max_nodes(
373+
&self,
374+
_max_nodes: u32,
375+
_max_link_aggregated_nodes: u32,
376+
) -> AsicResult<()> {
377+
Ok(())
378+
}
379+
368380
fn get_sidecar_identifiers(&self) -> AsicResult<impl SidecarIdentifiers> {
369381
Ok(Identifiers {
370382
id: Uuid::new_v4(),

asic/src/tofino_asic/imported_bf_functions

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,13 @@ bf_mc_create_session
2222
bf_mc_destroy_session
2323
bf_mc_mgrp_create
2424
bf_mc_mgrp_destroy
25+
bf_mc_mgrp_get_count
2526
bf_mc_node_create
2627
bf_mc_node_destroy
2728
bf_mc_node_update
2829
bf_mc_associate_node
2930
bf_mc_dissociate_node
31+
bf_mc_set_max_node_threshold
3032

3133
# bf_rt calls
3234
bf_rt_table_from_name_get

asic/src/tofino_asic/multicast.rs renamed to asic/src/tofino_asic/mcast.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,19 @@ fn mgrp_destroy(
8080
Ok(())
8181
}
8282

83+
fn mgrp_get_count(
84+
mcast_hdl: &Handle,
85+
dev_id: bf_dev_id_t,
86+
mut count: u32,
87+
) -> AsicResult<usize> {
88+
unsafe {
89+
bf_mc_mgrp_get_count(mcast_hdl.bf_get().mcast_hdl, dev_id, &mut count)
90+
.check_error("getting total count of multicast groups")?;
91+
}
92+
93+
Ok(count as usize)
94+
}
95+
8396
fn associate_node(
8497
mcast_hdl: bf_mc_session_hdl_t,
8598
dev_id: bf_dev_id_t,
@@ -166,6 +179,26 @@ fn cleanup_node(
166179
node_destroy(bf.mcast_hdl, bf.dev_id, port_state.node_hdl)
167180
}
168181

182+
fn set_max_node_threshold(
183+
mcast_hdl: bf_mc_session_hdl_t,
184+
dev_id: bf_dev_id_t,
185+
node_count: i32,
186+
node_port_lag_count: i32,
187+
) -> AsicResult<()> {
188+
unsafe {
189+
bf_mc_set_max_node_threshold(
190+
mcast_hdl,
191+
dev_id,
192+
node_count,
193+
node_port_lag_count,
194+
)
195+
.check_error("setting max node threshold")?;
196+
}
197+
198+
Ok(())
199+
}
200+
201+
/// All multicast domains.
169202
pub fn domains(hdl: &Handle) -> Vec<u16> {
170203
let mut list = Vec::new();
171204
let domains = hdl.domains.lock().unwrap();
@@ -190,6 +223,7 @@ fn domain_ports(domain: &DomainState) -> Vec<u16> {
190223
list
191224
}
192225

226+
/// Get the number of ports in a multicast domain.
193227
pub fn domain_port_count(hdl: &Handle, group_id: u16) -> AsicResult<usize> {
194228
let mut domains = hdl.domains.lock().unwrap();
195229
match domains.get_mut(&group_id) {
@@ -198,6 +232,7 @@ pub fn domain_port_count(hdl: &Handle, group_id: u16) -> AsicResult<usize> {
198232
}
199233
}
200234

235+
/// Add a port to a multicast domain.
201236
pub fn domain_add_port(
202237
hdl: &Handle,
203238
group_id: u16,
@@ -259,6 +294,7 @@ pub fn domain_add_port(
259294
}
260295
}
261296

297+
/// Remove a port from a multicast domain.
262298
pub fn domain_remove_port(
263299
hdl: &Handle,
264300
group_id: u16,
@@ -287,6 +323,7 @@ pub fn domain_remove_port(
287323
Ok(())
288324
}
289325

326+
/// Create a multicast domain.
290327
pub fn domain_create(hdl: &Handle, group_id: u16) -> AsicResult<()> {
291328
info!(hdl.log, "creating multicast domain {}", group_id);
292329
let mut domains = hdl.domains.lock().unwrap();
@@ -308,6 +345,7 @@ pub fn domain_create(hdl: &Handle, group_id: u16) -> AsicResult<()> {
308345
Ok(())
309346
}
310347

348+
/// Destroy a multicast domain.
311349
pub fn domain_destroy(hdl: &Handle, group_id: u16) -> AsicResult<()> {
312350
info!(hdl.log, "destroying multicast domain {}", group_id);
313351
let mut domains = hdl.domains.lock().unwrap();
@@ -333,3 +371,30 @@ pub fn domain_destroy(hdl: &Handle, group_id: u16) -> AsicResult<()> {
333371

334372
mgrp_destroy(bf.mcast_hdl, bf.dev_id, domain.mgrp_hdl)
335373
}
374+
375+
/// Domain exists.
376+
pub fn domain_exists(hdl: &Handle, group_id: u16) -> bool {
377+
let domains = hdl.domains.lock().unwrap();
378+
domains.contains_key(&group_id)
379+
}
380+
381+
/// Get the total number of multicast domains.
382+
pub fn domains_count(hdl: &Handle) -> AsicResult<usize> {
383+
let bf = hdl.bf_get();
384+
mgrp_get_count(hdl, bf.dev_id, 0)
385+
}
386+
387+
/// Set the maximum number of multicast nodes.
388+
pub fn set_max_nodes(
389+
hdl: &Handle,
390+
node_count: u32,
391+
node_port_lag_count: u32,
392+
) -> AsicResult<()> {
393+
let bf = hdl.bf_get();
394+
set_max_node_threshold(
395+
bf.mcast_hdl,
396+
bf.dev_id,
397+
node_count as i32,
398+
node_port_lag_count as i32,
399+
)
400+
}

asic/src/tofino_asic/mod.rs

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ mod bf_wrapper;
1919
mod genpd;
2020

2121
mod link_fsm;
22-
pub mod multicast;
22+
pub mod mcast;
2323
pub mod ports;
2424
pub mod qsfp;
2525
mod sde_log;
@@ -150,27 +150,43 @@ impl AsicOps for Handle {
150150
}
151151

152152
fn mc_domains(&self) -> Vec<u16> {
153-
multicast::domains(self)
153+
mcast::domains(self)
154154
}
155155

156156
fn mc_port_count(&self, group_id: u16) -> AsicResult<usize> {
157-
multicast::domain_port_count(self, group_id)
157+
mcast::domain_port_count(self, group_id)
158158
}
159159

160160
fn mc_port_add(&self, group_id: u16, port: u16) -> AsicResult<()> {
161-
multicast::domain_add_port(self, group_id, port)
161+
mcast::domain_add_port(self, group_id, port)
162162
}
163163

164164
fn mc_port_remove(&self, group_id: u16, port: u16) -> AsicResult<()> {
165-
multicast::domain_remove_port(self, group_id, port)
165+
mcast::domain_remove_port(self, group_id, port)
166166
}
167167

168168
fn mc_group_create(&self, group_id: u16) -> AsicResult<()> {
169-
multicast::domain_create(self, group_id)
169+
mcast::domain_create(self, group_id)
170170
}
171171

172172
fn mc_group_destroy(&self, group_id: u16) -> AsicResult<()> {
173-
multicast::domain_destroy(self, group_id)
173+
mcast::domain_destroy(self, group_id)
174+
}
175+
176+
fn mc_group_exists(&self, group_id: u16) -> bool {
177+
mcast::domain_exists(self, group_id)
178+
}
179+
180+
fn mc_groups_count(&self) -> AsicResult<usize> {
181+
mcast::domains_count(self)
182+
}
183+
184+
fn mc_set_max_nodes(
185+
&self,
186+
max_nodes: u32,
187+
max_link_aggregated_nodes: u32,
188+
) -> AsicResult<()> {
189+
mcast::set_max_nodes(self, max_nodes, max_link_aggregated_nodes)
174190
}
175191

176192
// Ideally we would get some sort of sidecar-level ID from the FRUID.
@@ -238,7 +254,7 @@ pub struct Handle {
238254
rt: tofino_common::BfRt,
239255
log: slog::Logger,
240256
phys_ports: Mutex<ports::PortData>,
241-
domains: Mutex<HashMap<u16, multicast::DomainState>>,
257+
domains: Mutex<HashMap<u16, mcast::DomainState>>,
242258
eth_connector_id: Option<u32>,
243259
}
244260

@@ -322,7 +338,7 @@ impl Handle {
322338

323339
// Note: we assume that bf_mc_init() has been called as part of the
324340
// bf_switch_init() operation.
325-
bf.mcast_hdl = multicast::create_session()?;
341+
bf.mcast_hdl = mcast::create_session()?;
326342

327343
Ok(Handle {
328344
dev_id,

0 commit comments

Comments
 (0)