1*cf78ab8cSAndroid Build Coastguard Worker // Copyright 2023 Google LLC 2*cf78ab8cSAndroid Build Coastguard Worker // 3*cf78ab8cSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); 4*cf78ab8cSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License. 5*cf78ab8cSAndroid Build Coastguard Worker // You may obtain a copy of the License at 6*cf78ab8cSAndroid Build Coastguard Worker // 7*cf78ab8cSAndroid Build Coastguard Worker // https://www.apache.org/licenses/LICENSE-2.0 8*cf78ab8cSAndroid Build Coastguard Worker // 9*cf78ab8cSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software 10*cf78ab8cSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, 11*cf78ab8cSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*cf78ab8cSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and 13*cf78ab8cSAndroid Build Coastguard Worker // limitations under the License. 14*cf78ab8cSAndroid Build Coastguard Worker 15*cf78ab8cSAndroid Build Coastguard Worker use crate::wifi::hwsim_attr_set::HwsimAttrSet; 16*cf78ab8cSAndroid Build Coastguard Worker use anyhow::Context; 17*cf78ab8cSAndroid Build Coastguard Worker use netsim_packets::ieee80211::{Ieee80211, MacAddress}; 18*cf78ab8cSAndroid Build Coastguard Worker use netsim_packets::mac80211_hwsim::{HwsimCmd, HwsimMsg, TxRate}; 19*cf78ab8cSAndroid Build Coastguard Worker use pdl_runtime::Packet; 20*cf78ab8cSAndroid Build Coastguard Worker 21*cf78ab8cSAndroid Build Coastguard Worker /// Parser for the hwsim Frame command (HWSIM_CMD_FRAME). 22*cf78ab8cSAndroid Build Coastguard Worker /// 23*cf78ab8cSAndroid Build Coastguard Worker /// The Frame command is sent by the kernel's mac80211_hwsim subsystem 24*cf78ab8cSAndroid Build Coastguard Worker /// and contains the IEEE 802.11 frame along with hwsim attributes. 25*cf78ab8cSAndroid Build Coastguard Worker /// 26*cf78ab8cSAndroid Build Coastguard Worker /// This module parses the required and optional hwsim attributes and 27*cf78ab8cSAndroid Build Coastguard Worker /// returns errors if any required attributes are missing. 28*cf78ab8cSAndroid Build Coastguard Worker 29*cf78ab8cSAndroid Build Coastguard Worker // The Frame struct contains parsed attributes along with the raw and 30*cf78ab8cSAndroid Build Coastguard Worker // parsed 802.11 frame in `data` and `ieee80211.` 31*cf78ab8cSAndroid Build Coastguard Worker #[derive(Debug)] 32*cf78ab8cSAndroid Build Coastguard Worker pub struct Frame { 33*cf78ab8cSAndroid Build Coastguard Worker pub transmitter: Option<MacAddress>, 34*cf78ab8cSAndroid Build Coastguard Worker pub flags: Option<u32>, 35*cf78ab8cSAndroid Build Coastguard Worker pub tx_info: Option<Vec<TxRate>>, 36*cf78ab8cSAndroid Build Coastguard Worker pub cookie: Option<u64>, 37*cf78ab8cSAndroid Build Coastguard Worker pub signal: Option<u32>, 38*cf78ab8cSAndroid Build Coastguard Worker pub freq: Option<u32>, 39*cf78ab8cSAndroid Build Coastguard Worker pub data: Vec<u8>, 40*cf78ab8cSAndroid Build Coastguard Worker pub ieee80211: Ieee80211, 41*cf78ab8cSAndroid Build Coastguard Worker pub hwsim_msg: HwsimMsg, 42*cf78ab8cSAndroid Build Coastguard Worker pub attrs: HwsimAttrSet, 43*cf78ab8cSAndroid Build Coastguard Worker } 44*cf78ab8cSAndroid Build Coastguard Worker 45*cf78ab8cSAndroid Build Coastguard Worker impl Frame { 46*cf78ab8cSAndroid Build Coastguard Worker // Builds and validates the Frame from the attributes in the 47*cf78ab8cSAndroid Build Coastguard Worker // packet. Called when a hwsim packet with HwsimCmd::Frame is 48*cf78ab8cSAndroid Build Coastguard Worker // found. parse(msg: &HwsimMsg) -> anyhow::Result<Frame>49*cf78ab8cSAndroid Build Coastguard Worker pub fn parse(msg: &HwsimMsg) -> anyhow::Result<Frame> { 50*cf78ab8cSAndroid Build Coastguard Worker // Only expected to be called with HwsimCmd::Frame 51*cf78ab8cSAndroid Build Coastguard Worker if msg.hwsim_hdr.hwsim_cmd != HwsimCmd::Frame { 52*cf78ab8cSAndroid Build Coastguard Worker panic!("Invalid hwsim_cmd"); 53*cf78ab8cSAndroid Build Coastguard Worker } 54*cf78ab8cSAndroid Build Coastguard Worker let attrs = HwsimAttrSet::parse(&msg.attributes).context("HwsimAttrSet")?; 55*cf78ab8cSAndroid Build Coastguard Worker let frame = attrs.frame.clone().context("Frame")?; 56*cf78ab8cSAndroid Build Coastguard Worker let ieee80211 = Ieee80211::decode_full(&frame).context("Ieee80211")?; 57*cf78ab8cSAndroid Build Coastguard Worker // Required attributes are unwrapped and return an error if 58*cf78ab8cSAndroid Build Coastguard Worker // they are not present. 59*cf78ab8cSAndroid Build Coastguard Worker Ok(Frame { 60*cf78ab8cSAndroid Build Coastguard Worker transmitter: attrs.transmitter, 61*cf78ab8cSAndroid Build Coastguard Worker flags: attrs.flags, 62*cf78ab8cSAndroid Build Coastguard Worker tx_info: attrs.tx_info.clone(), 63*cf78ab8cSAndroid Build Coastguard Worker cookie: attrs.cookie, 64*cf78ab8cSAndroid Build Coastguard Worker signal: attrs.signal, 65*cf78ab8cSAndroid Build Coastguard Worker freq: attrs.freq, 66*cf78ab8cSAndroid Build Coastguard Worker data: frame, 67*cf78ab8cSAndroid Build Coastguard Worker ieee80211, 68*cf78ab8cSAndroid Build Coastguard Worker hwsim_msg: msg.clone(), 69*cf78ab8cSAndroid Build Coastguard Worker attrs, 70*cf78ab8cSAndroid Build Coastguard Worker }) 71*cf78ab8cSAndroid Build Coastguard Worker } 72*cf78ab8cSAndroid Build Coastguard Worker } 73