Przeglądaj źródła

qcacmn: Do not reinject back defrag frames to REO

Deliver fragmented frames directly to stack without reinjecting back
to REO. Handle PN check for fragmented frames before delivery.
Drop the frames on PN check failure.

Change-Id: I7865def0d39fa83378073e07d318c34dccc6c6e5
CRs-Fixed: 2739870
Manjunathappa Prakash 5 lat temu
rodzic
commit
6ab2ce97e9
2 zmienionych plików z 137 dodań i 8 usunięć
  1. 134 8
      dp/wifi3.0/dp_rx_defrag.c
  2. 3 0
      dp/wifi3.0/dp_types.h

+ 134 - 8
dp/wifi3.0/dp_rx_defrag.c

@@ -330,6 +330,7 @@ static QDF_STATUS dp_rx_defrag_fraglist_insert(struct dp_peer *peer, unsigned ti
 	rx_desc_info = qdf_nbuf_data(frag);
 	cur_fragno = dp_rx_frag_get_mpdu_frag_number(rx_desc_info);
 
+	dp_debug("cur_fragno %d\n", cur_fragno);
 	/* If this is the first fragment */
 	if (!(*head_addr)) {
 		*head_addr = *tail_addr = frag;
@@ -401,6 +402,8 @@ static QDF_STATUS dp_rx_defrag_fraglist_insert(struct dp_peer *peer, unsigned ti
 		if (!next) {
 			*all_frag_present = 1;
 			return QDF_STATUS_SUCCESS;
+		} else {
+			/* revisit */
 		}
 	}
 
@@ -807,8 +810,17 @@ static QDF_STATUS dp_rx_defrag_tkip_demic(const uint8_t *key,
  */
 static void dp_rx_frag_pull_hdr(qdf_nbuf_t nbuf, uint16_t hdrsize)
 {
-	qdf_nbuf_pull_head(nbuf,
-			RX_PKT_TLVS_LEN + hdrsize);
+	struct rx_pkt_tlvs *rx_pkt_tlv =
+				(struct rx_pkt_tlvs *)qdf_nbuf_data(nbuf);
+	struct rx_mpdu_info *rx_mpdu_info_details =
+		&rx_pkt_tlv->mpdu_start_tlv.rx_mpdu_start.rx_mpdu_info_details;
+
+	dp_debug("pn_31_0 0x%x pn_63_32 0x%x pn_95_64 0x%x pn_127_96 0x%x\n",
+		 rx_mpdu_info_details->pn_31_0, rx_mpdu_info_details->pn_63_32,
+		 rx_mpdu_info_details->pn_95_64,
+		 rx_mpdu_info_details->pn_127_96);
+
+	qdf_nbuf_pull_head(nbuf, RX_PKT_TLVS_LEN + hdrsize);
 
 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
 		  "%s: final pktlen %d .11len %d",
@@ -825,15 +837,47 @@ static void dp_rx_frag_pull_hdr(qdf_nbuf_t nbuf, uint16_t hdrsize)
  *
  * Returns: None
  */
-static void
-dp_rx_construct_fraglist(struct dp_peer *peer,
-		qdf_nbuf_t head, uint16_t hdrsize)
+static int
+dp_rx_construct_fraglist(struct dp_peer *peer, int tid, qdf_nbuf_t head,
+			 uint16_t hdrsize)
 {
 	qdf_nbuf_t msdu = qdf_nbuf_next(head);
 	qdf_nbuf_t rx_nbuf = msdu;
+	struct dp_rx_tid *rx_tid = &peer->rx_tid[tid];
 	uint32_t len = 0;
+	uint64_t cur_pn128[2], prev_pn128[2];
+	int out_of_order = 0;
+
+	prev_pn128[0] = rx_tid->pn128[0];
+	prev_pn128[1] = rx_tid->pn128[1];
 
 	while (msdu) {
+		struct rx_pkt_tlvs *rx_pkt_tlv =
+				(struct rx_pkt_tlvs *)qdf_nbuf_data(msdu);
+		struct rx_mpdu_info *rx_mpdu_info_details =
+		 &rx_pkt_tlv->mpdu_start_tlv.rx_mpdu_start.rx_mpdu_info_details;
+
+		cur_pn128[0] = rx_mpdu_info_details->pn_31_0;
+		cur_pn128[0] |=
+			((uint64_t)rx_mpdu_info_details->pn_63_32 << 32);
+		cur_pn128[1] = rx_mpdu_info_details->pn_95_64;
+		cur_pn128[1] |=
+			((uint64_t)rx_mpdu_info_details->pn_127_96 << 32);
+
+		dp_debug("cur_pn128[0] 0x%llx cur_pn128[1] 0x%llx prev_pn128[0] 0x%llx prev_pn128[1] 0x%llx",
+			 cur_pn128[0], cur_pn128[1],
+			 prev_pn128[0], prev_pn128[1]);
+		if (cur_pn128[1] == prev_pn128[1])
+			out_of_order = (cur_pn128[0] <= prev_pn128[0]);
+		else
+			out_of_order = (cur_pn128[1] < prev_pn128[1]);
+
+		if (out_of_order)
+			return QDF_STATUS_E_FAILURE;
+
+		prev_pn128[0] = cur_pn128[0];
+		prev_pn128[1] = cur_pn128[1];
+
 		dp_rx_frag_pull_hdr(msdu, hdrsize);
 		len += qdf_nbuf_len(msdu);
 		msdu = qdf_nbuf_next(msdu);
@@ -849,6 +893,8 @@ dp_rx_construct_fraglist(struct dp_peer *peer,
 		  (uint32_t)qdf_nbuf_len(head),
 		  (uint32_t)qdf_nbuf_len(rx_nbuf),
 		  (uint32_t)(head->data_len));
+
+	return QDF_STATUS_SUCCESS;
 }
 
 /**
@@ -909,7 +955,7 @@ static void dp_rx_defrag_err(struct dp_vdev *vdev, qdf_nbuf_t nbuf)
  * Returns: None
  */
 static void
-dp_rx_defrag_nwifi_to_8023(struct dp_soc *soc,
+dp_rx_defrag_nwifi_to_8023(struct dp_soc *soc, struct dp_peer *peer, int tid,
 			   qdf_nbuf_t nbuf, uint16_t hdrsize)
 {
 	struct llc_snap_hdr_t *llchdr;
@@ -918,6 +964,21 @@ dp_rx_defrag_nwifi_to_8023(struct dp_soc *soc,
 	uint16_t fc = 0;
 	union dp_align_mac_addr mac_addr;
 	uint8_t *rx_desc_info = qdf_mem_malloc(RX_PKT_TLVS_LEN);
+	struct rx_pkt_tlvs *rx_pkt_tlv =
+				(struct rx_pkt_tlvs *)qdf_nbuf_data(nbuf);
+	struct rx_mpdu_info *rx_mpdu_info_details =
+		&rx_pkt_tlv->mpdu_start_tlv.rx_mpdu_start.rx_mpdu_info_details;
+	struct dp_rx_tid *rx_tid = &peer->rx_tid[tid];
+
+	dp_debug("head_nbuf pn_31_0 0x%x pn_63_32 0x%x pn_95_64 0x%x pn_127_96 0x%x\n",
+		 rx_mpdu_info_details->pn_31_0, rx_mpdu_info_details->pn_63_32,
+		 rx_mpdu_info_details->pn_95_64,
+		 rx_mpdu_info_details->pn_127_96);
+
+	rx_tid->pn128[0] = rx_mpdu_info_details->pn_31_0;
+	rx_tid->pn128[0] |= ((uint64_t)rx_mpdu_info_details->pn_63_32 << 32);
+	rx_tid->pn128[1] = rx_mpdu_info_details->pn_95_64;
+	rx_tid->pn128[1] |= ((uint64_t)rx_mpdu_info_details->pn_127_96 << 32);
 
 	if (!rx_desc_info) {
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
@@ -1000,6 +1061,62 @@ dp_rx_defrag_nwifi_to_8023(struct dp_soc *soc,
 	qdf_mem_free(rx_desc_info);
 }
 
+#ifdef RX_DEFRAG_DO_NOT_REINJECT
+/*
+ * dp_rx_defrag_deliver(): Deliver defrag packet to stack
+ * @peer: Pointer to the peer
+ * @tid: Transmit Identifier
+ * @head: Nbuf to be delivered
+ *
+ * Returns: None
+ */
+static inline void dp_rx_defrag_deliver(struct dp_peer *peer,
+					unsigned int tid,
+					qdf_nbuf_t head)
+{
+	struct dp_vdev *vdev = peer->vdev;
+	struct dp_soc *soc = vdev->pdev->soc;
+	qdf_nbuf_t deliver_list_head = NULL;
+	qdf_nbuf_t deliver_list_tail = NULL;
+	uint8_t *rx_tlv_hdr;
+
+	rx_tlv_hdr = qdf_nbuf_data(head);
+
+	QDF_NBUF_CB_RX_VDEV_ID(head) = vdev->vdev_id;
+	qdf_nbuf_set_tid_val(head, tid);
+	qdf_nbuf_pull_head(head, RX_PKT_TLVS_LEN);
+
+	DP_RX_LIST_APPEND(deliver_list_head, deliver_list_tail,
+			  head);
+	dp_rx_deliver_to_stack(soc, vdev, peer, deliver_list_head,
+			       deliver_list_tail);
+}
+
+/*
+ * dp_rx_defrag_reo_reinject(): Reinject the fragment chain back into REO
+ * @peer: Pointer to the peer
+ * @tid: Transmit Identifier
+ * @head: Buffer to be reinjected back
+ *
+ * Reinject the fragment chain back into REO
+ *
+ * Returns: QDF_STATUS
+ */
+static QDF_STATUS dp_rx_defrag_reo_reinject(struct dp_peer *peer,
+					    unsigned int tid, qdf_nbuf_t head)
+{
+	struct dp_rx_reorder_array_elem *rx_reorder_array_elem;
+
+	rx_reorder_array_elem = peer->rx_tid[tid].array;
+
+	dp_rx_defrag_deliver(peer, tid, head);
+	rx_reorder_array_elem->head = NULL;
+	rx_reorder_array_elem->tail = NULL;
+	dp_rx_return_head_frag_desc(peer, tid);
+
+	return QDF_STATUS_SUCCESS;
+}
+#else
 #ifdef WLAN_FEATURE_DP_RX_RING_HISTORY
 /**
  * dp_rx_reinject_ring_record_entry() - Record reinject ring history
@@ -1235,6 +1352,7 @@ static QDF_STATUS dp_rx_defrag_reo_reinject(struct dp_peer *peer,
 		  "%s: reinjection done !", __func__);
 	return QDF_STATUS_SUCCESS;
 }
+#endif
 
 /*
  * dp_rx_defrag(): Defragment the fragment chain
@@ -1371,8 +1489,9 @@ static QDF_STATUS dp_rx_defrag(struct dp_peer *peer, unsigned tid,
 	}
 
 	/* Convert the header to 802.3 header */
-	dp_rx_defrag_nwifi_to_8023(soc, frag_list_head, hdr_space);
-	dp_rx_construct_fraglist(peer, frag_list_head, hdr_space);
+	dp_rx_defrag_nwifi_to_8023(soc, peer, tid, frag_list_head, hdr_space);
+	if (dp_rx_construct_fraglist(peer, tid, frag_list_head, hdr_space))
+		return QDF_STATUS_E_DEFRAG_ERROR;
 
 	return QDF_STATUS_SUCCESS;
 }
@@ -1576,9 +1695,13 @@ dp_rx_defrag_store_fragment(struct dp_soc *soc,
 	}
 
 	/* Check if the fragment is for the same sequence or a different one */
+	dp_debug("rx_tid %d", tid);
 	if (rx_reorder_array_elem->head) {
+		dp_debug("rxseq %d\n", rxseq);
 		if (rxseq != rx_tid->curr_seq_num) {
 
+			dp_debug("mismatch cur_seq %d rxseq %d\n",
+				 rx_tid->curr_seq_num, rxseq);
 			/* Drop stored fragments if out of sequence
 			 * fragment is received
 			 */
@@ -1586,6 +1709,7 @@ dp_rx_defrag_store_fragment(struct dp_soc *soc,
 
 			DP_STATS_INC(soc, rx.rx_frag_oor, 1);
 
+			dp_debug("cur rxseq %d\n", rxseq);
 			/*
 			 * The sequence number for this fragment becomes the
 			 * new sequence number to be processed
@@ -1593,9 +1717,11 @@ dp_rx_defrag_store_fragment(struct dp_soc *soc,
 			rx_tid->curr_seq_num = rxseq;
 		}
 	} else {
+		dp_debug("cur rxseq %d\n", rxseq);
 		/* Start of a new sequence */
 		dp_rx_defrag_cleanup(peer, tid);
 		rx_tid->curr_seq_num = rxseq;
+		/* store PN number also */
 	}
 
 	/*

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

@@ -608,6 +608,9 @@ struct dp_rx_tid {
 	uint32_t curr_seq_num;
 	uint32_t curr_frag_num;
 
+	/* head PN number */
+	uint64_t pn128[2];
+
 	uint32_t defrag_timeout_ms;
 	uint16_t dialogtoken;
 	uint16_t statuscode;