MLD STA: Indicate per link channel switch

Parse link id info from channel switch events and indicate the info to
control interface using new per link channel switch events. If channel
switch happens on the link which used during association both legacy
and new per-link channel switch events will be reported.

Signed-off-by: Veerendranath Jakkam <quic_vjakkam@quicinc.com>
This commit is contained in:
Veerendranath Jakkam 2022-09-08 20:14:22 +05:30 committed by Jouni Malinen
parent b7f98d92dc
commit 1b6f3b5850
5 changed files with 89 additions and 4 deletions

View file

@ -92,6 +92,15 @@ extern "C" {
#define WPA_EVENT_CHANNEL_SWITCH_STARTED "CTRL-EVENT-STARTED-CHANNEL-SWITCH " #define WPA_EVENT_CHANNEL_SWITCH_STARTED "CTRL-EVENT-STARTED-CHANNEL-SWITCH "
/** Channel switch (followed by freq=<MHz> and other channel parameters) */ /** Channel switch (followed by freq=<MHz> and other channel parameters) */
#define WPA_EVENT_CHANNEL_SWITCH "CTRL-EVENT-CHANNEL-SWITCH " #define WPA_EVENT_CHANNEL_SWITCH "CTRL-EVENT-CHANNEL-SWITCH "
/** MLO link channel switch started (followed by freq=<MHz> and other channel
* parameters)
*/
#define WPA_EVENT_LINK_CHANNEL_SWITCH_STARTED \
"CTRL-EVENT-STARTED-LINK-CHANNEL-SWITCH "
/** MLO link channel switch (followed by freq=<MHz> and other channel
* parameters)
*/
#define WPA_EVENT_LINK_CHANNEL_SWITCH "CTRL-EVENT-LINK-CHANNEL-SWITCH "
/** SAE authentication failed due to unknown password identifier */ /** SAE authentication failed due to unknown password identifier */
#define WPA_EVENT_SAE_UNKNOWN_PASSWORD_IDENTIFIER \ #define WPA_EVENT_SAE_UNKNOWN_PASSWORD_IDENTIFIER \
"CTRL-EVENT-SAE-UNKNOWN-PASSWORD-IDENTIFIER " "CTRL-EVENT-SAE-UNKNOWN-PASSWORD-IDENTIFIER "

View file

@ -5426,6 +5426,24 @@ enum wpa_event_type {
* PASN authentication and secure ranging context for multiple peers. * PASN authentication and secure ranging context for multiple peers.
*/ */
EVENT_PASN_AUTH, EVENT_PASN_AUTH,
/**
* EVENT_LINK_CH_SWITCH - MLD AP link decided to switch channels
*
* Described in wpa_event_data.ch_switch.
*
*/
EVENT_LINK_CH_SWITCH,
/**
* EVENT_LINK_CH_SWITCH_STARTED - MLD AP link started to switch channels
*
* This is a pre-switch event indicating the shortly following switch
* of operating channels.
*
* Described in wpa_event_data.ch_switch.
*/
EVENT_LINK_CH_SWITCH_STARTED,
}; };
@ -6141,6 +6159,7 @@ union wpa_event_data {
* @ch_width: Channel width * @ch_width: Channel width
* @cf1: Center frequency 1 * @cf1: Center frequency 1
* @cf2: Center frequency 2 * @cf2: Center frequency 2
* @link_id: Link ID of the MLO link
*/ */
struct ch_switch { struct ch_switch {
int freq; int freq;
@ -6149,6 +6168,7 @@ union wpa_event_data {
enum chan_width ch_width; enum chan_width ch_width;
int cf1; int cf1;
int cf2; int cf2;
int link_id;
} ch_switch; } ch_switch;
/** /**

View file

@ -96,6 +96,8 @@ const char * event_to_string(enum wpa_event_type event)
E2S(CCA_ABORTED_NOTIFY); E2S(CCA_ABORTED_NOTIFY);
E2S(CCA_NOTIFY); E2S(CCA_NOTIFY);
E2S(PASN_AUTH); E2S(PASN_AUTH);
E2S(LINK_CH_SWITCH);
E2S(LINK_CH_SWITCH_STARTED);
} }
return "UNKNOWN"; return "UNKNOWN";

View file

@ -782,10 +782,10 @@ static int calculate_chan_offset(int width, int freq, int cf1, int cf2)
static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv, static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv,
struct nlattr *ifindex, struct nlattr *freq, struct nlattr *ifindex, struct nlattr *link,
struct nlattr *type, struct nlattr *bw, struct nlattr *freq, struct nlattr *type,
struct nlattr *cf1, struct nlattr *cf2, struct nlattr *bw, struct nlattr *cf1,
int finished) struct nlattr *cf2, int finished)
{ {
struct i802_bss *bss; struct i802_bss *bss;
union wpa_event_data data; union wpa_event_data data;
@ -849,6 +849,25 @@ static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv,
if (finished) if (finished)
bss->freq = data.ch_switch.freq; bss->freq = data.ch_switch.freq;
if (link) {
u8 link_id = nla_get_u8(link);
if (link_id < MAX_NUM_MLD_LINKS &&
drv->sta_mlo_info.valid_links & BIT(link_id)) {
data.ch_switch.link_id = link_id;
drv->sta_mlo_info.links[link_id].freq =
data.ch_switch.freq;
wpa_supplicant_event(
bss->ctx,
finished ? EVENT_LINK_CH_SWITCH :
EVENT_LINK_CH_SWITCH_STARTED, &data);
}
if (link_id != drv->mlo_assoc_link_id)
return;
}
drv->assoc_freq = data.ch_switch.freq; drv->assoc_freq = data.ch_switch.freq;
wpa_supplicant_event(bss->ctx, finished ? wpa_supplicant_event(bss->ctx, finished ?
@ -3303,6 +3322,7 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
case NL80211_CMD_CH_SWITCH_STARTED_NOTIFY: case NL80211_CMD_CH_SWITCH_STARTED_NOTIFY:
mlme_event_ch_switch(drv, mlme_event_ch_switch(drv,
tb[NL80211_ATTR_IFINDEX], tb[NL80211_ATTR_IFINDEX],
tb[NL80211_ATTR_MLO_LINK_ID],
tb[NL80211_ATTR_WIPHY_FREQ], tb[NL80211_ATTR_WIPHY_FREQ],
tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE], tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE],
tb[NL80211_ATTR_CHANNEL_WIDTH], tb[NL80211_ATTR_CHANNEL_WIDTH],
@ -3313,6 +3333,7 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
case NL80211_CMD_CH_SWITCH_NOTIFY: case NL80211_CMD_CH_SWITCH_NOTIFY:
mlme_event_ch_switch(drv, mlme_event_ch_switch(drv,
tb[NL80211_ATTR_IFINDEX], tb[NL80211_ATTR_IFINDEX],
tb[NL80211_ATTR_MLO_LINK_ID],
tb[NL80211_ATTR_WIPHY_FREQ], tb[NL80211_ATTR_WIPHY_FREQ],
tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE], tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE],
tb[NL80211_ATTR_CHANNEL_WIDTH], tb[NL80211_ATTR_CHANNEL_WIDTH],

View file

@ -5367,6 +5367,39 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
break; break;
#endif /* CONFIG_AP */ #endif /* CONFIG_AP */
case EVENT_LINK_CH_SWITCH_STARTED:
case EVENT_LINK_CH_SWITCH:
if (!data || !wpa_s->current_ssid ||
!(wpa_s->valid_links & BIT(data->ch_switch.link_id)))
break;
wpa_msg(wpa_s, MSG_INFO,
"%sfreq=%d link_id=%d ht_enabled=%d ch_offset=%d ch_width=%s cf1=%d cf2=%d",
event == EVENT_LINK_CH_SWITCH ?
WPA_EVENT_LINK_CHANNEL_SWITCH :
WPA_EVENT_LINK_CHANNEL_SWITCH_STARTED,
data->ch_switch.freq,
data->ch_switch.link_id,
data->ch_switch.ht_enabled,
data->ch_switch.ch_offset,
channel_width_to_string(data->ch_switch.ch_width),
data->ch_switch.cf1,
data->ch_switch.cf2);
if (event == EVENT_LINK_CH_SWITCH_STARTED)
break;
wpa_s->links[data->ch_switch.link_id].freq =
data->ch_switch.freq;
if (wpa_s->links[data->ch_switch.link_id].bss &&
wpa_s->links[data->ch_switch.link_id].bss->freq !=
data->ch_switch.freq) {
wpa_s->links[data->ch_switch.link_id].bss->freq =
data->ch_switch.freq;
notify_bss_changes(
wpa_s, WPA_BSS_FREQ_CHANGED_FLAG,
wpa_s->links[data->ch_switch.link_id].bss);
}
break;
case EVENT_CH_SWITCH_STARTED: case EVENT_CH_SWITCH_STARTED:
case EVENT_CH_SWITCH: case EVENT_CH_SWITCH:
if (!data || !wpa_s->current_ssid) if (!data || !wpa_s->current_ssid)