aboutsummaryrefslogtreecommitdiffstats
path: root/src/vnet/ip/icmp4.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vnet/ip/icmp4.c')
-rw-r--r--src/vnet/ip/icmp4.c39
1 files changed, 17 insertions, 22 deletions
diff --git a/src/vnet/ip/icmp4.c b/src/vnet/ip/icmp4.c
index a598ca9f174..ce81dc04f65 100644
--- a/src/vnet/ip/icmp4.c
+++ b/src/vnet/ip/icmp4.c
@@ -476,15 +476,29 @@ ip4_icmp_error (vlib_main_t * vm,
while (n_left_from > 0 && n_left_to_next > 0)
{
- u32 pi0 = from[0];
+ /*
+ * Duplicate first buffer and free the original chain. Keep
+ * as much of the original packet as possible, within the
+ * minimum MTU. We chat "a little" here by keeping whatever
+ * is available in the first buffer.
+ */
+
+ u32 pi0 = ~0;
+ u32 org_pi0 = from[0];
u32 next0 = IP4_ICMP_ERROR_NEXT_LOOKUP;
u8 error0 = ICMP4_ERROR_NONE;
- vlib_buffer_t *p0;
+ vlib_buffer_t *p0, *org_p0;
ip4_header_t *ip0, *out_ip0;
icmp46_header_t *icmp0;
u32 sw_if_index0, if_add_index0;
ip_csum_t sum;
+ org_p0 = vlib_get_buffer (vm, org_pi0);
+ p0 = vlib_buffer_copy_no_chain (vm, org_p0, &pi0);
+ vlib_buffer_free_one (vm, org_pi0);
+ if (!p0 || pi0 == ~0) /* Out of buffers */
+ continue;
+
/* Speculatively enqueue p0 to the current next frame */
to_next[0] = pi0;
from += 1;
@@ -492,28 +506,9 @@ ip4_icmp_error (vlib_main_t * vm,
n_left_from -= 1;
n_left_to_next -= 1;
- p0 = vlib_get_buffer (vm, pi0);
ip0 = vlib_buffer_get_current (p0);
sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
- /*
- * RFC1812 says to keep as much of the original packet as
- * possible within the minimum MTU (576). We cheat "a little"
- * here by keeping whatever fits in the first buffer, to be more
- * efficient
- */
- if (PREDICT_FALSE (p0->total_length_not_including_first_buffer))
- {
- /* clear current_length of all other buffers in chain */
- vlib_buffer_t *b = p0;
- p0->total_length_not_including_first_buffer = 0;
- while (b->flags & VLIB_BUFFER_NEXT_PRESENT)
- {
- b = vlib_get_buffer (vm, b->next_buffer);
- b->current_length = 0;
- }
- }
-
/* Add IP header and ICMPv4 header including a 4 byte data field */
vlib_buffer_advance (p0,
-sizeof (ip4_header_t) -
@@ -521,7 +516,6 @@ ip4_icmp_error (vlib_main_t * vm,
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];
@@ -570,6 +564,7 @@ ip4_icmp_error (vlib_main_t * vm,
/* Update error status */
if (error0 == ICMP4_ERROR_NONE)
error0 = icmp4_icmp_type_to_error (icmp0->type);
+
vlib_error_count (vm, node->node_index, error0, 1);
/* Verify speculative enqueue, maybe switch current next frame */