summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorOle Troan <ot@cisco.com>2018-05-18 11:01:31 +0200
committerFlorin Coras <florin.coras@gmail.com>2018-05-23 16:39:45 +0000
commit8a9c8f1412cb1258340b18a8eb622a835ef3c37b (patch)
treee8ec27f0cccb0aac65a984fd0509d8d6426995ac /src
parent2c2feab7d89239c92df4622c96e853230393deb9 (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.c2
-rw-r--r--src/vnet/ip/icmp4.c6
-rw-r--r--src/vnet/ip/ip4_forward.c69
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 ==