diff mbox

[V3,2/2] brcmfmac: handle monitor mode marked msgbuf packets

Message ID 20180619154809.25698-3-zajec5@gmail.com (mailing list archive)
State Superseded
Delegated to: Kalle Valo
Headers show

Commit Message

Rafał Miłecki June 19, 2018, 3:48 p.m. UTC
From: Rafał Miłecki <rafal@milecki.pl>

New Broadcom firmwares mark monitor mode packets using a newly defined
bit in the flags field. Use it to filter them out and pass to the
monitor interface. These defines were found in bcmmsgbuf.h from SDK.

As not every firmware generates radiotap header this commit introduces
BRCMF_FEAT_MONITOR_FMT_RADIOTAP flag. It has to be has based on firmware
capabilities. If not present brcmf_netif_mon_rx() will assume packet is
a raw 802.11 frame and will prepend it with an empty radiotap header.

This new code is limited to the msgbuf protocol at this point. Adding
support for SDIO/USB devices will require some extra work (possibly a
new firmware release).

Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
---
V2: Use cpu_to_le16 when setting it_len
V3: Update TODO comments
    Rename flag (after adding MONITOR)
    Update commit message
---
 .../wireless/broadcom/brcm80211/brcmfmac/core.c    | 25 ++++++++++++++++++++++
 .../wireless/broadcom/brcm80211/brcmfmac/core.h    |  2 ++
 .../wireless/broadcom/brcm80211/brcmfmac/feature.h |  4 +++-
 .../wireless/broadcom/brcm80211/brcmfmac/msgbuf.c  | 17 +++++++++++++++
 4 files changed, 47 insertions(+), 1 deletion(-)

Comments

Arend van Spriel June 19, 2018, 7:35 p.m. UTC | #1
On 6/19/2018 5:48 PM, Rafał Miłecki wrote:
> From: Rafał Miłecki <rafal@milecki.pl>
>
> New Broadcom firmwares mark monitor mode packets using a newly defined
> bit in the flags field. Use it to filter them out and pass to the
> monitor interface. These defines were found in bcmmsgbuf.h from SDK.
>
> As not every firmware generates radiotap header this commit introduces
> BRCMF_FEAT_MONITOR_FMT_RADIOTAP flag. It has to be has based on firmware
> capabilities. If not present brcmf_netif_mon_rx() will assume packet is
> a raw 802.11 frame and will prepend it with an empty radiotap header.
>
> This new code is limited to the msgbuf protocol at this point. Adding
> support for SDIO/USB devices will require some extra work (possibly a
> new firmware release).

Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
> Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
> ---
> V2: Use cpu_to_le16 when setting it_len
> V3: Update TODO comments
>      Rename flag (after adding MONITOR)
>      Update commit message
> ---
>   .../wireless/broadcom/brcm80211/brcmfmac/core.c    | 25 ++++++++++++++++++++++
>   .../wireless/broadcom/brcm80211/brcmfmac/core.h    |  2 ++
>   .../wireless/broadcom/brcm80211/brcmfmac/feature.h |  4 +++-
>   .../wireless/broadcom/brcm80211/brcmfmac/msgbuf.c  | 17 +++++++++++++++
>   4 files changed, 47 insertions(+), 1 deletion(-)
Dan Carpenter June 20, 2018, 9:27 a.m. UTC | #2
Hi Rafał,

I love your patch! Perhaps something to improve:

[auto build test WARNING on wireless-drivers-next/master]
[also build test WARNING on v4.18-rc1 next-20180619]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Rafa-Mi-ecki/brcmfmac-detect-firmware-support-for-monitor-interface/20180620-012610
base:   https://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next.git master

smatch warnings:
drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:1166 brcmf_msgbuf_process_rx_complete() error: we previously assumed 'ifp' could be null (see line 1161)

# https://github.com/0day-ci/linux/commit/71f840a490aca9a2d4e9609641a929c6936c20e2
git remote add linux-review https://github.com/0day-ci/linux
git remote update linux-review
git checkout 71f840a490aca9a2d4e9609641a929c6936c20e2
vim +/ifp +1166 drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c

9a1bb6025 drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c          Hante Meuleman   2014-07-30  1124  
9a1bb6025 drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c          Hante Meuleman   2014-07-30  1125  
9a1bb6025 drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c          Hante Meuleman   2014-07-30  1126  static void
9a1bb6025 drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c          Hante Meuleman   2014-07-30  1127  brcmf_msgbuf_process_rx_complete(struct brcmf_msgbuf *msgbuf, void *buf)
9a1bb6025 drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c          Hante Meuleman   2014-07-30  1128  {
9a1bb6025 drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c          Hante Meuleman   2014-07-30  1129  	struct msgbuf_rx_complete *rx_complete;
9a1bb6025 drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c          Hante Meuleman   2014-07-30  1130  	struct sk_buff *skb;
9a1bb6025 drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c          Hante Meuleman   2014-07-30  1131  	u16 data_offset;
9a1bb6025 drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c          Hante Meuleman   2014-07-30  1132  	u16 buflen;
71f840a49 drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c Rafał Miłecki    2018-06-19  1133  	u16 flags;
9a1bb6025 drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c          Hante Meuleman   2014-07-30  1134  	u32 idx;
c56caa9db drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c Franky Lin       2016-04-11  1135  	struct brcmf_if *ifp;
9a1bb6025 drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c          Hante Meuleman   2014-07-30  1136  
9a1bb6025 drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c          Hante Meuleman   2014-07-30  1137  	brcmf_msgbuf_update_rxbufpost_count(msgbuf, 1);
9a1bb6025 drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c          Hante Meuleman   2014-07-30  1138  
9a1bb6025 drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c          Hante Meuleman   2014-07-30  1139  	rx_complete = (struct msgbuf_rx_complete *)buf;
9a1bb6025 drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c          Hante Meuleman   2014-07-30  1140  	data_offset = le16_to_cpu(rx_complete->data_offset);
9a1bb6025 drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c          Hante Meuleman   2014-07-30  1141  	buflen = le16_to_cpu(rx_complete->data_len);
9a1bb6025 drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c          Hante Meuleman   2014-07-30  1142  	idx = le32_to_cpu(rx_complete->msg.request_id);
71f840a49 drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c Rafał Miłecki    2018-06-19  1143  	flags = le16_to_cpu(rx_complete->flags);
9a1bb6025 drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c          Hante Meuleman   2014-07-30  1144  
9a1bb6025 drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c          Hante Meuleman   2014-07-30  1145  	skb = brcmf_msgbuf_get_pktid(msgbuf->drvr->bus_if->dev,
9a1bb6025 drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c          Hante Meuleman   2014-07-30  1146  				     msgbuf->rx_pktids, idx);
7d072b404 drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c          Arend van Spriel 2015-05-26  1147  	if (!skb)
7d072b404 drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c          Arend van Spriel 2015-05-26  1148  		return;
9a1bb6025 drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c          Hante Meuleman   2014-07-30  1149  
9a1bb6025 drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c          Hante Meuleman   2014-07-30  1150  	if (data_offset)
9a1bb6025 drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c          Hante Meuleman   2014-07-30  1151  		skb_pull(skb, data_offset);
9a1bb6025 drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c          Hante Meuleman   2014-07-30  1152  	else if (msgbuf->rx_dataoffset)
9a1bb6025 drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c          Hante Meuleman   2014-07-30  1153  		skb_pull(skb, msgbuf->rx_dataoffset);
9a1bb6025 drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c          Hante Meuleman   2014-07-30  1154  
9a1bb6025 drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c          Hante Meuleman   2014-07-30  1155  	skb_trim(skb, buflen);
9a1bb6025 drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c          Hante Meuleman   2014-07-30  1156  
71f840a49 drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c Rafał Miłecki    2018-06-19  1157  	if ((flags & BRCMF_MSGBUF_PKT_FLAGS_FRAME_MASK) ==
71f840a49 drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c Rafał Miłecki    2018-06-19  1158  	    BRCMF_MSGBUF_PKT_FLAGS_FRAME_802_11) {
71f840a49 drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c Rafał Miłecki    2018-06-19  1159  		ifp = msgbuf->drvr->mon_if;
71f840a49 drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c Rafał Miłecki    2018-06-19  1160  
71f840a49 drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c Rafał Miłecki    2018-06-19 @1161  		if (!ifp) {
71f840a49 drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c Rafał Miłecki    2018-06-19  1162  			brcmf_err("Received unexpected monitor pkt\n");
71f840a49 drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c Rafał Miłecki    2018-06-19  1163  			brcmu_pkt_buf_free_skb(skb);
71f840a49 drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c Rafał Miłecki    2018-06-19  1164  		}
71f840a49 drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c Rafał Miłecki    2018-06-19  1165  
71f840a49 drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c Rafał Miłecki    2018-06-19 @1166  		brcmf_netif_mon_rx(ifp, skb);
71f840a49 drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c Rafał Miłecki    2018-06-19  1167  		return;
71f840a49 drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c Rafał Miłecki    2018-06-19  1168  	}
71f840a49 drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c Rafał Miłecki    2018-06-19  1169  
c56caa9db drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c Franky Lin       2016-04-11  1170  	ifp = brcmf_get_ifp(msgbuf->drvr, rx_complete->msg.ifidx);
c56caa9db drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c Franky Lin       2016-04-11  1171  	if (!ifp || !ifp->ndev) {
c56caa9db drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c Franky Lin       2016-04-11  1172  		brcmf_err("Received pkt for invalid ifidx %d\n",
c56caa9db drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c Franky Lin       2016-04-11  1173  			  rx_complete->msg.ifidx);
c56caa9db drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c Franky Lin       2016-04-11  1174  		brcmu_pkt_buf_free_skb(skb);
c56caa9db drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c Franky Lin       2016-04-11  1175  		return;
c56caa9db drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c Franky Lin       2016-04-11  1176  	}
31143e293 drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c Franky Lin       2016-06-02  1177  
31143e293 drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c Franky Lin       2016-06-02  1178  	skb->protocol = eth_type_trans(skb, ifp->ndev);
9c349892c drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c Arend van Spriel 2016-04-11  1179  	brcmf_netif_rx(ifp, skb);
9a1bb6025 drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c          Hante Meuleman   2014-07-30  1180  }
9a1bb6025 drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c          Hante Meuleman   2014-07-30  1181  

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
diff mbox

Patch

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
index 72954fd6df3b..b1f702faff4f 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
@@ -21,6 +21,7 @@ 
 #include <net/cfg80211.h>
 #include <net/rtnetlink.h>
 #include <net/addrconf.h>
+#include <net/ieee80211_radiotap.h>
 #include <net/ipv6.h>
 #include <brcmu_utils.h>
 #include <brcmu_wifi.h>
@@ -404,6 +405,30 @@  void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb)
 		netif_rx_ni(skb);
 }
 
+void brcmf_netif_mon_rx(struct brcmf_if *ifp, struct sk_buff *skb)
+{
+	if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MONITOR_FMT_RADIOTAP)) {
+		/* Do nothing */
+	} else {
+		struct ieee80211_radiotap_header *radiotap;
+
+		/* TODO: use RX status to fill some radiotap data */
+		radiotap = skb_push(skb, sizeof(*radiotap));
+		memset(radiotap, 0, sizeof(*radiotap));
+		radiotap->it_len = cpu_to_le16(sizeof(*radiotap));
+
+		/* TODO: 4 bytes with receive status? */
+		skb->len -= 4;
+	}
+
+	skb->dev = ifp->ndev;
+	skb_reset_mac_header(skb);
+	skb->pkt_type = PACKET_OTHERHOST;
+	skb->protocol = htons(ETH_P_802_2);
+
+	brcmf_netif_rx(ifp, skb);
+}
+
 static int brcmf_rx_hdrpull(struct brcmf_pub *drvr, struct sk_buff *skb,
 			    struct brcmf_if **ifp)
 {
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
index 401f50458686..dcf6e27cc16f 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
@@ -121,6 +121,7 @@  struct brcmf_pub {
 
 	struct brcmf_if *iflist[BRCMF_MAX_IFS];
 	s32 if2bss[BRCMF_MAX_IFS];
+	struct brcmf_if *mon_if;
 
 	struct mutex proto_block;
 	unsigned char proto_buf[BRCMF_DCMD_MAXLEN];
@@ -216,6 +217,7 @@  void brcmf_txflowblock_if(struct brcmf_if *ifp,
 			  enum brcmf_netif_stop_reason reason, bool state);
 void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success);
 void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb);
+void brcmf_netif_mon_rx(struct brcmf_if *ifp, struct sk_buff *skb);
 void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on);
 int __init brcmf_core_init(void);
 void __exit brcmf_core_exit(void);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
index 6eddb19ca48d..0782f2aa3767 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
@@ -34,6 +34,7 @@ 
  * GSCAN: enhanced scan offload feature.
  * FWSUP: Firmware supplicant.
  * MONITOR: monitor interface
+ * MONITOR_FMT_RADIOTAP: monitor packets include radiotap header
  */
 #define BRCMF_FEAT_LIST \
 	BRCMF_FEAT_DEF(MBSS) \
@@ -50,7 +51,8 @@ 
 	BRCMF_FEAT_DEF(MFP) \
 	BRCMF_FEAT_DEF(GSCAN) \
 	BRCMF_FEAT_DEF(FWSUP) \
-	BRCMF_FEAT_DEF(MONITOR)
+	BRCMF_FEAT_DEF(MONITOR) \
+	BRCMF_FEAT_DEF(MONITOR_FMT_RADIOTAP)
 
 /*
  * Quirks:
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
index c40ba8855cd5..6abf9795930e 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
@@ -69,6 +69,8 @@ 
 #define BRCMF_MSGBUF_MAX_EVENTBUF_POST		8
 
 #define BRCMF_MSGBUF_PKT_FLAGS_FRAME_802_3	0x01
+#define BRCMF_MSGBUF_PKT_FLAGS_FRAME_802_11	0x02
+#define BRCMF_MSGBUF_PKT_FLAGS_FRAME_MASK	0x07
 #define BRCMF_MSGBUF_PKT_FLAGS_PRIO_SHIFT	5
 
 #define BRCMF_MSGBUF_TX_FLUSH_CNT1		32
@@ -1128,6 +1130,7 @@  brcmf_msgbuf_process_rx_complete(struct brcmf_msgbuf *msgbuf, void *buf)
 	struct sk_buff *skb;
 	u16 data_offset;
 	u16 buflen;
+	u16 flags;
 	u32 idx;
 	struct brcmf_if *ifp;
 
@@ -1137,6 +1140,7 @@  brcmf_msgbuf_process_rx_complete(struct brcmf_msgbuf *msgbuf, void *buf)
 	data_offset = le16_to_cpu(rx_complete->data_offset);
 	buflen = le16_to_cpu(rx_complete->data_len);
 	idx = le32_to_cpu(rx_complete->msg.request_id);
+	flags = le16_to_cpu(rx_complete->flags);
 
 	skb = brcmf_msgbuf_get_pktid(msgbuf->drvr->bus_if->dev,
 				     msgbuf->rx_pktids, idx);
@@ -1150,6 +1154,19 @@  brcmf_msgbuf_process_rx_complete(struct brcmf_msgbuf *msgbuf, void *buf)
 
 	skb_trim(skb, buflen);
 
+	if ((flags & BRCMF_MSGBUF_PKT_FLAGS_FRAME_MASK) ==
+	    BRCMF_MSGBUF_PKT_FLAGS_FRAME_802_11) {
+		ifp = msgbuf->drvr->mon_if;
+
+		if (!ifp) {
+			brcmf_err("Received unexpected monitor pkt\n");
+			brcmu_pkt_buf_free_skb(skb);
+		}
+
+		brcmf_netif_mon_rx(ifp, skb);
+		return;
+	}
+
 	ifp = brcmf_get_ifp(msgbuf->drvr, rx_complete->msg.ifidx);
 	if (!ifp || !ifp->ndev) {
 		brcmf_err("Received pkt for invalid ifidx %d\n",