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. Forward the already-parsed MCST (Maximum Channel Switch Time) element value to userspace via the NL80211_CMD_CH_SWITCH_STARTED_NOTIFY netlink command. Userspace can use this information to decide whether to remain connected or disconnect before the AP moves to the new channel. 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 --- include/net/cfg80211.h | 4 +++- net/mac80211/cfg.c | 2 +- net/mac80211/mlme.c | 2 +- net/wireless/nl80211.c | 12 ++++++++---- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index ddcf559430dd..c55b7f4ea48a 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -9979,6 +9979,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 @@ -9987,7 +9989,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/net/mac80211/cfg.c b/net/mac80211/cfg.c index 0b1291ff7a2c..0cb6d949665a 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -4768,7 +4768,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 5b02141b0cb2..76f3c3a8feba 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -3182,7 +3182,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(); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 14d41142cf79..a17e87e782e4 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -22271,7 +22271,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; @@ -22303,6 +22304,9 @@ 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 && + nla_put_u32(msg, NL80211_ATTR_MAX_CH_SWITCH_TIME, mcst_tu)) + goto nla_put_failure; } genlmsg_end(msg, hdr); @@ -22355,7 +22359,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); @@ -22402,7 +22406,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; @@ -22416,7 +22420,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