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