Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ce7a45b9 authored by Manjunathappa Prakash's avatar Manjunathappa Prakash Committed by snandini
Browse files

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
parent ac1fe6e1
Loading
Loading
Loading
Loading
+134 −8
Original line number Original line Diff line number Diff line
@@ -329,6 +329,7 @@ static QDF_STATUS dp_rx_defrag_fraglist_insert(struct dp_peer *peer, unsigned ti
	rx_desc_info = qdf_nbuf_data(frag);
	rx_desc_info = qdf_nbuf_data(frag);
	cur_fragno = dp_rx_frag_get_mpdu_frag_number(rx_desc_info);
	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 this is the first fragment */
	if (!(*head_addr)) {
	if (!(*head_addr)) {
		*head_addr = *tail_addr = frag;
		*head_addr = *tail_addr = frag;
@@ -400,6 +401,8 @@ static QDF_STATUS dp_rx_defrag_fraglist_insert(struct dp_peer *peer, unsigned ti
		if (!next) {
		if (!next) {
			*all_frag_present = 1;
			*all_frag_present = 1;
			return QDF_STATUS_SUCCESS;
			return QDF_STATUS_SUCCESS;
		} else {
			/* revisit */
		}
		}
	}
	}


@@ -806,8 +809,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)
static void dp_rx_frag_pull_hdr(qdf_nbuf_t nbuf, uint16_t hdrsize)
{
{
	qdf_nbuf_pull_head(nbuf,
	struct rx_pkt_tlvs *rx_pkt_tlv =
			RX_PKT_TLVS_LEN + hdrsize);
				(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,
	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
		  "%s: final pktlen %d .11len %d",
		  "%s: final pktlen %d .11len %d",
@@ -824,15 +836,47 @@ static void dp_rx_frag_pull_hdr(qdf_nbuf_t nbuf, uint16_t hdrsize)
 *
 *
 * Returns: None
 * Returns: None
 */
 */
static void
static int
dp_rx_construct_fraglist(struct dp_peer *peer,
dp_rx_construct_fraglist(struct dp_peer *peer, int tid, qdf_nbuf_t head,
		qdf_nbuf_t head, uint16_t hdrsize)
			 uint16_t hdrsize)
{
{
	qdf_nbuf_t msdu = qdf_nbuf_next(head);
	qdf_nbuf_t msdu = qdf_nbuf_next(head);
	qdf_nbuf_t rx_nbuf = msdu;
	qdf_nbuf_t rx_nbuf = msdu;
	struct dp_rx_tid *rx_tid = &peer->rx_tid[tid];
	uint32_t len = 0;
	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) {
	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);
		dp_rx_frag_pull_hdr(msdu, hdrsize);
		len += qdf_nbuf_len(msdu);
		len += qdf_nbuf_len(msdu);
		msdu = qdf_nbuf_next(msdu);
		msdu = qdf_nbuf_next(msdu);
@@ -848,6 +892,8 @@ dp_rx_construct_fraglist(struct dp_peer *peer,
		  (uint32_t)qdf_nbuf_len(head),
		  (uint32_t)qdf_nbuf_len(head),
		  (uint32_t)qdf_nbuf_len(rx_nbuf),
		  (uint32_t)qdf_nbuf_len(rx_nbuf),
		  (uint32_t)(head->data_len));
		  (uint32_t)(head->data_len));

	return QDF_STATUS_SUCCESS;
}
}


/**
/**
@@ -908,7 +954,7 @@ static void dp_rx_defrag_err(struct dp_vdev *vdev, qdf_nbuf_t nbuf)
 * Returns: None
 * Returns: None
 */
 */
static void
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)
			   qdf_nbuf_t nbuf, uint16_t hdrsize)
{
{
	struct llc_snap_hdr_t *llchdr;
	struct llc_snap_hdr_t *llchdr;
@@ -917,6 +963,21 @@ dp_rx_defrag_nwifi_to_8023(struct dp_soc *soc,
	uint16_t fc = 0;
	uint16_t fc = 0;
	union dp_align_mac_addr mac_addr;
	union dp_align_mac_addr mac_addr;
	uint8_t *rx_desc_info = qdf_mem_malloc(RX_PKT_TLVS_LEN);
	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) {
	if (!rx_desc_info) {
		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
@@ -999,6 +1060,62 @@ dp_rx_defrag_nwifi_to_8023(struct dp_soc *soc,
	qdf_mem_free(rx_desc_info);
	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
#ifdef WLAN_FEATURE_DP_RX_RING_HISTORY
static inline void
static inline void
dp_rx_reinject_ring_record_entry(struct dp_soc *soc, uint64_t paddr,
dp_rx_reinject_ring_record_entry(struct dp_soc *soc, uint64_t paddr,
@@ -1210,6 +1327,7 @@ static QDF_STATUS dp_rx_defrag_reo_reinject(struct dp_peer *peer,
		  "%s: reinjection done !", __func__);
		  "%s: reinjection done !", __func__);
	return QDF_STATUS_SUCCESS;
	return QDF_STATUS_SUCCESS;
}
}
#endif


/*
/*
 * dp_rx_defrag(): Defragment the fragment chain
 * dp_rx_defrag(): Defragment the fragment chain
@@ -1346,8 +1464,9 @@ static QDF_STATUS dp_rx_defrag(struct dp_peer *peer, unsigned tid,
	}
	}


	/* Convert the header to 802.3 header */
	/* Convert the header to 802.3 header */
	dp_rx_defrag_nwifi_to_8023(soc, frag_list_head, hdr_space);
	dp_rx_defrag_nwifi_to_8023(soc, peer, tid, frag_list_head, hdr_space);
	dp_rx_construct_fraglist(peer, 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;
	return QDF_STATUS_SUCCESS;
}
}
@@ -1546,9 +1665,13 @@ dp_rx_defrag_store_fragment(struct dp_soc *soc,
	}
	}


	/* Check if the fragment is for the same sequence or a different one */
	/* 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) {
	if (rx_reorder_array_elem->head) {
		dp_debug("rxseq %d\n", rxseq);
		if (rxseq != rx_tid->curr_seq_num) {
		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
			/* Drop stored fragments if out of sequence
			 * fragment is received
			 * fragment is received
			 */
			 */
@@ -1556,6 +1679,7 @@ dp_rx_defrag_store_fragment(struct dp_soc *soc,


			DP_STATS_INC(soc, rx.rx_frag_oor, 1);
			DP_STATS_INC(soc, rx.rx_frag_oor, 1);


			dp_debug("cur rxseq %d\n", rxseq);
			/*
			/*
			 * The sequence number for this fragment becomes the
			 * The sequence number for this fragment becomes the
			 * new sequence number to be processed
			 * new sequence number to be processed
@@ -1563,9 +1687,11 @@ dp_rx_defrag_store_fragment(struct dp_soc *soc,
			rx_tid->curr_seq_num = rxseq;
			rx_tid->curr_seq_num = rxseq;
		}
		}
	} else {
	} else {
		dp_debug("cur rxseq %d\n", rxseq);
		/* Start of a new sequence */
		/* Start of a new sequence */
		dp_rx_defrag_cleanup(peer, tid);
		dp_rx_defrag_cleanup(peer, tid);
		rx_tid->curr_seq_num = rxseq;
		rx_tid->curr_seq_num = rxseq;
		/* store PN number also */
	}
	}


	/*
	/*
+3 −0
Original line number Original line Diff line number Diff line
@@ -579,6 +579,9 @@ struct dp_rx_tid {
	uint32_t curr_seq_num;
	uint32_t curr_seq_num;
	uint32_t curr_frag_num;
	uint32_t curr_frag_num;


	/* head PN number */
	uint64_t pn128[2];

	uint32_t defrag_timeout_ms;
	uint32_t defrag_timeout_ms;
	uint16_t dialogtoken;
	uint16_t dialogtoken;
	uint16_t statuscode;
	uint16_t statuscode;