Skip to content

Commit a6f5226

Browse files
committed
[opteadm] Add show-xde-underlay command.
This command only adds value for debugging and development purposes. It is unlikely to be of much value in the field. It is acutely useful for experimenting with different combinations of underlying macs, such as this Chelsio and Mellanox contraption: $ opteadm show-xde-underlay LINK MTU MAC mlxcx0 9000 6C:B3:11:88:AC:84 cxgbe1 9000 00:07:43:2F:E6:C8 Signed-off-by: Daniel Levin <daniel.levin@oxidecomputer.com>
1 parent cd7749d commit a6f5226

4 files changed

Lines changed: 83 additions & 0 deletions

File tree

bin/opteadm/src/bin/opteadm.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use opte::api::Ipv6Addr;
1717
use opte::api::MAJOR_VERSION;
1818
use opte::api::MacAddr;
1919
use opte::api::MulticastUnderlay;
20+
use opte::api::ReadXdeUnderlayResp;
2021
use opte::api::Vni;
2122
use opte::print::print_layer;
2223
use opte::print::print_list_layers;
@@ -228,6 +229,9 @@ enum Command {
228229
/// Clear xde underlay devices
229230
ClearXdeUnderlay,
230231

232+
/// Describe the underlay devices, if they exist.
233+
ShowXdeUnderlay,
234+
231235
/// Set a virtual-to-physical mapping
232236
SetV2P { vpc_ip: IpAddr, vpc_mac: MacAddr, underlay_ip: Ipv6Addr, vni: Vni },
233237

@@ -732,6 +736,18 @@ fn print_port(t: &mut impl Write, pi: PortInfo) -> std::io::Result<()> {
732736
Ok(())
733737
}
734738

739+
fn print_xde_underlay(resp: ReadXdeUnderlayResp) -> std::io::Result<()> {
740+
let mut t = TabWriter::new(std::io::stdout());
741+
writeln!(t, "LINK\tMTU\tMAC")?;
742+
743+
for dev in resp.devices {
744+
writeln!(t, "{}\t{}\t{}", dev.name, dev.mtu, dev.mac)?;
745+
}
746+
747+
t.flush()?;
748+
Ok(())
749+
}
750+
735751
fn main() -> anyhow::Result<()> {
736752
let cmd = Command::parse();
737753
let hdl = OpteHdl::open()?;
@@ -895,6 +911,11 @@ fn main() -> anyhow::Result<()> {
895911
let _ = hdl.clear_xde_underlay()?;
896912
}
897913

914+
Command::ShowXdeUnderlay => {
915+
let resp = hdl.read_xde_underlay()?;
916+
print_xde_underlay(resp)?;
917+
}
918+
898919
Command::RmFwRule { port, direction, id } => {
899920
let request = RemFwRuleReq { port_name: port, dir: direction, id };
900921
hdl.remove_firewall_rule(&request)?;

crates/opte-api/src/cmd.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,11 @@ pub enum OpteCmd {
8080
/// Requires that no XDE ports exist.
8181
ClearXdeUnderlay = 73,
8282

83+
/// Describe the XDE underlay devices. Probably only useful for development
84+
/// and debugging purposes, as the underlay devices will always be cxgbe0/1 on actual
85+
/// sleds, at least until Metro arrives.
86+
ReadXdeUnderlay = 74,
87+
8388
/// Set all external IP config for a port.
8489
SetExternalIps = 80,
8590

@@ -145,6 +150,7 @@ impl TryFrom<c_int> for OpteCmd {
145150
71 => Ok(Self::DeleteXde),
146151
72 => Ok(Self::SetXdeUnderlay),
147152
73 => Ok(Self::ClearXdeUnderlay),
153+
74 => Ok(Self::ReadXdeUnderlay),
148154
80 => Ok(Self::SetExternalIps),
149155
90 => Ok(Self::AllowCidr),
150156
91 => Ok(Self::RemoveCidr),
@@ -488,3 +494,21 @@ pub struct RuleDump {
488494
pub data_predicates: Vec<String>,
489495
pub action: String,
490496
}
497+
498+
/// Tack on 'Resp' to the name to avoid polluting
499+
/// the space of symbols in XDE-proper.
500+
#[derive(Debug, Default, Deserialize, Serialize)]
501+
pub struct XdeUnderlayDeviceResp {
502+
pub name: String,
503+
pub mac: MacAddr,
504+
pub mtu: u32,
505+
}
506+
507+
#[derive(Debug, Default, Deserialize, Serialize)]
508+
pub struct ReadXdeUnderlayResp {
509+
/// Today, the number of expected underlay devices is zero or two.
510+
/// It is convenient (and lazy) to simply report a possibly-empty list of them to userland.
511+
pub devices: Vec<XdeUnderlayDeviceResp>,
512+
}
513+
514+
impl CmdOk for ReadXdeUnderlayResp {}

lib/opte-ioctl/src/lib.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ use oxide_vpc::api::ListPortsResp;
4949
use oxide_vpc::api::McastSubscribeReq;
5050
use oxide_vpc::api::McastUnsubscribeAllReq;
5151
use oxide_vpc::api::McastUnsubscribeReq;
52+
use oxide_vpc::api::ReadXdeUnderlayResp;
5253
use oxide_vpc::api::RemFwRuleReq;
5354
use oxide_vpc::api::RemoveCidrReq;
5455
use oxide_vpc::api::RemoveCidrResp;
@@ -326,6 +327,14 @@ impl OpteHdl {
326327
run_cmd_ioctl(self.device.as_raw_fd(), cmd, None::<&()>)
327328
}
328329

330+
pub fn read_xde_underlay(&self) -> Result<ReadXdeUnderlayResp, Error> {
331+
run_cmd_ioctl(
332+
self.device.as_raw_fd(),
333+
OpteCmd::ReadXdeUnderlay,
334+
None::<&()>,
335+
)
336+
}
337+
329338
pub fn add_router_entry(
330339
&self,
331340
req: &AddRouterEntryReq,

xde/src/xde.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,8 +230,10 @@ use opte::api::NoResp;
230230
use opte::api::OpteCmd;
231231
use opte::api::OpteCmdIoctl;
232232
use opte::api::OpteError;
233+
use opte::api::ReadXdeUnderlayResp;
233234
use opte::api::SetXdeUnderlayReq;
234235
use opte::api::XDE_IOC_OPTE_CMD;
236+
use opte::api::XdeUnderlayDeviceResp;
235237
use opte::d_error::LabelBlock;
236238
use opte::ddi::kstat::KStatNamed;
237239
use opte::ddi::kstat::KStatProvider;
@@ -913,6 +915,28 @@ fn clear_xde_underlay_hdlr() -> Result<NoResp, OpteError> {
913915
clear_xde_underlay()
914916
}
915917

918+
#[unsafe(no_mangle)]
919+
fn read_xde_underlay_hdlr() -> Result<ReadXdeUnderlayResp, OpteError> {
920+
let state = get_xde_state();
921+
let xde_mgmt = state.management_lock.lock();
922+
923+
let mut resp = ReadXdeUnderlayResp::default();
924+
let mut report = |&XdeUnderlayPort { ref name, mac, mtu, .. }| {
925+
resp.devices.push(XdeUnderlayDeviceResp {
926+
name: name.clone(),
927+
mac: mac.into(),
928+
mtu,
929+
});
930+
};
931+
932+
if let Some(underlay) = &xde_mgmt.underlay {
933+
report(&underlay.u1);
934+
report(&underlay.u2);
935+
}
936+
937+
Ok(resp)
938+
}
939+
916940
// This is the entry point for all OPTE commands. It verifies the API
917941
// version and then multiplexes the command to its appropriate handler.
918942
#[unsafe(no_mangle)]
@@ -973,6 +997,11 @@ unsafe extern "C" fn xde_ioc_opte_cmd(karg: *mut c_void, mode: c_int) -> c_int {
973997
hdlr_resp(&mut env, resp)
974998
}
975999

1000+
OpteCmd::ReadXdeUnderlay => {
1001+
let resp = read_xde_underlay_hdlr();
1002+
hdlr_resp(&mut env, resp)
1003+
}
1004+
9761005
OpteCmd::DumpLayer => {
9771006
let resp = dump_layer_hdlr(&mut env);
9781007
hdlr_resp(&mut env, resp)

0 commit comments

Comments
 (0)