Snap for 11973804 from 7db013bca868b5fe8e7086c761cd156a3f28573a to 24Q3-release Change-Id: I1af176ea5ce1feac3975650324a9f840b8442342
diff --git a/Android.bp b/Android.bp index 5ae785a..0d5654e 100644 --- a/Android.bp +++ b/Android.bp
@@ -145,14 +145,14 @@ genrule { name: "netsim_netlink_rust_gen", - defaults: ["pdl_rust_legacy_generator_defaults"], + defaults: ["pdl_rust_generator_defaults"], srcs: ["pdl/netlink.pdl"], out: ["netlink_packets.rs"], } genrule { name: "netsim_mac80211_hwsim_rust_gen", - defaults: ["pdl_rust_legacy_generator_defaults"], + defaults: ["pdl_rust_generator_defaults"], srcs: ["pdl/mac80211_hwsim.pdl"], out: ["mac80211_hwsim_packets.rs"], }
diff --git a/pdl/CMakeLists.txt b/pdl/CMakeLists.txt index 1f32cb6..4f1cedf 100644 --- a/pdl/CMakeLists.txt +++ b/pdl/CMakeLists.txt
@@ -10,7 +10,7 @@ OUTPUT netlink_packets.rs LANG - rust_legacy) + rust) pdl_gen( NAME @@ -20,7 +20,7 @@ OUTPUT mac80211_hwsim_packets.rs LANG - rust_legacy) + rust) pdl_gen( NAME
diff --git a/rust/daemon/src/devices/devices_handler.rs b/rust/daemon/src/devices/devices_handler.rs index 5ad92eb..1707751 100644 --- a/rust/daemon/src/devices/devices_handler.rs +++ b/rust/daemon/src/devices/devices_handler.rs
@@ -577,7 +577,7 @@ .map_err(|e| anyhow::anyhow!("{e:?}")) } -fn reset_all() -> Result<(), String> { +pub fn reset_all() -> Result<(), String> { let manager = get_manager(); // Perform reset for all manager for device in manager.devices.read().unwrap().values() { @@ -627,8 +627,7 @@ } } -/// Performs ListDevices to get the list of DeviceManager and write to writer. -fn handle_device_list(writer: ResponseWritable) { +pub fn list_device() -> anyhow::Result<ListDeviceResponse, String> { // Instantiate ListDeviceResponse and add DeviceManager let mut response = ListDeviceResponse::new(); let manager = get_manager(); @@ -645,7 +644,12 @@ ..Default::default() }) .into(); + Ok(response) +} +/// Performs ListDevices to get the list of DeviceManager and write to writer. +fn handle_device_list(writer: ResponseWritable) { + let response = list_device().unwrap(); // Perform protobuf-json-mapping with the given protobuf if let Ok(json_response) = print_to_string_with_options(&response, &JSON_PRINT_OPTION) { writer.put_ok("text/json", &json_response, vec![])
diff --git a/rust/daemon/src/ffi.rs b/rust/daemon/src/ffi.rs index f9b14f4..4caf77a 100644 --- a/rust/daemon/src/ffi.rs +++ b/rust/daemon/src/ffi.rs
@@ -253,6 +253,14 @@ #[namespace = "netsim::wifi"] fn HandleWifiRequestCxx(chip_id: u32, packet: &Vec<u8>); + #[rust_name = hostapd_send] + #[namespace = "netsim::wifi"] + fn HostapdSendCxx(chip_id: u32, packet: &Vec<u8>); + + #[rust_name = libslirp_send] + #[namespace = "netsim::wifi"] + fn LibslirpSendCxx(chip_id: u32, packet: &Vec<u8>); + #[namespace = "netsim::wifi"] pub fn libslirp_main_loop_wait();
diff --git a/rust/daemon/src/grpc_server/frontend.rs b/rust/daemon/src/grpc_server/frontend.rs index 692ffcb..912df98 100644 --- a/rust/daemon/src/grpc_server/frontend.rs +++ b/rust/daemon/src/grpc_server/frontend.rs
@@ -12,64 +12,71 @@ // See the License for the specific language governing permissions and // limitations under the License. +use crate::devices::devices_handler; use futures_util::{FutureExt as _, TryFutureExt as _}; -use grpcio::{RpcContext, UnarySink}; +use grpcio::{RpcContext, RpcStatus, RpcStatusCode, UnarySink}; +use log::warn; use netsim_proto::frontend::VersionResponse; use netsim_proto::frontend_grpc::FrontendService; +use protobuf::well_known_types::empty::Empty; #[derive(Clone)] pub struct FrontendClient; impl FrontendService for FrontendClient { - fn get_version( - &mut self, - ctx: RpcContext<'_>, - req: protobuf::well_known_types::empty::Empty, - sink: UnarySink<VersionResponse>, - ) { - let response = VersionResponse { - version: "netsim test server version 0.0.1".to_string(), - ..Default::default() - }; + fn get_version(&mut self, ctx: RpcContext<'_>, req: Empty, sink: UnarySink<VersionResponse>) { + let response = + VersionResponse { version: crate::version::get_version(), ..Default::default() }; let f = sink .success(response) - .map_err(move |e| eprintln!("failed to reply {:?}: {:?}", req, e)) + .map_err(move |e| eprintln!("client error {:?}: {:?}", req, e)) .map(|_| ()); ctx.spawn(f) } fn list_device( &mut self, - _ctx: grpcio::RpcContext, - _req: protobuf::well_known_types::empty::Empty, - _sink: grpcio::UnarySink<netsim_proto::frontend::ListDeviceResponse>, + ctx: grpcio::RpcContext, + req: Empty, + sink: grpcio::UnarySink<netsim_proto::frontend::ListDeviceResponse>, ) { - todo!() + let response = match devices_handler::list_device() { + Ok(response) => sink.success(response), + Err(e) => { + warn!("failed to list device: {}", e); + sink.fail(RpcStatus::with_message(RpcStatusCode::INTERNAL, e)) + } + }; + + ctx.spawn(response.map_err(move |e| warn!("client error {:?}: {:?}", req, e)).map(|_| ())) } fn patch_device( &mut self, _ctx: grpcio::RpcContext, _req: netsim_proto::frontend::PatchDeviceRequest, - _sink: grpcio::UnarySink<protobuf::well_known_types::empty::Empty>, + _sink: grpcio::UnarySink<Empty>, ) { todo!() } - fn reset( - &mut self, - _ctx: grpcio::RpcContext, - _req: protobuf::well_known_types::empty::Empty, - _sink: grpcio::UnarySink<protobuf::well_known_types::empty::Empty>, - ) { - todo!() + fn reset(&mut self, ctx: grpcio::RpcContext, _req: Empty, sink: grpcio::UnarySink<Empty>) { + let response = match devices_handler::reset_all() { + Ok(_) => sink.success(Empty::new()), + Err(e) => { + warn!("failed to reset: {}", e); + sink.fail(RpcStatus::with_message(RpcStatusCode::INTERNAL, e)) + } + }; + + ctx.spawn(response.map_err(move |e| warn!("client error: {:?}", e)).map(|_| ())) } fn patch_capture( &mut self, _ctx: grpcio::RpcContext, _req: netsim_proto::frontend::PatchCaptureRequest, - _sink: grpcio::UnarySink<protobuf::well_known_types::empty::Empty>, + _sink: grpcio::UnarySink<Empty>, ) { todo!() } @@ -77,7 +84,7 @@ fn list_capture( &mut self, _ctx: grpcio::RpcContext, - _req: protobuf::well_known_types::empty::Empty, + _req: Empty, _sink: grpcio::UnarySink<netsim_proto::frontend::ListCaptureResponse>, ) { todo!()
diff --git a/rust/daemon/src/ranging.rs b/rust/daemon/src/ranging.rs index 9abd718..18bc6f7 100644 --- a/rust/daemon/src/ranging.rs +++ b/rust/daemon/src/ranging.rs
@@ -108,9 +108,9 @@ /// UWB Ranging Model for computing range, azimuth, and elevation /// The raning model brought from https://github.com/google/pica #[allow(unused)] -pub fn compute_range_azimuth_elevation(a: &Pose, b: &Pose) -> anyhow::Result<(u16, i16, i8)> { +pub fn compute_range_azimuth_elevation(a: &Pose, b: &Pose) -> anyhow::Result<(f32, i16, i8)> { let delta = b.position - a.position; - let distance = delta.length(); + let distance = delta.length().clamp(0.0, u16::MAX as f32); let direction = a.orientation.mul_vec3(delta); let azimuth = azimuth(direction).to_degrees().round(); let elevation = elevation(direction).to_degrees().round(); @@ -121,7 +121,7 @@ if !(-90. ..=90.).contains(&elevation) { return Err(anyhow::anyhow!("elevation is not between -90 and 90. value: {elevation}")); } - Ok((f32::min(distance, u16::MAX as f32) as u16, azimuth as i16, elevation as i8)) + Ok((distance, azimuth as i16, elevation as i8)) } #[cfg(test)] @@ -162,22 +162,22 @@ { let b_pose = Pose::new(10.0, 0.0, 0.0, 0.0, 0.0, 0.0); let (range, _, _) = compute_range_azimuth_elevation(&a_pose, &b_pose).unwrap(); - assert_eq!(range, 1000); + assert_eq!(range, 1000.); } { let b_pose = Pose::new(-10.0, 0.0, 0.0, 0.0, 0.0, 0.0); let (range, _, _) = compute_range_azimuth_elevation(&a_pose, &b_pose).unwrap(); - assert_eq!(range, 1000); + assert_eq!(range, 1000.); } { let b_pose = Pose::new(10.0, 10.0, 0.0, 0.0, 0.0, 0.0); let (range, _, _) = compute_range_azimuth_elevation(&a_pose, &b_pose).unwrap(); - assert_eq!(range, f32::sqrt(2000000.).round() as u16); + assert_eq!(range, f32::sqrt(2000000.)); } { let b_pose = Pose::new(-10.0, -10.0, -10.0, 0.0, 0.0, 0.0); let (range, _, _) = compute_range_azimuth_elevation(&a_pose, &b_pose).unwrap(); - assert_eq!(range, f32::sqrt(3000000.).round() as u16); + assert_eq!(range, f32::sqrt(3000000.)); } }
diff --git a/rust/daemon/src/uwb/ranging_data.rs b/rust/daemon/src/uwb/ranging_data.rs index c442d45..3050838 100644 --- a/rust/daemon/src/uwb/ranging_data.rs +++ b/rust/daemon/src/uwb/ranging_data.rs
@@ -16,11 +16,11 @@ use std::collections::BTreeMap; -type TrueDistance = f64; // meters -type EstimatedDistance = f64; // meters +type TrueDistance = f32; // meters +type EstimatedDistance = f32; // meters /// The data is organized as a `BTreeMap` for efficient lookup and interpolation. -struct RangingDataSet { +pub struct RangingDataSet { /// Stores ranging data in the form of (true distance, [estimated distances]) pairs. /// The map keys are true distances in u16 centimeters. data: BTreeMap<u16, Vec<EstimatedDistance>>, @@ -33,8 +33,14 @@ /// ranging sensor. pub fn new(ranging_data: Option<Vec<(TrueDistance, EstimatedDistance)>>) -> Self { // Use sample_ranging_data.csv if ranging_data is not provided. - let sample_ranging_data: Vec<(TrueDistance, EstimatedDistance)> = + #[allow(clippy::excessive_precision)] + let mut sample_ranging_data: Vec<(TrueDistance, EstimatedDistance)> = ranging_data.unwrap_or(include!("sample_ranging_data.csv")); + // Convert to centimeters as Pica uses centimeters for ranging units + sample_ranging_data = sample_ranging_data + .into_iter() + .map(|(true_dist, est_dist)| (true_dist * 100.0, est_dist * 100.0)) + .collect::<Vec<(TrueDistance, EstimatedDistance)>>(); // Process the sample_raning_data into BTreeMap let mut data: BTreeMap<u16, Vec<EstimatedDistance>> = BTreeMap::new(); @@ -84,9 +90,9 @@ let upper = self.data.range(&distance_u16..).next(); match (lower, upper) { (Some((lower_key, lower_vals)), Some((upper_key, upper_vals))) => { - let x1 = *lower_key as f64 / 100.0; + let x1 = *lower_key as f32 / 100.0; let y1 = *lower_vals.choose(&mut rng).unwrap(); - let x2 = *upper_key as f64 / 100.0; + let x2 = *upper_key as f32 / 100.0; let y2 = *upper_vals.choose(&mut rng).unwrap(); y1 + (distance - x1) * (y2 - y1) / (x2 - x1) } @@ -108,10 +114,10 @@ fn test_sample_ranging_data_set() { let ranging_data_set = sample_ranging_data_set(); // Linear Interpolation - assert_eq!(ranging_data_set.sample(0.5, None), 0.55); + assert_eq!(ranging_data_set.sample(50., None), 55.); // Exact distance found in dataset - assert!([1.9, 2.1].contains(&ranging_data_set.sample(2.0, None))); + assert!([190., 210.].contains(&ranging_data_set.sample(200., None))); // Out of Range - assert_eq!(ranging_data_set.sample(3.0, None), 3.0); + assert_eq!(ranging_data_set.sample(300., None), 300.); } }
diff --git a/rust/daemon/src/uwb/ranging_estimator.rs b/rust/daemon/src/uwb/ranging_estimator.rs index ede8777..fb4a91d 100644 --- a/rust/daemon/src/uwb/ranging_estimator.rs +++ b/rust/daemon/src/uwb/ranging_estimator.rs
@@ -18,6 +18,7 @@ use crate::devices::{chip::ChipIdentifier, devices_handler::get_device}; use crate::ranging::{compute_range_azimuth_elevation, Pose}; +use crate::uwb::ranging_data::RangingDataSet; use std::collections::HashMap; use std::sync::{Arc, Mutex, MutexGuard}; @@ -54,11 +55,12 @@ // Netsim's UwbRangingEstimator pub struct UwbRangingEstimator { shared_state: SharedState, + data_set: RangingDataSet, } impl UwbRangingEstimator { pub fn new(shared_state: SharedState) -> Self { - UwbRangingEstimator { shared_state } + UwbRangingEstimator { shared_state, data_set: RangingDataSet::new(None) } } // Utility to convert the UWB Chip handle into the device and chip_id. @@ -86,7 +88,11 @@ let a_pose = Pose::new(a_p.x, a_p.y, a_p.z, a_o.yaw, a_o.pitch, a_o.roll); let b_pose = Pose::new(b_p.x, b_p.y, b_p.z, b_o.yaw, b_o.pitch, b_o.roll); compute_range_azimuth_elevation(&a_pose, &b_pose) - .map(|(range, azimuth, elevation)| RangingMeasurement { range, azimuth, elevation }) + .map(|(range, azimuth, elevation)| RangingMeasurement { + range: self.data_set.sample(range, None).round() as u16, + azimuth, + elevation, + }) .map_err(|e| error!("{e:?}")) .ok() }
diff --git a/rust/daemon/src/wifi/frame.rs b/rust/daemon/src/wifi/frame.rs index 8ef6775..00acb98 100644 --- a/rust/daemon/src/wifi/frame.rs +++ b/rust/daemon/src/wifi/frame.rs
@@ -48,10 +48,10 @@ // found. pub fn parse(msg: &HwsimMsg) -> anyhow::Result<Frame> { // Only expected to be called with HwsimCmd::Frame - if msg.get_hwsim_hdr().hwsim_cmd != HwsimCmd::Frame { + if msg.hwsim_hdr.hwsim_cmd != HwsimCmd::Frame { panic!("Invalid hwsim_cmd"); } - let attrs = HwsimAttrSet::parse(msg.get_attributes()).context("HwsimAttrSet")?; + let attrs = HwsimAttrSet::parse(&msg.attributes).context("HwsimAttrSet")?; let frame = attrs.frame.clone().context("Frame")?; let ieee80211 = Ieee80211::decode_full(&frame).context("Ieee80211")?; // Required attributes are unwrapped and return an error if
diff --git a/rust/daemon/src/wifi/hwsim_attr_set.rs b/rust/daemon/src/wifi/hwsim_attr_set.rs index bb87f06..cd64cb6 100644 --- a/rust/daemon/src/wifi/hwsim_attr_set.rs +++ b/rust/daemon/src/wifi/hwsim_attr_set.rs
@@ -17,7 +17,7 @@ use super::packets::ieee80211::MacAddress; use super::packets::mac80211_hwsim::{self, HwsimAttr, HwsimAttrChild::*, TxRate, TxRateFlag}; use super::packets::netlink::NlAttrHdr; -use anyhow::anyhow; +use anyhow::{anyhow, Context}; use pdl_runtime::Packet; use std::option::Option; @@ -103,98 +103,81 @@ } pub fn transmitter(&mut self, transmitter: &[u8; 6]) -> &mut Self { - self.extend_attributes( - mac80211_hwsim::HwsimAttrAddrTransmitterBuilder { - address: *transmitter, - nla_m: 0, - nla_o: 0, - } - .build(), - ); + self.extend_attributes(mac80211_hwsim::HwsimAttrAddrTransmitter { + address: *transmitter, + nla_m: 0, + nla_o: 0, + }); self.transmitter = Some(MacAddress::from(transmitter)); self } pub fn receiver(&mut self, receiver: &[u8; 6]) -> &mut Self { - self.extend_attributes( - mac80211_hwsim::HwsimAttrAddrReceiverBuilder { address: *receiver, nla_m: 0, nla_o: 0 } - .build(), - ); + self.extend_attributes(mac80211_hwsim::HwsimAttrAddrReceiver { + address: *receiver, + nla_m: 0, + nla_o: 0, + }); self.receiver = Some(MacAddress::from(receiver)); self } pub fn frame(&mut self, frame: &[u8]) -> &mut Self { - self.extend_attributes( - mac80211_hwsim::HwsimAttrFrameBuilder { data: (*frame).to_vec(), nla_m: 0, nla_o: 0 } - .build(), - ); + self.extend_attributes(mac80211_hwsim::HwsimAttrFrame { + data: (*frame).to_vec(), + nla_m: 0, + nla_o: 0, + }); self.frame = Some(frame.to_vec()); self } pub fn flags(&mut self, flags: u32) -> &mut Self { - self.extend_attributes( - mac80211_hwsim::HwsimAttrFlagsBuilder { flags, nla_m: 0, nla_o: 0 }.build(), - ); + self.extend_attributes(mac80211_hwsim::HwsimAttrFlags { flags, nla_m: 0, nla_o: 0 }); self.flags = Some(flags); self } pub fn rx_rate(&mut self, rx_rate_idx: u32) -> &mut Self { - self.extend_attributes( - mac80211_hwsim::HwsimAttrRxRateBuilder { rx_rate_idx, nla_m: 0, nla_o: 0 }.build(), - ); + self.extend_attributes(mac80211_hwsim::HwsimAttrRxRate { rx_rate_idx, nla_m: 0, nla_o: 0 }); self.rx_rate_idx = Some(rx_rate_idx); self } pub fn signal(&mut self, signal: u32) -> &mut Self { - self.extend_attributes( - mac80211_hwsim::HwsimAttrSignalBuilder { signal, nla_m: 0, nla_o: 0 }.build(), - ); + self.extend_attributes(mac80211_hwsim::HwsimAttrSignal { signal, nla_m: 0, nla_o: 0 }); self.signal = Some(signal); self } pub fn cookie(&mut self, cookie: u64) -> &mut Self { - self.extend_attributes( - mac80211_hwsim::HwsimAttrCookieBuilder { cookie, nla_m: 0, nla_o: 0 }.build(), - ); + self.extend_attributes(mac80211_hwsim::HwsimAttrCookie { cookie, nla_m: 0, nla_o: 0 }); self.cookie = Some(cookie); self } pub fn freq(&mut self, freq: u32) -> &mut Self { - self.extend_attributes( - mac80211_hwsim::HwsimAttrFreqBuilder { freq, nla_m: 0, nla_o: 0 }.build(), - ); + self.extend_attributes(mac80211_hwsim::HwsimAttrFreq { freq, nla_m: 0, nla_o: 0 }); self.freq = Some(freq); self } pub fn tx_info(&mut self, tx_info: &[TxRate]) -> &mut Self { - self.extend_attributes( - mac80211_hwsim::HwsimAttrTxInfoBuilder { - tx_rates: (*tx_info).to_vec(), - nla_m: 0, - nla_o: 0, - } - .build(), - ); + self.extend_attributes(mac80211_hwsim::HwsimAttrTxInfo { + tx_rates: (*tx_info).to_vec(), + nla_m: 0, + nla_o: 0, + }); self.tx_info = Some(tx_info.to_vec()); self } pub fn tx_info_flags(&mut self, tx_rate_flags: &[TxRateFlag]) -> &mut Self { - self.extend_attributes( - mac80211_hwsim::HwsimAttrTxInfoFlagsBuilder { - tx_rate_flags: (*tx_rate_flags).to_vec(), - nla_m: 0, - nla_o: 0, - } - .build(), - ); + self.extend_attributes(mac80211_hwsim::HwsimAttrTxInfoFlags { + tx_rate_flags: (*tx_rate_flags).to_vec(), + nla_m: 0, + nla_o: 0, + }); self.tx_info_flags = Some(tx_rate_flags.to_vec()); self } @@ -267,28 +250,29 @@ let mut builder = HwsimAttrSet::builder(); while index < attributes.len() { // Parse a generic netlink attribute to get the size - let nla_hdr = NlAttrHdr::parse(&attributes[index..index + 4]).unwrap(); + let nla_hdr = + NlAttrHdr::decode_full(&attributes[index..index + 4]).context("NlAttrHdr")?; let nla_len = nla_hdr.nla_len as usize; // Now parse a single attribute at a time from the // attributes to allow padding per attribute. - let hwsim_attr = HwsimAttr::parse(&attributes[index..index + nla_len])?; - match hwsim_attr.specialize() { + let hwsim_attr = HwsimAttr::decode_full(&attributes[index..index + nla_len])?; + match hwsim_attr.specialize().context("HwsimAttr")? { HwsimAttrAddrTransmitter(child) => { - builder.transmitter(transmitter.unwrap_or(child.get_address())) + builder.transmitter(transmitter.unwrap_or(child.address())) } - HwsimAttrAddrReceiver(child) => builder.receiver(child.get_address()), - HwsimAttrFrame(child) => builder.frame(frame.unwrap_or(child.get_data())), - HwsimAttrFlags(child) => builder.flags(child.get_flags()), - HwsimAttrRxRate(child) => builder.rx_rate(child.get_rx_rate_idx()), - HwsimAttrSignal(child) => builder.signal(child.get_signal()), - HwsimAttrCookie(child) => builder.cookie(child.get_cookie()), - HwsimAttrFreq(child) => builder.freq(child.get_freq()), - HwsimAttrTxInfo(child) => builder.tx_info(child.get_tx_rates()), - HwsimAttrTxInfoFlags(child) => builder.tx_info_flags(child.get_tx_rate_flags()), + HwsimAttrAddrReceiver(child) => builder.receiver(&child.address), + HwsimAttrFrame(child) => builder.frame(frame.unwrap_or(&child.data)), + HwsimAttrFlags(child) => builder.flags(child.flags), + HwsimAttrRxRate(child) => builder.rx_rate(child.rx_rate_idx), + HwsimAttrSignal(child) => builder.signal(child.signal), + HwsimAttrCookie(child) => builder.cookie(child.cookie), + HwsimAttrFreq(child) => builder.freq(child.freq), + HwsimAttrTxInfo(child) => builder.tx_info(&child.tx_rates), + HwsimAttrTxInfoFlags(child) => builder.tx_info_flags(&child.tx_rate_flags), _ => { return Err(anyhow!( "Invalid attribute message: {:?}", - hwsim_attr.get_nla_type() as u32 + hwsim_attr.nla_type as u32 )) } }; @@ -313,9 +297,9 @@ #[test] fn test_attr_set_parse() { let packet: Vec<u8> = include!("test_packets/hwsim_cmd_frame.csv"); - let hwsim_msg = HwsimMsg::parse(&packet).unwrap(); - assert_eq!(hwsim_msg.get_hwsim_hdr().hwsim_cmd, HwsimCmd::Frame); - let attrs = HwsimAttrSet::parse(hwsim_msg.get_attributes()).unwrap(); + let hwsim_msg = HwsimMsg::decode_full(&packet).unwrap(); + assert_eq!(hwsim_msg.hwsim_hdr().hwsim_cmd, HwsimCmd::Frame); + let attrs = HwsimAttrSet::parse(hwsim_msg.attributes()).unwrap(); // Validate each attribute parsed assert_eq!(attrs.transmitter, MacAddress::try_from(11670786u64).ok()); @@ -336,10 +320,10 @@ #[test] fn test_attr_set_attributes() { let packet: Vec<u8> = include!("test_packets/hwsim_cmd_frame.csv"); - let hwsim_msg = HwsimMsg::parse(&packet).unwrap(); - assert_eq!(hwsim_msg.get_hwsim_hdr().hwsim_cmd, HwsimCmd::Frame); - let attrs = HwsimAttrSet::parse(hwsim_msg.get_attributes()).unwrap(); - assert_eq!(&attrs.attributes, hwsim_msg.get_attributes()); + let hwsim_msg = HwsimMsg::decode_full(&packet).unwrap(); + assert_eq!(hwsim_msg.hwsim_hdr().hwsim_cmd, HwsimCmd::Frame); + let attrs = HwsimAttrSet::parse(hwsim_msg.attributes()).unwrap(); + assert_eq!(&attrs.attributes, hwsim_msg.attributes()); } /// Validate changing frame and transmitter during the parse. @@ -349,12 +333,12 @@ #[test] fn test_attr_set_parse_with_frame_transmitter() -> Result<(), Error> { let packet: Vec<u8> = include!("test_packets/hwsim_cmd_frame.csv"); - let hwsim_msg = HwsimMsg::parse(&packet)?; - assert_eq!(hwsim_msg.get_hwsim_hdr().hwsim_cmd, HwsimCmd::Frame); - let attrs = HwsimAttrSet::parse(hwsim_msg.get_attributes())?; + let hwsim_msg = HwsimMsg::decode_full(&packet)?; + assert_eq!(hwsim_msg.hwsim_hdr().hwsim_cmd, HwsimCmd::Frame); + let attrs = HwsimAttrSet::parse(hwsim_msg.attributes())?; let transmitter: [u8; 6] = attrs.transmitter.context("transmitter")?.into(); let mod_attrs = HwsimAttrSet::parse_with_frame_transmitter( - hwsim_msg.get_attributes(), + hwsim_msg.attributes(), attrs.frame.as_deref(), Some(&transmitter), )?; @@ -381,8 +365,8 @@ #[test] fn test_hwsim_attr_set_display() { let packet: Vec<u8> = include!("test_packets/hwsim_cmd_frame.csv"); - let hwsim_msg = HwsimMsg::parse(&packet).unwrap(); - let attrs = HwsimAttrSet::parse(hwsim_msg.get_attributes()).unwrap(); + let hwsim_msg = HwsimMsg::decode_full(&packet).unwrap(); + let attrs = HwsimAttrSet::parse(hwsim_msg.attributes()).unwrap(); let fmt_attrs = format!("{}", attrs); assert!(fmt_attrs.contains("transmitter: 02:15:b2:00:00:00"));
diff --git a/rust/daemon/src/wifi/medium.rs b/rust/daemon/src/wifi/medium.rs index c1521f0..c54a114 100644 --- a/rust/daemon/src/wifi/medium.rs +++ b/rust/daemon/src/wifi/medium.rs
@@ -13,7 +13,7 @@ // limitations under the License. use super::packets::ieee80211::MacAddress; -use super::packets::mac80211_hwsim::{HwsimCmd, HwsimMsg, HwsimMsgBuilder, HwsimMsgHdr, NlMsgHdr}; +use super::packets::mac80211_hwsim::{HwsimCmd, HwsimMsg, HwsimMsgHdr, NlMsgHdr}; use crate::wifi::frame::Frame; use crate::wifi::hwsim_attr_set::HwsimAttrSet; use anyhow::{anyhow, Context}; @@ -162,11 +162,11 @@ } fn process_internal(&self, client_id: u32, packet: &Bytes) -> anyhow::Result<bool> { - let hwsim_msg = HwsimMsg::parse(packet)?; + let hwsim_msg = HwsimMsg::decode_full(packet)?; // The virtio handler only accepts HWSIM_CMD_FRAME, HWSIM_CMD_TX_INFO_FRAME and HWSIM_CMD_REPORT_PMSR // in https://source.corp.google.com/h/kernel/pub/scm/linux/kernel/git/torvalds/linux/+/master:drivers/net/wireless/virtual/mac80211_hwsim.c - match hwsim_msg.get_hwsim_hdr().hwsim_cmd { + match hwsim_msg.hwsim_hdr.hwsim_cmd { HwsimCmd::Frame => { let frame = Frame::parse(&hwsim_msg)?; // Incoming frame must contain transmitter, flag, cookie, and tx_info fields. @@ -233,8 +233,8 @@ } return Ok(()); } - let hwsim_msg = HwsimMsg::parse(packet)?; - let hwsim_cmd = hwsim_msg.get_hwsim_hdr().hwsim_cmd; + let hwsim_msg = HwsimMsg::decode_full(packet)?; + let hwsim_cmd = hwsim_msg.hwsim_hdr.hwsim_cmd; match hwsim_cmd { HwsimCmd::Frame => self.send_frame_response(packet, &hwsim_msg)?, // TODO: Handle sending TxInfo frame for WifiService so we don't have to @@ -281,7 +281,7 @@ } fn send_tx_info_response(&self, packet: &Bytes, hwsim_msg: &HwsimMsg) -> anyhow::Result<()> { - let attrs = HwsimAttrSet::parse(hwsim_msg.get_attributes()).context("HwsimAttrSet")?; + let attrs = HwsimAttrSet::parse(&hwsim_msg.attributes).context("HwsimAttrSet")?; let hwsim_addr = attrs.transmitter.context("missing transmitter")?; let client_ids = self .stations() @@ -440,7 +440,7 @@ // Simulates transmission through hostapd. fn create_hwsim_msg(&self, frame: &Frame, dest_hwsim_addr: &MacAddress) -> Option<HwsimMsg> { let hwsim_msg = &frame.hwsim_msg; - assert_eq!(hwsim_msg.get_hwsim_hdr().hwsim_cmd, HwsimCmd::Frame); + assert_eq!(hwsim_msg.hwsim_hdr.hwsim_cmd, HwsimCmd::Frame); let attributes_result = self.create_hwsim_attr(frame, dest_hwsim_addr); let attributes = match attributes_result { Ok(attributes) => attributes, @@ -450,20 +450,19 @@ } }; - let nlmsg_len = hwsim_msg.get_nl_hdr().nlmsg_len + attributes.len() as u32 - - hwsim_msg.get_attributes().len() as u32; - let new_hwsim_msg = HwsimMsgBuilder { + let nlmsg_len = hwsim_msg.nl_hdr.nlmsg_len + attributes.len() as u32 + - hwsim_msg.attributes.len() as u32; + let new_hwsim_msg = HwsimMsg { nl_hdr: NlMsgHdr { nlmsg_len, nlmsg_type: NLMSG_MIN_TYPE, - nlmsg_flags: hwsim_msg.get_nl_hdr().nlmsg_flags, + nlmsg_flags: hwsim_msg.nl_hdr.nlmsg_flags, nlmsg_seq: 0, nlmsg_pid: 0, }, - hwsim_hdr: hwsim_msg.get_hwsim_hdr().clone(), + hwsim_hdr: hwsim_msg.hwsim_hdr.clone(), attributes, - } - .build(); + }; Some(new_hwsim_msg) } } @@ -479,10 +478,10 @@ /// /// Reference to ackLocalFrame() in external/qemu/android-qemu2-glue/emulation/VirtioWifiForwarder.cpp fn build_tx_info(hwsim_msg: &HwsimMsg) -> anyhow::Result<HwsimMsg> { - let attrs = HwsimAttrSet::parse(hwsim_msg.get_attributes()).context("HwsimAttrSet").unwrap(); + let attrs = HwsimAttrSet::parse(&hwsim_msg.attributes).context("HwsimAttrSet").unwrap(); - let hwsim_hdr = hwsim_msg.get_hwsim_hdr(); - let nl_hdr = hwsim_msg.get_nl_hdr(); + let hwsim_hdr = &hwsim_msg.hwsim_hdr; + let nl_hdr = &hwsim_msg.nl_hdr; let mut new_attr_builder = HwsimAttrSet::builder(); const HWSIM_TX_STAT_ACK: u32 = 1 << 2; @@ -496,7 +495,7 @@ let new_attr = new_attr_builder.build().unwrap(); let nlmsg_len = nl_hdr.nlmsg_len + new_attr.attributes.len() as u32 - attrs.attributes.len() as u32; - let new_hwsim_msg = HwsimMsgBuilder { + let new_hwsim_msg = HwsimMsg { attributes: new_attr.attributes, hwsim_hdr: HwsimMsgHdr { hwsim_cmd: HwsimCmd::TxInfoFrame, @@ -510,21 +509,20 @@ nlmsg_seq: 0, nlmsg_pid: 0, }, - } - .build(); + }; Ok(new_hwsim_msg) } // It's used by radiotap.rs for packet capture. pub fn parse_hwsim_cmd(packet: &[u8]) -> anyhow::Result<HwsimCmdEnum> { - let hwsim_msg = HwsimMsg::parse(packet)?; - match hwsim_msg.get_hwsim_hdr().hwsim_cmd { + let hwsim_msg = HwsimMsg::decode_full(packet)?; + match hwsim_msg.hwsim_hdr.hwsim_cmd { HwsimCmd::Frame => { let frame = Frame::parse(&hwsim_msg)?; Ok(HwsimCmdEnum::Frame(Box::new(frame))) } HwsimCmd::TxInfoFrame => Ok(HwsimCmdEnum::TxInfoFrame), - _ => Err(anyhow!("Unknown HwsimMsg cmd={:?}", hwsim_msg.get_hwsim_hdr().hwsim_cmd)), + _ => Err(anyhow!("Unknown HwsimMsg cmd={:?}", hwsim_msg.hwsim_hdr.hwsim_cmd)), } } @@ -598,7 +596,7 @@ #[test] fn test_is_mdns_packet() { let packet: Vec<u8> = include!("test_packets/hwsim_cmd_frame_mdns.csv"); - let hwsim_msg = HwsimMsg::parse(&packet).unwrap(); + let hwsim_msg = HwsimMsg::decode_full(&packet).unwrap(); let mdns_frame = Frame::parse(&hwsim_msg).unwrap(); assert!(!mdns_frame.ieee80211.get_source().is_multicast()); assert!(mdns_frame.ieee80211.get_destination().is_multicast()); @@ -607,8 +605,8 @@ #[test] fn test_build_tx_info_reconstruct() { let packet: Vec<u8> = include!("test_packets/hwsim_cmd_tx_info.csv"); - let hwsim_msg = HwsimMsg::parse(&packet).unwrap(); - assert_eq!(hwsim_msg.get_hwsim_hdr().hwsim_cmd, HwsimCmd::TxInfoFrame); + let hwsim_msg = HwsimMsg::decode_full(&packet).unwrap(); + assert_eq!(hwsim_msg.hwsim_hdr().hwsim_cmd, HwsimCmd::TxInfoFrame); let new_hwsim_msg = build_tx_info(&hwsim_msg).unwrap(); assert_eq!(hwsim_msg, new_hwsim_msg); @@ -617,23 +615,23 @@ #[test] fn test_build_tx_info() { let packet: Vec<u8> = include!("test_packets/hwsim_cmd_frame.csv"); - let hwsim_msg = HwsimMsg::parse(&packet).unwrap(); + let hwsim_msg = HwsimMsg::decode_full(&packet).unwrap(); let hwsim_msg_tx_info = build_tx_info(&hwsim_msg).unwrap(); - assert_eq!(hwsim_msg_tx_info.get_hwsim_hdr().hwsim_cmd, HwsimCmd::TxInfoFrame); + assert_eq!(hwsim_msg_tx_info.hwsim_hdr().hwsim_cmd, HwsimCmd::TxInfoFrame); } fn build_tx_info_and_compare(frame_bytes: &Bytes, tx_info_expected_bytes: &Bytes) { - let frame = HwsimMsg::parse(frame_bytes).unwrap(); + let frame = HwsimMsg::decode_full(frame_bytes).unwrap(); let tx_info = build_tx_info(&frame).unwrap(); - let tx_info_expected = HwsimMsg::parse(tx_info_expected_bytes).unwrap(); + let tx_info_expected = HwsimMsg::decode_full(tx_info_expected_bytes).unwrap(); - assert_eq!(tx_info.get_hwsim_hdr(), tx_info_expected.get_hwsim_hdr()); - assert_eq!(tx_info.get_nl_hdr(), tx_info_expected.get_nl_hdr()); + assert_eq!(tx_info.hwsim_hdr(), tx_info_expected.hwsim_hdr()); + assert_eq!(tx_info.nl_hdr(), tx_info_expected.nl_hdr()); - let attrs = HwsimAttrSet::parse(tx_info.get_attributes()).context("HwsimAttrSet").unwrap(); + let attrs = HwsimAttrSet::parse(tx_info.attributes()).context("HwsimAttrSet").unwrap(); let attrs_expected = - HwsimAttrSet::parse(tx_info_expected.get_attributes()).context("HwsimAttrSet").unwrap(); + HwsimAttrSet::parse(tx_info_expected.attributes()).context("HwsimAttrSet").unwrap(); // NOTE: TX info is different and the counts are all zeros in the TX info packet generated by WifiService. // TODO: Confirm if the behavior is intended in WifiService.
diff --git a/rust/daemon/src/wireless/wifi.rs b/rust/daemon/src/wireless/wifi.rs index f7f5ac0..55537e4 100644 --- a/rust/daemon/src/wireless/wifi.rs +++ b/rust/daemon/src/wireless/wifi.rs
@@ -64,6 +64,7 @@ if crate::config::get_disable_wifi_p2p() || !WIFI_MANAGER.medium.process(chip_id, &packet) { + // TODO: Replace with libslirp_send() and hostapd_send() ffi_wifi::handle_wifi_request(chip_id, &packet.to_vec()); ffi_wifi::libslirp_main_loop_wait(); }
diff --git a/src/wifi/wifi_facade.cc b/src/wifi/wifi_facade.cc index 0d47890..31c43fc 100644 --- a/src/wifi/wifi_facade.cc +++ b/src/wifi/wifi_facade.cc
@@ -122,4 +122,24 @@ #endif } +void HostapdSendCxx(uint32_t chip_id, const rust::Vec<uint8_t> &packet) { +#ifdef NETSIM_ANDROID_EMULATOR + // Send the packet to Hostapd. + struct iovec iov[1]; + iov[0].iov_base = (void *)packet.data(); + iov[0].iov_len = packet.size(); + wifi_service->hostapd_send(android::base::IOVector(iov, iov + 1)); +#endif +} + +void LibslirpSendCxx(uint32_t chip_id, const rust::Vec<uint8_t> &packet) { +#ifdef NETSIM_ANDROID_EMULATOR + // Send the packet to libslirp. + struct iovec iov[1]; + iov[0].iov_base = (void *)packet.data(); + iov[0].iov_len = packet.size(); + wifi_service->libslirp_send(android::base::IOVector(iov, iov + 1)); +#endif +} + } // namespace netsim::wifi
diff --git a/src/wifi/wifi_packet_hub.h b/src/wifi/wifi_packet_hub.h index a133594..a583d6e 100644 --- a/src/wifi/wifi_packet_hub.h +++ b/src/wifi/wifi_packet_hub.h
@@ -31,4 +31,8 @@ void HandleWifiRequestCxx(uint32_t chip_id, const rust::Vec<uint8_t> &packet); +void HostapdSendCxx(uint32_t chip_id, const rust::Vec<uint8_t> &packet); + +void LibslirpSendCxx(uint32_t chip_id, const rust::Vec<uint8_t> &packet); + } // namespace netsim::wifi