DPDK IPv4 reassembly code was not following RFC 791 section 3.2
which says:
    The internet identification field (ID) is used together with the
    source and destination address, and the protocol fields, to identify
    datagram fragments for reassembly.

Omitting the protocol means two datagrams between the
same pair of hosts that share an IP id but carry different protocols
(for example UDP and ICMP) are merged into a single reassembly context,
producing a corrupted datagram.

Fold the protocol into the unused upper bits of the 32-bit id field
of the key. The IPv4 identification is 16 bits and occupies the low
half, so the protocol can be carried in the upper bits without changing
the key layout, the key comparison or the hash.

Fixes: cc8f4d020c0b ("examples/ip_reassembly: initial import")
Cc: [email protected]

Signed-off-by: Stephen Hemminger <[email protected]>
---
 lib/ip_frag/rte_ipv4_reassembly.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/lib/ip_frag/rte_ipv4_reassembly.c 
b/lib/ip_frag/rte_ipv4_reassembly.c
index 3c8ae113ba..980f7a3b77 100644
--- a/lib/ip_frag/rte_ipv4_reassembly.c
+++ b/lib/ip_frag/rte_ipv4_reassembly.c
@@ -111,9 +111,15 @@ rte_ipv4_frag_reassemble_packet(struct rte_ip_frag_tbl 
*tbl,
        ip_ofs = (uint16_t)(flag_offset & RTE_IPV4_HDR_OFFSET_MASK);
        ip_flag = (uint16_t)(flag_offset & RTE_IPV4_HDR_MF_FLAG);
 
+       /*
+        * RFC 791 requires using: source, destination, identifier field and 
protocol
+        */
+
        /* use first 8 bytes only */
        memcpy(&key.src_dst[0], &ip_hdr->src_addr, 8);
-       key.id = ip_hdr->packet_id;
+
+       /* packet_id is 16 bits and proto id is 8 bits */
+       key.id = ((uint32_t) ip_hdr->next_proto_id << 16) | ip_hdr->packet_id;
        key.key_len = IPV4_KEYLEN;
 
        ip_ofs *= RTE_IPV4_HDR_OFFSET_UNITS;
-- 
2.53.0

Reply via email to