1mod akm_algorithm;
14pub mod ap;
15pub mod auth;
16mod block_ack;
17pub mod client;
18mod ddk_converter;
19pub mod device;
20pub mod disconnect;
21pub mod error;
22mod minstrel;
23mod probe_sequence;
24
25use anyhow::{Error, bail, format_err};
26pub use ddk_converter::*;
27use device::DeviceOps;
28use fidl_fuchsia_wlan_common as fidl_common;
29pub use fidl_fuchsia_wlan_ieee80211 as fidl_ieee80211;
30use fidl_fuchsia_wlan_softmac as fidl_softmac;
31use fuchsia_sync::Mutex;
32use fuchsia_trace as trace;
33use futures::channel::mpsc::{self, TrySendError};
34use futures::channel::oneshot;
35use futures::{Future, StreamExt, select};
36use log::info;
37use std::fmt;
38use std::sync::Arc;
39use std::time::Duration;
40pub use wlan_common as common;
41use wlan_ffi_transport::{EthernetTxEvent, EthernetTxEventSender, WlanRxEvent, WlanRxEventSender};
42use wlan_fidl_ext::{ResponderExt, SendResultExt};
43use wlan_trace as wtrace;
44
45trait WlanTxPacketExt {
46 fn template(mac_frame: Vec<u8>) -> Self;
47}
48
49impl WlanTxPacketExt for fidl_softmac::WlanTxPacket {
50 fn template(mac_frame: Vec<u8>) -> Self {
51 fidl_softmac::WlanTxPacket {
52 mac_frame,
53 info: fidl_softmac::WlanTxInfo {
57 tx_flags: 0,
58 valid_fields: 0,
59 tx_vector_idx: 0,
60 phy: fidl_ieee80211::WlanPhyType::Dsss,
61 bandwidth: fidl_ieee80211::ChannelBandwidth::Cbw20,
62 mcs: 0,
63 },
64 }
65 }
66}
67
68pub trait MlmeImpl {
69 type Config;
70 type Device: DeviceOps;
71 type TimerEvent;
72 fn new(
73 config: Self::Config,
74 device: Self::Device,
75 scheduler: common::timer::Timer<Self::TimerEvent>,
76 ) -> impl Future<Output = Result<Self, Error>>
77 where
78 Self: Sized;
79 fn handle_mlme_request(
80 &mut self,
81 msg: wlan_sme::MlmeRequest,
82 ) -> impl Future<Output = Result<(), Error>>;
83 fn handle_mac_frame_rx(
84 &mut self,
85 bytes: &[u8],
86 rx_info: fidl_softmac::WlanRxInfo,
87 async_id: trace::Id,
88 ) -> impl Future<Output = ()>;
89 fn handle_eth_frame_tx(&mut self, bytes: &[u8], async_id: trace::Id) -> Result<(), Error>;
90 fn handle_scan_complete(
91 &mut self,
92 status: zx::Status,
93 scan_id: u64,
94 ) -> impl Future<Output = ()>;
95 fn handle_timeout(&mut self, event: Self::TimerEvent) -> impl Future<Output = ()>;
96}
97
98pub struct MinstrelTimer {
99 timer: wlan_common::timer::Timer<()>,
100 current_timer: Option<common::timer::EventHandle>,
101}
102
103impl minstrel::TimerManager for MinstrelTimer {
104 fn schedule(&mut self, from_now: Duration) {
105 self.current_timer.replace(self.timer.schedule_after(from_now.into(), ()));
106 }
107 fn cancel(&mut self) {
108 self.current_timer.take();
109 }
110}
111
112type MinstrelWrapper = Arc<Mutex<minstrel::MinstrelRateSelector<MinstrelTimer>>>;
113
114#[derive(Clone)]
120pub struct DriverEventSink(mpsc::UnboundedSender<DriverEvent>);
121
122impl DriverEventSink {
123 pub fn new() -> (Self, mpsc::UnboundedReceiver<DriverEvent>) {
124 let (sink, stream) = mpsc::unbounded();
125 (Self(sink), stream)
126 }
127
128 pub fn unbounded_send(
129 &self,
130 driver_event: DriverEvent,
131 ) -> Result<(), TrySendError<DriverEvent>> {
132 self.0.unbounded_send(driver_event)
133 }
134
135 pub fn disconnect(&mut self) {
136 self.0.disconnect()
137 }
138
139 pub fn unbounded_send_or_respond<R>(
140 &self,
141 driver_event: DriverEvent,
142 responder: R,
143 response: R::Response<'_>,
144 ) -> Result<R, anyhow::Error>
145 where
146 R: ResponderExt,
147 {
148 match self.unbounded_send(driver_event) {
149 Err(e) => {
150 let error_string = e.to_string();
151 let event = e.into_inner();
152 let e = format_err!("Failed to queue {}: {}", event, error_string);
153
154 match responder.send(response).format_send_err() {
155 Ok(()) => Err(e),
156 Err(send_error) => Err(send_error.context(e)),
157 }
158 }
159 Ok(()) => Ok(responder),
160 }
161 }
162}
163
164impl EthernetTxEventSender for DriverEventSink {
165 fn unbounded_send(&self, event: EthernetTxEvent) -> Result<(), (String, EthernetTxEvent)> {
166 DriverEventSink::unbounded_send(self, DriverEvent::EthernetTxEvent(event)).map_err(|e| {
167 if let (error, DriverEvent::EthernetTxEvent(event)) =
168 (format!("{:?}", e), e.into_inner())
169 {
170 (error, event)
171 } else {
172 unreachable!();
173 }
174 })
175 }
176}
177
178impl WlanRxEventSender for DriverEventSink {
179 fn unbounded_send(&self, event: WlanRxEvent) -> Result<(), (String, WlanRxEvent)> {
180 DriverEventSink::unbounded_send(self, DriverEvent::WlanRxEvent(event)).map_err(|e| {
181 if let (error, DriverEvent::WlanRxEvent(event)) = (format!("{:?}", e), e.into_inner()) {
182 (error, event)
183 } else {
184 unreachable!();
185 }
186 })
187 }
188}
189
190pub enum DriverEvent {
191 Stop { responder: fidl_softmac::WlanSoftmacIfcBridgeStopBridgedDriverResponder },
193 ScanComplete { status: zx::Status, scan_id: u64 },
195 TxResultReport { tx_result: fidl_softmac::WlanTxResult },
197 EthernetTxEvent(EthernetTxEvent),
198 WlanRxEvent(WlanRxEvent),
199}
200
201impl fmt::Display for DriverEvent {
202 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
203 write!(
204 f,
205 "{}",
206 match self {
207 DriverEvent::Stop { .. } => "Stop",
208 DriverEvent::ScanComplete { .. } => "ScanComplete",
209 DriverEvent::TxResultReport { .. } => "TxResultReport",
210 DriverEvent::EthernetTxEvent(EthernetTxEvent { .. }) => "EthernetTxEvent",
211 DriverEvent::WlanRxEvent(WlanRxEvent { .. }) => "WlanRxEvent",
212 }
213 )
214 }
215}
216
217impl fmt::Debug for DriverEvent {
222 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
223 write!(
224 f,
225 "{}",
226 match self {
227 DriverEvent::Stop { .. } => "Stop",
228 DriverEvent::ScanComplete { .. } => "ScanComplete",
229 DriverEvent::TxResultReport { .. } => "TxResultReport",
230 DriverEvent::EthernetTxEvent(EthernetTxEvent { .. }) => "EthernetTxEvent",
231 DriverEvent::WlanRxEvent(WlanRxEvent { .. }) => "WlanRxEvent",
232 }
233 )
234 }
235}
236
237fn should_enable_minstrel(mac_sublayer: &fidl_common::MacSublayerSupport) -> bool {
238 mac_sublayer
239 .device
240 .as_ref()
241 .and_then(|device| device.tx_status_report_supported)
242 .unwrap_or(false)
243 && !mac_sublayer
244 .rate_selection_offload
245 .as_ref()
246 .and_then(|selection| selection.supported)
247 .unwrap_or(false)
248}
249
250const MINSTREL_UPDATE_INTERVAL: std::time::Duration = std::time::Duration::from_millis(100);
251const MINSTREL_UPDATE_INTERVAL_HW_SIM: std::time::Duration = std::time::Duration::from_millis(83);
258
259pub async fn mlme_main_loop<T: MlmeImpl>(
260 init_sender: oneshot::Sender<()>,
261 config: T::Config,
262 mut device: T::Device,
263 mlme_request_stream: mpsc::UnboundedReceiver<wlan_sme::MlmeRequest>,
264 driver_event_stream: mpsc::UnboundedReceiver<DriverEvent>,
265) -> Result<(), Error> {
266 info!("Starting MLME main loop...");
267 let (minstrel_timer, minstrel_time_stream) = common::timer::create_timer();
268 let minstrel = device.mac_sublayer_support().await.ok().filter(should_enable_minstrel).map(
269 |mac_sublayer_support| {
270 let minstrel = Arc::new(Mutex::new(minstrel::MinstrelRateSelector::new(
271 MinstrelTimer { timer: minstrel_timer, current_timer: None },
272 if mac_sublayer_support
273 .device
274 .and_then(|device| device.is_synthetic)
275 .unwrap_or(false)
276 {
277 MINSTREL_UPDATE_INTERVAL_HW_SIM
278 } else {
279 MINSTREL_UPDATE_INTERVAL
280 },
281 probe_sequence::ProbeSequence::random_new(),
282 )));
283 device.set_minstrel(minstrel.clone());
284 minstrel
285 },
286 );
287 let (timer, time_stream) = common::timer::create_timer();
288
289 let mlme_impl = T::new(config, device, timer).await.expect("Failed to create MLME.");
292
293 info!("MLME initialization complete!");
294 init_sender.send(()).map_err(|_| format_err!("Failed to signal init complete."))?;
295
296 main_loop_impl(
297 mlme_impl,
298 minstrel,
299 mlme_request_stream,
300 driver_event_stream,
301 time_stream,
302 minstrel_time_stream,
303 )
304 .await
305}
306
307async fn main_loop_impl<T: MlmeImpl>(
311 mut mlme_impl: T,
312 minstrel: Option<MinstrelWrapper>,
313 mut mlme_request_stream: mpsc::UnboundedReceiver<wlan_sme::MlmeRequest>,
315 mut driver_event_stream: mpsc::UnboundedReceiver<DriverEvent>,
318 time_stream: common::timer::EventStream<T::TimerEvent>,
319 minstrel_time_stream: common::timer::EventStream<()>,
320) -> Result<(), Error> {
321 let mut timer_stream = common::timer::make_async_timed_event_stream(time_stream).fuse();
322 let mut minstrel_timer_stream =
323 common::timer::make_async_timed_event_stream(minstrel_time_stream).fuse();
324
325 loop {
326 select! {
327 mlme_request = mlme_request_stream.next() => match mlme_request {
329 Some(req) => {
330 let method_name = req.name();
331 if let Err(e) = mlme_impl.handle_mlme_request(req).await {
332 info!("Failed to handle mlme {} request: {}", method_name, e);
333 }
334 },
335 None => bail!("MLME request stream terminated unexpectedly."),
336 },
337 driver_event = driver_event_stream.next() => match driver_event {
339 Some(event) => match event {
340 DriverEvent::Stop {responder} => {
342 responder.send().format_send_err_with_context("Stop")?;
343 return Ok(())
344 },
345 DriverEvent::ScanComplete { status, scan_id } => {
346 mlme_impl.handle_scan_complete(status, scan_id).await
347 },
348 DriverEvent::TxResultReport { tx_result } => {
349 if let Some(minstrel) = minstrel.as_ref() {
350 minstrel.lock().handle_tx_result_report(&tx_result)
351 }
352 }
353 DriverEvent::EthernetTxEvent(EthernetTxEvent { bytes, async_id, borrowed_operation }) => {
354 wtrace::duration!("DriverEvent::EthernetTxEvent");
355 let bytes: &[u8] = unsafe { &*bytes.as_ptr() };
356 match mlme_impl.handle_eth_frame_tx(&bytes[..], async_id) {
357 Ok(()) => borrowed_operation.reply(Ok(())),
358 Err(e) => {
359 info!("Failed to handle eth frame: {}", e);
361 wtrace::async_end_wlansoftmac_tx(async_id, zx::Status::INTERNAL);
362 borrowed_operation.reply(Err(zx::Status::INTERNAL));
363 }
364 }
365 }
366 DriverEvent::WlanRxEvent(WlanRxEvent { bytes, rx_info, async_id }) => {
367 wtrace::duration!("DriverEvent::WlanRxEvent");
368 mlme_impl.handle_mac_frame_rx(&bytes[..], rx_info, async_id).await;
369 }
370
371
372 },
373 None => bail!("Driver event stream terminated unexpectedly."),
374 },
375 timed_event = timer_stream.select_next_some() => {
376 mlme_impl.handle_timeout(timed_event.event).await;
377 }
378 _minstrel_timeout = minstrel_timer_stream.select_next_some() => {
379 if let Some(minstrel) = minstrel.as_ref() {
380 minstrel.lock().handle_timeout()
381 }
382 }
383 }
384 }
385}
386
387#[cfg(test)]
388pub mod test_utils {
389 use super::*;
390 use crate::device::FakeDevice;
391 use fidl_fuchsia_wlan_mlme as fidl_mlme;
392 use ieee80211::{MacAddr, MacAddrBytes};
393 use wlan_common::channel;
394
395 pub struct FakeMlme {}
396
397 impl MlmeImpl for FakeMlme {
398 type Config = ();
399 type Device = FakeDevice;
400 type TimerEvent = ();
401
402 async fn new(
403 _config: Self::Config,
404 _device: Self::Device,
405 _scheduler: wlan_common::timer::Timer<Self::TimerEvent>,
406 ) -> Result<Self, Error> {
407 Ok(Self {})
408 }
409
410 async fn handle_mlme_request(
411 &mut self,
412 _msg: wlan_sme::MlmeRequest,
413 ) -> Result<(), anyhow::Error> {
414 unimplemented!()
415 }
416
417 async fn handle_mac_frame_rx(
418 &mut self,
419 _bytes: &[u8],
420 _rx_info: fidl_softmac::WlanRxInfo,
421 _async_id: trace::Id,
422 ) {
423 unimplemented!()
424 }
425
426 fn handle_eth_frame_tx(
427 &mut self,
428 _bytes: &[u8],
429 _async_id: trace::Id,
430 ) -> Result<(), anyhow::Error> {
431 unimplemented!()
432 }
433
434 async fn handle_scan_complete(&mut self, _status: zx::Status, _scan_id: u64) {
435 unimplemented!()
436 }
437
438 async fn handle_timeout(&mut self, _event: Self::TimerEvent) {
439 unimplemented!()
440 }
441 }
442
443 pub(crate) fn fake_wlan_channel() -> channel::Channel {
444 channel::Channel::new(1, channel::Cbw::Cbw20, fidl_ieee80211::WlanBand::TwoGhz)
445 }
446
447 #[derive(Copy, Clone, Debug)]
448 pub struct MockWlanRxInfo {
449 pub rx_flags: fidl_softmac::WlanRxInfoFlags,
450 pub valid_fields: fidl_softmac::WlanRxInfoValid,
451 pub phy: fidl_ieee80211::WlanPhyType,
452 pub data_rate: u32,
453 pub channel: fidl_ieee80211::ChannelNumber,
454 pub mcs: u8,
455 pub rssi_dbm: i8,
456 pub snr_dbh: i16,
457 pub bandwidth: fidl_ieee80211::ChannelBandwidth,
458 pub secondary80: fidl_ieee80211::ChannelNumber,
459 }
460
461 impl MockWlanRxInfo {
462 pub(crate) fn with_channel(channel: fidl_ieee80211::ChannelNumber) -> Self {
463 Self {
464 valid_fields: fidl_softmac::WlanRxInfoValid::CHAN_WIDTH
465 | fidl_softmac::WlanRxInfoValid::RSSI
466 | fidl_softmac::WlanRxInfoValid::SNR,
467 channel,
468 rssi_dbm: -40,
469 snr_dbh: 35,
470
471 rx_flags: fidl_softmac::WlanRxInfoFlags::empty(),
474 phy: fidl_ieee80211::WlanPhyType::Dsss,
475 data_rate: 0,
476 mcs: 0,
477 bandwidth: fidl_ieee80211::ChannelBandwidth::Cbw20,
478 secondary80: fidl_ieee80211::ChannelNumber { band: channel.band, number: 0 },
479 }
480 }
481 }
482
483 impl From<MockWlanRxInfo> for fidl_softmac::WlanRxInfo {
484 fn from(mock_rx_info: MockWlanRxInfo) -> fidl_softmac::WlanRxInfo {
485 fidl_softmac::WlanRxInfo {
486 rx_flags: mock_rx_info.rx_flags,
487 valid_fields: mock_rx_info.valid_fields,
488 phy: mock_rx_info.phy,
489 data_rate: mock_rx_info.data_rate,
490 primary: mock_rx_info.channel,
491 mcs: mock_rx_info.mcs,
492 rssi_dbm: mock_rx_info.rssi_dbm,
493 snr_dbh: mock_rx_info.snr_dbh,
494 bandwidth: mock_rx_info.bandwidth,
495 vht_secondary_80_channel: mock_rx_info.secondary80,
496 }
497 }
498 }
499
500 pub(crate) fn fake_key(address: MacAddr) -> fidl_mlme::SetKeyDescriptor {
501 fidl_mlme::SetKeyDescriptor {
502 cipher_suite_oui: [1, 2, 3],
503 cipher_suite_type: fidl_ieee80211::CipherSuiteType::from_primitive_allow_unknown(4),
504 key_type: fidl_mlme::KeyType::Pairwise,
505 address: address.to_array(),
506 key_id: 6,
507 key: vec![1, 2, 3, 4, 5, 6, 7],
508 rsc: 8,
509 }
510 }
511
512 pub(crate) fn fake_set_keys_req(address: MacAddr) -> wlan_sme::MlmeRequest {
513 wlan_sme::MlmeRequest::SetKeys(fidl_mlme::SetKeysRequest {
514 keylist: vec![fake_key(address)],
515 })
516 }
517}
518
519#[cfg(test)]
520mod tests {
521 use super::device::FakeDevice;
522 use super::test_utils::FakeMlme;
523 use super::*;
524 use assert_matches::assert_matches;
525 use fuchsia_async::TestExecutor;
526 use std::task::Poll;
527
528 enum Request {
534 Ax { responder: RequestAxResponder },
535 Cx { responder: RequestCxResponder },
536 }
537
538 struct RequestAxResponder {}
539 impl RequestAxResponder {
540 fn send(self) -> Result<(), fidl::Error> {
541 Ok(())
542 }
543 }
544
545 struct RequestCxResponder {}
546 impl RequestCxResponder {
547 fn send(self, _result: Result<u64, u64>) -> Result<(), fidl::Error> {
548 Ok(())
549 }
550 }
551
552 impl ResponderExt for RequestAxResponder {
553 type Response<'a> = ();
554 const REQUEST_NAME: &'static str = stringify!(RequestAx);
555
556 fn send(self, _: Self::Response<'_>) -> Result<(), fidl::Error> {
557 Self::send(self)
558 }
559 }
560
561 impl ResponderExt for RequestCxResponder {
562 type Response<'a> = Result<u64, u64>;
563 const REQUEST_NAME: &'static str = stringify!(RequestCx);
564
565 fn send(self, response: Self::Response<'_>) -> Result<(), fidl::Error> {
566 Self::send(self, response)
567 }
568 }
569
570 #[test]
571 fn unbounded_send_or_respond_with_error_simple() {
572 let (driver_event_sink, _driver_event_stream) = DriverEventSink::new();
573 if let Request::Ax { responder } = (Request::Ax { responder: RequestAxResponder {} }) {
574 let _responder: RequestAxResponder = driver_event_sink
575 .unbounded_send_or_respond(
576 DriverEvent::ScanComplete { status: zx::Status::OK, scan_id: 3 },
577 responder,
578 (),
579 )
580 .unwrap();
581 }
582 }
583
584 #[test]
585 fn unbounded_send_or_respond_with_error_simple_with_error() {
586 let (driver_event_sink, _driver_event_stream) = DriverEventSink::new();
587 if let Request::Cx { responder } = (Request::Cx { responder: RequestCxResponder {} }) {
588 let _responder: RequestCxResponder = driver_event_sink
589 .unbounded_send_or_respond(
590 DriverEvent::ScanComplete { status: zx::Status::IO_REFUSED, scan_id: 0 },
591 responder,
592 Err(10),
593 )
594 .unwrap();
595 }
596 }
597
598 #[fuchsia::test(allow_stalls = false)]
599 async fn start_and_stop_main_loop() {
600 let (fake_device, _fake_device_state) = FakeDevice::new().await;
601 let (device_sink, device_stream) = mpsc::unbounded();
602 let (_mlme_request_sink, mlme_request_stream) = mpsc::unbounded();
603 let (init_sender, mut init_receiver) = oneshot::channel();
604 let mut main_loop = Box::pin(mlme_main_loop::<FakeMlme>(
605 init_sender,
606 (),
607 fake_device,
608 mlme_request_stream,
609 device_stream,
610 ));
611 assert_matches!(TestExecutor::poll_until_stalled(&mut main_loop).await, Poll::Pending);
612 assert_eq!(TestExecutor::poll_until_stalled(&mut init_receiver).await, Poll::Ready(Ok(())));
613
614 let (softmac_ifc_bridge_proxy, mut softmac_ifc_bridge_request_stream) =
617 fidl::endpoints::create_proxy_and_stream::<fidl_softmac::WlanSoftmacIfcBridgeMarker>();
618
619 let mut stop_response_fut = softmac_ifc_bridge_proxy.stop_bridged_driver();
620 assert_matches!(
621 TestExecutor::poll_until_stalled(&mut stop_response_fut).await,
622 Poll::Pending
623 );
624 let Some(Ok(fidl_softmac::WlanSoftmacIfcBridgeRequest::StopBridgedDriver { responder })) =
625 softmac_ifc_bridge_request_stream.next().await
626 else {
627 panic!("Did not receive StopBridgedDriver message");
628 };
629
630 device_sink
631 .unbounded_send(DriverEvent::Stop { responder })
632 .expect("Failed to send stop event");
633 assert_matches!(
634 TestExecutor::poll_until_stalled(&mut main_loop).await,
635 Poll::Ready(Ok(()))
636 );
637 assert_matches!(
638 TestExecutor::poll_until_stalled(&mut stop_response_fut).await,
639 Poll::Ready(Ok(()))
640 );
641 assert!(device_sink.is_closed());
642 }
643}