diff --git a/local/recipes/drivers/redbear-iwlwifi/source/src/linux_mld.h b/local/recipes/drivers/redbear-iwlwifi/source/src/linux_mld.h index b1da4a18bd..f1487b47d9 100644 --- a/local/recipes/drivers/redbear-iwlwifi/source/src/linux_mld.h +++ b/local/recipes/drivers/redbear-iwlwifi/source/src/linux_mld.h @@ -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); diff --git a/local/recipes/drivers/redbear-iwlwifi/source/src/linux_port.c b/local/recipes/drivers/redbear-iwlwifi/source/src/linux_port.c index 971d99451d..f54744c643 100644 --- a/local/recipes/drivers/redbear-iwlwifi/source/src/linux_port.c +++ b/local/recipes/drivers/redbear-iwlwifi/source/src/linux_port.c @@ -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) diff --git a/local/recipes/drivers/redbear-iwlwifi/source/src/main.rs b/local/recipes/drivers/redbear-iwlwifi/source/src/main.rs index f08dcb1e65..8fcbfbcbf7 100644 --- a/local/recipes/drivers/redbear-iwlwifi/source/src/main.rs +++ b/local/recipes/drivers/redbear-iwlwifi/source/src/main.rs @@ -1256,10 +1256,14 @@ fn linux_kpi_status_candidate(candidate: &Candidate) -> Result, 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), ]) } diff --git a/local/recipes/drivers/redbear-iwlwifi/source/src/mld/dispatch.rs b/local/recipes/drivers/redbear-iwlwifi/source/src/mld/dispatch.rs index d07db869c6..2b7bf8654a 100644 --- a/local/recipes/drivers/redbear-iwlwifi/source/src/mld/dispatch.rs +++ b/local/recipes/drivers/redbear-iwlwifi/source/src/mld/dispatch.rs @@ -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);