From 7c3275e84b64ade4e20d00e4457bd4e437b1894f Mon Sep 17 00:00:00 2001 From: Klement Sekera Date: Tue, 7 Dec 2021 09:49:53 +0000 Subject: ip: reassembly: handle atomic fragments correctly If a fragment arrives with fragment offset = 0 and M = 0, it means that this is actually a complete packet and per RFC 8200, it should be treated independently from other fragments. This patch does that. Fragmentation header is stripped and fragment is forwarded irregardles of other existing reassemblies in case of full reassembly and treated the same way as regular packet in shallow virtual reassembly. Type: improvement Change-Id: If3322d5e3160cd755b8465a642702a9166d46cc2 Signed-off-by: Klement Sekera --- src/vnet/ip/reass/ip6_sv_reass.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'src/vnet/ip/reass/ip6_sv_reass.c') diff --git a/src/vnet/ip/reass/ip6_sv_reass.c b/src/vnet/ip/reass/ip6_sv_reass.c index fb435ba9630..3656c5a8f61 100644 --- a/src/vnet/ip/reass/ip6_sv_reass.c +++ b/src/vnet/ip/reass/ip6_sv_reass.c @@ -215,7 +215,7 @@ format_ip6_sv_reass_trace (u8 * s, va_list * args) clib_net_to_host_u16 (t->l4_dst_port)); break; case REASS_PASSTHROUGH: - s = format (s, "[not-fragmented]"); + s = format (s, "[not fragmented or atomic fragment]"); break; } return s; @@ -532,13 +532,24 @@ ip6_sv_reassembly_inline (vlib_main_t * vm, ip6_header_t *ip0 = vlib_buffer_get_current (b0); ip6_frag_hdr_t *frag_hdr; ip6_ext_hdr_chain_t hdr_chain; + bool is_atomic_fragment = false; int res = ip6_ext_header_walk ( b0, ip0, IP_PROTOCOL_IPV6_FRAGMENTATION, &hdr_chain); + if (res >= 0 && + hdr_chain.eh[res].protocol == IP_PROTOCOL_IPV6_FRAGMENTATION) + { + frag_hdr = + ip6_ext_next_header_offset (ip0, hdr_chain.eh[res].offset); + is_atomic_fragment = (0 == ip6_frag_hdr_offset (frag_hdr) && + !ip6_frag_hdr_more (frag_hdr)); + } + if (res < 0 || - hdr_chain.eh[res].protocol != IP_PROTOCOL_IPV6_FRAGMENTATION) + hdr_chain.eh[res].protocol != IP_PROTOCOL_IPV6_FRAGMENTATION || + is_atomic_fragment) { - // this is a regular packet - no fragmentation + // this is a regular unfragmented packet or an atomic fragment if (!ip6_get_port (vm, b0, ip0, b0->current_length, &(vnet_buffer (b0)->ip.reass.ip_proto), @@ -565,10 +576,10 @@ ip6_sv_reassembly_inline (vlib_main_t * vm, } goto packet_enqueue; } - frag_hdr = - ip6_ext_next_header_offset (ip0, hdr_chain.eh[res].offset); + vnet_buffer (b0)->ip.reass.ip6_frag_hdr_offset = hdr_chain.eh[res].offset; + if (0 == ip6_frag_hdr_offset (frag_hdr)) { // first fragment - verify upper-layer is present -- cgit 1.2.3-korg