From: Vladimir Ratnikov Date: Tue, 14 Jan 2020 14:48:31 +0000 (-0500) Subject: map: ip4-map-t more RFC compliant X-Git-Tag: v20.09-rc0~705 X-Git-Url: https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commitdiff_plain;h=0d4a61216c2329eec5167d0411481431037ac5c1 map: ip4-map-t more RFC compliant When MTU is not set, ignore_df and mtu check always returns true and packets are dropped. This patch puts MTU checks after it was compared with 0 and set to maximum if not set. Added trace node. If MTU is less than the total length value of the IPv4 packet plus 20, the translator MUST send an ICMPv4 "Fragmentation Needed" error message to the IPv4 source address Type: fix Fixes: 87663cdf644fb7c94c0fec9460829b7e4e7c35ca Signed-off-by: Vladimir Ratnikov Change-Id: I35b99bc2648984cdbf5b6a57ddec91c586b15bef --- diff --git a/src/plugins/map/ip4_map_t.c b/src/plugins/map/ip4_map_t.c index dca32846480..d243a45cd41 100644 --- a/src/plugins/map/ip4_map_t.c +++ b/src/plugins/map/ip4_map_t.c @@ -22,6 +22,7 @@ typedef enum IP4_MAPT_NEXT_MAPT_TCP_UDP, IP4_MAPT_NEXT_MAPT_ICMP, IP4_MAPT_NEXT_MAPT_FRAGMENTED, + IP4_MAPT_NEXT_ICMP_ERROR, IP4_MAPT_NEXT_DROP, IP4_MAPT_N_NEXT } ip4_mapt_next_t; @@ -575,21 +576,31 @@ ip4_map_t (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) goto exit; } + dst_port0 = -1; + bool df0 = ip40->flags_and_fragment_offset & clib_host_to_net_u16 (IP4_HEADER_FLAG_DONT_FRAGMENT); + vnet_buffer (p0)->map_t.mtu = d0->mtu ? d0->mtu : ~0; + if (PREDICT_FALSE - (df0 && !map_main.frag_ignore_df && (ip4_len0 > d0->mtu))) + (df0 && !map_main.frag_ignore_df + && + ((ip4_len0 + + (sizeof (ip6_header_t) - sizeof (ip4_header_t))) > + vnet_buffer (p0)->map_t.mtu))) { - p0->error = error_node->errors[MAP_ERROR_FRAGMENT_DROPPED]; - next0 = IP4_MAPT_NEXT_DROP; - goto exit; + icmp4_error_set_vnet_buffer (p0, ICMP4_destination_unreachable, + ICMP4_destination_unreachable_fragmentation_needed_and_dont_fragment_set, + vnet_buffer (p0)->map_t.mtu - + (sizeof (ip6_header_t) - + sizeof (ip4_header_t))); + p0->error = error_node->errors[MAP_ERROR_DF_SET]; + next0 = IP4_MAPT_NEXT_ICMP_ERROR; + goto trace; } - vnet_buffer (p0)->map_t.mtu = d0->mtu ? d0->mtu : ~0; - - dst_port0 = -1; ip4_map_t_classify (p0, d0, ip40, ip4_len0, &dst_port0, &error0, &next0, l4_dst_port); @@ -626,7 +637,7 @@ ip4_map_t (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) next0 = (error0 != MAP_ERROR_NONE) ? IP4_MAPT_NEXT_DROP : next0; p0->error = error_node->errors[error0]; - + trace: if (PREDICT_FALSE (p0->flags & VLIB_BUFFER_IS_TRACED)) { map_add_trace (vm, node, p0, d0 - map_main.domains, dst_port0); @@ -730,6 +741,7 @@ VLIB_REGISTER_NODE(ip4_map_t_node) = { [IP4_MAPT_NEXT_MAPT_TCP_UDP] = "ip4-map-t-tcp-udp", [IP4_MAPT_NEXT_MAPT_ICMP] = "ip4-map-t-icmp", [IP4_MAPT_NEXT_MAPT_FRAGMENTED] = "ip4-map-t-fragmented", + [IP4_MAPT_NEXT_ICMP_ERROR] = "ip4-icmp-error", [IP4_MAPT_NEXT_DROP] = "error-drop", }, };