diff options
author | Chris Luke <chrisy@flirble.org> | 2016-06-14 16:24:47 -0400 |
---|---|---|
committer | Dave Barach <openvpp@barachs.net> | 2016-06-28 23:35:13 +0000 |
commit | 816f3e1b879b43802ea8035d6a3f1cbf5db76825 (patch) | |
tree | 84365630b1fa8faffc1c1ecd3e1a290d3afbbf50 /vnet/vnet/ip/ip6_forward.c | |
parent | 154d445f7f8f1553d9bb00d1be42bf1b06eda9f1 (diff) |
VPP-48 Fixes for ip4/6 ttl checks and icmp responses
This patch fixes a few minor things:
- Previously ip[46]_input was rejecting packets with an input TTL (hop
limit) of one; this was not correct behavior. Packets that are bound
for this device can validly have a TTL of one.
- ip[46]_forward was not generating an ICMP TTL expired message if the
act of decrementing the TTL caused it to become zero. This was not
previously an issue because ip[46]_input was filtering packets where
this could happen.
- udp_local was not generating ICMP Port Unreachable messages if
UDP packets arrived for a port that is not listened to. This is
typically the signal that "traceroute" uses to terminate its
search.
Together these fixes mean that traceroute probes transiting a VPP
node, or are targetted toward a VPP node, now work as expected.
Change-Id: I84bb940883f7a18435f29f4518fb0445b989a3e3
Signed-off-by: Chris Luke <chrisy@flirble.org>
Diffstat (limited to 'vnet/vnet/ip/ip6_forward.c')
-rw-r--r-- | vnet/vnet/ip/ip6_forward.c | 87 |
1 files changed, 66 insertions, 21 deletions
diff --git a/vnet/vnet/ip/ip6_forward.c b/vnet/vnet/ip/ip6_forward.c index afb23f1bf6c..eabaa89802b 100644 --- a/vnet/vnet/ip/ip6_forward.c +++ b/vnet/vnet/ip/ip6_forward.c @@ -2277,6 +2277,7 @@ ip6_probe_neighbor (vlib_main_t * vm, ip6_address_t * dst, u32 sw_if_index) typedef enum { IP6_REWRITE_NEXT_DROP, + IP6_REWRITE_NEXT_ICMP_ERROR, } ip6_rewrite_next_t; always_inline uword @@ -2345,6 +2346,7 @@ ip6_rewrite_inline (vlib_main_t * vm, ip1 = vlib_buffer_get_current (p1); error0 = error1 = IP6_ERROR_NONE; + next0 = next1 = IP6_REWRITE_NEXT_DROP; if (! rewrite_for_locally_received_packets) { @@ -2360,8 +2362,26 @@ ip6_rewrite_inline (vlib_main_t * vm, ip0->hop_limit = hop_limit0; ip1->hop_limit = hop_limit1; - error0 = hop_limit0 <= 0 ? IP6_ERROR_TIME_EXPIRED : error0; - error1 = hop_limit1 <= 0 ? IP6_ERROR_TIME_EXPIRED : error1; + /* + * If the hop count drops below 1 when forwarding, generate + * an ICMP response. + */ + if (PREDICT_FALSE(hop_limit0 <= 0)) + { + error0 = IP6_ERROR_TIME_EXPIRED; + next0 = IP6_REWRITE_NEXT_ICMP_ERROR; + vnet_buffer (p0)->sw_if_index[VLIB_TX] = (u32)~0; + icmp6_error_set_vnet_buffer(p0, ICMP6_time_exceeded, + ICMP6_time_exceeded_ttl_exceeded_in_transit, 0); + } + if (PREDICT_FALSE(hop_limit1 <= 0)) + { + error1 = IP6_ERROR_TIME_EXPIRED; + next1 = IP6_REWRITE_NEXT_ICMP_ERROR; + vnet_buffer (p1)->sw_if_index[VLIB_TX] = (u32)~0; + icmp6_error_set_vnet_buffer(p1, ICMP6_time_exceeded, + ICMP6_time_exceeded_ttl_exceeded_in_transit, 0); + } } adj0 = ip_get_adjacency (lm, adj_index0); @@ -2403,19 +2423,26 @@ ip6_rewrite_inline (vlib_main_t * vm, ? IP6_ERROR_MTU_EXCEEDED : error1); - p0->current_data -= rw_len0; - p1->current_data -= rw_len1; + /* Don't adjust the buffer for hop count issue; icmp-error node + * wants to see the IP headerr */ + if (PREDICT_TRUE(error0 == IP6_ERROR_NONE)) + { + p0->current_data -= rw_len0; + p0->current_length += rw_len0; - p0->current_length += rw_len0; - p1->current_length += rw_len1; + vnet_buffer (p0)->sw_if_index[VLIB_TX] = + adj0[0].rewrite_header.sw_if_index; + next0 = adj0[0].rewrite_header.next_index; + } + if (PREDICT_TRUE(error1 == IP6_ERROR_NONE)) + { + p1->current_data -= rw_len1; + p1->current_length += rw_len1; - vnet_buffer (p0)->sw_if_index[VLIB_TX] = adj0[0].rewrite_header.sw_if_index; - vnet_buffer (p1)->sw_if_index[VLIB_TX] = adj1[0].rewrite_header.sw_if_index; - - next0 = (error0 == IP6_ERROR_NONE) ? - adj0[0].rewrite_header.next_index : IP6_REWRITE_NEXT_DROP; - next1 = (error1 == IP6_ERROR_NONE) ? - adj1[0].rewrite_header.next_index : IP6_REWRITE_NEXT_DROP; + vnet_buffer (p1)->sw_if_index[VLIB_TX] = + adj1[0].rewrite_header.sw_if_index; + next1 = adj1[0].rewrite_header.next_index; + } /* Guess we are only writing on simple Ethernet header. */ vnet_rewrite_two_headers (adj0[0], adj1[0], @@ -2449,6 +2476,7 @@ ip6_rewrite_inline (vlib_main_t * vm, ip0 = vlib_buffer_get_current (p0); error0 = IP6_ERROR_NONE; + next0 = IP6_REWRITE_NEXT_DROP; /* Check hop limit */ if (! rewrite_for_locally_received_packets) @@ -2461,7 +2489,18 @@ ip6_rewrite_inline (vlib_main_t * vm, ip0->hop_limit = hop_limit0; - error0 = hop_limit0 <= 0 ? IP6_ERROR_TIME_EXPIRED : error0; + if (PREDICT_FALSE(hop_limit0 <= 0)) + { + /* + * If the hop count drops below 1 when forwarding, generate + * an ICMP response. + */ + error0 = IP6_ERROR_TIME_EXPIRED; + next0 = IP6_REWRITE_NEXT_ICMP_ERROR; + vnet_buffer (p0)->sw_if_index[VLIB_TX] = (u32)~0; + icmp6_error_set_vnet_buffer(p0, ICMP6_time_exceeded, + ICMP6_time_exceeded_ttl_exceeded_in_transit, 0); + } } if (rewrite_for_locally_received_packets) @@ -2488,12 +2527,17 @@ ip6_rewrite_inline (vlib_main_t * vm, ? IP6_ERROR_MTU_EXCEEDED : error0); - p0->current_data -= rw_len0; - p0->current_length += rw_len0; - vnet_buffer (p0)->sw_if_index[VLIB_TX] = adj0[0].rewrite_header.sw_if_index; - - next0 = (error0 == IP6_ERROR_NONE) ? - adj0[0].rewrite_header.next_index : IP6_REWRITE_NEXT_DROP; + /* Don't adjust the buffer for hop count issue; icmp-error node + * wants to see the IP headerr */ + if (PREDICT_TRUE(error0 == IP6_ERROR_NONE)) + { + p0->current_data -= rw_len0; + p0->current_length += rw_len0; + + vnet_buffer (p0)->sw_if_index[VLIB_TX] = + adj0[0].rewrite_header.sw_if_index; + next0 = adj0[0].rewrite_header.next_index; + } p0->error = error_node->errors[error0]; @@ -2542,9 +2586,10 @@ VLIB_REGISTER_NODE (ip6_rewrite_node) = { .format_trace = format_ip6_rewrite_trace, - .n_next_nodes = 1, + .n_next_nodes = 2, .next_nodes = { [IP6_REWRITE_NEXT_DROP] = "error-drop", + [IP6_REWRITE_NEXT_ICMP_ERROR] = "ip6-icmp-error", }, }; |