aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-12-14 00:25:15 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-12-14 00:25:15 +0000
commit5658c3db12895bca6fa218737ee2933a6d615ac1 (patch)
treec56d4d48b2ed65ec2b179b0312d2815453037fdb
parentadb07458fca5d3a35632bf3fd3a58322e235c42d (diff)
parent154857395c25564b37c80e3767a8ca9e4136b843 (diff)
downloadnetsim-5658c3db12895bca6fa218737ee2933a6d615ac1.tar.gz
Snap for 11216811 from 154857395c25564b37c80e3767a8ca9e4136b843 to 24Q1-release
Change-Id: I46a6ccc06bade41b8e9cd28a9932a4c7c6488813
-rw-r--r--TEST_MAPPING3
-rw-r--r--pdl/ieee80211.pdl79
-rw-r--r--rust/daemon/src/bluetooth/beacon.rs10
-rw-r--r--rust/daemon/src/bluetooth/chip.rs6
-rw-r--r--rust/daemon/src/bluetooth/mocked.rs1
-rw-r--r--rust/daemon/src/devices/chip.rs203
-rw-r--r--rust/daemon/src/devices/device.rs2
-rw-r--r--rust/daemon/src/devices/devices_handler.rs50
-rw-r--r--rust/daemon/src/echip/ble_beacon.rs9
-rw-r--r--rust/daemon/src/echip/bluetooth.rs13
-rw-r--r--rust/daemon/src/echip/emulated_chip.rs19
-rw-r--r--rust/daemon/src/echip/mocked.rs21
-rw-r--r--rust/daemon/src/echip/wifi.rs11
-rw-r--r--rust/daemon/src/ffi.rs9
-rw-r--r--rust/daemon/src/wifi/frame.rs2
-rw-r--r--rust/daemon/src/wifi/ieee80211.rs112
-rw-r--r--rust/daemon/src/wifi/mod.rs1
-rw-r--r--rust/daemon/src/wifi/packets.rs8
-rw-r--r--src/hci/bluetooth_facade.cc42
-rw-r--r--src/hci/bluetooth_facade.h8
20 files changed, 483 insertions, 126 deletions
diff --git a/TEST_MAPPING b/TEST_MAPPING
index e49a4a3b..454a8df0 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -10,6 +10,9 @@
"exclude-filter": "android.bluetooth.cts.LeL2capSocketTest#openInsecureLeL2capServerSocketRepeatedly"
}
]
+ },
+ {
+ "name": "net_test_bluetooth"
}
]
} \ No newline at end of file
diff --git a/pdl/ieee80211.pdl b/pdl/ieee80211.pdl
index f94a6b21..3e28f60d 100644
--- a/pdl/ieee80211.pdl
+++ b/pdl/ieee80211.pdl
@@ -5,6 +5,8 @@
little_endian_packets
+custom_field MacAddress : 48 "macaddr/"
+
// Frame type B3..B2
enum FrameType : 2 {
MGMT = 0,
@@ -13,7 +15,21 @@ enum FrameType : 2 {
EXT = 3,
}
-// Management subtype B7..B4
+// Data substypes
+enum DataSubType : 4 {
+ DATA = 0,
+ DATA_CF_ACK = 1,
+ DATA_CF_POLL = 2,
+ DATA_CF_ACPL = 3,
+ NODATA = 4,
+ NODATA_CF_ACK = 5,
+ NODATA_CF_POLL = 6,
+ NODATA_CF_ACPL = 7,
+ QOS = 8,
+ QOS_NULL = 12,
+}
+
+// Management subtypes
enum ManagementSubType : 4 {
ASSOC_REQ = 0,
ASSOC_RESP = 1,
@@ -29,12 +45,12 @@ enum ManagementSubType : 4 {
ACTION = 13,
}
-struct FrameControl {
+group FrameControl {
version : 2, // B1..B0
ftype: FrameType, // B3..B2
stype: 4, // B7..B4
- tods: 1, // B8
- fromds: 1, // B9
+ to_ds: 1, // B8
+ from_ds: 1, // B9
more_frags: 1, // B10
retry: 1, // B11
pm : 1, // B12
@@ -43,13 +59,58 @@ struct FrameControl {
order: 1, // B15
}
+
packet Ieee80211 {
- frame_control: FrameControl,
+ FrameControl,
duration_id: 16,
- addr1 : 8[6],
- addr2 : 8[6],
- addr3 : 8[6],
+ _payload_,
+}
+
+/*
+ * DS bit usage
+ *
+ * TA = transmitter address
+ * RA = receiver address
+ * DA = destination address
+ * SA = source address
+ *
+ * ToDS FromDS A1(RA) A2(TA) A3 A4 Use
+ * -----------------------------------------------------------------
+ * 0 0 DA SA BSSID - IBSS/DLS
+ * 0 1 DA BSSID SA - AP -> STA
+ * 1 0 BSSID SA DA - AP <- STA
+ * 1 1 RA TA DA SA unspecified (WDS)
+ */
+
+packet Ieee80211Ibss : Ieee80211 (to_ds=0, from_ds=0) {
+ destination : MacAddress,
+ source : MacAddress,
+ bssid : MacAddress,
+ seq_ctrl : 16,
+ payload: 8[],
+}
+
+packet Ieee80211FromAp : Ieee80211 (to_ds=0, from_ds=1) {
+ destination : MacAddress,
+ bssid : MacAddress,
+ source : MacAddress,
+ seq_ctrl : 16,
+ payload: 8[],
+}
+
+packet Ieee80211ToAp : Ieee80211 (to_ds=1, from_ds=0) {
+ bssid : MacAddress,
+ source : MacAddress,
+ destination : MacAddress,
+ seq_ctrl : 16,
+ payload: 8[],
+}
+
+packet Ieee80211Wds : Ieee80211 (to_ds=1, from_ds=1) {
+ receiver : MacAddress,
+ transmitter : MacAddress,
+ destination : MacAddress,
seq_ctrl : 16,
- addr4 : 8[6],
+ source : MacAddress,
payload: 8[],
}
diff --git a/rust/daemon/src/bluetooth/beacon.rs b/rust/daemon/src/bluetooth/beacon.rs
index 13d8ef8c..77c69648 100644
--- a/rust/daemon/src/bluetooth/beacon.rs
+++ b/rust/daemon/src/bluetooth/beacon.rs
@@ -234,7 +234,6 @@ impl RustBluetoothChipCallbacks for BeaconChipCallbacks {
/// Similar to `bluetooth_add()`.
#[cfg(not(test))]
pub fn ble_beacon_add(
- device_id: DeviceIdentifier,
device_name: String,
chip_id: ChipIdentifier,
chip_proto: &ChipCreateProto,
@@ -253,17 +252,14 @@ pub fn ble_beacon_add(
let callbacks: Box<dyn RustBluetoothChipCallbacks> = Box::new(BeaconChipCallbacks { chip_id });
let add_rust_device_result = rust_bluetooth_add(
- device_id,
+ chip_id,
callbacks,
String::from("beacon"),
beacon_proto.address.clone(),
);
let rust_chip = add_rust_device_result.rust_chip;
let facade_id = add_rust_device_result.facade_id;
- info!(
- "Creating HCI facade_id: {} for device_id: {} chip_id: {}",
- facade_id, device_id, chip_id
- );
+ info!("Creating HCI facade_id: {} for chip_id: {}", facade_id, chip_id);
BT_CHIPS.write().unwrap().insert(chip_id, Mutex::new(rust_chip));
Ok(facade_id)
@@ -408,6 +404,7 @@ pub mod tests {
};
use super::*;
+ // using ble_beacon_add from mocked.rs
use crate::bluetooth::ble_beacon_add;
lazy_static! {
@@ -418,7 +415,6 @@ pub mod tests {
let id = TEST_GUID_GENERATOR.lock().unwrap().next_id();
let add_result = ble_beacon_add(
- 0,
format!("test-device-{:?}", thread::current().id()),
id,
&ChipCreateProto {
diff --git a/rust/daemon/src/bluetooth/chip.rs b/rust/daemon/src/bluetooth/chip.rs
index faaecbe1..add0a865 100644
--- a/rust/daemon/src/bluetooth/chip.rs
+++ b/rust/daemon/src/bluetooth/chip.rs
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-use crate::ffi::ffi_bluetooth::RustBluetoothChip;
+use crate::{devices::chip::ChipIdentifier, ffi::ffi_bluetooth::RustBluetoothChip};
use cxx::{let_cxx_string, UniquePtr};
/// Rust bluetooth chip trait.
@@ -44,7 +44,7 @@ pub fn create_add_rust_device_result(
/// Add a bluetooth chip by an object implements RustBluetoothChipCallbacks trait.
pub fn rust_bluetooth_add(
- device_id: u32,
+ chip_id: ChipIdentifier,
callbacks: Box<dyn RustBluetoothChipCallbacks>,
string_type: String,
address: String,
@@ -52,7 +52,7 @@ pub fn rust_bluetooth_add(
let_cxx_string!(cxx_string_type = string_type);
let_cxx_string!(cxx_address = address);
crate::ffi::ffi_bluetooth::bluetooth_add_rust_device(
- device_id,
+ chip_id,
Box::new(callbacks),
&cxx_string_type,
&cxx_address,
diff --git a/rust/daemon/src/bluetooth/mocked.rs b/rust/daemon/src/bluetooth/mocked.rs
index 41e757a4..68a60a67 100644
--- a/rust/daemon/src/bluetooth/mocked.rs
+++ b/rust/daemon/src/bluetooth/mocked.rs
@@ -43,7 +43,6 @@ impl FacadeIds {
// Avoid crossing cxx boundary in tests
pub fn ble_beacon_add(
- device_id: DeviceIdentifier,
device_name: String,
chip_id: ChipIdentifier,
chip_proto: &ChipCreate,
diff --git a/rust/daemon/src/devices/chip.rs b/rust/daemon/src/devices/chip.rs
index 1979abde..2008257d 100644
--- a/rust/daemon/src/devices/chip.rs
+++ b/rust/daemon/src/devices/chip.rs
@@ -26,18 +26,35 @@ use netsim_proto::configuration::Controller as ProtoController;
use netsim_proto::model::Chip as ProtoChip;
use netsim_proto::stats::NetsimRadioStats as ProtoRadioStats;
use protobuf::EnumOrUnknown;
-use std::sync::RwLock;
+use std::collections::HashMap;
+use std::sync::{Arc, Mutex, MutexGuard, RwLock};
use std::time::Instant;
+use super::device::DeviceIdentifier;
+
pub type ChipIdentifier = u32;
pub type FacadeIdentifier = u32;
const INITIAL_CHIP_ID: ChipIdentifier = 1000;
+// ChipMap is a singleton that contains a hash map from
+// chip_id to Chip objects.
+type ChipMap = HashMap<ChipIdentifier, Chip>;
+
+#[derive(Clone)]
+struct SharedChips(Arc<Mutex<ChipMap>>);
+
+impl SharedChips {
+ fn lock(&self) -> MutexGuard<ChipMap> {
+ self.0.lock().expect("Poisoned Shared Chips lock")
+ }
+}
+
// Allocator for chip identifiers.
lazy_static! {
static ref IDS: RwLock<IdFactory<ChipIdentifier>> =
RwLock::new(IdFactory::new(INITIAL_CHIP_ID, 1));
+ static ref CHIPS: SharedChips = SharedChips(Arc::new(Mutex::new(HashMap::new())));
}
pub struct CreateParams {
@@ -51,8 +68,10 @@ pub struct CreateParams {
/// Chip contains the common information for each Chip/Controller.
/// Radio-specific information is contained in the emulated_chip.
+#[derive(Clone)]
pub struct Chip {
pub id: ChipIdentifier,
+ pub device_id: DeviceIdentifier,
pub emulated_chip: Option<SharedEmulatedChip>,
pub kind: ProtoChipKind,
pub address: String,
@@ -71,9 +90,15 @@ impl Chip {
// Any Chip with an emulated_chip == None is temporary.
// Creating the echip first required holding a Chip+Device lock through
// initialization which caused a deadlock under certain (rare) conditions.
- fn new(id: ChipIdentifier, device_name: &str, create_params: &CreateParams) -> Self {
+ fn new(
+ id: ChipIdentifier,
+ device_id: DeviceIdentifier,
+ device_name: &str,
+ create_params: &CreateParams,
+ ) -> Self {
Self {
id,
+ device_id,
emulated_chip: None,
kind: create_params.kind,
address: create_params.address.clone(),
@@ -138,8 +163,174 @@ impl Chip {
}
}
-/// Allocates a new chip with a facade_id.
-pub fn chip_new(device_name: &str, create_params: &CreateParams) -> Result<Chip, String> {
- let id = IDS.write().unwrap().next_id();
- Ok(Chip::new(id, device_name, create_params))
+/// Obtains a Chip with given chip_id
+pub fn get(chip_id: ChipIdentifier) -> Result<Chip, String> {
+ get_with_singleton(chip_id, CHIPS.clone())
+}
+
+/// Testable function for get()
+fn get_with_singleton(chip_id: ChipIdentifier, shared_chips: SharedChips) -> Result<Chip, String> {
+ Ok(shared_chips
+ .lock()
+ .get(&chip_id)
+ .ok_or(format!("CHIPS does not contains key {chip_id}"))?
+ .clone())
+}
+
+/// Allocates a new chip.
+pub fn new(
+ device_id: DeviceIdentifier,
+ device_name: &str,
+ create_params: &CreateParams,
+) -> Result<Chip, String> {
+ new_with_singleton(device_id, device_name, create_params, CHIPS.clone(), &IDS)
+}
+
+/// Testable function for new()
+fn new_with_singleton(
+ device_id: DeviceIdentifier,
+ device_name: &str,
+ create_params: &CreateParams,
+ shared_chips: SharedChips,
+ id_factory: &RwLock<IdFactory<ChipIdentifier>>,
+) -> Result<Chip, String> {
+ let id = id_factory.write().unwrap().next_id();
+ let chip = Chip::new(id, device_id, device_name, create_params);
+ shared_chips.lock().insert(id, chip.clone());
+ Ok(chip)
+}
+
+#[cfg(test)]
+mod tests {
+ use netsim_proto::stats::netsim_radio_stats;
+
+ use crate::echip::mocked;
+
+ use super::*;
+
+ const DEVICE_ID: u32 = 0;
+ const DEVICE_NAME: &str = "device";
+ const CHIP_KIND: ProtoChipKind = ProtoChipKind::UNSPECIFIED;
+ const ADDRESS: &str = "address";
+ const MANUFACTURER: &str = "manufacturer";
+ const PRODUCT_NAME: &str = "product_name";
+
+ fn new_test_chip(
+ emulated_chip: Option<SharedEmulatedChip>,
+ shared_chips: SharedChips,
+ id_factory: &RwLock<IdFactory<ChipIdentifier>>,
+ ) -> Chip {
+ let create_params = CreateParams {
+ kind: CHIP_KIND,
+ address: ADDRESS.to_string(),
+ name: None,
+ manufacturer: MANUFACTURER.to_string(),
+ product_name: PRODUCT_NAME.to_string(),
+ bt_properties: None,
+ };
+ match new_with_singleton(
+ DEVICE_ID,
+ DEVICE_NAME,
+ &create_params,
+ shared_chips.clone(),
+ id_factory,
+ ) {
+ Ok(mut chip) => {
+ chip.emulated_chip = emulated_chip;
+ chip
+ }
+ Err(err) => {
+ unreachable!("{err:?}");
+ }
+ }
+ }
+
+ #[test]
+ fn test_new_and_get_with_singleton() {
+ // Construct a new Chip by calling new_test_chip, which calls new_with_singleton
+ let shared_chips = SharedChips(Arc::new(Mutex::new(HashMap::new())));
+ let id_factory = RwLock::new(IdFactory::new(INITIAL_CHIP_ID, 1));
+ let chip = new_test_chip(None, shared_chips.clone(), &id_factory);
+
+ // Check if the Chip has been successfully inserted in SharedChips
+ let chip_id = chip.id;
+ assert!(shared_chips.lock().contains_key(&chip_id));
+
+ // Check if the get_with_singleton can successfully fetch the chip
+ let chip_result = get_with_singleton(chip_id, shared_chips.clone());
+ assert!(chip_result.is_ok());
+
+ // Check if the fields are correctly populated
+ let chip = chip_result.unwrap();
+ assert_eq!(chip.device_id, DEVICE_ID);
+ assert_eq!(chip.device_name, DEVICE_NAME);
+ assert!(chip.emulated_chip.is_none());
+ assert_eq!(chip.kind, CHIP_KIND);
+ assert_eq!(chip.address, ADDRESS);
+ assert_eq!(chip.name, format!("chip-{chip_id}"));
+ assert_eq!(chip.manufacturer, MANUFACTURER);
+ assert_eq!(chip.product_name, PRODUCT_NAME);
+ }
+
+ #[test]
+ fn test_chip_get_stats() {
+ // When emulated_chip is constructed
+ let mocked_echip =
+ mocked::new(&mocked::CreateParams { chip_kind: ProtoChipKind::UNSPECIFIED }, 0);
+ let shared_chips = SharedChips(Arc::new(Mutex::new(HashMap::new())));
+ let id_factory = RwLock::new(IdFactory::new(INITIAL_CHIP_ID, 1));
+ let chip = new_test_chip(Some(mocked_echip), shared_chips.clone(), &id_factory);
+ assert_eq!(netsim_radio_stats::Kind::UNSPECIFIED, chip.get_stats().first().unwrap().kind());
+
+ // When emulated_chip is not constructed
+ let chip = new_test_chip(None, shared_chips.clone(), &id_factory);
+ assert_eq!(Vec::<ProtoRadioStats>::new(), chip.get_stats());
+ }
+
+ #[test]
+ fn test_chip_get() {
+ let mocked_echip =
+ mocked::new(&mocked::CreateParams { chip_kind: ProtoChipKind::UNSPECIFIED }, 0);
+ let shared_chips = SharedChips(Arc::new(Mutex::new(HashMap::new())));
+ let id_factory = RwLock::new(IdFactory::new(INITIAL_CHIP_ID, 1));
+ let chip = new_test_chip(Some(mocked_echip.clone()), shared_chips.clone(), &id_factory);
+
+ // Obtain actual chip.get()
+ let actual = chip.get().unwrap();
+
+ // Construct expected ProtoChip
+ let mut expected = mocked_echip.lock().get();
+ expected.kind = EnumOrUnknown::new(chip.kind);
+ expected.id = chip.id;
+ expected.name = chip.name.clone();
+ expected.manufacturer = chip.manufacturer.clone();
+ expected.product_name = chip.product_name.clone();
+
+ // Compare
+ assert_eq!(expected, actual);
+ }
+
+ #[test]
+ fn test_chip_patch() {
+ let mocked_echip =
+ mocked::new(&mocked::CreateParams { chip_kind: ProtoChipKind::UNSPECIFIED }, 0);
+ let shared_chips = SharedChips(Arc::new(Mutex::new(HashMap::new())));
+ let id_factory = RwLock::new(IdFactory::new(INITIAL_CHIP_ID, 1));
+ let mut chip = new_test_chip(Some(mocked_echip.clone()), shared_chips.clone(), &id_factory);
+
+ // Construct the patch body for modifying manufacturer and product_name
+ let mut patch_body = ProtoChip::new();
+ patch_body.manufacturer = "patched_manufacturer".to_string();
+ patch_body.product_name = "patched_product_name".to_string();
+
+ // Perform Patch
+ assert!(chip.patch(&patch_body).is_ok());
+
+ // Check if fields of chip has been patched
+ assert_eq!(patch_body.manufacturer, chip.manufacturer);
+ assert_eq!(patch_body.product_name, chip.product_name)
+ }
+
+ // TODO (b/309529194)
+ // Implement echip/mocked.rs to test emulated_chip level of patch and resets.
}
diff --git a/rust/daemon/src/devices/device.rs b/rust/daemon/src/devices/device.rs
index 8b46061d..fc889833 100644
--- a/rust/daemon/src/devices/device.rs
+++ b/rust/daemon/src/devices/device.rs
@@ -186,7 +186,7 @@ impl Device {
}
}
- let chip = chip::chip_new(&self.name, chip_create_params)?;
+ let chip = chip::new(self.id, &self.name, chip_create_params)?;
let chip_id = chip.id;
self.chips.insert(chip_id, chip);
diff --git a/rust/daemon/src/devices/devices_handler.rs b/rust/daemon/src/devices/devices_handler.rs
index 400420bf..dc96d5a7 100644
--- a/rust/daemon/src/devices/devices_handler.rs
+++ b/rust/daemon/src/devices/devices_handler.rs
@@ -144,7 +144,7 @@ pub fn add_chip(
match result {
// id_tuple = (DeviceIdentifier, ChipIdentifier)
Ok((device_id, chip_id)) => {
- let emulated_chip = echip::new(echip_create_params, device_id, chip_id);
+ let emulated_chip = echip::new(echip_create_params, chip_id);
// Lock Device Resource
{
let devices_arc = get_devices();
@@ -562,17 +562,23 @@ fn distance(a: &ProtoPosition, b: &ProtoPosition) -> f32 {
}
#[allow(dead_code)]
-fn get_distance(id: DeviceIdentifier, other_id: DeviceIdentifier) -> Result<f32, String> {
+fn get_distance(id: ChipIdentifier, other_id: ChipIdentifier) -> Result<f32, String> {
+ let device_id = crate::devices::chip::get(id)
+ .or(Err(format!("No such device with chip_id {id}")))?
+ .device_id;
+ let other_device_id = crate::devices::chip::get(other_id)
+ .or(Err(format!("No such device with chip_id {other_id}")))?
+ .device_id;
let devices_arc = get_devices();
let devices = devices_arc.read().unwrap();
let a = devices
.entries
- .get(&id)
+ .get(&device_id)
.map(|device_ref| device_ref.position.clone())
.ok_or(format!("No such device with id {id}"))?;
let b = devices
.entries
- .get(&other_id)
+ .get(&other_device_id)
.map(|device_ref| device_ref.position.clone())
.ok_or(format!("No such device with id {other_id}"))?;
Ok(distance(&a, &b))
@@ -1434,6 +1440,42 @@ mod tests {
assert!(get_devices().read().unwrap().entries.get(&bt_chip_result.device_id).is_some());
}
+ #[test]
+ fn test_get_distance() {
+ // Initializing Logger
+ logger_setup();
+
+ // Add 2 chips of different devices
+ let bt_chip_params = test_chip_1_bt();
+ let bt_chip_2_params = test_chip_2_bt();
+ let bt_chip_result = bt_chip_params.add_chip().unwrap();
+ let bt_chip_2_result = bt_chip_2_params.add_chip().unwrap();
+
+ // Patch the first chip
+ let mut patch_device_request = PatchDeviceRequest::new();
+ let mut proto_device = ProtoDevice::new();
+ let request_position = new_position(1.0, 1.0, 1.0);
+ proto_device.name = bt_chip_params.device_name;
+ proto_device.position = Some(request_position.clone()).into();
+ patch_device_request.device = Some(proto_device.clone()).into();
+ let patch_json = print_to_string(&patch_device_request).unwrap();
+ patch_device(Some(bt_chip_result.device_id), patch_json.as_str()).unwrap();
+
+ // Patch the second chip
+ let mut patch_device_request = PatchDeviceRequest::new();
+ let mut proto_device = ProtoDevice::new();
+ let request_position = new_position(1.0, 4.0, 5.0);
+ proto_device.name = bt_chip_2_params.device_name;
+ proto_device.position = Some(request_position.clone()).into();
+ patch_device_request.device = Some(proto_device.clone()).into();
+ let patch_json = print_to_string(&patch_device_request).unwrap();
+ patch_device(Some(bt_chip_2_result.device_id), patch_json.as_str()).unwrap();
+
+ // Verify the get_distance performs the correct computation of
+ // sqrt((1-1)**2 + (4-1)**2 + (5-1)**2)
+ assert_eq!(Ok(5.0), get_distance(bt_chip_result.chip_id, bt_chip_2_result.chip_id))
+ }
+
#[allow(dead_code)]
fn list_request() -> Request<Vec<u8>> {
Request::builder()
diff --git a/rust/daemon/src/echip/ble_beacon.rs b/rust/daemon/src/echip/ble_beacon.rs
index 53fddc1b..0b8dd9f6 100644
--- a/rust/daemon/src/echip/ble_beacon.rs
+++ b/rust/daemon/src/echip/ble_beacon.rs
@@ -14,7 +14,6 @@
use crate::bluetooth::{ble_beacon_add, ble_beacon_get, ble_beacon_patch, ble_beacon_remove};
use crate::devices::chip::{ChipIdentifier, FacadeIdentifier};
-use crate::devices::device::DeviceIdentifier;
use crate::echip::{EmulatedChip, SharedEmulatedChip};
use log::{error, info};
@@ -94,12 +93,8 @@ impl EmulatedChip for BleBeacon {
}
/// Create a new Emulated BleBeacon Chip
-pub fn new(
- params: &CreateParams,
- device_id: DeviceIdentifier,
- chip_id: ChipIdentifier,
-) -> SharedEmulatedChip {
- match ble_beacon_add(device_id, params.device_name.clone(), chip_id, &params.chip_proto) {
+pub fn new(params: &CreateParams, chip_id: ChipIdentifier) -> SharedEmulatedChip {
+ match ble_beacon_add(params.device_name.clone(), chip_id, &params.chip_proto) {
Ok(facade_id) => {
info!("BleBeacon EmulatedChip created with facade_id: {facade_id} chip_id: {chip_id}");
SharedEmulatedChip(Arc::new(Mutex::new(Box::new(BleBeacon { facade_id, chip_id }))))
diff --git a/rust/daemon/src/echip/bluetooth.rs b/rust/daemon/src/echip/bluetooth.rs
index abe77c3d..1661128f 100644
--- a/rust/daemon/src/echip/bluetooth.rs
+++ b/rust/daemon/src/echip/bluetooth.rs
@@ -13,11 +13,8 @@
// limitations under the License.
use crate::devices::chip::ChipIdentifier;
+use crate::echip::{EmulatedChip, SharedEmulatedChip};
use crate::ffi::ffi_bluetooth;
-use crate::{
- devices::device::DeviceIdentifier,
- echip::{EmulatedChip, SharedEmulatedChip},
-};
use cxx::let_cxx_string;
use log::info;
@@ -103,11 +100,7 @@ impl EmulatedChip for Bluetooth {
}
/// Create a new Emulated Bluetooth Chip
-pub fn new(
- create_params: &CreateParams,
- device_id: DeviceIdentifier,
- chip_id: ChipIdentifier,
-) -> SharedEmulatedChip {
+pub fn new(create_params: &CreateParams, chip_id: ChipIdentifier) -> SharedEmulatedChip {
// Lock to protect id_to_chip_info_ table in C++
let _unused = ECHIP_BT_MUTEX.lock().expect("Failed to acquire lock on ECHIP_BT_MUTEX");
let_cxx_string!(cxx_address = create_params.address.clone());
@@ -115,7 +108,7 @@ pub fn new(
Some(properties) => properties.write_to_bytes().unwrap(),
None => Vec::new(),
};
- let rootcanal_id = ffi_bluetooth::bluetooth_add(device_id, chip_id, &cxx_address, &proto_bytes);
+ let rootcanal_id = ffi_bluetooth::bluetooth_add(chip_id, &cxx_address, &proto_bytes);
info!("Bluetooth EmulatedChip created with rootcanal_id: {rootcanal_id} chip_id: {chip_id}");
let echip = Bluetooth { rootcanal_id };
SharedEmulatedChip(Arc::new(Mutex::new(Box::new(echip))))
diff --git a/rust/daemon/src/echip/emulated_chip.rs b/rust/daemon/src/echip/emulated_chip.rs
index e9c14f61..27970a22 100644
--- a/rust/daemon/src/echip/emulated_chip.rs
+++ b/rust/daemon/src/echip/emulated_chip.rs
@@ -24,7 +24,7 @@ use netsim_proto::model::Chip as ProtoChip;
use netsim_proto::stats::NetsimRadioStats as ProtoRadioStats;
use crate::{
- devices::{chip::ChipIdentifier, device::DeviceIdentifier},
+ devices::chip::ChipIdentifier,
echip::{ble_beacon, mocked},
};
@@ -116,21 +116,17 @@ pub fn remove(chip_id: ChipIdentifier) -> Option<SharedEmulatedChip> {
/// This is called when the transport module receives a new packet stream
/// connection from a virtual device.
-pub fn new(
- create_param: &CreateParam,
- device_id: DeviceIdentifier,
- chip_id: ChipIdentifier,
-) -> SharedEmulatedChip {
+pub fn new(create_param: &CreateParam, chip_id: ChipIdentifier) -> SharedEmulatedChip {
// Based on create_param, construct SharedEmulatedChip.
let shared_echip = match create_param {
- CreateParam::BleBeacon(params) => ble_beacon::new(params, device_id, chip_id),
+ CreateParam::BleBeacon(params) => ble_beacon::new(params, chip_id),
#[cfg(not(test))]
- CreateParam::Bluetooth(params) => bluetooth::new(params, device_id, chip_id),
+ CreateParam::Bluetooth(params) => bluetooth::new(params, chip_id),
#[cfg(not(test))]
- CreateParam::Wifi(params) => wifi::new(params, device_id, chip_id),
+ CreateParam::Wifi(params) => wifi::new(params, chip_id),
#[cfg(not(test))]
CreateParam::Uwb => todo!(),
- CreateParam::Mock(params) => mocked::new(params, device_id),
+ CreateParam::Mock(params) => mocked::new(params, chip_id),
};
// Insert into ECHIPS Map
@@ -150,9 +146,8 @@ mod tests {
fn test_echip_new() {
let mock_param =
CreateParam::Mock(mocked::CreateParams { chip_kind: ProtoChipKind::UNSPECIFIED });
- let mock_device_id = 0;
let mock_chip_id = 0;
- let echip = new(&mock_param, mock_device_id, mock_chip_id);
+ let echip = new(&mock_param, mock_chip_id);
assert_eq!(echip.lock().get_kind(), ProtoChipKind::UNSPECIFIED);
assert_eq!(echip.lock().get(), ProtoChip::new());
}
diff --git a/rust/daemon/src/echip/mocked.rs b/rust/daemon/src/echip/mocked.rs
index 9c5cf47e..00e49153 100644
--- a/rust/daemon/src/echip/mocked.rs
+++ b/rust/daemon/src/echip/mocked.rs
@@ -12,12 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-use crate::devices::device::DeviceIdentifier;
+use crate::devices::chip::ChipIdentifier;
use crate::echip::{EmulatedChip, SharedEmulatedChip};
use netsim_proto::common::ChipKind as ProtoChipKind;
use netsim_proto::model::Chip as ProtoChip;
-use netsim_proto::stats::NetsimRadioStats as ProtoRadioStats;
+use netsim_proto::stats::{netsim_radio_stats, NetsimRadioStats as ProtoRadioStats};
+use protobuf::EnumOrUnknown;
use std::sync::{Arc, Mutex};
@@ -37,7 +38,9 @@ impl EmulatedChip for Mock {
fn reset(&mut self) {}
fn get(&self) -> ProtoChip {
- ProtoChip::new()
+ let mut proto_chip = ProtoChip::new();
+ proto_chip.kind = EnumOrUnknown::new(self.chip_kind);
+ proto_chip
}
fn patch(&mut self, chip: &ProtoChip) {}
@@ -45,7 +48,15 @@ impl EmulatedChip for Mock {
fn remove(&mut self) {}
fn get_stats(&self, duration_secs: u64) -> Vec<ProtoRadioStats> {
- vec![ProtoRadioStats::new()]
+ let mut stats = ProtoRadioStats::new();
+ stats.kind = Some(EnumOrUnknown::new(match self.chip_kind {
+ ProtoChipKind::UNSPECIFIED => netsim_radio_stats::Kind::UNSPECIFIED,
+ ProtoChipKind::BLUETOOTH => netsim_radio_stats::Kind::BLUETOOTH_LOW_ENERGY,
+ ProtoChipKind::WIFI => netsim_radio_stats::Kind::WIFI,
+ ProtoChipKind::UWB => netsim_radio_stats::Kind::UWB,
+ ProtoChipKind::BLUETOOTH_BEACON => netsim_radio_stats::Kind::BLE_BEACON,
+ }));
+ vec![stats]
}
fn get_kind(&self) -> ProtoChipKind {
@@ -54,6 +65,6 @@ impl EmulatedChip for Mock {
}
/// Create a new MockedChip
-pub fn new(create_params: &CreateParams, device_id: DeviceIdentifier) -> SharedEmulatedChip {
+pub fn new(create_params: &CreateParams, _chip_id: ChipIdentifier) -> SharedEmulatedChip {
SharedEmulatedChip(Arc::new(Mutex::new(Box::new(Mock { chip_kind: create_params.chip_kind }))))
}
diff --git a/rust/daemon/src/echip/wifi.rs b/rust/daemon/src/echip/wifi.rs
index f9e81a35..2dba81ae 100644
--- a/rust/daemon/src/echip/wifi.rs
+++ b/rust/daemon/src/echip/wifi.rs
@@ -13,12 +13,9 @@
// limitations under the License.
use crate::devices::chip::ChipIdentifier;
+use crate::echip::{EmulatedChip, SharedEmulatedChip};
use crate::ffi::ffi_wifi;
use crate::wifi::medium;
-use crate::{
- devices::device::DeviceIdentifier,
- echip::{EmulatedChip, SharedEmulatedChip},
-};
use log::info;
use netsim_proto::common::ChipKind as ProtoChipKind;
use netsim_proto::config::WiFi as WiFiConfig;
@@ -84,11 +81,7 @@ impl EmulatedChip for Wifi {
}
/// Create a new Emulated Wifi Chip
-pub fn new(
- _params: &CreateParams,
- _device_id: DeviceIdentifier,
- chip_id: ChipIdentifier,
-) -> SharedEmulatedChip {
+pub fn new(_params: &CreateParams, chip_id: ChipIdentifier) -> SharedEmulatedChip {
ffi_wifi::wifi_add(chip_id);
info!("WiFi EmulatedChip created chip_id: {chip_id}");
let echip = Wifi { chip_id };
diff --git a/rust/daemon/src/ffi.rs b/rust/daemon/src/ffi.rs
index 2da65992..19763f21 100644
--- a/rust/daemon/src/ffi.rs
+++ b/rust/daemon/src/ffi.rs
@@ -185,12 +185,7 @@ pub mod ffi_bluetooth {
#[rust_name = bluetooth_add]
#[namespace = "netsim::hci::facade"]
- pub fn Add(
- device_id: u32,
- chip_id: u32,
- address: &CxxString,
- controller_proto_bytes: &[u8],
- ) -> u32;
+ pub fn Add(chip_id: u32, address: &CxxString, controller_proto_bytes: &[u8]) -> u32;
/*
From https://cxx.rs/binding/box.html#restrictions,
@@ -206,7 +201,7 @@ pub mod ffi_bluetooth {
#[rust_name = bluetooth_add_rust_device]
#[namespace = "netsim::hci::facade"]
pub fn AddRustDevice(
- device_id: u32,
+ chip_id: u32,
callbacks: Box<DynRustBluetoothChipCallbacks>,
string_type: &CxxString,
address: &CxxString,
diff --git a/rust/daemon/src/wifi/frame.rs b/rust/daemon/src/wifi/frame.rs
index 7737ae50..9a194362 100644
--- a/rust/daemon/src/wifi/frame.rs
+++ b/rust/daemon/src/wifi/frame.rs
@@ -12,10 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+use super::ieee80211::Ieee80211;
use super::packets::mac80211_hwsim::HwsimAttrChild::*;
use super::packets::mac80211_hwsim::{HwsimAttr, HwsimMsg, HwsimMsgHdr, TxRate, TxRateFlag};
use super::packets::netlink::{NlAttrHdr, NlMsgHdr};
-use crate::wifi::packets::ieee80211::Ieee80211;
use anyhow::{anyhow, Context};
use log::{info, warn};
use std::mem;
diff --git a/rust/daemon/src/wifi/ieee80211.rs b/rust/daemon/src/wifi/ieee80211.rs
index d5a4f1e4..7e501b8e 100644
--- a/rust/daemon/src/wifi/ieee80211.rs
+++ b/rust/daemon/src/wifi/ieee80211.rs
@@ -12,12 +12,108 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-/// FrameInfo stores mac80211 hwsim attributes once parsed
-
-pub struct FrameInfo {
- cookie: u64,
- flags: u32,
- channel: u32,
- // tx_rates
- transmitter: [u8; 6],
+//! ieee80211 frames
+
+#![allow(clippy::all)]
+#![allow(missing_docs)]
+include!(concat!(env!("OUT_DIR"), "/ieee80211_packets.rs"));
+
+/// A Ieee80211 MAC address
+
+impl fmt::Display for MacAddress {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let bytes = u64::to_le_bytes(self.0);
+ write!(
+ f,
+ "{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}",
+ bytes[5], bytes[4], bytes[3], bytes[2], bytes[1], bytes[0],
+ )
+ }
+}
+
+impl From<&[u8; 6]> for MacAddress {
+ fn from(bytes: &[u8; 6]) -> Self {
+ Self(u64::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], 0, 0]))
+ }
+}
+
+impl From<MacAddress> for [u8; 6] {
+ fn from(MacAddress(addr): MacAddress) -> Self {
+ let bytes = u64::to_le_bytes(addr);
+ bytes[0..6].try_into().unwrap()
+ }
+}
+
+impl Ieee80211 {
+ // Frame has addr4 field
+ pub fn has_a4(&self) -> bool {
+ self.ieee80211.to_ds == 1 || self.ieee80211.from_ds == 1
+ }
+
+ // Frame type is management
+ pub fn is_mgmt(&self) -> bool {
+ self.ieee80211.ftype == FrameType::Mgmt
+ }
+
+ // Frame type is data
+ pub fn is_data(&self) -> bool {
+ self.ieee80211.ftype == FrameType::Data
+ }
+
+ // Frame is probe request
+ pub fn is_probe_req(&self) -> bool {
+ self.ieee80211.ftype == FrameType::Ctl
+ && self.ieee80211.stype == (ManagementSubType::ProbeReq as u8)
+ }
+
+ pub fn get_source(&self) -> MacAddress {
+ match self.specialize() {
+ Ieee80211Child::Ieee80211ToAp(hdr) => hdr.get_source(),
+ Ieee80211Child::Ieee80211FromAp(hdr) => hdr.get_source(),
+ Ieee80211Child::Ieee80211Ibss(hdr) => hdr.get_source(),
+ Ieee80211Child::Ieee80211Wds(hdr) => hdr.get_source(),
+ _ => panic!("unexpected specialized header"),
+ }
+ }
+}
+
+fn parse_mac_address(s: &str) -> Option<MacAddress> {
+ let parts: Vec<&str> = s.split(':').collect();
+ if parts.len() != 6 {
+ return None;
+ }
+ let mut bytes = [0u8; 6];
+ for (i, part) in parts.iter().enumerate() {
+ match u8::from_str_radix(part, 16) {
+ Ok(n) => bytes[i] = n,
+ Err(e) => return None,
+ }
+ }
+ Some(MacAddress::from(&bytes))
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ // These tests use the packets available here
+ // https://community.cisco.com/t5/wireless-mobility-knowledge-base/802-11-frames-a-starter-guide-to-learn-wireless-sniffer-traces/ta-p/3110019
+
+ #[test]
+ fn test_frame_qos() {
+ let frame: Vec<u8> = vec![
+ 0x88, 0x02, 0x2c, 0x00, 0x00, 0x13, 0xe8, 0xeb, 0xd6, 0x03, 0x00, 0x0b, 0x85, 0x71,
+ 0x20, 0xce, 0x00, 0x0b, 0x85, 0x71, 0x20, 0xce, 0x00, 0x26, 0x00, 0x00,
+ ];
+ let hdr = Ieee80211::parse(&frame).unwrap();
+ assert!(hdr.is_data());
+ assert_eq!(hdr.get_stype(), DataSubType::Qos as u8);
+ assert_eq!(hdr.get_from_ds(), 1);
+ assert_eq!(hdr.get_to_ds(), 0);
+ assert_eq!(hdr.get_duration_id(), 44);
+ // Source address: Cisco_71:20:ce (00:0b:85:71:20:ce)
+ let a = format!("{}", hdr.get_source());
+ let b = format!("{}", parse_mac_address("00:0b:85:71:20:ce").unwrap());
+ assert_eq!(a, b);
+ }
}
diff --git a/rust/daemon/src/wifi/mod.rs b/rust/daemon/src/wifi/mod.rs
index 43c62605..8891cce0 100644
--- a/rust/daemon/src/wifi/mod.rs
+++ b/rust/daemon/src/wifi/mod.rs
@@ -18,6 +18,7 @@
#![allow(unused)]
pub(crate) mod frame;
+pub(crate) mod ieee80211;
pub(crate) mod medium;
pub(crate) mod packets;
pub(crate) mod radiotap;
diff --git a/rust/daemon/src/wifi/packets.rs b/rust/daemon/src/wifi/packets.rs
index 934b707d..a3f99870 100644
--- a/rust/daemon/src/wifi/packets.rs
+++ b/rust/daemon/src/wifi/packets.rs
@@ -27,11 +27,3 @@ pub mod mac80211_hwsim {
include!(concat!(env!("OUT_DIR"), "/mac80211_hwsim_packets.rs"));
}
-
-pub mod ieee80211 {
- #![allow(clippy::all)]
- #![allow(unused)]
- #![allow(missing_docs)]
-
- include!(concat!(env!("OUT_DIR"), "/ieee80211_packets.rs"));
-}
diff --git a/src/hci/bluetooth_facade.cc b/src/hci/bluetooth_facade.cc
index b97eb42b..7195f464 100644
--- a/src/hci/bluetooth_facade.cc
+++ b/src/hci/bluetooth_facade.cc
@@ -275,7 +275,7 @@ void PatchPhy(int device_id, bool isAddToPhy, bool isLowEnergy) {
class ChipInfo {
public:
- uint32_t simulation_device;
+ uint32_t chip_id;
std::shared_ptr<model::Chip::Bluetooth> model;
int le_tx_count = 0;
int classic_tx_count = 0;
@@ -284,14 +284,13 @@ class ChipInfo {
std::shared_ptr<rootcanal::configuration::Controller> controller_proto;
std::unique_ptr<rootcanal::ControllerProperties> controller_properties;
- ChipInfo(uint32_t simulation_device,
- std::shared_ptr<model::Chip::Bluetooth> model)
- : simulation_device(simulation_device), model(model) {}
+ ChipInfo(uint32_t chip_id, std::shared_ptr<model::Chip::Bluetooth> model)
+ : chip_id(chip_id), model(model) {}
ChipInfo(
- uint32_t simulation_device, std::shared_ptr<model::Chip::Bluetooth> model,
+ uint32_t chip_id, std::shared_ptr<model::Chip::Bluetooth> model,
std::shared_ptr<rootcanal::configuration::Controller> controller_proto,
std::unique_ptr<rootcanal::ControllerProperties> controller_properties)
- : simulation_device(simulation_device),
+ : chip_id(chip_id),
model(model),
controller_proto(std::move(controller_proto)),
controller_properties(std::move(controller_properties)) {}
@@ -364,8 +363,7 @@ void Remove(uint32_t id) {
// Rename AddChip(model::Chip, device, transport)
-uint32_t Add(uint32_t simulation_device, uint32_t chip_id,
- const std::string &address_string,
+uint32_t Add(uint32_t chip_id, const std::string &address_string,
const rust::Slice<::std::uint8_t const> controller_proto_bytes) {
auto transport = std::make_shared<HciPacketTransport>(chip_id, gAsyncManager);
@@ -376,8 +374,8 @@ uint32_t Add(uint32_t simulation_device, uint32_t chip_id,
rootcanal::configuration::Controller custom_proto;
custom_proto.ParseFromArray(controller_proto_bytes.data(),
controller_proto_bytes.size());
- BtsLogInfo("device_id: %d has rootcanal Controller configuration: %s",
- simulation_device, custom_proto.ShortDebugString().c_str());
+ BtsLogInfo("chip_id: %d has rootcanal Controller configuration: %s",
+ chip_id, custom_proto.ShortDebugString().c_str());
// When emulators restore from a snapshot the PacketStreamer connection to
// netsim is recreated with a new (uninitialized) Rootcanal device. However
@@ -414,17 +412,16 @@ uint32_t Add(uint32_t simulation_device, uint32_t chip_id,
auto rootcanal_id = rootcanal_id_future.get();
HciPacketTransport::Add(rootcanal_id, transport);
- BtsLogInfo("Creating HCI rootcanal_id: %d for device_id: %d", rootcanal_id,
- simulation_device);
+ BtsLogInfo("Creating HCI rootcanal_id: %d for chip_id: %d", rootcanal_id,
+ chip_id);
auto model = std::make_shared<model::Chip::Bluetooth>();
model->mutable_classic()->set_state(model::State::ON);
model->mutable_low_energy()->set_state(model::State::ON);
- id_to_chip_info_.emplace(
- rootcanal_id,
- std::make_shared<ChipInfo>(simulation_device, model, controller_proto,
- std::move(controller_properties)));
+ id_to_chip_info_.emplace(rootcanal_id, std::make_shared<ChipInfo>(
+ chip_id, model, controller_proto,
+ std::move(controller_properties)));
return rootcanal_id;
}
@@ -433,9 +430,8 @@ void RemoveRustDevice(uint32_t rootcanal_id) {
}
rust::Box<AddRustDeviceResult> AddRustDevice(
- uint32_t simulation_device,
- rust::Box<DynRustBluetoothChipCallbacks> callbacks, const std::string &type,
- const std::string &address) {
+ uint32_t chip_id, rust::Box<DynRustBluetoothChipCallbacks> callbacks,
+ const std::string &type, const std::string &address) {
auto rust_device =
std::make_shared<RustDevice>(std::move(callbacks), type, address);
@@ -448,8 +444,8 @@ rust::Box<AddRustDeviceResult> AddRustDevice(
auto model = std::make_shared<model::Chip::Bluetooth>();
// Only enable ble for beacon.
model->mutable_low_energy()->set_state(model::State::ON);
- id_to_chip_info_.emplace(
- rootcanal_id, std::make_shared<ChipInfo>(simulation_device, model));
+ id_to_chip_info_.emplace(rootcanal_id,
+ std::make_shared<ChipInfo>(chip_id, model));
return CreateAddRustDeviceResult(
rootcanal_id, std::make_unique<RustBluetoothChip>(rust_device));
}
@@ -496,8 +492,8 @@ int8_t SimComputeRssi(int send_id, int recv_id, int8_t tx_power) {
#endif
return tx_power;
}
- auto a = id_to_chip_info_[send_id]->simulation_device;
- auto b = id_to_chip_info_[recv_id]->simulation_device;
+ auto a = id_to_chip_info_[send_id]->chip_id;
+ auto b = id_to_chip_info_[recv_id]->chip_id;
auto distance = netsim::device::GetDistanceCxx(a, b);
return netsim::DistanceToRssi(tx_power, distance);
}
diff --git a/src/hci/bluetooth_facade.h b/src/hci/bluetooth_facade.h
index b8998a27..bb84e0db 100644
--- a/src/hci/bluetooth_facade.h
+++ b/src/hci/bluetooth_facade.h
@@ -39,14 +39,12 @@ void Reset(uint32_t);
void Remove(uint32_t);
void Patch(uint32_t, const model::Chip::Bluetooth &);
model::Chip::Bluetooth Get(uint32_t);
-uint32_t Add(uint32_t simulation_device, uint32_t chip_id,
- const std::string &address_string,
+uint32_t Add(uint32_t chip_id, const std::string &address_string,
const rust::Slice<::std::uint8_t const> controller_proto_bytes);
rust::Box<AddRustDeviceResult> AddRustDevice(
- uint32_t simulation_device,
- rust::Box<DynRustBluetoothChipCallbacks> callbacks, const std::string &type,
- const std::string &address);
+ uint32_t chip_id, rust::Box<DynRustBluetoothChipCallbacks> callbacks,
+ const std::string &type, const std::string &address);
void SetRustDeviceAddress(
uint32_t rootcanal_id,
std::array<uint8_t, rootcanal::Address::kLength> address);