Skip to contentSkip to conversation

brcmfmac: Add few features in AP mode

PATCH In review Wright Feng 3 participants 9 messages Oct 20, 2020 – Nov 7, 2020 Broadcom BRCM80211 IEEE802.11 wireless drivers

lore
Share & tools
lore
#0 lore raw

v2 cover brcmfmac: Add few features in AP mode

This patch series add support for AP isolation and forwarding mechanism in AP mode.

changes in v2:
- Remove u32 cast from patch 1/4
- Fix sparse warning in patch 3/4
- Remove the macro from patch 3/4
- Change conditional statements in patch 4/4

Jia-Shyr Chuang (1):
brcmfmac: support the forwarding packet

Ting-Ying Li (2):
brcmfmac: don't allow arp/nd offload to be enabled if ap mode exists
brcmfmac: add a variable for packet forwarding condition

Wright Feng (1):
brcmfmac: add change_bss to support AP isolation

 .../broadcom/brcm80211/brcmfmac/cfg80211.c    |  65 +++++++++-
 .../broadcom/brcm80211/brcmfmac/cfg80211.h    |   1 +
 .../broadcom/brcm80211/brcmfmac/core.c        | 117 +++++++++++++++++-
 .../broadcom/brcm80211/brcmfmac/core.h        |  18 ++-
 .../broadcom/brcm80211/brcmfmac/feature.c     |   1 +
 .../broadcom/brcm80211/brcmfmac/feature.h     |   3 +-
 .../broadcom/brcm80211/brcmfmac/msgbuf.c      |  31 ++++-
 7 files changed, 228 insertions(+), 8 deletions(-)
Signature · 1 line
2.25.0
#1 lore raw

PATCH v2 1/4 brcmfmac: add change_bss to support AP isolation

Hostap has a parameter "ap_isolate" which is used to prevent low-level bridging of frames between associated stations in the BSS. Regarding driver side, we add cfg80211 ops method change_bss to support setting AP isolation if firmware has ap_isolate feature.

---
v2: Remove u32 cast

---
 .../broadcom/brcm80211/brcmfmac/cfg80211.c    | 23 +++++++++++++++++++
 .../broadcom/brcm80211/brcmfmac/feature.c     |  1 +
 .../broadcom/brcm80211/brcmfmac/feature.h     |  3 ++-
 3 files changed, 26 insertions(+), 1 deletion(-)
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +23 -0
index a2dbbb977d0c..4d0447784426 100644
@@ -5466,6 +5466,26 @@ static int brcmf_cfg80211_del_pmk(struct wiphy *wiphy, struct net_device *dev,
 	return brcmf_set_pmk(ifp, NULL, 0);
 }
 
+static int
+brcmf_cfg80211_change_bss(struct wiphy *wiphy, struct net_device *dev,
+			  struct bss_parameters *params)
+{
+	struct brcmf_if *ifp;
+	int ret = 0;
+	u32 ap_isolate;
+
+	brcmf_dbg(TRACE, "Enter\n");
+	ifp = netdev_priv(dev);
+	if (params->ap_isolate >= 0) {
+		ap_isolate = params->ap_isolate;
+		ret = brcmf_fil_iovar_int_set(ifp, "ap_isolate", ap_isolate);
+		if (ret < 0)
+			brcmf_err("ap_isolate iovar failed: ret=%d\n", ret);
+	}
+
+	return ret;
+}
+
 static struct cfg80211_ops brcmf_cfg80211_ops = {
 	.add_virtual_intf = brcmf_cfg80211_add_iface,
 	.del_virtual_intf = brcmf_cfg80211_del_iface,
@@ -7540,6 +7560,9 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
 	if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_GTK))
 		ops->set_rekey_data = brcmf_cfg80211_set_rekey_data;
 #endif
+	if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_AP_ISOLATE))
+		ops->change_bss = brcmf_cfg80211_change_bss;
+
 	err = wiphy_register(wiphy);
 	if (err < 0) {
 		bphy_err(drvr, "Could not register wiphy device (%d)\n", err);
drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c +1 -0
index 7c68d9849324..1118b291fb29 100644
@@ -279,6 +279,7 @@ void brcmf_feat_attach(struct brcmf_pub *drvr)
 	brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_RSDB, "rsdb_mode");
 	brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_TDLS, "tdls_enable");
 	brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_MFP, "mfp");
+	brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_AP_ISOLATE, "ap_isolate");
 
 	pfn_mac.version = BRCMF_PFN_MACADDR_CFG_VER;
 	err = brcmf_fil_iovar_data_get(ifp, "pfn_macaddr", &pfn_mac,
drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h +2 -1
index d1f4257af696..cec5a9c4b18c 100644
@@ -51,7 +51,8 @@
 	BRCMF_FEAT_DEF(MONITOR_FMT_HW_RX_HDR) \
 	BRCMF_FEAT_DEF(DOT11H) \
 	BRCMF_FEAT_DEF(SAE) \
-	BRCMF_FEAT_DEF(FWAUTH)
+	BRCMF_FEAT_DEF(FWAUTH) \
+	BRCMF_FEAT_DEF(AP_ISOLATE)
 
 /*
  * Quirks:
Signature · 1 line
2.25.0
maintainer Reviewed-by on v2 1/4
#2 lore raw

Re: [PATCH v2 1/4] brcmfmac: add change_bss to support AP isolation

Quoted 4 lines · Wright Feng

Hostap has a parameter "ap_isolate" which is used to prevent low-level bridging of frames between associated stations in the BSS. Regarding driver side, we add cfg80211 ops method change_bss to support setting AP isolation if firmware has ap_isolate feature.

Quoted 9 lines

---
v2: Remove u32 cast

---
  .../broadcom/brcm80211/brcmfmac/cfg80211.c    | 23 +++++++++++++++++++
  .../broadcom/brcm80211/brcmfmac/feature.c     |  1 +
  .../broadcom/brcm80211/brcmfmac/feature.h     |  3 ++-
  3 files changed, 26 insertions(+), 1 deletion(-)
#3 lore raw

Re: [PATCH v2 1/4] brcmfmac: add change_bss to support AP isolation

In reply to Wright Feng
Quoted 8 lines · Wright Feng

Hostap has a parameter "ap_isolate" which is used to prevent low-level bridging of frames between associated stations in the BSS. Regarding driver side, we add cfg80211 ops method change_bss to support setting AP isolation if firmware has ap_isolate feature.

Dropping as no response to Arend's comment.

4 patches set to Changes Requested.

11845611 [v2,1/4] brcmfmac: add change_bss to support AP isolation 11845613 [v2,2/4] brcmfmac: don't allow arp/nd offload to be enabled if ap mode exists 11845615 [v2,3/4] brcmfmac: support the forwarding packet
11845617 [v2,4/4] brcmfmac: add a variable for packet forwarding condition

Signature · 3 lines
https://patchwork.kernel.org/project/linux-wireless/patch/[email protected]/

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
#4 lore raw

PATCH v2 2/4 brcmfmac: don't allow arp/nd offload to be enabled if ap mode exists

In reply to Wright Feng

From: Ting-Ying Li <[email protected]>

Add a condition to determine whether arp/nd offload enabling request is allowed. If there is any interface acts as ap mode and is operating, then reject the request of arp oflload enabling from cfg80211.

---
 .../broadcom/brcm80211/brcmfmac/cfg80211.c      | 17 ++++++++++++++++-
 .../broadcom/brcm80211/brcmfmac/cfg80211.h      |  1 +
 .../wireless/broadcom/brcm80211/brcmfmac/core.c |  5 +++++
 3 files changed, 22 insertions(+), 1 deletion(-)
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +16 -1
index 4d0447784426..2f24222eb59c 100644
@@ -769,6 +769,21 @@ void brcmf_set_mpc(struct brcmf_if *ifp, int mpc)
 	}
 }
 
+bool brcmf_is_apmode_operating(struct wiphy *wiphy)
+{
+	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct brcmf_cfg80211_vif *vif;
+	bool ret = false;
+
+	list_for_each_entry(vif, &cfg->vif_list, list) {
+		if (brcmf_is_apmode(vif) &&
+		    test_bit(BRCMF_VIF_STATUS_AP_CREATED, &vif->sme_state))
+			ret = true;
+	}
+
+	return ret;
+}
+
 s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
 				struct brcmf_if *ifp, bool aborted,
 				bool fw_abort)
@@ -4990,8 +5005,8 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
 			bphy_err(drvr, "bss_enable config failed %d\n", err);
 	}
 	brcmf_set_mpc(ifp, 1);
-	brcmf_configure_arp_nd_offload(ifp, true);
 	clear_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);
+	brcmf_configure_arp_nd_offload(ifp, true);
 	brcmf_net_setcarrier(ifp, false);
 
 	return err;
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h +1 -0
index 17817cdb5de2..94996574c9c7 100644
@@ -461,5 +461,6 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
 void brcmf_set_mpc(struct brcmf_if *ndev, int mpc);
 void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg);
 void brcmf_cfg80211_free_netdev(struct net_device *ndev);
+bool brcmf_is_apmode_operating(struct wiphy *wiphy);
 
 #endif /* BRCMFMAC_CFG80211_H */
drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +5 -0
index 3dd28f5fef19..043c9cbc6394 100644
@@ -96,6 +96,11 @@ void brcmf_configure_arp_nd_offload(struct brcmf_if *ifp, bool enable)
 	s32 err;
 	u32 mode;
 
+	if (enable && brcmf_is_apmode_operating(ifp->drvr->wiphy)) {
+		brcmf_dbg(TRACE, "Skip ARP/ND offload enable when soft AP is running\n");
+		return;
+	}
+
 	if (enable)
 		mode = BRCMF_ARP_OL_AGENT | BRCMF_ARP_OL_PEER_AUTO_REPLY;
 	else
Signature · 1 line
2.25.0
maintainer Reviewed-by on v2 2/4
#5 lore raw

Re: [PATCH v2 2/4] brcmfmac: don't allow arp/nd offload to be enabled if ap mode exists

Quoted 6 lines · Wright Feng

From: Ting-Ying Li <[email protected]>

Add a condition to determine whether arp/nd offload enabling request is allowed. If there is any interface acts as ap mode and is operating, then reject the request of arp oflload enabling from cfg80211.

Quoted 7 lines
---
  .../broadcom/brcm80211/brcmfmac/cfg80211.c      | 17 ++++++++++++++++-
  .../broadcom/brcm80211/brcmfmac/cfg80211.h      |  1 +
  .../wireless/broadcom/brcm80211/brcmfmac/core.c |  5 +++++
  3 files changed, 22 insertions(+), 1 deletion(-)
#6 lore raw

PATCH v2 3/4 brcmfmac: support the forwarding packet

In reply to Wright Feng

From: Jia-Shyr Chuang <[email protected]>

Support packet forwarding mechanism for some special usages on PCIE, and observed that packet only send BE when pumping iperf with VI. we need to set priority before forwarding packet.

---
v2: Fix sparse warning and remove the macro from the patch

---
 .../broadcom/brcm80211/brcmfmac/cfg80211.c    |  12 +-
 .../broadcom/brcm80211/brcmfmac/core.c        | 112 +++++++++++++++++-
 .../broadcom/brcm80211/brcmfmac/core.h        |  17 ++-
 .../broadcom/brcm80211/brcmfmac/msgbuf.c      |  31 ++++-
 4 files changed, 166 insertions(+), 6 deletions(-)
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +9 -3
index 2f24222eb59c..5e49ac3d82b9 100644
@@ -611,7 +611,7 @@ struct wireless_dev *brcmf_ap_add_vif(struct wiphy *wiphy, const char *name,
 	return ERR_PTR(err);
 }
 
-static bool brcmf_is_apmode(struct brcmf_cfg80211_vif *vif)
+bool brcmf_is_apmode(struct brcmf_cfg80211_vif *vif)
 {
 	enum nl80211_iftype iftype;
 
@@ -4812,7 +4812,6 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
 		err = -EINVAL;
 		goto exit;
 	}
-
 	/* Interface specific setup */
 	if (dev_role == NL80211_IFTYPE_AP) {
 		if ((brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) && (!mbss))
@@ -4892,7 +4891,6 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
 				 err);
 			goto exit;
 		}
-
 		brcmf_dbg(TRACE, "AP mode configuration complete\n");
 	} else if (dev_role == NL80211_IFTYPE_P2P_GO) {
 		err = brcmf_fil_iovar_int_set(ifp, "chanspec", chanspec);
@@ -6086,6 +6084,14 @@ brcmf_notify_connect_status(struct brcmf_if *ifp,
 	}
 
 	if (brcmf_is_apmode(ifp->vif)) {
+		if (e->event_code == BRCMF_E_ASSOC_IND ||
+		    e->event_code == BRCMF_E_REASSOC_IND) {
+			brcmf_findadd_sta(ifp, e->addr);
+		} else if ((e->event_code == BRCMF_E_DISASSOC_IND) ||
+				(e->event_code == BRCMF_E_DEAUTH_IND) ||
+				(e->event_code == BRCMF_E_DEAUTH)) {
+			brcmf_del_sta(ifp, e->addr);
+		}
 		err = brcmf_notify_connect_status_ap(cfg, ndev, e, data);
 	} else if (brcmf_is_linkup(ifp->vif, e)) {
 		brcmf_dbg(CONN, "Linkup\n");
drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +111 -1

121 lines not on this page · raw message

drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h +16 -1
index 5767d665cee5..9ebafe0b2117 100644
@@ -193,6 +193,18 @@ struct brcmf_if {
 	struct in6_addr ipv6_addr_tbl[NDOL_MAX_ENTRIES];
 	u8 ipv6addr_idx;
 	bool fwil_fwerr;
+	struct list_head sta_list;              /* sll of associated stations */
+	spinlock_t sta_list_lock;
+};
+
+struct ether_addr {
+	u8 octet[ETH_ALEN];
+};
+
+struct brcmf_sta {
+	void *ifp;             /* associated brcm_if */
+	struct ether_addr ea;   /* stations ethernet mac address */
+	struct list_head list;  /* link into brcmf_if::sta_list */
 };
 
 int brcmf_netdev_wait_pend8021x(struct brcmf_if *ifp);
@@ -215,5 +227,8 @@ int brcmf_net_mon_attach(struct brcmf_if *ifp);
 void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on);
 int __init brcmf_core_init(void);
 void __exit brcmf_core_exit(void);
-
+void brcmf_del_sta(struct brcmf_if *ifp, const u8 *ea);
+struct brcmf_sta *brcmf_find_sta(struct brcmf_if *ifp, const u8 *ea);
+struct brcmf_sta *brcmf_findadd_sta(struct brcmf_if *ifp, const u8 *ea);
+bool brcmf_is_apmode(struct brcmf_cfg80211_vif *vif);
 #endif /* BRCMFMAC_CORE_H */
drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c +30 -1
index 7c8e08ee8f0f..b98cf5e2d0a8 100644
@@ -1141,7 +1141,8 @@ brcmf_msgbuf_process_rx_complete(struct brcmf_msgbuf *msgbuf, void *buf)
 {
 	struct brcmf_pub *drvr = msgbuf->drvr;
 	struct msgbuf_rx_complete *rx_complete;
-	struct sk_buff *skb;
+	struct sk_buff *skb, *cpskb = NULL;
+	struct ethhdr *eh;
 	u16 data_offset;
 	u16 buflen;
 	u16 flags;
@@ -1190,6 +1191,34 @@ brcmf_msgbuf_process_rx_complete(struct brcmf_msgbuf *msgbuf, void *buf)
 		return;
 	}
 
+	eh = (struct ethhdr *)(skb->data);
+	if (brcmf_is_apmode(ifp->vif)) {
+		skb_set_network_header(skb, sizeof(struct ethhdr));
+		skb->protocol = eh->h_proto;
+		skb->priority = cfg80211_classify8021d(skb, NULL);
+		if (is_unicast_ether_addr(eh->h_dest)) {
+			if (brcmf_find_sta(ifp, eh->h_dest)) {
+				 /* determine the priority */
+				if (skb->priority == 0 || skb->priority > 7) {
+					skb->priority =
+						cfg80211_classify8021d(skb,
+								       NULL);
+				}
+				brcmf_proto_tx_queue_data(ifp->drvr,
+							  ifp->ifidx, skb);
+				return;
+			}
+		} else {
+			cpskb = pskb_copy(skb, GFP_ATOMIC);
+			if (cpskb) {
+				brcmf_proto_tx_queue_data(ifp->drvr,
+							  ifp->ifidx,
+							  cpskb);
+			} else {
+				brcmf_err("Unable to do skb copy\n");
+			}
+		}
+	}
 	skb->protocol = eth_type_trans(skb, ifp->ndev);
 	brcmf_netif_rx(ifp, skb, false);
 }
Signature · 1 line
2.25.0
maintainer
#7 lore raw

Re: [PATCH v2 3/4] brcmfmac: support the forwarding packet

Quoted 5 lines · Wright Feng

From: Jia-Shyr Chuang <[email protected]>

Support packet forwarding mechanism for some special usages on PCIE, and observed that packet only send BE when pumping iperf with VI. we need to set priority before forwarding packet.

I commented on this feature in the previous patch set, but did not see any follow up on that.

https://patchwork.kernel.org/project/linux-wireless/patch/[email protected]/

Regards,
Arend

#8 lore raw

PATCH v2 4/4 brcmfmac: add a variable for packet forwarding condition

In reply to Wright Feng

From: Ting-Ying Li <[email protected]>

When the "ap_isolate" function is not set by the host, host-based packet forwarding will be enabled if the packet forwarding mechanism is not offloaded to the lower layer.

---
v4: Change conditional statements

---
 .../broadcom/brcm80211/brcmfmac/cfg80211.c      | 17 +++++++++++++++--
 .../wireless/broadcom/brcm80211/brcmfmac/core.h |  1 +
 .../broadcom/brcm80211/brcmfmac/msgbuf.c        |  2 +-
 3 files changed, 17 insertions(+), 3 deletions(-)
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +15 -2
index 5e49ac3d82b9..063cbb09d751 100644
@@ -5484,8 +5484,8 @@ brcmf_cfg80211_change_bss(struct wiphy *wiphy, struct net_device *dev,
 			  struct bss_parameters *params)
 {
 	struct brcmf_if *ifp;
-	int ret = 0;
-	u32 ap_isolate;
+	int ret = 0, result = 0;
+	u32 ap_isolate, val;
 
 	brcmf_dbg(TRACE, "Enter\n");
 	ifp = netdev_priv(dev);
@@ -5496,6 +5496,19 @@ brcmf_cfg80211_change_bss(struct wiphy *wiphy, struct net_device *dev,
 			brcmf_err("ap_isolate iovar failed: ret=%d\n", ret);
 	}
 
+	/* Get ap_isolate value from firmware to detemine whether fmac */
+	/* driver enables packet forwarding. */
+	result = brcmf_fil_iovar_int_get(ifp, "ap_isolate", &val);
+	if (result == 0 &&
+	    params->ap_isolate == 0 &&
+	    val == 1) {
+		ifp->fmac_pkt_fwd_en = true;
+	} else {
+		if (result < 0)
+			brcmf_err("get ap_isolate iovar failed: result=%d\n", result);
+		ifp->fmac_pkt_fwd_en = false;
+	}
+
 	return ret;
 }
 
drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h +1 -0
index 9ebafe0b2117..30b29053d133 100644
@@ -195,6 +195,7 @@ struct brcmf_if {
 	bool fwil_fwerr;
 	struct list_head sta_list;              /* sll of associated stations */
 	spinlock_t sta_list_lock;
+	bool fmac_pkt_fwd_en;
 };
 
 struct ether_addr {
drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c +1 -1
index b98cf5e2d0a8..2d7e77097209 100644
@@ -1192,7 +1192,7 @@ brcmf_msgbuf_process_rx_complete(struct brcmf_msgbuf *msgbuf, void *buf)
 	}
 
 	eh = (struct ethhdr *)(skb->data);
-	if (brcmf_is_apmode(ifp->vif)) {
+	if (brcmf_is_apmode(ifp->vif) && ifp->fmac_pkt_fwd_en) {
 		skb_set_network_header(skb, sizeof(struct ethhdr));
 		skb->protocol = eh->h_proto;
 		skb->priority = cfg80211_classify8021d(skb, NULL);
Signature · 1 line
2.25.0