From: Rahul Bhansali <rbhans...@marvell.com>

In reassembly path, next header field in IPv6 header is not
updated correctly, hence reassembled packet is corrupted.
This fix will consider IPv6 fragment header presence at start/mid/end in
extension list and update the next header field accordingly.

Fixes: ec28231ed260 ("net/cnxk: support reassembly of multi-segment packets")

Signed-off-by: Rahul Bhansali <rbhans...@marvell.com>
---
 drivers/net/cnxk/cn10k_rx.h | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/net/cnxk/cn10k_rx.h b/drivers/net/cnxk/cn10k_rx.h
index 982fd26045..41d11349fd 100644
--- a/drivers/net/cnxk/cn10k_rx.h
+++ b/drivers/net/cnxk/cn10k_rx.h
@@ -205,26 +205,36 @@ nix_sec_reass_first_frag_update(struct rte_mbuf *head, 
const uint8_t *m_ipptr,
                struct rte_ipv6_hdr *hdr = (struct rte_ipv6_hdr *)ipptr;
                size_t ext_len = sizeof(struct rte_ipv6_hdr);
                uint8_t *nxt_hdr = (uint8_t *)hdr;
+               uint8_t *nxt_proto = &hdr->proto;
                int nh = hdr->proto;
 
                *ihl = 0;
+               tot_len = 0;
                while (nh != -EINVAL) {
                        nxt_hdr += ext_len;
                        *ihl += ext_len;
+                       if (nh == IPPROTO_FRAGMENT) {
+                               *nxt_proto = *nxt_hdr;
+                               tot_len = *ihl;
+                       }
                        nh = rte_ipv6_get_next_ext(nxt_hdr, nh, &ext_len);
+                       nxt_proto = nxt_hdr;
                }
 
                /* Remove the frag header by moving header 8 bytes forward */
                hdr->payload_len = rte_cpu_to_be_16(fragx_sum + *ihl -
                                        8 - 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 *),
-                          lcptr + sizeof(struct rte_ipv6_hdr));
+                          lcptr + tot_len);
 
                head->data_len -= 8;
                head->data_off += 8;
                head->pkt_len = lcptr + *ihl - 8 + fragx_sum;
+               /* ihl l3hdr size value should be up to fragment header for 
next frags */
+               *ihl = tot_len + 8;
        }
 }
 
-- 
2.25.1

Reply via email to