diff --git a/vm/devices/net/gdma/src/bnic.rs b/vm/devices/net/gdma/src/bnic.rs index 6653e2f7ff..826f0cb645 100644 --- a/vm/devices/net/gdma/src/bnic.rs +++ b/vm/devices/net/gdma/src/bnic.rs @@ -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())?; diff --git a/vm/devices/net/gdma_defs/src/bnic.rs b/vm/devices/net/gdma_defs/src/bnic.rs index 7ec51d4a5f..07307e015f 100644 --- a/vm/devices/net/gdma_defs/src/bnic.rs +++ b/vm/devices/net/gdma_defs/src/bnic.rs @@ -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; @@ -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 { @@ -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() } } @@ -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 */ diff --git a/vm/devices/net/mana_driver/src/bnic_driver.rs b/vm/devices/net/mana_driver/src/bnic_driver.rs index a3cc4042c6..cd7727821e 100644 --- a/vm/devices/net/mana_driver/src/bnic_driver.rs +++ b/vm/devices/net/mana_driver/src/bnic_driver.rs @@ -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; @@ -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 { - 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, diff --git a/vm/devices/net/mana_driver/src/gdma_driver.rs b/vm/devices/net/mana_driver/src/gdma_driver.rs index be8fead775..cfa8c9565f 100644 --- a/vm/devices/net/mana_driver/src/gdma_driver.rs +++ b/vm/devices/net/mana_driver/src/gdma_driver.rs @@ -866,6 +866,14 @@ impl GdmaDriver { 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::() + size_of::(); + 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); diff --git a/vm/devices/net/mana_driver/src/mana.rs b/vm/devices/net/mana_driver/src/mana.rs index 983301508c..b0af0d8314 100644 --- a/vm/devices/net/mana_driver/src/mana.rs +++ b/vm/devices/net/mana_driver/src/mana.rs @@ -390,6 +390,12 @@ impl Vport { 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, diff --git a/vm/devices/net/net_mana/src/lib.rs b/vm/devices/net/net_mana/src/lib.rs index ec30448493..3d27012193 100644 --- a/vm/devices/net/net_mana/src/lib.rs +++ b/vm/devices/net/net_mana/src/lib.rs @@ -564,8 +564,7 @@ impl Endpoint for ManaEndpoint { } fn link_speed(&self) -> u64 { - // Hard code to 200Gbps until MANA supports querying this. - 200 * 1000 * 1000 * 1000 + self.vport.link_speed_bps() } } diff --git a/vm/devices/net/net_mana/src/test.rs b/vm/devices/net/net_mana/src/test.rs index 12ca34ba9c..f2bbe39342 100644 --- a/vm/devices/net/net_mana/src/test.rs +++ b/vm/devices/net/net_mana/src/test.rs @@ -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, }; let thing = ManaDevice::new(&driver, device, 1, 1, None).await.unwrap(); let _ = thing.new_vport(0, None, &dev_config).await.unwrap(); @@ -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();