Skip to content

Commit a3f94ef

Browse files
[multicast] Wire softnpu backend to multicast management protocol
## Changes This connect dendrite's AsicMulticastOps implementation for the softnpu backend to softnpu's multicast management messages. Previously, all four operations (mc_group_create, mc_group_destroy, mc_port_add, mc_port_remove) returned OperationUnsupported or were silent no-ops, as softnpu wasn't hooked up as of yet. We wire each method through mgmt::write using the corresponding ManagementRequest variant (MulticastGroupCreate, MulticastGroupRemove, MulticastPortAdd, MulticastPortRemove). Query methods (mc_domains, mc_port_count, mc_groups_count) now issue a MulticastGroupList round-trip to softnpu for accurate state rather than returning placeholder port counts. We also update mgmt::read to return a typed ManagementResponse instead of a raw String, and fix the existing RadixRequest caller to match. ## Deps This PR points the softnpu-lib dependency to the zl/multicast branch which provides the multicast management message types.
1 parent e8a6811 commit a3f94ef

4 files changed

Lines changed: 88 additions & 28 deletions

File tree

Cargo.lock

Lines changed: 16 additions & 4 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
@@ -54,7 +54,7 @@ oximeter-instruments = { git = "https://github.com/oxidecomputer/omicron", branc
5454
oxnet = { version = "0.1.4", default-features = false, features = ["schemars", "serde"] }
5555
propolis = { git = "https://github.com/oxidecomputer/propolis" }
5656
smf = { git = "https://github.com/illumos/smf-rs" }
57-
softnpu-lib = { git = "https://github.com/oxidecomputer/softnpu" , package = "softnpu" , branch = "main"}
57+
softnpu-lib = { git = "https://github.com/oxidecomputer/softnpu" , package = "softnpu" , branch = "zl/multicast"}
5858
tofino = { git = "https://github.com/oxidecomputer/tofino", branch = "main" }
5959
transceiver-controller = { git = "https://github.com/oxidecomputer/transceiver-control", branch = "main" }
6060

asic/src/softnpu/mgmt.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use std::io::Read;
99
use std::io::Write;
1010

1111
use propolis::hw::virtio::softnpu::{MANAGEMENT_MESSAGE_PREAMBLE, SOFTNPU_TTY};
12-
use softnpu_lib::ManagementRequest;
12+
use softnpu_lib::{ManagementRequest, ManagementResponse};
1313
use std::os::unix::net::UnixDatagram;
1414

1515
type ParseError = &'static str;
@@ -56,12 +56,16 @@ pub fn write(msg: ManagementRequest, config: &ManagementConfig) {
5656
}
5757
}
5858

59-
/// Read a management request response from a SoftNPU asic.
60-
pub fn read(msg: ManagementRequest, config: &ManagementConfig) -> String {
61-
match config {
59+
/// Send a management request and deserialize the response.
60+
pub fn read(
61+
msg: ManagementRequest,
62+
config: &ManagementConfig,
63+
) -> serde_json::Result<ManagementResponse> {
64+
let raw = match config {
6265
ManagementConfig::UART => read_uart(msg),
6366
ManagementConfig::UDS { socket_path } => read_uds(msg, socket_path),
64-
}
67+
};
68+
serde_json::from_str(&raw)
6569
}
6670

6771
fn write_uart(msg: ManagementRequest) {

asic/src/softnpu/mod.rs

Lines changed: 62 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,13 @@ use aal::{
2525
use common::ports::{
2626
PortFec, PortId, PortMedia, PortPrbsMode, PortSpeed, TxEq,
2727
};
28+
#[cfg(feature = "multicast")]
29+
use softnpu_lib::ManagementResponse;
2830

29-
use softnpu_lib::ManagementRequest;
31+
use softnpu_lib::{
32+
ManagementRequest, MulticastGroupCreate, MulticastGroupRemove,
33+
MulticastPortAdd, MulticastPortRemove,
34+
};
3035

3136
pub mod mgmt;
3237
pub mod table;
@@ -143,43 +148,80 @@ impl Handle {
143148
}
144149

145150
pub fn fini(&self) {}
151+
152+
/// Query softnpu for the current multicast group membership table.
153+
#[cfg(feature = "multicast")]
154+
fn mc_group_list(&self) -> std::collections::BTreeMap<u16, Vec<u16>> {
155+
match mgmt::read(
156+
ManagementRequest::MulticastGroupList,
157+
&self.mgmt_config,
158+
) {
159+
Ok(ManagementResponse::MulticastGroupListResponse(groups)) => {
160+
groups
161+
}
162+
_ => std::collections::BTreeMap::new(),
163+
}
164+
}
146165
}
147166

148167
#[cfg(feature = "multicast")]
149168
impl AsicMulticastOps for Handle {
150169
fn mc_domains(&self) -> Vec<u16> {
151-
let len = self.ports.lock().unwrap().len() as u16;
152-
(0..len).collect()
170+
let groups = self.mc_group_list();
171+
groups.keys().copied().collect()
153172
}
154173

155-
fn mc_port_count(&self, _group_id: u16) -> AsicResult<usize> {
156-
Ok(self.ports.lock().unwrap().len())
174+
fn mc_port_count(&self, group_id: u16) -> AsicResult<usize> {
175+
let groups = self.mc_group_list();
176+
Ok(groups.get(&group_id).map_or(0, |ports| ports.len()))
157177
}
158178

159179
fn mc_port_add(
160180
&self,
161-
_group_id: u16,
162-
_port: u16,
163-
_rid: u16,
164-
_level1_excl_id: u16,
181+
group_id: u16,
182+
port: u16,
183+
rid: u16,
184+
level1_excl_id: u16,
165185
) -> AsicResult<()> {
166-
Err(AsicError::OperationUnsupported)
186+
let msg = ManagementRequest::MulticastPortAdd(MulticastPortAdd {
187+
group_id,
188+
port,
189+
rid,
190+
level1_excl_id,
191+
});
192+
mgmt::write(msg, &self.mgmt_config);
193+
Ok(())
167194
}
168195

169-
fn mc_port_remove(&self, _group_id: u16, _port: u16) -> AsicResult<()> {
196+
fn mc_port_remove(&self, group_id: u16, port: u16) -> AsicResult<()> {
197+
let msg = ManagementRequest::MulticastPortRemove(MulticastPortRemove {
198+
group_id,
199+
port,
200+
});
201+
mgmt::write(msg, &self.mgmt_config);
170202
Ok(())
171203
}
172204

173-
fn mc_group_create(&self, _group_id: u16) -> AsicResult<()> {
174-
Err(AsicError::OperationUnsupported)
205+
fn mc_group_create(&self, group_id: u16) -> AsicResult<()> {
206+
let msg =
207+
ManagementRequest::MulticastGroupCreate(MulticastGroupCreate {
208+
group_id,
209+
});
210+
mgmt::write(msg, &self.mgmt_config);
211+
Ok(())
175212
}
176213

177-
fn mc_group_destroy(&self, _group_id: u16) -> AsicResult<()> {
214+
fn mc_group_destroy(&self, group_id: u16) -> AsicResult<()> {
215+
let msg =
216+
ManagementRequest::MulticastGroupRemove(MulticastGroupRemove {
217+
group_id,
218+
});
219+
mgmt::write(msg, &self.mgmt_config);
178220
Ok(())
179221
}
180222

181223
fn mc_groups_count(&self) -> AsicResult<usize> {
182-
Ok(self.ports.lock().unwrap().len())
224+
Ok(self.mc_group_list().len())
183225
}
184226

185227
fn mc_set_max_nodes(
@@ -354,11 +396,13 @@ impl AsicOps for Handle {
354396
fn get_connectors(&self) -> Vec<Connector> {
355397
let msg = ManagementRequest::RadixRequest;
356398
crate::softnpu::mgmt::write(msg, &self.mgmt_config);
357-
let response = crate::softnpu::mgmt::read(
399+
let radix: u16 = match crate::softnpu::mgmt::read(
358400
ManagementRequest::RadixRequest,
359401
&self.mgmt_config,
360-
);
361-
let radix: u16 = response.trim().parse().unwrap();
402+
) {
403+
Ok(softnpu_lib::ManagementResponse::RadixResponse(r)) => r,
404+
other => panic!("unexpected RadixRequest response: {other:?}"),
405+
};
362406

363407
let mut result = vec![Connector::CPU];
364408
for i in 1..radix + 1 {

0 commit comments

Comments
 (0)