FD.io VPP  v21.10.1-2-g0a485f517
Vector Packet Processing
icmp6.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 /*
16  * ip/icmp6.c: ip6 icmp
17  *
18  * Copyright (c) 2008 Eliot Dresselhaus
19  *
20  * Permission is hereby granted, free of charge, to any person obtaining
21  * a copy of this software and associated documentation files (the
22  * "Software"), to deal in the Software without restriction, including
23  * without limitation the rights to use, copy, modify, merge, publish,
24  * distribute, sublicense, and/or sell copies of the Software, and to
25  * permit persons to whom the Software is furnished to do so, subject to
26  * the following conditions:
27  *
28  * The above copyright notice and this permission notice shall be
29  * included in all copies or substantial portions of the Software.
30  *
31  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
34  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
35  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
36  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
37  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38  */
39 
40 #include <vlib/vlib.h>
41 #include <vnet/ip/ip.h>
42 #include <vnet/pg/pg.h>
43 #include <vnet/ip/ip_sas.h>
44 
45 static u8 *
46 format_ip6_icmp_type_and_code (u8 * s, va_list * args)
47 {
48  icmp6_type_t type = va_arg (*args, int);
49  u8 code = va_arg (*args, int);
50  char *t = 0;
51 
52 #define _(n,f) case n: t = #f; break;
53 
54  switch (type)
55  {
57 
58  default:
59  break;
60  }
61 
62 #undef _
63 
64  if (!t)
65  return format (s, "unknown 0x%x", type);
66 
67  s = format (s, "%s", t);
68 
69  t = 0;
70  switch ((type << 8) | code)
71  {
72 #define _(a,n,f) case (ICMP6_##a << 8) | (n): t = #f; break;
73 
75 
76 #undef _
77  }
78 
79  if (t)
80  s = format (s, " %s", t);
81 
82  return s;
83 }
84 
85 static u8 *
86 format_icmp6_header (u8 * s, va_list * args)
87 {
88  icmp46_header_t *icmp = va_arg (*args, icmp46_header_t *);
89  u32 max_header_bytes = va_arg (*args, u32);
90 
91  /* Nothing to do. */
92  if (max_header_bytes < sizeof (icmp[0]))
93  return format (s, "ICMP header truncated");
94 
95  s = format (s, "ICMP %U checksum 0x%x",
97  clib_net_to_host_u16 (icmp->checksum));
98 
99  if (max_header_bytes >=
100  sizeof (icmp6_neighbor_solicitation_or_advertisement_header_t) &&
101  (icmp->type == ICMP6_neighbor_solicitation ||
102  icmp->type == ICMP6_neighbor_advertisement))
103  {
104  icmp6_neighbor_solicitation_or_advertisement_header_t *icmp6_nd =
105  (icmp6_neighbor_solicitation_or_advertisement_header_t *) icmp;
106  s = format (s, "\n target address %U",
107  format_ip6_address, &icmp6_nd->target_address);
108  }
109 
110  return s;
111 }
112 
113 u8 *
114 format_icmp6_input_trace (u8 * s, va_list * va)
115 {
116  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
117  CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
118  icmp6_input_trace_t *t = va_arg (*va, icmp6_input_trace_t *);
119 
120  s = format (s, "%U",
121  format_ip6_header, t->packet_data, sizeof (t->packet_data));
122 
123  return s;
124 }
125 
126 static char *icmp_error_strings[] = {
127 #define _(f,s) s,
129 #undef _
130 };
131 
132 typedef enum
133 {
137 
138 typedef struct
139 {
141 
143 
144  /* Vector dispatch table indexed by [icmp type]. */
145  u8 input_next_index_by_type[256];
146 
147  /* Max valid code indexed by icmp type. */
148  u8 max_valid_code_by_type[256];
149 
150  /* hop_limit must be >= this value for this icmp type. */
151  u8 min_valid_hop_limit_by_type[256];
152 
153  u8 min_valid_length_by_type[256];
154 } icmp6_main_t;
155 
157 
158 static uword
161 {
163  u32 *from, *to_next;
164  u32 n_left_from, n_left_to_next, next_index;
165 
167  n_left_from = frame->n_vectors;
168  next_index = node->cached_next_index;
169 
170  if (node->flags & VLIB_NODE_FLAG_TRACE)
172  /* stride */ 1,
173  sizeof (icmp6_input_trace_t));
174 
175  while (n_left_from > 0)
176  {
177  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
178 
179  while (n_left_from > 0 && n_left_to_next > 0)
180  {
181  vlib_buffer_t *b0;
182  ip6_header_t *ip0;
183  icmp46_header_t *icmp0;
184  icmp6_type_t type0;
185  u32 bi0, next0, error0, len0;
186 
187  bi0 = to_next[0] = from[0];
188 
189  from += 1;
190  n_left_from -= 1;
191  to_next += 1;
192  n_left_to_next -= 1;
193 
194  b0 = vlib_get_buffer (vm, bi0);
195  ip0 = vlib_buffer_get_current (b0);
196  icmp0 = ip6_next_header (ip0);
197  type0 = icmp0->type;
198 
199  error0 = ICMP6_ERROR_NONE;
200 
201  next0 = im->input_next_index_by_type[type0];
202  error0 =
203  next0 == ICMP_INPUT_NEXT_PUNT ? ICMP6_ERROR_UNKNOWN_TYPE : error0;
204 
205  /* Check code is valid for type. */
206  error0 =
207  icmp0->code >
208  im->max_valid_code_by_type[type0] ?
209  ICMP6_ERROR_INVALID_CODE_FOR_TYPE : error0;
210 
211  /* Checksum is already validated by ip6_local node so we don't need to check that. */
212 
213  /* Check that hop limit == 255 for certain types. */
214  error0 =
215  ip0->hop_limit <
216  im->min_valid_hop_limit_by_type[type0] ?
217  ICMP6_ERROR_INVALID_HOP_LIMIT_FOR_TYPE : error0;
218 
219  len0 = clib_net_to_host_u16 (ip0->payload_length);
220  error0 =
221  len0 <
222  im->min_valid_length_by_type[type0] ?
223  ICMP6_ERROR_LENGTH_TOO_SMALL_FOR_TYPE : error0;
224 
225  b0->error = node->errors[error0];
226 
227  next0 = error0 != ICMP6_ERROR_NONE ? ICMP_INPUT_NEXT_PUNT : next0;
228 
230  to_next, n_left_to_next,
231  bi0, next0);
232  }
233 
234  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
235  }
236 
237  return frame->n_vectors;
238 }
239 
240 /* *INDENT-OFF* */
242  .function = ip6_icmp_input,
243  .name = "ip6-icmp-input",
244 
245  .vector_size = sizeof (u32),
246 
247  .format_trace = format_icmp6_input_trace,
248 
249  .n_errors = ARRAY_LEN (icmp_error_strings),
250  .error_strings = icmp_error_strings,
251 
252  .n_next_nodes = 1,
253  .next_nodes = {
254  [ICMP_INPUT_NEXT_PUNT] = "ip6-punt",
255  },
256 };
257 /* *INDENT-ON* */
258 
259 typedef enum
260 {
265 
266 static uword
269 {
270  u32 *from, *to_next;
271  u32 n_left_from, n_left_to_next, next_index;
272  ip6_main_t *im = &ip6_main;
273 
275  n_left_from = frame->n_vectors;
276  next_index = node->cached_next_index;
277 
278  if (node->flags & VLIB_NODE_FLAG_TRACE)
280  /* stride */ 1,
281  sizeof (icmp6_input_trace_t));
282 
283  while (n_left_from > 0)
284  {
285  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
286 
287  while (n_left_from > 2 && n_left_to_next > 2)
288  {
289  vlib_buffer_t *p0, *p1;
290  ip6_header_t *ip0, *ip1;
291  icmp46_header_t *icmp0, *icmp1;
292  ip6_address_t tmp0, tmp1;
293  ip_csum_t sum0, sum1;
294  u32 bi0, bi1;
295  u32 fib_index0, fib_index1;
298 
299  bi0 = to_next[0] = from[0];
300  bi1 = to_next[1] = from[1];
301 
302  from += 2;
303  n_left_from -= 2;
304  to_next += 2;
305  n_left_to_next -= 2;
306 
307  p0 = vlib_get_buffer (vm, bi0);
308  p1 = vlib_get_buffer (vm, bi1);
309  ip0 = vlib_buffer_get_current (p0);
310  ip1 = vlib_buffer_get_current (p1);
311  icmp0 = ip6_next_header (ip0);
312  icmp1 = ip6_next_header (ip1);
313 
314  /* Check icmp type to echo reply and update icmp checksum. */
315  sum0 = icmp0->checksum;
316  sum1 = icmp1->checksum;
317 
318  ASSERT (icmp0->type == ICMP6_echo_request);
319  ASSERT (icmp1->type == ICMP6_echo_request);
320  sum0 = ip_csum_update (sum0, ICMP6_echo_request, ICMP6_echo_reply,
321  icmp46_header_t, type);
322  sum1 = ip_csum_update (sum1, ICMP6_echo_request, ICMP6_echo_reply,
323  icmp46_header_t, type);
324 
325  icmp0->checksum = ip_csum_fold (sum0);
326  icmp1->checksum = ip_csum_fold (sum1);
327 
328  icmp0->type = ICMP6_echo_reply;
329  icmp1->type = ICMP6_echo_reply;
330 
331  /* Swap source and destination address. */
332  tmp0 = ip0->src_address;
333  tmp1 = ip1->src_address;
334 
335  ip0->src_address = ip0->dst_address;
336  ip1->src_address = ip1->dst_address;
337 
338  ip0->dst_address = tmp0;
339  ip1->dst_address = tmp1;
340 
341  /* New hop count. */
342  ip0->hop_limit = im->host_config.ttl;
343  ip1->hop_limit = im->host_config.ttl;
344 
345  /* Determine the correct lookup fib indices... */
346  fib_index0 = vec_elt (im->fib_index_by_sw_if_index,
348  vnet_buffer (p0)->sw_if_index[VLIB_TX] = fib_index0;
349  /* Determine the correct lookup fib indices... */
350  fib_index1 = vec_elt (im->fib_index_by_sw_if_index,
352  vnet_buffer (p1)->sw_if_index[VLIB_TX] = fib_index1;
353 
354  p0->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
355  p1->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
356 
357  /* verify speculative enqueues, maybe switch current next frame */
358  /* if next0==next1==next_index then nothing special needs to be done */
360  to_next, n_left_to_next,
361  bi0, bi1, next0, next1);
362  }
363 
364  while (n_left_from > 0 && n_left_to_next > 0)
365  {
366  vlib_buffer_t *p0;
367  ip6_header_t *ip0;
368  icmp46_header_t *icmp0;
369  u32 bi0;
370  ip6_address_t tmp0;
371  ip_csum_t sum0;
372  u32 fib_index0;
374 
375  bi0 = to_next[0] = from[0];
376 
377  from += 1;
378  n_left_from -= 1;
379  to_next += 1;
380  n_left_to_next -= 1;
381 
382  p0 = vlib_get_buffer (vm, bi0);
383  ip0 = vlib_buffer_get_current (p0);
384  icmp0 = ip6_next_header (ip0);
385 
386  /* Check icmp type to echo reply and update icmp checksum. */
387  sum0 = icmp0->checksum;
388 
389  ASSERT (icmp0->type == ICMP6_echo_request);
390  sum0 = ip_csum_update (sum0, ICMP6_echo_request, ICMP6_echo_reply,
391  icmp46_header_t, type);
392 
393  icmp0->checksum = ip_csum_fold (sum0);
394 
395  icmp0->type = ICMP6_echo_reply;
396 
397  /* Swap source and destination address. */
398  tmp0 = ip0->src_address;
399  ip0->src_address = ip0->dst_address;
400  ip0->dst_address = tmp0;
401 
402  ip0->hop_limit = im->host_config.ttl;
403 
404  /* if the packet is link local, we'll bounce through the link-local
405  * table with the RX interface correctly set */
406  fib_index0 = vec_elt (im->fib_index_by_sw_if_index,
408  vnet_buffer (p0)->sw_if_index[VLIB_TX] = fib_index0;
409 
410  p0->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
411  /* Verify speculative enqueue, maybe switch current next frame */
413  to_next, n_left_to_next,
414  bi0, next0);
415  }
416 
417  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
418  }
419 
421  ICMP6_ERROR_ECHO_REPLIES_SENT, frame->n_vectors);
422 
423  return frame->n_vectors;
424 }
425 
426 /* *INDENT-OFF* */
428  .function = ip6_icmp_echo_request,
429  .name = "ip6-icmp-echo-request",
430 
431  .vector_size = sizeof (u32),
432 
433  .format_trace = format_icmp6_input_trace,
434 
435  .n_next_nodes = ICMP6_ECHO_REQUEST_N_NEXT,
436  .next_nodes = {
437  [ICMP6_ECHO_REQUEST_NEXT_LOOKUP] = "ip6-lookup",
438  [ICMP6_ECHO_REQUEST_NEXT_OUTPUT] = "interface-output",
439  },
440 };
441 /* *INDENT-ON* */
442 
443 typedef enum
444 {
449 
450 void
452 {
453  vnet_buffer (b)->ip.icmp.type = type;
454  vnet_buffer (b)->ip.icmp.code = code;
455  vnet_buffer (b)->ip.icmp.data = data;
456 }
457 
458 static u8
460 {
461  switch (type)
462  {
463  case ICMP6_destination_unreachable:
464  return ICMP6_ERROR_DEST_UNREACH_SENT;
465  case ICMP6_packet_too_big:
466  return ICMP6_ERROR_PACKET_TOO_BIG_SENT;
467  case ICMP6_time_exceeded:
468  return ICMP6_ERROR_TTL_EXPIRE_SENT;
469  case ICMP6_parameter_problem:
470  return ICMP6_ERROR_PARAM_PROBLEM_SENT;
471  default:
472  return ICMP6_ERROR_DROP;
473  }
474 }
475 
476 static uword
479 {
480  u32 *from, *to_next;
481  uword n_left_from, n_left_to_next;
483 
485  n_left_from = frame->n_vectors;
486  next_index = node->cached_next_index;
487 
488  if (node->flags & VLIB_NODE_FLAG_TRACE)
490  /* stride */ 1,
491  sizeof (icmp6_input_trace_t));
492 
493  while (n_left_from > 0)
494  {
495  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
496 
497  while (n_left_from > 0 && n_left_to_next > 0)
498  {
499  /*
500  * Duplicate first buffer and free the original chain. Keep
501  * as much of the original packet as possible, within the
502  * minimum MTU. We chat "a little" here by keeping whatever
503  * is available in the first buffer.
504  */
505 
506  u32 pi0 = ~0;
507  u32 org_pi0 = from[0];
509  u8 error0 = ICMP6_ERROR_NONE;
510  vlib_buffer_t *p0, *org_p0;
511  ip6_header_t *ip0, *out_ip0;
512  icmp46_header_t *icmp0;
513  u32 sw_if_index0;
514  int bogus_length;
515 
516  org_p0 = vlib_get_buffer (vm, org_pi0);
517  p0 = vlib_buffer_copy_no_chain (vm, org_p0, &pi0);
518  if (!p0 || pi0 == ~0) /* Out of buffers */
519  continue;
520 
521  /* Speculatively enqueue p0 to the current next frame */
522  to_next[0] = pi0;
523  from += 1;
524  to_next += 1;
525  n_left_from -= 1;
526  n_left_to_next -= 1;
527 
528  ip0 = vlib_buffer_get_current (p0);
529  sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
530 
531  /* Add IP header and ICMPv6 header including a 4 byte data field */
533  -(sizeof (ip6_header_t) +
534  sizeof (icmp46_header_t) + 4));
535 
536  vnet_buffer (p0)->sw_if_index[VLIB_TX] = ~0;
537  p0->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
538  p0->current_length =
539  p0->current_length > 1280 ? 1280 : p0->current_length;
540 
541  out_ip0 = vlib_buffer_get_current (p0);
542  icmp0 = (icmp46_header_t *) & out_ip0[1];
543 
544  /* Fill ip header fields */
546  clib_host_to_net_u32 (0x6 << 28);
547 
548  out_ip0->payload_length =
549  clib_host_to_net_u16 (p0->current_length - sizeof (ip6_header_t));
550  out_ip0->protocol = IP_PROTOCOL_ICMP6;
551  out_ip0->hop_limit = 0xff;
552  out_ip0->dst_address = ip0->src_address;
553  /* Prefer a source address from "offending interface" */
554  if (!ip6_sas_by_sw_if_index (sw_if_index0, &out_ip0->dst_address,
555  &out_ip0->src_address))
556  { /* interface has no IP6 address - should not happen */
557  next0 = IP6_ICMP_ERROR_NEXT_DROP;
558  error0 = ICMP6_ERROR_DROP;
559  }
560 
561  /* Fill icmp header fields */
562  icmp0->type = vnet_buffer (p0)->ip.icmp.type;
563  icmp0->code = vnet_buffer (p0)->ip.icmp.code;
564  *((u32 *) (icmp0 + 1)) =
565  clib_host_to_net_u32 (vnet_buffer (p0)->ip.icmp.data);
566  icmp0->checksum = 0;
567  icmp0->checksum =
569  &bogus_length);
570 
571  /* Update error status */
572  if (error0 == ICMP6_ERROR_NONE)
573  error0 = icmp6_icmp_type_to_error (icmp0->type);
574 
575  vlib_error_count (vm, node->node_index, error0, 1);
576 
577  /* Verify speculative enqueue, maybe switch current next frame */
579  to_next, n_left_to_next,
580  pi0, next0);
581  }
582  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
583  }
584 
585  /*
586  * push the original buffers to error-drop, so that
587  * they can get the error counters handled, then freed
588  */
592  frame->n_vectors);
593 
594  return frame->n_vectors;
595 }
596 
597 /* *INDENT-OFF* */
599  .function = ip6_icmp_error,
600  .name = "ip6-icmp-error",
601  .vector_size = sizeof (u32),
602 
603  .n_errors = ARRAY_LEN (icmp_error_strings),
604  .error_strings = icmp_error_strings,
605 
606  .n_next_nodes = IP6_ICMP_ERROR_N_NEXT,
607  .next_nodes = {
608  [IP6_ICMP_ERROR_NEXT_DROP] = "error-drop",
609  [IP6_ICMP_ERROR_NEXT_LOOKUP] = "ip6-lookup",
610  },
611 
612  .format_trace = format_icmp6_input_trace,
613 };
614 /* *INDENT-ON* */
615 
616 
617 static uword
619 {
620  icmp46_header_t *h = va_arg (*args, icmp46_header_t *);
622  u32 i;
623 
625  cm->type_and_code_by_name, &i))
626  {
627  h->type = (i >> 8) & 0xff;
628  h->code = (i >> 0) & 0xff;
629  }
631  cm->type_by_name, &i))
632  {
633  h->type = i;
634  h->code = 0;
635  }
636  else
637  return 0;
638 
639  return 1;
640 }
641 
642 static void
644  pg_stream_t * s,
645  pg_edit_group_t * g, u32 * packets, u32 n_packets)
646 {
648  u32 ip_offset, icmp_offset;
649  int bogus_length;
650 
651  icmp_offset = g->start_byte_offset;
652  ip_offset = (g - 1)->start_byte_offset;
653 
654  while (n_packets >= 1)
655  {
656  vlib_buffer_t *p0;
657  ip6_header_t *ip0;
658  icmp46_header_t *icmp0;
659 
660  p0 = vlib_get_buffer (vm, packets[0]);
661  n_packets -= 1;
662  packets += 1;
663 
664  ASSERT (p0->current_data == 0);
665  ip0 = (void *) (p0->data + ip_offset);
666  icmp0 = (void *) (p0->data + icmp_offset);
667 
668  icmp0->checksum = ip6_tcp_udp_icmp_compute_checksum (vm, p0, ip0,
669  &bogus_length);
670  ASSERT (bogus_length == 0);
671  }
672 }
673 
674 typedef struct
675 {
676  pg_edit_t type, code;
677  pg_edit_t checksum;
679 
680 always_inline void
682 {
683  /* Initialize fields that are not bit fields in the IP header. */
684 #define _(f) pg_edit_init (&p->f, icmp46_header_t, f);
685  _(type);
686  _(code);
687  _(checksum);
688 #undef _
689 }
690 
691 static uword
692 unformat_pg_icmp_header (unformat_input_t * input, va_list * args)
693 {
694  pg_stream_t *s = va_arg (*args, pg_stream_t *);
696  u32 group_index;
697 
698  p = pg_create_edit_group (s, sizeof (p[0]), sizeof (icmp46_header_t),
699  &group_index);
701 
703 
704  {
705  icmp46_header_t tmp;
706 
707  if (!unformat (input, "ICMP %U", unformat_icmp_type_and_code, &tmp))
708  goto error;
709 
710  pg_edit_set_fixed (&p->type, tmp.type);
711  pg_edit_set_fixed (&p->code, tmp.code);
712  }
713 
714  /* Parse options. */
715  while (1)
716  {
717  if (unformat (input, "checksum %U",
719  ;
720 
721  /* Can't parse input: try next protocol level. */
722  else
723  break;
724  }
725 
726  if (!unformat_user (input, unformat_pg_payload, s))
727  goto error;
728 
730  {
731  pg_edit_group_t *g = pg_stream_get_group (s, group_index);
733  g->edit_function_opaque = 0;
734  }
735 
736  return 1;
737 
738 error:
739  /* Free up any edits we may have added. */
740  pg_free_edit_group (s);
741  return 0;
742 }
743 
744 void
746 {
748 
749  ASSERT ((int) type < ARRAY_LEN (im->input_next_index_by_type));
750  im->input_next_index_by_type[type]
752 }
753 
754 static clib_error_t *
756 {
757  ip_main_t *im = &ip_main;
758  ip_protocol_info_t *pi;
761 
763 
764  if (error)
765  return error;
766 
767  pi = ip_get_protocol_info (im, IP_PROTOCOL_ICMP6);
770 
771  cm->type_by_name = hash_create_string (0, sizeof (uword));
772 #define _(n,t) hash_set_mem (cm->type_by_name, #t, (n));
774 #undef _
775 
776  cm->type_and_code_by_name = hash_create_string (0, sizeof (uword));
777 #define _(a,n,t) hash_set_mem (cm->type_by_name, #t, (n) | (ICMP6_##a << 8));
779 #undef _
780 
781  clib_memset (cm->input_next_index_by_type,
782  ICMP_INPUT_NEXT_PUNT, sizeof (cm->input_next_index_by_type));
783  clib_memset (cm->max_valid_code_by_type, 0,
784  sizeof (cm->max_valid_code_by_type));
785 
786 #define _(a,n,t) cm->max_valid_code_by_type[ICMP6_##a] = clib_max (cm->max_valid_code_by_type[ICMP6_##a], n);
788 #undef _
789 
790  clib_memset (cm->min_valid_hop_limit_by_type, 0,
791  sizeof (cm->min_valid_hop_limit_by_type));
792  cm->min_valid_hop_limit_by_type[ICMP6_router_solicitation] = 255;
793  cm->min_valid_hop_limit_by_type[ICMP6_router_advertisement] = 255;
794  cm->min_valid_hop_limit_by_type[ICMP6_neighbor_solicitation] = 255;
795  cm->min_valid_hop_limit_by_type[ICMP6_neighbor_advertisement] = 255;
796  cm->min_valid_hop_limit_by_type[ICMP6_redirect] = 255;
797 
798  clib_memset (cm->min_valid_length_by_type, sizeof (icmp46_header_t),
799  sizeof (cm->min_valid_length_by_type));
800  cm->min_valid_length_by_type[ICMP6_router_solicitation] =
801  sizeof (icmp6_neighbor_discovery_header_t);
802  cm->min_valid_length_by_type[ICMP6_router_advertisement] =
803  sizeof (icmp6_router_advertisement_header_t);
804  cm->min_valid_length_by_type[ICMP6_neighbor_solicitation] =
805  sizeof (icmp6_neighbor_solicitation_or_advertisement_header_t);
806  cm->min_valid_length_by_type[ICMP6_neighbor_advertisement] =
807  sizeof (icmp6_neighbor_solicitation_or_advertisement_header_t);
808  cm->min_valid_length_by_type[ICMP6_redirect] =
809  sizeof (icmp6_redirect_header_t);
810 
811  icmp6_register_type (vm, ICMP6_echo_request,
813 
814  return (NULL);
815 }
816 
818 
819 /*
820  * fd.io coding-style-patch-verification: ON
821  *
822  * Local Variables:
823  * eval: (c-set-style "gnu")
824  * End:
825  */
vlib.h
tmp
u32 * tmp
Definition: interface_output.c:1096
icmp_error_strings
static char * icmp_error_strings[]
Definition: icmp6.c:126
icmp6_main
icmp6_main_t icmp6_main
Definition: icmp6.c:156
im
vnet_interface_main_t * im
Definition: interface_output.c:415
pg_icmp46_header_t
Definition: icmp4.c:455
pg_edit_set_fixed
static void pg_edit_set_fixed(pg_edit_t *e, u64 value)
Definition: edit.h:153
unformat_user
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:989
pg_edit_group_t::start_byte_offset
u32 start_byte_offset
Definition: pg.h:69
frame
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: nat44_ei.c:3048
icmp6_error_set_vnet_buffer
void icmp6_error_set_vnet_buffer(vlib_buffer_t *b, u8 type, u8 code, u32 data)
Definition: icmp6.c:451
vlib_node_add_next
static uword vlib_node_add_next(vlib_main_t *vm, uword node, uword next_node)
Definition: node_funcs.h:1177
ip6_tcp_udp_icmp_compute_checksum
u16 ip6_tcp_udp_icmp_compute_checksum(vlib_main_t *vm, vlib_buffer_t *p0, ip6_header_t *ip0, int *bogus_lengthp)
Definition: ip6_forward.c:1096
pg_icmp46_header_t::checksum
pg_edit_t checksum
Definition: icmp4.c:458
next_index
nat44_ei_hairpin_src_next_t next_index
Definition: nat44_ei_hairpinning.c:412
pg_icmp_header_init
static void pg_icmp_header_init(pg_icmp46_header_t *p)
Definition: icmp6.c:681
pg.h
vlib_get_buffer
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:111
format_ip6_header
format_function_t format_ip6_header
Definition: format.h:95
ip6_icmp_echo_request
static uword ip6_icmp_echo_request(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: icmp6.c:267
ip6_header_t::protocol
u8 protocol
Definition: ip6_packet.h:304
ICMP_INPUT_NEXT_PUNT
@ ICMP_INPUT_NEXT_PUNT
Definition: icmp6.c:134
vlib_trace_frame_buffers_only
void vlib_trace_frame_buffers_only(vlib_main_t *vm, vlib_node_runtime_t *node, u32 *buffers, uword n_buffers, uword next_buffer_stride, uword n_buffer_data_bytes_in_trace)
Definition: trace.c:48
PG_EDIT_UNSPECIFIED
@ PG_EDIT_UNSPECIFIED
Definition: edit.h:61
node
vlib_main_t vlib_node_runtime_t * node
Definition: nat44_ei.c:3047
ip6_header_t::hop_limit
u8 hop_limit
Definition: ip6_packet.h:307
ip_main
ip_main_t ip_main
Definition: ip_init.c:42
ip_get_protocol_info
static ip_protocol_info_t * ip_get_protocol_info(ip_main_t *im, u32 protocol)
Definition: ip.h:134
hash_create_string
#define hash_create_string(elts, value_bytes)
Definition: hash.h:689
ip_protocol_info_t::format_header
format_function_t * format_header
Definition: ip.h:79
ip_sas.h
ip6_icmp_error
static uword ip6_icmp_error(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: icmp6.c:477
vlib_call_init_function
#define vlib_call_init_function(vm, x)
Definition: init.h:259
vm
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
VLIB_RX
@ VLIB_RX
Definition: defs.h:46
node_index
node node_index
Definition: interface_output.c:440
foreach_icmp6_code
@ foreach_icmp6_code
Definition: icmp46_packet.h:186
unformat_pg_number
uword unformat_pg_number(unformat_input_t *input, va_list *args)
Definition: edit.c:85
unformat_input_t
struct _unformat_input_t unformat_input_t
icmp6_echo_request_next_t
icmp6_echo_request_next_t
Definition: icmp6.c:259
vlib_error_count
static void vlib_error_count(vlib_main_t *vm, uword node_index, uword counter, uword increment)
Definition: error_funcs.h:57
ip6_next_header
static void * ip6_next_header(ip6_header_t *i)
Definition: ip6_packet.h:407
vlib_frame_t
Definition: node.h:372
h
h
Definition: flowhash_template.h:372
error
Definition: cJSON.c:88
ip6_icmp_echo_request_node
static vlib_node_registration_t ip6_icmp_echo_request_node
(constructor) VLIB_REGISTER_NODE (ip6_icmp_echo_request_node)
Definition: icmp6.c:427
unformat
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
vec_elt
#define vec_elt(v, i)
Get vector value at index i.
Definition: vec_bootstrap.h:210
icmp6_register_type
void icmp6_register_type(vlib_main_t *vm, icmp6_type_t type, u32 node_index)
Definition: icmp6.c:745
vlib_buffer_t::current_data
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:119
vlib_buffer_enqueue_to_single_next
static_always_inline void vlib_buffer_enqueue_to_single_next(vlib_main_t *vm, vlib_node_runtime_t *node, u32 *buffers, u16 next_index, u32 count)
Definition: buffer_node.h:373
pg_edit_group_t::edit_function_opaque
uword edit_function_opaque
Definition: pg.h:81
vlib_buffer_advance
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:276
pg_edit_group_t
Definition: pg.h:56
vlib_buffer_t::error
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:145
icmp_input_next_t
icmp_input_next_t
Definition: icmp6.c:132
icmp6_input_trace_t
Definition: icmp6.h:62
icmp6_type_t
icmp6_type_t
Definition: icmp46_packet.h:176
ip6_icmp_input
static uword ip6_icmp_input(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: icmp6.c:159
CLIB_UNUSED
#define CLIB_UNUSED(x)
Definition: clib.h:90
vnet_buffer
#define vnet_buffer(b)
Definition: buffer.h:441
VLIB_NODE_FLAG_TRACE
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:291
ARRAY_LEN
#define ARRAY_LEN(x)
Definition: clib.h:70
vlib_frame_vector_args
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:301
pg_edit_t::type
pg_edit_type_t type
Definition: edit.h:66
ICMP6_ECHO_REQUEST_NEXT_LOOKUP
@ ICMP6_ECHO_REQUEST_NEXT_LOOKUP
Definition: icmp6.c:261
uword
u64 uword
Definition: types.h:112
icmp6_init
static clib_error_t * icmp6_init(vlib_main_t *vm)
Definition: icmp6.c:755
ip6_header_t::dst_address
ip6_address_t dst_address
Definition: ip6_packet.h:310
cm
vnet_feature_config_main_t * cm
Definition: nat44_ei_hairpinning.c:594
ICMP6_ECHO_REQUEST_NEXT_OUTPUT
@ ICMP6_ECHO_REQUEST_NEXT_OUTPUT
Definition: icmp6.c:262
pg_stream_get_group
static pg_edit_group_t * pg_stream_get_group(pg_stream_t *s, u32 group_index)
Definition: pg.h:233
pg_free_edit_group
static void pg_free_edit_group(pg_stream_t *s)
Definition: pg.h:292
ip_main_init
clib_error_t * ip_main_init(vlib_main_t *vm)
Definition: ip_init.c:45
vlib_buffer_copy_no_chain
static vlib_buffer_t * vlib_buffer_copy_no_chain(vlib_main_t *vm, vlib_buffer_t *b, u32 *di)
Definition: buffer_funcs.h:1137
vlib_node_registration_t
struct _vlib_node_registration vlib_node_registration_t
unformat_pg_edit
uword unformat_pg_edit(unformat_input_t *input, va_list *args)
Definition: edit.c:106
IP6_ICMP_ERROR_NEXT_DROP
@ IP6_ICMP_ERROR_NEXT_DROP
Definition: icmp6.c:445
IP6_ICMP_ERROR_N_NEXT
@ IP6_ICMP_ERROR_N_NEXT
Definition: icmp6.c:447
vlib_buffer_t::current_length
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:122
unformat_icmp_type_and_code
static uword unformat_icmp_type_and_code(unformat_input_t *input, va_list *args)
Definition: icmp6.c:618
format_icmp6_input_trace
u8 * format_icmp6_input_trace(u8 *s, va_list *va)
Definition: icmp6.c:114
icmp6_main_t::type_by_name
uword * type_by_name
Definition: icmp6.c:142
ip6_main
ip6_main_t ip6_main
Definition: ip6_forward.c:2785
data
u8 data[128]
Definition: ipsec_types.api:95
unformat_pg_payload
uword unformat_pg_payload(unformat_input_t *input, va_list *args)
Definition: edit.c:127
vlib_validate_buffer_enqueue_x1
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
Definition: buffer_node.h:224
always_inline
#define always_inline
Definition: rdma_mlx5dv.h:23
ip6_icmp_error_node
vlib_node_registration_t ip6_icmp_error_node
(constructor) VLIB_REGISTER_NODE (ip6_icmp_error_node)
Definition: icmp6.c:598
icmp
icmp
Definition: map.api:387
pg_main_t
Definition: pg.h:338
pg_icmp46_header_t::code
pg_edit_t code
Definition: icmp4.c:457
format
description fragment has unexpected format
Definition: map.api:433
ASSERT
#define ASSERT(truth)
Definition: error_bootstrap.h:69
pg_create_edit_group
static void * pg_create_edit_group(pg_stream_t *s, int n_edit_bytes, int n_packet_bytes, u32 *group_index)
Definition: pg.h:239
vlib_put_next_frame
vlib_put_next_frame(vm, node, next_index, 0)
ip.h
u32
unsigned int u32
Definition: types.h:88
VLIB_INIT_FUNCTION
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:172
ip_protocol_info_t
Definition: ip.h:70
unformat_pg_icmp_header
static uword unformat_pg_icmp_header(unformat_input_t *input, va_list *args)
Definition: icmp6.c:692
ip6_header_t
Definition: ip6_packet.h:294
icmp6_icmp_type_to_error
static u8 icmp6_icmp_type_to_error(u8 type)
Definition: icmp6.c:459
ip6_main_t
Definition: ip6.h:110
ip6_header_t::src_address
ip6_address_t src_address
Definition: ip6_packet.h:310
clib_memset
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
vlib_main_t
Definition: main.h:102
ip_csum_update
#define ip_csum_update(sum, old, new, type, field)
Definition: ip_packet.h:295
vlib_node_t
Definition: node.h:247
vlib_get_main
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:38
b
vlib_buffer_t ** b
Definition: nat44_ei_out2in.c:717
u8
unsigned char u8
Definition: types.h:56
clib_error_t
Definition: clib_error.h:21
icmp6_main_t::type_and_code_by_name
uword * type_and_code_by_name
Definition: icmp6.c:140
vlib_buffer_get_current
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:257
vlib_init_function_t
clib_error_t *() vlib_init_function_t(struct vlib_main_t *vm)
Definition: init.h:51
ip_csum_t
uword ip_csum_t
Definition: ip_packet.h:245
format_ip6_address
format_function_t format_ip6_address
Definition: format.h:91
vlib_buffer_t::data
u8 data[]
Packet data.
Definition: buffer.h:204
ICMP6_ECHO_REQUEST_N_NEXT
@ ICMP6_ECHO_REQUEST_N_NEXT
Definition: icmp6.c:263
ICMP_INPUT_N_NEXT
@ ICMP_INPUT_N_NEXT
Definition: icmp6.c:135
i
int i
Definition: flowhash_template.h:376
ip6_sas_by_sw_if_index
bool ip6_sas_by_sw_if_index(u32 sw_if_index, const ip6_address_t *dst, ip6_address_t *src)
Definition: ip_sas.c:72
pg_edit_t
Definition: edit.h:64
pg_stream_t
Definition: pg.h:96
vlib_validate_buffer_enqueue_x2
#define vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next, n_left_to_next, bi0, bi1, next0, next1)
Finish enqueueing two buffers forward in the graph.
Definition: buffer_node.h:70
ip_main_t
Definition: ip.h:107
ip6_icmp_input_node
vlib_node_registration_t ip6_icmp_input_node
(constructor) VLIB_REGISTER_NODE (ip6_icmp_input_node)
Definition: icmp6.c:241
icmp6_input_trace_t::packet_data
u8 packet_data[64]
Definition: icmp6.h:64
ip6_header_t::payload_length
u16 payload_length
Definition: ip6_packet.h:301
vlib_node_runtime_t
Definition: node.h:454
pg_icmp46_header_t::type
pg_edit_t type
Definition: icmp4.c:457
from
from
Definition: nat44_ei_hairpinning.c:415
format_ip6_icmp_type_and_code
static u8 * format_ip6_icmp_type_and_code(u8 *s, va_list *args)
Definition: icmp6.c:46
unformat_vlib_number_by_name
uword unformat_vlib_number_by_name(unformat_input_t *input, va_list *args)
Definition: format.c:157
pg_edit_group_t::edit_function
void(* edit_function)(struct pg_main_t *pg, struct pg_stream_t *s, struct pg_edit_group_t *g, u32 *buffers, u32 n_buffers)
Definition: pg.h:75
sw_if_index
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:34
vlib_get_next_frame
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:395
ip_csum_fold
static u16 ip_csum_fold(ip_csum_t c)
Definition: ip_packet.h:301
foreach_icmp6_type
@ foreach_icmp6_type
Definition: icmp46_packet.h:179
ip_protocol_info_t::unformat_pg_edit
unformat_function_t * unformat_pg_edit
Definition: ip.h:88
VLIB_TX
@ VLIB_TX
Definition: defs.h:47
icmp6_pg_edit_function
static void icmp6_pg_edit_function(pg_main_t *pg, pg_stream_t *s, pg_edit_group_t *g, u32 *packets, u32 n_packets)
Definition: icmp6.c:643
format_icmp6_header
static u8 * format_icmp6_header(u8 *s, va_list *args)
Definition: icmp6.c:86
n_left_from
n_left_from
Definition: nat44_ei_hairpinning.c:416
foreach_icmp6_error
@ foreach_icmp6_error
Definition: icmp6.h:58
ip6_header_t::ip_version_traffic_class_and_flow_label
u32 ip_version_traffic_class_and_flow_label
Definition: ip6_packet.h:297
type
vl_api_fib_path_type_t type
Definition: fib_types.api:123
ip6_icmp_error_next_t
ip6_icmp_error_next_t
Definition: icmp6.c:443
icmp6_main_t
Definition: icmp6.c:138
vlib_buffer_t::flags
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index,...
Definition: buffer.h:133
IP6_ICMP_ERROR_NEXT_LOOKUP
@ IP6_ICMP_ERROR_NEXT_LOOKUP
Definition: icmp6.c:446
vlib_buffer_t
VLIB buffer representation.
Definition: buffer.h:111
packets
units packets
Definition: map.api:366
VLIB_REGISTER_NODE
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169