From: Chandru Gopi IEEE Std 802.11-2024 subclause 9.4.2.216 (Max Channel Switch Time element) defines a Switch Time field in the Channel Switch Announcement (CSA) element that indicates the time delta between the time the last beacon is transmitted by the AP in the current channel and the expected time of the first beacon transmitted by the AP in the new channel. Add a new u32 nl80211 attribute, NL80211_ATTR_MAX_CH_SWITCH_TIME, and extend cfg80211_ch_switch_started_notify() to carry this value. The value is forwarded to userspace via the NL80211_CMD_CH_SWITCH_STARTED_NOTIFY event. Userspace can use this information to decide whether to remain connected or disconnect before the AP moves to the new channel. Signed-off-by: Chandru Gopi Signed-off-by: Shashikala Prabhu --- include/net/cfg80211.h | 4 +++- include/uapi/linux/nl80211.h | 11 +++++++++++ net/wireless/nl80211.c | 13 +++++++++---- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 8188ad200de5..93ce6bf4d385 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -9987,6 +9987,8 @@ void cfg80211_ch_switch_notify(struct net_device *dev, * @link_id: the link ID for MLO, must be 0 for non-MLO * @count: the number of TBTTs until the channel switch happens * @quiet: whether or not immediate quiet was requested by the AP + * @mcst_tu: max channel switch time in TUs, 0 if the MCST element was not + * present * * Inform the userspace about the channel switch that has just * started, so that it can take appropriate actions (eg. starting @@ -9995,7 +9997,7 @@ void cfg80211_ch_switch_notify(struct net_device *dev, void cfg80211_ch_switch_started_notify(struct net_device *dev, struct cfg80211_chan_def *chandef, unsigned int link_id, u8 count, - bool quiet); + bool quiet, u32 mcst_tu); /** * ieee80211_operating_class_to_band - convert operating class to band diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 9998f6c0a665..daee71bcf9cd 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -953,6 +953,10 @@ * after %NL80211_ATTR_CH_SWITCH_COUNT TBTT's. The userspace may * decide to react to this indication by requesting other * interfaces to change channel as well. + * %NL80211_ATTR_MAX_CH_SWITCH_TIME included in this command indicates the + * AP's Max Channel Switch Time. Userspace can use this information to + * decide whether to remain connected or disconnect before the AP moves to + * the new channel. * * @NL80211_CMD_START_P2P_DEVICE: Start the given P2P Device, identified by * its %NL80211_ATTR_WDEV identifier. It must have been created with @@ -3165,6 +3169,12 @@ enum nl80211_commands { * @NL80211_ATTR_NPCA_PRIMARY_FREQ: NPCA primary channel (u32) * @NL80211_ATTR_NPCA_PUNCT_BITMAP: NPCA puncturing bitmap (u32) * + * @NL80211_ATTR_MAX_CH_SWITCH_TIME: u32 attribute carrying the Switch Time + * field from the MCST (Max Channel Switch Time) element, indicating the + * time delta between the time the last beacon is transmitted by the AP in + * the current channel and the expected time of the first beacon + * transmitted by the AP in the new channel, expressed in TUs. + * * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use @@ -3762,6 +3772,7 @@ enum nl80211_attrs { NL80211_ATTR_NPCA_PRIMARY_FREQ, NL80211_ATTR_NPCA_PUNCT_BITMAP, + NL80211_ATTR_MAX_CH_SWITCH_TIME, /* add attributes here, update the policy in nl80211.c */ diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 53b4b3f76697..b6bc5e395a7f 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -22290,7 +22290,8 @@ static void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev, struct cfg80211_chan_def *chandef, gfp_t gfp, enum nl80211_commands notif, - u8 count, bool quiet) + u8 count, bool quiet, + u32 mcst_tu) { struct wireless_dev *wdev = netdev->ieee80211_ptr; struct sk_buff *msg; @@ -22322,6 +22323,10 @@ static void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev, if (quiet && nla_put_flag(msg, NL80211_ATTR_CH_SWITCH_BLOCK_TX)) goto nla_put_failure; + if (mcst_tu && (wdev->iftype == NL80211_IFTYPE_STATION || + wdev->iftype == NL80211_IFTYPE_P2P_CLIENT) && + nla_put_u32(msg, NL80211_ATTR_MAX_CH_SWITCH_TIME, mcst_tu)) + goto nla_put_failure; } genlmsg_end(msg, hdr); @@ -22374,7 +22379,7 @@ void cfg80211_ch_switch_notify(struct net_device *dev, cfg80211_sched_dfs_chan_update(rdev); nl80211_ch_switch_notify(rdev, dev, link_id, chandef, GFP_KERNEL, - NL80211_CMD_CH_SWITCH_NOTIFY, 0, false); + NL80211_CMD_CH_SWITCH_NOTIFY, 0, false, 0); } EXPORT_SYMBOL(cfg80211_ch_switch_notify); @@ -22421,7 +22426,7 @@ EXPORT_SYMBOL(cfg80211_incumbent_signal_notify); void cfg80211_ch_switch_started_notify(struct net_device *dev, struct cfg80211_chan_def *chandef, unsigned int link_id, u8 count, - bool quiet) + bool quiet, u32 mcst_tu) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct wiphy *wiphy = wdev->wiphy; @@ -22435,7 +22440,7 @@ void cfg80211_ch_switch_started_notify(struct net_device *dev, nl80211_ch_switch_notify(rdev, dev, link_id, chandef, GFP_KERNEL, NL80211_CMD_CH_SWITCH_STARTED_NOTIFY, - count, quiet); + count, quiet, mcst_tu); } EXPORT_SYMBOL(cfg80211_ch_switch_started_notify); -- 2.34.1 From: Chandru Gopi IEEE Std 802.11-2024 subclause 9.4.2.216 (Max Channel Switch Time element) defines a Switch Time field in the Channel Switch Announcement (CSA) element that indicates the time delta between the time the last beacon is transmitted by the AP in the current channel and the expected time of the first beacon transmitted by the AP in the new channel. Pass the already-parsed MCST (Maximum Channel Switch Time) element value to cfg80211_ch_switch_started_notify(). Pass mcst_tu=0 in the __ieee80211_channel_switch() call to cfg80211_ch_switch_started_notify() since the AP-initiated channel switch path does not carry a MCST element, as this element is only present in Beacon/Probe Response frames processed on the STA side via ieee80211_sta_process_chanswitch(). Signed-off-by: Chandru Gopi Signed-off-by: Shashikala Prabhu --- net/mac80211/cfg.c | 2 +- net/mac80211/mlme.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 3b58af59f7e4..70cb8e39a64f 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -4802,7 +4802,7 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, cfg80211_ch_switch_started_notify(sdata->dev, &link_data->csa.chanreq.oper, link_id, - params->count, params->block_tx); + params->count, params->block_tx, 0); if (changed) { ieee80211_link_info_change_notify(sdata, link_data, changed); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 9e92337bb6f9..507d7e81ddcd 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -3470,7 +3470,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_link_data *link, cfg80211_ch_switch_started_notify(sdata->dev, &csa_ie.chanreq.oper, link->link_id, csa_ie.count, - csa_ie.mode); + csa_ie.mode, csa_ie.max_switch_time); /* we may have to handle timeout for deactivated link in software */ now = ktime_get_boottime(); -- 2.34.1