[PATCH 10/18] net/cnxk: update NIX reassembly fast path

Rahul Bhansali rbhansali at marvell.com
Wed Jan 28 07:03:08 CET 2026


Update NIX reassembly fastpath for cn20k based on
CPT CSR change.

Signed-off-by: Rahul Bhansali <rbhansali at marvell.com>
---
 drivers/net/cnxk/cn20k_rx.h | 80 +++++++++++++++++++++++++++++--------
 1 file changed, 64 insertions(+), 16 deletions(-)

diff --git a/drivers/net/cnxk/cn20k_rx.h b/drivers/net/cnxk/cn20k_rx.h
index 1944e507b0..ea8675be00 100644
--- a/drivers/net/cnxk/cn20k_rx.h
+++ b/drivers/net/cnxk/cn20k_rx.h
@@ -191,15 +191,13 @@ nix_sec_reass_first_frag_update(struct rte_mbuf *head, const rte_iova_t *iova_li
 	}
 
 	/* Remove the frag header by moving header 8 bytes forward */
-	ipv6_hdr->payload_len = rte_cpu_to_be_16(rlen - 8 - sizeof(struct rte_ipv6_hdr));
+	ipv6_hdr->payload_len = rte_cpu_to_be_16(rlen - sizeof(struct rte_ipv6_hdr));
 
 	/* tot_len is sum of all IP header's length before fragment header */
 	rte_memcpy(rte_pktmbuf_mtod_offset(head, void *, 8), rte_pktmbuf_mtod(head, void *),
 		   lc_off + tot_len);
 
-	head->data_len -= 8;
 	head->data_off += 8;
-	head->pkt_len -= 8;
 }
 
 static __rte_always_inline uint64_t
@@ -300,6 +298,7 @@ nix_update_match_id(const uint16_t match_id, uint64_t ol_flags, struct rte_mbuf
 	return ol_flags;
 }
 
+#if defined(RTE_ARCH_ARM64)
 static __rte_always_inline void
 nix_cqe_xtract_mseg(const union nix_rx_parse_u *rx, struct rte_mbuf *mbuf, uint64_t rearm,
 		    uintptr_t cpth, uintptr_t sa_base, const uint64_t buf_sz, const uint16_t flags)
@@ -314,6 +313,7 @@ nix_cqe_xtract_mseg(const union nix_rx_parse_u *rx, struct rte_mbuf *mbuf, uint6
 	uint16_t rlen = hdr->w3.rlen;
 	const rte_iova_t *iova_list;
 	uint8_t sg_cnt = 1, nb_segs;
+	uint16x4_t fsz, sg_swap;
 	uint16_t later_skip = 0;
 	bool reas_fail = false;
 	const rte_iova_t *eol;
@@ -321,6 +321,7 @@ nix_cqe_xtract_mseg(const union nix_rx_parse_u *rx, struct rte_mbuf *mbuf, uint6
 	uint8_t ts_rx_off;
 	int dyn_off = 0;
 	uint16_t sg_len;
+	uint16_t l4_off;
 	int64_t len;
 	uintptr_t p;
 
@@ -341,7 +342,7 @@ nix_cqe_xtract_mseg(const union nix_rx_parse_u *rx, struct rte_mbuf *mbuf, uint6
 		finfo = (const struct cpt_frag_info_s *)sg_base;
 		sg_base += num_frags ? (num_frags > 4 ? 32 : 16) : 0;
 		sg = *(uint64_t *)sg_base;
-		nb_segs = (sg >> 48) & 0x3;
+		nb_segs = (sg >> 14) & 0x3;
 		iova_list = (rte_iova_t *)(sg_base);
 		eol = iova_list + (hdr->w4.gthr_size << 2);
 		iova_list += 2;
@@ -357,11 +358,22 @@ nix_cqe_xtract_mseg(const union nix_rx_parse_u *rx, struct rte_mbuf *mbuf, uint6
 			if (hdr->w0.reas_sts ||
 			    (hdr->w0.err_sum && !roc_ie_ow_ucc_is_success(hdr->w3.uc_ccode))) {
 				reas_fail = true;
-				nxt_frag = (sg >> 51) & 0x3;
-				fsz_w1 = finfo->w1.u64 >> 16;
+				nxt_frag = (sg >> 11) & 0x3;
+				nxt_frag = ((nxt_frag << 1) | (nxt_frag >> 1)) & 0x3;
+
+				/* Reverse the order of fragment sizes */
+				fsz = vreinterpret_u16_u64(vdup_n_u64(finfo->w1.u64));
+				fsz = vrev64_u16(fsz);
+				fsz_w1 = vget_lane_u64(vreinterpret_u64_u16(fsz), 0) >> 16;
 				finfo++;
+				l4_off = ((cq_w5 >> 24) & 0xFF) - (cq_w5 & 0xFF);
 			}
 		}
+
+		/* sg byte swap */
+		sg_swap = vreinterpret_u16_u64(vdup_n_u64(sg));
+		sg_swap = vrev64_u16(sg_swap);
+		sg = vget_lane_u64(vreinterpret_u64_u16(sg_swap), 0);
 	} else {
 		sg = *(const uint64_t *)(rx + 1);
 		nb_segs = (sg >> 48) & 0x3;
@@ -376,8 +388,10 @@ nix_cqe_xtract_mseg(const union nix_rx_parse_u *rx, struct rte_mbuf *mbuf, uint6
 		iova_list = ((const rte_iova_t *)(rx + 1)) + 2;
 	}
 
-	/* Update data len as per the segment size */
 	sg_len = sg & 0xFFFF;
+	sg = sg >> 16;
+
+	/* Update data len as per the segment size */
 	mbuf->data_len = sg_len;
 	mbuf->nb_segs = nb_segs;
 	head = mbuf;
@@ -387,7 +401,6 @@ nix_cqe_xtract_mseg(const union nix_rx_parse_u *rx, struct rte_mbuf *mbuf, uint6
 		nix_sec_reass_first_frag_update(mbuf, iova_list - 1, cpth, cq_w1, cq_w5, rlen);
 
 	len -= sg_len;
-	sg = sg >> 16;
 	nb_segs--;
 
 	later_skip = (uintptr_t)mbuf->buf_addr - (uintptr_t)mbuf;
@@ -404,6 +417,9 @@ nix_cqe_xtract_mseg(const union nix_rx_parse_u *rx, struct rte_mbuf *mbuf, uint6
 
 		RTE_MEMPOOL_CHECK_COOKIES(mbuf->pool, (void **)&mbuf, 1, 1);
 
+		sg_len = sg & 0xFFFF;
+		sg = sg >> 16;
+
 		/* Process reassembly failure case */
 		if ((flags & NIX_RX_REAS_F) && unlikely(reas_fail && (nxt_frag & 1))) {
 			head->ol_flags |=
@@ -419,20 +435,25 @@ nix_cqe_xtract_mseg(const union nix_rx_parse_u *rx, struct rte_mbuf *mbuf, uint6
 			last_mbuf->next = NULL;
 			head = mbuf;
 			len = fsz_w1 & 0xFFFF;
-			head->pkt_len = len - ts_rx_off;
+			head->pkt_len = l4_off + len - ts_rx_off;
 			head->nb_segs = sg_cnt;
+			/* later frag size update*/
+			sg_len += l4_off;
 			data_off = rearm & 0xFFFF;
 			sg_cnt = 0;
 			nxt_frag = nxt_frag >> 1;
 			fsz_w1 = fsz_w1 >> 16;
-			if (--num_frags == 4)
-				fsz_w1 = finfo->w1.u64;
+			if (--num_frags == 4) {
+				/* Reverse the order of fragment sizes */
+				fsz = vreinterpret_u16_u64(vdup_n_u64(finfo->w1.u64));
+				fsz = vrev64_u16(fsz);
+				fsz_w1 = vget_lane_u64(vreinterpret_u64_u16(fsz), 0);
+			}
 		}
 
 		if ((flags & NIX_RX_REAS_F) && num_frags && !reas_fail)
 			data_off = *iova_list - (uint64_t)mbuf->buf_addr;
 
-		sg_len = sg & 0xFFFF;
 		if ((flags & NIX_RX_OFFLOAD_SECURITY_F) && !(flags & NIX_RX_REAS_F)) {
 			/* Adjust last mbuf data length with negative offset for
 			 * security pkts if needed.
@@ -443,7 +464,6 @@ nix_cqe_xtract_mseg(const union nix_rx_parse_u *rx, struct rte_mbuf *mbuf, uint6
 		}
 
 		mbuf->data_len = sg_len;
-		sg = sg >> 16;
 		p = (uintptr_t)&mbuf->rearm_data;
 		*(uint64_t *)p = (rearm & ~0xFFFF) | data_off;
 
@@ -454,11 +474,25 @@ nix_cqe_xtract_mseg(const union nix_rx_parse_u *rx, struct rte_mbuf *mbuf, uint6
 
 		if (!nb_segs && (iova_list + 1 < eol)) {
 			sg = *(const uint64_t *)(iova_list);
-			nb_segs = (sg >> 48) & 0x3;
+
+			if ((flags & NIX_RX_SEC_REASSEMBLY_F) && (cq_w1 & BIT(11))) {
+				nb_segs = (sg >> 14) & 0x3;
+
+				if (unlikely(reas_fail)) {
+					nxt_frag = (sg >> 11) & 7;
+					nxt_frag = ((nxt_frag << 2) | (nxt_frag & 2) |
+						    (nxt_frag >> 2)) & 0x7;
+				}
+
+				sg_swap = vreinterpret_u16_u64(vdup_n_u64(sg));
+				sg_swap = vrev64_u16(sg_swap);
+				sg = vget_lane_u64(vreinterpret_u64_u16(sg_swap), 0);
+			} else {
+				nb_segs = (sg >> 48) & 0x3;
+			}
+
 			iova_list++;
 			head->nb_segs += nb_segs;
-			if ((flags & NIX_RX_REAS_F) && reas_fail)
-				nxt_frag = (sg >> 50) & 0x7;
 		}
 	}
 
@@ -468,6 +502,20 @@ nix_cqe_xtract_mseg(const union nix_rx_parse_u *rx, struct rte_mbuf *mbuf, uint6
 		cnxk_ip_reassembly_dynfield(head, dyn_off)->nb_frags = 0;
 	}
 }
+#else
+static __rte_always_inline void
+nix_cqe_xtract_mseg(const union nix_rx_parse_u *rx, struct rte_mbuf *mbuf, uint64_t rearm,
+		    uintptr_t cpth, uintptr_t sa_base, const uint64_t buf_sz, const uint16_t flags)
+{
+	RTE_SET_USED(rx);
+	RTE_SET_USED(mbuf);
+	RTE_SET_USED(rearm);
+	RTE_SET_USED(cpth);
+	RTE_SET_USED(sa_base);
+	RTE_SET_USED(buf_sz);
+	RTE_SET_USED(flags);
+}
+#endif
 
 static __rte_always_inline void
 cn20k_nix_cqe_to_mbuf(const struct nix_cqe_hdr_s *cq, const uint32_t tag, struct rte_mbuf *mbuf,
-- 
2.34.1



More information about the dev mailing list