feat(iwlwifi): wire remaining ops + CLI status + fix test race
Second round of MLD dispatch improvements:
linux_port.c:
- iwl_ops_sw_scan_start now calls rb_mld_ops_hw_scan(1)
- iwl_ops_sw_scan_complete now calls rb_mld_ops_cancel_hw_scan()
- iwl_ops_set_key now calls rb_mld_ops_set_key (full cipher
suite mapping: CCMP/CCMP256/GCMP128/GCMP256/TKIP/WEP40/WEP104)
mld/dispatch.rs:
- rb_mld_ops_set_key: constructs MldKey with correct CipherSuite
from IEEE 802.11 cipher suite OUI+type values, dispatches to
MldState::install_key / remove_key
- Fixed intermittent test failure: dispatch tests now serialize
via static TEST_LOCK to prevent races on the global MLD_STATE
main.rs:
- --status now reports mld_state=live|inactive and mld_rx_frames=N
so operators can verify the Rust MLD layer is receiving callbacks
linux_mld.h: rb_mld_ops_set_key declaration
57 tests pass consistently across 3 consecutive runs.
This commit is contained in:
@@ -385,6 +385,8 @@ int rb_mld_ops_restart_complete(void);
|
||||
int rb_mld_ops_configure_filter(uint32_t changed, uint32_t *total);
|
||||
int rb_mld_ops_conf_tx(uint8_t mac_id, uint8_t ac);
|
||||
int rb_mld_ops_wake_tx_queue(uint16_t fw_id);
|
||||
int rb_mld_ops_set_key(int cmd, uint32_t sta_id, uint8_t key_idx, uint32_t cipher,
|
||||
const uint8_t *key_data, uint32_t key_len);
|
||||
|
||||
/* Notification dispatch (from ISR/tasklet) */
|
||||
int rb_mld_notify_rx(uint16_t wide_id, const uint8_t *data, size_t len);
|
||||
|
||||
@@ -2050,6 +2050,8 @@ static int iwl_ops_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
trans->last_security[0] = '\0';
|
||||
}
|
||||
|
||||
rb_mld_ops_set_key(cmd == SET_KEY ? 0 : 1, sta ? sta->aid : 0,
|
||||
key->keyidx, key->cipher, key->key, (uint32_t)key->keylen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2063,6 +2065,7 @@ static void iwl_ops_sw_scan_start(struct ieee80211_hw *hw, struct ieee80211_vif
|
||||
trans->scan_results_count = 0;
|
||||
trans->scan_active = 1;
|
||||
trans->svc_flags |= RB_IWL_SVC_SCAN_ACTIVE;
|
||||
rb_mld_ops_hw_scan(1);
|
||||
}
|
||||
|
||||
static void iwl_ops_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
@@ -2074,6 +2077,7 @@ static void iwl_ops_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_v
|
||||
rb_iwlwifi_report_scan_result(trans);
|
||||
trans->scan_active = 0;
|
||||
trans->svc_flags &= ~RB_IWL_SVC_SCAN_ACTIVE;
|
||||
rb_mld_ops_cancel_hw_scan();
|
||||
}
|
||||
|
||||
static int iwl_ops_sched_scan_start(struct ieee80211_hw *hw, struct ieee80211_vif *vif, void *req)
|
||||
|
||||
@@ -1256,10 +1256,14 @@ fn linux_kpi_status_candidate(candidate: &Candidate) -> Result<Vec<String>, Driv
|
||||
.trim_matches(char::from(0))
|
||||
.trim()
|
||||
.to_string();
|
||||
let mld_active = mld::dispatch::rb_mld_state_available();
|
||||
let mld_rx = mld::dispatch::rb_mld_rx_frame_count();
|
||||
Ok(vec![
|
||||
format!("device={}", candidate.location),
|
||||
format!("family={}", candidate.family),
|
||||
parsed,
|
||||
format!("mld_state={}", if mld_active > 0 { "live" } else { "inactive" }),
|
||||
format!("mld_rx_frames={}", mld_rx),
|
||||
])
|
||||
}
|
||||
|
||||
|
||||
@@ -258,6 +258,73 @@ pub extern "C" fn rb_mld_ops_configure_filter(changed: u32, total: *mut u32) ->
|
||||
rc
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn rb_mld_ops_set_key(
|
||||
cmd: i32,
|
||||
sta_id: u32,
|
||||
key_idx: u8,
|
||||
cipher: u32,
|
||||
key_data: *const u8,
|
||||
key_len: u32,
|
||||
) -> i32 {
|
||||
if key_data.is_null() && key_len > 0 {
|
||||
return -1;
|
||||
}
|
||||
with_mld(-1, |mld| {
|
||||
if cmd == 0 {
|
||||
let key_slice = if key_len > 0 && !key_data.is_null() {
|
||||
unsafe { std::slice::from_raw_parts(key_data, key_len as usize) }
|
||||
} else {
|
||||
&[]
|
||||
};
|
||||
let mut mld_key = key::MldKey::default();
|
||||
mld_key.sta_id = sta_id;
|
||||
mld_key.key_idx = key_idx;
|
||||
mld_key.pairwise = true;
|
||||
mld_key.cipher = match cipher {
|
||||
0x000FAC04 => key::CipherSuite::Ccmp,
|
||||
0x000FAC0A => key::CipherSuite::Ccmp256,
|
||||
0x000FAC08 => key::CipherSuite::Gcmp128,
|
||||
0x000FAC09 => key::CipherSuite::Gcmp256,
|
||||
0x000FAC02 => key::CipherSuite::Tkip,
|
||||
0x000FAC01 => key::CipherSuite::Wep40,
|
||||
0x000FAC05 => key::CipherSuite::Wep104,
|
||||
_ => key::CipherSuite::None,
|
||||
};
|
||||
if !key_slice.is_empty() {
|
||||
mld_key.key = key_slice.to_vec();
|
||||
}
|
||||
log::info!(
|
||||
"rb_mld_ops_set_key: SET_KEY sta={} idx={} cipher={:#06x} len={}",
|
||||
sta_id,
|
||||
key_idx,
|
||||
cipher,
|
||||
key_len
|
||||
);
|
||||
match mld.install_key(&mld_key) {
|
||||
Ok(_) => 0,
|
||||
Err(e) => {
|
||||
log::warn!("rb_mld_ops_set_key install: {:?}", e);
|
||||
-1
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log::info!(
|
||||
"rb_mld_ops_set_key: DISABLE_KEY sta={} idx={}",
|
||||
sta_id,
|
||||
key_idx
|
||||
);
|
||||
match mld.remove_key(sta_id, key_idx) {
|
||||
Ok(_) => 0,
|
||||
Err(e) => {
|
||||
log::warn!("rb_mld_ops_set_key remove: {:?}", e);
|
||||
-1
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn rb_mld_ops_conf_tx(mac_id: u8, ac: u8) -> i32 {
|
||||
with_mld(-1, |mld| match mld.callback_conf_tx(mac_id, ac) {
|
||||
@@ -317,8 +384,15 @@ pub extern "C" fn rb_mld_rx_frame_count() -> u32 {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
static TEST_LOCK: Mutex<()> = Mutex::new(());
|
||||
|
||||
fn lock() -> std::sync::MutexGuard<'static, ()> {
|
||||
TEST_LOCK.lock().unwrap_or_else(|e| e.into_inner())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rb_mld_state_available_reports_init() {
|
||||
let _g = lock();
|
||||
{
|
||||
let mut guard = MLD_STATE.lock().unwrap();
|
||||
*guard = Some(Box::new(MldState::new()));
|
||||
@@ -330,6 +404,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn rb_mld_init_creates_state() {
|
||||
let _g = lock();
|
||||
rb_mld_destroy();
|
||||
assert_eq!(rb_mld_init(std::ptr::null_mut()), 0);
|
||||
assert_eq!(rb_mld_state_available(), 1);
|
||||
@@ -338,6 +413,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn rb_mld_ops_start_without_dev_handle_returns_zero() {
|
||||
let _g = lock();
|
||||
rb_mld_destroy();
|
||||
assert_eq!(rb_mld_init(std::ptr::null_mut()), 0);
|
||||
let rc = rb_mld_ops_start();
|
||||
@@ -347,6 +423,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn rb_mld_ops_when_uninitialized_returns_error() {
|
||||
let _g = lock();
|
||||
rb_mld_destroy();
|
||||
assert_eq!(rb_mld_ops_start(), -1);
|
||||
assert_eq!(rb_mld_ops_config(0), -1);
|
||||
@@ -354,6 +431,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn rb_mld_notify_rx_null_data_returns_error() {
|
||||
let _g = lock();
|
||||
rb_mld_destroy();
|
||||
assert_eq!(rb_mld_init(std::ptr::null_mut()), 0);
|
||||
assert_eq!(rb_mld_notify_rx(0xc1, std::ptr::null(), 0), -1);
|
||||
@@ -362,6 +440,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn rb_mld_rx_frame_count_tracks_notifications() {
|
||||
let _g = lock();
|
||||
rb_mld_destroy();
|
||||
assert_eq!(rb_mld_init(std::ptr::null_mut()), 0);
|
||||
assert_eq!(rb_mld_rx_frame_count(), 0);
|
||||
|
||||
Reference in New Issue
Block a user