Browse Source

qcacmn: Add check to discard multicast echo packets

The bridge forwards the multicast packets to all the
interfaces attached the bridge.

When the STA network interface receives such packets
from bridge and send it to the AP, it is echoed back
from the BSS.

These packets are not intended for the bridge as it
will lead to looping.

Add a check to detect and drop such packets when
received back from the BSS.

Refactor dp_rx_mcast_echo_check function to fix
compilation errors from the above change.

CRs-Fixed: 2894272
Change-Id: I3f9e92c3598af11d3ff4e6b9b8afbc4110a926fc
Subrat Dash 4 years ago
parent
commit
ecb559ab6f
3 changed files with 74 additions and 28 deletions
  1. 39 0
      dp/wifi3.0/dp_rx.c
  2. 28 0
      dp/wifi3.0/dp_rx.h
  3. 7 28
      dp/wifi3.0/dp_rx_err.c

+ 39 - 0
dp/wifi3.0/dp_rx.c

@@ -2271,6 +2271,33 @@ void dp_rx_deliver_to_pkt_capture_no_peer(struct dp_soc *soc, qdf_nbuf_t nbuf,
 
 #endif
 
+#if defined(FEATURE_MCL_REPEATER) && defined(FEATURE_MEC)
+/**
+ * dp_rx_mec_check_wrapper() - wrapper to dp_rx_mcast_echo_check
+ * @soc: core DP main context
+ * @peer: dp peer handler
+ * @rx_tlv_hdr: start of the rx TLV header
+ * @nbuf: pkt buffer
+ *
+ * Return: bool (true if it is a looped back pkt else false)
+ */
+static inline bool dp_rx_mec_check_wrapper(struct dp_soc *soc,
+					   struct dp_peer *peer,
+					   uint8_t *rx_tlv_hdr,
+					   qdf_nbuf_t nbuf)
+{
+	return dp_rx_mcast_echo_check(soc, peer, rx_tlv_hdr, nbuf);
+}
+#else
+static inline bool dp_rx_mec_check_wrapper(struct dp_soc *soc,
+					   struct dp_peer *peer,
+					   uint8_t *rx_tlv_hdr,
+					   qdf_nbuf_t nbuf)
+{
+	return false;
+}
+#endif
+
 /**
  * dp_rx_process() - Brain of the Rx processing functionality
  *		     Called from the bottom half (tasklet/NET_RX_SOFTIRQ)
@@ -2933,6 +2960,18 @@ done:
 					tid_stats->intrabss_cnt++;
 					continue; /* Get next desc */
 				}
+
+			if (qdf_unlikely(dp_rx_mec_check_wrapper(soc,
+								 peer,
+								 rx_tlv_hdr,
+								 nbuf))) {
+				/* this is a looped back MCBC pkt,drop it */
+				DP_STATS_INC_PKT(peer, rx.mec_drop, 1,
+						 QDF_NBUF_CB_RX_PKT_LEN(nbuf));
+				qdf_nbuf_free(nbuf);
+				nbuf = next;
+				continue;
+			}
 		}
 
 		dp_rx_fill_gro_info(soc, rx_tlv_hdr, nbuf, &rx_ol_pkt_cnt);

+ 28 - 0
dp/wifi3.0/dp_rx.h

@@ -1694,4 +1694,32 @@ dp_rx_deliver_to_pkt_capture_no_peer(struct dp_soc *soc, qdf_nbuf_t nbuf,
 {
 }
 #endif
+
+#ifndef QCA_HOST_MODE_WIFI_DISABLED
+#ifdef FEATURE_MEC
+/**
+ * dp_rx_mcast_echo_check() - check if the mcast pkt is a loop
+ *			      back on same vap or a different vap.
+ * @soc: core DP main context
+ * @peer: dp peer handler
+ * @rx_tlv_hdr: start of the rx TLV header
+ * @nbuf: pkt buffer
+ *
+ * Return: bool (true if it is a looped back pkt else false)
+ *
+ */
+bool dp_rx_mcast_echo_check(struct dp_soc *soc,
+			    struct dp_peer *peer,
+			    uint8_t *rx_tlv_hdr,
+			    qdf_nbuf_t nbuf);
+#else
+static inline bool dp_rx_mcast_echo_check(struct dp_soc *soc,
+					  struct dp_peer *peer,
+					  uint8_t *rx_tlv_hdr,
+					  qdf_nbuf_t nbuf)
+{
+	return false;
+}
+#endif /* FEATURE_MEC */
+#endif /* QCA_HOST_MODE_WIFI_DISABLED */
 #endif /* _DP_RX_H */

+ 7 - 28
dp/wifi3.0/dp_rx_err.c

@@ -46,28 +46,15 @@
 #define DP_MAX_INVALID_BUFFERS 10
 
 #ifdef FEATURE_MEC
-/**
- * dp_rx_mcast_echo_check() - check if the mcast pkt is a loop
- *			      back on same vap or a different vap.
- *
- * @soc: core DP main context
- * @peer: dp peer handler
- * @rx_tlv_hdr: start of the rx TLV header
- * @nbuf: pkt buffer
- *
- * Return: bool (true if it is a looped back pkt else false)
- *
- */
-static inline bool dp_rx_mcast_echo_check(struct dp_soc *soc,
-					  struct dp_peer *peer,
-					  uint8_t *rx_tlv_hdr,
-					  qdf_nbuf_t nbuf)
+bool dp_rx_mcast_echo_check(struct dp_soc *soc,
+			    struct dp_peer *peer,
+			    uint8_t *rx_tlv_hdr,
+			    qdf_nbuf_t nbuf)
 {
 	struct dp_vdev *vdev = peer->vdev;
 	struct dp_pdev *pdev = vdev->pdev;
 	struct dp_mec_entry *mecentry = NULL;
 	uint8_t *data;
-
 	/*
 	 * Multicast Echo Check is required only if vdev is STA and
 	 * received pkt is a multicast/broadcast pkt. otherwise
@@ -75,7 +62,6 @@ static inline bool dp_rx_mcast_echo_check(struct dp_soc *soc,
 	 */
 	if (vdev->opmode != wlan_op_mode_sta)
 		return false;
-
 	if (!hal_rx_msdu_end_da_is_mcbc_get(soc->hal_soc, rx_tlv_hdr))
 		return false;
 
@@ -85,8 +71,8 @@ static inline bool dp_rx_mcast_echo_check(struct dp_soc *soc,
 	 * mac address then drop the pkt as it is looped back
 	 */
 	if (!(qdf_mem_cmp(&data[QDF_MAC_ADDR_SIZE],
-			vdev->mac_addr.raw,
-			QDF_MAC_ADDR_SIZE)))
+			  vdev->mac_addr.raw,
+			  QDF_MAC_ADDR_SIZE)))
 		return true;
 
 	/*
@@ -116,16 +102,9 @@ static inline bool dp_rx_mcast_echo_check(struct dp_soc *soc,
 
 	dp_rx_err_info("%pK: received pkt with same src mac " QDF_MAC_ADDR_FMT,
 		       soc, QDF_MAC_ADDR_REF(&data[QDF_MAC_ADDR_SIZE]));
+
 	return true;
 }
-#else
-static inline bool dp_rx_mcast_echo_check(struct dp_soc *soc,
-					  struct dp_peer *peer,
-					  uint8_t *rx_tlv_hdr,
-					  qdf_nbuf_t nbuf)
-{
-	return false;
-}
 #endif
 #endif /* QCA_HOST_MODE_WIFI_DISABLED */