[lowpan][lowpan-spinel-driver] Get Neighbor Table
Get neighbor table from ot-stack.
Test: fx test lowpan-spinel-driver-test
Bug: 44678
Change-Id: I9ef4dd88d91d733eef25afb69fe83be111ce318a
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/473358
Fuchsia-Auto-Submit: Jiaming (Charlie) Wang <jiamingw@google.com>
Commit-Queue: Auto-Submit <auto-submit@fuchsia-infra.iam.gserviceaccount.com>
Reviewed-by: Robert Quattlebaum <rquattle@google.com>
diff --git a/src/connectivity/lowpan/drivers/lowpan-spinel-driver/src/driver/api.rs b/src/connectivity/lowpan/drivers/lowpan-spinel-driver/src/driver/api.rs
index a8b6576..e72e786 100644
--- a/src/connectivity/lowpan/drivers/lowpan-spinel-driver/src/driver/api.rs
+++ b/src/connectivity/lowpan/drivers/lowpan-spinel-driver/src/driver/api.rs
@@ -964,8 +964,30 @@
}
async fn get_neighbor_table(&self) -> ZxResult<Vec<NeighborInfo>> {
- // TODO: Implement.
- return Ok(vec![]);
+ // Wait until we are ready.
+ self.wait_for_state(DriverState::is_initialized).await;
+
+ // Wait for our turn.
+ let _lock = self.wait_for_api_task_lock("get_neighbor_table").await?;
+
+ Ok(self
+ .get_property_simple::<NeighborTable, _>(PropThread::NeighborTable)
+ .await?
+ .into_iter()
+ .map(|item| NeighborInfo {
+ mac_address: Some(item.extended_addr.0.to_vec()),
+ short_address: Some(item.short_addr),
+ age: Some(fuchsia_zircon::Duration::from_seconds(item.age.into()).into_nanos()),
+ is_child: Some(item.is_child),
+ link_frame_count: Some(item.link_frame_cnt),
+ mgmt_frame_count: Some(item.mle_frame_cnt),
+ last_rssi_in: Some(item.last_rssi.into()),
+ avg_rssi_in: Some(item.avg_rssi),
+ lqi_in: Some(item.link_quality),
+ thread_mode: Some(item.mode),
+ ..NeighborInfo::EMPTY
+ })
+ .collect::<Vec<_>>())
}
async fn get_counters(&self) -> ZxResult<Counters> {
diff --git a/src/connectivity/lowpan/drivers/lowpan-spinel-driver/src/driver/tests.rs b/src/connectivity/lowpan/drivers/lowpan-spinel-driver/src/driver/tests.rs
index 5c08cc9..d862581 100644
--- a/src/connectivity/lowpan/drivers/lowpan-spinel-driver/src/driver/tests.rs
+++ b/src/connectivity/lowpan/drivers/lowpan-spinel-driver/src/driver/tests.rs
@@ -10,6 +10,7 @@
use crate::spinel::mock::PROP_DEBUG_LOGGING_TEST;
use fidl_fuchsia_lowpan::{Credential, Identity, ProvisioningParams, NET_TYPE_THREAD_1_X};
+use fidl_fuchsia_lowpan_test::NeighborInfo;
use lowpan_driver_common::Driver as _;
impl<DS, NI> SpinelDriver<DS, NI> {
@@ -87,6 +88,42 @@
traceln!("app_task: thread_rloc16: {:?}", thread_rloc16);
assert_eq!(thread_rloc16.map(|_| ()), Ok(()));
+ let thread_neighbor_table = driver.get_neighbor_table().await;
+ traceln!("app_task: thread_neighbor_table: {:?}", thread_neighbor_table);
+ let thread_neighbor_entry_vec = thread_neighbor_table.unwrap();
+ assert_eq!(
+ thread_neighbor_entry_vec[0],
+ NeighborInfo {
+ mac_address: Some([0, 1, 2, 3, 4, 5, 6, 7].to_vec()),
+ short_address: Some(0x123),
+ age: Some(fuchsia_zircon::Duration::from_seconds(11).into_nanos()),
+ is_child: Some(true),
+ link_frame_count: Some(1),
+ mgmt_frame_count: Some(1),
+ last_rssi_in: Some(-20),
+ avg_rssi_in: Some(-20),
+ lqi_in: Some(3),
+ thread_mode: Some(0x0b),
+ ..NeighborInfo::EMPTY
+ }
+ );
+ assert_eq!(
+ thread_neighbor_entry_vec[1],
+ NeighborInfo {
+ mac_address: Some([1, 2, 3, 4, 5, 6, 7, 8].to_vec()),
+ short_address: Some(0x1234),
+ age: Some(fuchsia_zircon::Duration::from_seconds(22).into_nanos()),
+ is_child: Some(true),
+ link_frame_count: Some(1),
+ mgmt_frame_count: Some(1),
+ last_rssi_in: Some(-30),
+ avg_rssi_in: Some(-30),
+ lqi_in: Some(4),
+ thread_mode: Some(0x0b),
+ ..NeighborInfo::EMPTY
+ }
+ );
+
traceln!("app_task: Attempting a reset...");
assert_eq!(driver.reset().await, Ok(()));
traceln!("app_task: Did reset!");
diff --git a/src/connectivity/lowpan/drivers/lowpan-spinel-driver/src/spinel/mock/fake_device_client.rs b/src/connectivity/lowpan/drivers/lowpan-spinel-driver/src/spinel/mock/fake_device_client.rs
index 1eb51d3..925b5b5d 100644
--- a/src/connectivity/lowpan/drivers/lowpan-spinel-driver/src/spinel/mock/fake_device_client.rs
+++ b/src/connectivity/lowpan/drivers/lowpan-spinel-driver/src/spinel/mock/fake_device_client.rs
@@ -546,6 +546,40 @@
spinel_write!(&mut response, "CiiS", frame.header, Cmd::PropValueIs, prop, 0x0000,)
.unwrap();
}
+ Prop::Thread(PropThread::NeighborTable) => {
+ spinel_write!(
+ &mut response,
+ "Ciidd",
+ frame.header,
+ Cmd::PropValueIs,
+ prop,
+ NeighborTableEntry {
+ extended_addr: EUI64([0, 1, 2, 3, 4, 5, 6, 7]),
+ short_addr: 0x123,
+ age: 11,
+ is_child: true,
+ link_frame_cnt: 1,
+ mle_frame_cnt: 1,
+ last_rssi: -20,
+ avg_rssi: -20,
+ link_quality: 3,
+ mode: 0x0b,
+ },
+ NeighborTableEntry {
+ extended_addr: EUI64([1, 2, 3, 4, 5, 6, 7, 8]),
+ short_addr: 0x1234,
+ age: 22,
+ is_child: true,
+ link_frame_cnt: 1,
+ mle_frame_cnt: 1,
+ last_rssi: -30,
+ avg_rssi: -30,
+ link_quality: 4,
+ mode: 0x0b,
+ },
+ )
+ .unwrap();
+ }
prop => {
let properties = self.properties.lock();
if let Some(value) = properties.get(&prop) {
diff --git a/src/connectivity/lowpan/drivers/lowpan-spinel-driver/src/spinel/types.rs b/src/connectivity/lowpan/drivers/lowpan-spinel-driver/src/spinel/types.rs
index 2234b0b..d55f55e 100644
--- a/src/connectivity/lowpan/drivers/lowpan-spinel-driver/src/spinel/types.rs
+++ b/src/connectivity/lowpan/drivers/lowpan-spinel-driver/src/spinel/types.rs
@@ -278,6 +278,23 @@
pub type DenyList = HashSet<DenyListEntry>;
+#[spinel_packed("ESLCcCbLLc")]
+#[derive(Debug, Hash, Clone, Eq, PartialEq)]
+pub struct NeighborTableEntry {
+ pub extended_addr: EUI64,
+ pub short_addr: u16,
+ pub age: u32,
+ pub link_quality: u8,
+ pub avg_rssi: i8,
+ pub mode: u8,
+ pub is_child: bool,
+ pub link_frame_cnt: u32,
+ pub mle_frame_cnt: u32,
+ pub last_rssi: i8,
+}
+
+pub type NeighborTable = Vec<NeighborTableEntry>;
+
#[cfg(test)]
mod tests {
use super::*;