From 63bfa4684814fcc7e686deefccfd9d1ba0688da4 Mon Sep 17 00:00:00 2001 From: Aloka Dixit Date: Tue, 28 Nov 2023 10:12:33 -0800 Subject: [PATCH 6/7] hostapd: add device parameters to radar events Add new device bandwidth and center frequency parameters to radar events. Device bandwidth can be twice the current operating bandwidth. These parameters will be used to decide if the radar was detected or channel availability check was started/aborted/finished in the non-operating bandwidth portion of the device bandwidth. When frequency hoping radar while this feature is enabled internal channel switch logic will be used for operation. Signed-off-by: Aloka Dixit Signed-off-by: Shivani Tambatkar --- src/ap/dfs.c | 21 +++++++++++++-------- src/ap/dfs.h | 9 ++++++--- src/ap/drv_callbacks.c | 14 +++++++++----- src/drivers/driver.h | 2 ++ src/drivers/driver_nl80211_event.c | 16 +++++++++++++--- wpa_supplicant/ap.c | 12 ++++++++---- 6 files changed, 51 insertions(+), 23 deletions(-) --- a/src/ap/dfs.c +++ b/src/ap/dfs.c @@ -1375,13 +1375,25 @@ bool hostapd_is_freq_in_current_hw_info( return chan_in_current_hw_info(iface->current_hw_info, chan); } + +bool hostapd_is_device_params_present(int chan_width, int cf1, int chan_width_device, + int cf_device) +{ + return (cf_device && chan_width_device && + chan_width_device != chan_width && cf_device != cf1); +} + + int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq, int ht_enabled, int chan_offset, int chan_width, - int cf1, int cf2, bool is_background) + int cf1, int cf2, bool is_background, + int chan_width_device, int cf_device) { wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_COMPLETED - "success=%d freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d", - success, freq, ht_enabled, chan_offset, chan_width, cf1, cf2); + "success=%d freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d " + "chan_width_device=%d cf_device=%d", + success, freq, ht_enabled, chan_offset, chan_width, cf1, cf2, + chan_width_device, cf_device); if (!hostapd_is_freq_in_current_hw_info(iface, freq)) { wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_COMPLETED @@ -1398,9 +1410,15 @@ int hostapd_dfs_complete_cac(struct host else iface->cac_started = 0; } else { - set_dfs_state(iface, freq, ht_enabled, chan_offset, - chan_width, cf1, cf2, - HOSTAPD_CHAN_DFS_AVAILABLE,0); + if (hostapd_is_device_params_present(chan_width, cf1, + chan_width_device, cf_device)) + set_dfs_state(iface, freq, ht_enabled, chan_offset, + chan_width_device, cf_device, cf2, + HOSTAPD_CHAN_DFS_AVAILABLE, 0); + else + set_dfs_state(iface, freq, ht_enabled, chan_offset, + chan_width, cf1, cf2, + HOSTAPD_CHAN_DFS_AVAILABLE, 0); /* * Radar event from background chain for the selected @@ -1446,11 +1464,13 @@ int hostapd_dfs_complete_cac(struct host int hostapd_dfs_pre_cac_expired(struct hostapd_iface *iface, int freq, int ht_enabled, int chan_offset, int chan_width, - int cf1, int cf2) + int cf1, int cf2, int chan_width_device, int cf_device) { wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_PRE_CAC_EXPIRED - "freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d", - freq, ht_enabled, chan_offset, chan_width, cf1, cf2); + "freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d " + "chan_width_device=%d cf_device=%d", + freq, ht_enabled, chan_offset, chan_width, cf1, cf2, chan_width_device, + cf_device); if (!hostapd_is_freq_in_current_hw_info(iface, freq)) { wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_PRE_CAC_EXPIRED @@ -1713,25 +1733,79 @@ enum oper_chan_width convert_to_oper_cha return CHAN_WIDTH_UNKNOWN; } +static u32 hostapd_radar_bitmap_oper(int chan_width, int cf1, u16 radar_bitmap, + int chan_width_device, int cf_device) +{ + u16 radar_bitmap_oper; + + switch (chan_width_device) { + case CHAN_WIDTH_40: + if (cf1 < cf_device) + radar_bitmap_oper = radar_bitmap & 0x1; + else + radar_bitmap_oper = (radar_bitmap >> 1) & 0x1; + break; + case CHAN_WIDTH_80: + if (cf1 < cf_device) + radar_bitmap_oper = radar_bitmap & 0x3; + else + radar_bitmap_oper = (radar_bitmap >> 2) & 0x3; + break; + case CHAN_WIDTH_160: + if (cf1 < cf_device) + radar_bitmap_oper = radar_bitmap & 0xF; + else + radar_bitmap_oper = (radar_bitmap >> 4) & 0xF; + break; + case CHAN_WIDTH_320: + if (cf1 < cf_device) + radar_bitmap_oper = radar_bitmap & 0xFF; + else + radar_bitmap_oper = (radar_bitmap >> 8) & 0xFF; + break; + default: + return 0; + } + + return radar_bitmap_oper; +} + + int hostapd_dfs_radar_detected(struct hostapd_iface *iface, int freq, int ht_enabled, int chan_offset, int chan_width, - int cf1, int cf2, u16 radar_bitmap) + int cf1, int cf2, u16 radar_bitmap, + int chan_width_device, int cf_device) { - u16 radar_bit_pattern; + u16 radar_bit_pattern, radar_bitmap_oper = 0; u16 cur_punct_bits = iface->conf->ru_punct_bitmap; + bool device_params_present; wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_RADAR_DETECTED - "freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d radar_bitmap:%d", - freq, ht_enabled, chan_offset, chan_width, cf1, cf2, radar_bitmap); + "freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d radar_bitmap:%d " + "chan_width_device=%d cf_device=%d", + freq, ht_enabled, chan_offset, chan_width, cf1, cf2, radar_bitmap, + chan_width_device, cf_device); + + radar_bitmap_oper = radar_bitmap; + device_params_present = hostapd_is_device_params_present(chan_width, + cf1, + chan_width_device, + cf_device); + + if (device_params_present) + radar_bitmap_oper = hostapd_radar_bitmap_oper(chan_width, cf1, + radar_bitmap, + chan_width_device, + cf_device); - if (iface->conf->use_ru_puncture_dfs) { + if (iface->conf->use_ru_puncture_dfs && radar_bitmap_oper) { radar_bit_pattern = iface->radar_bit_pattern | iface->conf->ru_punct_bitmap; /* Radar detected already punctured sub channel*/ - if (radar_bit_pattern & radar_bitmap) + if (radar_bit_pattern & radar_bitmap_oper) return 0; - radar_bit_pattern |= radar_bitmap; + radar_bit_pattern |= radar_bitmap_oper; iface->conf->ru_punct_bitmap = radar_bit_pattern; } @@ -1743,9 +1817,16 @@ int hostapd_dfs_radar_detected(struct ho return 0; /* mark radar frequency as invalid */ - if (!set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width, - cf1, cf2, HOSTAPD_CHAN_DFS_UNAVAILABLE, radar_bitmap)) - return 0; + if (device_params_present) { + if (!set_dfs_state(iface, freq, ht_enabled, chan_offset, + chan_width_device, cf_device, cf2, + HOSTAPD_CHAN_DFS_UNAVAILABLE, radar_bitmap)) + return 0; + } else { + if (!set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width, + cf1, cf2, HOSTAPD_CHAN_DFS_UNAVAILABLE, radar_bitmap)) + return 0; + } if (iface->conf->dfs_test_mode) { set_dfs_state(iface, freq, ht_enabled, chan_offset, @@ -1763,7 +1844,7 @@ int hostapd_dfs_radar_detected(struct ho } if (iface->conf->use_ru_puncture_dfs && hostapd_is_usable_ru_punct_bitmap(iface)) { - iface->radar_bit_pattern = radar_bitmap; + iface->radar_bit_pattern = radar_bitmap_oper; iface->conf->ru_punct_bitmap = cur_punct_bits; u8 oper_centr_freq_seg0_idx = iface->conf->vht_oper_centr_freq_seg0_idx; u8 oper_centr_freq_seg1_idx = iface->conf->vht_oper_centr_freq_seg1_idx; @@ -1802,11 +1883,17 @@ int hostapd_dfs_radar_detected(struct ho oper_centr_freq_seg0_idx, oper_centr_freq_seg1_idx); } + if (!radar_bitmap && iface->conf->disable_csa_dfs && + (iface->drv_flags2 & WPA_DRIVER_DEVICE_PARAMS_SUPPORTED)) { + /* Frequency Hoping RADAR detected while operating, switch the channel. */ + return hostapd_dfs_start_channel_switch(iface); + } + /* Switch channel with random channel selection for invalid puncturing pattern */ iface->radar_bit_pattern = 0; iface->conf->ru_punct_bitmap = 0; - if (hostapd_dfs_background_start_channel_switch(iface, freq)) { + if (hostapd_dfs_background_start_channel_switch(iface, freq) && radar_bitmap_oper) { if (!iface->conf->disable_csa_dfs) { /* Radar detected while operating, switch the channel. */ return hostapd_dfs_start_channel_switch(iface); @@ -1824,11 +1911,11 @@ int hostapd_dfs_radar_detected(struct ho int hostapd_dfs_nop_finished(struct hostapd_iface *iface, int freq, int ht_enabled, int chan_offset, int chan_width, - int cf1, int cf2) + int cf1, int cf2, int chan_width_device, int cf_device) { wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NOP_FINISHED - "freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d", - freq, ht_enabled, chan_offset, chan_width, cf1, cf2); + "freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d, chan_width_device=%d cf_device=%d", + freq, ht_enabled, chan_offset, chan_width, cf1, cf2, chan_width_device, cf_device); if (!hostapd_is_freq_in_current_hw_info(iface, freq)) { wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NOP_FINISHED @@ -1841,8 +1928,13 @@ int hostapd_dfs_nop_finished(struct host return 0; /* TODO add correct implementation here */ - set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width, - cf1, cf2, HOSTAPD_CHAN_DFS_USABLE,0); + if (hostapd_is_device_params_present(chan_width, cf1, + chan_width_device, cf_device)) + set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width_device, + cf_device, cf2, HOSTAPD_CHAN_DFS_USABLE, 0); + else + set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width, + cf1, cf2, HOSTAPD_CHAN_DFS_USABLE, 0); if (iface->state == HAPD_IFACE_DFS && !iface->cac_started) { /* Handle cases where all channels were initially unavailable */ @@ -1889,7 +1981,8 @@ int hostapd_is_dfs_required(struct hosta int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq, int ht_enabled, int chan_offset, int chan_width, - int cf1, int cf2, bool is_background) + int cf1, int cf2, bool is_background, + int chan_width_device, int cf_device) { int n_chans, n_chans1, ch_idx, ch_idx_1, dfs_cac_ms; int chwidth; @@ -1974,10 +2067,10 @@ int hostapd_dfs_start_cac(struct hostapd wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_START "freq=%d chan=%d chan_offset=%d width=%d seg0=%d " - "seg1=%d cac_time=%ds%s", + "seg1=%d cac_time=%ds chan_width_device=%d cf_device=%d%s", freq, (freq - 5000) / 5, chan_offset, chan_width, cf1, cf2, - dfs_cac_ms / 1000, - hostapd_dfs_is_background_event(iface, freq) ? + dfs_cac_ms / 1000, chan_width_device, cf_device, + (is_background || hostapd_dfs_is_background_event(iface, freq)) ? " (background)" : ""); os_get_reltime(&iface->dfs_cac_start); --- a/src/ap/dfs.h +++ b/src/ap/dfs.h @@ -25,22 +25,27 @@ int hostapd_handle_dfs(struct hostapd_if int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq, int ht_enabled, int chan_offset, int chan_width, - int cf1, int cf2, bool is_background); + int cf1, int cf2, bool is_background, + int chan_width_device, int cf_device); int hostapd_dfs_pre_cac_expired(struct hostapd_iface *iface, int freq, int ht_enabled, int chan_offset, int chan_width, - int cf1, int cf2); + int cf1, int cf2, + int chan_width_device, int cf_device); int hostapd_dfs_radar_detected(struct hostapd_iface *iface, int freq, int ht_enabled, int chan_offset, int chan_width, - int cf1, int cf2, u16 radar_bitmap); + int cf1, int cf2, u16 radar_bitmap, + int chan_width_device, int cf_device); int hostapd_dfs_nop_finished(struct hostapd_iface *iface, int freq, int ht_enabled, - int chan_offset, int chan_width, int cf1, int cf2); + int chan_offset, int chan_width, int cf1, int cf2, + int chan_width_device, int cf_device); int hostapd_is_dfs_required(struct hostapd_iface *iface); int hostapd_is_dfs_chan_available(struct hostapd_iface *iface); int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq, int ht_enabled, int chan_offset, int chan_width, - int cf1, int cf2, bool is_background); + int cf1, int cf2, bool is_background, + int chan_width_device, int cf_device); int hostapd_handle_dfs_offload(struct hostapd_iface *iface); int hostapd_is_dfs_overlap(struct hostapd_iface *iface, enum chan_width width, int center_freq); --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -1900,7 +1900,8 @@ static void hostapd_event_dfs_radar_dete wpa_printf(MSG_DEBUG, "DFS radar detected on %d MHz", radar->freq); hostapd_dfs_radar_detected(hapd->iface, radar->freq, radar->ht_enabled, radar->chan_offset, radar->chan_width, - radar->cf1, radar->cf2, radar->radar_bitmap); + radar->cf1, radar->cf2, radar->radar_bitmap, + radar->chan_width_device, radar->cf_device); } static void hostapd_event_awgn_detected(struct hostapd_data *hapd, @@ -1917,7 +1918,8 @@ static void hostapd_event_dfs_pre_cac_ex wpa_printf(MSG_DEBUG, "DFS Pre-CAC expired on %d MHz", radar->freq); hostapd_dfs_pre_cac_expired(hapd->iface, radar->freq, radar->ht_enabled, radar->chan_offset, radar->chan_width, - radar->cf1, radar->cf2); + radar->cf1, radar->cf2, + radar->chan_width_device, radar->cf_device); } @@ -1927,7 +1929,8 @@ static void hostapd_event_dfs_cac_finish wpa_printf(MSG_DEBUG, "DFS CAC finished on %d MHz", radar->freq); hostapd_dfs_complete_cac(hapd->iface, 1, radar->freq, radar->ht_enabled, radar->chan_offset, radar->chan_width, - radar->cf1, radar->cf2, radar->is_background); + radar->cf1, radar->cf2, radar->is_background, + radar->chan_width_device, radar->cf_device); } @@ -1937,7 +1940,8 @@ static void hostapd_event_dfs_cac_aborte wpa_printf(MSG_DEBUG, "DFS CAC aborted on %d MHz", radar->freq); hostapd_dfs_complete_cac(hapd->iface, 0, radar->freq, radar->ht_enabled, radar->chan_offset, radar->chan_width, - radar->cf1, radar->cf2, radar->is_background); + radar->cf1, radar->cf2, radar->is_background, + radar->chan_width_device, radar->cf_device); } @@ -1947,7 +1951,8 @@ static void hostapd_event_dfs_nop_finish wpa_printf(MSG_DEBUG, "DFS NOP finished on %d MHz", radar->freq); hostapd_dfs_nop_finished(hapd->iface, radar->freq, radar->ht_enabled, radar->chan_offset, radar->chan_width, - radar->cf1, radar->cf2); + radar->cf1, radar->cf2, + radar->chan_width_device, radar->cf_device); } @@ -1957,7 +1962,8 @@ static void hostapd_event_dfs_cac_starte wpa_printf(MSG_DEBUG, "DFS offload CAC started on %d MHz", radar->freq); hostapd_dfs_start_cac(hapd->iface, radar->freq, radar->ht_enabled, radar->chan_offset, radar->chan_width, - radar->cf1, radar->cf2, radar->is_background); + radar->cf1, radar->cf2, radar->is_background, + radar->chan_width_device, radar->cf_device); } #endif /* NEED_AP_MLME */ --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -6749,6 +6749,8 @@ union wpa_event_data { int cf2; u16 radar_bitmap; bool is_background; + enum chan_width chan_width_device; + int cf_device; } dfs_event; /** --- a/src/drivers/driver_nl80211_event.c +++ b/src/drivers/driver_nl80211_event.c @@ -2646,10 +2646,20 @@ static void nl80211_radar_event(struct i if (tb[NL80211_ATTR_RADAR_BITMAP]) data.dfs_event.radar_bitmap = nla_get_u16(tb[NL80211_ATTR_RADAR_BITMAP]); - wpa_printf(MSG_DEBUG, "nl80211: DFS event on freq %d MHz, ht: %d, offset: %d, width: %d, cf1: %dMHz, cf2: %dMHz" - "radar_bitmap: %0x ", data.dfs_event.freq, data.dfs_event.ht_enabled, + if (tb[NL80211_ATTR_CHANNEL_WIDTH_DEVICE]) + data.dfs_event.chan_width_device = + convert2width(nla_get_u32(tb[NL80211_ATTR_CHANNEL_WIDTH_DEVICE])); + if (tb[NL80211_ATTR_CENTER_FREQ_DEVICE]) + data.dfs_event.cf_device = + nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ_DEVICE]); + + wpa_printf(MSG_DEBUG, + "nl80211: DFS event on freq %d MHz, ht: %d, offset: %d, width: %d, cf1: %dMHz, " + "cf2: %dMHz radar_bitmap: %0x chan_width_device: %d cf_device: %d", + data.dfs_event.freq, data.dfs_event.ht_enabled, data.dfs_event.chan_offset, data.dfs_event.chan_width, - data.dfs_event.cf1, data.dfs_event.cf2, data.dfs_event.radar_bitmap); + data.dfs_event.cf1, data.dfs_event.cf2, data.dfs_event.radar_bitmap, + data.dfs_event.chan_width_device, data.dfs_event.cf_device); ret = wpa_is_freq_in_bss(bss, data.dfs_event.freq, &mld_link); if (ret) { --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c @@ -2148,7 +2148,8 @@ void wpas_ap_event_dfs_radar_detected(st radar->ht_enabled, radar->chan_offset, radar->chan_width, radar->cf1, radar->cf2, - radar->radar_bitmap); + radar->radar_bitmap, + radar->chan_width_device, radar->cf_device); } @@ -2165,7 +2166,8 @@ void wpas_ap_event_dfs_cac_started(struc hostapd_dfs_start_cac(iface, radar->freq, radar->ht_enabled, radar->chan_offset, radar->chan_width, radar->cf1, radar->cf2, - radar->is_background); + radar->is_background, + radar->chan_width_device, radar->cf_device); } @@ -2182,7 +2184,8 @@ void wpas_ap_event_dfs_cac_finished(stru hostapd_dfs_complete_cac(iface, 1, radar->freq, radar->ht_enabled, radar->chan_offset, radar->chan_width, radar->cf1, radar->cf2, - radar->is_background); + radar->is_background, + radar->chan_width_device, radar->cf_device); } @@ -2199,7 +2202,8 @@ void wpas_ap_event_dfs_cac_aborted(struc hostapd_dfs_complete_cac(iface, 0, radar->freq, radar->ht_enabled, radar->chan_offset, radar->chan_width, radar->cf1, radar->cf2, - radar->is_background); + radar->is_background, + radar->chan_width_device, radar->cf_device); } @@ -2215,7 +2219,8 @@ void wpas_ap_event_dfs_cac_nop_finished( wpa_printf(MSG_DEBUG, "DFS NOP finished on %d MHz", radar->freq); hostapd_dfs_nop_finished(iface, radar->freq, radar->ht_enabled, radar->chan_offset, - radar->chan_width, radar->cf1, radar->cf2); + radar->chan_width, radar->cf1, radar->cf2, + radar->chan_width_device, radar->cf_device); } #endif /* NEED_AP_MLME */