[wlan][fidl] Add GenericSme in wlandevicemonitor and sme.
This is a new mechanism for establishing a connection to an SME. This
API will eventually fully replace the existing APIs, removing our
dependency on wlanstack.
Bug: 66772
Test: Added unit tests
Change-Id: I5648837057ec3c6a95982b78b170214be576fdfe
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/683843
API-Review: Rebecca Silberstein <silberst@google.com>
Commit-Queue: Dylan Swiggett <swiggett@google.com>
Reviewed-by: Kiet Tran <kiettran@google.com>
Reviewed-by: Rebecca Silberstein <silberst@google.com>
diff --git a/sdk/fidl/fuchsia.wlan.device.service/service.fidl b/sdk/fidl/fuchsia.wlan.device.service/service.fidl
index c8d6601..210c82a 100644
--- a/sdk/fidl/fuchsia.wlan.device.service/service.fidl
+++ b/sdk/fidl/fuchsia.wlan.device.service/service.fidl
@@ -75,6 +75,7 @@
phy_id uint16;
assigned_iface_id uint16;
iface client_end:fuchsia.wlan.mlme.MLME;
+ generic_sme server_end:fuchsia.wlan.sme.GenericSme;
};
type AddIfaceResponse = struct {
@@ -294,4 +295,21 @@
}) -> (struct {
status int32;
});
+
+ // SME methods
+ GetClientSme(struct {
+ iface_id uint16;
+ }) -> (resource struct {
+ sme client_end:fuchsia.wlan.sme.ClientSme;
+ }) error zx.status;
+ GetApSme(struct {
+ iface_id uint16;
+ }) -> (resource struct {
+ sme client_end:fuchsia.wlan.sme.ApSme;
+ }) error zx.status;
+ GetSmeTelemetry(struct {
+ iface_id uint16;
+ }) -> (resource struct {
+ sme client_end:fuchsia.wlan.sme.Telemetry;
+ }) error zx.status;
};
diff --git a/sdk/fidl/fuchsia.wlan.sme/BUILD.gn b/sdk/fidl/fuchsia.wlan.sme/BUILD.gn
index c4514fb..7a86000 100644
--- a/sdk/fidl/fuchsia.wlan.sme/BUILD.gn
+++ b/sdk/fidl/fuchsia.wlan.sme/BUILD.gn
@@ -19,6 +19,7 @@
"//sdk/fidl/fuchsia.wlan.ieee80211",
"//sdk/fidl/fuchsia.wlan.internal",
"//sdk/fidl/fuchsia.wlan.mesh",
+ "//sdk/fidl/fuchsia.wlan.stats",
"//zircon/vdso/zx",
]
}
diff --git a/sdk/fidl/fuchsia.wlan.sme/sme.fidl b/sdk/fidl/fuchsia.wlan.sme/sme.fidl
index fded336..3731da7 100644
--- a/sdk/fidl/fuchsia.wlan.sme/sme.fidl
+++ b/sdk/fidl/fuchsia.wlan.sme/sme.fidl
@@ -8,6 +8,7 @@
using fuchsia.wlan.ieee80211 as ieee80211;
using fuchsia.wlan.internal;
using fuchsia.wlan.mesh;
+using fuchsia.wlan.stats;
using zx;
/// Security protection which should mirror the Protection enum defined in wlan lib common
@@ -296,3 +297,24 @@
path fuchsia.wlan.mesh.MeshPathTable;
});
};
+
+protocol Telemetry {
+ GetCounterStats() -> (struct {
+ stats fuchsia.wlan.stats.IfaceCounterStats;
+ }) error zx.status;
+ GetHistogramStats() -> (struct {
+ stats fuchsia.wlan.stats.IfaceHistogramStats;
+ }) error zx.status;
+};
+
+protocol GenericSme {
+ GetClientSme() -> (resource struct {
+ sme client_end:ClientSme;
+ }) error zx.status;
+ GetApSme() -> (resource struct {
+ sme client_end:ApSme;
+ }) error zx.status;
+ GetSmeTelemetry() -> (resource struct {
+ sme client_end:Telemetry;
+ }) error zx.status;
+};
diff --git a/src/connectivity/wlan/lib/sme/src/serve/mod.rs b/src/connectivity/wlan/lib/sme/src/serve/mod.rs
index 2b86252..90cec97 100644
--- a/src/connectivity/wlan/lib/sme/src/serve/mod.rs
+++ b/src/connectivity/wlan/lib/sme/src/serve/mod.rs
@@ -9,10 +9,14 @@
use {
crate::{MlmeRequest, MlmeStream, Station},
anyhow::format_err,
+ fidl::endpoints::create_endpoints,
fidl_fuchsia_wlan_common as fidl_common,
fidl_fuchsia_wlan_mlme::{self as fidl_mlme, MlmeEventStream, MlmeProxy},
+ fidl_fuchsia_wlan_sme as fidl_sme,
fuchsia_inspect_contrib::auto_persist,
+ fuchsia_zircon as zx,
futures::{channel::mpsc, future::FutureObj, prelude::*, select},
+ log::{error, warn},
std::marker::Unpin,
std::sync::{Arc, Mutex},
wlan_common::{
@@ -25,12 +29,76 @@
pub type ApSmeServer = mpsc::UnboundedSender<ap::Endpoint>;
pub type MeshSmeServer = mpsc::UnboundedSender<mesh::Endpoint>;
+#[derive(Clone)]
pub enum SmeServer {
Client(ClientSmeServer),
Ap(ApSmeServer),
Mesh(MeshSmeServer),
}
+async fn serve_generic_sme(
+ generic_sme: fidl::endpoints::ServerEnd<fidl_sme::GenericSmeMarker>,
+ mut sme_server: SmeServer,
+) -> Result<(), anyhow::Error> {
+ let mut generic_sme_stream = match generic_sme.into_stream() {
+ Ok(stream) => stream,
+ Err(e) => return Err(format_err!("Failed to handle Generic SME stream: {}", e)),
+ };
+ loop {
+ match generic_sme_stream.next().await {
+ // Right now we only support one API per-sme, but in the future we plan to support
+ // multiple and this fn will be more useful.
+ Some(Ok(req)) => {
+ let result = match req {
+ fidl_sme::GenericSmeRequest::GetClientSme { responder } => {
+ let (client_end, server_end) =
+ create_endpoints::<fidl_sme::ClientSmeMarker>()
+ .expect("failed to create ClientSme");
+ let mut response = if let SmeServer::Client(server) = &mut sme_server {
+ server
+ .send(server_end)
+ .await
+ .map(|_| client_end)
+ .map_err(|_| zx::Status::PEER_CLOSED.into_raw())
+ } else {
+ Err(zx::Status::NOT_SUPPORTED.into_raw())
+ };
+ responder.send(&mut response)
+ }
+ fidl_sme::GenericSmeRequest::GetApSme { responder } => {
+ let (client_end, server_end) = create_endpoints::<fidl_sme::ApSmeMarker>()
+ .expect("failed to create ApSme");
+ let mut response = if let SmeServer::Ap(server) = &mut sme_server {
+ server
+ .send(server_end)
+ .await
+ .map(|_| client_end)
+ .map_err(|_| zx::Status::PEER_CLOSED.into_raw())
+ } else {
+ Err(zx::Status::NOT_SUPPORTED.into_raw())
+ };
+ responder.send(&mut response)
+ }
+ fidl_sme::GenericSmeRequest::GetSmeTelemetry { responder } => {
+ // TODO(fxbug.dev/66772): Support SME Telemetry API
+ warn!("Requested unsupported SME telemetry API");
+ responder.send(&mut Err(zx::Status::NOT_SUPPORTED.into_raw()))
+ }
+ };
+ if let Err(e) = result {
+ error!("Failed to respond to SME handle request: {}", e);
+ }
+ }
+ Some(Err(e)) => {
+ return Err(format_err!("Generic SME stream failed: {}", e));
+ }
+ None => {
+ return Err(format_err!("Generic SME stream terminated"));
+ }
+ }
+ }
+}
+
pub fn create_sme(
cfg: crate::Config,
mlme_proxy: fidl_mlme::MlmeProxy,
@@ -42,6 +110,7 @@
hasher: WlanHasher,
persistence_req_sender: auto_persist::PersistenceReqSender,
mut shutdown_receiver: mpsc::Receiver<()>,
+ generic_sme: fidl::endpoints::ServerEnd<fidl_sme::GenericSmeMarker>,
) -> (SmeServer, impl Future<Output = Result<(), anyhow::Error>>) {
let device_info = device_info.clone();
let event_stream = mlme_proxy.take_event_stream();
@@ -75,9 +144,11 @@
(SmeServer::Mesh(sender), FutureObj::new(Box::new(fut)))
}
};
+ let generic_sme_fut = serve_generic_sme(generic_sme, server.clone());
let sme_fut_with_shutdown = async move {
select! {
sme_fut = sme_fut.fuse() => sme_fut,
+ generic_sme_fut = generic_sme_fut.fuse() => generic_sme_fut,
_ = shutdown_receiver.select_next_some() => Ok(()),
}
};
@@ -162,7 +233,7 @@
fuchsia_inspect::Inspector,
futures::task::Poll,
pin_utils::pin_mut,
- std::sync::Arc,
+ std::{pin::Pin, sync::Arc},
wlan_common::{
assert_variant,
test_utils::fake_features::{
@@ -185,6 +256,8 @@
let (persistence_req_sender, _persistence_stream) =
test_utils::create_inspect_persistence_channel();
let (mut shutdown_sender, shutdown_receiver) = mpsc::channel(1);
+ let (_generic_sme_proxy, generic_sme_server) =
+ create_proxy::<fidl_sme::GenericSmeMarker>().expect("failed to create MlmeProxy");
let (_sme_server, serve_fut) = create_sme(
crate::Config::default(),
mlme_proxy,
@@ -196,6 +269,7 @@
WlanHasher::new(PLACEHOLDER_HASH_KEY),
persistence_req_sender,
shutdown_receiver,
+ generic_sme_server,
);
pin_mut!(serve_fut);
assert_variant!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
@@ -208,7 +282,7 @@
}
#[test]
- fn sme_close_endpoint() {
+ fn sme_close_endpoints() {
let mut exec = fasync::TestExecutor::new().expect("failed to create an executor");
let (mlme_proxy, _mlme_server) =
create_proxy::<MlmeMarker>().expect("failed to create MlmeProxy");
@@ -217,6 +291,8 @@
let (persistence_req_sender, _persistence_stream) =
test_utils::create_inspect_persistence_channel();
let (_shutdown_sender, shutdown_receiver) = mpsc::channel(1);
+ let (generic_sme_proxy, generic_sme_server) =
+ create_proxy::<fidl_sme::GenericSmeMarker>().expect("failed to create MlmeProxy");
let (mut sme_server, serve_fut) = create_sme(
crate::Config::default(),
mlme_proxy,
@@ -228,6 +304,7 @@
WlanHasher::new(PLACEHOLDER_HASH_KEY),
persistence_req_sender,
shutdown_receiver,
+ generic_sme_server,
);
pin_mut!(serve_fut);
assert_variant!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
@@ -242,7 +319,123 @@
pin_mut!(close_fut);
assert_variant!(exec.run_until_stalled(&mut close_fut), Poll::Ready(_));
+ // Also close secondary SME endpoint in the Generic SME.
+ drop(generic_sme_proxy);
+
// Verify SME future is finished
assert_variant!(exec.run_until_stalled(&mut serve_fut), Poll::Ready(Err(_)));
}
+
+ struct GenericSmeTestHelper {
+ proxy: fidl_sme::GenericSmeProxy,
+ // These values must stay in scope or the SME will terminate, but they
+ // are not relevant to Generic SME tests.
+ _inspector: Inspector,
+ _shutdown_sender: mpsc::Sender<()>,
+ _persistence_stream: mpsc::Receiver<String>,
+ _mlme_server: fidl::endpoints::ServerEnd<fidl_mlme::MlmeMarker>,
+ // Executor goes last to avoid test shutdown failures.
+ exec: fasync::TestExecutor,
+ }
+
+ fn start_generic_sme_test(
+ role: fidl_common::WlanMacRole,
+ ) -> (GenericSmeTestHelper, Pin<Box<impl Future<Output = Result<(), anyhow::Error>>>>) {
+ let mut exec = fasync::TestExecutor::new().expect("failed to create an executor");
+ let inspector = Inspector::new();
+ let (mlme_proxy, mlme_server) =
+ create_proxy::<MlmeMarker>().expect("failed to create MlmeProxy");
+ let iface_tree_holder = IfaceTreeHolder::new(inspector.root().create_child("sme"));
+ let (persistence_req_sender, persistence_stream) =
+ test_utils::create_inspect_persistence_channel();
+ let (shutdown_sender, shutdown_receiver) = mpsc::channel(1);
+ let (generic_sme_proxy, generic_sme_server) =
+ create_proxy::<fidl_sme::GenericSmeMarker>().expect("failed to create MlmeProxy");
+ let device_info = fidl_mlme::DeviceInfo { role, ..test_utils::fake_device_info([0; 6]) };
+ let (_sme_server, serve_fut) = create_sme(
+ crate::Config::default(),
+ mlme_proxy,
+ &device_info,
+ fake_mac_sublayer_support(),
+ fake_security_support(),
+ fake_spectrum_management_support_empty(),
+ Arc::new(iface_tree_holder),
+ WlanHasher::new(PLACEHOLDER_HASH_KEY),
+ persistence_req_sender,
+ shutdown_receiver,
+ generic_sme_server,
+ );
+ let mut serve_fut = Box::pin(serve_fut);
+ assert_variant!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
+
+ (
+ GenericSmeTestHelper {
+ proxy: generic_sme_proxy,
+ _inspector: inspector,
+ _shutdown_sender: shutdown_sender,
+ _persistence_stream: persistence_stream,
+ _mlme_server: mlme_server,
+ exec,
+ },
+ serve_fut,
+ )
+ }
+
+ #[test]
+ fn generic_sme_get_client() {
+ let (mut helper, mut serve_fut) = start_generic_sme_test(fidl_common::WlanMacRole::Client);
+
+ let mut client_sme_fut = helper.proxy.get_client_sme();
+ assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
+ let client_sme = assert_variant!(helper.exec.run_until_stalled(&mut client_sme_fut), Poll::Ready(Ok(Ok(sme))) => sme);
+ let client_proxy = client_sme.into_proxy().unwrap();
+
+ let mut status_fut = client_proxy.status();
+ assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
+ assert_variant!(
+ helper.exec.run_until_stalled(&mut status_fut),
+ Poll::Ready(Ok(fidl_sme::ClientStatusResponse::Idle(_)))
+ );
+ }
+
+ #[test]
+ fn generic_sme_get_ap_from_client_fails() {
+ let (mut helper, mut serve_fut) = start_generic_sme_test(fidl_common::WlanMacRole::Client);
+
+ let mut client_sme_fut = helper.proxy.get_ap_sme();
+ assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
+ assert_variant!(
+ helper.exec.run_until_stalled(&mut client_sme_fut),
+ Poll::Ready(Ok(Err(_)))
+ );
+ }
+
+ #[test]
+ fn generic_sme_get_ap() {
+ let (mut helper, mut serve_fut) = start_generic_sme_test(fidl_common::WlanMacRole::Ap);
+
+ let mut client_sme_fut = helper.proxy.get_ap_sme();
+ assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
+ let ap_sme = assert_variant!(helper.exec.run_until_stalled(&mut client_sme_fut), Poll::Ready(Ok(Ok(sme))) => sme);
+ let ap_proxy = ap_sme.into_proxy().unwrap();
+
+ let mut status_fut = ap_proxy.status();
+ assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
+ assert_variant!(
+ helper.exec.run_until_stalled(&mut status_fut),
+ Poll::Ready(Ok(fidl_sme::ApStatusResponse { .. }))
+ );
+ }
+
+ #[test]
+ fn generic_sme_get_client_from_ap_fails() {
+ let (mut helper, mut serve_fut) = start_generic_sme_test(fidl_common::WlanMacRole::Ap);
+
+ let mut client_sme_fut = helper.proxy.get_client_sme();
+ assert_variant!(helper.exec.run_until_stalled(&mut serve_fut), Poll::Pending);
+ assert_variant!(
+ helper.exec.run_until_stalled(&mut client_sme_fut),
+ Poll::Ready(Ok(Err(_)))
+ );
+ }
}
diff --git a/src/connectivity/wlan/wlandevicemonitor/BUILD.gn b/src/connectivity/wlan/wlandevicemonitor/BUILD.gn
index 83dab1b..352db7b 100644
--- a/src/connectivity/wlan/wlandevicemonitor/BUILD.gn
+++ b/src/connectivity/wlan/wlandevicemonitor/BUILD.gn
@@ -30,6 +30,7 @@
"//sdk/fidl/fuchsia.wlan.device.service:fuchsia.wlan.device.service-rustc",
"//sdk/fidl/fuchsia.wlan.ieee80211:fuchsia.wlan.ieee80211-rustc",
"//sdk/fidl/fuchsia.wlan.mlme:fuchsia.wlan.mlme-rustc",
+ "//sdk/fidl/fuchsia.wlan.sme:fuchsia.wlan.sme-rustc",
"//sdk/fidl/fuchsia.wlan.tap:fuchsia.wlan.tap-rustc",
"//sdk/lib/device-watcher/rust",
"//src/connectivity/wlan/lib/common/rust/:wlan-common",
diff --git a/src/connectivity/wlan/wlandevicemonitor/src/device.rs b/src/connectivity/wlan/wlandevicemonitor/src/device.rs
index c04f7c2..25b0637 100644
--- a/src/connectivity/wlan/wlandevicemonitor/src/device.rs
+++ b/src/connectivity/wlan/wlandevicemonitor/src/device.rs
@@ -4,7 +4,7 @@
use {
anyhow::{format_err, Error},
- fidl_fuchsia_wlan_device as fidl_wlan_dev,
+ fidl_fuchsia_wlan_device as fidl_wlan_dev, fidl_fuchsia_wlan_sme as fidl_wlan_sme,
fuchsia_inspect_contrib::inspect_log,
futures::{
future::FutureExt,
@@ -34,6 +34,8 @@
pub id: u16,
// Information about this iface's PHY.
pub phy_ownership: PhyOwnership,
+ // The handle for connecting channels to this iface's SME.
+ pub generic_sme: fidl_wlan_sme::GenericSmeProxy,
}
pub struct PhyDevice {
@@ -43,6 +45,7 @@
pub struct IfaceDevice {
pub phy_ownership: PhyOwnership,
+ pub generic_sme: fidl_wlan_sme::GenericSmeProxy,
}
pub type PhyMap = WatchableMap<u16, PhyDevice>;
diff --git a/src/connectivity/wlan/wlandevicemonitor/src/service.rs b/src/connectivity/wlan/wlandevicemonitor/src/service.rs
index 0ee6c58..1e2b252 100644
--- a/src/connectivity/wlan/wlandevicemonitor/src/service.rs
+++ b/src/connectivity/wlan/wlandevicemonitor/src/service.rs
@@ -11,7 +11,7 @@
fidl::endpoints::create_endpoints,
fidl_fuchsia_wlan_common as fidl_common, fidl_fuchsia_wlan_device as fidl_dev,
fidl_fuchsia_wlan_device_service::{self as fidl_svc, DeviceMonitorRequest},
- fidl_fuchsia_wlan_mlme as fidl_mlme, fuchsia_zircon as zx,
+ fidl_fuchsia_wlan_mlme as fidl_mlme, fidl_fuchsia_wlan_sme as fidl_sme, fuchsia_zircon as zx,
futures::TryStreamExt,
log::{error, info},
std::sync::Arc,
@@ -61,7 +61,10 @@
info!("iface #{} started ({:?})", new_iface.id, new_iface.phy_ownership);
ifaces.insert(
new_iface.id,
- IfaceDevice { phy_ownership: new_iface.phy_ownership },
+ IfaceDevice {
+ phy_ownership: new_iface.phy_ownership,
+ generic_sme: new_iface.generic_sme,
+ },
);
let resp = fidl_svc::CreateIfaceResponse { iface_id: new_iface.id };
@@ -75,6 +78,18 @@
let status = into_status_and_opt(result).0;
responder.send(status.into_raw())
}
+ DeviceMonitorRequest::GetClientSme { iface_id, responder } => {
+ let result = get_client_sme(&ifaces, iface_id).await;
+ responder.send(&mut result.map_err(|e| e.into_raw()))
+ }
+ DeviceMonitorRequest::GetApSme { iface_id, responder } => {
+ let result = get_ap_sme(&ifaces, iface_id).await;
+ responder.send(&mut result.map_err(|e| e.into_raw()))
+ }
+ DeviceMonitorRequest::GetSmeTelemetry { iface_id, responder } => {
+ let result = get_sme_telemetry(&ifaces, iface_id).await;
+ responder.send(&mut result.map_err(|e| e.into_raw()))
+ }
}?;
}
@@ -217,11 +232,22 @@
})?;
zx::Status::ok(r.status)?;
+ let (generic_sme_client, generic_sme_server) = create_endpoints::<fidl_sme::GenericSmeMarker>()
+ .map_err(|e| {
+ error!("failed to create GenericSmeProxy: {}", e);
+ zx::Status::INTERNAL
+ })?;
+ let generic_sme_proxy = generic_sme_client.into_proxy().map_err(|e| {
+ error!("Error creating GenericSmeProxy: {}", e);
+ zx::Status::INTERNAL
+ })?;
+
let (status, iface_id) = dev_svc
.add_iface(&mut fidl_svc::AddIfaceRequest {
phy_id,
assigned_iface_id: r.iface_id,
iface: mlme_client,
+ generic_sme: generic_sme_server,
})
.await
.map_err(|e| {
@@ -234,6 +260,7 @@
Ok(NewIface {
id: added_iface.iface_id,
phy_ownership: device::PhyOwnership { phy_id, phy_assigned_id: r.iface_id },
+ generic_sme: generic_sme_proxy,
})
}
@@ -266,6 +293,45 @@
zx::Status::ok(r.status)
}
+async fn get_client_sme(
+ ifaces: &IfaceMap,
+ id: u16,
+) -> Result<fidl::endpoints::ClientEnd<fidl_sme::ClientSmeMarker>, zx::Status> {
+ info!("get_client_sme(id = {})", id);
+ let iface = ifaces.get(&id).ok_or(zx::Status::NOT_FOUND)?;
+ let result = iface.generic_sme.get_client_sme().await.map_err(|e| {
+ error!("Failed to request client SME: {}", e);
+ zx::Status::INTERNAL
+ })?;
+ result.map_err(|e| zx::Status::from_raw(e))
+}
+
+async fn get_ap_sme(
+ ifaces: &IfaceMap,
+ id: u16,
+) -> Result<fidl::endpoints::ClientEnd<fidl_sme::ApSmeMarker>, zx::Status> {
+ info!("get_ap_sme(id = {})", id);
+ let iface = ifaces.get(&id).ok_or(zx::Status::NOT_FOUND)?;
+ let result = iface.generic_sme.get_ap_sme().await.map_err(|e| {
+ error!("Failed to request AP SME: {}", e);
+ zx::Status::INTERNAL
+ })?;
+ result.map_err(|e| zx::Status::from_raw(e))
+}
+
+async fn get_sme_telemetry(
+ ifaces: &IfaceMap,
+ id: u16,
+) -> Result<fidl::endpoints::ClientEnd<fidl_sme::TelemetryMarker>, zx::Status> {
+ info!("get_sme_telemetry(id = {})", id);
+ let iface = ifaces.get(&id).ok_or(zx::Status::NOT_FOUND)?;
+ let result = iface.generic_sme.get_sme_telemetry().await.map_err(|e| {
+ error!("Failed to request SME telemetry: {}", e);
+ zx::Status::INTERNAL
+ })?;
+ result.map_err(|e| zx::Status::from_raw(e))
+}
+
fn into_status_and_opt<T>(r: Result<T, zx::Status>) -> (zx::Status, Option<T>) {
match r {
Ok(x) => (zx::Status::OK, Some(x)),
@@ -278,7 +344,7 @@
use {
super::*,
crate::device::PhyOwnership,
- fidl::endpoints::create_proxy,
+ fidl::endpoints::{create_proxy, create_proxy_and_stream},
fidl_fuchsia_wlan_common as fidl_wlan_common, fuchsia_async as fasync,
futures::{future::BoxFuture, task::Poll, StreamExt},
ieee80211::NULL_MAC_ADDR,
@@ -698,9 +764,14 @@
pin_mut!(next_fut);
assert_variant!(exec.run_until_stalled(&mut next_fut), Poll::Pending);
+ // Create a generic SME proxy but drop the server since we won't use it.
+ let (generic_sme, _) = create_proxy::<fidl_sme::GenericSmeMarker>()
+ .expect("Failed to create generic SME proxy");
// Add an interface and make sure the update is received.
- let fake_iface =
- IfaceDevice { phy_ownership: PhyOwnership { phy_id: 0, phy_assigned_id: 0 } };
+ let fake_iface = IfaceDevice {
+ phy_ownership: PhyOwnership { phy_id: 0, phy_assigned_id: 0 },
+ generic_sme,
+ };
test_values.ifaces.insert(0, fake_iface);
assert_variant!(exec.run_until_stalled(&mut watcher_fut), Poll::Pending);
assert_variant!(
@@ -735,9 +806,14 @@
assert_variant!(exec.run_until_stalled(&mut service_fut), Poll::Pending);
+ // Create a generic SME proxy but drop the server since we won't use it.
+ let (generic_sme, _) = create_proxy::<fidl_sme::GenericSmeMarker>()
+ .expect("Failed to create generic SME proxy");
// Add an interface before beginning to watch for devices.
- let fake_iface =
- IfaceDevice { phy_ownership: PhyOwnership { phy_id: 0, phy_assigned_id: 0 } };
+ let fake_iface = IfaceDevice {
+ phy_ownership: PhyOwnership { phy_id: 0, phy_assigned_id: 0 },
+ generic_sme,
+ };
test_values.ifaces.insert(0, fake_iface);
assert_variant!(exec.run_until_stalled(&mut watcher_fut), Poll::Pending);
@@ -1206,9 +1282,15 @@
) -> fidl_dev::PhyRequestStream {
let (phy, phy_stream) = fake_phy();
phy_map.insert(10, phy);
+ // Create a generic SME proxy but drop the server since we won't use it.
+ let (proxy, _) = create_proxy::<fidl_sme::GenericSmeMarker>()
+ .expect("Failed to create generic SME proxy");
iface_map.insert(
42,
- device::IfaceDevice { phy_ownership: PhyOwnership { phy_id: 10, phy_assigned_id: 0 } },
+ device::IfaceDevice {
+ phy_ownership: PhyOwnership { phy_id: 10, phy_assigned_id: 0 },
+ generic_sme: proxy,
+ },
);
phy_stream
}
@@ -1311,4 +1393,106 @@
pin_mut!(fut);
assert_eq!(Poll::Ready(Err(zx::Status::NOT_FOUND)), exec.run_until_stalled(&mut fut));
}
+
+ #[test]
+ fn get_client_sme() {
+ let mut exec = fasync::TestExecutor::new().expect("Failed to create an executor");
+ let test_values = test_setup();
+ let (phy, _phy_stream) = fake_phy();
+ let phy_id = 10u16;
+ test_values.phys.insert(phy_id, phy);
+ let (generic_sme_proxy, mut generic_sme_stream) =
+ create_proxy_and_stream::<fidl_sme::GenericSmeMarker>()
+ .expect("Failed to create generic SME proxy and stream");
+
+ test_values.ifaces.insert(
+ 42,
+ device::IfaceDevice {
+ phy_ownership: PhyOwnership { phy_id: 10, phy_assigned_id: 0 },
+ generic_sme: generic_sme_proxy,
+ },
+ );
+
+ let req_fut = super::get_client_sme(&test_values.ifaces, 42);
+ pin_mut!(req_fut);
+ assert_eq!(Poll::Pending, exec.run_until_stalled(&mut req_fut));
+
+ let (client_sme_client, client_sme_server) =
+ create_endpoints::<fidl_sme::ClientSmeMarker>().expect("Failed to create client SME");
+
+ // Respond to a client SME request with a client endpoint.
+ assert_variant!(exec.run_until_stalled(&mut generic_sme_stream.next()),
+ Poll::Ready(Some(Ok(fidl_sme::GenericSmeRequest::GetClientSme { responder }))) => {
+ responder.send(&mut Ok(client_sme_client)).expect("Failed to send response");
+ }
+ );
+ let client_sme = assert_variant!(exec.run_until_stalled(&mut req_fut), Poll::Ready(Ok(client_sme)) => client_sme);
+
+ // Verify that the correct endpoint was returned.
+ let client_sme_proxy = client_sme.into_proxy().expect("Failed to get client SME proxy");
+ let _status_req = client_sme_proxy.status();
+
+ let mut client_sme_stream =
+ client_sme_server.into_stream().expect("Failed to get client SME stream");
+ assert_variant!(
+ exec.run_until_stalled(&mut client_sme_stream.next()),
+ Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Status { .. })))
+ );
+ }
+
+ #[test]
+ fn get_client_sme_fails() {
+ let mut exec = fasync::TestExecutor::new().expect("Failed to create an executor");
+ let test_values = test_setup();
+ let (phy, _phy_stream) = fake_phy();
+ let phy_id = 10u16;
+ test_values.phys.insert(phy_id, phy);
+ let (generic_sme_proxy, generic_sme_server) = create_proxy::<fidl_sme::GenericSmeMarker>()
+ .expect("Failed to create generic SME proxy");
+
+ test_values.ifaces.insert(
+ 42,
+ device::IfaceDevice {
+ phy_ownership: PhyOwnership { phy_id: 10, phy_assigned_id: 0 },
+ generic_sme: generic_sme_proxy,
+ },
+ );
+
+ let req_fut = super::get_client_sme(&test_values.ifaces, 42);
+ pin_mut!(req_fut);
+ assert_eq!(Poll::Pending, exec.run_until_stalled(&mut req_fut));
+
+ // Respond to a client SME request with an error.
+ let mut generic_sme_stream =
+ generic_sme_server.into_stream().expect("Failed to create generic SME stream");
+ assert_variant!(exec.run_until_stalled(&mut generic_sme_stream.next()),
+ Poll::Ready(Some(Ok(fidl_sme::GenericSmeRequest::GetClientSme { responder }))) => {
+ responder.send(&mut Err(1)).expect("Failed to send response");
+ }
+ );
+ assert_variant!(exec.run_until_stalled(&mut req_fut), Poll::Ready(Err(_)));
+ }
+
+ #[test]
+ fn get_client_sme_invalid_iface() {
+ let mut exec = fasync::TestExecutor::new().expect("Failed to create an executor");
+ let test_values = test_setup();
+ let (phy, _phy_stream) = fake_phy();
+ let phy_id = 10u16;
+ test_values.phys.insert(phy_id, phy);
+ let (generic_sme_proxy, _generic_sme_server) = create_proxy::<fidl_sme::GenericSmeMarker>()
+ .expect("Failed to create generic SME proxy");
+
+ test_values.ifaces.insert(
+ 42,
+ device::IfaceDevice {
+ phy_ownership: PhyOwnership { phy_id: 10, phy_assigned_id: 0 },
+ generic_sme: generic_sme_proxy,
+ },
+ );
+
+ let req_fut = super::get_client_sme(&test_values.ifaces, 1337);
+ pin_mut!(req_fut);
+ assert_variant!(exec.run_until_stalled(&mut req_fut), Poll::Ready(Err(_)));
+ }
}
diff --git a/src/connectivity/wlan/wlanstack/src/device.rs b/src/connectivity/wlan/wlanstack/src/device.rs
index f9e456b..9e854a9 100644
--- a/src/connectivity/wlan/wlanstack/src/device.rs
+++ b/src/connectivity/wlan/wlanstack/src/device.rs
@@ -5,6 +5,7 @@
use {
anyhow::{format_err, Error},
fidl_fuchsia_wlan_common as fidl_common, fidl_fuchsia_wlan_mlme as fidl_mlme,
+ fidl_fuchsia_wlan_sme as fidl_sme,
fuchsia_inspect_contrib::{auto_persist, inspect_log},
futures::{channel::mpsc, future::Future},
log::info,
@@ -89,6 +90,7 @@
spectrum_management_support: fidl_common::SpectrumManagementSupport,
dev_monitor_proxy: fidl_fuchsia_wlan_device_service::DeviceMonitorProxy,
persistence_req_sender: auto_persist::PersistenceReqSender,
+ generic_sme: fidl::endpoints::ServerEnd<fidl_sme::GenericSmeMarker>,
) -> Result<impl Future<Output = Result<(), Error>>, Error> {
let (shutdown_sender, shutdown_receiver) = mpsc::channel(1);
let (sme, sme_fut) = create_sme(
@@ -102,6 +104,7 @@
inspect_tree.hasher.clone(),
persistence_req_sender,
shutdown_receiver,
+ generic_sme,
);
info!("new iface #{} with role '{:?}'", id, device_info.role);
@@ -214,6 +217,8 @@
.expect("failed to create DeviceMonitor proxy");
let (persistence_req_sender, _persistence_stream) =
test_helper::create_inspect_persistence_channel();
+ let (generic_sme_proxy, generic_sme_server) =
+ create_proxy::<fidl_sme::GenericSmeMarker>().expect("failed to create MlmeProxy");
// Assert that the IfaceMap is initially empty.
assert!(iface_map.get(&5).is_none());
@@ -232,6 +237,7 @@
fake_spectrum_management_support_empty(),
dev_monitor_proxy,
persistence_req_sender,
+ generic_sme_server,
)
.expect("failed to create SME");
@@ -256,6 +262,7 @@
pin_mut!(close_fut);
let fut_result = exec.run_until_stalled(&mut close_fut);
assert_variant!(fut_result, Poll::Ready(_), "expected closing SME to succeed");
+ drop(generic_sme_proxy);
// Insert iface back into map.
let (mlme_proxy, _) = create_proxy::<MlmeMarker>().expect("failed to create MlmeProxy");
@@ -303,6 +310,8 @@
.expect("failed to create DeviceMonitor request stream");
let (persistence_req_sender, _persistence_stream) =
test_helper::create_inspect_persistence_channel();
+ let (_generic_sme_proxy, generic_sme_server) =
+ create_proxy::<fidl_sme::GenericSmeMarker>().expect("failed to create MlmeProxy");
// Assert that the IfaceMap is initially empty.
assert!(iface_map.get(&5).is_none());
@@ -321,6 +330,7 @@
fake_spectrum_management_support_empty(),
dev_monitor_proxy,
persistence_req_sender,
+ generic_sme_server,
)
.expect("failed to create SME");
diff --git a/src/connectivity/wlan/wlanstack/src/service.rs b/src/connectivity/wlan/wlanstack/src/service.rs
index 45ccd49..0d856b3 100644
--- a/src/connectivity/wlan/wlanstack/src/service.rs
+++ b/src/connectivity/wlan/wlanstack/src/service.rs
@@ -431,6 +431,7 @@
spectrum_management_support,
dev_monitor_proxy,
persistence_req_sender,
+ req.generic_sme,
) {
Ok(fut) => fut,
Err(e) => return AddIfaceResult::from_error(e, zx::sys::ZX_ERR_INTERNAL),
@@ -964,13 +965,19 @@
let cfg = ServiceCfg { wep_supported: false, wpa1_supported: false };
let (persistence_req_sender, _persistence_stream) =
test_helper::create_inspect_persistence_channel();
+ let (_generic_sme_proxy, generic_sme) =
+ create_proxy::<fidl_sme::GenericSmeMarker>().expect("failed to create MlmeProxy");
// Construct the request.
let (mlme_channel, mlme_receiver) =
create_endpoints().expect("failed to create fake MLME proxy");
let mut mlme_stream = mlme_receiver.into_stream().expect("failed to create MLME stream");
- let req =
- fidl_svc::AddIfaceRequest { phy_id: 123, assigned_iface_id: 456, iface: mlme_channel };
+ let req = fidl_svc::AddIfaceRequest {
+ phy_id: 123,
+ assigned_iface_id: 456,
+ iface: mlme_channel,
+ generic_sme,
+ };
let fut = add_iface(
req,
&cfg,
@@ -1041,6 +1048,8 @@
let cfg = ServiceCfg { wep_supported: false, wpa1_supported: false };
let (persistence_req_sender, _persistence_stream) =
test_helper::create_inspect_persistence_channel();
+ let (_generic_sme_proxy, generic_sme) =
+ create_proxy::<fidl_sme::GenericSmeMarker>().expect("failed to create MlmeProxy");
// Construct the request.
let (mlme_channel, mlme_receiver) =
@@ -1049,8 +1058,12 @@
// Drop the receiver so that the initial device info query fails.
drop(mlme_receiver);
- let req =
- fidl_svc::AddIfaceRequest { phy_id: 123, assigned_iface_id: 456, iface: mlme_channel };
+ let req = fidl_svc::AddIfaceRequest {
+ phy_id: 123,
+ assigned_iface_id: 456,
+ iface: mlme_channel,
+ generic_sme,
+ };
let fut = add_iface(
req,
&cfg,
@@ -1084,14 +1097,20 @@
let cfg = ServiceCfg { wep_supported: false, wpa1_supported: false };
let (persistence_req_sender, _persistence_stream) =
test_helper::create_inspect_persistence_channel();
+ let (_generic_sme_proxy, generic_sme) =
+ create_proxy::<fidl_sme::GenericSmeMarker>().expect("failed to create MlmeProxy");
// Construct the request.
let (mlme_channel, mlme_receiver) =
create_endpoints().expect("failed to create fake MLME proxy");
let mut mlme_stream = mlme_receiver.into_stream().expect("failed to create MLME stream");
- let req =
- fidl_svc::AddIfaceRequest { phy_id: 123, assigned_iface_id: 456, iface: mlme_channel };
+ let req = fidl_svc::AddIfaceRequest {
+ phy_id: 123,
+ assigned_iface_id: 456,
+ iface: mlme_channel,
+ generic_sme,
+ };
let fut = add_iface(
req,
&cfg,