Skip to content
3 changes: 3 additions & 0 deletions vm/devices/net/gdma/src/bnic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,9 @@ impl BasicNic {
max_num_vports: self.vports.len() as u16,
reserved: 0,
max_num_eqs: 64,
adapter_mtu: 0,
reserved2: 0,
adapter_link_speed_mbps: 0,
};

write.write(resp.as_bytes())?;
Expand Down
19 changes: 19 additions & 0 deletions vm/devices/net/gdma_defs/src/bnic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ open_enum! {
}
}

pub const MANA_QUERY_DEV_CONFIG_REQUEST_V1: u16 = 1;
pub const MANA_QUERY_DEV_CONFIG_RESPONSE_V4: u16 = 4;
pub const MANA_VTL2_MOVE_FILTER_REQUEST_V2: u16 = 2;
pub const MANA_VTL2_MOVE_FILTER_RESPONSE_V1: u16 = 1;
pub const MANA_VTL2_ASSIGN_SERIAL_NUMBER_REQUEST_V1: u16 = 1;
Expand Down Expand Up @@ -73,6 +75,10 @@ pub struct ManaQueryDeviceCfgResp {
pub max_num_vports: u16,
pub reserved: u16,
pub max_num_eqs: u32,

pub adapter_mtu: u16,
pub reserved2: u16,
pub adapter_link_speed_mbps: u32,
}

impl std::fmt::Debug for ManaQueryDeviceCfgResp {
Expand All @@ -85,6 +91,9 @@ impl std::fmt::Debug for ManaQueryDeviceCfgResp {
.field("max_num_vports", &self.max_num_vports)
.field("reserved", &self.reserved)
.field("max_num_eqs", &self.max_num_eqs)
.field("adapter_mtu", &self.adapter_mtu)
.field("reserved2", &self.reserved2)
.field("adapter_link_speed_mbps", &self.adapter_link_speed_mbps)
.finish()
}
}
Expand All @@ -99,6 +108,16 @@ impl ManaQueryDeviceCfgResp {
pub fn cap_filter_state_query(&self) -> bool {
self.pf_cap_flags1.query_filter_state() != 0
}
/// Returns the adapter link speed in bits per second.
/// Falls back to a default of 200 Gbps when the hardware does not report
/// a link speed (OVL2 or lower responses return 0).
pub fn link_speed_bps(&self) -> u64 {
if self.adapter_link_speed_mbps > 0 {
self.adapter_link_speed_mbps as u64 * 1000 * 1000
} else {
200 * 1000 * 1000 * 1000
}
}
}

/* Query vPort Configuration */
Expand Down
9 changes: 7 additions & 2 deletions vm/devices/net/mana_driver/src/bnic_driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ use crate::resources::Resource;
use gdma_defs::GdmaDevId;
use gdma_defs::GdmaQueueType;
use gdma_defs::GdmaReqHdr;
use gdma_defs::bnic::MANA_QUERY_DEV_CONFIG_REQUEST_V1;
use gdma_defs::bnic::MANA_QUERY_DEV_CONFIG_RESPONSE_V4;
use gdma_defs::bnic::MANA_VTL2_ASSIGN_SERIAL_NUMBER_REQUEST_V1;
use gdma_defs::bnic::MANA_VTL2_ASSIGN_SERIAL_NUMBER_RESPONSE_V1;
use gdma_defs::bnic::MANA_VTL2_MOVE_FILTER_REQUEST_V2;
Expand Down Expand Up @@ -49,10 +51,13 @@ impl<'a, T: DeviceBacking> BnicDriver<'a, T> {

#[tracing::instrument(skip(self), level = "debug", err)]
pub async fn query_dev_config(&mut self) -> anyhow::Result<ManaQueryDeviceCfgResp> {
let resp: ManaQueryDeviceCfgResp = self
let (resp, _activity_id): (ManaQueryDeviceCfgResp, u32) = self
.gdma
.request(
.request_version(
ManaCommandCode::MANA_QUERY_DEV_CONFIG.0,
MANA_QUERY_DEV_CONFIG_REQUEST_V1,
ManaCommandCode::MANA_QUERY_DEV_CONFIG.0,
MANA_QUERY_DEV_CONFIG_RESPONSE_V4,
self.dev_id,
ManaQueryDeviceCfgReq {
mn_drv_cap_flags1: 0,
Expand Down
8 changes: 8 additions & 0 deletions vm/devices/net/mana_driver/src/gdma_driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -866,6 +866,14 @@ impl<T: DeviceBacking> GdmaDriver<T> {
activity_id = format!("{:#x}", hdr.activity_id),
"HWC request",
);
// Zero the response page for the expected response size before sending
// the request. This ensures that fields added in newer response versions
// read as zero when talking to an older socmana that does not populate
// them, rather than containing stale data.
let expected_resp_size = size_of::<GdmaRespHdr>() + size_of::<Resp>();
self.dma_buffer
.write_at(RESPONSE_PAGE * PAGE_SIZE, &vec![0u8; expected_resp_size]);

self.dma_buffer.write_obj(REQUEST_PAGE * PAGE_SIZE, &hdr);
self.dma_buffer
.write_obj(REQUEST_PAGE * PAGE_SIZE + size_of_val(&hdr), &req);
Expand Down
6 changes: 6 additions & 0 deletions vm/devices/net/mana_driver/src/mana.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,12 @@ impl<T: DeviceBacking> Vport<T> {
self.config.num_indirection_ent
}

/// Returns the adapter link speed in bits per second, as reported by the
/// device configuration.
pub fn link_speed_bps(&self) -> u64 {
self.inner.dev_config.link_speed_bps()
}

/// Creates a new event queue.
pub async fn new_eq(
&self,
Expand Down
3 changes: 1 addition & 2 deletions vm/devices/net/net_mana/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -564,8 +564,7 @@ impl<T: DeviceBacking> Endpoint for ManaEndpoint<T> {
}

fn link_speed(&self) -> u64 {
// Hard code to 200Gbps until MANA supports querying this.
200 * 1000 * 1000 * 1000
self.vport.link_speed_bps()
}
}

Expand Down
6 changes: 6 additions & 0 deletions vm/devices/net/net_mana/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,9 @@ async fn test_vport_with_query_filter_state(driver: DefaultDriver) {
max_num_vports: 1,
reserved: 0,
max_num_eqs: 64,
adapter_mtu: 0,
reserved2: 0,
adapter_link_speed_mbps: 0,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we have a variation of the test where this is getting populated with a non-zero value and then later it checks that the query returns the right link speed on the adapter?

};
let thing = ManaDevice::new(&driver, device, 1, 1, None).await.unwrap();
let _ = thing.new_vport(0, None, &dev_config).await.unwrap();
Expand Down Expand Up @@ -729,6 +732,9 @@ async fn test_endpoint(
max_num_vports: 1,
reserved: 0,
max_num_eqs: 64,
adapter_mtu: 0,
reserved2: 0,
adapter_link_speed_mbps: 0,
};
let thing = ManaDevice::new(&driver, device, 1, 1, None).await.unwrap();
let vport = thing.new_vport(0, None, &dev_config).await.unwrap();
Expand Down