Repository navigation
LTE-3100: DFS channel can't be reuse for BH on nop_started - #1542
poornakumar-pk wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
The new validation relies on incorrect frequency conversion that rejects valid backhaul candidates.
1 open issue
What changed in this PR
Backports #1490’s DFS non-occupancy protection to stable2, validating backhaul candidates before attempting a connection.
Changes:
- Validates cached and scanned candidates against radio capabilities and runtime channel availability before calling
wifi_hal_connect(). - Updates candidate state and reschedules connection selection after rejection.
- Extends radar checks to valid 160 MHz operating blocks, including those with non-DFS primary channels.
| File | Description |
|---|---|
| source/utils/wifi_util.c | Expands DFS runtime checks to cover 160 MHz operating blocks. |
| source/core/services/vap_svc_mesh_ext.c | Adds candidate validation and rejection handling before backhaul connection attempts. |
Review effort: Balanced
2539b71 to
5c847a3
Compare
Reason for change: It prevents the STA connection attempt when the candidate is invalid Test Procedure: check XLE not use same channel while it is in the nop_started state Risks: Priority: P1 Signed-off-by: poornakumar_mezhiselvam@comcast.com
5c847a3 to
e21d3f9
Compare
|
@poornakumar-pk thanks for the band-aware converter, the retry on allocation failure and the width update in the latest push. Taking the smaller of the parent's width and the radio's width fixes the false rejections (149/80 with a radio last at 160 MHz, 165/20). Three gaps remain:
Proposal: check only what this PR is about, the NOP state of the parent's whole operating block, and keep the radio-config validator out of the connect path. The parent's block always contains the block the extender will use, so no NOP channel is missed. The cost is a conservative reject when the extender can't use the full width. It also removes the 100 KB copy per attempt and the width special cases. Patch on top of the current head: diff --git a/source/core/services/vap_svc_mesh_ext.c b/source/core/services/vap_svc_mesh_ext.c
--- a/source/core/services/vap_svc_mesh_ext.c
+++ b/source/core/services/vap_svc_mesh_ext.c
@@ -1054,6 +1054,41 @@ static void reset_sta_state(vap_svc_t *svc, unsigned int vap_index)
}
}
+/* True if any 20 MHz channel of the 5 GHz block (channel, width) is in DFS non-occupancy */
+static bool ext_channel_block_in_nop(wifi_radio_operationParam_t *radio_params,
+ unsigned int channel, wifi_channelBandwidth_t width)
+{
+ unsigned int i, span, first;
+ int ch;
+
+ if (radio_params->band != WIFI_FREQUENCY_5_BAND &&
+ radio_params->band != WIFI_FREQUENCY_5L_BAND &&
+ radio_params->band != WIFI_FREQUENCY_5H_BAND) {
+ return false;
+ }
+
+ // block size in channel numbers, one 20 MHz channel is 4
+ if (width == WIFI_CHANNELBANDWIDTH_160MHZ || width == WIFI_CHANNELBANDWIDTH_320MHZ) {
+ span = 32;
+ } else if (width == WIFI_CHANNELBANDWIDTH_80MHZ || width == WIFI_CHANNELBANDWIDTH_80_80MHZ) {
+ span = 16;
+ } else if (width == WIFI_CHANNELBANDWIDTH_40MHZ) {
+ span = 8;
+ } else {
+ span = 4;
+ }
+ first = 36 + (channel - 36) / span * span;
+
+ for (i = 0; i < sizeof(radio_params->channel_map) / sizeof(radio_params->channel_map[0]); i++) {
+ ch = radio_params->channel_map[i].ch_number;
+ if (ch >= (int)first && ch < (int)(first + span) &&
+ radio_params->channel_map[i].ch_state == CHAN_STATE_DFS_NOP_START) {
+ return true;
+ }
+ }
+ return false;
+}
+
void ext_try_connecting(vap_svc_t *svc)
{
vap_svc_ext_t *ext;
@@ -1068,7 +1103,7 @@ void ext_try_connecting(vap_svc_t *svc)
wifi_ctrl_t *ctrl;
wifi_mgr_t *mgr;
wifi_radio_operationParam_t *radio_params;
- wifi_radio_operationParam_t *candidate_params;
+ wifi_channelBandwidth_t candidate_bw;
unsigned char candidate_channel;
ctrl = svc->ctrl;
@@ -1183,51 +1218,15 @@ void ext_try_connecting(vap_svc_t *svc)
candidate_channel = 0;
convert_freq_to_channel(candidate->radio_freq_band, candidate->external_ap.freq,
&candidate_channel);
- candidate_params = (wifi_radio_operationParam_t *)malloc(sizeof(wifi_radio_operationParam_t));
- if (candidate_params == NULL) {
- wifi_util_error_print(WIFI_CTRL, "%s:%d: failed to allocate candidate radio parameters\n",
- __func__, __LINE__);
- schedule_connect_sm(svc);
- return;
- }
-
+ // check the parent's whole block; fall back to the radio width if the parent's is unknown
+ candidate_bw = candidate->external_ap.oper_chan_bw;
pthread_mutex_lock(&mgr->data_cache_lock);
- memcpy(candidate_params, radio_params, sizeof(wifi_radio_operationParam_t));
- pthread_mutex_unlock(&mgr->data_cache_lock);
-
- candidate_params->channel = candidate_channel;
- /*
- * When AP width is unknown, retain the configured STA width so DFS
- * validation does not assume a narrower channel block.
- */
- if (candidate->external_ap.oper_chan_bw != 0) {
- if ((candidate->radio_freq_band == WIFI_FREQUENCY_5_BAND ||
- candidate->radio_freq_band == WIFI_FREQUENCY_5L_BAND ||
- candidate->radio_freq_band == WIFI_FREQUENCY_5H_BAND) &&
- candidate->external_ap.oper_chan_bw == WIFI_CHANNELBANDWIDTH_80_80MHZ) {
- if (radio_params->channelWidth <= WIFI_CHANNELBANDWIDTH_80MHZ) {
- candidate_params->channelWidth = radio_params->channelWidth;
- } else {
- /*
- * BSS information does not provide the second 80 MHz
- * segment, so its DFS/NOP state cannot be validated.
- */
- candidate_params->channelWidth = WIFI_CHANNELBANDWIDTH_80_80MHZ;
- }
- } else {
- if (radio_params->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ) {
- candidate_params->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
- }
- if (candidate->external_ap.oper_chan_bw < candidate_params->channelWidth) {
- candidate_params->channelWidth = candidate->external_ap.oper_chan_bw;
- }
- }
+ if (candidate_bw == 0) {
+ candidate_bw = radio_params->channelWidth;
}
-
candidate_valid = (candidate_channel != 0) &&
- (wifi_radio_operationParam_validation(&mgr->hal_cap, candidate_params) == RETURN_OK);
- free(candidate_params);
- candidate_params = NULL;
+ !ext_channel_block_in_nop(radio_params, candidate_channel, candidate_bw);
+ pthread_mutex_unlock(&mgr->data_cache_lock);
if (!candidate_valid) {
wifi_util_error_print(WIFI_CTRL,When the parent's width is unknown ( I tested it with an RPi build and link, plus a table test that runs the real helper, validator and converter code over 25 scenarios, with your current push as a column. Your push misses only the 36/160 NOP case, the DFS-off case and the unknown-width cases. The same change applies on develop on top of this PR, so could you open the develop follow-up as well? |


Reason for change: It prevents the STA connection attempt when the candidate is invalid
Test Procedure: check XLE not use same channel while it is in the nop_started state
Risks:
Priority: P1
Signed-off-by: poornakumar_mezhiselvam@comcast.com