wifi-4421: Fix client disconn when in DFS channel

On detecting Radar on the DFS channel the radio switches
the channel to backup channel. However, the opensync tries
to set it back to the configured channel every 30 seconds, which
which would fail since the channel is in a radar NOP period, this
leads to dropping of clients.
Fix by adding a check for the configured channel's availability
before trying to change to that channel.
Also, check if the radio Channel config has changed before
attempting to change the channel.

Signed-off-by: Chaitanya Godavarthi <chaitanya.kiran@netexperience.com>
This commit is contained in:
Chaitanya Godavarthi
2021-09-26 20:03:06 -04:00
committed by Arif
parent 4cd7cab7d0
commit 16149f6ba5
7 changed files with 113 additions and 9 deletions

View File

@@ -0,0 +1,29 @@
Index: hostapd-2020-07-02-58b384f4/src/ap/ubus.c
===================================================================
--- hostapd-2020-07-02-58b384f4.orig/src/ap/ubus.c
+++ hostapd-2020-07-02-58b384f4/src/ap/ubus.c
@@ -1016,12 +1016,18 @@ hostapd_switch_chan(struct ubus_context
css.freq_params.center_freq1,
css.freq_params.center_freq2);
- if ((chan->flag & HOSTAPD_CHAN_RADAR) &&
- ((chan->flag & HOSTAPD_CHAN_DFS_MASK)
- != HOSTAPD_CHAN_DFS_AVAILABLE)) {
- wpa_printf(MSG_INFO, "%s: DFS chan need CAC", __func__);
- hostapd_switch_chan_dfs(iface, &css);
- return UBUS_STATUS_OK;
+ if (chan->flag & HOSTAPD_CHAN_RADAR) {
+ if ((chan->flag & HOSTAPD_CHAN_DFS_MASK) ==
+ HOSTAPD_CHAN_DFS_UNAVAILABLE) {
+ wpa_printf(MSG_WARNING, "DFS chan %d not Available",
+ chan->chan);
+ return UBUS_STATUS_NOT_SUPPORTED;
+ } else if ((chan->flag & HOSTAPD_CHAN_DFS_MASK)
+ != HOSTAPD_CHAN_DFS_AVAILABLE) {
+ wpa_printf(MSG_DEBUG, "DFS chan do CAC");
+ hostapd_switch_chan_dfs(iface, &css);
+ return UBUS_STATUS_OK;
+ }
}
for (i = 0; i < hapd->iface->num_bss; i++) {

View File

@@ -0,0 +1,29 @@
Index: hostapd-2020-06-08-5a8b3662/src/ap/ubus.c
===================================================================
--- hostapd-2020-06-08-5a8b3662.orig/src/ap/ubus.c
+++ hostapd-2020-06-08-5a8b3662/src/ap/ubus.c
@@ -1015,12 +1015,18 @@ hostapd_switch_chan(struct ubus_context
css.freq_params.center_freq1,
css.freq_params.center_freq2);
- if ((chan->flag & HOSTAPD_CHAN_RADAR) &&
- ((chan->flag & HOSTAPD_CHAN_DFS_MASK)
- != HOSTAPD_CHAN_DFS_AVAILABLE)) {
- wpa_printf(MSG_INFO, "%s: DFS chan need CAC", __func__);
- hostapd_switch_chan_dfs(iface, &css);
- return UBUS_STATUS_OK;
+ if (chan->flag & HOSTAPD_CHAN_RADAR) {
+ if ((chan->flag & HOSTAPD_CHAN_DFS_MASK) ==
+ HOSTAPD_CHAN_DFS_UNAVAILABLE) {
+ wpa_printf(MSG_WARNING, "DFS chan %d not Available",
+ chan->chan);
+ return UBUS_STATUS_NOT_SUPPORTED;
+ } else if ((chan->flag & HOSTAPD_CHAN_DFS_MASK)
+ != HOSTAPD_CHAN_DFS_AVAILABLE) {
+ wpa_printf(MSG_DEBUG, "DFS chan do CAC");
+ hostapd_switch_chan_dfs(iface, &css);
+ return UBUS_STATUS_OK;
+ }
}
for (i = 0; i < hapd->iface->num_bss; i++) {

View File

@@ -21,10 +21,13 @@ struct radio_fixup {
struct avl_node avl;
char rname[IF_NAMESIZE];
char hw_mode[8];
int chan;
};
struct radio_fixup * radio_fixup_find(const char *name);
void radio_fixup_del(char *ifname);
void radio_fixup_set_hw_mode(const char *ifname, char *hw_mode);
char *radio_fixup_get_hw_mode(const char *ifname);
int radio_fixup_get_primary_chan(const char *ifname);
void radio_fixup_set_primary_chan(const char *ifname, int chan);
#endif

View File

@@ -40,6 +40,6 @@ void callback_Wifi_RRM_Config(ovsdb_update_monitor_t *mon,
struct schema_Wifi_RRM_Config *old, struct schema_Wifi_RRM_Config *conf);
void rrm_radio_rebalance_channel(const struct schema_Wifi_Radio_Config *rconf);
int rrm_radio_rebalance_channel(const struct schema_Wifi_Radio_Config *rconf);
#endif /* RRM_CONFIG_H_INCLUDED */

View File

@@ -138,3 +138,26 @@ char * radio_fixup_get_hw_mode(const char *ifname)
else
return NULL;
}
/* primary channel */
void radio_fixup_set_primary_chan(const char *ifname, int chan)
{
struct radio_fixup * radio = NULL;
radio = radio_fixup_find(ifname);
if (radio)
radio->chan = chan;
}
int radio_fixup_get_primary_chan(const char *ifname)
{
struct radio_fixup * radio = NULL;
radio = radio_fixup_find(ifname);
if (radio)
return radio->chan;
else
return -1;
}

View File

@@ -226,7 +226,7 @@ static int get_channel_tx_power_debugfs(char *stats_path, int *tx_power)
fp = fopen(stats_path, "r");
if (!fp) {
LOGE("%s: Failed to get tx power, stats file does not exist", __func__);
LOGI("%s: ERR Failed to get tx power, stats file does not exist", __func__);
return -1;
}
@@ -279,13 +279,24 @@ static int get_channel_tx_power(char* phy, int *tx_power)
}
if (get_channel_tx_power_debugfs(stats_path, tx_power)) {
LOGE("%s: Failed to get Channel Tx Power", __func__);
LOGI("%s: ERR Failed to get Channel Tx Power", __func__);
return -1;
}
return 0;
}
int is_cloud_channel_change(const struct schema_Wifi_Radio_Config *rconf)
{
int channel = 0;
channel = radio_fixup_get_primary_chan(rconf->if_name);
if (channel == rconf->channel)
return -1;
return 0;
}
const struct uci_blob_param_list wifi_device_param = {
.n_params = __WDEV_ATTR_MAX,
.params = wifi_device_policy,
@@ -330,6 +341,8 @@ static bool radio_state_update(struct uci_section *s, struct schema_Wifi_Radio_C
SCHEMA_SET_INT(rstate.channel, chan);
else
SCHEMA_SET_INT(rstate.channel, blobmsg_get_u32(tb[WDEV_ATTR_CHANNEL]));
radio_fixup_set_primary_chan(rstate.if_name,
blobmsg_get_u32(tb[WDEV_ATTR_CHANNEL]));
}
SCHEMA_SET_INT(rstate.enabled, 1);
@@ -341,7 +354,7 @@ static bool radio_state_update(struct uci_section *s, struct schema_Wifi_Radio_C
if (!get_channel_tx_power(phy, &tx_power)) {
SCHEMA_SET_INT(rstate.tx_power, tx_power);
} else {
LOGE("%s: Failed to update Channel Tx Power", __func__);
LOGI("%s:ERR: Failed to update Channel Tx Power", __func__);
/* Set Tx Power to max OVSDB value */
SCHEMA_SET_INT(rstate.tx_power, 32);
}
@@ -452,8 +465,15 @@ bool target_radio_config_set2(const struct schema_Wifi_Radio_Config *rconf,
strncpy(phy, target_map_ifname(ifname), sizeof(phy));
if (changed->channel && rconf->channel) {
blobmsg_add_u32(&b, "channel", rconf->channel);
rrm_radio_rebalance_channel(rconf);
/* If radio channel config has changed then rebalance channel,
* if not, that means the channel state changed due to a
* radar detection and shall remain in the backup channel */
if (is_cloud_channel_change(rconf) == 0) {
if(rrm_radio_rebalance_channel(rconf) == 0) {
blobmsg_add_u32(&b, "channel", rconf->channel);
radio_fixup_set_primary_chan(rconf->if_name, rconf->channel);
}
}
}
if (changed->enabled)

View File

@@ -319,7 +319,7 @@ void get_channel_bandwidth(const char* htmode, int *channel_bandwidth)
*channel_bandwidth=80;
}
void rrm_radio_rebalance_channel(const struct schema_Wifi_Radio_Config *rconf)
int rrm_radio_rebalance_channel(const struct schema_Wifi_Radio_Config *rconf)
{
int channel_bandwidth;
int sec_chan_offset=0;
@@ -339,7 +339,7 @@ void rrm_radio_rebalance_channel(const struct schema_Wifi_Radio_Config *rconf)
hw_mode = radio_fixup_get_hw_mode(rconf->if_name);
if (hw_mode == NULL) {
LOGE("Failed to get hw mode");
return;
return -1;
}
m = mode_map_get_uci(rconf->freq_band, mode, hw_mode);
@@ -352,7 +352,7 @@ void rrm_radio_rebalance_channel(const struct schema_Wifi_Radio_Config *rconf)
get_channel_bandwidth(mode, &channel_bandwidth);
ubus_set_channel_switch(wlanif, freq, hw_mode,
return ubus_set_channel_switch(wlanif, freq, hw_mode,
channel_bandwidth, sec_chan_offset, 1);
}