diff options
author | Ole Troan <ot@cisco.com> | 2018-05-18 11:01:31 +0200 |
---|---|---|
committer | Florin Coras <florin.coras@gmail.com> | 2018-05-23 16:39:45 +0000 |
commit | 8a9c8f1412cb1258340b18a8eb622a835ef3c37b (patch) | |
tree | e8ec27f0cccb0aac65a984fd0509d8d6426995ac /src | |
parent | 2c2feab7d89239c92df4622c96e853230393deb9 (diff) |
VPP-1283: IPv4 PMTU missing MTU value in ICMP4 message.
Change-Id: I7a4133c59ff45b0744b48e246a049d9f015026fc
Signed-off-by: Ole Troan <ot@cisco.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/plugins/igmp/igmp.c | 2 | ||||
-rw-r--r-- | src/vnet/ip/icmp4.c | 6 | ||||
-rw-r--r-- | src/vnet/ip/ip4_forward.c | 69 |
3 files changed, 44 insertions, 33 deletions
diff --git a/src/plugins/igmp/igmp.c b/src/plugins/igmp/igmp.c index 5ff88e58ec3..6499b5be466 100644 --- a/src/plugins/igmp/igmp.c +++ b/src/plugins/igmp/igmp.c @@ -712,7 +712,7 @@ igmp_timer_process (vlib_main_t * vm, vlib_node_runtime_t * rt, goto next_timer; IGMP_DBG ("time: %f", vlib_time_now (vm)); /* timer expired */ - if (NULL != timer) + if (NULL != timer && timer->func != NULL) timer->func (vm, rt, im, timer); next_timer: timer = igmp_get_next_timer (im); diff --git a/src/vnet/ip/icmp4.c b/src/vnet/ip/icmp4.c index 1fe01e48500..a4808f23271 100644 --- a/src/vnet/ip/icmp4.c +++ b/src/vnet/ip/icmp4.c @@ -513,13 +513,15 @@ ip4_icmp_error (vlib_main_t * vm, b->current_length = 0; } } - p0->current_length = - p0->current_length > 576 ? 576 : p0->current_length; /* Add IP header and ICMPv4 header including a 4 byte data field */ vlib_buffer_advance (p0, -sizeof (ip4_header_t) - sizeof (icmp46_header_t) - 4); + + p0->current_length = + p0->current_length > 576 ? 576 : p0->current_length; + out_ip0 = vlib_buffer_get_current (p0); icmp0 = (icmp46_header_t *) & out_ip0[1]; diff --git a/src/vnet/ip/ip4_forward.c b/src/vnet/ip/ip4_forward.c index ce2d619941c..40fe9dc447e 100644 --- a/src/vnet/ip/ip4_forward.c +++ b/src/vnet/ip/ip4_forward.c @@ -1963,6 +1963,29 @@ typedef enum #define IP4_MCAST_ADDR_MASK 0xffff7f00 #endif +always_inline void +ip4_mtu_check (vlib_buffer_t * b, u16 packet_len, + u16 adj_packet_bytes, bool df, u32 * next, u32 * error) +{ + if (packet_len > adj_packet_bytes) + { + *error = IP4_ERROR_MTU_EXCEEDED; + if (df) + { + icmp4_error_set_vnet_buffer + (b, ICMP4_destination_unreachable, + ICMP4_destination_unreachable_fragmentation_needed_and_dont_fragment_set, + adj_packet_bytes); + *next = IP4_REWRITE_NEXT_ICMP_ERROR; + } + else + { + /* Add support for fragmentation here */ + *next = IP4_REWRITE_NEXT_DROP; + } + } +} + always_inline uword ip4_rewrite_inline (vlib_main_t * vm, vlib_node_runtime_t * node, @@ -2123,26 +2146,16 @@ ip4_rewrite_inline (vlib_main_t * vm, vnet_buffer (p1)->ip.save_rewrite_length = rw_len1; /* Check MTU of outgoing interface. */ - if (vlib_buffer_length_in_chain (vm, p0) > - adj0[0].rewrite_header.max_l3_packet_bytes) - { - error0 = IP4_ERROR_MTU_EXCEEDED; - next0 = IP4_REWRITE_NEXT_ICMP_ERROR; - icmp4_error_set_vnet_buffer - (p0, ICMP4_destination_unreachable, - ICMP4_destination_unreachable_fragmentation_needed_and_dont_fragment_set, - 0); - } - if (vlib_buffer_length_in_chain (vm, p1) > - adj1[0].rewrite_header.max_l3_packet_bytes) - { - error1 = IP4_ERROR_MTU_EXCEEDED; - next1 = IP4_REWRITE_NEXT_ICMP_ERROR; - icmp4_error_set_vnet_buffer - (p1, ICMP4_destination_unreachable, - ICMP4_destination_unreachable_fragmentation_needed_and_dont_fragment_set, - 0); - } + ip4_mtu_check (p0, clib_net_to_host_u16 (ip0->length), + adj0[0].rewrite_header.max_l3_packet_bytes, + ip0->flags_and_fragment_offset & + clib_host_to_net_u16 (IP4_HEADER_FLAG_DONT_FRAGMENT), + &next0, &error0); + ip4_mtu_check (p1, clib_net_to_host_u16 (ip1->length), + adj1[0].rewrite_header.max_l3_packet_bytes, + ip1->flags_and_fragment_offset & + clib_host_to_net_u16 (IP4_HEADER_FLAG_DONT_FRAGMENT), + &next1, &error1); if (is_mcast) { @@ -2326,16 +2339,12 @@ ip4_rewrite_inline (vlib_main_t * vm, vlib_buffer_length_in_chain (vm, p0) + rw_len0); /* Check MTU of outgoing interface. */ - if (vlib_buffer_length_in_chain (vm, p0) > - adj0[0].rewrite_header.max_l3_packet_bytes) - { - error0 = IP4_ERROR_MTU_EXCEEDED; - next0 = IP4_REWRITE_NEXT_ICMP_ERROR; - icmp4_error_set_vnet_buffer - (p0, ICMP4_destination_unreachable, - ICMP4_destination_unreachable_fragmentation_needed_and_dont_fragment_set, - 0); - } + ip4_mtu_check (p0, clib_net_to_host_u16 (ip0->length), + adj0[0].rewrite_header.max_l3_packet_bytes, + ip0->flags_and_fragment_offset & + clib_host_to_net_u16 (IP4_HEADER_FLAG_DONT_FRAGMENT), + &next0, &error0); + if (is_mcast) { error0 = ((adj0[0].rewrite_header.sw_if_index == |