Browse Source

qcacmn: Temporary WAR for Multicast echo check in host

This is a temporary WAR in host for multicast loopback check
until we finalize on exact design, and host or firmware will
take care of this

Change-Id: I4d2d1b0f5d2a78d4c8716740b74c4fee22c28e96
CRs-Fixed: 2039038
Tallapragada Kalyan 8 years ago
parent
commit
274eb9e76b
5 changed files with 88 additions and 22 deletions
  1. 7 2
      dp/wifi3.0/dp_rx.c
  2. 25 5
      dp/wifi3.0/dp_rx_err.c
  3. 42 0
      dp/wifi3.0/dp_tx.c
  4. 11 0
      dp/wifi3.0/dp_types.h
  5. 3 15
      qdf/linux/src/i_qdf_nbuf.h

+ 7 - 2
dp/wifi3.0/dp_rx.c

@@ -337,6 +337,8 @@ dp_rx_intrabss_fwd(struct dp_soc *soc,
 		if (da_peer->vdev == sa_peer->vdev && !da_peer->bss_peer) {
 			memset(nbuf->cb, 0x0, sizeof(nbuf->cb));
 			len = qdf_nbuf_len(nbuf);
+			qdf_nbuf_set_fctx_type(nbuf, (void *)NULL,
+						CB_FTYPE_INTRABSS_FWD);
 			if (!dp_tx_send(sa_peer->vdev, nbuf)) {
 				DP_STATS_INC_PKT(sa_peer, rx.intra_bss.pkts,
 						1, len);
@@ -363,9 +365,12 @@ dp_rx_intrabss_fwd(struct dp_soc *soc,
 			return false;
 		memset(nbuf_copy->cb, 0x0, sizeof(nbuf_copy->cb));
 		len = qdf_nbuf_len(nbuf_copy);
-		if (dp_tx_send(sa_peer->vdev, nbuf_copy))
+		qdf_nbuf_set_fctx_type(nbuf_copy, (void *)NULL,
+					CB_FTYPE_INTRABSS_FWD);
+		if (dp_tx_send(sa_peer->vdev, nbuf_copy)) {
+			DP_STATS_INC_PKT(sa_peer, rx.intra_bss.fail, 1, len);
 			qdf_nbuf_free(nbuf_copy);
-		else
+		} else
 			DP_STATS_INC_PKT(sa_peer, rx.intra_bss.pkts, 1, len);
 	}
 	/* return false as we have to still send the original pkt

+ 25 - 5
dp/wifi3.0/dp_rx_err.c

@@ -224,6 +224,9 @@ dp_rx_null_q_desc_handle(struct dp_soc *soc, struct dp_rx_desc *rx_desc,
 	uint16_t peer_id = 0xFFFF;
 	struct dp_peer *peer = NULL;
 	uint32_t sgi, rate_mcs, tid;
+	uint8_t count;
+	struct mect_entry *mect_entry;
+	uint8_t *nbuf_data = NULL;
 
 	rx_bufs_used++;
 
@@ -293,11 +296,6 @@ dp_rx_null_q_desc_handle(struct dp_soc *soc, struct dp_rx_desc *rx_desc,
 		"%s: %d, SGI: %d, rate_mcs: %d, tid: %d",
 		__func__, __LINE__, sgi, rate_mcs, tid);
 
-	/* WDS Source Port Learning */
-	if (qdf_likely(vdev->rx_decap_type == htt_cmn_pkt_type_ethernet) &&
-			(vdev->wds_enabled))
-		dp_rx_wds_srcport_learn(soc, rx_desc->rx_buf_start, peer, nbuf);
-
 	/*
 	 * Advance the packet start pointer by total size of
 	 * pre-header TLV's
@@ -307,6 +305,28 @@ dp_rx_null_q_desc_handle(struct dp_soc *soc, struct dp_rx_desc *rx_desc,
 	if (l2_hdr_offset)
 		qdf_nbuf_pull_head(nbuf, l2_hdr_offset);
 
+	nbuf_data = qdf_nbuf_data(nbuf);
+	for (count = 0; count < soc->mect_cnt; count++) {
+		mect_entry = &soc->mect_table[count];
+		mect_entry->ts = jiffies_64;
+		if (!(memcmp(mect_entry->mac_addr, &nbuf_data[DP_MAC_ADDR_LEN],
+				DP_MAC_ADDR_LEN))) {
+			QDF_TRACE(QDF_MODULE_ID_DP,
+				QDF_TRACE_LEVEL_INFO,
+				FL("received pkt with same src MAC"));
+
+			/* Drop & free packet */
+			qdf_nbuf_free(nbuf);
+			/* Statistics */
+			goto fail;
+		}
+	}
+
+	/* WDS Source Port Learning */
+	if (qdf_likely(vdev->rx_decap_type == htt_cmn_pkt_type_ethernet) &&
+			(vdev->wds_enabled))
+		dp_rx_wds_srcport_learn(soc, rx_desc->rx_buf_start, peer, nbuf);
+
 	if (hal_rx_mpdu_start_mpdu_qos_control_valid_get(
 		rx_desc->rx_buf_start)) {
 		/* TODO: Assuming that qos_control_valid also indicates

+ 42 - 0
dp/wifi3.0/dp_tx.c

@@ -1397,11 +1397,53 @@ qdf_nbuf_t dp_tx_send(void *vap_dev, qdf_nbuf_t nbuf)
 	struct dp_tx_msdu_info_s msdu_info;
 	struct dp_tx_seg_info_s seg_info;
 	struct dp_vdev *vdev = (struct dp_vdev *) vap_dev;
+	struct dp_soc *soc = vdev->pdev->soc;
 	uint16_t peer_id = HTT_INVALID_PEER;
+	uint8_t count;
+	uint8_t found = 0;
+	uint8_t oldest_mec_entry_idx = 0;
+	uint64_t oldest_mec_ts = 0;
+	struct mect_entry *mect_entry;
 
 	qdf_mem_set(&msdu_info, sizeof(msdu_info), 0x0);
 	qdf_mem_set(&seg_info, sizeof(seg_info), 0x0);
 
+	if (qdf_nbuf_get_ftype(nbuf) == CB_FTYPE_INTRABSS_FWD)
+		goto out;
+
+	eh = (struct ether_header *)qdf_nbuf_data(nbuf);
+	if (DP_FRAME_IS_MULTICAST((eh)->ether_dhost)) {
+		for (count = 0; count < soc->mect_cnt; count++) {
+			mect_entry = &soc->mect_table[count];
+			if (!memcmp(mect_entry->mac_addr, eh->ether_shost,
+					DP_MAC_ADDR_LEN)) {
+				found = 1;
+				break;
+			}
+
+			if (!oldest_mec_ts) {
+				oldest_mec_entry_idx = count;
+				oldest_mec_ts = mect_entry->ts;
+			} else if (mect_entry->ts < oldest_mec_ts) {
+				oldest_mec_entry_idx = count;
+				oldest_mec_ts = mect_entry->ts;
+			}
+		}
+
+		if (!found) {
+			if (count >= DP_MAX_MECT_ENTRIES)
+				count = oldest_mec_entry_idx;
+			else
+				soc->mect_cnt++;
+
+			mect_entry = &soc->mect_table[count];
+			mect_entry->ts = jiffies_64;
+			memcpy(mect_entry->mac_addr, eh->ether_shost,
+				DP_MAC_ADDR_LEN);
+		}
+	}
+
+out:
 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
 			"%s , skb %0x:%0x:%0x:%0x:%0x:%0x\n",
 			__func__, nbuf->data[0], nbuf->data[1], nbuf->data[2],

+ 11 - 0
dp/wifi3.0/dp_types.h

@@ -87,6 +87,7 @@
 #define MAX_TX_HW_QUEUES 3
 
 #define DP_MAX_INTERRUPT_CONTEXTS 8
+#define DP_MAX_MECT_ENTRIES 64
 
 struct dp_soc_cmn;
 struct dp_pdev;
@@ -378,6 +379,13 @@ struct dp_ast_entry {
 	TAILQ_ENTRY(dp_ast_entry) ast_entry_elem;
 };
 
+struct mect_entry {
+	uint8_t idx;
+	uint8_t valid;
+	uint8_t mac_addr[6];
+	uint64_t ts;
+};
+
 /* SOC level structure for data path */
 struct dp_soc {
 	/* Common base structure - Should be the first member */
@@ -612,6 +620,9 @@ struct dp_soc {
 #endif
 	qdf_list_t reo_desc_freelist;
 	qdf_spinlock_t reo_desc_freelist_lock;
+	struct mect_entry mect_table[DP_MAX_MECT_ENTRIES];
+	uint8_t mect_cnt;
+
 	/* Obj Mgr SoC */
 	struct wlan_objmgr_psoc *psoc;
 	qdf_nbuf_t invalid_peer_head_msdu;

+ 3 - 15
qdf/linux/src/i_qdf_nbuf.h

@@ -569,28 +569,16 @@ void __qdf_nbuf_num_frags_init(struct sk_buff *skb)
 	QDF_NBUF_CB_TX_NUM_EXTRA_FRAGS(skb) = 0;
 }
 
-#ifdef CONFIG_MCL
-typedef enum {
-	CB_FTYPE_INVALID = 0,
-	CB_FTYPE_MCAST2UCAST = 1,
-	CB_FTYPE_TSO = 2,
-	CB_FTYPE_TSO_SG = 3,
-	CB_FTYPE_SG = 4,
-} CB_FTYPE;
-#else
 typedef enum {
 	CB_FTYPE_INVALID = 0,
 	CB_FTYPE_MCAST2UCAST = 1,
 	CB_FTYPE_TSO = 2,
 	CB_FTYPE_TSO_SG = 3,
 	CB_FTYPE_SG = 4,
-#if ATH_DATA_RX_INFO_EN
-	CB_FTYPE_RX_INFO = 5,
-#else
-	CB_FTYPE_MESH_RX_INFO = 5,
-#endif
+	CB_FTYPE_INTRABSS_FWD = 5,
+	CB_FTYPE_RX_INFO = 6,
+	CB_FTYPE_MESH_RX_INFO = 7,
 } CB_FTYPE;
-#endif
 
 /*
  * prototypes. Implemented in qdf_nbuf.c