[wlan][policy] Log network selection decisions to Inspect
Logs network selection decisions to Inspect.
Bug: 74364
Test: fx test wlancfg-tests
Multiply: wlancfg-tests
Change-Id: Ie10661bbdf9093c3b268ad8887016fcf896ad511
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/514721
Reviewed-by: Charles Celerier <chcl@google.com>
Commit-Queue: Auto-Submit <auto-submit@fuchsia-infra.iam.gserviceaccount.com>
diff --git a/src/connectivity/wlan/lib/common/rust/src/hasher.rs b/src/connectivity/wlan/lib/common/rust/src/hasher.rs
index efad95f..c1a5fc5 100644
--- a/src/connectivity/wlan/lib/common/rust/src/hasher.rs
+++ b/src/connectivity/wlan/lib/common/rust/src/hasher.rs
@@ -13,7 +13,7 @@
const HASH_KEY_LEN: usize = 8;
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, PartialEq)]
/// Hasher used to hash sensitive information, preserving user privacy.
pub struct WlanHasher {
hash_key: [u8; HASH_KEY_LEN],
diff --git a/src/connectivity/wlan/wlancfg/BUILD.gn b/src/connectivity/wlan/wlancfg/BUILD.gn
index 0558f67..7267852 100644
--- a/src/connectivity/wlan/wlancfg/BUILD.gn
+++ b/src/connectivity/wlan/wlancfg/BUILD.gn
@@ -39,8 +39,10 @@
"//sdk/fidl/fuchsia.wlan.sme:fuchsia.wlan.sme-rustc",
"//sdk/fidl/fuchsia.wlan.stats:fuchsia.wlan.stats-rustc",
"//src/connectivity/wlan/lib/common/rust/:wlan-common",
+ "//src/connectivity/wlan/lib/inspect:wlan-inspect",
"//src/connectivity/wlan/lib/stash/:wlan-stash",
"//src/lib/cobalt/rust:fuchsia-cobalt",
+ "//src/lib/diagnostics/inspect/contrib/rust",
"//src/lib/diagnostics/inspect/rust",
"//src/lib/fidl/rust/fidl",
"//src/lib/fuchsia-async",
diff --git a/src/connectivity/wlan/wlancfg/src/client/mod.rs b/src/connectivity/wlan/wlancfg/src/client/mod.rs
index d93a104..5f643ba 100644
--- a/src/connectivity/wlan/wlancfg/src/client/mod.rs
+++ b/src/connectivity/wlan/wlancfg/src/client/mod.rs
@@ -489,6 +489,7 @@
async_trait::async_trait,
fidl::endpoints::{create_proxy, create_request_stream, Proxy},
fidl_fuchsia_stash as fidl_stash, fuchsia_async as fasync,
+ fuchsia_inspect::{self as inspect},
futures::{
channel::{mpsc, oneshot},
lock::Mutex,
@@ -738,6 +739,7 @@
let network_selector = Arc::new(network_selection::NetworkSelector::new(
Arc::clone(&saved_networks),
create_mock_cobalt_sender(),
+ inspect::Inspector::new().root().create_child("network_selector"),
));
let (provider, requests) = create_proxy::<fidl_policy::ClientProviderMarker>()
.expect("failed to create ClientProvider proxy");
@@ -1333,6 +1335,7 @@
let network_selector = Arc::new(network_selection::NetworkSelector::new(
Arc::clone(&saved_networks),
create_mock_cobalt_sender(),
+ inspect::Inspector::new().root().create_child("network_selector"),
));
let (provider, requests) = create_proxy::<fidl_policy::ClientProviderMarker>()
@@ -1404,6 +1407,7 @@
let network_selector = Arc::new(network_selection::NetworkSelector::new(
Arc::clone(&saved_networks),
create_mock_cobalt_sender(),
+ inspect::Inspector::new().root().create_child("network_selector"),
));
let (provider, requests) = create_proxy::<fidl_policy::ClientProviderMarker>()
@@ -1489,6 +1493,7 @@
let network_selector = Arc::new(network_selection::NetworkSelector::new(
Arc::clone(&saved_networks),
create_mock_cobalt_sender(),
+ inspect::Inspector::new().root().create_child("network_selector"),
));
let (provider, requests) = create_proxy::<fidl_policy::ClientProviderMarker>()
.expect("failed to create ClientProvider proxy");
@@ -1576,6 +1581,7 @@
let network_selector = Arc::new(network_selection::NetworkSelector::new(
Arc::clone(&saved_networks),
create_mock_cobalt_sender(),
+ inspect::Inspector::new().root().create_child("network_selector"),
));
let (provider, requests) = create_proxy::<fidl_policy::ClientProviderMarker>()
@@ -1645,6 +1651,7 @@
let network_selector = Arc::new(network_selection::NetworkSelector::new(
Arc::clone(&saved_networks),
create_mock_cobalt_sender(),
+ inspect::Inspector::new().root().create_child("network_selector"),
));
let (provider, requests) = create_proxy::<fidl_policy::ClientProviderMarker>()
.expect("failed to create ClientProvider proxy");
@@ -1808,6 +1815,7 @@
let network_selector = Arc::new(network_selection::NetworkSelector::new(
Arc::clone(&saved_networks),
create_mock_cobalt_sender(),
+ inspect::Inspector::new().root().create_child("network_selector"),
));
let (provider, requests) = create_proxy::<fidl_policy::ClientProviderMarker>()
.expect("failed to create ClientProvider proxy");
@@ -2147,6 +2155,7 @@
let network_selector = Arc::new(network_selection::NetworkSelector::new(
Arc::clone(&saved_networks),
create_mock_cobalt_sender(),
+ inspect::Inspector::new().root().create_child("network_selector"),
));
let iface_manager = Arc::new(Mutex::new(FakeIfaceManagerNoIfaces {}));
diff --git a/src/connectivity/wlan/wlancfg/src/client/network_selection.rs b/src/connectivity/wlan/wlancfg/src/client/network_selection.rs
index dfd600e..56d4fa8 100644
--- a/src/connectivity/wlan/wlancfg/src/client/network_selection.rs
+++ b/src/connectivity/wlan/wlancfg/src/client/network_selection.rs
@@ -18,12 +18,19 @@
fidl_fuchsia_wlan_internal as fidl_internal, fidl_fuchsia_wlan_policy as fidl_policy,
fidl_fuchsia_wlan_sme as fidl_sme,
fuchsia_cobalt::CobaltSender,
+ fuchsia_inspect::Node as InspectNode,
+ fuchsia_inspect_contrib::{
+ inspect_insert, inspect_log,
+ log::{InspectList, WriteInspect},
+ nodes::{BoundedListNode as InspectBoundedListNode, NodeWriter},
+ },
fuchsia_zircon as zx,
futures::lock::Mutex,
log::{debug, error, info, trace},
rand::Rng,
- std::{collections::HashMap, sync::Arc},
+ std::{collections::HashMap, convert::TryInto as _, sync::Arc},
wlan_common::{channel::Channel, hasher::WlanHasher},
+ wlan_inspect::wrappers::InspectWlanChan,
wlan_metrics_registry::{
ActiveScanRequestedForNetworkSelectionMetricDimensionActiveScanSsidsRequested as ActiveScanSsidsRequested,
SavedNetworkInScanResultMetricDimensionBssCount,
@@ -51,11 +58,15 @@
/// on a retry.
const SCORE_PENALTY_FOR_RECENT_CREDENTIAL_REJECTED: i8 = 30;
+const INSPECT_EVENT_LIMIT_FOR_NETWORK_SELECTIONS: usize = 20;
+
pub struct NetworkSelector {
saved_network_manager: Arc<SavedNetworksManager>,
scan_result_cache: Arc<Mutex<ScanResultCache>>,
cobalt_api: Arc<Mutex<CobaltSender>>,
hasher: WlanHasher,
+ _inspect_node_root: Arc<Mutex<InspectNode>>,
+ inspect_node_for_network_selections: Arc<Mutex<InspectBoundedListNode>>,
}
struct ScanResultCache {
@@ -76,6 +87,7 @@
network_info: InternalSavedNetworkData,
bss_info: &'a types::Bss,
multiple_bss_candidates: bool,
+ hasher: WlanHasher,
}
impl InternalBss<'_> {
@@ -110,28 +122,39 @@
return score.saturating_sub(failure_score);
}
- fn print_without_pii(&self, hasher: &WlanHasher) {
- let channel = Channel::from_fidl(self.bss_info.channel);
- let rssi = self.bss_info.rssi;
- let recent_failure_count = self
- .network_info
+ fn recent_failure_count(&self) -> u64 {
+ self.network_info
.recent_failures
.iter()
.filter(|failure| failure.bssid == self.bss_info.bssid)
- .collect::<Vec<_>>()
- .len();
- let security_type = match self.network_info.network_id.type_ {
+ .count()
+ .try_into()
+ .unwrap_or_else(|e| {
+ error!("{}", e);
+ u64::MAX
+ })
+ }
+
+ fn saved_security_type_to_string(&self) -> String {
+ match self.network_info.network_id.type_ {
fidl_policy::SecurityType::None => "open",
fidl_policy::SecurityType::Wep => "WEP",
fidl_policy::SecurityType::Wpa => "WPA",
fidl_policy::SecurityType::Wpa2 => "WPA2",
fidl_policy::SecurityType::Wpa3 => "WPA3",
- };
- info!(
- "{}({:4}), {}, {:>4}dBm, chan {:8}, score {:4},{}{}{}",
- hasher.hash_ssid(&self.network_info.network_id.ssid),
- security_type,
- hasher.hash_mac_addr(&self.bss_info.bssid),
+ }
+ .to_string()
+ }
+
+ fn to_string_without_pii(&self) -> String {
+ let channel = Channel::from_fidl(self.bss_info.channel);
+ let rssi = self.bss_info.rssi;
+ let recent_failure_count = self.recent_failure_count();
+ format!(
+ "{}({:4}), {}, {:>4}dBm, chan {:8}, score {:4}{}{}{}",
+ self.hasher.hash_ssid(&self.network_info.network_id.ssid),
+ self.saved_security_type_to_string(),
+ self.hasher.hash_mac_addr(&self.bss_info.bssid),
rssi,
channel,
self.score(),
@@ -145,9 +168,32 @@
)
}
}
+impl<'a> WriteInspect for InternalBss<'a> {
+ fn write_inspect(&self, writer: &mut NodeWriter<'_>, key: &str) {
+ inspect_insert!(writer, var key: {
+ ssid_hash: self.hasher.hash_ssid(&self.network_info.network_id.ssid),
+ bssid_hash: self.hasher.hash_mac_addr(&self.bss_info.bssid),
+ rssi: self.bss_info.rssi,
+ score: self.score(),
+ security_type_saved: self.saved_security_type_to_string(),
+ channel: InspectWlanChan(&self.bss_info.channel),
+ compatible: self.bss_info.compatible,
+ recent_failure_count: self.recent_failure_count(),
+ saved_network_has_ever_connected: self.network_info.has_ever_connected,
+ });
+ }
+}
impl NetworkSelector {
- pub fn new(saved_network_manager: Arc<SavedNetworksManager>, cobalt_api: CobaltSender) -> Self {
+ pub fn new(
+ saved_network_manager: Arc<SavedNetworksManager>,
+ cobalt_api: CobaltSender,
+ inspect_node: InspectNode,
+ ) -> Self {
+ let inspect_node_for_network_selection = InspectBoundedListNode::new(
+ inspect_node.create_child("network_selection"),
+ INSPECT_EVENT_LIMIT_FOR_NETWORK_SELECTIONS,
+ );
Self {
saved_network_manager,
scan_result_cache: Arc::new(Mutex::new(ScanResultCache {
@@ -156,6 +202,10 @@
})),
cobalt_api: Arc::new(Mutex::new(cobalt_api)),
hasher: WlanHasher::new(rand::thread_rng().gen::<u64>().to_le_bytes()),
+ _inspect_node_root: Arc::new(Mutex::new(inspect_node)),
+ inspect_node_for_network_selections: Arc::new(Mutex::new(
+ inspect_node_for_network_selection,
+ )),
}
}
@@ -269,10 +319,12 @@
saved_networks,
&scan_result_guard.results,
wpa3_supported,
+ &self.hasher,
)
.await;
- match select_best_connection_candidate(networks, ignore_list, &self.hasher) {
+ let mut inspect_node = self.inspect_node_for_network_selections.lock().await;
+ match select_best_connection_candidate(networks, ignore_list, &mut inspect_node) {
Some((selected, channel, bssid)) => {
Some(augment_bss_with_active_scan(selected, channel, bssid, iface_manager).await)
}
@@ -300,10 +352,12 @@
saved_networks,
&scan_results,
wpa3_supported,
+ &self.hasher,
)
.await;
let ignore_list = vec![];
- select_best_connection_candidate(networks, &ignore_list, &self.hasher).map(
+ let mut inspect_node = self.inspect_node_for_network_selections.lock().await;
+ select_best_connection_candidate(networks, &ignore_list, &mut inspect_node).map(
|(candidate, _, _)| {
// Strip out the information about passive vs active scan, because we can't know
// if this network would have been observed in a passive scan (since we never
@@ -322,6 +376,7 @@
saved_networks: HashMap<types::NetworkIdentifier, InternalSavedNetworkData>,
scan_results: &'a Vec<types::ScanResult>,
wpa3_supported: bool,
+ hasher: &WlanHasher,
) -> Vec<InternalBss<'a>> {
let mut merged_networks = vec![];
for scan_result in scan_results {
@@ -337,6 +392,7 @@
bss_info: bss,
multiple_bss_candidates,
network_info: saved_network_info.clone(),
+ hasher: hasher.clone(),
});
}
}
@@ -425,13 +481,14 @@
fn select_best_connection_candidate<'a>(
bss_list: Vec<InternalBss<'a>>,
ignore_list: &Vec<types::NetworkIdentifier>,
- hasher: &WlanHasher,
+ inspect_node: &mut InspectBoundedListNode,
) -> Option<(types::ConnectionCandidate, types::WlanChan, types::Bssid)> {
info!("Selecting from {} BSSs found for saved networks", bss_list.len());
- bss_list
- .into_iter()
+
+ let selected = bss_list
+ .iter()
.inspect(|bss| {
- bss.print_without_pii(hasher);
+ info!("{}", bss.to_string_without_pii());
})
.filter(|bss| {
// Filter out incompatible BSSs
@@ -446,22 +503,26 @@
}
true
})
- .max_by(|bss_a, bss_b| bss_a.score().partial_cmp(&bss_b.score()).unwrap())
- .map(|bss| {
- info!("Selected BSS:");
- bss.print_without_pii(hasher);
- (
- types::ConnectionCandidate {
- network: bss.network_info.network_id,
- credential: bss.network_info.credential,
- observed_in_passive_scan: Some(bss.bss_info.observed_in_passive_scan),
- bss: bss.bss_info.bss_desc.clone(),
- multiple_bss_candidates: Some(bss.multiple_bss_candidates),
- },
- bss.bss_info.channel,
- bss.bss_info.bssid,
- )
- })
+ .max_by(|bss_a, bss_b| bss_a.score().partial_cmp(&bss_b.score()).unwrap());
+
+ // Log the candidates into Inspect
+ inspect_log!(inspect_node, candidates: InspectList(&bss_list), selected?: selected);
+
+ selected.map(|bss| {
+ info!("Selected BSS:");
+ info!("{}", bss.to_string_without_pii());
+ (
+ types::ConnectionCandidate {
+ network: bss.network_info.network_id.clone(),
+ credential: bss.network_info.credential.clone(),
+ observed_in_passive_scan: Some(bss.bss_info.observed_in_passive_scan),
+ bss: bss.bss_info.bss_desc.clone(),
+ multiple_bss_candidates: Some(bss.multiple_bss_candidates),
+ },
+ bss.bss_info.channel,
+ bss.bss_info.bssid,
+ )
+ })
}
/// If a BSS was discovered via a passive scan, we need to perform an active scan on it to discover
@@ -629,6 +690,7 @@
fidl_fuchsia_wlan_common as fidl_common, fidl_fuchsia_wlan_sme as fidl_sme,
fuchsia_async as fasync,
fuchsia_cobalt::cobalt_event_builder::CobaltEventExt,
+ fuchsia_inspect::{self as inspect, assert_inspect_tree},
futures::{
channel::{mpsc, oneshot},
prelude::*,
@@ -647,6 +709,7 @@
cobalt_events: mpsc::Receiver<CobaltEvent>,
iface_manager: Arc<Mutex<FakeIfaceManager>>,
sme_stream: fidl_sme::ClientSmeRequestStream,
+ inspector: inspect::Inspector,
}
async fn test_setup() -> TestValues {
@@ -655,8 +718,14 @@
// setup modules
let (cobalt_api, cobalt_events) = create_mock_cobalt_sender_and_receiver();
let saved_network_manager = Arc::new(SavedNetworksManager::new_for_test().await.unwrap());
- let network_selector =
- Arc::new(NetworkSelector::new(Arc::clone(&saved_network_manager), cobalt_api));
+ let inspector = inspect::Inspector::new();
+ let inspect_node = inspector.root().create_child("net_select_test");
+
+ let network_selector = Arc::new(NetworkSelector::new(
+ Arc::clone(&saved_network_manager),
+ cobalt_api,
+ inspect_node,
+ ));
let (client_sme, remote) =
create_proxy::<fidl_sme::ClientSmeMarker>().expect("error creating proxy");
let iface_manager = Arc::new(Mutex::new(FakeIfaceManager::new(client_sme)));
@@ -667,6 +736,7 @@
cobalt_events,
iface_manager,
sme_stream: remote.into_stream().expect("failed to create stream"),
+ inspector,
}
}
@@ -948,6 +1018,7 @@
);
// build our expected result
+ let hasher = WlanHasher::new(rand::thread_rng().gen::<u64>().to_le_bytes());
let expected_internal_data_1 = InternalSavedNetworkData {
network_id: test_id_1.clone(),
credential: credential_1.clone(),
@@ -959,16 +1030,19 @@
network_info: expected_internal_data_1.clone(),
bss_info: &mock_scan_results[0].entries[0],
multiple_bss_candidates: true,
+ hasher: hasher.clone(),
},
InternalBss {
network_info: expected_internal_data_1.clone(),
bss_info: &mock_scan_results[0].entries[1],
multiple_bss_candidates: true,
+ hasher: hasher.clone(),
},
InternalBss {
network_info: expected_internal_data_1,
bss_info: &mock_scan_results[0].entries[2],
multiple_bss_candidates: true,
+ hasher: hasher.clone(),
},
InternalBss {
network_info: InternalSavedNetworkData {
@@ -979,12 +1053,14 @@
},
bss_info: &mock_scan_results[1].entries[0],
multiple_bss_candidates: false,
+ hasher: hasher.clone(),
},
];
// validate the function works
let result =
- merge_saved_networks_and_scan_data(saved_networks, &mock_scan_results, true).await;
+ merge_saved_networks_and_scan_data(saved_networks, &mock_scan_results, true, &hasher)
+ .await;
assert_eq!(result, expected_result);
}
@@ -1022,6 +1098,7 @@
},
bss_info: &bss,
multiple_bss_candidates: false,
+ hasher: WlanHasher::new(rand::thread_rng().gen::<u64>().to_le_bytes()),
};
assert_eq!(internal_bss.score(), expected_score)
@@ -1042,11 +1119,13 @@
network_info: internal_data.clone(),
bss_info: &bss_info_worse,
multiple_bss_candidates: true,
+ hasher: WlanHasher::new(rand::thread_rng().gen::<u64>().to_le_bytes()),
};
let bss_better = InternalBss {
network_info: internal_data,
bss_info: &bss_info_better,
multiple_bss_candidates: true,
+ hasher: WlanHasher::new(rand::thread_rng().gen::<u64>().to_le_bytes()),
};
// Check that the better BSS has a higher score than the worse BSS.
assert!(bss_better.score() > bss_worse.score());
@@ -1068,11 +1147,13 @@
network_info: internal_data.clone(),
bss_info: &bss_info_worse,
multiple_bss_candidates: false,
+ hasher: WlanHasher::new(rand::thread_rng().gen::<u64>().to_le_bytes()),
};
let bss_better = InternalBss {
network_info: internal_data,
bss_info: &bss_info_better,
multiple_bss_candidates: false,
+ hasher: WlanHasher::new(rand::thread_rng().gen::<u64>().to_le_bytes()),
};
assert!(bss_better.score() > bss_worse.score());
}
@@ -1100,11 +1181,13 @@
network_info: internal_data.clone(),
bss_info: &bss_info_worse,
multiple_bss_candidates: true,
+ hasher: WlanHasher::new(rand::thread_rng().gen::<u64>().to_le_bytes()),
};
let bss_better = InternalBss {
network_info: internal_data,
bss_info: &bss_info_better,
multiple_bss_candidates: true,
+ hasher: WlanHasher::new(rand::thread_rng().gen::<u64>().to_le_bytes()),
};
assert!(bss_better.score() > bss_worse.score());
@@ -1112,6 +1195,10 @@
#[test]
fn select_best_connection_candidate_sorts_by_score() {
+ // generate Inspect nodes
+ let inspector = inspect::Inspector::new();
+ let mut inspect_node =
+ InspectBoundedListNode::new(inspector.root().create_child("test"), 10);
// build networks list
let test_id_1 = types::NetworkIdentifier {
ssid: "foo".as_bytes().to_vec(),
@@ -1141,6 +1228,7 @@
},
bss_info: &bss_info1,
multiple_bss_candidates: true,
+ hasher: WlanHasher::new(rand::thread_rng().gen::<u64>().to_le_bytes()),
});
let bss_info2 = types::Bss {
@@ -1158,6 +1246,7 @@
},
bss_info: &bss_info2,
multiple_bss_candidates: true,
+ hasher: WlanHasher::new(rand::thread_rng().gen::<u64>().to_le_bytes()),
});
let bss_info3 = types::Bss {
@@ -1175,15 +1264,12 @@
},
bss_info: &bss_info3,
multiple_bss_candidates: false,
+ hasher: WlanHasher::new(rand::thread_rng().gen::<u64>().to_le_bytes()),
});
// there's a network on 5G, it should get a boost and be selected
assert_eq!(
- select_best_connection_candidate(
- networks.clone(),
- &vec![],
- &WlanHasher::new(rand::thread_rng().gen::<u64>().to_le_bytes())
- ),
+ select_best_connection_candidate(networks.clone(), &vec![], &mut inspect_node),
Some((
types::ConnectionCandidate {
network: test_id_1.clone(),
@@ -1206,11 +1292,7 @@
// all networks are 2.4GHz, strongest RSSI network returned
assert_eq!(
- select_best_connection_candidate(
- networks.clone(),
- &vec![],
- &WlanHasher::new(rand::thread_rng().gen::<u64>().to_le_bytes())
- ),
+ select_best_connection_candidate(networks.clone(), &vec![], &mut inspect_node),
Some((
types::ConnectionCandidate {
network: test_id_2.clone(),
@@ -1227,6 +1309,10 @@
#[test]
fn select_best_connection_candidate_sorts_by_failure_count() {
+ // generate Inspect nodes
+ let inspector = inspect::Inspector::new();
+ let mut inspect_node =
+ InspectBoundedListNode::new(inspector.root().create_child("test"), 10);
// build networks list
let test_id_1 = types::NetworkIdentifier {
ssid: "foo".as_bytes().to_vec(),
@@ -1256,6 +1342,7 @@
},
bss_info: &bss_info1,
multiple_bss_candidates: false,
+ hasher: WlanHasher::new(rand::thread_rng().gen::<u64>().to_le_bytes()),
});
let bss_info2 = types::Bss {
@@ -1273,15 +1360,12 @@
},
bss_info: &bss_info2,
multiple_bss_candidates: false,
+ hasher: WlanHasher::new(rand::thread_rng().gen::<u64>().to_le_bytes()),
});
// stronger network returned
assert_eq!(
- select_best_connection_candidate(
- networks.clone(),
- &vec![],
- &WlanHasher::new(rand::thread_rng().gen::<u64>().to_le_bytes())
- ),
+ select_best_connection_candidate(networks.clone(), &vec![], &mut inspect_node),
Some((
types::ConnectionCandidate {
network: test_id_1.clone(),
@@ -1304,11 +1388,7 @@
// weaker network (with no failures) returned
assert_eq!(
- select_best_connection_candidate(
- networks.clone(),
- &vec![],
- &WlanHasher::new(rand::thread_rng().gen::<u64>().to_le_bytes())
- ),
+ select_best_connection_candidate(networks.clone(), &vec![], &mut inspect_node),
Some((
types::ConnectionCandidate {
network: test_id_2.clone(),
@@ -1328,11 +1408,7 @@
// stronger network returned
assert_eq!(
- select_best_connection_candidate(
- networks.clone(),
- &vec![],
- &WlanHasher::new(rand::thread_rng().gen::<u64>().to_le_bytes())
- ),
+ select_best_connection_candidate(networks.clone(), &vec![], &mut inspect_node),
Some((
types::ConnectionCandidate {
network: test_id_1.clone(),
@@ -1349,6 +1425,10 @@
#[test]
fn select_best_connection_candidate_incompatible() {
+ // generate Inspect nodes
+ let inspector = inspect::Inspector::new();
+ let mut inspect_node =
+ InspectBoundedListNode::new(inspector.root().create_child("test"), 10);
// build networks list
let test_id_1 = types::NetworkIdentifier {
ssid: "foo".as_bytes().to_vec(),
@@ -1378,6 +1458,7 @@
},
bss_info: &bss_info1,
multiple_bss_candidates: true,
+ hasher: WlanHasher::new(rand::thread_rng().gen::<u64>().to_le_bytes()),
});
let bss_info2 = types::Bss {
@@ -1395,6 +1476,7 @@
},
bss_info: &bss_info2,
multiple_bss_candidates: true,
+ hasher: WlanHasher::new(rand::thread_rng().gen::<u64>().to_le_bytes()),
});
let bss_info3 = types::Bss {
@@ -1412,15 +1494,12 @@
},
bss_info: &bss_info3,
multiple_bss_candidates: false,
+ hasher: WlanHasher::new(rand::thread_rng().gen::<u64>().to_le_bytes()),
});
// stronger network returned
assert_eq!(
- select_best_connection_candidate(
- networks.clone(),
- &vec![],
- &WlanHasher::new(rand::thread_rng().gen::<u64>().to_le_bytes())
- ),
+ select_best_connection_candidate(networks.clone(), &vec![], &mut inspect_node),
Some((
types::ConnectionCandidate {
network: test_id_2.clone(),
@@ -1443,11 +1522,7 @@
// other network returned
assert_eq!(
- select_best_connection_candidate(
- networks.clone(),
- &vec![],
- &WlanHasher::new(rand::thread_rng().gen::<u64>().to_le_bytes())
- ),
+ select_best_connection_candidate(networks.clone(), &vec![], &mut inspect_node),
Some((
types::ConnectionCandidate {
network: test_id_1.clone(),
@@ -1464,6 +1539,10 @@
#[test]
fn select_best_connection_candidate_ignore_list() {
+ // generate Inspect nodes
+ let inspector = inspect::Inspector::new();
+ let mut inspect_node =
+ InspectBoundedListNode::new(inspector.root().create_child("test"), 10);
// build networks list
let test_id_1 = types::NetworkIdentifier {
ssid: "foo".as_bytes().to_vec(),
@@ -1488,6 +1567,7 @@
},
bss_info: &bss_info1,
multiple_bss_candidates: false,
+ hasher: WlanHasher::new(rand::thread_rng().gen::<u64>().to_le_bytes()),
});
let bss_info2 = types::Bss { compatible: true, rssi: -12, ..generate_random_bss() };
@@ -1500,15 +1580,12 @@
},
bss_info: &bss_info2,
multiple_bss_candidates: false,
+ hasher: WlanHasher::new(rand::thread_rng().gen::<u64>().to_le_bytes()),
});
// stronger network returned
assert_eq!(
- select_best_connection_candidate(
- networks.clone(),
- &vec![],
- &WlanHasher::new(rand::thread_rng().gen::<u64>().to_le_bytes())
- ),
+ select_best_connection_candidate(networks.clone(), &vec![], &mut inspect_node),
Some((
types::ConnectionCandidate {
network: test_id_2.clone(),
@@ -1527,7 +1604,7 @@
select_best_connection_candidate(
networks.clone(),
&vec![test_id_2.clone()],
- &WlanHasher::new(rand::thread_rng().gen::<u64>().to_le_bytes())
+ &mut inspect_node
),
Some((
types::ConnectionCandidate {
@@ -1543,6 +1620,131 @@
);
}
+ #[test]
+ fn select_best_connection_candidate_logs_to_inspect() {
+ // generate Inspect nodes
+ let inspector = inspect::Inspector::new();
+ let mut inspect_node =
+ InspectBoundedListNode::new(inspector.root().create_child("test"), 10);
+ // build networks list
+ let test_id_1 = types::NetworkIdentifier {
+ ssid: "foo".as_bytes().to_vec(),
+ type_: types::SecurityType::Wpa3,
+ };
+ let credential_1 = Credential::Password("foo_pass".as_bytes().to_vec());
+ let test_id_2 = types::NetworkIdentifier {
+ ssid: "bar".as_bytes().to_vec(),
+ type_: types::SecurityType::Wpa,
+ };
+ let credential_2 = Credential::Password("bar_pass".as_bytes().to_vec());
+
+ let mut networks = vec![];
+
+ let bss_info1 = types::Bss {
+ compatible: true,
+ rssi: -14,
+ channel: generate_channel(1),
+ ..generate_random_bss()
+ };
+ networks.push(InternalBss {
+ network_info: InternalSavedNetworkData {
+ network_id: test_id_1.clone(),
+ credential: credential_1.clone(),
+ has_ever_connected: true,
+ recent_failures: Vec::new(),
+ },
+ bss_info: &bss_info1,
+ multiple_bss_candidates: true,
+ hasher: WlanHasher::new(rand::thread_rng().gen::<u64>().to_le_bytes()),
+ });
+
+ let bss_info2 = types::Bss {
+ compatible: false,
+ rssi: -10,
+ channel: generate_channel(1),
+ ..generate_random_bss()
+ };
+ networks.push(InternalBss {
+ network_info: InternalSavedNetworkData {
+ network_id: test_id_1.clone(),
+ credential: credential_1.clone(),
+ has_ever_connected: true,
+ recent_failures: Vec::new(),
+ },
+ bss_info: &bss_info2,
+ multiple_bss_candidates: true,
+ hasher: WlanHasher::new(rand::thread_rng().gen::<u64>().to_le_bytes()),
+ });
+
+ let bss_info3 = types::Bss {
+ compatible: true,
+ rssi: -12,
+ channel: generate_channel(1),
+ ..generate_random_bss()
+ };
+ networks.push(InternalBss {
+ network_info: InternalSavedNetworkData {
+ network_id: test_id_2.clone(),
+ credential: credential_2.clone(),
+ has_ever_connected: true,
+ recent_failures: Vec::new(),
+ },
+ bss_info: &bss_info3,
+ multiple_bss_candidates: false,
+ hasher: WlanHasher::new(rand::thread_rng().gen::<u64>().to_le_bytes()),
+ });
+
+ // stronger network returned
+ assert_eq!(
+ select_best_connection_candidate(networks.clone(), &vec![], &mut inspect_node),
+ Some((
+ types::ConnectionCandidate {
+ network: test_id_2.clone(),
+ credential: credential_2.clone(),
+ bss: bss_info3.bss_desc.clone(),
+ observed_in_passive_scan: Some(networks[2].bss_info.observed_in_passive_scan),
+ multiple_bss_candidates: Some(false),
+ },
+ bss_info3.channel,
+ bss_info3.bssid
+ ))
+ );
+
+ assert_inspect_tree!(inspector, root: {
+ test: {
+ "0": {
+ "@time": inspect::testing::AnyProperty,
+ "candidates": {
+ "0": contains {
+ score: inspect::testing::AnyProperty,
+ },
+ "1": contains {
+ score: inspect::testing::AnyProperty,
+ },
+ "2": contains {
+ score: inspect::testing::AnyProperty,
+ },
+ },
+ "selected": {
+ ssid_hash: networks[2].hasher.hash_ssid(&networks[2].network_info.network_id.ssid),
+ bssid_hash: networks[2].hasher.hash_mac_addr(&networks[2].bss_info.bssid),
+ rssi: i64::from(networks[2].bss_info.rssi),
+ score: i64::from(networks[2].score()),
+ security_type_saved: networks[2].saved_security_type_to_string(),
+ channel: {
+ cbw: inspect::testing::AnyProperty,
+ primary: u64::from(networks[2].bss_info.channel.primary),
+ secondary80: u64::from(networks[2].bss_info.channel.secondary80),
+ },
+ compatible: networks[2].bss_info.compatible,
+ recent_failure_count: networks[2].recent_failure_count(),
+ saved_network_has_ever_connected: networks[2].network_info.has_ever_connected,
+ },
+ }
+ },
+ });
+ }
+
#[fasync::run_singlethreaded(test)]
async fn perform_scan_cache_is_fresh() {
let mut test_values = test_setup().await;
@@ -2012,6 +2214,48 @@
multiple_bss_candidates: Some(false)
})
);
+
+ // Check the network selections were logged
+ assert_inspect_tree!(test_values.inspector, root: {
+ net_select_test: {
+ network_selection: {
+ "0": {
+ "@time": inspect::testing::AnyProperty,
+ "candidates": {
+ "0": contains {
+ bssid_hash: inspect::testing::AnyProperty,
+ score: inspect::testing::AnyProperty,
+ },
+ "1": contains {
+ bssid_hash: inspect::testing::AnyProperty,
+ score: inspect::testing::AnyProperty,
+ },
+ },
+ "selected": contains {
+ bssid_hash: inspect::testing::AnyProperty,
+ score: inspect::testing::AnyProperty,
+ },
+ },
+ "1": {
+ "@time": inspect::testing::AnyProperty,
+ "candidates": {
+ "0": contains {
+ bssid_hash: inspect::testing::AnyProperty,
+ score: inspect::testing::AnyProperty,
+ },
+ "1": contains {
+ bssid_hash: inspect::testing::AnyProperty,
+ score: inspect::testing::AnyProperty,
+ },
+ },
+ "selected": contains {
+ bssid_hash: inspect::testing::AnyProperty,
+ score: inspect::testing::AnyProperty,
+ },
+ }
+ }
+ },
+ });
}
#[test]
diff --git a/src/connectivity/wlan/wlancfg/src/client/state_machine.rs b/src/connectivity/wlan/wlancfg/src/client/state_machine.rs
index f0fcaf1..cdac8ec 100644
--- a/src/connectivity/wlan/wlancfg/src/client/state_machine.rs
+++ b/src/connectivity/wlan/wlancfg/src/client/state_machine.rs
@@ -731,6 +731,7 @@
fidl_fuchsia_stash as fidl_stash, fidl_fuchsia_wlan_common as fidl_common,
fidl_fuchsia_wlan_policy as fidl_policy,
fuchsia_cobalt::CobaltEventExt,
+ fuchsia_inspect::{self as inspect},
fuchsia_zircon,
futures::{task::Poll, Future},
pin_utils::pin_mut,
@@ -764,6 +765,7 @@
let network_selector = Arc::new(network_selection::NetworkSelector::new(
saved_networks_manager.clone(),
create_mock_cobalt_sender(),
+ inspect::Inspector::new().root().create_child("network_selector"),
));
TestValues {
@@ -833,6 +835,7 @@
let network_selector = Arc::new(network_selection::NetworkSelector::new(
saved_networks_manager.clone(),
create_mock_cobalt_sender(),
+ inspect::Inspector::new().root().create_child("network_selector"),
));
let next_network_ssid = "bar";
let bss_desc = generate_random_bss_desc();
@@ -998,6 +1001,7 @@
let network_selector = Arc::new(network_selection::NetworkSelector::new(
saved_networks_manager.clone(),
create_mock_cobalt_sender(),
+ inspect::Inspector::new().root().create_child("network_selector"),
));
let next_network_ssid = "bar";
let bss_desc = generate_random_bss_desc();
@@ -1187,6 +1191,7 @@
let network_selector = Arc::new(network_selection::NetworkSelector::new(
saved_networks_manager.clone(),
create_mock_cobalt_sender(),
+ inspect::Inspector::new().root().create_child("network_selector"),
));
let next_network_ssid = "bar";
let bss_desc = generate_random_bss_desc();
@@ -1449,6 +1454,7 @@
let network_selector = Arc::new(network_selection::NetworkSelector::new(
saved_networks_manager.clone(),
create_mock_cobalt_sender(),
+ inspect::Inspector::new().root().create_child("network_selector"),
));
let next_network_ssid = "bar";
let bss_desc = generate_random_bss_desc();
@@ -1649,6 +1655,7 @@
let network_selector = Arc::new(network_selection::NetworkSelector::new(
saved_networks_manager.clone(),
create_mock_cobalt_sender(),
+ inspect::Inspector::new().root().create_child("network_selector"),
));
let common_options = CommonStateOptions {
proxy: sme_proxy,
@@ -1787,6 +1794,7 @@
let network_selector = Arc::new(network_selection::NetworkSelector::new(
saved_networks_manager.clone(),
create_mock_cobalt_sender(),
+ inspect::Inspector::new().root().create_child("network_selector"),
));
let common_options = CommonStateOptions {
@@ -2766,6 +2774,7 @@
let network_selector = Arc::new(network_selection::NetworkSelector::new(
saved_networks_manager.clone(),
create_mock_cobalt_sender(),
+ inspect::Inspector::new().root().create_child("network_selector"),
));
let network_ssid = "foo";
let bss_desc = generate_random_bss_desc();
diff --git a/src/connectivity/wlan/wlancfg/src/main.rs b/src/connectivity/wlan/wlancfg/src/main.rs
index fc15062..35a0c07 100644
--- a/src/connectivity/wlan/wlancfg/src/main.rs
+++ b/src/connectivity/wlan/wlancfg/src/main.rs
@@ -214,8 +214,11 @@
let saved_networks =
Arc::new(executor.run_singlethreaded(SavedNetworksManager::new(cobalt_api.clone()))?);
- let network_selector =
- Arc::new(NetworkSelector::new(Arc::clone(&saved_networks), cobalt_api.clone()));
+ let network_selector = Arc::new(NetworkSelector::new(
+ Arc::clone(&saved_networks),
+ cobalt_api.clone(),
+ component::inspector().root().create_child("network_selector"),
+ ));
let phy_manager = Arc::new(Mutex::new(PhyManager::new(
wlan_svc.clone(),
diff --git a/src/connectivity/wlan/wlancfg/src/mode_management/iface_manager.rs b/src/connectivity/wlan/wlancfg/src/mode_management/iface_manager.rs
index 1a58c35..29543d2 100644
--- a/src/connectivity/wlan/wlancfg/src/mode_management/iface_manager.rs
+++ b/src/connectivity/wlan/wlancfg/src/mode_management/iface_manager.rs
@@ -1324,8 +1324,11 @@
let inspector = inspect::Inspector::new();
let node = inspector.root().create_child("phy_manager");
let (cobalt_api, cobalt_receiver) = create_mock_cobalt_sender_and_receiver();
- let network_selector =
- Arc::new(NetworkSelector::new(saved_networks.clone(), cobalt_api.clone()));
+ let network_selector = Arc::new(NetworkSelector::new(
+ saved_networks.clone(),
+ cobalt_api.clone(),
+ inspector.root().create_child("network_selection"),
+ ));
TestValues {
device_service_proxy: proxy,
@@ -3857,8 +3860,11 @@
// Create other components to run the service.
let iface_manager_client = Arc::new(Mutex::new(FakeIfaceManagerRequester::new()));
- let network_selector =
- Arc::new(NetworkSelector::new(test_values.saved_networks, create_mock_cobalt_sender()));
+ let network_selector = Arc::new(NetworkSelector::new(
+ test_values.saved_networks,
+ create_mock_cobalt_sender(),
+ inspect::Inspector::new().root().create_child("network_selector"),
+ ));
// Create mpsc channel to handle requests.
let (mut sender, receiver) = mpsc::channel(1);
@@ -3905,8 +3911,11 @@
// Create other components to run the service.
let iface_manager_client = Arc::new(Mutex::new(FakeIfaceManagerRequester::new()));
- let network_selector =
- Arc::new(NetworkSelector::new(test_values.saved_networks, create_mock_cobalt_sender()));
+ let network_selector = Arc::new(NetworkSelector::new(
+ test_values.saved_networks,
+ create_mock_cobalt_sender(),
+ inspect::Inspector::new().root().create_child("network_selector"),
+ ));
// Create mpsc channel to handle requests.
let (mut sender, receiver) = mpsc::channel(1);
@@ -3942,8 +3951,11 @@
// Create other components to run the service.
let iface_manager_client = Arc::new(Mutex::new(FakeIfaceManagerRequester::new()));
- let network_selector =
- Arc::new(NetworkSelector::new(test_values.saved_networks, create_mock_cobalt_sender()));
+ let network_selector = Arc::new(NetworkSelector::new(
+ test_values.saved_networks,
+ create_mock_cobalt_sender(),
+ inspect::Inspector::new().root().create_child("network_selector"),
+ ));
// Create mpsc channel to handle requests.
let (mut sender, receiver) = mpsc::channel(1);
@@ -4086,8 +4098,11 @@
// Create other components to run the service.
let iface_manager_client = Arc::new(Mutex::new(FakeIfaceManagerRequester::new()));
- let network_selector =
- Arc::new(NetworkSelector::new(test_values.saved_networks, create_mock_cobalt_sender()));
+ let network_selector = Arc::new(NetworkSelector::new(
+ test_values.saved_networks,
+ create_mock_cobalt_sender(),
+ inspect::Inspector::new().root().create_child("network_selector"),
+ ));
// Create mpsc channel to handle requests.
let (mut sender, receiver) = mpsc::channel(1);
@@ -4759,6 +4774,7 @@
let selector = Arc::new(NetworkSelector::new(
test_values.saved_networks.clone(),
create_mock_cobalt_sender(),
+ inspect::Inspector::new().root().create_child("network_selector"),
));
// Setup the test to prevent a network selection from happening for whatever reason was specified.
@@ -4888,6 +4904,7 @@
let selector = Arc::new(NetworkSelector::new(
test_values.saved_networks.clone(),
create_mock_cobalt_sender(),
+ inspect::Inspector::new().root().create_child("network_selector"),
));
// Inject a scan result into the network selector.
@@ -5006,6 +5023,7 @@
let selector = Arc::new(NetworkSelector::new(
test_values.saved_networks.clone(),
create_mock_cobalt_sender(),
+ inspect::Inspector::new().root().create_child("network_selector"),
));
// Inject a scan result into the network selector.
@@ -5105,6 +5123,7 @@
let selector = Arc::new(NetworkSelector::new(
test_values.saved_networks.clone(),
create_mock_cobalt_sender(),
+ inspect::Inspector::new().root().create_child("network_selector"),
));
// Create an interface manager with an unconfigured client interface.
@@ -5152,6 +5171,7 @@
let selector = Arc::new(NetworkSelector::new(
test_values.saved_networks.clone(),
create_mock_cobalt_sender(),
+ inspect::Inspector::new().root().create_child("network_selector"),
));
// Create an interface manager with an unconfigured client interface.