Search Linux Wireless

[PATCH] wifi: Add support for sending BSSMaxIdle in association request

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



When WNM is enabled, a station can send its preferred BSS maximum idle
period in the association request, add a new netlink attribute to get
this value from the supplicant and add BSS maximum idle IE in the
association request.

Tested using mac80211_hwsim with the corresponding WPA supplicant patch.

Signed-off-by: Chaitanya Tata <Chaitanya.Tata@xxxxxxxxxxxxx>
---
 include/net/cfg80211.h       |  2 ++
 include/uapi/linux/nl80211.h |  2 ++
 net/mac80211/ieee80211_i.h   |  4 ++++
 net/mac80211/mlme.c          |  4 ++++
 net/mac80211/util.c          | 11 +++++++++++
 net/wireless/nl80211.c       | 11 +++++++++++
 net/wireless/sme.c           |  1 +
 7 files changed, 35 insertions(+)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 9e04f69712b1..fe8a5149a1d5 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2961,6 +2961,7 @@ struct cfg80211_assoc_request {
 	struct cfg80211_assoc_link links[IEEE80211_MLD_MAX_NUM_LINKS];
 	const u8 *ap_mld_addr;
 	s8 link_id;
+	u16 bss_max_idle_period;
 };
 
 /**
@@ -3173,6 +3174,7 @@ struct cfg80211_connect_params {
 	size_t fils_erp_rrk_len;
 	bool want_1x;
 	struct ieee80211_edmg edmg;
+	u16 bss_max_idle_period;
 };
 
 /**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index c59fec406da5..b1608df96b83 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -3341,6 +3341,8 @@ enum nl80211_attrs {
 
 	NL80211_ATTR_EMA_RNR_ELEMS,
 
+	NL80211_ATTR_BSS_MAX_IDLE_PERIOD,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index a0a7839cb961..5d83e9bd30ea 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -436,6 +436,8 @@ struct ieee80211_mgd_assoc_data {
 	u8 fils_kek[FILS_MAX_KEK_LEN];
 	size_t fils_kek_len;
 
+	u16 bss_max_idle_period;
+
 	size_t ie_len;
 	u8 *ie_pos; /* used to fill ie[] with link[].elems */
 	u8 ie[];
@@ -2614,4 +2616,6 @@ ieee80211_eht_cap_ie_to_sta_eht_cap(struct ieee80211_sub_if_data *sdata,
 				    const struct ieee80211_eht_cap_elem *eht_cap_ie_elem,
 				    u8 eht_cap_len,
 				    struct link_sta_info *link_sta);
+
+u8 *ieee80211_add_bss_max_idle_ie(u8 *buf, u16 max_idle_period);
 #endif /* IEEE80211_I_H */
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index e13a0354c397..2d955b237014 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1203,6 +1203,8 @@ static size_t ieee80211_assoc_link_elems(struct ieee80211_sub_if_data *sdata,
 		ieee80211_add_s1g_capab_ie(sdata, &sband->s1g_cap, skb);
 	}
 
+	ieee80211_add_bss_max_idle_ie(skb_put(skb, 5), assoc_data->bss_max_idle_period);
+
 	if (iftd && iftd->vendor_elems.data && iftd->vendor_elems.len)
 		skb_put_data(skb, iftd->vendor_elems.data, iftd->vendor_elems.len);
 
@@ -7378,6 +7380,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
 					req->crypto.control_port_over_nl80211;
 	sdata->control_port_no_preauth = req->crypto.control_port_no_preauth;
 
+	assoc_data->bss_max_idle_period = req->bss_max_idle_period;
+
 	/* kick off associate process */
 	ifmgd->assoc_data = assoc_data;
 
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 1527d6aafc14..d0217fd50d50 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -5076,3 +5076,14 @@ void ieee80211_fragment_element(struct sk_buff *skb, u8 *len_pos)
 
 	*len_pos = elem_len;
 }
+
+u8 *ieee80211_add_bss_max_idle_ie(u8 *buf, u16 max_idle_period)
+{
+	*buf++ = WLAN_EID_BSS_MAX_IDLE_PERIOD;
+	*buf++ = 3;
+	*(u16 *)buf++ = cpu_to_le16(max_idle_period);
+	/* Protected keep alive not applicable in association request */
+	*buf++ = 0;
+
+	return buf;
+}
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index d95f8053020d..1e6c49096407 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -816,6 +816,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
 	[NL80211_ATTR_MAX_HW_TIMESTAMP_PEERS] = { .type = NLA_U16 },
 	[NL80211_ATTR_HW_TIMESTAMP_ENABLED] = { .type = NLA_FLAG },
 	[NL80211_ATTR_EMA_RNR_ELEMS] = { .type = NLA_NESTED },
+	[NL80211_ATTR_BSS_MAX_IDLE_PERIOD] = { .type = NLA_U16 },
 };
 
 /* policy for the key attributes */
@@ -11136,6 +11137,11 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
 		ap_addr = req.bss->bssid;
 	}
 
+	if (info->attrs[NL80211_ATTR_BSS_MAX_IDLE_PERIOD]) {
+		req.bss_max_idle_period =
+			nla_get_u16(info->attrs[NL80211_ATTR_BSS_MAX_IDLE_PERIOD]);
+	}
+
 	err = nl80211_crypto_settings(rdev, info, &req.crypto, 1);
 	if (!err) {
 		wdev_lock(dev->ieee80211_ptr);
@@ -11971,6 +11977,11 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
 	if (nla_get_flag(info->attrs[NL80211_ATTR_MLO_SUPPORT]))
 		connect.flags |= CONNECT_REQ_MLO_SUPPORT;
 
+	if (info->attrs[NL80211_ATTR_BSS_MAX_IDLE_PERIOD]) {
+		connect.bss_max_idle_period =
+			nla_get_u16(info->attrs[NL80211_ATTR_BSS_MAX_IDLE_PERIOD]);
+	}
+
 	wdev_lock(dev->ieee80211_ptr);
 
 	err = cfg80211_connect(rdev, dev, &connect, connkeys,
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 7bdeb8eea92d..3ab9adb3f1a4 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -200,6 +200,7 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev,
 		req.vht_capa = params->vht_capa;
 		req.vht_capa_mask = params->vht_capa_mask;
 		req.link_id = -1;
+		req.bss_max_idle_period = params->bss_max_idle_period;
 
 		req.bss = cfg80211_get_bss(&rdev->wiphy, params->channel,
 					   params->bssid,
-- 
2.34.1




[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Wireless Regulations]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux