blob: a73c76af2aa31ab3e667c3a97b66b4eae7e9b933 [file] [log] [blame]
// 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::ffi::ffi_wifi;
use crate::wifi::medium;
use crate::{
devices::device::DeviceIdentifier,
echip::{EmulatedChip, SharedEmulatedChip},
};
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 netsim_proto::stats::{netsim_radio_stats, NetsimRadioStats as ProtoRadioStats};
use protobuf::{Message, MessageField};
use std::sync::Arc;
/// Parameters for creating Wifi chips
pub struct CreateParams {}
/// Wifi struct will keep track of facade_id
pub struct Wifi {
chip_id: ChipIdentifier,
}
impl EmulatedChip for Wifi {
fn handle_request(&self, packet: &[u8]) {
if crate::config::get_dev() {
let _ = medium::parse_hwsim_cmd(packet);
}
ffi_wifi::handle_wifi_request(self.chip_id, &packet.to_vec());
}
fn reset(&self) {
ffi_wifi::wifi_reset(self.chip_id);
}
fn get(&self) -> ProtoChip {
let radio_bytes = ffi_wifi::wifi_get_cxx(self.chip_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.chip_id, &radio_bytes);
}
fn remove(&self) {
ffi_wifi::wifi_remove(self.chip_id);
}
fn get_stats(&self, duration_secs: u64) -> Vec<ProtoRadioStats> {
let mut stats_proto = ProtoRadioStats::new();
stats_proto.set_duration_secs(duration_secs);
stats_proto.set_kind(netsim_radio_stats::Kind::WIFI);
let chip_proto = self.get();
if chip_proto.has_wifi() {
stats_proto.set_tx_count(chip_proto.wifi().tx_count);
stats_proto.set_rx_count(chip_proto.wifi().rx_count);
}
vec![stats_proto]
}
fn get_kind(&self) -> ProtoChipKind {
ProtoChipKind::WIFI
}
fn get_facade_id(&self) -> FacadeIdentifier {
self.chip_id
}
}
/// Create a new Emulated Wifi Chip
pub fn new(
_params: &CreateParams,
_device_id: DeviceIdentifier,
chip_id: ChipIdentifier,
) -> SharedEmulatedChip {
ffi_wifi::wifi_add(chip_id);
let echip = Wifi { chip_id };
Arc::new(Box::new(echip))
}
/// Starts the WiFi service.
pub fn wifi_start(config: &MessageField<WiFiConfig>) {
if crate::config::get_dev() {
medium::test_parse_hwsim_cmd();
}
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();
}