P2P: DFS offload for the autonomous GO
Enhance the P2P_GROUP_ADD command to support DFS channel with 80 and 160 MHz bandwidth to be used for autonomous GO when using offloaded DFS. For example, 'P2P_GROUP_ADD freq=5500 max_oper_chwidth=80 ht40 vht' - Previous behavior: AP fallback to channel 100 using 20 MHz with "No VHT higher bandwidth support for the selected channel 100" - Enhanced behavior: AP starts on channel 100 using 80 MHz with "VHT center channel 106 for 80 or 80+80 MHz bandwidth" This functionality is on top of the driver's capability to offload DFS, which is advertized through WPA_DRIVER_FLAGS_DFS_OFFLOAD. Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
This commit is contained in:
parent
6ba665c5c3
commit
ce267f4da9
5 changed files with 50 additions and 8 deletions
|
@ -1531,6 +1531,16 @@ int ieee80211_is_dfs(int freq, const struct hostapd_hw_modes *modes,
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* 802.11-2020: Table E-4 - Global operating classes
|
||||
* DFS_50_100_Behavior: 118, 119, 120, 121, 122, 123
|
||||
*/
|
||||
int is_dfs_global_op_class(u8 op_class)
|
||||
{
|
||||
return (op_class >= 118) && (op_class <= 123);
|
||||
}
|
||||
|
||||
|
||||
static int is_11b(u8 rate)
|
||||
{
|
||||
return rate == 0x02 || rate == 0x04 || rate == 0x0b || rate == 0x16;
|
||||
|
|
|
@ -218,6 +218,7 @@ int ieee80211_chaninfo_to_channel(unsigned int freq, enum chan_width chanwidth,
|
|||
int sec_channel, u8 *op_class, u8 *channel);
|
||||
int ieee80211_is_dfs(int freq, const struct hostapd_hw_modes *modes,
|
||||
u16 num_modes);
|
||||
int is_dfs_global_op_class(u8 op_class);
|
||||
enum phy_type ieee80211_get_phy_type(int freq, int ht, int vht);
|
||||
|
||||
int supp_rates_11b_only(struct ieee802_11_elems *elems);
|
||||
|
|
|
@ -6931,6 +6931,10 @@ static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
|
|||
if (allow_6ghz && chwidth == 40)
|
||||
max_oper_chwidth = CHANWIDTH_40MHZ_6GHZ;
|
||||
|
||||
/* Allow DFS to be used for Autonomous GO */
|
||||
wpa_s->p2p_go_allow_dfs = !!(wpa_s->drv_flags &
|
||||
WPA_DRIVER_FLAGS_DFS_OFFLOAD);
|
||||
|
||||
if (group_id >= 0)
|
||||
return p2p_ctrl_group_add_persistent(wpa_s, group_id,
|
||||
freq, freq2, ht40, vht,
|
||||
|
|
|
@ -1038,6 +1038,7 @@ static int wpas_p2p_group_delete(struct wpa_supplicant *wpa_s,
|
|||
wpa_s->p2p_group_common_freqs = NULL;
|
||||
wpa_s->p2p_group_common_freqs_num = 0;
|
||||
wpa_s->p2p_go_do_acs = 0;
|
||||
wpa_s->p2p_go_allow_dfs = 0;
|
||||
|
||||
wpa_s->waiting_presence_resp = 0;
|
||||
|
||||
|
@ -3585,12 +3586,12 @@ static enum chan_allowed has_channel(struct wpa_global *global,
|
|||
if ((unsigned int) mode->channels[i].freq == freq) {
|
||||
if (flags)
|
||||
*flags = mode->channels[i].flag;
|
||||
if (mode->channels[i].flag &
|
||||
(HOSTAPD_CHAN_DISABLED |
|
||||
HOSTAPD_CHAN_RADAR))
|
||||
if (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED)
|
||||
return NOT_ALLOWED;
|
||||
if (mode->channels[i].flag & HOSTAPD_CHAN_NO_IR)
|
||||
return NO_IR;
|
||||
if (mode->channels[i].flag & HOSTAPD_CHAN_RADAR)
|
||||
return RADAR;
|
||||
return ALLOWED;
|
||||
}
|
||||
}
|
||||
|
@ -3650,7 +3651,8 @@ static enum chan_allowed wpas_p2p_verify_80mhz(struct wpa_supplicant *wpa_s,
|
|||
chans, num_chans);
|
||||
if (!center_chan)
|
||||
return NOT_ALLOWED;
|
||||
if (!is_6ghz && center_chan >= 58 && center_chan <= 138)
|
||||
if (!wpa_s->p2p_go_allow_dfs &&
|
||||
!is_6ghz && center_chan >= 58 && center_chan <= 138)
|
||||
return NOT_ALLOWED; /* Do not allow DFS channels for P2P */
|
||||
|
||||
/* check all the channels are available */
|
||||
|
@ -3661,6 +3663,8 @@ static enum chan_allowed wpas_p2p_verify_80mhz(struct wpa_supplicant *wpa_s,
|
|||
&flags);
|
||||
if (res == NOT_ALLOWED)
|
||||
return NOT_ALLOWED;
|
||||
if (res == RADAR)
|
||||
ret = RADAR;
|
||||
if (res == NO_IR)
|
||||
ret = NO_IR;
|
||||
if (!is_6ghz) {
|
||||
|
@ -3742,6 +3746,8 @@ static enum chan_allowed wpas_p2p_verify_160mhz(struct wpa_supplicant *wpa_s,
|
|||
if (res == NOT_ALLOWED)
|
||||
return NOT_ALLOWED;
|
||||
|
||||
if (res == RADAR)
|
||||
ret = RADAR;
|
||||
if (res == NO_IR)
|
||||
ret = NO_IR;
|
||||
|
||||
|
@ -3828,6 +3834,8 @@ static enum chan_allowed wpas_p2p_verify_channel(struct wpa_supplicant *wpa_s,
|
|||
return NOT_ALLOWED;
|
||||
if (res == NO_IR || res2 == NO_IR)
|
||||
return NO_IR;
|
||||
if (res == RADAR || res2 == RADAR)
|
||||
return RADAR;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -3936,7 +3944,11 @@ int wpas_p2p_get_sec_channel_offset_40mhz(struct wpa_supplicant *wpa_s,
|
|||
u16 ch;
|
||||
int chan = channel;
|
||||
|
||||
if (o->p2p == NO_P2P_SUPP ||
|
||||
/* Allow DFS channels marked as NO_P2P_SUPP to be used with
|
||||
* driver offloaded DFS. */
|
||||
if ((o->p2p == NO_P2P_SUPP &&
|
||||
(!is_dfs_global_op_class(o->op_class) ||
|
||||
!wpa_s->p2p_go_allow_dfs)) ||
|
||||
(is_6ghz_op_class(o->op_class) &&
|
||||
wpa_s->conf->p2p_6ghz_disable))
|
||||
continue;
|
||||
|
@ -3959,6 +3971,11 @@ int wpas_p2p_get_sec_channel_offset_40mhz(struct wpa_supplicant *wpa_s,
|
|||
return get_6ghz_sec_channel(channel);
|
||||
return (o->bw == BW40MINUS) ? -1 : 1;
|
||||
}
|
||||
if (ret == RADAR && wpa_s->p2p_go_allow_dfs) {
|
||||
/* Allow RADAR channels used for driver
|
||||
* offloaded DFS */
|
||||
return (o->bw == BW40MINUS) ? -1 : 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
@ -3971,8 +3988,10 @@ int wpas_p2p_get_vht80_center(struct wpa_supplicant *wpa_s,
|
|||
{
|
||||
const u8 *chans;
|
||||
size_t num_chans;
|
||||
enum chan_allowed ret;
|
||||
|
||||
if (!wpas_p2p_verify_channel(wpa_s, mode, op_class, channel, BW80))
|
||||
ret = wpas_p2p_verify_channel(wpa_s, mode, op_class, channel, BW80);
|
||||
if (!(ret == ALLOWED || (ret == RADAR && wpa_s->p2p_go_allow_dfs)))
|
||||
return 0;
|
||||
|
||||
if (is_6ghz_op_class(op_class)) {
|
||||
|
@ -3993,8 +4012,10 @@ int wpas_p2p_get_vht160_center(struct wpa_supplicant *wpa_s,
|
|||
{
|
||||
const u8 *chans;
|
||||
size_t num_chans;
|
||||
enum chan_allowed ret;
|
||||
|
||||
if (!wpas_p2p_verify_channel(wpa_s, mode, op_class, channel, BW160))
|
||||
ret = wpas_p2p_verify_channel(wpa_s, mode, op_class, channel, BW160);
|
||||
if (!(ret == ALLOWED || (ret == RADAR && wpa_s->p2p_go_allow_dfs)))
|
||||
return 0;
|
||||
if (is_6ghz_op_class(op_class)) {
|
||||
chans = center_channels_6ghz_160mhz;
|
||||
|
@ -6766,6 +6787,11 @@ wpas_p2p_get_group_iface(struct wpa_supplicant *wpa_s, int addr_allocated,
|
|||
wpa_s->p2p_go_do_acs = 0;
|
||||
}
|
||||
|
||||
if (go && wpa_s->p2p_go_allow_dfs) {
|
||||
group_wpa_s->p2p_go_allow_dfs = wpa_s->p2p_go_allow_dfs;
|
||||
wpa_s->p2p_go_allow_dfs = 0;
|
||||
}
|
||||
|
||||
wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Use separate group interface %s",
|
||||
group_wpa_s->ifname);
|
||||
group_wpa_s->p2p_first_connection_timeout = 0;
|
||||
|
|
|
@ -1125,6 +1125,7 @@ struct wpa_supplicant {
|
|||
unsigned int p2p_disable_ip_addr_req:1;
|
||||
unsigned int p2ps_method_config_any:1;
|
||||
unsigned int p2p_cli_probe:1;
|
||||
unsigned int p2p_go_allow_dfs:1;
|
||||
enum hostapd_hw_mode p2p_go_acs_band;
|
||||
int p2p_persistent_go_freq;
|
||||
int p2p_persistent_id;
|
||||
|
@ -1675,7 +1676,7 @@ void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s);
|
|||
|
||||
/* op_classes.c */
|
||||
enum chan_allowed {
|
||||
NOT_ALLOWED, NO_IR, ALLOWED
|
||||
NOT_ALLOWED, NO_IR, RADAR, ALLOWED
|
||||
};
|
||||
|
||||
enum chan_allowed verify_channel(struct hostapd_hw_modes *mode, u8 op_class,
|
||||
|
|
Loading…
Reference in a new issue