[PATCH 00/21][SRU][OEM-OSP1-B] iwlwifi: mvm: support HE context cmd API change

classic Classic list List threaded Threaded
24 messages Options
12
Reply | Threaded
Open this post in threaded view
|

[PATCH 00/21][SRU][OEM-OSP1-B] iwlwifi: mvm: support HE context cmd API change

You-Sheng Yang
BugLink: https://bugs.launchpad.net/bugs/1845138

[Impact]
When trying to associate with an 802.11ax Wi-Fi AP on platforms with
Intel AX1650s/AX1650i, iwlwifi gives a firmware error about command in
SYN CMD STA_HE_CTXT_CMD and hardware resets.

[Fix]
AX1650s/AX1650i firmware expects passed command struct to include
multiple bssid support when associating with 802.11ax APs, and the
implementation has been landed to v5.2 as:

  commit d14ae796f849: iwlwifi: mvm: support HE context cmd API change

This commit, along with its prerequisites in kernel mac80211/cfg80211
framework are neccesary to complete 802.11ax AP associations.

[Test Case]
Tested on AX1650s/AX1650i, as well as 9462/9560, to associate with
AX/N/AC/BG open/wpa AP.

[Regression Risk]
Medium. These patches introduces new features to mac80211/cfg80211
framework but are only enabled when IEEE80211_HW_SUPPORTS_MULTI_BSSID
and/or IEEE80211_HW_SUPPORTS_ONLY_HE_MULTI_BSSID are set. There is also
refactoring to information element access for cfg80211.

For the firmware part, this should only be enabled when firmware blobs
has explicitly declared IWL_UCODE_TLV_API_MBSSID_HE capability. And when
this capability is set, like fw for AX1650s/AX1650i, changes here are
necessary to make an association to 802.11ax Wi-Fi AP successfully.

Johannes Berg (6):
  cfg80211: add and use strongly typed element iteration macros
  mac80211: use element iteration macro in parsing
  cfg80211: add various struct element finding helpers
  nl80211: use for_each_element() in validate_ie_attr()
  cfg80211: use for_each_element() for multi-bssid parsing
  cfg80211: add missing kernel-doc for multi-BSSID fields

Jouni Malinen (1):
  mac80211_hwsim: Declare support for Multi-BSSID

Peng Xu (1):
  cfg80211: Parsing of Multiple BSSID information in scanning

Sara Sharon (13):
  mac80211: pass bssids to elements parsing function
  mac80211: move the bss update from elements to an helper
  cfg80211: Properly track transmitting and non-transmitting BSS
  cfg80211: Move Multiple BSS info to struct cfg80211_bss to be visible
  cfg80211: parse multi-bssid only if HW supports it
  cfg80211: make BSSID generation function inline
  cfg80211: save multi-bssid properties
  mac80211: support multi-bssid
  mac80211: indicate support for multiple BSSID
  cfg80211: fix the IE inheritance of extension IEs
  cfg80211: fix memory leak of new_ie
  iwlwifi: mvm: support multiple BSSID
  iwlwifi: mvm: support HE context cmd API change

 .../net/wireless/intel/iwlwifi/fw/api/mac.h   |  77 ++-
 drivers/net/wireless/intel/iwlwifi/fw/file.h  |   3 +
 .../net/wireless/intel/iwlwifi/mvm/mac80211.c |  22 +-
 drivers/net/wireless/mac80211_hwsim.c         |   1 +
 include/linux/ieee80211.h                     |  92 ++-
 include/net/cfg80211.h                        | 179 +++++-
 include/net/mac80211.h                        |  22 +
 net/mac80211/debugfs.c                        |   4 +-
 net/mac80211/ibss.c                           |   8 +-
 net/mac80211/ieee80211_i.h                    |  20 +-
 net/mac80211/main.c                           |  13 +-
 net/mac80211/mesh.c                           |  10 +-
 net/mac80211/mesh_hwmp.c                      |   3 +-
 net/mac80211/mesh_plink.c                     |   4 +-
 net/mac80211/mlme.c                           | 185 ++++--
 net/mac80211/scan.c                           | 160 +++--
 net/mac80211/tdls.c                           |   6 +-
 net/mac80211/util.c                           | 133 +++-
 net/wireless/core.h                           |  13 +-
 net/wireless/nl80211.c                        |  28 +-
 net/wireless/scan.c                           | 595 ++++++++++++++++--
 net/wireless/util.c                           |   6 +-
 22 files changed, 1314 insertions(+), 270 deletions(-)

--
2.23.0


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[PATCH 01/21][SRU][OEM-OSP1-B] cfg80211: add and use strongly typed element iteration macros

You-Sheng Yang
From: Johannes Berg <[hidden email]>

BugLink: https://bugs.launchpad.net/bugs/1845138

Rather than always iterating elements from frames with pure
u8 pointers, add a type "struct element" that encapsulates
the id/datalen/data format of them.

Then, add the element iteration macros
 * for_each_element
 * for_each_element_id
 * for_each_element_extid

which take, as their first 'argument', such a structure and
iterate through a given u8 array interpreting it as elements.

While at it and since we'll need it, also add
 * for_each_subelement
 * for_each_subelement_id
 * for_each_subelement_extid

which instead of taking data/length just take an outer element
and use its data/datalen.

Also add for_each_element_completed() to determine if any of
the loops above completed, i.e. it was able to parse all of
the elements successfully and no data remained.

Use for_each_element_id() in cfg80211_find_ie_match() as the
first user of this.

Signed-off-by: Johannes Berg <[hidden email]>
(cherry picked from commit 0f3b07f027f87a38ebe5c436490095df762819be)
Signed-off-by: You-Sheng Yang <[hidden email]>
---
 include/linux/ieee80211.h | 53 +++++++++++++++++++++++++++++++++++++++
 net/wireless/scan.c       | 14 +++++------
 2 files changed, 59 insertions(+), 8 deletions(-)

diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 9f761e6bf5de9..f89f7d74325f1 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -3253,4 +3253,57 @@ static inline bool ieee80211_action_contains_tpc(struct sk_buff *skb)
  return true;
 }
 
+struct element {
+ u8 id;
+ u8 datalen;
+ u8 data[];
+};
+
+/* element iteration helpers */
+#define for_each_element(element, _data, _datalen) \
+ for (element = (void *)(_data); \
+     (u8 *)(_data) + (_datalen) - (u8 *)element >= \
+ sizeof(*element) && \
+     (u8 *)(_data) + (_datalen) - (u8 *)element >= \
+ sizeof(*element) + element->datalen; \
+     element = (void *)(element->data + element->datalen))
+
+#define for_each_element_id(element, _id, data, datalen) \
+ for_each_element(element, data, datalen) \
+ if (element->id == (_id))
+
+#define for_each_element_extid(element, extid, data, datalen) \
+ for_each_element(element, data, datalen) \
+ if (element->id == WLAN_EID_EXTENSION && \
+    element->datalen > 0 && \
+    element->data[0] == (extid))
+
+#define for_each_subelement(sub, element) \
+ for_each_element(sub, (element)->data, (element)->datalen)
+
+#define for_each_subelement_id(sub, id, element) \
+ for_each_element_id(sub, id, (element)->data, (element)->datalen)
+
+#define for_each_subelement_extid(sub, extid, element) \
+ for_each_element_extid(sub, extid, (element)->data, (element)->datalen)
+
+/**
+ * for_each_element_completed - determine if element parsing consumed all data
+ * @element: element pointer after for_each_element() or friends
+ * @data: same data pointer as passed to for_each_element() or friends
+ * @datalen: same data length as passed to for_each_element() or friends
+ *
+ * This function returns %true if all the data was parsed or considered
+ * while walking the elements. Only use this if your for_each_element()
+ * loop cannot be broken out of, otherwise it always returns %false.
+ *
+ * If some data was malformed, this returns %false since the last parsed
+ * element will not fill the whole remaining data.
+ */
+static inline bool for_each_element_completed(const struct element *element,
+      const void *data, size_t datalen)
+{
+ return (u8 *)element == (u8 *)data + datalen;
+}
+
 #endif /* LINUX_IEEE80211_H */
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 5123667f4569a..c7f64bb9c581a 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -484,6 +484,8 @@ const u8 *cfg80211_find_ie_match(u8 eid, const u8 *ies, int len,
  const u8 *match, int match_len,
  int match_offset)
 {
+ const struct element *elem;
+
  /* match_offset can't be smaller than 2, unless match_len is
  * zero, in which case match_offset must be zero as well.
  */
@@ -491,14 +493,10 @@ const u8 *cfg80211_find_ie_match(u8 eid, const u8 *ies, int len,
     (!match_len && match_offset)))
  return NULL;
 
- while (len >= 2 && len >= ies[1] + 2) {
- if ((ies[0] == eid) &&
-    (ies[1] + 2 >= match_offset + match_len) &&
-    !memcmp(ies + match_offset, match, match_len))
- return ies;
-
- len -= ies[1] + 2;
- ies += ies[1] + 2;
+ for_each_element_id(elem, eid, ies, len) {
+ if (elem->datalen >= match_offset - 2 + match_len &&
+    !memcmp(elem->data + match_offset - 2, match, match_len))
+ return (void *)elem;
  }
 
  return NULL;
--
2.23.0


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[PATCH 02/21][SRU][OEM-OSP1-B] mac80211: use element iteration macro in parsing

You-Sheng Yang
In reply to this post by You-Sheng Yang
From: Johannes Berg <[hidden email]>

BugLink: https://bugs.launchpad.net/bugs/1845138

Instead of open-coding the element walk, use the new macro.

Signed-off-by: Johannes Berg <[hidden email]>
(cherry picked from commit c17e28d1bcd357219264aaab37d5daba8181f9d3)
Signed-off-by: You-Sheng Yang <[hidden email]>
---
 net/mac80211/util.c | 25 ++++++-------------------
 1 file changed, 6 insertions(+), 19 deletions(-)

diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index fa59dda7feb0a..09392cf4f9559 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -895,8 +895,7 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
        struct ieee802_11_elems *elems,
        u64 filter, u32 crc)
 {
- size_t left = len;
- const u8 *pos = start;
+ struct element *elem;
  bool calc_crc = filter != 0;
  DECLARE_BITMAP(seen_elems, 256);
  const u8 *ie;
@@ -906,18 +905,11 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
  elems->ie_start = start;
  elems->total_len = len;
 
- while (left >= 2) {
- u8 id, elen;
+ for_each_element(elem, start, len) {
  bool elem_parse_failed;
-
- id = *pos++;
- elen = *pos++;
- left -= 2;
-
- if (elen > left) {
- elems->parse_error = true;
- break;
- }
+ u8 id = elem->id;
+ u8 elen = elem->datalen;
+ const u8 *pos = elem->data;
 
  switch (id) {
  case WLAN_EID_SSID:
@@ -960,8 +952,6 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
  */
  if (test_bit(id, seen_elems)) {
  elems->parse_error = true;
- left -= elen;
- pos += elen;
  continue;
  }
  break;
@@ -1244,12 +1234,9 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
  elems->parse_error = true;
  else
  __set_bit(id, seen_elems);
-
- left -= elen;
- pos += elen;
  }
 
- if (left != 0)
+ if (!for_each_element_completed(elem, start, len))
  elems->parse_error = true;
 
  return crc;
--
2.23.0


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[PATCH 03/21][SRU][OEM-OSP1-B] cfg80211: add various struct element finding helpers

You-Sheng Yang
In reply to this post by You-Sheng Yang
From: Johannes Berg <[hidden email]>

BugLink: https://bugs.launchpad.net/bugs/1845138

We currently have a number of helpers to find elements that just
return a u8 *, change those to return a struct element and add
inlines to deal with the u8 * compatibility.

Note that the match behaviour is changed to start the natch at
the data, so conversion from _ie_match to _elem_match need to
be done carefully.

Signed-off-by: Johannes Berg <[hidden email]>
(cherry picked from commit 49a68e0d88890060a2b9b6c6ad1ec53eb50abccf)
Signed-off-by: You-Sheng Yang <[hidden email]>
---
 include/net/cfg80211.h | 135 ++++++++++++++++++++++++++++++++++++++---
 net/wireless/scan.c    |  39 ++++++------
 net/wireless/util.c    |   6 +-
 3 files changed, 148 insertions(+), 32 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 68649a131cf87..16651a3f2a4b1 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2034,16 +2034,30 @@ struct cfg80211_bss {
  u8 priv[0] __aligned(sizeof(void *));
 };
 
+/**
+ * ieee80211_bss_get_elem - find element with given ID
+ * @bss: the bss to search
+ * @id: the element ID
+ *
+ * Note that the return value is an RCU-protected pointer, so
+ * rcu_read_lock() must be held when calling this function.
+ * Return: %NULL if not found.
+ */
+const struct element *ieee80211_bss_get_elem(struct cfg80211_bss *bss, u8 id);
+
 /**
  * ieee80211_bss_get_ie - find IE with given ID
  * @bss: the bss to search
- * @ie: the IE ID
+ * @id: the element ID
  *
  * Note that the return value is an RCU-protected pointer, so
  * rcu_read_lock() must be held when calling this function.
  * Return: %NULL if not found.
  */
-const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie);
+static inline const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 id)
+{
+ return (void *)ieee80211_bss_get_elem(bss, id);
+}
 
 
 /**
@@ -4951,6 +4965,33 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
 unsigned int cfg80211_classify8021d(struct sk_buff *skb,
     struct cfg80211_qos_map *qos_map);
 
+/**
+ * cfg80211_find_elem_match - match information element and byte array in data
+ *
+ * @eid: element ID
+ * @ies: data consisting of IEs
+ * @len: length of data
+ * @match: byte array to match
+ * @match_len: number of bytes in the match array
+ * @match_offset: offset in the IE data where the byte array should match.
+ * Note the difference to cfg80211_find_ie_match() which considers
+ * the offset to start from the element ID byte, but here we take
+ * the data portion instead.
+ *
+ * Return: %NULL if the element ID could not be found or if
+ * the element is invalid (claims to be longer than the given
+ * data) or if the byte array doesn't match; otherwise return the
+ * requested element struct.
+ *
+ * Note: There are no checks on the element length other than
+ * having to fit into the given data and being large enough for the
+ * byte array to match.
+ */
+const struct element *
+cfg80211_find_elem_match(u8 eid, const u8 *ies, unsigned int len,
+ const u8 *match, unsigned int match_len,
+ unsigned int match_offset);
+
 /**
  * cfg80211_find_ie_match - match information element and byte array in data
  *
@@ -4975,9 +5016,44 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb,
  * having to fit into the given data and being large enough for the
  * byte array to match.
  */
-const u8 *cfg80211_find_ie_match(u8 eid, const u8 *ies, int len,
- const u8 *match, int match_len,
- int match_offset);
+static inline const u8 *
+cfg80211_find_ie_match(u8 eid, const u8 *ies, unsigned int len,
+       const u8 *match, unsigned int match_len,
+       unsigned int match_offset)
+{
+ /* match_offset can't be smaller than 2, unless match_len is
+ * zero, in which case match_offset must be zero as well.
+ */
+ if (WARN_ON((match_len && match_offset < 2) ||
+    (!match_len && match_offset)))
+ return NULL;
+
+ return (void *)cfg80211_find_elem_match(eid, ies, len,
+ match, match_len,
+ match_offset ?
+ match_offset - 2 : 0);
+}
+
+/**
+ * cfg80211_find_elem - find information element in data
+ *
+ * @eid: element ID
+ * @ies: data consisting of IEs
+ * @len: length of data
+ *
+ * Return: %NULL if the element ID could not be found or if
+ * the element is invalid (claims to be longer than the given
+ * data) or if the byte array doesn't match; otherwise return the
+ * requested element struct.
+ *
+ * Note: There are no checks on the element length other than
+ * having to fit into the given data.
+ */
+static inline const struct element *
+cfg80211_find_elem(u8 eid, const u8 *ies, int len)
+{
+ return cfg80211_find_elem_match(eid, ies, len, NULL, 0, 0);
+}
 
 /**
  * cfg80211_find_ie - find information element in data
@@ -4999,6 +5075,28 @@ static inline const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len)
  return cfg80211_find_ie_match(eid, ies, len, NULL, 0, 0);
 }
 
+/**
+ * cfg80211_find_ext_elem - find information element with EID Extension in data
+ *
+ * @ext_eid: element ID Extension
+ * @ies: data consisting of IEs
+ * @len: length of data
+ *
+ * Return: %NULL if the etended element could not be found or if
+ * the element is invalid (claims to be longer than the given
+ * data) or if the byte array doesn't match; otherwise return the
+ * requested element struct.
+ *
+ * Note: There are no checks on the element length other than
+ * having to fit into the given data.
+ */
+static inline const struct element *
+cfg80211_find_ext_elem(u8 ext_eid, const u8 *ies, int len)
+{
+ return cfg80211_find_elem_match(WLAN_EID_EXTENSION, ies, len,
+ &ext_eid, 1, 0);
+}
+
 /**
  * cfg80211_find_ext_ie - find information element with EID Extension in data
  *
@@ -5020,6 +5118,25 @@ static inline const u8 *cfg80211_find_ext_ie(u8 ext_eid, const u8 *ies, int len)
       &ext_eid, 1, 2);
 }
 
+/**
+ * cfg80211_find_vendor_elem - find vendor specific information element in data
+ *
+ * @oui: vendor OUI
+ * @oui_type: vendor-specific OUI type (must be < 0xff), negative means any
+ * @ies: data consisting of IEs
+ * @len: length of data
+ *
+ * Return: %NULL if the vendor specific element ID could not be found or if the
+ * element is invalid (claims to be longer than the given data); otherwise
+ * return the element structure for the requested element.
+ *
+ * Note: There are no checks on the element length other than having to fit into
+ * the given data.
+ */
+const struct element *cfg80211_find_vendor_elem(unsigned int oui, int oui_type,
+ const u8 *ies,
+ unsigned int len);
+
 /**
  * cfg80211_find_vendor_ie - find vendor specific information element in data
  *
@@ -5036,8 +5153,12 @@ static inline const u8 *cfg80211_find_ext_ie(u8 ext_eid, const u8 *ies, int len)
  * Note: There are no checks on the element length other than having to fit into
  * the given data.
  */
-const u8 *cfg80211_find_vendor_ie(unsigned int oui, int oui_type,
-  const u8 *ies, int len);
+static inline const u8 *
+cfg80211_find_vendor_ie(unsigned int oui, int oui_type,
+ const u8 *ies, unsigned int len)
+{
+ return (void *)cfg80211_find_vendor_elem(oui, oui_type, ies, len);
+}
 
 /**
  * cfg80211_send_layer2_update - send layer 2 update frame
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index c7f64bb9c581a..d2c9ca5f4f573 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -480,48 +480,43 @@ void cfg80211_bss_expire(struct cfg80211_registered_device *rdev)
  __cfg80211_bss_expire(rdev, jiffies - IEEE80211_SCAN_RESULT_EXPIRE);
 }
 
-const u8 *cfg80211_find_ie_match(u8 eid, const u8 *ies, int len,
- const u8 *match, int match_len,
- int match_offset)
+const struct element *
+cfg80211_find_elem_match(u8 eid, const u8 *ies, unsigned int len,
+ const u8 *match, unsigned int match_len,
+ unsigned int match_offset)
 {
  const struct element *elem;
 
- /* match_offset can't be smaller than 2, unless match_len is
- * zero, in which case match_offset must be zero as well.
- */
- if (WARN_ON((match_len && match_offset < 2) ||
-    (!match_len && match_offset)))
- return NULL;
-
  for_each_element_id(elem, eid, ies, len) {
- if (elem->datalen >= match_offset - 2 + match_len &&
-    !memcmp(elem->data + match_offset - 2, match, match_len))
- return (void *)elem;
+ if (elem->datalen >= match_offset + match_len &&
+    !memcmp(elem->data + match_offset, match, match_len))
+ return elem;
  }
 
  return NULL;
 }
-EXPORT_SYMBOL(cfg80211_find_ie_match);
+EXPORT_SYMBOL(cfg80211_find_elem_match);
 
-const u8 *cfg80211_find_vendor_ie(unsigned int oui, int oui_type,
-  const u8 *ies, int len)
+const struct element *cfg80211_find_vendor_elem(unsigned int oui, int oui_type,
+ const u8 *ies,
+ unsigned int len)
 {
- const u8 *ie;
+ const struct element *elem;
  u8 match[] = { oui >> 16, oui >> 8, oui, oui_type };
  int match_len = (oui_type < 0) ? 3 : sizeof(match);
 
  if (WARN_ON(oui_type > 0xff))
  return NULL;
 
- ie = cfg80211_find_ie_match(WLAN_EID_VENDOR_SPECIFIC, ies, len,
-    match, match_len, 2);
+ elem = cfg80211_find_elem_match(WLAN_EID_VENDOR_SPECIFIC, ies, len,
+ match, match_len, 0);
 
- if (ie && (ie[1] < 4))
+ if (!elem || elem->datalen < 4)
  return NULL;
 
- return ie;
+ return elem;
 }
-EXPORT_SYMBOL(cfg80211_find_vendor_ie);
+EXPORT_SYMBOL(cfg80211_find_vendor_elem);
 
 static bool is_bss(struct cfg80211_bss *a, const u8 *bssid,
    const u8 *ssid, size_t ssid_len)
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 57c8832882df6..ad741d745982a 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -789,7 +789,7 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb,
 }
 EXPORT_SYMBOL(cfg80211_classify8021d);
 
-const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie)
+const struct element *ieee80211_bss_get_elem(struct cfg80211_bss *bss, u8 id)
 {
  const struct cfg80211_bss_ies *ies;
 
@@ -797,9 +797,9 @@ const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie)
  if (!ies)
  return NULL;
 
- return cfg80211_find_ie(ie, ies->data, ies->len);
+ return cfg80211_find_elem(id, ies->data, ies->len);
 }
-EXPORT_SYMBOL(ieee80211_bss_get_ie);
+EXPORT_SYMBOL(ieee80211_bss_get_elem);
 
 void cfg80211_upload_connect_keys(struct wireless_dev *wdev)
 {
--
2.23.0


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[PATCH 04/21][SRU][OEM-OSP1-B] nl80211: use for_each_element() in validate_ie_attr()

You-Sheng Yang
In reply to this post by You-Sheng Yang
From: Johannes Berg <[hidden email]>

BugLink: https://bugs.launchpad.net/bugs/1845138

This makes for much simpler code, simply walk through all
the elements and check that the last one found ends with
the end of the data. This works because if any element is
malformed the walk is aborted, we end up with a mismatch.

Signed-off-by: Johannes Berg <[hidden email]>
(cherry picked from commit 9f308616b6176b6dc470e6eb3569a09b100a823a)
Signed-off-by: You-Sheng Yang <[hidden email]>
---
 net/wireless/nl80211.c | 28 ++++++++--------------------
 1 file changed, 8 insertions(+), 20 deletions(-)

diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 58d669690fb20..12265faed00ec 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -203,29 +203,17 @@ cfg80211_get_dev_from_info(struct net *netns, struct genl_info *info)
 static int validate_ie_attr(const struct nlattr *attr,
     struct netlink_ext_ack *extack)
 {
- const u8 *pos;
- int len;
+ const u8 *data = nla_data(attr);
+ unsigned int len = nla_len(attr);
+ struct element *elem;
 
- pos = nla_data(attr);
- len = nla_len(attr);
-
- while (len) {
- u8 elemlen;
-
- if (len < 2)
- goto error;
- len -= 2;
-
- elemlen = pos[1];
- if (elemlen > len)
- goto error;
-
- len -= elemlen;
- pos += 2 + elemlen;
+ for_each_element(elem, data, len) {
+ /* nothing */
  }
 
- return 0;
-error:
+ if (for_each_element_completed(elem, data, len))
+ return 0;
+
  NL_SET_ERR_MSG_ATTR(extack, attr, "malformed information elements");
  return -EINVAL;
 }
--
2.23.0


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[PATCH 05/21][SRU][OEM-OSP1-B] mac80211: pass bssids to elements parsing function

You-Sheng Yang
In reply to this post by You-Sheng Yang
From: Sara Sharon <[hidden email]>

BugLink: https://bugs.launchpad.net/bugs/1845138

In multiple BSSID, we have nested IEs inside the multiple
BSSID IE, that override the external ones for that specific
BSS. As preparation for supporting that, pass 2 BSSIDs to the
parse function, the transmitter, and the selected BSSID, so
it can know which IEs to choose. If the selected BSSID is
NULL, the outer ones will be applied.

Change ieee80211_bss_info_update to parse elements itself,
instead of receiving them parsed, so we have the relevant
bss entry in hand.

Signed-off-by: Sara Sharon <[hidden email]>
Signed-off-by: Johannes Berg <[hidden email]>
(cherry picked from commit 4abb52a46e7336c1e568a53761c8b7a81bbaaeaf)
Signed-off-by: You-Sheng Yang <[hidden email]>
---
 net/mac80211/ibss.c        |  8 ++--
 net/mac80211/ieee80211_i.h | 13 ++++---
 net/mac80211/mesh.c        | 10 +++--
 net/mac80211/mesh_hwmp.c   |  3 +-
 net/mac80211/mesh_plink.c  |  4 +-
 net/mac80211/mlme.c        | 45 +++++++++++++----------
 net/mac80211/scan.c        | 75 ++++++++++++++++++++------------------
 net/mac80211/tdls.c        |  6 ++-
 net/mac80211/util.c        |  3 +-
 9 files changed, 95 insertions(+), 72 deletions(-)

diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 0d704e8d7078c..4e4507115cf30 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -8,6 +8,7 @@
  * Copyright 2009, Johannes Berg <[hidden email]>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
  * Copyright(c) 2016 Intel Deutschland GmbH
+ * Copyright(c) 2018-2019 Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -1124,8 +1125,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
 
  ieee80211_update_sta_info(sdata, mgmt, len, rx_status, elems, channel);
 
- bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems,
- channel);
+ bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, channel);
  if (!bss)
  return;
 
@@ -1604,7 +1604,7 @@ void ieee80211_rx_mgmt_probe_beacon(struct ieee80211_sub_if_data *sdata,
  return;
 
  ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen,
-       false, &elems);
+       false, &elems, mgmt->bssid, NULL);
 
  ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems);
 }
@@ -1654,7 +1654,7 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
 
  ieee802_11_parse_elems(
  mgmt->u.action.u.chan_switch.variable,
- ies_len, true, &elems);
+ ies_len, true, &elems, mgmt->bssid, NULL);
 
  if (elems.parse_error)
  break;
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index ad827cad052fe..797f48c3f0257 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -4,7 +4,7 @@
  * Copyright 2006-2007 Jiri Benc <[hidden email]>
  * Copyright 2007-2010 Johannes Berg <[hidden email]>
  * Copyright 2013-2015  Intel Mobile Communications GmbH
- * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018-2019 Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -1661,7 +1661,6 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
   struct ieee80211_rx_status *rx_status,
   struct ieee80211_mgmt *mgmt,
   size_t len,
-  struct ieee802_11_elems *elems,
   struct ieee80211_channel *channel);
 void ieee80211_rx_bss_put(struct ieee80211_local *local,
   struct ieee80211_bss *bss);
@@ -1945,12 +1944,16 @@ static inline void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata,
 
 u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
        struct ieee802_11_elems *elems,
-       u64 filter, u32 crc);
+       u64 filter, u32 crc, u8 *transmitter_bssid,
+       u8 *bss_bssid);
 static inline void ieee802_11_parse_elems(const u8 *start, size_t len,
   bool action,
-  struct ieee802_11_elems *elems)
+  struct ieee802_11_elems *elems,
+  u8 *transmitter_bssid,
+  u8 *bss_bssid)
 {
- ieee802_11_parse_elems_crc(start, len, action, elems, 0, 0);
+ ieee802_11_parse_elems_crc(start, len, action, elems, 0, 0,
+   transmitter_bssid, bss_bssid);
 }
 
 
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index a3faae4b91b8d..fe44f0d98de02 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2008, 2009 open80211s Ltd.
- * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018 - 2019 Intel Corporation
  * Authors:    Luis Carlos Cobo <[hidden email]>
  *       Javier Cardona <[hidden email]>
  *
@@ -1107,7 +1107,8 @@ ieee80211_mesh_rx_probe_req(struct ieee80211_sub_if_data *sdata,
  if (baselen > len)
  return;
 
- ieee802_11_parse_elems(pos, len - baselen, false, &elems);
+ ieee802_11_parse_elems(pos, len - baselen, false, &elems, mgmt->bssid,
+       NULL);
 
  if (!elems.mesh_id)
  return;
@@ -1171,7 +1172,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
  return;
 
  ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen,
-       false, &elems);
+       false, &elems, mgmt->bssid, NULL);
 
  /* ignore non-mesh or secure / unsecure mismatch */
  if ((!elems.mesh_id || !elems.mesh_config) ||
@@ -1310,7 +1311,8 @@ static void mesh_rx_csa_frame(struct ieee80211_sub_if_data *sdata,
  pos = mgmt->u.action.u.chan_switch.variable;
  baselen = offsetof(struct ieee80211_mgmt,
    u.action.u.chan_switch.variable);
- ieee802_11_parse_elems(pos, len - baselen, true, &elems);
+ ieee802_11_parse_elems(pos, len - baselen, true, &elems,
+       mgmt->bssid, NULL);
 
  ifmsh->chsw_ttl = elems.mesh_chansw_params_ie->mesh_ttl;
  if (!--ifmsh->chsw_ttl)
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index 6950cd0bf5940..28c5cdd8ed0aa 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2008, 2009 open80211s Ltd.
+ * Copyright (C) 2019 Intel Corporation
  * Author:     Luis Carlos Cobo <[hidden email]>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -909,7 +910,7 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
 
  baselen = (u8 *) mgmt->u.action.u.mesh_action.variable - (u8 *) mgmt;
  ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable,
-       len - baselen, false, &elems);
+       len - baselen, false, &elems, mgmt->bssid, NULL);
 
  if (elems.preq) {
  if (elems.preq_len != 37)
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 33055c8ed37ec..8afd0ece94c93 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2008, 2009 open80211s Ltd.
+ * Copyright (C) 2019 Intel Corporation
  * Author:     Luis Carlos Cobo <[hidden email]>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -1214,6 +1215,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata,
  if (baselen > len)
  return;
  }
- ieee802_11_parse_elems(baseaddr, len - baselen, true, &elems);
+ ieee802_11_parse_elems(baseaddr, len - baselen, true, &elems,
+       mgmt->bssid, NULL);
  mesh_process_plink_frame(sdata, mgmt, &elems, rx_status);
 }
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 06db6f7f4a2c2..6bd1de8871fa1 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -2769,7 +2769,8 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
  u32 tx_flags = 0;
 
  pos = mgmt->u.auth.variable;
- ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), false, &elems);
+ ieee802_11_parse_elems(pos, len - (pos - (u8 *)mgmt), false, &elems,
+       mgmt->bssid, auth_data->bss->bssid);
  if (!elems.challenge)
  return;
  auth_data->expected_transaction = 4;
@@ -3147,7 +3148,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
  }
 
  pos = mgmt->u.assoc_resp.variable;
- ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), false, &elems);
+ ieee802_11_parse_elems(pos, len - (pos - (u8 *)mgmt), false, &elems,
+       mgmt->bssid, assoc_data->bss->bssid);
 
  if (!elems.supp_rates) {
  sdata_info(sdata, "no SuppRates element in AssocResp\n");
@@ -3184,7 +3186,9 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
  return false;
 
  ieee802_11_parse_elems(bss_ies->data, bss_ies->len,
-       false, &bss_elems);
+       false, &bss_elems,
+       mgmt->bssid,
+       assoc_data->bss->bssid);
  if (assoc_data->wmm &&
     !elems.wmm_param && bss_elems.wmm_param) {
  elems.wmm_param = bss_elems.wmm_param;
@@ -3481,7 +3485,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
  return;
 
  pos = mgmt->u.assoc_resp.variable;
- ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), false, &elems);
+ ieee802_11_parse_elems(pos, len - (pos - (u8 *)mgmt), false, &elems,
+       mgmt->bssid, assoc_data->bss->bssid);
 
  if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY &&
     elems.timeout_int &&
@@ -3538,8 +3543,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
 
 static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
   struct ieee80211_mgmt *mgmt, size_t len,
-  struct ieee80211_rx_status *rx_status,
-  struct ieee802_11_elems *elems)
+  struct ieee80211_rx_status *rx_status)
 {
  struct ieee80211_local *local = sdata->local;
  struct ieee80211_bss *bss;
@@ -3551,8 +3555,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
  if (!channel)
  return;
 
- bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems,
- channel);
+ bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, channel);
  if (bss) {
  sdata->vif.bss_conf.beacon_rate = bss->beacon_rate;
  ieee80211_rx_bss_put(local, bss);
@@ -3567,7 +3570,6 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
  struct ieee80211_if_managed *ifmgd;
  struct ieee80211_rx_status *rx_status = (void *) skb->cb;
  size_t baselen, len = skb->len;
- struct ieee802_11_elems elems;
 
  ifmgd = &sdata->u.mgd;
 
@@ -3580,10 +3582,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
  if (baselen > len)
  return;
 
- ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen,
-       false, &elems);
-
- ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems);
+ ieee80211_rx_bss_info(sdata, mgmt, len, rx_status);
 
  if (ifmgd->associated &&
     ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid))
@@ -3753,9 +3752,11 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
  if (ifmgd->assoc_data && ifmgd->assoc_data->need_beacon &&
     ether_addr_equal(mgmt->bssid, ifmgd->assoc_data->bss->bssid)) {
  ieee802_11_parse_elems(mgmt->u.beacon.variable,
-       len - baselen, false, &elems);
+       len - baselen, false, &elems,
+       mgmt->bssid,
+       ifmgd->assoc_data->bss->bssid);
 
- ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems);
+ ieee80211_rx_bss_info(sdata, mgmt, len, rx_status);
  if (elems.tim && !elems.parse_error) {
  const struct ieee80211_tim_ie *tim_ie = elems.tim;
  ifmgd->dtim_period = tim_ie->dtim_period;
@@ -3804,7 +3805,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
  ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4);
  ncrc = ieee802_11_parse_elems_crc(mgmt->u.beacon.variable,
   len - baselen, false, &elems,
-  care_about_ies, ncrc);
+  care_about_ies, ncrc,
+  mgmt->bssid, bssid);
 
  if (ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK) &&
     ieee80211_check_tim(elems.tim, elems.tim_len, ifmgd->aid)) {
@@ -3888,7 +3890,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
  ifmgd->beacon_crc = ncrc;
  ifmgd->beacon_crc_valid = true;
 
- ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems);
+ ieee80211_rx_bss_info(sdata, mgmt, len, rx_status);
 
  ieee80211_sta_process_chanswitch(sdata, rx_status->mactime,
  rx_status->device_timestamp,
@@ -4009,9 +4011,10 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
  if (ies_len < 0)
  break;
 
+ /* CSA IE cannot be overridden, no need for BSSID */
  ieee802_11_parse_elems(
  mgmt->u.action.u.chan_switch.variable,
- ies_len, true, &elems);
+ ies_len, true, &elems, mgmt->bssid, NULL);
 
  if (elems.parse_error)
  break;
@@ -4028,9 +4031,13 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
  if (ies_len < 0)
  break;
 
+ /*
+ * extended CSA IE can't be overridden, no need for
+ * BSSID
+ */
  ieee802_11_parse_elems(
  mgmt->u.action.u.ext_chan_switch.variable,
- ies_len, true, &elems);
+ ies_len, true, &elems, mgmt->bssid, NULL);
 
  if (elems.parse_error)
  break;
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 95413413f98c9..b58f75da9c844 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -8,6 +8,7 @@
  * Copyright 2007, Michael Wu <[hidden email]>
  * Copyright 2013-2015  Intel Mobile Communications GmbH
  * Copyright 2016-2017  Intel Deutschland GmbH
+ * Copyright (C) 2018-2019 Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -61,7 +62,6 @@ struct ieee80211_bss *
 ieee80211_bss_info_update(struct ieee80211_local *local,
   struct ieee80211_rx_status *rx_status,
   struct ieee80211_mgmt *mgmt, size_t len,
-  struct ieee802_11_elems *elems,
   struct ieee80211_channel *channel)
 {
  bool beacon = ieee80211_is_beacon(mgmt->frame_control);
@@ -73,6 +73,9 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
  };
  bool signal_valid;
  struct ieee80211_sub_if_data *scan_sdata;
+ struct ieee802_11_elems elems;
+ size_t baselen;
+ u8 *elements;
 
  if (rx_status->flag & RX_FLAG_NO_SIGNAL_VAL)
  bss_meta.signal = 0; /* invalid signal indication */
@@ -106,6 +109,22 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
       mgmt, len, GFP_ATOMIC);
  if (!cbss)
  return NULL;
+
+ if (ieee80211_is_probe_resp(mgmt->frame_control)) {
+ elements = mgmt->u.probe_resp.variable;
+ baselen = offsetof(struct ieee80211_mgmt,
+   u.probe_resp.variable);
+ } else {
+ baselen = offsetof(struct ieee80211_mgmt, u.beacon.variable);
+ elements = mgmt->u.beacon.variable;
+ }
+
+ if (baselen > len)
+ return NULL;
+
+ ieee802_11_parse_elems(elements, len - baselen, false, &elems,
+       mgmt->bssid, cbss->bssid);
+
  /* In case the signal is invalid update the status */
  signal_valid = abs(channel->center_freq - cbss->channel->center_freq)
  <= local->hw.wiphy->max_adj_channel_rssi_comp;
@@ -119,7 +138,7 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
  else
  bss->device_ts_presp = rx_status->device_timestamp;
 
- if (elems->parse_error) {
+ if (elems.parse_error) {
  if (beacon)
  bss->corrupt_data |= IEEE80211_BSS_CORRUPT_BEACON;
  else
@@ -132,45 +151,45 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
  }
 
  /* save the ERP value so that it is available at association time */
- if (elems->erp_info && (!elems->parse_error ||
- !(bss->valid_data & IEEE80211_BSS_VALID_ERP))) {
- bss->erp_value = elems->erp_info[0];
+ if (elems.erp_info && (!elems.parse_error ||
+       !(bss->valid_data & IEEE80211_BSS_VALID_ERP))) {
+ bss->erp_value = elems.erp_info[0];
  bss->has_erp_value = true;
- if (!elems->parse_error)
+ if (!elems.parse_error)
  bss->valid_data |= IEEE80211_BSS_VALID_ERP;
  }
 
  /* replace old supported rates if we get new values */
- if (!elems->parse_error ||
+ if (!elems.parse_error ||
     !(bss->valid_data & IEEE80211_BSS_VALID_RATES)) {
  srlen = 0;
- if (elems->supp_rates) {
+ if (elems.supp_rates) {
  clen = IEEE80211_MAX_SUPP_RATES;
- if (clen > elems->supp_rates_len)
- clen = elems->supp_rates_len;
- memcpy(bss->supp_rates, elems->supp_rates, clen);
+ if (clen > elems.supp_rates_len)
+ clen = elems.supp_rates_len;
+ memcpy(bss->supp_rates, elems.supp_rates, clen);
  srlen += clen;
  }
- if (elems->ext_supp_rates) {
+ if (elems.ext_supp_rates) {
  clen = IEEE80211_MAX_SUPP_RATES - srlen;
- if (clen > elems->ext_supp_rates_len)
- clen = elems->ext_supp_rates_len;
- memcpy(bss->supp_rates + srlen, elems->ext_supp_rates,
+ if (clen > elems.ext_supp_rates_len)
+ clen = elems.ext_supp_rates_len;
+ memcpy(bss->supp_rates + srlen, elems.ext_supp_rates,
        clen);
  srlen += clen;
  }
  if (srlen) {
  bss->supp_rates_len = srlen;
- if (!elems->parse_error)
+ if (!elems.parse_error)
  bss->valid_data |= IEEE80211_BSS_VALID_RATES;
  }
  }
 
- if (!elems->parse_error ||
+ if (!elems.parse_error ||
     !(bss->valid_data & IEEE80211_BSS_VALID_WMM)) {
- bss->wmm_used = elems->wmm_param || elems->wmm_info;
- bss->uapsd_supported = is_uapsd_supported(elems);
- if (!elems->parse_error)
+ bss->wmm_used = elems.wmm_param || elems.wmm_info;
+ bss->uapsd_supported = is_uapsd_supported(&elems);
+ if (!elems.parse_error)
  bss->valid_data |= IEEE80211_BSS_VALID_WMM;
  }
 
@@ -206,10 +225,7 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb)
  struct ieee80211_sub_if_data *sdata1, *sdata2;
  struct ieee80211_mgmt *mgmt = (void *)skb->data;
  struct ieee80211_bss *bss;
- u8 *elements;
  struct ieee80211_channel *channel;
- size_t baselen;
- struct ieee802_11_elems elems;
 
  if (skb->len < 24 ||
     (!ieee80211_is_probe_resp(mgmt->frame_control) &&
@@ -244,26 +260,15 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb)
     !ieee80211_scan_accept_presp(sdata2, sched_scan_req_flags,
  mgmt->da))
  return;
-
- elements = mgmt->u.probe_resp.variable;
- baselen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
- } else {
- baselen = offsetof(struct ieee80211_mgmt, u.beacon.variable);
- elements = mgmt->u.beacon.variable;
  }
 
- if (baselen > skb->len)
- return;
-
- ieee802_11_parse_elems(elements, skb->len - baselen, false, &elems);
-
  channel = ieee80211_get_channel(local->hw.wiphy, rx_status->freq);
 
  if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
  return;
 
  bss = ieee80211_bss_info_update(local, rx_status,
- mgmt, skb->len, &elems,
+ mgmt, skb->len,
  channel);
  if (bss)
  ieee80211_rx_bss_put(local, bss);
diff --git a/net/mac80211/tdls.c b/net/mac80211/tdls.c
index 67745d1d4c5d1..fcc5cd49c3ac2 100644
--- a/net/mac80211/tdls.c
+++ b/net/mac80211/tdls.c
@@ -5,6 +5,7 @@
  * Copyright 2014, Intel Corporation
  * Copyright 2014  Intel Mobile Communications GmbH
  * Copyright 2015 - 2016 Intel Deutschland GmbH
+ * Copyright (C) 2019 Intel Corporation
  *
  * This file is GPLv2 as found in COPYING.
  */
@@ -1716,7 +1717,8 @@ ieee80211_process_tdls_channel_switch_resp(struct ieee80211_sub_if_data *sdata,
  }
 
  ieee802_11_parse_elems(tf->u.chan_switch_resp.variable,
-       skb->len - baselen, false, &elems);
+       skb->len - baselen, false, &elems,
+       NULL, NULL);
  if (elems.parse_error) {
  tdls_dbg(sdata, "Invalid IEs in TDLS channel switch resp\n");
  ret = -EINVAL;
@@ -1828,7 +1830,7 @@ ieee80211_process_tdls_channel_switch_req(struct ieee80211_sub_if_data *sdata,
  }
 
  ieee802_11_parse_elems(tf->u.chan_switch_req.variable,
-       skb->len - baselen, false, &elems);
+       skb->len - baselen, false, &elems, NULL, NULL);
  if (elems.parse_error) {
  tdls_dbg(sdata, "Invalid IEs in TDLS channel switch req\n");
  return -EINVAL;
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 09392cf4f9559..0877dda03b142 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -893,7 +893,8 @@ EXPORT_SYMBOL(ieee80211_queue_delayed_work);
 
 u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
        struct ieee802_11_elems *elems,
-       u64 filter, u32 crc)
+       u64 filter, u32 crc, u8 *transmitter_bssid,
+       u8 *bss_bssid)
 {
  struct element *elem;
  bool calc_crc = filter != 0;
--
2.23.0


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[PATCH 06/21][SRU][OEM-OSP1-B] mac80211: move the bss update from elements to an helper

You-Sheng Yang
In reply to this post by You-Sheng Yang
From: Sara Sharon <[hidden email]>

BugLink: https://bugs.launchpad.net/bugs/1845138

This will allow iterating over multiple BSSs inside
cfg80211_bss, in case of multiple BSSID.

Signed-off-by: Sara Sharon <[hidden email]>
Signed-off-by: Johannes Berg <[hidden email]>
(cherry picked from commit fcea7db50467e72338beb262fe6342ed01643399)
Signed-off-by: You-Sheng Yang <[hidden email]>
---
 net/mac80211/scan.c | 150 +++++++++++++++++++++++---------------------
 1 file changed, 80 insertions(+), 70 deletions(-)

diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index b58f75da9c844..20211cbc63f4f 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -58,6 +58,85 @@ static bool is_uapsd_supported(struct ieee802_11_elems *elems)
  return qos_info & IEEE80211_WMM_IE_AP_QOSINFO_UAPSD;
 }
 
+static void
+ieee80211_update_bss_from_elems(struct ieee80211_local *local,
+ struct ieee80211_bss *bss,
+ struct ieee802_11_elems *elems,
+ struct ieee80211_rx_status *rx_status,
+ bool beacon)
+{
+ int clen, srlen;
+
+ if (beacon)
+ bss->device_ts_beacon = rx_status->device_timestamp;
+ else
+ bss->device_ts_presp = rx_status->device_timestamp;
+
+ if (elems->parse_error) {
+ if (beacon)
+ bss->corrupt_data |= IEEE80211_BSS_CORRUPT_BEACON;
+ else
+ bss->corrupt_data |= IEEE80211_BSS_CORRUPT_PROBE_RESP;
+ } else {
+ if (beacon)
+ bss->corrupt_data &= ~IEEE80211_BSS_CORRUPT_BEACON;
+ else
+ bss->corrupt_data &= ~IEEE80211_BSS_CORRUPT_PROBE_RESP;
+ }
+
+ /* save the ERP value so that it is available at association time */
+ if (elems->erp_info && (!elems->parse_error ||
+ !(bss->valid_data & IEEE80211_BSS_VALID_ERP))) {
+ bss->erp_value = elems->erp_info[0];
+ bss->has_erp_value = true;
+ if (!elems->parse_error)
+ bss->valid_data |= IEEE80211_BSS_VALID_ERP;
+ }
+
+ /* replace old supported rates if we get new values */
+ if (!elems->parse_error ||
+    !(bss->valid_data & IEEE80211_BSS_VALID_RATES)) {
+ srlen = 0;
+ if (elems->supp_rates) {
+ clen = IEEE80211_MAX_SUPP_RATES;
+ if (clen > elems->supp_rates_len)
+ clen = elems->supp_rates_len;
+ memcpy(bss->supp_rates, elems->supp_rates, clen);
+ srlen += clen;
+ }
+ if (elems->ext_supp_rates) {
+ clen = IEEE80211_MAX_SUPP_RATES - srlen;
+ if (clen > elems->ext_supp_rates_len)
+ clen = elems->ext_supp_rates_len;
+ memcpy(bss->supp_rates + srlen, elems->ext_supp_rates,
+       clen);
+ srlen += clen;
+ }
+ if (srlen) {
+ bss->supp_rates_len = srlen;
+ if (!elems->parse_error)
+ bss->valid_data |= IEEE80211_BSS_VALID_RATES;
+ }
+ }
+
+ if (!elems->parse_error ||
+    !(bss->valid_data & IEEE80211_BSS_VALID_WMM)) {
+ bss->wmm_used = elems->wmm_param || elems->wmm_info;
+ bss->uapsd_supported = is_uapsd_supported(elems);
+ if (!elems->parse_error)
+ bss->valid_data |= IEEE80211_BSS_VALID_WMM;
+ }
+
+ if (beacon) {
+ struct ieee80211_supported_band *sband =
+ local->hw.wiphy->bands[rx_status->band];
+ if (!(rx_status->encoding == RX_ENC_HT) &&
+    !(rx_status->encoding == RX_ENC_VHT))
+ bss->beacon_rate =
+ &sband->bitrates[rx_status->rate_idx];
+ }
+}
+
 struct ieee80211_bss *
 ieee80211_bss_info_update(struct ieee80211_local *local,
   struct ieee80211_rx_status *rx_status,
@@ -67,7 +146,6 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
  bool beacon = ieee80211_is_beacon(mgmt->frame_control);
  struct cfg80211_bss *cbss;
  struct ieee80211_bss *bss;
- int clen, srlen;
  struct cfg80211_inform_bss bss_meta = {
  .boottime_ns = rx_status->boottime_ns,
  };
@@ -132,75 +210,7 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
  rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
 
  bss = (void *)cbss->priv;
-
- if (beacon)
- bss->device_ts_beacon = rx_status->device_timestamp;
- else
- bss->device_ts_presp = rx_status->device_timestamp;
-
- if (elems.parse_error) {
- if (beacon)
- bss->corrupt_data |= IEEE80211_BSS_CORRUPT_BEACON;
- else
- bss->corrupt_data |= IEEE80211_BSS_CORRUPT_PROBE_RESP;
- } else {
- if (beacon)
- bss->corrupt_data &= ~IEEE80211_BSS_CORRUPT_BEACON;
- else
- bss->corrupt_data &= ~IEEE80211_BSS_CORRUPT_PROBE_RESP;
- }
-
- /* save the ERP value so that it is available at association time */
- if (elems.erp_info && (!elems.parse_error ||
-       !(bss->valid_data & IEEE80211_BSS_VALID_ERP))) {
- bss->erp_value = elems.erp_info[0];
- bss->has_erp_value = true;
- if (!elems.parse_error)
- bss->valid_data |= IEEE80211_BSS_VALID_ERP;
- }
-
- /* replace old supported rates if we get new values */
- if (!elems.parse_error ||
-    !(bss->valid_data & IEEE80211_BSS_VALID_RATES)) {
- srlen = 0;
- if (elems.supp_rates) {
- clen = IEEE80211_MAX_SUPP_RATES;
- if (clen > elems.supp_rates_len)
- clen = elems.supp_rates_len;
- memcpy(bss->supp_rates, elems.supp_rates, clen);
- srlen += clen;
- }
- if (elems.ext_supp_rates) {
- clen = IEEE80211_MAX_SUPP_RATES - srlen;
- if (clen > elems.ext_supp_rates_len)
- clen = elems.ext_supp_rates_len;
- memcpy(bss->supp_rates + srlen, elems.ext_supp_rates,
-       clen);
- srlen += clen;
- }
- if (srlen) {
- bss->supp_rates_len = srlen;
- if (!elems.parse_error)
- bss->valid_data |= IEEE80211_BSS_VALID_RATES;
- }
- }
-
- if (!elems.parse_error ||
-    !(bss->valid_data & IEEE80211_BSS_VALID_WMM)) {
- bss->wmm_used = elems.wmm_param || elems.wmm_info;
- bss->uapsd_supported = is_uapsd_supported(&elems);
- if (!elems.parse_error)
- bss->valid_data |= IEEE80211_BSS_VALID_WMM;
- }
-
- if (beacon) {
- struct ieee80211_supported_band *sband =
- local->hw.wiphy->bands[rx_status->band];
- if (!(rx_status->encoding == RX_ENC_HT) &&
-    !(rx_status->encoding == RX_ENC_VHT))
- bss->beacon_rate =
- &sband->bitrates[rx_status->rate_idx];
- }
+ ieee80211_update_bss_from_elems(local, bss, &elems, rx_status, beacon);
 
  return bss;
 }
--
2.23.0


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[PATCH 07/21][SRU][OEM-OSP1-B] cfg80211: Parsing of Multiple BSSID information in scanning

You-Sheng Yang
In reply to this post by You-Sheng Yang
From: Peng Xu <[hidden email]>

BugLink: https://bugs.launchpad.net/bugs/1845138

This extends cfg80211 BSS table processing to be able to parse Multiple
BSSID element from Beacon and Probe Response frames and to update the
BSS profiles in internal database for non-transmitted BSSs.

Signed-off-by: Peng Xu <[hidden email]>
Signed-off-by: Sara Sharon <[hidden email]>
Signed-off-by: Jouni Malinen <[hidden email]>
Signed-off-by: Johannes Berg <[hidden email]>
(cherry picked from commit 0b8fb8235be8be99a197e8d948fc0a2df8dc261a)
Signed-off-by: You-Sheng Yang <[hidden email]>
---
 net/wireless/core.h |   3 +-
 net/wireless/scan.c | 508 ++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 472 insertions(+), 39 deletions(-)

diff --git a/net/wireless/core.h b/net/wireless/core.h
index f6b40563dc633..353998d749321 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -3,7 +3,7 @@
  * Wireless configuration interface internals.
  *
  * Copyright 2006-2010 Johannes Berg <[hidden email]>
- * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018-2019 Intel Corporation
  */
 #ifndef __NET_WIRELESS_CORE_H
 #define __NET_WIRELESS_CORE_H
@@ -152,6 +152,7 @@ extern int cfg80211_rdev_list_generation;
 struct cfg80211_internal_bss {
  struct list_head list;
  struct list_head hidden_list;
+ struct list_head nontrans_list;
  struct rb_node rbn;
  u64 ts_boottime;
  unsigned long ts;
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index d2c9ca5f4f573..531c2e56413fd 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -5,6 +5,7 @@
  * Copyright 2008 Johannes Berg <[hidden email]>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
  * Copyright 2016 Intel Deutschland GmbH
+ * Copyright (C) 2018-2019 Intel Corporation
  */
 #include <linux/kernel.h>
 #include <linux/slab.h>
@@ -150,6 +151,7 @@ static bool __cfg80211_unlink_bss(struct cfg80211_registered_device *rdev,
  }
 
  list_del_init(&bss->list);
+ list_del_init(&bss->nontrans_list);
  rb_erase(&bss->rbn, &rdev->bss_tree);
  rdev->bss_entries--;
  WARN_ONCE((rdev->bss_entries == 0) ^ list_empty(&rdev->bss_list),
@@ -159,6 +161,172 @@ static bool __cfg80211_unlink_bss(struct cfg80211_registered_device *rdev,
  return true;
 }
 
+static void cfg80211_gen_new_bssid(const u8 *bssid, u8 max_bssid,
+   u8 mbssid_index, u8 *new_bssid_addr)
+{
+ u64 bssid_tmp, new_bssid = 0;
+ u64 lsb_n;
+
+ bssid_tmp = ether_addr_to_u64(bssid);
+
+ lsb_n = bssid_tmp & ((1 << max_bssid) - 1);
+ new_bssid = bssid_tmp;
+ new_bssid &= ~((1 << max_bssid) - 1);
+ new_bssid |= (lsb_n + mbssid_index) % (1 << max_bssid);
+
+ u64_to_ether_addr(new_bssid, new_bssid_addr);
+}
+
+static size_t cfg80211_gen_new_ie(const u8 *ie, size_t ielen,
+  const u8 *subelement, size_t subie_len,
+  u8 *new_ie, gfp_t gfp)
+{
+ u8 *pos, *tmp;
+ const u8 *tmp_old, *tmp_new;
+ u8 *sub_copy;
+
+ /* copy subelement as we need to change its content to
+ * mark an ie after it is processed.
+ */
+ sub_copy = kmalloc(subie_len, gfp);
+ if (!sub_copy)
+ return 0;
+ memcpy(sub_copy, subelement, subie_len);
+
+ pos = &new_ie[0];
+
+ /* set new ssid */
+ tmp_new = cfg80211_find_ie(WLAN_EID_SSID, sub_copy, subie_len);
+ if (tmp_new) {
+ memcpy(pos, tmp_new, tmp_new[1] + 2);
+ pos += (tmp_new[1] + 2);
+ }
+
+ /* go through IEs in ie (skip SSID) and subelement,
+ * merge them into new_ie
+ */
+ tmp_old = cfg80211_find_ie(WLAN_EID_SSID, ie, ielen);
+ tmp_old = (tmp_old) ? tmp_old + tmp_old[1] + 2 : ie;
+
+ while (tmp_old + tmp_old[1] + 2 - ie <= ielen) {
+ if (tmp_old[0] == 0) {
+ tmp_old++;
+ continue;
+ }
+
+ tmp = (u8 *)cfg80211_find_ie(tmp_old[0], sub_copy, subie_len);
+ if (!tmp) {
+ /* ie in old ie but not in subelement */
+ if (tmp_old[0] != WLAN_EID_MULTIPLE_BSSID) {
+ memcpy(pos, tmp_old, tmp_old[1] + 2);
+ pos += tmp_old[1] + 2;
+ }
+ } else {
+ /* ie in transmitting ie also in subelement,
+ * copy from subelement and flag the ie in subelement
+ * as copied (by setting eid field to 0xff). For
+ * vendor ie, compare OUI + type + subType to
+ * determine if they are the same ie.
+ */
+ if (tmp_old[0] == WLAN_EID_VENDOR_SPECIFIC) {
+ if (!memcmp(tmp_old + 2, tmp + 2, 5)) {
+ /* same vendor ie, copy from
+ * subelement
+ */
+ memcpy(pos, tmp, tmp[1] + 2);
+ pos += tmp[1] + 2;
+ tmp[0] = 0xff;
+ } else {
+ memcpy(pos, tmp_old, tmp_old[1] + 2);
+ pos += tmp_old[1] + 2;
+ }
+ } else {
+ /* copy ie from subelement into new ie */
+ memcpy(pos, tmp, tmp[1] + 2);
+ pos += tmp[1] + 2;
+ tmp[0] = 0xff;
+ }
+ }
+
+ if (tmp_old + tmp_old[1] + 2 - ie == ielen)
+ break;
+
+ tmp_old += tmp_old[1] + 2;
+ }
+
+ /* go through subelement again to check if there is any ie not
+ * copied to new ie, skip ssid, capability, bssid-index ie
+ */
+ tmp_new = sub_copy;
+ while (tmp_new + tmp_new[1] + 2 - sub_copy <= subie_len) {
+ if (!(tmp_new[0] == WLAN_EID_NON_TX_BSSID_CAP ||
+      tmp_new[0] == WLAN_EID_SSID ||
+      tmp_new[0] == WLAN_EID_MULTI_BSSID_IDX ||
+      tmp_new[0] == 0xff)) {
+ memcpy(pos, tmp_new, tmp_new[1] + 2);
+ pos += tmp_new[1] + 2;
+ }
+ if (tmp_new + tmp_new[1] + 2 - sub_copy == subie_len)
+ break;
+ tmp_new += tmp_new[1] + 2;
+ }
+
+ kfree(sub_copy);
+ return pos - new_ie;
+}
+
+static bool is_bss(struct cfg80211_bss *a, const u8 *bssid,
+   const u8 *ssid, size_t ssid_len)
+{
+ const struct cfg80211_bss_ies *ies;
+ const u8 *ssidie;
+
+ if (bssid && !ether_addr_equal(a->bssid, bssid))
+ return false;
+
+ if (!ssid)
+ return true;
+
+ ies = rcu_access_pointer(a->ies);
+ if (!ies)
+ return false;
+ ssidie = cfg80211_find_ie(WLAN_EID_SSID, ies->data, ies->len);
+ if (!ssidie)
+ return false;
+ if (ssidie[1] != ssid_len)
+ return false;
+ return memcmp(ssidie + 2, ssid, ssid_len) == 0;
+}
+
+static int
+cfg80211_add_nontrans_list(struct cfg80211_internal_bss *trans_bss,
+   struct cfg80211_internal_bss *nontrans_bss)
+{
+ const u8 *ssid;
+ size_t ssid_len;
+ struct cfg80211_internal_bss *bss = NULL;
+
+ rcu_read_lock();
+ ssid = ieee80211_bss_get_ie(&nontrans_bss->pub, WLAN_EID_SSID);
+ if (!ssid) {
+ rcu_read_unlock();
+ return -EINVAL;
+ }
+ ssid_len = ssid[1];
+ ssid = ssid + 2;
+ rcu_read_unlock();
+
+ /* check if nontrans_bss is in the list */
+ list_for_each_entry(bss, &trans_bss->nontrans_list, nontrans_list) {
+ if (is_bss(&bss->pub, nontrans_bss->pub.bssid, ssid, ssid_len))
+ return 0;
+ }
+
+ /* add to the list */
+ list_add_tail(&nontrans_bss->nontrans_list, &trans_bss->nontrans_list);
+ return 0;
+}
+
 static void __cfg80211_bss_expire(struct cfg80211_registered_device *rdev,
   unsigned long expire_time)
 {
@@ -518,29 +686,6 @@ const struct element *cfg80211_find_vendor_elem(unsigned int oui, int oui_type,
 }
 EXPORT_SYMBOL(cfg80211_find_vendor_elem);
 
-static bool is_bss(struct cfg80211_bss *a, const u8 *bssid,
-   const u8 *ssid, size_t ssid_len)
-{
- const struct cfg80211_bss_ies *ies;
- const u8 *ssidie;
-
- if (bssid && !ether_addr_equal(a->bssid, bssid))
- return false;
-
- if (!ssid)
- return true;
-
- ies = rcu_access_pointer(a->ies);
- if (!ies)
- return false;
- ssidie = cfg80211_find_ie(WLAN_EID_SSID, ies->data, ies->len);
- if (!ssidie)
- return false;
- if (ssidie[1] != ssid_len)
- return false;
- return memcmp(ssidie + 2, ssid, ssid_len) == 0;
-}
-
 /**
  * enum bss_compare_mode - BSS compare mode
  * @BSS_CMP_REGULAR: regular compare mode (for insertion and normal find)
@@ -1002,6 +1147,7 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev,
  memcpy(new, tmp, sizeof(*new));
  new->refcount = 1;
  INIT_LIST_HEAD(&new->hidden_list);
+ INIT_LIST_HEAD(&new->nontrans_list);
 
  if (rcu_access_pointer(tmp->pub.proberesp_ies)) {
  hidden = rb_find_bss(rdev, tmp, BSS_CMP_HIDE_ZLEN);
@@ -1123,17 +1269,19 @@ cfg80211_get_bss_channel(struct wiphy *wiphy, const u8 *ie, size_t ielen,
 }
 
 /* Returned bss is reference counted and must be cleaned up appropriately. */
-struct cfg80211_bss *
-cfg80211_inform_bss_data(struct wiphy *wiphy,
- struct cfg80211_inform_bss *data,
- enum cfg80211_bss_frame_type ftype,
- const u8 *bssid, u64 tsf, u16 capability,
- u16 beacon_interval, const u8 *ie, size_t ielen,
- gfp_t gfp)
+static struct cfg80211_bss *
+cfg80211_inform_single_bss_data(struct wiphy *wiphy,
+ struct cfg80211_inform_bss *data,
+ enum cfg80211_bss_frame_type ftype,
+ const u8 *bssid, u64 tsf, u16 capability,
+ u16 beacon_interval, const u8 *ie, size_t ielen,
+ struct cfg80211_bss *trans_bss,
+ gfp_t gfp)
 {
+ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
  struct cfg80211_bss_ies *ies;
  struct ieee80211_channel *channel;
- struct cfg80211_internal_bss tmp = {}, *res;
+ struct cfg80211_internal_bss tmp = {}, *res, *trans_internal;
  int bss_type;
  bool signal_valid;
 
@@ -1202,19 +1350,252 @@ cfg80211_inform_bss_data(struct wiphy *wiphy,
  regulatory_hint_found_beacon(wiphy, channel, gfp);
  }
 
+ if (trans_bss) {
+ /* this is a nontransmitting bss, we need to add it to
+ * transmitting bss' list if it is not there
+ */
+ trans_internal = container_of(trans_bss,
+      struct cfg80211_internal_bss,
+      pub);
+ if (cfg80211_add_nontrans_list(trans_internal, res)) {
+ if (__cfg80211_unlink_bss(rdev, res))
+ rdev->bss_generation++;
+ }
+ }
+
  trace_cfg80211_return_bss(&res->pub);
  /* cfg80211_bss_update gives us a referenced result */
  return &res->pub;
 }
-EXPORT_SYMBOL(cfg80211_inform_bss_data);
 
-/* cfg80211_inform_bss_width_frame helper */
+static void cfg80211_parse_mbssid_data(struct wiphy *wiphy,
+       struct cfg80211_inform_bss *data,
+       enum cfg80211_bss_frame_type ftype,
+       const u8 *bssid, u64 tsf,
+       u16 beacon_interval, const u8 *ie,
+       size_t ielen,
+       struct cfg80211_bss *trans_bss,
+       gfp_t gfp)
+{
+ const u8 *pos, *subelement, *mbssid_end_pos;
+ const u8 *tmp, *mbssid_index_ie;
+ size_t subie_len, new_ie_len;
+ u8 new_bssid[ETH_ALEN];
+ u8 *new_ie;
+ u16 capability;
+ struct cfg80211_bss *bss;
+
+ if (!trans_bss)
+ return;
+ if (!cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, ie, ielen))
+ return;
+
+ pos = ie;
+
+ new_ie = kmalloc(IEEE80211_MAX_DATA_LEN, gfp);
+ if (!new_ie)
+ return;
+
+ while (pos < ie + ielen + 2) {
+ tmp = cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, pos,
+       ielen - (pos - ie));
+ if (!tmp)
+ break;
+
+ mbssid_end_pos = tmp + tmp[1] + 2;
+ /* Skip Element ID, Len, MaxBSSID Indicator */
+ if (tmp[1] < 4)
+ break;
+ for (subelement = tmp + 3; subelement < mbssid_end_pos - 1;
+     subelement += 2 + subelement[1]) {
+ subie_len = subelement[1];
+ if (mbssid_end_pos - subelement < 2 + subie_len)
+ break;
+ if (subelement[0] != 0 || subelement[1] < 4) {
+ /* not a valid BSS profile */
+ continue;
+ }
+
+ if (subelement[2] != WLAN_EID_NON_TX_BSSID_CAP ||
+    subelement[3] != 2) {
+ /* The first element within the Nontransmitted
+ * BSSID Profile is not the Nontransmitted
+ * BSSID Capability element.
+ */
+ continue;
+ }
+
+ /* found a Nontransmitted BSSID Profile */
+ mbssid_index_ie = cfg80211_find_ie
+ (WLAN_EID_MULTI_BSSID_IDX,
+ subelement + 2, subie_len);
+ if (!mbssid_index_ie || mbssid_index_ie[1] < 1 ||
+    mbssid_index_ie[2] == 0) {
+ /* No valid Multiple BSSID-Index element */
+ continue;
+ }
+
+ cfg80211_gen_new_bssid(bssid, tmp[2],
+       mbssid_index_ie[2],
+       new_bssid);
+ memset(new_ie, 0, IEEE80211_MAX_DATA_LEN);
+ new_ie_len = cfg80211_gen_new_ie(ie, ielen,
+ subelement + 2,
+ subie_len, new_ie,
+ gfp);
+ if (!new_ie_len)
+ continue;
+
+ capability = le16_to_cpup((const __le16 *)
+  &subelement[4]);
+ bss = cfg80211_inform_single_bss_data(wiphy, data,
+      ftype,
+      new_bssid, tsf,
+      capability,
+      beacon_interval,
+      new_ie,
+      new_ie_len,
+      trans_bss, gfp);
+ if (!bss)
+ break;
+ cfg80211_put_bss(wiphy, bss);
+ }
+
+ pos = mbssid_end_pos;
+ }
+
+ kfree(new_ie);
+}
+
 struct cfg80211_bss *
-cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
-       struct cfg80211_inform_bss *data,
-       struct ieee80211_mgmt *mgmt, size_t len,
-       gfp_t gfp)
+cfg80211_inform_bss_data(struct wiphy *wiphy,
+ struct cfg80211_inform_bss *data,
+ enum cfg80211_bss_frame_type ftype,
+ const u8 *bssid, u64 tsf, u16 capability,
+ u16 beacon_interval, const u8 *ie, size_t ielen,
+ gfp_t gfp)
+{
+ struct cfg80211_bss *res;
+
+ res = cfg80211_inform_single_bss_data(wiphy, data, ftype, bssid, tsf,
+      capability, beacon_interval, ie,
+      ielen, NULL, gfp);
+ cfg80211_parse_mbssid_data(wiphy, data, ftype, bssid, tsf,
+   beacon_interval, ie, ielen, res, gfp);
+ return res;
+}
+EXPORT_SYMBOL(cfg80211_inform_bss_data);
 
+static void
+cfg80211_parse_mbssid_frame_data(struct wiphy *wiphy,
+ struct cfg80211_inform_bss *data,
+ struct ieee80211_mgmt *mgmt, size_t len,
+ struct cfg80211_bss *trans_bss,
+ gfp_t gfp)
+{
+ enum cfg80211_bss_frame_type ftype;
+ const u8 *ie = mgmt->u.probe_resp.variable;
+ size_t ielen = len - offsetof(struct ieee80211_mgmt,
+      u.probe_resp.variable);
+
+ ftype = ieee80211_is_beacon(mgmt->frame_control) ?
+ CFG80211_BSS_FTYPE_BEACON : CFG80211_BSS_FTYPE_PRESP;
+
+ cfg80211_parse_mbssid_data(wiphy, data, ftype, mgmt->bssid,
+   le64_to_cpu(mgmt->u.probe_resp.timestamp),
+   le16_to_cpu(mgmt->u.probe_resp.beacon_int),
+   ie, ielen, trans_bss, gfp);
+}
+
+static void
+cfg80211_update_notlisted_nontrans(struct wiphy *wiphy,
+   struct cfg80211_internal_bss *nontrans_bss,
+   struct ieee80211_mgmt *mgmt, size_t len,
+   gfp_t gfp)
+{
+ u8 *ie, *new_ie, *pos;
+ const u8 *nontrans_ssid, *trans_ssid, *mbssid;
+ size_t ielen = len - offsetof(struct ieee80211_mgmt,
+      u.probe_resp.variable);
+ size_t new_ie_len;
+ struct cfg80211_bss_ies *new_ies;
+ const struct cfg80211_bss_ies *old;
+ u8 cpy_len;
+
+ ie = mgmt->u.probe_resp.variable;
+
+ new_ie_len = ielen;
+ trans_ssid = cfg80211_find_ie(WLAN_EID_SSID, ie, ielen);
+ if (!trans_ssid)
+ return;
+ new_ie_len -= trans_ssid[1];
+ mbssid = cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, ie, ielen);
+ if (!mbssid)
+ return;
+ new_ie_len -= mbssid[1];
+ rcu_read_lock();
+ nontrans_ssid = ieee80211_bss_get_ie(&nontrans_bss->pub, WLAN_EID_SSID);
+ if (!nontrans_ssid) {
+ rcu_read_unlock();
+ return;
+ }
+ new_ie_len += nontrans_ssid[1];
+ rcu_read_unlock();
+
+ /* generate new ie for nontrans BSS
+ * 1. replace SSID with nontrans BSS' SSID
+ * 2. skip MBSSID IE
+ */
+ new_ie = kzalloc(new_ie_len, gfp);
+ if (!new_ie)
+ return;
+ new_ies = kzalloc(sizeof(*new_ies) + new_ie_len, gfp);
+ if (!new_ies) {
+ kfree(new_ie);
+ return;
+ }
+
+ pos = new_ie;
+
+ /* copy the nontransmitted SSID */
+ cpy_len = nontrans_ssid[1] + 2;
+ memcpy(pos, nontrans_ssid, cpy_len);
+ pos += cpy_len;
+ /* copy the IEs between SSID and MBSSID */
+ cpy_len = trans_ssid[1] + 2;
+ memcpy(pos, (trans_ssid + cpy_len), (mbssid - (trans_ssid + cpy_len)));
+ pos += (mbssid - (trans_ssid + cpy_len));
+ /* copy the IEs after MBSSID */
+ cpy_len = mbssid[1] + 2;
+ memcpy(pos, mbssid + cpy_len, ((ie + ielen) - (mbssid + cpy_len)));
+
+ /* update ie */
+ new_ies->len = new_ie_len;
+ new_ies->tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp);
+ new_ies->from_beacon = ieee80211_is_beacon(mgmt->frame_control);
+ memcpy(new_ies->data, new_ie, new_ie_len);
+ if (ieee80211_is_probe_resp(mgmt->frame_control)) {
+ old = rcu_access_pointer(nontrans_bss->pub.proberesp_ies);
+ rcu_assign_pointer(nontrans_bss->pub.proberesp_ies, new_ies);
+ rcu_assign_pointer(nontrans_bss->pub.ies, new_ies);
+ if (old)
+ kfree_rcu((struct cfg80211_bss_ies *)old, rcu_head);
+ } else {
+ old = rcu_access_pointer(nontrans_bss->pub.beacon_ies);
+ rcu_assign_pointer(nontrans_bss->pub.beacon_ies, new_ies);
+ rcu_assign_pointer(nontrans_bss->pub.ies, new_ies);
+ if (old)
+ kfree_rcu((struct cfg80211_bss_ies *)old, rcu_head);
+ }
+}
+
+/* cfg80211_inform_bss_width_frame helper */
+static struct cfg80211_bss *
+cfg80211_inform_single_bss_frame_data(struct wiphy *wiphy,
+      struct cfg80211_inform_bss *data,
+      struct ieee80211_mgmt *mgmt, size_t len,
+      struct cfg80211_bss *trans_bss,
+      gfp_t gfp)
 {
  struct cfg80211_internal_bss tmp = {}, *res;
  struct cfg80211_bss_ies *ies;
@@ -1293,6 +1674,50 @@ cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
  /* cfg80211_bss_update gives us a referenced result */
  return &res->pub;
 }
+
+struct cfg80211_bss *
+cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
+       struct cfg80211_inform_bss *data,
+       struct ieee80211_mgmt *mgmt, size_t len,
+       gfp_t gfp)
+{
+ struct cfg80211_bss *res;
+ struct cfg80211_internal_bss *trans_bss, *tmp_bss;
+ const u8 *ie = mgmt->u.probe_resp.variable;
+ const struct cfg80211_bss_ies *ies1, *ies2;
+ size_t ielen = len - offsetof(struct ieee80211_mgmt,
+      u.probe_resp.variable);
+
+ res = cfg80211_inform_single_bss_frame_data(wiphy, data, mgmt,
+    len, NULL, gfp);
+ if (!res || !cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, ie, ielen))
+ return res;
+
+ /* process each non-transmitting bss */
+ cfg80211_parse_mbssid_frame_data(wiphy, data, mgmt, len, res, gfp);
+
+ /* check if the res has other nontransmitting bss which is not
+ * in MBSSID IE
+ */
+ ies1 = rcu_access_pointer(res->ies);
+ trans_bss = container_of(res, struct cfg80211_internal_bss, pub);
+ if (!trans_bss)
+ return res;
+
+ /* go through nontrans_list, if the timestamp of the BSS is
+ * earlier than the timestamp of the transmitting BSS then
+ * update it
+ */
+ list_for_each_entry(tmp_bss, &trans_bss->nontrans_list,
+    nontrans_list) {
+ ies2 = rcu_access_pointer(tmp_bss->pub.ies);
+ if (ies2->tsf < ies1->tsf)
+ cfg80211_update_notlisted_nontrans(wiphy, tmp_bss,
+   mgmt, len, gfp);
+ }
+
+ return res;
+}
 EXPORT_SYMBOL(cfg80211_inform_bss_frame_data);
 
 void cfg80211_ref_bss(struct wiphy *wiphy, struct cfg80211_bss *pub)
@@ -1330,7 +1755,7 @@ EXPORT_SYMBOL(cfg80211_put_bss);
 void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub)
 {
  struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
- struct cfg80211_internal_bss *bss;
+ struct cfg80211_internal_bss *bss, *nontrans_bss, *tmp;
 
  if (WARN_ON(!pub))
  return;
@@ -1339,6 +1764,13 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub)
 
  spin_lock_bh(&rdev->bss_lock);
  if (!list_empty(&bss->list)) {
+ list_for_each_entry_safe(nontrans_bss, tmp,
+ &bss->nontrans_list,
+ nontrans_list) {
+ if (__cfg80211_unlink_bss(rdev, nontrans_bss))
+ rdev->bss_generation++;
+ }
+
  if (__cfg80211_unlink_bss(rdev, bss))
  rdev->bss_generation++;
  }
--
2.23.0


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[PATCH 08/21][SRU][OEM-OSP1-B] cfg80211: use for_each_element() for multi-bssid parsing

You-Sheng Yang
In reply to this post by You-Sheng Yang
From: Johannes Berg <[hidden email]>

BugLink: https://bugs.launchpad.net/bugs/1845138

Use the new for_each_element() helper here, we cannot use
for_each_subelement() since we have a fixed 1 byte before
the subelements start.

While at it, also fix le16_to_cpup() to be get_unaligned_le16()
since we don't know anything about alignment.

Signed-off-by: Johannes Berg <[hidden email]>
(cherry picked from commit 1c8745f3ec6f46f5fa99dbcdf92381144ae1b37f)
Signed-off-by: You-Sheng Yang <[hidden email]>
---
 net/wireless/scan.c | 47 +++++++++++++++------------------------------
 1 file changed, 15 insertions(+), 32 deletions(-)

diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 531c2e56413fd..54feb7741c26c 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -1377,9 +1377,9 @@ static void cfg80211_parse_mbssid_data(struct wiphy *wiphy,
        struct cfg80211_bss *trans_bss,
        gfp_t gfp)
 {
- const u8 *pos, *subelement, *mbssid_end_pos;
- const u8 *tmp, *mbssid_index_ie;
- size_t subie_len, new_ie_len;
+ const u8 *mbssid_index_ie;
+ const struct element *elem, *sub;
+ size_t new_ie_len;
  u8 new_bssid[ETH_ALEN];
  u8 *new_ie;
  u16 capability;
@@ -1390,34 +1390,21 @@ static void cfg80211_parse_mbssid_data(struct wiphy *wiphy,
  if (!cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, ie, ielen))
  return;
 
- pos = ie;
-
  new_ie = kmalloc(IEEE80211_MAX_DATA_LEN, gfp);
  if (!new_ie)
  return;
 
- while (pos < ie + ielen + 2) {
- tmp = cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, pos,
-       ielen - (pos - ie));
- if (!tmp)
- break;
-
- mbssid_end_pos = tmp + tmp[1] + 2;
- /* Skip Element ID, Len, MaxBSSID Indicator */
- if (tmp[1] < 4)
- break;
- for (subelement = tmp + 3; subelement < mbssid_end_pos - 1;
-     subelement += 2 + subelement[1]) {
- subie_len = subelement[1];
- if (mbssid_end_pos - subelement < 2 + subie_len)
- break;
- if (subelement[0] != 0 || subelement[1] < 4) {
+ for_each_element_id(elem, WLAN_EID_MULTIPLE_BSSID, ie, ielen) {
+ if (elem->datalen < 4)
+ continue;
+ for_each_element(sub, elem->data + 1, elem->datalen - 1) {
+ if (sub->id != 0 || sub->datalen < 4) {
  /* not a valid BSS profile */
  continue;
  }
 
- if (subelement[2] != WLAN_EID_NON_TX_BSSID_CAP ||
-    subelement[3] != 2) {
+ if (sub->data[0] != WLAN_EID_NON_TX_BSSID_CAP ||
+    sub->data[1] != 2) {
  /* The first element within the Nontransmitted
  * BSSID Profile is not the Nontransmitted
  * BSSID Capability element.
@@ -1428,26 +1415,24 @@ static void cfg80211_parse_mbssid_data(struct wiphy *wiphy,
  /* found a Nontransmitted BSSID Profile */
  mbssid_index_ie = cfg80211_find_ie
  (WLAN_EID_MULTI_BSSID_IDX,
- subelement + 2, subie_len);
+ sub->data, sub->datalen);
  if (!mbssid_index_ie || mbssid_index_ie[1] < 1 ||
     mbssid_index_ie[2] == 0) {
  /* No valid Multiple BSSID-Index element */
  continue;
  }
 
- cfg80211_gen_new_bssid(bssid, tmp[2],
+ cfg80211_gen_new_bssid(bssid, elem->data[0],
        mbssid_index_ie[2],
        new_bssid);
  memset(new_ie, 0, IEEE80211_MAX_DATA_LEN);
- new_ie_len = cfg80211_gen_new_ie(ie, ielen,
- subelement + 2,
- subie_len, new_ie,
+ new_ie_len = cfg80211_gen_new_ie(ie, ielen, sub->data,
+ sub->datalen, new_ie,
  gfp);
  if (!new_ie_len)
  continue;
 
- capability = le16_to_cpup((const __le16 *)
-  &subelement[4]);
+ capability = get_unaligned_le16(sub->data + 2);
  bss = cfg80211_inform_single_bss_data(wiphy, data,
       ftype,
       new_bssid, tsf,
@@ -1460,8 +1445,6 @@ static void cfg80211_parse_mbssid_data(struct wiphy *wiphy,
  break;
  cfg80211_put_bss(wiphy, bss);
  }
-
- pos = mbssid_end_pos;
  }
 
  kfree(new_ie);
--
2.23.0


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[PATCH 09/21][SRU][OEM-OSP1-B] cfg80211: Properly track transmitting and non-transmitting BSS

You-Sheng Yang
In reply to this post by You-Sheng Yang
From: Sara Sharon <[hidden email]>

BugLink: https://bugs.launchpad.net/bugs/1845138

When holding data of the non-transmitting BSS, we need to keep the
transmitting BSS data on. Otherwise it will be released, and release
the non-transmitting BSS with it.

Signed-off-by: Sara Sharon <[hidden email]>
Signed-off-by: Johannes Berg <[hidden email]>
(cherry picked from commit a3584f56de1c808d4383a275b4a74467b19e5645)
Signed-off-by: You-Sheng Yang <[hidden email]>
---
 net/wireless/core.h | 12 ++++++++++++
 net/wireless/scan.c | 36 ++++++++++++++++++++++++++++++++++--
 2 files changed, 46 insertions(+), 2 deletions(-)

diff --git a/net/wireless/core.h b/net/wireless/core.h
index 353998d749321..fcad5e9d1c9fa 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -153,6 +153,7 @@ struct cfg80211_internal_bss {
  struct list_head list;
  struct list_head hidden_list;
  struct list_head nontrans_list;
+ struct cfg80211_bss *transmitted_bss;
  struct rb_node rbn;
  u64 ts_boottime;
  unsigned long ts;
@@ -183,12 +184,23 @@ static inline struct cfg80211_internal_bss *bss_from_pub(struct cfg80211_bss *pu
 static inline void cfg80211_hold_bss(struct cfg80211_internal_bss *bss)
 {
  atomic_inc(&bss->hold);
+ if (bss->transmitted_bss) {
+ bss = container_of(bss->transmitted_bss,
+   struct cfg80211_internal_bss, pub);
+ atomic_inc(&bss->hold);
+ }
 }
 
 static inline void cfg80211_unhold_bss(struct cfg80211_internal_bss *bss)
 {
  int r = atomic_dec_return(&bss->hold);
  WARN_ON(r < 0);
+ if (bss->transmitted_bss) {
+ bss = container_of(bss->transmitted_bss,
+   struct cfg80211_internal_bss, pub);
+ r = atomic_dec_return(&bss->hold);
+ WARN_ON(r < 0);
+ }
 }
 
 
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 54feb7741c26c..d5950a23e619c 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -110,6 +110,12 @@ static inline void bss_ref_get(struct cfg80211_registered_device *rdev,
    pub);
  bss->refcount++;
  }
+ if (bss->transmitted_bss) {
+ bss = container_of(bss->transmitted_bss,
+   struct cfg80211_internal_bss,
+   pub);
+ bss->refcount++;
+ }
 }
 
 static inline void bss_ref_put(struct cfg80211_registered_device *rdev,
@@ -126,6 +132,18 @@ static inline void bss_ref_put(struct cfg80211_registered_device *rdev,
  if (hbss->refcount == 0)
  bss_free(hbss);
  }
+
+ if (bss->transmitted_bss) {
+ struct cfg80211_internal_bss *tbss;
+
+ tbss = container_of(bss->transmitted_bss,
+    struct cfg80211_internal_bss,
+    pub);
+ tbss->refcount--;
+ if (tbss->refcount == 0)
+ bss_free(tbss);
+ }
+
  bss->refcount--;
  if (bss->refcount == 0)
  bss_free(bss);
@@ -1024,6 +1042,7 @@ static bool cfg80211_combine_bsses(struct cfg80211_registered_device *rdev,
 static struct cfg80211_internal_bss *
 cfg80211_bss_update(struct cfg80211_registered_device *rdev,
     struct cfg80211_internal_bss *tmp,
+    struct cfg80211_bss *trans_bss,
     bool signal_valid)
 {
  struct cfg80211_internal_bss *found = NULL;
@@ -1181,6 +1200,17 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev,
  goto drop;
  }
 
+ /* This must be before the call to bss_ref_get */
+ if (trans_bss) {
+ struct cfg80211_internal_bss *pbss =
+ container_of(trans_bss,
+     struct cfg80211_internal_bss,
+     pub);
+
+ new->transmitted_bss = trans_bss;
+ bss_ref_get(rdev, pbss);
+ }
+
  list_add_tail(&new->list, &rdev->bss_list);
  rdev->bss_entries++;
  rb_insert_bss(rdev, new);
@@ -1336,7 +1366,8 @@ cfg80211_inform_single_bss_data(struct wiphy *wiphy,
 
  signal_valid = abs(data->chan->center_freq - channel->center_freq) <=
  wiphy->max_adj_channel_rssi_comp;
- res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp, signal_valid);
+ res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp, trans_bss,
+  signal_valid);
  if (!res)
  return NULL;
 
@@ -1639,7 +1670,8 @@ cfg80211_inform_single_bss_frame_data(struct wiphy *wiphy,
 
  signal_valid = abs(data->chan->center_freq - channel->center_freq) <=
  wiphy->max_adj_channel_rssi_comp;
- res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp, signal_valid);
+ res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp, trans_bss,
+  signal_valid);
  if (!res)
  return NULL;
 
--
2.23.0


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[PATCH 10/21][SRU][OEM-OSP1-B] cfg80211: Move Multiple BSS info to struct cfg80211_bss to be visible

You-Sheng Yang
In reply to this post by You-Sheng Yang
From: Sara Sharon <[hidden email]>

BugLink: https://bugs.launchpad.net/bugs/1845138

Previously the transmitted BSS and the non-trasmitted BSS list were
defined in struct cfg80211_internal_bss. Move them to struct cfg80211_bss
since mac80211 needs this info.

Signed-off-by: Sara Sharon <[hidden email]>
Signed-off-by: Johannes Berg <[hidden email]>
(cherry picked from commit 7011ba583f425780ab1ee52f41161a0171197365)
Signed-off-by: You-Sheng Yang <[hidden email]>
---
 include/net/cfg80211.h |  4 ++-
 net/wireless/core.h    | 10 +++---
 net/wireless/scan.c    | 80 ++++++++++++++++++++----------------------
 3 files changed, 46 insertions(+), 48 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 16651a3f2a4b1..850d34b2d2c75 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -6,7 +6,7 @@
  * Copyright 2006-2010 Johannes Berg <[hidden email]>
  * Copyright 2013-2014 Intel Mobile Communications GmbH
  * Copyright 2015-2017 Intel Deutschland GmbH
- * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018-2019 Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -2021,6 +2021,8 @@ struct cfg80211_bss {
  const struct cfg80211_bss_ies __rcu *proberesp_ies;
 
  struct cfg80211_bss *hidden_beacon_bss;
+ struct cfg80211_bss *transmitted_bss;
+ struct list_head nontrans_list;
 
  s32 signal;
 
diff --git a/net/wireless/core.h b/net/wireless/core.h
index fcad5e9d1c9fa..84d36ca7a7aba 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -152,8 +152,6 @@ extern int cfg80211_rdev_list_generation;
 struct cfg80211_internal_bss {
  struct list_head list;
  struct list_head hidden_list;
- struct list_head nontrans_list;
- struct cfg80211_bss *transmitted_bss;
  struct rb_node rbn;
  u64 ts_boottime;
  unsigned long ts;
@@ -184,8 +182,8 @@ static inline struct cfg80211_internal_bss *bss_from_pub(struct cfg80211_bss *pu
 static inline void cfg80211_hold_bss(struct cfg80211_internal_bss *bss)
 {
  atomic_inc(&bss->hold);
- if (bss->transmitted_bss) {
- bss = container_of(bss->transmitted_bss,
+ if (bss->pub.transmitted_bss) {
+ bss = container_of(bss->pub.transmitted_bss,
    struct cfg80211_internal_bss, pub);
  atomic_inc(&bss->hold);
  }
@@ -195,8 +193,8 @@ static inline void cfg80211_unhold_bss(struct cfg80211_internal_bss *bss)
 {
  int r = atomic_dec_return(&bss->hold);
  WARN_ON(r < 0);
- if (bss->transmitted_bss) {
- bss = container_of(bss->transmitted_bss,
+ if (bss->pub.transmitted_bss) {
+ bss = container_of(bss->pub.transmitted_bss,
    struct cfg80211_internal_bss, pub);
  r = atomic_dec_return(&bss->hold);
  WARN_ON(r < 0);
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index d5950a23e619c..325323a842d8a 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -110,8 +110,8 @@ static inline void bss_ref_get(struct cfg80211_registered_device *rdev,
    pub);
  bss->refcount++;
  }
- if (bss->transmitted_bss) {
- bss = container_of(bss->transmitted_bss,
+ if (bss->pub.transmitted_bss) {
+ bss = container_of(bss->pub.transmitted_bss,
    struct cfg80211_internal_bss,
    pub);
  bss->refcount++;
@@ -133,10 +133,10 @@ static inline void bss_ref_put(struct cfg80211_registered_device *rdev,
  bss_free(hbss);
  }
 
- if (bss->transmitted_bss) {
+ if (bss->pub.transmitted_bss) {
  struct cfg80211_internal_bss *tbss;
 
- tbss = container_of(bss->transmitted_bss,
+ tbss = container_of(bss->pub.transmitted_bss,
     struct cfg80211_internal_bss,
     pub);
  tbss->refcount--;
@@ -169,7 +169,7 @@ static bool __cfg80211_unlink_bss(struct cfg80211_registered_device *rdev,
  }
 
  list_del_init(&bss->list);
- list_del_init(&bss->nontrans_list);
+ list_del_init(&bss->pub.nontrans_list);
  rb_erase(&bss->rbn, &rdev->bss_tree);
  rdev->bss_entries--;
  WARN_ONCE((rdev->bss_entries == 0) ^ list_empty(&rdev->bss_list),
@@ -317,15 +317,15 @@ static bool is_bss(struct cfg80211_bss *a, const u8 *bssid,
 }
 
 static int
-cfg80211_add_nontrans_list(struct cfg80211_internal_bss *trans_bss,
-   struct cfg80211_internal_bss *nontrans_bss)
+cfg80211_add_nontrans_list(struct cfg80211_bss *trans_bss,
+   struct cfg80211_bss *nontrans_bss)
 {
  const u8 *ssid;
  size_t ssid_len;
- struct cfg80211_internal_bss *bss = NULL;
+ struct cfg80211_bss *bss = NULL;
 
  rcu_read_lock();
- ssid = ieee80211_bss_get_ie(&nontrans_bss->pub, WLAN_EID_SSID);
+ ssid = ieee80211_bss_get_ie(nontrans_bss, WLAN_EID_SSID);
  if (!ssid) {
  rcu_read_unlock();
  return -EINVAL;
@@ -336,7 +336,7 @@ cfg80211_add_nontrans_list(struct cfg80211_internal_bss *trans_bss,
 
  /* check if nontrans_bss is in the list */
  list_for_each_entry(bss, &trans_bss->nontrans_list, nontrans_list) {
- if (is_bss(&bss->pub, nontrans_bss->pub.bssid, ssid, ssid_len))
+ if (is_bss(bss, nontrans_bss->bssid, ssid, ssid_len))
  return 0;
  }
 
@@ -1166,7 +1166,7 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev,
  memcpy(new, tmp, sizeof(*new));
  new->refcount = 1;
  INIT_LIST_HEAD(&new->hidden_list);
- INIT_LIST_HEAD(&new->nontrans_list);
+ INIT_LIST_HEAD(&new->pub.nontrans_list);
 
  if (rcu_access_pointer(tmp->pub.proberesp_ies)) {
  hidden = rb_find_bss(rdev, tmp, BSS_CMP_HIDE_ZLEN);
@@ -1207,7 +1207,7 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev,
      struct cfg80211_internal_bss,
      pub);
 
- new->transmitted_bss = trans_bss;
+ new->pub.transmitted_bss = trans_bss;
  bss_ref_get(rdev, pbss);
  }
 
@@ -1311,7 +1311,7 @@ cfg80211_inform_single_bss_data(struct wiphy *wiphy,
  struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
  struct cfg80211_bss_ies *ies;
  struct ieee80211_channel *channel;
- struct cfg80211_internal_bss tmp = {}, *res, *trans_internal;
+ struct cfg80211_internal_bss tmp = {}, *res;
  int bss_type;
  bool signal_valid;
 
@@ -1385,10 +1385,7 @@ cfg80211_inform_single_bss_data(struct wiphy *wiphy,
  /* this is a nontransmitting bss, we need to add it to
  * transmitting bss' list if it is not there
  */
- trans_internal = container_of(trans_bss,
-      struct cfg80211_internal_bss,
-      pub);
- if (cfg80211_add_nontrans_list(trans_internal, res)) {
+ if (cfg80211_add_nontrans_list(trans_bss, &res->pub)) {
  if (__cfg80211_unlink_bss(rdev, res))
  rdev->bss_generation++;
  }
@@ -1523,7 +1520,7 @@ cfg80211_parse_mbssid_frame_data(struct wiphy *wiphy,
 
 static void
 cfg80211_update_notlisted_nontrans(struct wiphy *wiphy,
-   struct cfg80211_internal_bss *nontrans_bss,
+   struct cfg80211_bss *nontrans_bss,
    struct ieee80211_mgmt *mgmt, size_t len,
    gfp_t gfp)
 {
@@ -1548,7 +1545,7 @@ cfg80211_update_notlisted_nontrans(struct wiphy *wiphy,
  return;
  new_ie_len -= mbssid[1];
  rcu_read_lock();
- nontrans_ssid = ieee80211_bss_get_ie(&nontrans_bss->pub, WLAN_EID_SSID);
+ nontrans_ssid = ieee80211_bss_get_ie(nontrans_bss, WLAN_EID_SSID);
  if (!nontrans_ssid) {
  rcu_read_unlock();
  return;
@@ -1589,15 +1586,15 @@ cfg80211_update_notlisted_nontrans(struct wiphy *wiphy,
  new_ies->from_beacon = ieee80211_is_beacon(mgmt->frame_control);
  memcpy(new_ies->data, new_ie, new_ie_len);
  if (ieee80211_is_probe_resp(mgmt->frame_control)) {
- old = rcu_access_pointer(nontrans_bss->pub.proberesp_ies);
- rcu_assign_pointer(nontrans_bss->pub.proberesp_ies, new_ies);
- rcu_assign_pointer(nontrans_bss->pub.ies, new_ies);
+ old = rcu_access_pointer(nontrans_bss->proberesp_ies);
+ rcu_assign_pointer(nontrans_bss->proberesp_ies, new_ies);
+ rcu_assign_pointer(nontrans_bss->ies, new_ies);
  if (old)
  kfree_rcu((struct cfg80211_bss_ies *)old, rcu_head);
  } else {
- old = rcu_access_pointer(nontrans_bss->pub.beacon_ies);
- rcu_assign_pointer(nontrans_bss->pub.beacon_ies, new_ies);
- rcu_assign_pointer(nontrans_bss->pub.ies, new_ies);
+ old = rcu_access_pointer(nontrans_bss->beacon_ies);
+ rcu_assign_pointer(nontrans_bss->beacon_ies, new_ies);
+ rcu_assign_pointer(nontrans_bss->ies, new_ies);
  if (old)
  kfree_rcu((struct cfg80211_bss_ies *)old, rcu_head);
  }
@@ -1696,8 +1693,7 @@ cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
        struct ieee80211_mgmt *mgmt, size_t len,
        gfp_t gfp)
 {
- struct cfg80211_bss *res;
- struct cfg80211_internal_bss *trans_bss, *tmp_bss;
+ struct cfg80211_bss *res, *tmp_bss;
  const u8 *ie = mgmt->u.probe_resp.variable;
  const struct cfg80211_bss_ies *ies1, *ies2;
  size_t ielen = len - offsetof(struct ieee80211_mgmt,
@@ -1715,17 +1711,14 @@ cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
  * in MBSSID IE
  */
  ies1 = rcu_access_pointer(res->ies);
- trans_bss = container_of(res, struct cfg80211_internal_bss, pub);
- if (!trans_bss)
- return res;
 
  /* go through nontrans_list, if the timestamp of the BSS is
  * earlier than the timestamp of the transmitting BSS then
  * update it
  */
- list_for_each_entry(tmp_bss, &trans_bss->nontrans_list,
+ list_for_each_entry(tmp_bss, &res->nontrans_list,
     nontrans_list) {
- ies2 = rcu_access_pointer(tmp_bss->pub.ies);
+ ies2 = rcu_access_pointer(tmp_bss->ies);
  if (ies2->tsf < ies1->tsf)
  cfg80211_update_notlisted_nontrans(wiphy, tmp_bss,
    mgmt, len, gfp);
@@ -1770,7 +1763,8 @@ EXPORT_SYMBOL(cfg80211_put_bss);
 void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub)
 {
  struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
- struct cfg80211_internal_bss *bss, *nontrans_bss, *tmp;
+ struct cfg80211_internal_bss *bss, *tmp1;
+ struct cfg80211_bss *nontrans_bss, *tmp;
 
  if (WARN_ON(!pub))
  return;
@@ -1778,17 +1772,21 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub)
  bss = container_of(pub, struct cfg80211_internal_bss, pub);
 
  spin_lock_bh(&rdev->bss_lock);
- if (!list_empty(&bss->list)) {
- list_for_each_entry_safe(nontrans_bss, tmp,
- &bss->nontrans_list,
- nontrans_list) {
- if (__cfg80211_unlink_bss(rdev, nontrans_bss))
- rdev->bss_generation++;
- }
+ if (list_empty(&bss->list))
+ goto out;
 
- if (__cfg80211_unlink_bss(rdev, bss))
+ list_for_each_entry_safe(nontrans_bss, tmp,
+ &pub->nontrans_list,
+ nontrans_list) {
+ tmp1 = container_of(nontrans_bss,
+    struct cfg80211_internal_bss, pub);
+ if (__cfg80211_unlink_bss(rdev, tmp1))
  rdev->bss_generation++;
  }
+
+ if (__cfg80211_unlink_bss(rdev, bss))
+ rdev->bss_generation++;
+out:
  spin_unlock_bh(&rdev->bss_lock);
 }
 EXPORT_SYMBOL(cfg80211_unlink_bss);
--
2.23.0


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[PATCH 11/21][SRU][OEM-OSP1-B] cfg80211: parse multi-bssid only if HW supports it

You-Sheng Yang
In reply to this post by You-Sheng Yang
From: Sara Sharon <[hidden email]>

BugLink: https://bugs.launchpad.net/bugs/1845138

Parsing and exposing nontransmitted APs is problematic
when underlying HW doesn't support it. Do it only if
driver indicated support. Allow HE restriction as well,
since the HE spec defined the exact manner that Multiple
BSSID set should behave. APs that not support the HE
spec will have less predictable Multiple BSSID set
support/behavior

Signed-off-by: Sara Sharon <[hidden email]>
Signed-off-by: Johannes Berg <[hidden email]>
(cherry picked from commit 213ed579d38ef47c55694a4a411926af3dfc6558)
Signed-off-by: You-Sheng Yang <[hidden email]>
---
 include/net/cfg80211.h |  8 ++++++++
 net/wireless/scan.c    | 11 ++++++++++-
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 850d34b2d2c75..05ea88213e74a 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -4282,6 +4282,11 @@ struct cfg80211_pmsr_capabilities {
  * @txq_memory_limit: configuration internal TX queue memory limit
  * @txq_quantum: configuration of internal TX queue scheduler quantum
  *
+ * @support_mbssid: can HW support association with nontransmitted AP
+ * @support_only_he_mbssid: don't parse MBSSID elements if it is not
+ * HE AP, in order to avoid compatibility issues.
+ * @support_mbssid must be set for this to have any effect.
+ *
  * @pmsr_capa: peer measurement capabilities
  */
 struct wiphy {
@@ -4419,6 +4424,9 @@ struct wiphy {
  u32 txq_memory_limit;
  u32 txq_quantum;
 
+ u8 support_mbssid:1,
+   support_only_he_mbssid:1;
+
  const struct cfg80211_pmsr_capabilities *pmsr_capa;
 
  char priv[0] __aligned(NETDEV_ALIGN);
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 325323a842d8a..ab0f0178ee0eb 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -1417,6 +1417,11 @@ static void cfg80211_parse_mbssid_data(struct wiphy *wiphy,
  return;
  if (!cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, ie, ielen))
  return;
+ if (!wiphy->support_mbssid)
+ return;
+ if (wiphy->support_only_he_mbssid &&
+    !cfg80211_find_ext_ie(WLAN_EID_EXT_HE_CAPABILITY, ie, ielen))
+ return;
 
  new_ie = kmalloc(IEEE80211_MAX_DATA_LEN, gfp);
  if (!new_ie)
@@ -1701,7 +1706,11 @@ cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
 
  res = cfg80211_inform_single_bss_frame_data(wiphy, data, mgmt,
     len, NULL, gfp);
- if (!res || !cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, ie, ielen))
+ if (!res || !wiphy->support_mbssid ||
+    !cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, ie, ielen))
+ return res;
+ if (wiphy->support_only_he_mbssid &&
+    !cfg80211_find_ext_ie(WLAN_EID_EXT_HE_CAPABILITY, ie, ielen))
  return res;
 
  /* process each non-transmitting bss */
--
2.23.0


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[PATCH 12/21][SRU][OEM-OSP1-B] cfg80211: make BSSID generation function inline

You-Sheng Yang
In reply to this post by You-Sheng Yang
From: Sara Sharon <[hidden email]>

BugLink: https://bugs.launchpad.net/bugs/1845138

This will enable reuse by mac80211.

Signed-off-by: Sara Sharon <[hidden email]>
Signed-off-by: Johannes Berg <[hidden email]>
(cherry picked from commit 7ece9c372b21635120e7ab5ea3fc41ce9892ead8)
Signed-off-by: You-Sheng Yang <[hidden email]>
---
 include/net/cfg80211.h | 23 +++++++++++++++++++++++
 net/wireless/scan.c    | 16 ----------------
 2 files changed, 23 insertions(+), 16 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 05ea88213e74a..360c7b6b19c4b 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -5413,6 +5413,29 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy,
  return cfg80211_inform_bss_frame_data(wiphy, &data, mgmt, len, gfp);
 }
 
+/**
+ * cfg80211_gen_new_bssid - generate a nontransmitted BSSID for multi-BSSID
+ * @bssid: transmitter BSSID
+ * @max_bssid: max BSSID indicator, taken from Multiple BSSID element
+ * @mbssid_index: BSSID index, taken from Multiple BSSID index element
+ * @new_bssid_addr: address of the resulting BSSID
+ */
+static inline void cfg80211_gen_new_bssid(const u8 *bssid, u8 max_bssid,
+  u8 mbssid_index, u8 *new_bssid_addr)
+{
+ u64 bssid_tmp, new_bssid;
+ u64 lsb_n;
+
+ bssid_tmp = ether_addr_to_u64(bssid);
+
+ lsb_n = bssid_tmp & ((1 << max_bssid) - 1);
+ new_bssid = bssid_tmp;
+ new_bssid &= ~((1 << max_bssid) - 1);
+ new_bssid |= (lsb_n + mbssid_index) % (1 << max_bssid);
+
+ u64_to_ether_addr(new_bssid, new_bssid_addr);
+}
+
 /**
  * enum cfg80211_bss_frame_type - frame type that the BSS data came from
  * @CFG80211_BSS_FTYPE_UNKNOWN: driver doesn't know whether the data is
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index ab0f0178ee0eb..f1b06e9c1038a 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -179,22 +179,6 @@ static bool __cfg80211_unlink_bss(struct cfg80211_registered_device *rdev,
  return true;
 }
 
-static void cfg80211_gen_new_bssid(const u8 *bssid, u8 max_bssid,
-   u8 mbssid_index, u8 *new_bssid_addr)
-{
- u64 bssid_tmp, new_bssid = 0;
- u64 lsb_n;
-
- bssid_tmp = ether_addr_to_u64(bssid);
-
- lsb_n = bssid_tmp & ((1 << max_bssid) - 1);
- new_bssid = bssid_tmp;
- new_bssid &= ~((1 << max_bssid) - 1);
- new_bssid |= (lsb_n + mbssid_index) % (1 << max_bssid);
-
- u64_to_ether_addr(new_bssid, new_bssid_addr);
-}
-
 static size_t cfg80211_gen_new_ie(const u8 *ie, size_t ielen,
   const u8 *subelement, size_t subie_len,
   u8 *new_ie, gfp_t gfp)
--
2.23.0


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[PATCH 13/21][SRU][OEM-OSP1-B] cfg80211: save multi-bssid properties

You-Sheng Yang
In reply to this post by You-Sheng Yang
From: Sara Sharon <[hidden email]>

BugLink: https://bugs.launchpad.net/bugs/1845138

When the new IEs are generated, the multiple BSSID elements
are not saved. Save aside properties that are needed later
for PS.

Signed-off-by: Sara Sharon <[hidden email]>
Signed-off-by: Johannes Berg <[hidden email]>
(cherry picked from commit 0cd01efb03396c5368b1a32eed0ccb2aa453bdc8)
Signed-off-by: You-Sheng Yang <[hidden email]>
---
 include/net/cfg80211.h |  5 +++
 net/wireless/scan.c    | 69 +++++++++++++++++++++++++++++-------------
 2 files changed, 53 insertions(+), 21 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 360c7b6b19c4b..881a5a0f9b2c7 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2010,6 +2010,8 @@ struct cfg80211_bss_ies {
  * @signal: signal strength value (type depends on the wiphy's signal_type)
  * @chains: bitmask for filled values in @chain_signal.
  * @chain_signal: per-chain signal strength of last received BSS in dBm.
+ * @bssid_index: index in the multiple BSS set
+ * @max_bssid_indicator: max number of members in the BSS set
  * @priv: private area for driver use, has at least wiphy->bss_priv_size bytes
  */
 struct cfg80211_bss {
@@ -2033,6 +2035,9 @@ struct cfg80211_bss {
  u8 chains;
  s8 chain_signal[IEEE80211_MAX_CHAINS];
 
+ u8 bssid_index;
+ u8 max_bssid_indicator;
+
  u8 priv[0] __aligned(sizeof(void *));
 };
 
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index f1b06e9c1038a..387e5f868684d 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -1022,11 +1022,16 @@ static bool cfg80211_combine_bsses(struct cfg80211_registered_device *rdev,
  return true;
 }
 
+struct cfg80211_non_tx_bss {
+ struct cfg80211_bss *tx_bss;
+ u8 max_bssid_indicator;
+ u8 bssid_index;
+};
+
 /* Returned bss is reference counted and must be cleaned up appropriately. */
 static struct cfg80211_internal_bss *
 cfg80211_bss_update(struct cfg80211_registered_device *rdev,
     struct cfg80211_internal_bss *tmp,
-    struct cfg80211_bss *trans_bss,
     bool signal_valid)
 {
  struct cfg80211_internal_bss *found = NULL;
@@ -1126,6 +1131,8 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev,
  memcpy(found->pub.chain_signal, tmp->pub.chain_signal,
        IEEE80211_MAX_CHAINS);
  ether_addr_copy(found->parent_bssid, tmp->parent_bssid);
+ found->pub.max_bssid_indicator = tmp->pub.max_bssid_indicator;
+ found->pub.bssid_index = tmp->pub.bssid_index;
  } else {
  struct cfg80211_internal_bss *new;
  struct cfg80211_internal_bss *hidden;
@@ -1185,13 +1192,13 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev,
  }
 
  /* This must be before the call to bss_ref_get */
- if (trans_bss) {
+ if (tmp->pub.transmitted_bss) {
  struct cfg80211_internal_bss *pbss =
- container_of(trans_bss,
+ container_of(tmp->pub.transmitted_bss,
      struct cfg80211_internal_bss,
      pub);
 
- new->pub.transmitted_bss = trans_bss;
+ new->pub.transmitted_bss = tmp->pub.transmitted_bss;
  bss_ref_get(rdev, pbss);
  }
 
@@ -1289,7 +1296,7 @@ cfg80211_inform_single_bss_data(struct wiphy *wiphy,
  enum cfg80211_bss_frame_type ftype,
  const u8 *bssid, u64 tsf, u16 capability,
  u16 beacon_interval, const u8 *ie, size_t ielen,
- struct cfg80211_bss *trans_bss,
+ struct cfg80211_non_tx_bss *non_tx_data,
  gfp_t gfp)
 {
  struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
@@ -1318,6 +1325,11 @@ cfg80211_inform_single_bss_data(struct wiphy *wiphy,
  tmp.pub.beacon_interval = beacon_interval;
  tmp.pub.capability = capability;
  tmp.ts_boottime = data->boottime_ns;
+ if (non_tx_data) {
+ tmp.pub.transmitted_bss = non_tx_data->tx_bss;
+ tmp.pub.bssid_index = non_tx_data->bssid_index;
+ tmp.pub.max_bssid_indicator = non_tx_data->max_bssid_indicator;
+ }
 
  /*
  * If we do not know here whether the IEs are from a Beacon or Probe
@@ -1350,8 +1362,7 @@ cfg80211_inform_single_bss_data(struct wiphy *wiphy,
 
  signal_valid = abs(data->chan->center_freq - channel->center_freq) <=
  wiphy->max_adj_channel_rssi_comp;
- res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp, trans_bss,
-  signal_valid);
+ res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp, signal_valid);
  if (!res)
  return NULL;
 
@@ -1365,11 +1376,12 @@ cfg80211_inform_single_bss_data(struct wiphy *wiphy,
  regulatory_hint_found_beacon(wiphy, channel, gfp);
  }
 
- if (trans_bss) {
+ if (non_tx_data && non_tx_data->tx_bss) {
  /* this is a nontransmitting bss, we need to add it to
  * transmitting bss' list if it is not there
  */
- if (cfg80211_add_nontrans_list(trans_bss, &res->pub)) {
+ if (cfg80211_add_nontrans_list(non_tx_data->tx_bss,
+       &res->pub)) {
  if (__cfg80211_unlink_bss(rdev, res))
  rdev->bss_generation++;
  }
@@ -1386,7 +1398,7 @@ static void cfg80211_parse_mbssid_data(struct wiphy *wiphy,
        const u8 *bssid, u64 tsf,
        u16 beacon_interval, const u8 *ie,
        size_t ielen,
-       struct cfg80211_bss *trans_bss,
+       struct cfg80211_non_tx_bss *non_tx_data,
        gfp_t gfp)
 {
  const u8 *mbssid_index_ie;
@@ -1397,7 +1409,7 @@ static void cfg80211_parse_mbssid_data(struct wiphy *wiphy,
  u16 capability;
  struct cfg80211_bss *bss;
 
- if (!trans_bss)
+ if (!non_tx_data)
  return;
  if (!cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, ie, ielen))
  return;
@@ -1439,8 +1451,12 @@ static void cfg80211_parse_mbssid_data(struct wiphy *wiphy,
  continue;
  }
 
- cfg80211_gen_new_bssid(bssid, elem->data[0],
-       mbssid_index_ie[2],
+ non_tx_data->bssid_index = mbssid_index_ie[2];
+ non_tx_data->max_bssid_indicator = elem->data[0];
+
+ cfg80211_gen_new_bssid(bssid,
+       non_tx_data->max_bssid_indicator,
+       non_tx_data->bssid_index,
        new_bssid);
  memset(new_ie, 0, IEEE80211_MAX_DATA_LEN);
  new_ie_len = cfg80211_gen_new_ie(ie, ielen, sub->data,
@@ -1457,7 +1473,8 @@ static void cfg80211_parse_mbssid_data(struct wiphy *wiphy,
       beacon_interval,
       new_ie,
       new_ie_len,
-      trans_bss, gfp);
+      non_tx_data,
+      gfp);
  if (!bss)
  break;
  cfg80211_put_bss(wiphy, bss);
@@ -1476,12 +1493,15 @@ cfg80211_inform_bss_data(struct wiphy *wiphy,
  gfp_t gfp)
 {
  struct cfg80211_bss *res;
+ struct cfg80211_non_tx_bss non_tx_data;
 
  res = cfg80211_inform_single_bss_data(wiphy, data, ftype, bssid, tsf,
       capability, beacon_interval, ie,
       ielen, NULL, gfp);
+ non_tx_data.tx_bss = res;
  cfg80211_parse_mbssid_data(wiphy, data, ftype, bssid, tsf,
-   beacon_interval, ie, ielen, res, gfp);
+   beacon_interval, ie, ielen, &non_tx_data,
+   gfp);
  return res;
 }
 EXPORT_SYMBOL(cfg80211_inform_bss_data);
@@ -1490,7 +1510,7 @@ static void
 cfg80211_parse_mbssid_frame_data(struct wiphy *wiphy,
  struct cfg80211_inform_bss *data,
  struct ieee80211_mgmt *mgmt, size_t len,
- struct cfg80211_bss *trans_bss,
+ struct cfg80211_non_tx_bss *non_tx_data,
  gfp_t gfp)
 {
  enum cfg80211_bss_frame_type ftype;
@@ -1504,7 +1524,7 @@ cfg80211_parse_mbssid_frame_data(struct wiphy *wiphy,
  cfg80211_parse_mbssid_data(wiphy, data, ftype, mgmt->bssid,
    le64_to_cpu(mgmt->u.probe_resp.timestamp),
    le16_to_cpu(mgmt->u.probe_resp.beacon_int),
-   ie, ielen, trans_bss, gfp);
+   ie, ielen, non_tx_data, gfp);
 }
 
 static void
@@ -1594,7 +1614,7 @@ static struct cfg80211_bss *
 cfg80211_inform_single_bss_frame_data(struct wiphy *wiphy,
       struct cfg80211_inform_bss *data,
       struct ieee80211_mgmt *mgmt, size_t len,
-      struct cfg80211_bss *trans_bss,
+      struct cfg80211_non_tx_bss *non_tx_data,
       gfp_t gfp)
 {
  struct cfg80211_internal_bss tmp = {}, *res;
@@ -1653,11 +1673,15 @@ cfg80211_inform_single_bss_frame_data(struct wiphy *wiphy,
  tmp.pub.chains = data->chains;
  memcpy(tmp.pub.chain_signal, data->chain_signal, IEEE80211_MAX_CHAINS);
  ether_addr_copy(tmp.parent_bssid, data->parent_bssid);
+ if (non_tx_data) {
+ tmp.pub.transmitted_bss = non_tx_data->tx_bss;
+ tmp.pub.bssid_index = non_tx_data->bssid_index;
+ tmp.pub.max_bssid_indicator = non_tx_data->max_bssid_indicator;
+ }
 
  signal_valid = abs(data->chan->center_freq - channel->center_freq) <=
  wiphy->max_adj_channel_rssi_comp;
- res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp, trans_bss,
-  signal_valid);
+ res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp, signal_valid);
  if (!res)
  return NULL;
 
@@ -1687,6 +1711,7 @@ cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
  const struct cfg80211_bss_ies *ies1, *ies2;
  size_t ielen = len - offsetof(struct ieee80211_mgmt,
       u.probe_resp.variable);
+ struct cfg80211_non_tx_bss non_tx_data;
 
  res = cfg80211_inform_single_bss_frame_data(wiphy, data, mgmt,
     len, NULL, gfp);
@@ -1697,8 +1722,10 @@ cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
     !cfg80211_find_ext_ie(WLAN_EID_EXT_HE_CAPABILITY, ie, ielen))
  return res;
 
+ non_tx_data.tx_bss = res;
  /* process each non-transmitting bss */
- cfg80211_parse_mbssid_frame_data(wiphy, data, mgmt, len, res, gfp);
+ cfg80211_parse_mbssid_frame_data(wiphy, data, mgmt, len,
+ &non_tx_data, gfp);
 
  /* check if the res has other nontransmitting bss which is not
  * in MBSSID IE
--
2.23.0


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[PATCH 14/21][SRU][OEM-OSP1-B] mac80211: support multi-bssid

You-Sheng Yang
In reply to this post by You-Sheng Yang
From: Sara Sharon <[hidden email]>

BugLink: https://bugs.launchpad.net/bugs/1845138

Add support for multi-bssid.

This includes:
- Parsing multi-bssid element
- Overriding DTIM values
- Taking into account in various places the inner BSSID instead of
  transmitter BSSID
- Save aside some multi-bssid properties needed by drivers

Signed-off-by: Sara Sharon <[hidden email]>
Signed-off-by: Johannes Berg <[hidden email]>
(cherry picked from commit 78ac51f81532c1e361a31ac112c1fea470ea9036)
Signed-off-by: You-Sheng Yang <[hidden email]>
---
 include/linux/ieee80211.h  |  34 +++++++++-
 include/net/mac80211.h     |  15 +++++
 net/mac80211/ieee80211_i.h |   7 +++
 net/mac80211/mlme.c        | 125 ++++++++++++++++++++++++++-----------
 net/mac80211/scan.c        |  11 +++-
 net/mac80211/util.c        | 111 +++++++++++++++++++++++++++++---
 6 files changed, 255 insertions(+), 48 deletions(-)

diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index f89f7d74325f1..583597ed97889 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -8,7 +8,7 @@
  * Copyright (c) 2006, Michael Wu <[hidden email]>
  * Copyright (c) 2013 - 2014 Intel Mobile Communications GmbH
  * Copyright (c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright (c) 2018        Intel Corporation
+ * Copyright (c) 2018 - 2019 Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -2485,6 +2485,7 @@ enum ieee80211_eid_ext {
  WLAN_EID_EXT_HE_OPERATION = 36,
  WLAN_EID_EXT_UORA = 37,
  WLAN_EID_EXT_HE_MU_EDCA = 38,
+ WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION = 55,
 };
 
 /* Action category code */
@@ -2701,6 +2702,9 @@ enum ieee80211_tdls_actioncode {
 #define WLAN_EXT_CAPA10_TWT_REQUESTER_SUPPORT BIT(5)
 #define WLAN_EXT_CAPA10_TWT_RESPONDER_SUPPORT BIT(6)
 
+/* Defines support for enhanced multi-bssid advertisement*/
+#define WLAN_EXT_CAPA11_EMA_SUPPORT BIT(1)
+
 /* TDLS specific payload type in the LLC/SNAP header */
 #define WLAN_TDLS_SNAP_RFTYPE 0x2
 
@@ -2892,6 +2896,34 @@ enum ieee80211_sa_query_action {
  WLAN_ACTION_SA_QUERY_RESPONSE = 1,
 };
 
+/**
+ * struct ieee80211_bssid_index
+ *
+ * This structure refers to "Multiple BSSID-index element"
+ *
+ * @bssid_index: BSSID index
+ * @dtim_period: optional, overrides transmitted BSS dtim period
+ * @dtim_count: optional, overrides transmitted BSS dtim count
+ */
+struct ieee80211_bssid_index {
+ u8 bssid_index;
+ u8 dtim_period;
+ u8 dtim_count;
+};
+
+/**
+ * struct ieee80211_multiple_bssid_configuration
+ *
+ * This structure refers to "Multiple BSSID Configuration element"
+ *
+ * @bssid_count: total number of active BSSIDs in the set
+ * @profile_periodicity: the least number of beacon frames need to be received
+ * in order to discover all the nontransmitted BSSIDs in the set.
+ */
+struct ieee80211_multiple_bssid_configuration {
+ u8 bssid_count;
+ u8 profile_periodicity;
+};
 
 #define SUITE(oui, id) (((oui) << 8) | (id))
 
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 88219cc137c38..2ba14021668fe 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -585,6 +585,14 @@ struct ieee80211_ftm_responder_params {
  * @ftm_responder: whether to enable or disable fine timing measurement FTM
  * responder functionality.
  * @ftmr_params: configurable lci/civic parameter when enabling FTM responder.
+ * @nontransmitted: this BSS is a nontransmitted BSS profile
+ * @transmitter_bssid: the address of transmitter AP
+ * @bssid_index: index inside the multiple BSSID set
+ * @bssid_indicator: 2^bssid_indicator is the maximum number of APs in set
+ * @ema_ap: AP supports enhancements of discovery and advertisement of
+ * nontransmitted BSSIDs
+ * @profile_periodicity: the least number of beacon frames need to be received
+ * in order to discover all the nontransmitted BSSIDs in the set.
  */
 struct ieee80211_bss_conf {
  const u8 *bssid;
@@ -638,6 +646,13 @@ struct ieee80211_bss_conf {
  bool protected_keep_alive;
  bool ftm_responder;
  struct ieee80211_ftm_responder_params *ftmr_params;
+ /* Multiple BSSID data */
+ bool nontransmitted;
+ u8 transmitter_bssid[ETH_ALEN];
+ u8 bssid_index;
+ u8 bssid_indicator;
+ bool ema_ap;
+ u8 profile_periodicity;
 };
 
 /**
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 797f48c3f0257..524230cf3d708 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1484,6 +1484,12 @@ struct ieee802_11_elems {
  const struct ieee80211_sec_chan_offs_ie *sec_chan_offs;
  struct ieee80211_mesh_chansw_params_ie *mesh_chansw_params_ie;
  const struct ieee80211_bss_max_idle_period_ie *max_idle_period_ie;
+ const struct ieee80211_multiple_bssid_configuration *mbssid_config_ie;
+ const struct ieee80211_bssid_index *bssid_index;
+ const u8 *nontransmitted_bssid_profile;
+ u8 max_bssid_indicator;
+ u8 dtim_count;
+ u8 dtim_period;
 
  /* length of them, respectively */
  u8 ext_capab_len;
@@ -1502,6 +1508,7 @@ struct ieee802_11_elems {
  u8 prep_len;
  u8 perr_len;
  u8 country_elem_len;
+ u8 bssid_index_len;
 
  /* whether a parse error occurred while retrieving these elements */
  bool parse_error;
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 6bd1de8871fa1..264f857af24b2 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3325,6 +3325,14 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
  /* TODO: OPEN: what happens if BSS color disable is set? */
  }
 
+ if (cbss->transmitted_bss) {
+ bss_conf->nontransmitted = true;
+ ether_addr_copy(bss_conf->transmitter_bssid,
+ cbss->transmitted_bss->bssid);
+ bss_conf->bssid_indicator = cbss->max_bssid_indicator;
+ bss_conf->bssid_index = cbss->bssid_index;
+ }
+
  /*
  * Some APs, e.g. Netgear WNDR3700, report invalid HT operation data
  * in their association response, so ignore that data for our own
@@ -3709,6 +3717,16 @@ static void ieee80211_handle_beacon_sig(struct ieee80211_sub_if_data *sdata,
  }
 }
 
+static bool ieee80211_rx_our_beacon(const u8 *tx_bssid,
+    struct cfg80211_bss *bss)
+{
+ if (ether_addr_equal(tx_bssid, bss->bssid))
+ return true;
+ if (!bss->transmitted_bss)
+ return false;
+ return ether_addr_equal(tx_bssid, bss->transmitted_bss->bssid);
+}
+
 static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
      struct ieee80211_mgmt *mgmt, size_t len,
      struct ieee80211_rx_status *rx_status)
@@ -3750,17 +3768,16 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
  rcu_read_unlock();
 
  if (ifmgd->assoc_data && ifmgd->assoc_data->need_beacon &&
-    ether_addr_equal(mgmt->bssid, ifmgd->assoc_data->bss->bssid)) {
+    ieee80211_rx_our_beacon(mgmt->bssid, ifmgd->assoc_data->bss)) {
  ieee802_11_parse_elems(mgmt->u.beacon.variable,
        len - baselen, false, &elems,
        mgmt->bssid,
        ifmgd->assoc_data->bss->bssid);
 
  ieee80211_rx_bss_info(sdata, mgmt, len, rx_status);
- if (elems.tim && !elems.parse_error) {
- const struct ieee80211_tim_ie *tim_ie = elems.tim;
- ifmgd->dtim_period = tim_ie->dtim_period;
- }
+
+ if (elems.dtim_period)
+ ifmgd->dtim_period = elems.dtim_period;
  ifmgd->have_beacon = true;
  ifmgd->assoc_data->need_beacon = false;
  if (ieee80211_hw_check(&local->hw, TIMING_BEACON_ONLY)) {
@@ -3768,12 +3785,17 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
  le64_to_cpu(mgmt->u.beacon.timestamp);
  sdata->vif.bss_conf.sync_device_ts =
  rx_status->device_timestamp;
- if (elems.tim)
- sdata->vif.bss_conf.sync_dtim_count =
- elems.tim->dtim_count;
- else
- sdata->vif.bss_conf.sync_dtim_count = 0;
+ sdata->vif.bss_conf.sync_dtim_count = elems.dtim_count;
  }
+
+ if (elems.mbssid_config_ie)
+ bss_conf->profile_periodicity =
+ elems.mbssid_config_ie->profile_periodicity;
+
+ if (elems.ext_capab_len >= 11 &&
+    (elems.ext_capab[10] & WLAN_EXT_CAPA11_EMA_SUPPORT))
+ bss_conf->ema_ap = true;
+
  /* continue assoc process */
  ifmgd->assoc_data->timeout = jiffies;
  ifmgd->assoc_data->timeout_started = true;
@@ -3782,7 +3804,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
  }
 
  if (!ifmgd->associated ||
-    !ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid))
+    !ieee80211_rx_our_beacon(mgmt->bssid,  ifmgd->associated))
  return;
  bssid = ifmgd->associated->bssid;
 
@@ -3878,11 +3900,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
  le64_to_cpu(mgmt->u.beacon.timestamp);
  sdata->vif.bss_conf.sync_device_ts =
  rx_status->device_timestamp;
- if (elems.tim)
- sdata->vif.bss_conf.sync_dtim_count =
- elems.tim->dtim_count;
- else
- sdata->vif.bss_conf.sync_dtim_count = 0;
+ sdata->vif.bss_conf.sync_dtim_count = elems.dtim_count;
  }
 
  if (ncrc == ifmgd->beacon_crc && ifmgd->beacon_crc_valid)
@@ -3908,10 +3926,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
  */
  if (!ifmgd->have_beacon) {
  /* a few bogus AP send dtim_period = 0 or no TIM IE */
- if (elems.tim)
- bss_conf->dtim_period = elems.tim->dtim_period ?: 1;
- else
- bss_conf->dtim_period = 1;
+ bss_conf->dtim_period = elems.dtim_period ?: 1;
 
  changed |= BSS_CHANGED_BEACON_INFO;
  ifmgd->have_beacon = true;
@@ -4778,6 +4793,40 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
  return ret;
 }
 
+static bool ieee80211_get_dtim(const struct cfg80211_bss_ies *ies,
+       u8 *dtim_count, u8 *dtim_period)
+{
+ const u8 *tim_ie = cfg80211_find_ie(WLAN_EID_TIM, ies->data, ies->len);
+ const u8 *idx_ie = cfg80211_find_ie(WLAN_EID_MULTI_BSSID_IDX, ies->data,
+ ies->len);
+ const struct ieee80211_tim_ie *tim = NULL;
+ const struct ieee80211_bssid_index *idx;
+ bool valid = tim_ie && tim_ie[1] >= 2;
+
+ if (valid)
+ tim = (void *)(tim_ie + 2);
+
+ if (dtim_count)
+ *dtim_count = valid ? tim->dtim_count : 0;
+
+ if (dtim_period)
+ *dtim_period = valid ? tim->dtim_period : 0;
+
+ /* Check if value is overridden by non-transmitted profile */
+ if (!idx_ie || idx_ie[1] < 3)
+ return valid;
+
+ idx = (void *)(idx_ie + 2);
+
+ if (dtim_count)
+ *dtim_count = idx->dtim_count;
+
+ if (dtim_period)
+ *dtim_period = idx->dtim_period;
+
+ return true;
+}
+
 static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
      struct cfg80211_bss *cbss, bool assoc,
      bool override)
@@ -4869,17 +4918,13 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
  rcu_read_lock();
  ies = rcu_dereference(cbss->beacon_ies);
  if (ies) {
- const u8 *tim_ie;
-
  sdata->vif.bss_conf.sync_tsf = ies->tsf;
  sdata->vif.bss_conf.sync_device_ts =
  bss->device_ts_beacon;
- tim_ie = cfg80211_find_ie(WLAN_EID_TIM,
-  ies->data, ies->len);
- if (tim_ie && tim_ie[1] >= 2)
- sdata->vif.bss_conf.sync_dtim_count = tim_ie[2];
- else
- sdata->vif.bss_conf.sync_dtim_count = 0;
+
+ ieee80211_get_dtim(ies,
+   &sdata->vif.bss_conf.sync_dtim_count,
+   NULL);
  } else if (!ieee80211_hw_check(&sdata->local->hw,
        TIMING_BEACON_ONLY)) {
  ies = rcu_dereference(cbss->proberesp_ies);
@@ -5349,17 +5394,12 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
  assoc_data->timeout_started = true;
  assoc_data->need_beacon = true;
  } else if (beacon_ies) {
- const u8 *tim_ie = cfg80211_find_ie(WLAN_EID_TIM,
-    beacon_ies->data,
-    beacon_ies->len);
+ const u8 *ie;
  u8 dtim_count = 0;
 
- if (tim_ie && tim_ie[1] >= sizeof(struct ieee80211_tim_ie)) {
- const struct ieee80211_tim_ie *tim;
- tim = (void *)(tim_ie + 2);
- ifmgd->dtim_period = tim->dtim_period;
- dtim_count = tim->dtim_count;
- }
+ ieee80211_get_dtim(beacon_ies, &dtim_count,
+   &ifmgd->dtim_period);
+
  ifmgd->have_beacon = true;
  assoc_data->timeout = jiffies;
  assoc_data->timeout_started = true;
@@ -5370,6 +5410,17 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
  bss->device_ts_beacon;
  sdata->vif.bss_conf.sync_dtim_count = dtim_count;
  }
+
+ ie = cfg80211_find_ext_ie(WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION,
+  beacon_ies->data, beacon_ies->len);
+ if (ie && ie[1] >= 3)
+ sdata->vif.bss_conf.profile_periodicity = ie[4];
+
+ ie = cfg80211_find_ie(WLAN_EID_EXT_CAPABILITY,
+      beacon_ies->data, beacon_ies->len);
+ if (ie && ie[1] >= 11 &&
+    (ie[10] & WLAN_EXT_CAPA11_EMA_SUPPORT))
+ sdata->vif.bss_conf.ema_ap = true;
  } else {
  assoc_data->timeout = jiffies;
  assoc_data->timeout_started = true;
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 20211cbc63f4f..0cf0667006236 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -144,8 +144,8 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
   struct ieee80211_channel *channel)
 {
  bool beacon = ieee80211_is_beacon(mgmt->frame_control);
- struct cfg80211_bss *cbss;
- struct ieee80211_bss *bss;
+ struct cfg80211_bss *cbss, *non_tx_cbss;
+ struct ieee80211_bss *bss, *non_tx_bss;
  struct cfg80211_inform_bss bss_meta = {
  .boottime_ns = rx_status->boottime_ns,
  };
@@ -212,6 +212,13 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
  bss = (void *)cbss->priv;
  ieee80211_update_bss_from_elems(local, bss, &elems, rx_status, beacon);
 
+ list_for_each_entry(non_tx_cbss, &cbss->nontrans_list, nontrans_list) {
+ non_tx_bss = (void *)non_tx_cbss->priv;
+
+ ieee80211_update_bss_from_elems(local, non_tx_bss, &elems,
+ rx_status, beacon);
+ }
+
  return bss;
 }
 
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 0877dda03b142..de65e8063fb95 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -891,20 +891,18 @@ void ieee80211_queue_delayed_work(struct ieee80211_hw *hw,
 }
 EXPORT_SYMBOL(ieee80211_queue_delayed_work);
 
-u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
-       struct ieee802_11_elems *elems,
-       u64 filter, u32 crc, u8 *transmitter_bssid,
-       u8 *bss_bssid)
+static u32
+_ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
+    struct ieee802_11_elems *elems,
+    u64 filter, u32 crc, u8 *transmitter_bssid,
+    u8 *bss_bssid)
 {
- struct element *elem;
+ const struct element *elem, *sub;
  bool calc_crc = filter != 0;
  DECLARE_BITMAP(seen_elems, 256);
  const u8 *ie;
 
  bitmap_zero(seen_elems, 256);
- memset(elems, 0, sizeof(*elems));
- elems->ie_start = start;
- elems->total_len = len;
 
  for_each_element(elem, start, len) {
  bool elem_parse_failed;
@@ -1210,6 +1208,57 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
  if (elen >= sizeof(*elems->max_idle_period_ie))
  elems->max_idle_period_ie = (void *)pos;
  break;
+ case WLAN_EID_MULTIPLE_BSSID:
+ if (!bss_bssid || !transmitter_bssid || elen < 4)
+ break;
+
+ elems->max_bssid_indicator = pos[0];
+
+ for_each_element(sub, pos + 1, elen - 1) {
+ u8 sub_len = sub->datalen;
+ u8 new_bssid[ETH_ALEN];
+ const u8 *index;
+
+ /*
+ * we only expect the "non-transmitted BSSID
+ * profile" subelement (subelement id 0)
+ */
+ if (sub->id != 0 || sub->datalen < 4) {
+ /* not a valid BSS profile */
+ continue;
+ }
+
+ if (sub->data[0] != WLAN_EID_NON_TX_BSSID_CAP ||
+    sub->data[1] != 2) {
+ /* The first element of the
+ * Nontransmitted BSSID Profile is not
+ * the Nontransmitted BSSID Capability
+ * element.
+ */
+ continue;
+ }
+
+ /* found a Nontransmitted BSSID Profile */
+ index = cfg80211_find_ie(WLAN_EID_MULTI_BSSID_IDX,
+ sub->data, sub_len);
+ if (!index || index[1] < 1 || index[2] == 0) {
+ /* Invalid MBSSID Index element */
+ continue;
+ }
+
+ cfg80211_gen_new_bssid(transmitter_bssid,
+       pos[0],
+       index[2],
+       new_bssid);
+ if (ether_addr_equal(new_bssid, bss_bssid)) {
+ elems->nontransmitted_bssid_profile =
+ (void *)sub;
+ elems->bssid_index_len = index[1];
+ elems->bssid_index = (void *)&index[2];
+ break;
+ }
+ }
+ break;
  case WLAN_EID_EXTENSION:
  if (pos[0] == WLAN_EID_EXT_HE_MU_EDCA &&
     elen >= (sizeof(*elems->mu_edca_param_set) + 1)) {
@@ -1225,6 +1274,10 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
  elems->he_operation = (void *)&pos[1];
  } else if (pos[0] == WLAN_EID_EXT_UORA && elen >= 1) {
  elems->uora_element = (void *)&pos[1];
+ } else if (pos[0] ==
+   WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION &&
+   elen == 3) {
+ elems->mbssid_config_ie = (void *)&pos[1];
  }
  break;
  default:
@@ -1243,6 +1296,48 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
  return crc;
 }
 
+u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
+       struct ieee802_11_elems *elems,
+       u64 filter, u32 crc, u8 *transmitter_bssid,
+       u8 *bss_bssid)
+{
+ memset(elems, 0, sizeof(*elems));
+ elems->ie_start = start;
+ elems->total_len = len;
+
+ crc = _ieee802_11_parse_elems_crc(start, len, action, elems, filter,
+  crc, transmitter_bssid, bss_bssid);
+
+ /* Override with nontransmitted profile, if found */
+ if (transmitter_bssid && elems->nontransmitted_bssid_profile) {
+ const u8 *profile = elems->nontransmitted_bssid_profile;
+
+ _ieee802_11_parse_elems_crc(&profile[2], profile[1],
+    action, elems, 0, 0,
+    transmitter_bssid, bss_bssid);
+ }
+
+ if (elems->tim && !elems->parse_error) {
+ const struct ieee80211_tim_ie *tim_ie = elems->tim;
+
+ elems->dtim_period = tim_ie->dtim_period;
+ elems->dtim_count = tim_ie->dtim_count;
+ }
+
+ /* Override DTIM period and count if needed */
+ if (elems->bssid_index &&
+    elems->bssid_index_len >=
+    offsetofend(struct ieee80211_bssid_index, dtim_period))
+ elems->dtim_period = elems->bssid_index->dtim_period;
+
+ if (elems->bssid_index &&
+    elems->bssid_index_len >=
+    offsetofend(struct ieee80211_bssid_index, dtim_count))
+ elems->dtim_count = elems->bssid_index->dtim_count;
+
+ return crc;
+}
+
 void ieee80211_regulatory_limit_wmm_params(struct ieee80211_sub_if_data *sdata,
    struct ieee80211_tx_queue_params
    *qparam, int ac)
--
2.23.0


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[PATCH 15/21][SRU][OEM-OSP1-B] mac80211: indicate support for multiple BSSID

You-Sheng Yang
In reply to this post by You-Sheng Yang
From: Sara Sharon <[hidden email]>

BugLink: https://bugs.launchpad.net/bugs/1845138

Set multi-bssid support flags according to driver support.

Signed-off-by: Sara Sharon <[hidden email]>
Signed-off-by: Johannes Berg <[hidden email]>
(backported from commit caf56338c22f00098bf2acd646b0ddc691c80c24)
Signed-off-by: You-Sheng Yang <[hidden email]>
---
 include/linux/ieee80211.h |  5 +++++
 include/net/mac80211.h    |  7 +++++++
 net/mac80211/debugfs.c    |  4 +++-
 net/mac80211/main.c       | 13 ++++++++++++-
 net/mac80211/mlme.c       | 15 +++++++++++++++
 5 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 583597ed97889..c9946ef2f48f9 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -2667,6 +2667,11 @@ enum ieee80211_tdls_actioncode {
  */
 #define WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING BIT(2)
 
+/* Multiple BSSID capability is set in the 6th bit of 3rd byte of the
+ * @WLAN_EID_EXT_CAPABILITY information element
+ */
+#define WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT BIT(6)
+
 /* TDLS capabilities in the the 4th byte of @WLAN_EID_EXT_CAPABILITY */
 #define WLAN_EXT_CAPA4_TDLS_BUFFER_STA BIT(4)
 #define WLAN_EXT_CAPA4_TDLS_PEER_PSM BIT(5)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 2ba14021668fe..fe6208d601743 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2199,6 +2199,11 @@ struct ieee80211_txq {
  * MMPDUs on station interfaces. This of course requires the driver to use
  * TXQs to start with.
  *
+ * @IEEE80211_HW_SUPPORTS_MULTI_BSSID: Hardware supports multi BSSID
+ *
+ * @IEEE80211_HW_SUPPORTS_ONLY_HE_MULTI_BSSID: Hardware supports multi BSSID
+ * only for HE APs. Applies if @IEEE80211_HW_SUPPORTS_MULTI_BSSID is set.
+ *
  * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
  */
 enum ieee80211_hw_flags {
@@ -2247,6 +2252,8 @@ enum ieee80211_hw_flags {
  IEEE80211_HW_BUFF_MMPDU_TXQ,
  IEEE80211_HW_SUPPORTS_VHT_EXT_NSS_BW,
  IEEE80211_HW_STA_MMPDU_TXQ,
+ IEEE80211_HW_SUPPORTS_MULTI_BSSID,
+ IEEE80211_HW_SUPPORTS_ONLY_HE_MULTI_BSSID,
 
  /* keep last, obviously */
  NUM_IEEE80211_HW_FLAGS
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index 3fe541e358f3c..70b5dac1ce22c 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -3,7 +3,7 @@
  *
  * Copyright 2007 Johannes Berg <[hidden email]>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
- * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018 - 2019 Intel Corporation
  *
  * GPLv2
  *
@@ -218,6 +218,8 @@ static const char *hw_flag_names[] = {
  FLAG(BUFF_MMPDU_TXQ),
  FLAG(SUPPORTS_VHT_EXT_NSS_BW),
  FLAG(STA_MMPDU_TXQ),
+ FLAG(SUPPORTS_MULTI_BSSID),
+ FLAG(SUPPORTS_ONLY_HE_MULTI_BSSID),
 #undef FLAG
 };
 
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 977dea436ee89..debbf12b7f548 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -4,7 +4,7 @@
  * Copyright 2006-2007 Jiri Benc <[hidden email]>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
  * Copyright (C) 2017     Intel Deutschland GmbH
- * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018 - 2019 Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -1104,6 +1104,17 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
  if (ieee80211_hw_check(&local->hw, CHANCTX_STA_CSA))
  local->ext_capa[0] |= WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING;
 
+ /* mac80211 supports multi BSSID, if the driver supports it */
+ if (ieee80211_hw_check(&local->hw, SUPPORTS_MULTI_BSSID)) {
+ local->hw.wiphy->support_mbssid = true;
+ if (ieee80211_hw_check(&local->hw,
+       SUPPORTS_ONLY_HE_MULTI_BSSID))
+ local->hw.wiphy->support_only_he_mbssid = true;
+ else
+ local->ext_capa[2] |=
+ WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT;
+ }
+
  local->hw.wiphy->max_num_csa_counters = IEEE80211_MAX_CSA_COUNTERS_NUM;
 
  result = wiphy_register(local->hw.wiphy);
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 264f857af24b2..a4519e257743a 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -813,6 +813,21 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
  }
  }
 
+ /* Set MBSSID support for HE AP if needed */
+ if (ieee80211_hw_check(&local->hw, SUPPORTS_ONLY_HE_MULTI_BSSID) &&
+    !(ifmgd->flags & IEEE80211_STA_DISABLE_HE) && assoc_data->ie_len) {
+ struct element *elem;
+
+ /* we know it's writable, cast away the const */
+ elem = (void *)cfg80211_find_elem(WLAN_EID_EXT_CAPABILITY,
+  assoc_data->ie,
+  assoc_data->ie_len);
+
+ /* We can probably assume both always true */
+ if (elem && elem->datalen >= 3)
+ elem->data[2] |= WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT;
+ }
+
  /* if present, add any custom IEs that go before HT */
  if (assoc_data->ie_len) {
  static const u8 before_ht[] = {
--
2.23.0


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[PATCH 16/21][SRU][OEM-OSP1-B] cfg80211: fix the IE inheritance of extension IEs

You-Sheng Yang
In reply to this post by You-Sheng Yang
From: Sara Sharon <[hidden email]>

BugLink: https://bugs.launchpad.net/bugs/1845138

Extension IEs have ID 255 followed by extension ID. Current
code is buggy in handling it in two ways:
1. When checking if IE is in the frame, it uses just the ID, which
   for extension elements is too broad.
2. It uses 0xFF to mark copied IEs, which will result in not copying
   extension IEs from the subelement.

Fix both issue.

Signed-off-by: Sara Sharon <[hidden email]>
Signed-off-by: Johannes Berg <[hidden email]>
(cherry picked from commit c17fe043a3b79255c6cbe76aafb594849fac0005)
Signed-off-by: You-Sheng Yang <[hidden email]>
---
 net/wireless/scan.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 387e5f868684d..46ecb10e85fb4 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -216,7 +216,13 @@ static size_t cfg80211_gen_new_ie(const u8 *ie, size_t ielen,
  continue;
  }
 
- tmp = (u8 *)cfg80211_find_ie(tmp_old[0], sub_copy, subie_len);
+ if (tmp_old[0] == WLAN_EID_EXTENSION)
+ tmp = (u8 *)cfg80211_find_ext_ie(tmp_old[2], sub_copy,
+ subie_len);
+ else
+ tmp = (u8 *)cfg80211_find_ie(tmp_old[0], sub_copy,
+     subie_len);
+
  if (!tmp) {
  /* ie in old ie but not in subelement */
  if (tmp_old[0] != WLAN_EID_MULTIPLE_BSSID) {
@@ -226,8 +232,9 @@ static size_t cfg80211_gen_new_ie(const u8 *ie, size_t ielen,
  } else {
  /* ie in transmitting ie also in subelement,
  * copy from subelement and flag the ie in subelement
- * as copied (by setting eid field to 0xff). For
- * vendor ie, compare OUI + type + subType to
+ * as copied (by setting eid field to WLAN_EID_SSID,
+ * which is skipped anyway).
+ * For vendor ie, compare OUI + type + subType to
  * determine if they are the same ie.
  */
  if (tmp_old[0] == WLAN_EID_VENDOR_SPECIFIC) {
@@ -237,7 +244,7 @@ static size_t cfg80211_gen_new_ie(const u8 *ie, size_t ielen,
  */
  memcpy(pos, tmp, tmp[1] + 2);
  pos += tmp[1] + 2;
- tmp[0] = 0xff;
+ tmp[0] = WLAN_EID_SSID;
  } else {
  memcpy(pos, tmp_old, tmp_old[1] + 2);
  pos += tmp_old[1] + 2;
@@ -246,7 +253,7 @@ static size_t cfg80211_gen_new_ie(const u8 *ie, size_t ielen,
  /* copy ie from subelement into new ie */
  memcpy(pos, tmp, tmp[1] + 2);
  pos += tmp[1] + 2;
- tmp[0] = 0xff;
+ tmp[0] = WLAN_EID_SSID;
  }
  }
 
@@ -263,8 +270,7 @@ static size_t cfg80211_gen_new_ie(const u8 *ie, size_t ielen,
  while (tmp_new + tmp_new[1] + 2 - sub_copy <= subie_len) {
  if (!(tmp_new[0] == WLAN_EID_NON_TX_BSSID_CAP ||
       tmp_new[0] == WLAN_EID_SSID ||
-      tmp_new[0] == WLAN_EID_MULTI_BSSID_IDX ||
-      tmp_new[0] == 0xff)) {
+      tmp_new[0] == WLAN_EID_MULTI_BSSID_IDX)) {
  memcpy(pos, tmp_new, tmp_new[1] + 2);
  pos += tmp_new[1] + 2;
  }
--
2.23.0


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[PATCH 17/21][SRU][OEM-OSP1-B] cfg80211: fix memory leak of new_ie

You-Sheng Yang
In reply to this post by You-Sheng Yang
From: Sara Sharon <[hidden email]>

BugLink: https://bugs.launchpad.net/bugs/1845138

new_ie is used as a temporary storage for the generation of
the new elements. However, after copying from it the memory
wasn't freed and leaked. Free it.

Signed-off-by: Sara Sharon <[hidden email]>
Signed-off-by: Johannes Berg <[hidden email]>
(cherry picked from commit bede8d2996475017918364ec3d0d2bc1558659e1)
Signed-off-by: You-Sheng Yang <[hidden email]>
---
 net/wireless/scan.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 46ecb10e85fb4..287518c6caa40 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -1576,10 +1576,8 @@ cfg80211_update_notlisted_nontrans(struct wiphy *wiphy,
  if (!new_ie)
  return;
  new_ies = kzalloc(sizeof(*new_ies) + new_ie_len, gfp);
- if (!new_ies) {
- kfree(new_ie);
- return;
- }
+ if (!new_ies)
+ goto out_free;
 
  pos = new_ie;
 
@@ -1613,6 +1611,9 @@ cfg80211_update_notlisted_nontrans(struct wiphy *wiphy,
  if (old)
  kfree_rcu((struct cfg80211_bss_ies *)old, rcu_head);
  }
+
+out_free:
+ kfree(new_ie);
 }
 
 /* cfg80211_inform_bss_width_frame helper */
--
2.23.0


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[PATCH 18/21][SRU][OEM-OSP1-B] mac80211_hwsim: Declare support for Multi-BSSID

You-Sheng Yang
In reply to this post by You-Sheng Yang
From: Jouni Malinen <[hidden email]>

BugLink: https://bugs.launchpad.net/bugs/1845138

This can be used to test cfg80211 support for Multi-BSSID scan result
parsing.

Signed-off-by: Jouni Malinen <[hidden email]>
Signed-off-by: Johannes Berg <[hidden email]>
(cherry picked from commit 040bda85b5dff5790f6ebe562e0b6ca09c851440)
Signed-off-by: You-Sheng Yang <[hidden email]>
---
 drivers/net/wireless/mac80211_hwsim.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index bb2bf4beed0f4..7d230038e168e 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -2810,6 +2810,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
  ieee80211_hw_set(hw, TDLS_WIDER_BW);
  if (rctbl)
  ieee80211_hw_set(hw, SUPPORTS_RC_TABLE);
+ ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
 
  hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS |
     WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
--
2.23.0


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[PATCH 19/21][SRU][OEM-OSP1-B] cfg80211: add missing kernel-doc for multi-BSSID fields

You-Sheng Yang
In reply to this post by You-Sheng Yang
From: Johannes Berg <[hidden email]>

BugLink: https://bugs.launchpad.net/bugs/1845138

Add the missing kernel-doc for the new multi-BSSID fields
in struct cfg80211_bss.

Signed-off-by: Johannes Berg <[hidden email]>
(cherry picked from commit 851ae31d34063deb1eae49f5d797a12a5557e832)
Signed-off-by: You-Sheng Yang <[hidden email]>
---
 include/net/cfg80211.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 881a5a0f9b2c7..dfa9d3d2162d5 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2007,6 +2007,10 @@ struct cfg80211_bss_ies {
  * a BSS that hides the SSID in its beacon, this points to the BSS struct
  * that holds the beacon data. @beacon_ies is still valid, of course, and
  * points to the same data as hidden_beacon_bss->beacon_ies in that case.
+ * @transmitted_bss: pointer to the transmitted BSS, if this is a
+ * non-transmitted one (multi-BSSID support)
+ * @nontrans_list: list of non-transmitted BSS, if this is a transmitted one
+ * (multi-BSSID support)
  * @signal: signal strength value (type depends on the wiphy's signal_type)
  * @chains: bitmask for filled values in @chain_signal.
  * @chain_signal: per-chain signal strength of last received BSS in dBm.
--
2.23.0


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
12