This patch adds support for passing the multiple bssid config to the kernel when adding an interface. If the BSS is non-transmitting it needs to be indicated. A non-transmitting BSSID will have a parent interface, which needs to be transmitting. The multiple bssid elements are passed as an array. Signed-off-by: John Crispin <john@xxxxxxxxxxx> --- include/net/cfg80211.h | 35 +++++++++++++++++++++++++++++++ include/uapi/linux/nl80211.h | 22 ++++++++++++++++++++ net/wireless/nl80211.c | 40 ++++++++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 541dea0fd571..0b0c730dc8d2 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -470,6 +470,21 @@ struct ieee80211_supported_band { const struct ieee80211_sband_iftype_data *iftype_data; }; +/** + * struct ieee80211_multiple_bssid - AP settings for multi bssid + * + * @index: the index of this AP in the multi bssid group. + * @count: the total number of multi bssid peer APs. + * @parent: a non-transmitted bssid has a transmitted parent + * @non_transmitted: Is this a non-transmitted bssid + */ +struct ieee80211_multiple_bssid { + u8 index; + u8 count; + u32 parent; + bool non_transmitted; +}; + /** * ieee80211_get_sband_iftype_data - return sband data for a given iftype * @sband: the sband to search for the STA on @@ -614,6 +629,7 @@ static inline void wiphy_read_of_freq_limits(struct wiphy *wiphy) * belonging to that MU-MIMO groupID; %NULL if not changed * @vht_mumimo_follow_addr: MU-MIMO follow address, used for monitoring * MU-MIMO packets going to the specified station; %NULL if not changed + * @multiple_bssid: AP settings for multiple bssid */ struct vif_params { u32 flags; @@ -621,6 +637,7 @@ struct vif_params { u8 macaddr[ETH_ALEN]; const u8 *vht_mumimo_groups; const u8 *vht_mumimo_follow_addr; + struct ieee80211_multiple_bssid multiple_bssid; }; /** @@ -998,6 +1015,19 @@ struct cfg80211_crypto_settings { u8 sae_pwd_len; }; +/** + * struct cfg80211_multiple_bssid_data - multiple_bssid data + * @ies: array of extra information element(s) to add into Beacon frames for multiple + * bssid or %NULL + * @len: array of lengths of multiple_bssid.ies in octets + * @cnt: number of entries in multiple_bssid.ies + */ +struct cfg80211_multiple_bssid_data { + u8 *ies[NL80211_MULTIPLE_BSSID_IES_MAX]; + size_t len[NL80211_MULTIPLE_BSSID_IES_MAX]; + int cnt; +}; + /** * struct cfg80211_beacon_data - beacon data * @head: head portion of beacon (before TIM IE) @@ -1024,6 +1054,7 @@ struct cfg80211_crypto_settings { * Token (measurement type 11) * @lci_len: LCI data length * @civicloc_len: Civic location data length + * @multiple_bssid: multiple_bssid data */ struct cfg80211_beacon_data { const u8 *head, *tail; @@ -1042,6 +1073,8 @@ struct cfg80211_beacon_data { size_t probe_resp_len; size_t lci_len; size_t civicloc_len; + + struct cfg80211_multiple_bssid_data multiple_bssid; }; struct mac_address { @@ -1111,6 +1144,7 @@ enum cfg80211_ap_settings_flags { * @he_obss_pd: OBSS Packet Detection settings * @he_bss_color: BSS Color settings * @he_oper: HE operation IE (or %NULL if HE isn't enabled) + * @multiple_bssid: AP settings for multiple bssid */ struct cfg80211_ap_settings { struct cfg80211_chan_def chandef; @@ -1141,6 +1175,7 @@ struct cfg80211_ap_settings { u32 flags; struct ieee80211_he_obss_pd he_obss_pd; struct cfg80211_he_bss_color he_bss_color; + struct ieee80211_multiple_bssid multiple_bssid; }; /** diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index cade02a0e60e..5bc38d53c78c 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -2551,6 +2551,20 @@ enum nl80211_commands { * @NL80211_ATTR_COLOR_CHANGE_ANNOUNCEMENT_C_OFF_PRESP: An array of offsets (u16) to the color * switch counters in the probe response (%NL80211_ATTR_PROBE_RESP). * + * @NL80211_ATTR_MULTIPLE_BSSID_NON_TRANSMITTING: Set the Non-Transmitted flag for this + * BSSIDs beacon. + * + * @NL80211_ATTR_MULTIPLE_BSSID_PARENT: If this is a Non-Transmitted BSSID, define + * the parent (transmitting) interface. + * + * @NL80211_ATTR_MULTIPLE_BSSID_INDEX: The index of this BSS inside the multi bssid + * element. + * + * @NL80211_ATTR_MULTIPLE_BSSID_COUNT: The number of BSSs inside the multi bssid element. + * + * @NL80211_ATTR_MULTIPLE_BSSID_IES: The Elements that describe our multiple BSS group. + * these get passed separately as the kernel might need to split them up for EMA VAP. + * * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use @@ -3039,6 +3053,12 @@ enum nl80211_attrs { NL80211_ATTR_COLOR_CHANGE_ANNOUNCEMENT_COLOR, NL80211_ATTR_COLOR_CHANGE_ANNOUNCEMENT_IES, + NL80211_ATTR_MULTIPLE_BSSID_NON_TRANSMITTING, + NL80211_ATTR_MULTIPLE_BSSID_PARENT, + NL80211_ATTR_MULTIPLE_BSSID_INDEX, + NL80211_ATTR_MULTIPLE_BSSID_COUNT, + NL80211_ATTR_MULTIPLE_BSSID_IES, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -3102,6 +3122,8 @@ enum nl80211_attrs { #define NL80211_CQM_TXE_MAX_INTVL 1800 +#define NL80211_MULTIPLE_BSSID_IES_MAX 8 + /** * enum nl80211_iftype - (virtual) interface types * diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 2f0bae3c6572..4ba7203ad0d2 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -662,6 +662,11 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { [NL80211_ATTR_COLOR_CHANGE_ANNOUNCEMENT_COUNT] = { .type = NLA_U8 }, [NL80211_ATTR_COLOR_CHANGE_ANNOUNCEMENT_COLOR] = { .type = NLA_U8 }, [NL80211_ATTR_COLOR_CHANGE_ANNOUNCEMENT_IES] = NLA_POLICY_NESTED(nl80211_policy), + [NL80211_ATTR_MULTIPLE_BSSID_NON_TRANSMITTING] = { .type = NLA_FLAG }, + [NL80211_ATTR_MULTIPLE_BSSID_PARENT] = { .type = NLA_U32 }, + [NL80211_ATTR_MULTIPLE_BSSID_INDEX] = { .type = NLA_U8 }, + [NL80211_ATTR_MULTIPLE_BSSID_COUNT] = { .type = NLA_U8 }, + [NL80211_ATTR_MULTIPLE_BSSID_IES] = { .type = NLA_NESTED }, }; /* policy for the key attributes */ @@ -3758,6 +3763,14 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) return err; } + if (info->attrs[NL80211_ATTR_MULTIPLE_BSSID_NON_TRANSMITTING]) + params.multiple_bssid.non_transmitted = + nla_get_flag(info->attrs[NL80211_ATTR_MULTIPLE_BSSID_NON_TRANSMITTING]); + + if (info->attrs[NL80211_ATTR_MULTIPLE_BSSID_PARENT]) + params.multiple_bssid.parent = + nla_get_u8(info->attrs[NL80211_ATTR_MULTIPLE_BSSID_PARENT]); + if (!cfg80211_iftype_allowed(&rdev->wiphy, type, params.use_4addr, 0)) return -EOPNOTSUPP; @@ -4670,6 +4683,21 @@ static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev, bcn->ftm_responder = -1; } + if (attrs[NL80211_ATTR_MULTIPLE_BSSID_IES]) { + struct nlattr *nl_ie; + int rem_ie; + + nla_for_each_nested(nl_ie, attrs[NL80211_ATTR_MULTIPLE_BSSID_IES], rem_ie) { + if (bcn->multiple_bssid.cnt > NL80211_MULTIPLE_BSSID_IES_MAX) + return -EINVAL; + if (nla_type(nl_ie) != bcn->multiple_bssid.cnt + 1) + return -EINVAL; + bcn->multiple_bssid.ies[bcn->multiple_bssid.cnt] = nla_data(nl_ie); + bcn->multiple_bssid.len[bcn->multiple_bssid.cnt] = nla_len(nl_ie); + bcn->multiple_bssid.cnt++; + } + } + return 0; } @@ -5032,6 +5060,18 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) goto out; } + if (info->attrs[NL80211_ATTR_MULTIPLE_BSSID_INDEX]) + params.multiple_bssid.index = nla_get_u8( + info->attrs[NL80211_ATTR_MULTIPLE_BSSID_INDEX]); + + if (info->attrs[NL80211_ATTR_MULTIPLE_BSSID_COUNT]) + params.multiple_bssid.count = nla_get_u8( + info->attrs[NL80211_ATTR_MULTIPLE_BSSID_COUNT]); + + if (params.multiple_bssid.non_transmitted && + !info->attrs[NL80211_ATTR_MULTIPLE_BSSID_PARENT]) + return -EOPNOTSUPP; + nl80211_calculate_ap_params(¶ms); if (info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT]) -- 2.25.1