2020-08-12 15:03:11

by John Crispin

[permalink] [raw]
Subject: [PATCH V3 0/9] mac80211: add multiple bssid / EMA

This series addss multiple bssid and EMA beacons.

The V3 series has a lot of changes to V2. The biggest being the added
support for EMA. As we might have HW that can offload this we need to
pass the multiple bssid elements to the kernel. This gives us a lot of
flexibility for supporting different hardware.

John Crispin (9):
nl80211: add basic multiple bssid support
mac80211: add multiple bssid support to interface handling
mac80211: add multiple bssid support to beacon handling
mac80211: add multiple bssid/ema support to bcn templating
ath11k: add a struct to pass parameters into ath11k_wmi_vdev_up
ath11k: add the multiple bssid WMI commands
ath11k: add multiple bssid support to device creation
ath11k: add EMA beacon support
ath11k: set the multiple bssid hw flags and capabilities

drivers/net/wireless/ath/ath11k/mac.c | 83 ++++++++++++++++---
drivers/net/wireless/ath/ath11k/wmi.c | 20 +++--
drivers/net/wireless/ath/ath11k/wmi.h | 22 ++++-
include/net/cfg80211.h | 35 ++++++++
include/net/mac80211.h | 42 +++++++++-
include/uapi/linux/nl80211.h | 22 +++++
net/mac80211/cfg.c | 113 +++++++++++++++++++++++++-
net/mac80211/debugfs.c | 1 +
net/mac80211/ieee80211_i.h | 2 +
net/mac80211/iface.c | 7 ++
net/mac80211/tx.c | 49 ++++++++++-
net/wireless/nl80211.c | 40 +++++++++
12 files changed, 408 insertions(+), 28 deletions(-)

--
2.25.1


2020-08-12 15:04:09

by John Crispin

[permalink] [raw]
Subject: [PATCH V3 2/9] mac80211: add multiple bssid support to interface handling

When bringing up multi bssid APs we need to track the parent-child relation
of non-transmitting and transmitting VAPs. This patch checks the above by
using a linked list to track the relations. The patch also ensures that
when a non-transmitting interface is closed the transmitting one is also
closed.

Signed-off-by: John Crispin <[email protected]>
---
include/net/mac80211.h | 13 +++++++++-
net/mac80211/cfg.c | 54 ++++++++++++++++++++++++++++++++++++++++++
net/mac80211/debugfs.c | 1 +
net/mac80211/iface.c | 7 ++++++
4 files changed, 74 insertions(+), 1 deletion(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index f0ae718633d2..b409a5f1026c 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1649,6 +1649,9 @@ enum ieee80211_vif_flags {
* write-protected by sdata_lock and local->mtx so holding either is fine
* for read access.
* @cca_color: the color that we will have after the change.
+ * @multiple_bssid.parent: a non-transmitted bssid has a transmitted parent.
+ * @multiple_bssid.list: linked list for tracking parent - child relations.
+ * @multiple_bssid.non_transmitted: Is this a non-transmitted bssi
*/
struct ieee80211_vif {
enum nl80211_iftype type;
@@ -1675,6 +1678,11 @@ struct ieee80211_vif {
bool rx_mcast_action_reg;

bool txqs_stopped[IEEE80211_NUM_ACS];
+ struct {
+ struct ieee80211_vif *parent;
+ struct list_head list;
+ bool non_transmitted;
+ } multiple_bssid;

bool cca_active;
u8 cca_color;
@@ -2326,7 +2334,7 @@ struct ieee80211_txq {
* @IEEE80211_HW_TX_STATUS_NO_AMPDU_LEN: Driver does not report accurate A-MPDU
* length in tx status information
*
- * @IEEE80211_HW_SUPPORTS_MULTI_BSSID: Hardware supports multi BSSID
+ * @IEEE80211_HW_SUPPORTS_MULTI_BSSID: Hardware supports multi BSSID in STA mode
*
* @IEEE80211_HW_SUPPORTS_ONLY_HE_MULTI_BSSID: Hardware supports multi BSSID
* only for HE APs. Applies if @IEEE80211_HW_SUPPORTS_MULTI_BSSID is set.
@@ -2335,6 +2343,8 @@ struct ieee80211_txq {
* aggregating MPDUs with the same keyid, allowing mac80211 to keep Tx
* A-MPDU sessions active while rekeying with Extended Key ID.
*
+ * @IEEE80211_HW_SUPPORTS_MULTI_BSSID_AP: Hardware supports multi BSSID in AP mode
+ *
* @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
*/
enum ieee80211_hw_flags {
@@ -2387,6 +2397,7 @@ enum ieee80211_hw_flags {
IEEE80211_HW_SUPPORTS_MULTI_BSSID,
IEEE80211_HW_SUPPORTS_ONLY_HE_MULTI_BSSID,
IEEE80211_HW_AMPDU_KEYBORDER_SUPPORT,
+ IEEE80211_HW_SUPPORTS_MULTI_BSSID_AP,

/* keep last, obviously */
NUM_IEEE80211_HW_FLAGS
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 37a218b89c9a..50a219d8a2cc 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -111,6 +111,36 @@ static int ieee80211_set_mon_options(struct ieee80211_sub_if_data *sdata,
return 0;
}

+static int ieee80211_set_multiple_bssid_options(struct ieee80211_sub_if_data *sdata,
+ struct vif_params *params)
+{
+ struct ieee80211_local *local = sdata->local;
+ struct wiphy *wiphy = local->hw.wiphy;
+ struct net_device *parent;
+ struct ieee80211_sub_if_data *psdata;
+
+ if (!ieee80211_hw_check(&local->hw, SUPPORTS_MULTI_BSSID_AP))
+ return 0;
+
+ if (params->multiple_bssid.non_transmitted) {
+ parent = __dev_get_by_index(wiphy_net(wiphy),
+ params->multiple_bssid.parent);
+ if (!parent || !parent->ieee80211_ptr)
+ return -EINVAL;
+ psdata = IEEE80211_WDEV_TO_SUB_IF(parent->ieee80211_ptr);
+ if (psdata->vif.multiple_bssid.non_transmitted)
+ return -EINVAL;
+ sdata->vif.multiple_bssid.parent = &psdata->vif;
+ list_add(&sdata->vif.multiple_bssid.list,
+ &psdata->vif.multiple_bssid.list);
+ sdata->vif.multiple_bssid.non_transmitted = true;
+ } else {
+ INIT_LIST_HEAD(&sdata->vif.multiple_bssid.list);
+ }
+
+ return 0;
+}
+
static struct wireless_dev *ieee80211_add_iface(struct wiphy *wiphy,
const char *name,
unsigned char name_assign_type,
@@ -136,11 +166,35 @@ static struct wireless_dev *ieee80211_add_iface(struct wiphy *wiphy,
}
}

+ if (type == NL80211_IFTYPE_AP) {
+ err = ieee80211_set_multiple_bssid_options(sdata, params);
+ if (err) {
+ ieee80211_if_remove(sdata);
+ return NULL;
+ }
+ }
+
return wdev;
}

static int ieee80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev)
{
+ struct ieee80211_sub_if_data *sdata;
+ struct ieee80211_vif *child, *tmp;
+
+ sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
+ if (sdata->vif.type == NL80211_IFTYPE_AP) {
+ if (!sdata->vif.multiple_bssid.non_transmitted) {
+ if (!list_empty(&sdata->vif.multiple_bssid.list))
+ list_for_each_entry_safe(child, tmp,
+ &sdata->vif.multiple_bssid.list,
+ multiple_bssid.list)
+ dev_close(vif_to_sdata(child)->wdev.netdev);
+ } else {
+ list_del(&sdata->vif.multiple_bssid.list);
+ }
+ }
+
ieee80211_if_remove(IEEE80211_WDEV_TO_SUB_IF(wdev));

return 0;
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index 54080290d6e2..5d5c9185755a 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -408,6 +408,7 @@ static const char *hw_flag_names[] = {
FLAG(SUPPORTS_MULTI_BSSID),
FLAG(SUPPORTS_ONLY_HE_MULTI_BSSID),
FLAG(AMPDU_KEYBORDER_SUPPORT),
+ FLAG(SUPPORTS_MULTI_BSSID_AP),
#undef FLAG
};

diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 8060cdc102d4..e6397d0c788d 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -810,6 +810,13 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
bool cancel_scan;
struct cfg80211_nan_func *func;

+ if (sdata->vif.type == NL80211_IFTYPE_AP &&
+ sdata->vif.multiple_bssid.non_transmitted)
+ /* make sure the parent is already down */
+ if (sdata->vif.multiple_bssid.parent &&
+ ieee80211_sdata_running(vif_to_sdata(sdata->vif.multiple_bssid.parent)))
+ dev_close(vif_to_sdata(sdata->vif.multiple_bssid.parent)->wdev.netdev);
+
clear_bit(SDATA_STATE_RUNNING, &sdata->state);

cancel_scan = rcu_access_pointer(local->scan_sdata) == sdata;
--
2.25.1

2020-08-12 15:04:44

by John Crispin

[permalink] [raw]
Subject: [PATCH V3 7/9] ath11k: add multiple bssid support to device creation

We need to pass info such as parent device, bssid count/index and
(non-)transmit mode information to the FW when we create a new vdev.

Signed-off-by: John Crispin <[email protected]>
---
drivers/net/wireless/ath/ath11k/mac.c | 22 ++++++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index 2e4f1966da21..08e7f4ac8a26 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -4269,17 +4269,30 @@ static void ath11k_mac_op_stop(struct ieee80211_hw *hw)
atomic_set(&ar->num_pending_mgmt_tx, 0);
}

-static void
+static int
ath11k_mac_setup_vdev_create_params(struct ath11k_vif *arvif,
struct vdev_create_params *params)
{
struct ath11k *ar = arvif->ar;
+ struct ieee80211_vif *parent;
struct ath11k_pdev *pdev = ar->pdev;

params->if_id = arvif->vdev_id;
params->type = arvif->vdev_type;
params->subtype = arvif->vdev_subtype;
params->pdev_id = pdev->pdev_id;
+ params->vdevid_trans = 0;
+ if (arvif->vif->multiple_bssid.non_transmitted) {
+ params->flags = WMI_HOST_VDEV_FLAGS_NON_TRANSMIT_AP;
+ parent = arvif->vif->multiple_bssid.parent;
+ if (!parent)
+ return -ENOENT;
+ if (ar->hw->wiphy != ieee80211_vif_to_wdev(parent)->wiphy)
+ return -EINVAL;
+ params->vdevid_trans = ath11k_vif_to_arvif(parent)->vdev_id;
+ } else {
+ params->flags = WMI_HOST_VDEV_FLAGS_TRANSMIT_AP;
+ }

if (pdev->cap.supported_bands & WMI_HOST_WLAN_2G_CAP) {
params->chains[NL80211_BAND_2GHZ].tx = ar->num_tx_chains;
@@ -4294,6 +4307,7 @@ ath11k_mac_setup_vdev_create_params(struct ath11k_vif *arvif,
params->chains[NL80211_BAND_6GHZ].tx = ar->num_tx_chains;
params->chains[NL80211_BAND_6GHZ].rx = ar->num_rx_chains;
}
+ return 0;
}

static u32
@@ -4443,7 +4457,11 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
for (i = 0; i < ARRAY_SIZE(vif->hw_queue); i++)
vif->hw_queue[i] = i % (ATH11K_HW_MAX_QUEUES - 1);

- ath11k_mac_setup_vdev_create_params(arvif, &vdev_param);
+ ret = ath11k_mac_setup_vdev_create_params(arvif, &vdev_param);
+ if (ret) {
+ ath11k_warn(ab, "failed to prepare vdev %d\n", ret);
+ goto err;
+ }

ret = ath11k_wmi_vdev_create(ar, vif->addr, &vdev_param);
if (ret) {
--
2.25.1

2020-08-12 15:04:44

by John Crispin

[permalink] [raw]
Subject: [PATCH V3 6/9] ath11k: add the multiple bssid WMI commands

Add the code to pass the BSS specific multiple bssid info to the FW.

Signed-off-by: John Crispin <[email protected]>
---
drivers/net/wireless/ath/ath11k/wmi.c | 3 +++
drivers/net/wireless/ath/ath11k/wmi.h | 10 ++++++++++
2 files changed, 13 insertions(+)

diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c
index 04ef73d1f032..ffe8d7b1320b 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.c
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
@@ -641,6 +641,8 @@ int ath11k_wmi_vdev_create(struct ath11k *ar, u8 *macaddr,
cmd->vdev_subtype = param->subtype;
cmd->num_cfg_txrx_streams = WMI_NUM_SUPPORTED_BAND_MAX;
cmd->pdev_id = param->pdev_id;
+ cmd->flags = param->flags;
+ cmd->vdevid_trans = param->vdevid_trans;
ether_addr_copy(cmd->vdev_macaddr.addr, macaddr);

ptr = skb->data + sizeof(*cmd);
@@ -1603,6 +1605,7 @@ int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id,
cmd->csa_switch_count_offset = offs->cntdwn_counter_offs[0];
cmd->ext_csa_switch_count_offset = offs->cntdwn_counter_offs[1];
cmd->buf_len = bcn->len;
+ cmd->mbssid_ie_offset = offs->multiple_bssid_offset;

ptr = skb->data + sizeof(*cmd);

diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h
index a2d81abf6356..ad741add1ebe 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.h
+++ b/drivers/net/wireless/ath/ath11k/wmi.h
@@ -119,6 +119,12 @@ enum {
WMI_HOST_WLAN_2G_5G_CAP = 0x3,
};

+enum {
+ WMI_HOST_VDEV_FLAGS_NON_MBSSID_AP = 1,
+ WMI_HOST_VDEV_FLAGS_TRANSMIT_AP = 2,
+ WMI_HOST_VDEV_FLAGS_NON_TRANSMIT_AP = 4,
+};
+
/*
* wmi command groups.
*/
@@ -2456,6 +2462,8 @@ struct vdev_create_params {
u8 rx;
} chains[NUM_NL80211_BANDS];
u32 pdev_id;
+ u32 flags;
+ u32 vdevid_trans;
};

struct wmi_vdev_create_cmd {
@@ -2466,6 +2474,8 @@ struct wmi_vdev_create_cmd {
struct wmi_mac_addr vdev_macaddr;
u32 num_cfg_txrx_streams;
u32 pdev_id;
+ u32 flags;
+ u32 vdevid_trans;
} __packed;

struct wmi_vdev_txrx_streams {
--
2.25.1

2020-08-27 13:06:40

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH V3 2/9] mac80211: add multiple bssid support to interface handling


> + struct {
> + struct ieee80211_vif *parent;
> + struct list_head list;

Is there a lot of value in having a separate list, vs. iterating all
interfaces and checking the parent pointer?

And exposing the list to the driver seems like a bad idea anyway, they
can't really get locking right.

(to be continued, mail client is acting up)

johannes

2020-08-27 14:58:45

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH V3 2/9] mac80211: add multiple bssid support to interface handling


> + struct {
> + struct ieee80211_vif *parent;
> + struct list_head list;
> + bool non_transmitted;
> + } multiple_bssid;

Oh, and also - surely parent isn't set for the transmitted BSSID, so the
bool non_transmitted is redundant? It's basically the same as !!parent?

Which also applies at the cfg80211 level.

> +static int ieee80211_set_multiple_bssid_options(struct ieee80211_sub_if_data *sdata,
> + struct vif_params *params)
> +{
> + struct ieee80211_local *local = sdata->local;
> + struct wiphy *wiphy = local->hw.wiphy;
> + struct net_device *parent;
> + struct ieee80211_sub_if_data *psdata;
> +
> + if (!ieee80211_hw_check(&local->hw, SUPPORTS_MULTI_BSSID_AP))
> + return 0;

That was probably meant to be an error? Otherwise the function can be
void.

> +++ b/net/mac80211/iface.c
> @@ -810,6 +810,13 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
> bool cancel_scan;
> struct cfg80211_nan_func *func;
>
> + if (sdata->vif.type == NL80211_IFTYPE_AP &&
> + sdata->vif.multiple_bssid.non_transmitted)
> + /* make sure the parent is already down */
> + if (sdata->vif.multiple_bssid.parent &&
> + ieee80211_sdata_running(vif_to_sdata(sdata->vif.multiple_bssid.parent)))
> + dev_close(vif_to_sdata(sdata->vif.multiple_bssid.parent)->wdev.netdev);
> +
>

This is nice but somewhere you also need to actually NULL the pointer.
As it is now, it seems you could set up two interfaces, say

wlan_nontx
wlan_tx

then ifup both, then delete wlan_tx (forcing wlan_nontx down) and then
set wlan_nontx back up and back down or whatever, but the parent pointer
wasn't cleared so ... bad things will happen?

Maybe this stuff could even happen at the cfg80211 level? Might be
useful for others too.

johannes

2020-10-08 00:48:10

by Pradeep Kumar Chitrapu

[permalink] [raw]
Subject: Re: [PATCH V3 2/9] mac80211: add multiple bssid support to interface handling

>
> static int ieee80211_del_iface(struct wiphy *wiphy, struct
> wireless_dev *wdev)
> {
> + struct ieee80211_sub_if_data *sdata;
> + struct ieee80211_vif *child, *tmp;
> +
> + sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
> + if (sdata->vif.type == NL80211_IFTYPE_AP) {
Hi John, Observed a NULL ptr dereference error here..

Thanks
Pradeep

2020-10-08 08:08:11

by John Crispin

[permalink] [raw]
Subject: Re: [PATCH V3 2/9] mac80211: add multiple bssid support to interface handling


On 08.10.20 02:33, Pradeep Kumar Chitrapu wrote:
>>
>>  static int ieee80211_del_iface(struct wiphy *wiphy, struct
>> wireless_dev *wdev)
>>  {
>> +    struct ieee80211_sub_if_data *sdata;
>> +    struct ieee80211_vif *child, *tmp;
>> +
>> +    sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
>> +    if (sdata->vif.type == NL80211_IFTYPE_AP) {
> Hi John, Observed a NULL ptr dereference error here..
>
> Thanks
> Pradeep


how did you trigger it ?

    John

2020-10-08 18:41:19

by Pradeep Kumar Chitrapu

[permalink] [raw]
Subject: Re: [PATCH V3 2/9] mac80211: add multiple bssid support to interface handling

On 2020-10-08 01:06, John Crispin wrote:
> On 08.10.20 02:33, Pradeep Kumar Chitrapu wrote:
>>>
>>>  static int ieee80211_del_iface(struct wiphy *wiphy, struct
>>> wireless_dev *wdev)
>>>  {
>>> +    struct ieee80211_sub_if_data *sdata;
>>> +    struct ieee80211_vif *child, *tmp;
>>> +
>>> +    sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
>>> +    if (sdata->vif.type == NL80211_IFTYPE_AP) {
>> Hi John, Observed a NULL ptr dereference error here..
>>
>> Thanks
>> Pradeep
>
>
> how did you trigger it ?
>
>     John
Hi

Deleted the interface and did rmmod and insmod of cfg80211/mac80211/ath
modules.

[ 883.565933] Unable to handle kernel NULL pointer dereference at
virtual address 00000000
[ 883.565970] pgd = b311c000
[ 883.573357] [00000000] *pgd=00000000
[ 883.579021] Internal error: Oops: 5 [#1] PREEMPT SMP ARM
[ 883.848257] task: bd1ac600 ti: b027a000 task.ti: b027a000
[ 883.852904] PC is at ieee80211_del_iface+0x34/0x90 [mac80211]
[ 883.858333] LR is at extack_doit+0x20/0x6c [compat]
[ 884.092936] [<c751fbd8>] (ieee80211_del_iface [mac80211]) from
[<7f56181c>] (extack_doit+0x20/0x6c [compat])
[ 884.100991] [<7f56181c>] (extack_doit [compat]) from [<8076a340>]
(genl_rcv_msg+0x27c/0x300)
[ 884.110854] [<8076a340>] (genl_rcv_msg) from [<807696c0>]
(netlink_rcv_skb+0x58/0xb4)

Thanks
Pradeep

2020-10-08 21:23:45

by John Crispin

[permalink] [raw]
Subject: Re: [PATCH V3 2/9] mac80211: add multiple bssid support to interface handling


On 08.10.20 19:21, Pradeep Kumar Chitrapu wrote:
> On 2020-10-08 01:06, John Crispin wrote:
>> On 08.10.20 02:33, Pradeep Kumar Chitrapu wrote:
>>>>
>>>>  static int ieee80211_del_iface(struct wiphy *wiphy, struct
>>>> wireless_dev *wdev)
>>>>  {
>>>> +    struct ieee80211_sub_if_data *sdata;
>>>> +    struct ieee80211_vif *child, *tmp;
>>>> +
>>>> +    sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
>>>> +    if (sdata->vif.type == NL80211_IFTYPE_AP) {
>>> Hi John, Observed a NULL ptr dereference error here..
>>>
>>> Thanks
>>> Pradeep
>>
>>
>> how did you trigger it ?
>>
>>     John
> Hi
>
> Deleted the interface and did rmmod and insmod of
> cfg80211/mac80211/ath modules.
>
> [  883.565933] Unable to handle kernel NULL pointer dereference at
> virtual address 00000000
> [  883.565970] pgd = b311c000
> [  883.573357] [00000000] *pgd=00000000
> [  883.579021] Internal error: Oops: 5 [#1] PREEMPT SMP ARM
> [  883.848257] task: bd1ac600 ti: b027a000 task.ti: b027a000
> [  883.852904] PC is at ieee80211_del_iface+0x34/0x90 [mac80211]
> [  883.858333] LR is at extack_doit+0x20/0x6c [compat]
> [  884.092936] [<c751fbd8>] (ieee80211_del_iface [mac80211]) from
> [<7f56181c>] (extack_doit+0x20/0x6c [compat])
> [  884.100991] [<7f56181c>] (extack_doit [compat]) from [<8076a340>]
> (genl_rcv_msg+0x27c/0x300)
> [  884.110854] [<8076a340>] (genl_rcv_msg) from [<807696c0>]
> (netlink_rcv_skb+0x58/0xb4)
>
> Thanks
> Pradeep
>
last I tested rmmod/insmod will always crash the kernel when using ath11k

however i'll ass !NULL guard in the next series

    John