From 36ee9d37b53c933f4dd8f934f8e0273b5e901549 Mon Sep 17 00:00:00 2001 From: Sathishkumar Muruganandam Date: Fri, 8 Jan 2021 00:02:54 +0530 Subject: [PATCH 1/3] mac80211: add dynamic VLAN support on NSS offload NSS requires dynamic AP_VLAN vif ifnum and its corresponding VLAN ID and group key index to configure dynamic VLAN ext VDEV in NSS. Hence mac80211 set_key and sta_state callbacks are modified to advertise AP_VLAN vif when NSS offload is enabled and VLAN ID provided by hostapd in key params is stored to ieee80211_key_conf for the driver. Co-Developed-by: Seevalamuthu Mariappan Signed-off-by: Seevalamuthu Mariappan Signed-off-by: Sathishkumar Muruganandam --- include/net/mac80211.h | 3 +++ net/mac80211/cfg.c | 1 + net/mac80211/driver-ops.c | 4 +++- net/mac80211/driver-ops.h | 4 +++- net/mac80211/key.c | 5 ++++- net/mac80211/tx.c | 4 ++++ 6 files changed, 18 insertions(+), 3 deletions(-) --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1910,6 +1910,8 @@ enum ieee80211_key_flags { * @tx_pn: PN used for TX keys, may be used by the driver as well if it * needs to do software PN assignment by itself (e.g. due to TSO) * @flags: key flags, see &enum ieee80211_key_flags. + * @vlan_id: VLAN ID corresponding to the group key. + * For VLAN interfaces 1-4096, 0 for non-vlan interfaces * @keyidx: the key index (0-3) * @keylen: key material length * @key: key material. For ALG_TKIP the key is encoded as a 256-bit (32 byte) @@ -1928,6 +1930,7 @@ struct ieee80211_key_conf { u8 hw_key_idx; s8 keyidx; u16 flags; + u16 vlan_id; u8 keylen; u8 key[]; }; --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -510,6 +510,7 @@ static int ieee80211_add_key(struct wiph break; case NL80211_IFTYPE_AP: case NL80211_IFTYPE_AP_VLAN: + key->conf.vlan_id = params->vlan_id; /* Keys without a station are used for TX only */ if (sta && test_sta_flag(sta, WLAN_STA_MFP)) key->conf.flags |= IEEE80211_KEY_FLAG_RX_MGMT; --- a/net/mac80211/driver-ops.c +++ b/net/mac80211/driver-ops.c @@ -113,7 +113,11 @@ int drv_sta_state(struct ieee80211_local might_sleep(); - sdata = get_bss_sdata(sdata); + if (!ieee80211_hw_check(&local->hw, SUPPORTS_NSS_OFFLOAD) || + !(old_state == IEEE80211_STA_ASSOC && + new_state == IEEE80211_STA_AUTHORIZED)) + sdata = get_bss_sdata(sdata); + if (!check_sdata_in_driver(sdata)) return -EIO; --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -261,7 +261,9 @@ static inline int drv_set_key(struct iee might_sleep(); - sdata = get_bss_sdata(sdata); + if (!ieee80211_hw_check(&local->hw, SUPPORTS_NSS_OFFLOAD)) + sdata = get_bss_sdata(sdata); + if (!check_sdata_in_driver(sdata)) return -EIO; --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -167,7 +167,8 @@ static int ieee80211_key_enable_hw_accel goto out_unsupported; sdata = key->sdata; - if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN && + !ieee80211_hw_check(&key->local->hw, SUPPORTS_NSS_OFFLOAD)) { /* * The driver doesn't know anything about VLAN interfaces. * Hence, don't send GTKs for VLAN interfaces to the driver. @@ -553,6 +554,8 @@ ieee80211_key_alloc(u32 cipher, int idx, */ key->conf.flags = 0; key->flags = 0; + /* VLAN ID initialised to zero for non-vlan interfaces */ + key->conf.vlan_id = 0; key->conf.cipher = cipher; key->conf.keyidx = idx; --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -4248,8 +4248,11 @@ static void ieee80211_8023_xmit(struct i struct ieee80211_key *key, struct sk_buff *skb) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ethhdr *ehdr = (struct ethhdr *)skb->data; struct ieee80211_local *local = sdata->local; struct tid_ampdu_tx *tid_tx; + unsigned char *ra = ehdr->h_dest; + bool multicast; u8 tid; if (local->ops->wake_tx_queue) { @@ -4258,6 +4261,12 @@ static void ieee80211_8023_xmit(struct i skb_get_hash(skb); } + multicast = is_multicast_ether_addr(ra); + + if (multicast && sdata->vif.type == NL80211_IFTYPE_AP_VLAN && + !atomic_read(&sdata->u.vlan.num_mcast_sta)) + goto out_free; + if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning)) && test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state)) goto out_free;