fullmac_helpers/
lib.rs

1// Copyright 2024 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use assert_matches::assert_matches;
6use fidl::endpoints::{create_endpoints, create_proxy};
7use futures::StreamExt;
8use std::sync::LazyLock;
9use wlan_common::test_utils::fake_stas::FakeProtectionCfg;
10use wlan_common::{bss, fake_fidl_bss_description};
11use {
12    fidl_fuchsia_wlan_fullmac as fidl_fullmac, fidl_fuchsia_wlan_sme as fidl_sme,
13    fidl_test_wlan_testcontroller as fidl_testcontroller,
14};
15
16pub mod config;
17pub mod fake_ap;
18pub mod recorded_request_stream;
19
20// Compatible BSS descriptions are defined here.
21// "Compatible" here means that that an SME  with default configuration
22// will accept a connect request to a BSS with the returned BssDescription.
23pub static COMPATIBLE_OPEN_BSS: LazyLock<bss::BssDescription> = LazyLock::new(|| {
24    fake_fidl_bss_description!(
25        protection => FakeProtectionCfg::Open,
26        channel: wlan_common::channel::Channel::new(1, wlan_common::channel::Cbw::Cbw20),
27        rates: vec![2, 4, 11],
28    )
29    .try_into()
30    .expect("Could not convert BSS description from FIDL")
31});
32pub static COMPATIBLE_WPA2_BSS: LazyLock<bss::BssDescription> = LazyLock::new(|| {
33    fake_fidl_bss_description!(
34        protection => FakeProtectionCfg::Wpa2,
35        channel: wlan_common::channel::Channel::new(1, wlan_common::channel::Cbw::Cbw20),
36        rates: vec![2, 4, 11],
37    )
38    .try_into()
39    .expect("Could not convert BSS description from FIDL")
40});
41pub static COMPATIBLE_WPA3_BSS: LazyLock<bss::BssDescription> = LazyLock::new(|| {
42    fake_fidl_bss_description!(
43        protection => FakeProtectionCfg::Wpa3,
44        channel: wlan_common::channel::Channel::new(1, wlan_common::channel::Cbw::Cbw20),
45        rates: vec![2, 4, 11],
46    )
47    .try_into()
48    .expect("Could not convert BSS description from FIDL")
49});
50
51/// Creates and starts fullmac driver using |testcontroller_proxy|.
52/// This handles the request to start SME through the UsmeBootstrap protocol,
53/// and the sequence of query requests that SME makes to the fullmac driver on startup.
54///
55/// After this function is called, the fullmac driver is ready to be used in the test suite.
56pub async fn create_fullmac_driver(
57    testcontroller_proxy: &fidl_testcontroller::TestControllerProxy,
58    config: &config::FullmacDriverConfig,
59) -> (
60    fidl_testcontroller::FullmacId,
61    fidl_fullmac::WlanFullmacImpl_RequestStream,
62    fidl_fullmac::WlanFullmacImplIfcProxy,
63    fidl_sme::GenericSmeProxy,
64) {
65    let (fullmac_bridge_client, fullmac_bridge_server) = create_endpoints();
66
67    let fullmac_id = testcontroller_proxy
68        .create_fullmac(fullmac_bridge_client)
69        .await
70        .expect("FIDL error on create_fullmac")
71        .expect("TestController returned an error on create fullmac");
72
73    let mut fullmac_bridge_stream = fullmac_bridge_server.into_stream();
74
75    // Fullmac MLME queries driver before starting
76    let (fullmac_ifc_proxy, generic_sme_proxy) =
77        handle_fullmac_startup(&mut fullmac_bridge_stream, config).await;
78
79    (fullmac_id, fullmac_bridge_stream, fullmac_ifc_proxy, generic_sme_proxy)
80}
81
82pub async fn handle_fullmac_startup(
83    fullmac_bridge_stream: &mut fidl_fullmac::WlanFullmacImpl_RequestStream,
84    config: &config::FullmacDriverConfig,
85) -> (fidl_fullmac::WlanFullmacImplIfcProxy, fidl_sme::GenericSmeProxy) {
86    let (usme_bootstrap_proxy, usme_bootstrap_server) =
87        create_proxy::<fidl_sme::UsmeBootstrapMarker>();
88
89    let fullmac_ifc_proxy = assert_matches!(fullmac_bridge_stream.next().await,
90        Some(Ok(fidl_fullmac::WlanFullmacImpl_Request::Init { payload, responder })) => {
91            responder
92                .send(Ok(fidl_fullmac::WlanFullmacImplInitResponse {
93                    sme_channel: Some(usme_bootstrap_server.into_channel()),
94                    ..Default::default()
95                }))
96                .expect("Failed to respond to Init");
97            let ifc = payload.ifc.expect("Init response missing ifc");
98            ifc.into_proxy()
99        }
100    );
101
102    let (generic_sme_proxy, generic_sme_server) = create_proxy::<fidl_sme::GenericSmeMarker>();
103
104    let _bootstrap_result = usme_bootstrap_proxy
105        .start(generic_sme_server, &config.sme_legacy_privacy_support)
106        .await
107        .expect("Failed to call usme_bootstrap.start");
108
109    assert_matches!(fullmac_bridge_stream.next().await,
110        Some(Ok(fidl_fullmac::WlanFullmacImpl_Request::Query { responder })) => {
111            responder
112                .send(Ok(&config.query_info))
113                .expect("Failed to respond to Query");
114        }
115    );
116
117    assert_matches!(fullmac_bridge_stream.next().await,
118        Some(Ok(fidl_fullmac::WlanFullmacImpl_Request::QuerySecuritySupport {
119            responder,
120        })) => {
121            responder
122                .send(Ok(&config.security_support))
123                .expect("Failed to respond to QuerySecuritySupport");
124        }
125    );
126
127    assert_matches!(fullmac_bridge_stream.next().await,
128        Some(Ok(fidl_fullmac::WlanFullmacImpl_Request::QuerySpectrumManagementSupport {
129                responder,
130        })) => {
131            responder
132                .send(Ok(&config.spectrum_management_support))
133                .expect("Failed to respond to QuerySpectrumManagementSupport");
134        }
135    );
136
137    assert_matches!(fullmac_bridge_stream.next().await,
138        Some(Ok(fidl_fullmac::WlanFullmacImpl_Request::Query { responder })) => {
139            responder
140                .send(Ok(&config.query_info))
141                .expect("Failed to respond to Query");
142        }
143    );
144
145    (fullmac_ifc_proxy, generic_sme_proxy)
146}