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