Implement EmulatedChip trait for Bluetooth, BleBeacon, Wifi, and Mocked.
This is a starter code for EmulatedChip trait, which is not being
invoked by other modules yet. Next step is to migrate
handle_packet_response, and progressively replace the original code.
Test: atest --host-unit-test-only libnetsim_daemon_tests
Bug: 307963660
Change-Id: I42c43fd8b767f685dbda22ab9fd618256a93bb8f
diff --git a/rust/daemon/src/echip/ble_beacon.rs b/rust/daemon/src/echip/ble_beacon.rs
new file mode 100644
index 0000000..436df9e
--- /dev/null
+++ b/rust/daemon/src/echip/ble_beacon.rs
@@ -0,0 +1,72 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use crate::devices::chip::{ChipIdentifier, FacadeIdentifier};
+use crate::devices::device::DeviceIdentifier;
+use crate::echip::EmulatedChip;
+
+use netsim_proto::common::ChipKind as ProtoChipKind;
+use netsim_proto::model::Chip as ProtoChip;
+use netsim_proto::model::ChipCreate as ChipCreateProto;
+
+use std::rc::Rc;
+
+/// Parameters for creating BleBeacon chips
+pub struct CreateParams {
+ device_id: DeviceIdentifier,
+ device_name: String,
+ chip_id: ChipIdentifier,
+ chip_proto: ChipCreateProto,
+}
+
+/// BleBeacon struct will keep track of facade_id
+pub struct BleBeacon {
+ facade_id: FacadeIdentifier,
+}
+
+impl EmulatedChip for BleBeacon {
+ fn handle_request(&self, packet: &[u8]) {
+ todo!();
+ }
+
+ fn reset(&self) {
+ todo!();
+ }
+
+ fn get(&self) -> ProtoChip {
+ todo!();
+ }
+
+ fn patch(&self, chip: ProtoChip) {
+ todo!();
+ }
+
+ fn get_kind(&self) -> ProtoChipKind {
+ ProtoChipKind::BLUETOOTH_BEACON
+ }
+}
+
+impl Drop for BleBeacon {
+ /// At drop, Remove the emulated chip from the virtual device. No further calls will
+ /// be made on this emulated chip. This is called when the packet stream from
+ /// the virtual device closes.
+ fn drop(&mut self) {
+ todo!();
+ }
+}
+
+/// Create a new Emulated BleBeacon Chip
+pub fn new(params: CreateParams) -> Rc<dyn EmulatedChip> {
+ todo!();
+}
diff --git a/rust/daemon/src/echip/bluetooth.rs b/rust/daemon/src/echip/bluetooth.rs
new file mode 100644
index 0000000..509d566
--- /dev/null
+++ b/rust/daemon/src/echip/bluetooth.rs
@@ -0,0 +1,101 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use crate::devices::chip::FacadeIdentifier;
+use crate::ffi::ffi_bluetooth;
+use crate::{devices::device::DeviceIdentifier, echip::EmulatedChip};
+
+use cxx::let_cxx_string;
+use netsim_proto::common::ChipKind as ProtoChipKind;
+use netsim_proto::config::Bluetooth as BluetoothConfig;
+use netsim_proto::configuration::Controller as RootcanalController;
+use netsim_proto::model::chip::Bluetooth as ProtoBluetooth;
+use netsim_proto::model::Chip as ProtoChip;
+use protobuf::{Message, MessageField};
+
+use std::rc::Rc;
+
+/// Parameters for creating Bluetooth chips
+pub struct CreateParams {
+ device_id: DeviceIdentifier,
+ address: String,
+ bt_properties: MessageField<RootcanalController>,
+}
+
+/// Bluetooth struct will keep track of facade_id
+pub struct Bluetooth {
+ facade_id: FacadeIdentifier,
+}
+
+impl EmulatedChip for Bluetooth {
+ fn handle_request(&self, packet: &[u8]) {
+ ffi_bluetooth::handle_bt_request(self.facade_id, packet[0], &packet[1..].to_vec())
+ }
+
+ fn reset(&self) {
+ ffi_bluetooth::bluetooth_reset(self.facade_id);
+ }
+
+ fn get(&self) -> ProtoChip {
+ let bluetooth_bytes = ffi_bluetooth::bluetooth_get_cxx(self.facade_id);
+ let bt_proto = ProtoBluetooth::parse_from_bytes(&bluetooth_bytes).unwrap();
+ let mut chip_proto = ProtoChip::new();
+ chip_proto.mut_bt().clone_from(&bt_proto);
+ chip_proto
+ }
+
+ fn patch(&self, chip: ProtoChip) {
+ let bluetooth_bytes = chip.bt().write_to_bytes().unwrap();
+ ffi_bluetooth::bluetooth_patch_cxx(self.facade_id, &bluetooth_bytes);
+ }
+
+ fn get_kind(&self) -> ProtoChipKind {
+ ProtoChipKind::BLUETOOTH
+ }
+}
+
+impl Drop for Bluetooth {
+ /// At drop, Remove the emulated chip from the virtual device. No further calls will
+ /// be made on this emulated chip. This is called when the packet stream from
+ /// the virtual device closes.
+ fn drop(&mut self) {
+ ffi_bluetooth::bluetooth_remove(self.facade_id);
+ }
+}
+
+/// Create a new Emulated Bluetooth Chip
+pub fn new(create_params: CreateParams) -> Rc<dyn EmulatedChip> {
+ let_cxx_string!(cxx_address = create_params.address);
+ let proto_bytes =
+ create_params.bt_properties.as_ref().unwrap_or_default().write_to_bytes().unwrap();
+ let facade_id =
+ ffi_bluetooth::bluetooth_add(create_params.device_id, &cxx_address, &proto_bytes);
+ let echip = Bluetooth { facade_id };
+ Rc::new(echip)
+}
+
+/// Starts the Bluetooth service.
+pub fn bluetooth_start(
+ config: &MessageField<BluetoothConfig>,
+ instance_num: u16,
+ disable_address_reuse: bool,
+) {
+ let proto_bytes = config.as_ref().unwrap_or_default().write_to_bytes().unwrap();
+ ffi_bluetooth::bluetooth_start(&proto_bytes, instance_num, disable_address_reuse);
+}
+
+/// Stops the Bluetooth service.
+pub fn bluetooth_stop() {
+ ffi_bluetooth::bluetooth_stop();
+}
diff --git a/rust/daemon/src/echip/emulated_chip.rs b/rust/daemon/src/echip/emulated_chip.rs
new file mode 100644
index 0000000..01c6023
--- /dev/null
+++ b/rust/daemon/src/echip/emulated_chip.rs
@@ -0,0 +1,84 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use netsim_proto::common::ChipKind as ProtoChipKind;
+use netsim_proto::model::Chip as ProtoChip;
+
+use crate::echip::{ble_beacon, bluetooth, mocked, wifi};
+
+use std::rc::Rc;
+
+/// Parameter for each constructor of Emulated Chips
+pub enum CreateParam {
+ BleBeacon(ble_beacon::CreateParams),
+ Bluetooth(bluetooth::CreateParams),
+ Wifi(wifi::CreateParams),
+ Mock(mocked::CreateParams),
+}
+
+// TODO: Factory trait to include start, stop, and add
+/// EmulatedChip is a trait that provides interface between the generic Chip
+/// and Radio specific library (rootcanal, libslirp, pica).
+pub trait EmulatedChip {
+ /// This is the main entry for incoming host-to-controller packets
+ /// from virtual devices called by the transport module. The format of the
+ /// packet depends on the emulated chip kind:
+ /// * Bluetooth - packet is H4 HCI format
+ /// * Wi-Fi - packet is Radiotap format
+ /// * UWB - packet is UCI format
+ /// * NFC - packet is NCI format
+ fn handle_request(&self, packet: &[u8]);
+
+ /// Reset the internal state of the emulated chip for the virtual device.
+ /// The transmitted and received packet count will be set to 0 and the chip
+ /// shall be in the enabled state following a call to this function.
+ fn reset(&self);
+
+ /// Return the Chip model protobuf from the emulated chip. This is part of
+ /// the Frontend API.
+ fn get(&self) -> ProtoChip;
+
+ /// Patch the state of the emulated chip. For example enable/disable the
+ /// chip's host-to-controller packet processing. This is part of the
+ /// Frontend API
+ fn patch(&self, chip: ProtoChip);
+
+ /// Returns the kind of the emulated chip.
+ fn get_kind(&self) -> ProtoChipKind;
+}
+
+/// This is called when the transport module receives a new packet stream
+/// connection from a virtual device.
+pub fn new(create_param: CreateParam) -> Rc<dyn EmulatedChip> {
+ match create_param {
+ CreateParam::BleBeacon(params) => ble_beacon::new(params),
+ CreateParam::Bluetooth(params) => bluetooth::new(params),
+ CreateParam::Wifi(params) => wifi::new(params),
+ CreateParam::Mock(params) => mocked::new(params),
+ }
+}
+
+#[cfg(test)]
+mod tests {
+
+ use super::*;
+
+ #[test]
+ fn test_echip_new() {
+ let mock_param = CreateParam::Mock(mocked::CreateParams {});
+ let echip = new(mock_param);
+ assert_eq!(echip.get_kind(), ProtoChipKind::UNSPECIFIED);
+ assert_eq!(echip.get(), ProtoChip::new());
+ }
+}
diff --git a/rust/daemon/src/echip/mocked.rs b/rust/daemon/src/echip/mocked.rs
new file mode 100644
index 0000000..a74aef0
--- /dev/null
+++ b/rust/daemon/src/echip/mocked.rs
@@ -0,0 +1,47 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use crate::echip::EmulatedChip;
+
+use netsim_proto::common::ChipKind as ProtoChipKind;
+use netsim_proto::model::Chip as ProtoChip;
+
+use std::rc::Rc;
+
+/// Parameters for creating Mocked chips
+pub struct CreateParams {}
+
+/// Mock struct is remained empty.
+pub struct Mock {}
+
+impl EmulatedChip for Mock {
+ fn handle_request(&self, packet: &[u8]) {}
+
+ fn reset(&self) {}
+
+ fn get(&self) -> ProtoChip {
+ ProtoChip::new()
+ }
+
+ fn patch(&self, chip: ProtoChip) {}
+
+ fn get_kind(&self) -> ProtoChipKind {
+ ProtoChipKind::UNSPECIFIED
+ }
+}
+
+/// Create a new MockedChip
+pub fn new(create_params: CreateParams) -> Rc<dyn EmulatedChip> {
+ Rc::new(Mock {})
+}
diff --git a/rust/daemon/src/echip/mod.rs b/rust/daemon/src/echip/mod.rs
new file mode 100644
index 0000000..aab7ff8
--- /dev/null
+++ b/rust/daemon/src/echip/mod.rs
@@ -0,0 +1,21 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+mod ble_beacon;
+mod bluetooth;
+mod emulated_chip;
+mod mocked;
+mod wifi;
+
+use crate::echip::emulated_chip::EmulatedChip;
diff --git a/rust/daemon/src/echip/wifi.rs b/rust/daemon/src/echip/wifi.rs
new file mode 100644
index 0000000..00bba9c
--- /dev/null
+++ b/rust/daemon/src/echip/wifi.rs
@@ -0,0 +1,89 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use crate::devices::chip::FacadeIdentifier;
+use crate::ffi::ffi_wifi;
+use crate::{devices::device::DeviceIdentifier, echip::EmulatedChip};
+
+use netsim_proto::common::ChipKind as ProtoChipKind;
+use netsim_proto::config::WiFi as WiFiConfig;
+use netsim_proto::model::chip::Radio;
+use netsim_proto::model::Chip as ProtoChip;
+use protobuf::{Message, MessageField};
+
+use std::rc::Rc;
+
+/// Parameters for creating Wifi chips
+pub struct CreateParams {
+ device_id: DeviceIdentifier,
+}
+
+/// Wifi struct will keep track of facade_id
+pub struct Wifi {
+ facade_id: FacadeIdentifier,
+}
+
+impl EmulatedChip for Wifi {
+ fn handle_request(&self, packet: &[u8]) {
+ ffi_wifi::handle_wifi_request(self.facade_id, &packet.to_vec());
+ }
+
+ fn reset(&self) {
+ ffi_wifi::wifi_reset(self.facade_id);
+ }
+
+ fn get(&self) -> ProtoChip {
+ let radio_bytes = ffi_wifi::wifi_get_cxx(self.facade_id);
+ let wifi_proto = Radio::parse_from_bytes(&radio_bytes).unwrap();
+ let mut chip_proto = ProtoChip::new();
+ chip_proto.mut_wifi().clone_from(&wifi_proto);
+ chip_proto
+ }
+
+ fn patch(&self, chip: ProtoChip) {
+ let radio_bytes = chip.wifi().write_to_bytes().unwrap();
+ ffi_wifi::wifi_patch_cxx(self.facade_id, &radio_bytes);
+ }
+
+ fn get_kind(&self) -> ProtoChipKind {
+ ProtoChipKind::WIFI
+ }
+}
+
+impl Drop for Wifi {
+ /// At drop, Remove the emulated chip from the virtual device. No further calls will
+ /// be made on this emulated chip. This is called when the packet stream from
+ /// the virtual device closes.
+ fn drop(&mut self) {
+ ffi_wifi::wifi_remove(self.facade_id);
+ }
+}
+
+/// Create a new Emulated Wifi Chip
+pub fn new(params: CreateParams) -> Rc<dyn EmulatedChip> {
+ let facade_id = ffi_wifi::wifi_add(params.device_id);
+ let echip = Wifi { facade_id };
+ Rc::new(echip)
+}
+
+/// Starts the WiFi service.
+pub fn wifi_start(config: &MessageField<WiFiConfig>) {
+ let proto_bytes = config.as_ref().unwrap_or_default().write_to_bytes().unwrap();
+ ffi_wifi::wifi_start(&proto_bytes);
+}
+
+/// Stops the WiFi service.
+pub fn wifi_stop() {
+ ffi_wifi::wifi_stop();
+}
diff --git a/rust/daemon/src/lib.rs b/rust/daemon/src/lib.rs
index e655a63..a41e9ee 100644
--- a/rust/daemon/src/lib.rs
+++ b/rust/daemon/src/lib.rs
@@ -34,6 +34,10 @@
mod version;
mod wifi;
+// TODO(b/307145892): EmulatedChip Trait is actively being implemented.
+#[allow(dead_code, unused_variables)]
+mod echip;
+
// This feature is enabled only for CMake builds
#[cfg(feature = "local_ssl")]
mod openssl;