FD.io VPP  v18.10-34-gcce845e
Vector Packet Processing
udp_ping_node.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 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 #include <vnet/vnet.h>
17 #include <vlib/vlib.h>
18 #include <vlibapi/api.h>
19 #include <vlibmemory/api.h>
20 
21 #include <vnet/ip/ip.h>
22 #include <vnet/ip/ip6_hop_by_hop.h>
26 #include <ioam/udp-ping/udp_ping.h>
28 #include <vnet/srv6/sr_packet.h>
29 
30 typedef enum
31 {
40 
41 #define foreach_udp_ping_error \
42 _(BADHBH, "Malformed hop-by-hop header")
43 
44 typedef enum
45 {
46 #define _(sym,str) UDP_PING_ERROR_##sym,
48 #undef _
51 
52 static char *udp_ping_error_strings[] = {
53 #define _(sym,string) string,
55 #undef _
56 };
57 
59 
60 uword
63 
64 extern int
67 
68 typedef struct
69 {
78 
79 /* packet trace format function */
80 static u8 *
81 format_udp_ping_trace (u8 * s, va_list * args)
82 {
83  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
84  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
85  udp_ping_trace_t *t = va_arg (*args, udp_ping_trace_t *);
86 
87  s = format (s, "udp-ping-local: src %U, dst %U, src_port %u, dst_port %u "
88  "handle %u, next_index %u, msg_type %u",
91  t->src_port, t->dst_port,
92  t->handle, t->next_index, t->msg_type);
93  return s;
94 }
95 
96 /* *INDENT-OFF* */
98 {
99  .function = udp_ping_process,
100  .type = VLIB_NODE_TYPE_PROCESS,
101  .name = "udp-ping-process",
102 };
103 /* *INDENT-ON* */
104 
105 void
107 {
108  int i;
110  u16 min_interval = 0x1e9;
111 
112  for (i = 0; i < vec_len (udp_ping_main.ip46_flow); i++)
113  {
114  if (pool_is_free_index (udp_ping_main.ip46_flow, i))
115  continue;
116 
117  flow = pool_elt_at_index (udp_ping_main.ip46_flow, i);
118 
119  if (min_interval > flow->udp_data.interval)
120  min_interval = flow->udp_data.interval;
121  }
122 
123  if (udp_ping_main.timer_interval != min_interval)
124  {
125  udp_ping_main.timer_interval = min_interval;
126  vlib_process_signal_event (udp_ping_main.vlib_main,
127  udp_ping_node.index, EVENT_SIG_RECHECK, 0);
128  }
129 }
130 
131 void
132 ip46_udp_ping_set_flow (ip46_address_t src, ip46_address_t dst,
133  u16 start_src_port, u16 end_src_port,
134  u16 start_dst_port, u16 end_dst_port,
135  u16 interval, u8 fault_det, u8 is_disable)
136 {
137  u8 found = 0;
139  int i;
140 
141  for (i = 0; i < vec_len (udp_ping_main.ip46_flow); i++)
142  {
143  if (pool_is_free_index (udp_ping_main.ip46_flow, i))
144  continue;
145 
146  flow = pool_elt_at_index (udp_ping_main.ip46_flow, i);
147  if ((0 == udp_ping_compare_flow (src, dst,
148  start_src_port, end_src_port,
149  start_dst_port, end_dst_port, flow)))
150  {
151  found = 1;
152  break;
153  }
154  }
155 
156  if (found)
157  {
158  u16 cur_interval;
159  if (is_disable)
160  {
161  cur_interval = flow->udp_data.interval;
163  pool_put_index (udp_ping_main.ip46_flow, i);
164  if (udp_ping_main.timer_interval == interval)
166  return;
167  }
168 
169  cur_interval = flow->udp_data.interval;
170  flow->udp_data.interval = interval;
171  if (udp_ping_main.timer_interval > interval)
172  {
173  udp_ping_main.timer_interval = interval;
174  vlib_process_signal_event (udp_ping_main.vlib_main,
175  udp_ping_node.index,
176  EVENT_SIG_RECHECK, 0);
177  }
178  else if (udp_ping_main.timer_interval == cur_interval)
180 
181  return;
182  }
183 
184  /* Delete operation and item not found */
185  if (is_disable)
186  return;
187 
188  /* Alloc new session */
189  pool_get_aligned (udp_ping_main.ip46_flow, flow, CLIB_CACHE_LINE_BYTES);
190  udp_ping_populate_flow (src, dst,
191  start_src_port, end_src_port,
192  start_dst_port, end_dst_port,
193  interval, fault_det, flow);
194 
195  udp_ping_create_rewrite (flow, (flow - udp_ping_main.ip46_flow));
196 
197  if (udp_ping_main.timer_interval > interval)
198  {
199  udp_ping_main.timer_interval = interval;
200  vlib_process_signal_event (udp_ping_main.vlib_main,
201  udp_ping_node.index, EVENT_SIG_RECHECK, 0);
202  }
203  return;
204 }
205 
206 uword
207 unformat_port_range (unformat_input_t * input, va_list * args)
208 {
209  u16 *start_port, *end_port;
210  uword c;
211  u8 colon_present = 0;
212 
213  start_port = va_arg (*args, u16 *);
214  end_port = va_arg (*args, u16 *);
215 
216  *start_port = *end_port = 0;
217  /* Get start port */
218  while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
219  {
220  switch (c)
221  {
222  case '0' ... '9':
223  *start_port = ((*start_port) * 10) + (c - '0');
224  break;
225 
226  case ':':
227  colon_present = 1;
228  break;
229 
230  default:
231  return 0;
232  }
233 
234  if (colon_present)
235  break;
236  }
237 
238  if (!colon_present)
239  return 0;
240 
241  /* Get end port */
242  while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
243  {
244  switch (c)
245  {
246  case '0' ... '9':
247  *end_port = ((*end_port) * 10) + (c - '0');
248  break;
249 
250  default:
251  return 1;
252  }
253  }
254 
255  if (end_port < start_port)
256  return 0;
257 
258  return 1;
259 }
260 
261 static clib_error_t *
263  unformat_input_t * input, vlib_cli_command_t * cmd)
264 {
265  ip46_address_t dst, src;
266  u16 start_src_port, end_src_port;
267  u16 start_dst_port, end_dst_port;
268  u32 interval;
269  u8 is_disable = 0;
270  u8 fault_det = 0;
271 
273  {
274  if (unformat
275  (input, "src %U", unformat_ip46_address, &src, IP46_TYPE_ANY))
276  ;
277  else if (unformat (input, "src-port-range %U",
278  unformat_port_range, &start_src_port, &end_src_port))
279  ;
280  else
281  if (unformat
282  (input, "dst %U", unformat_ip46_address, &dst, IP46_TYPE_ANY))
283  ;
284  else if (unformat (input, "dst-port-range %U",
285  unformat_port_range, &start_dst_port, &end_dst_port))
286  ;
287  else if (unformat (input, "interval %d", &interval))
288  ;
289  else if (unformat (input, "fault-detect"))
290  fault_det = 1;
291  else if (unformat (input, "disable"))
292  is_disable = 1;
293  else
294  break;
295  }
296 
297  ip46_udp_ping_set_flow (src, dst, start_src_port, end_src_port,
298  start_dst_port, end_dst_port, (u16) interval,
299  fault_det, is_disable);
300 
301  return 0;
302 }
303 
304 /* *INDENT-OFF* */
305 VLIB_CLI_COMMAND (set_udp_ping_command, static) =
306 {
307  .path = "set udp-ping",
308  .short_help =
309  "set udp-ping src <local IPv6 address> src-port-range <local port range> \
310  dst <remote IPv6 address> dst-port-range <destination port range> \
311  interval <time interval in sec for which ping packet will be sent> \
312  [disable]",
313  .function = set_udp_ping_command_fn,
314 };
315 /* *INDENT-ON* */
316 
317 static clib_error_t *
319  unformat_input_t * input,
320  vlib_cli_command_t * cmd)
321 {
322  u8 *s = 0;
323  int i, j;
324  ip46_udp_ping_flow *ip46_flow;
326  udp_ping_flow_data *stats;
327 
328  s = format (s, "UDP-Ping data:\n");
329 
330  for (i = 0; i < vec_len (udp_ping_main.ip46_flow); i++)
331  {
332  if (pool_is_free_index (udp_ping_main.ip46_flow, i))
333  continue;
334 
335  ip46_flow = pool_elt_at_index (udp_ping_main.ip46_flow, i);
336  s = format (s, "Src: %U, Dst: %U\n",
337  format_ip46_address, &ip46_flow->src, IP46_TYPE_ANY,
338  format_ip46_address, &ip46_flow->dst, IP46_TYPE_ANY);
339 
340  s = format (s, "Start src port: %u, End src port: %u\n",
341  ip46_flow->udp_data.start_src_port,
342  ip46_flow->udp_data.end_src_port);
343  s = format (s, "Start dst port: %u, End dst port: %u\n",
344  ip46_flow->udp_data.start_dst_port,
345  ip46_flow->udp_data.end_dst_port);
346  s = format (s, "Interval: %u\n", ip46_flow->udp_data.interval);
347 
348  j = 0;
349  for (src_port = ip46_flow->udp_data.start_src_port;
350  src_port <= ip46_flow->udp_data.end_src_port; src_port++)
351  {
352  for (dst_port = ip46_flow->udp_data.start_dst_port;
353  dst_port <= ip46_flow->udp_data.end_dst_port; dst_port++)
354  {
355  stats = ip46_flow->udp_data.stats + j;
356  s =
357  format (s, "\nSrc Port - %u, Dst Port - %u, Flow CTX - %u\n",
358  src_port, dst_port, stats->flow_ctx);
359  s =
360  format (s, "Path State - %s\n",
361  (stats->retry > MAX_PING_RETRIES) ? "Down" : "Up");
362  s = format (s, "Path Data:\n");
363  s = print_analyse_flow (s,
364  &ip46_flow->udp_data.
365  stats[j].analyse_data);
366  j++;
367  }
368  }
369  s = format (s, "\n\n");
370  }
371 
372  vlib_cli_output (vm, "%v", s);
373  vec_free (s);
374  return 0;
375 }
376 
377 /* *INDENT-OFF* */
378 VLIB_CLI_COMMAND (show_udp_ping_cmd, static) =
379 {
380  .path = "show udp-ping summary",
381  .short_help = "Summary of udp-ping",
382  .function = show_udp_ping_summary_cmd_fn,
383 };
384 /* *INDENT-ON* */
385 
386 /**
387  * @brief UDP-Ping Process node.
388  * @node udp-ping-process
389  *
390  * This is process node which wakes up when periodically to send
391  * out udp probe packets for all configured sessions.
392  *
393  * @param vm vlib_main_t corresponding to the current thread.
394  * @param node vlib_node_runtime_t data for this node.
395  * @param frame vlib_frame_t whose contents should be dispatched.
396  *
397  */
398 uword
401 {
402  f64 now;
403  uword *event_data = 0;
404  int i;
405  ip46_udp_ping_flow *ip46_flow;
406 
407  while (1)
408  {
409  vec_reset_length (event_data);
411  (void) vlib_process_get_events (vm, &event_data);
412  now = vlib_time_now (vm);
413 
414  for (i = 0; i < vec_len (udp_ping_main.ip46_flow); i++)
415  {
416  if (pool_is_free_index (udp_ping_main.ip46_flow, i))
417  continue;
418 
419  ip46_flow = pool_elt_at_index (udp_ping_main.ip46_flow, i);
420  if (ip46_flow->udp_data.next_send_time < now)
421  udp_ping_send_ip6_pak (udp_ping_main.vlib_main, ip46_flow);
422  }
423  }
424  return 0;
425 }
426 
427 /**
428  * @brief HopByHop analyse function for udp-ping response.
429  *
430  * Walks through all hbh options present in udp-ping response
431  * and uses analyser library for the analysis.
432  *
433  */
434 void
436  u32 flow_id,
437  u16 src_port,
438  u16 dst_port,
440  ip6_hop_by_hop_option_t * limit0, u16 len)
441 {
442  u8 type0;
443  ip46_udp_ping_flow *ip46_flow;
444  u16 flow_index;
445  ioam_analyser_data_t *data;
446  ioam_e2e_option_t *e2e;
447  ioam_trace_option_t *trace;
448 
449  /* If the packet doesnt match UDP session then return */
450  if (PREDICT_FALSE (pool_is_free_index (udp_ping_main.ip46_flow, flow_id)))
451  return;
452 
453  ip46_flow = udp_ping_main.ip46_flow + flow_id;
454  /* Check port is within range */
455  if (PREDICT_FALSE ((src_port < ip46_flow->udp_data.start_src_port) ||
456  (src_port > ip46_flow->udp_data.end_src_port) ||
457  (dst_port < ip46_flow->udp_data.start_dst_port) ||
458  (dst_port > ip46_flow->udp_data.end_dst_port)))
459  return;
460 
461  flow_index = (src_port - ip46_flow->udp_data.start_src_port) *
462  (ip46_flow->udp_data.end_dst_port - ip46_flow->udp_data.start_dst_port +
463  1);
464  flow_index += (dst_port - ip46_flow->udp_data.start_dst_port);
465  data = &(ip46_flow->udp_data.stats[flow_index].analyse_data);
466 
467  data->pkt_counter++;
468  data->bytes_counter += len;
469 
470  vnet_buffer (b0)->l2_classify.opaque_index =
471  ip46_flow->udp_data.stats[flow_index].flow_ctx;
472 
473  while (opt0 < limit0)
474  {
475  type0 = opt0->type;
476  switch (type0)
477  {
479  /* Add trace for here as it hasnt been done yet */
480  vnet_buffer (b0)->sw_if_index[VLIB_TX] = ~0;
481  trace = (ioam_trace_option_t *) opt0;
482  if (PREDICT_FALSE
483  (trace->trace_hdr.ioam_trace_type & BIT_LOOPBACK_REPLY))
484  {
485  ip6_ioam_analyse_hbh_trace_loopback (data, &trace->trace_hdr,
486  (trace->hdr.length - 2));
487  return;
488  }
491  opt0);
492  (void) ip6_ioam_analyse_hbh_trace (data, &trace->trace_hdr, len,
493  (trace->hdr.length - 2));
494  break;
496  e2e = (ioam_e2e_option_t *) opt0;
497  (void) ip6_ioam_analyse_hbh_e2e (data, &e2e->e2e_hdr, len);
498  break;
499  case 0: /* Pad1 */
500  opt0 = (ip6_hop_by_hop_option_t *) ((u8 *) opt0) + 1;
501  continue;
502  case 1: /* PadN */
503  break;
504  default:
505  break;
506  }
507  opt0 = (ip6_hop_by_hop_option_t *) (((u8 *) opt0) + opt0->length +
508  sizeof (ip6_hop_by_hop_option_t));
509  }
510  ip46_flow->udp_data.stats[flow_index].retry = 0;
511 }
512 
513 /**
514  * @brief UDP-Ping request/response handler function.
515  *
516  * Checks udp-ping packet type - request/response and handles them.
517  * If not udp-ping packet then, strips off hbh options and enques
518  * packet to protocol registered node to enable next protocol processing.
519  *
520  */
521 void
524  u16 * next0)
525 {
526  ip6_main_t *im = &ip6_main;
527  ip_lookup_main_t *lm = &im->lookup_main;
528 
529  *next0 = UDP_PING_NEXT_IP6_DROP;
530 
531  /*
532  * Sanity check: hbh header length must be less than
533  * b0->current_length.
534  */
535  if (PREDICT_FALSE ((hbh0->length + 1) << 3) >= b0->current_length)
536  {
537  *next0 = UDP_PING_NEXT_DROP;
538  b0->error = node->errors[UDP_PING_ERROR_BADHBH];
539  return;
540  }
541 
542  if (PREDICT_TRUE (hbh0->protocol == IP_PROTOCOL_UDP))
543  {
545  ip6_hop_by_hop_option_t *limit0;
546  u16 p_len0;
547  udp_ping_t *udp0;
548 
549  /* Check for udp ping packet */
550  udp0 = (udp_ping_t *) ((u8 *) hbh0 + ((hbh0->length + 1) << 3));
551  opt0 = (ip6_hop_by_hop_option_t *) (hbh0 + 1);
552  if ((udp0->ping_data.probe_marker1 ==
553  clib_host_to_net_u32 (UDP_PING_PROBE_MARKER1)) &&
554  (udp0->ping_data.probe_marker2 ==
555  clib_host_to_net_u32 (UDP_PING_PROBE_MARKER2)))
556  {
557  if (udp0->ping_data.msg_type == UDP_PING_PROBE)
558  {
559  udp_ping_create_reply_from_probe_ip6 (ip0, hbh0, udp0);
560  /* Skip e2e processing */
561  vnet_buffer (b0)->l2_classify.opaque_index = 0x7FFFFFFF;
562  *next0 = UDP_PING_NEXT_IP6_LOOKUP;
563  return;
564  }
565 
566  /* Reply */
567  opt0 = (ip6_hop_by_hop_option_t *) (hbh0 + 1);
568  limit0 = (ip6_hop_by_hop_option_t *)
569  ((u8 *) hbh0 + ((hbh0->length + 1) << 3));
570  p_len0 = clib_net_to_host_u16 (ip0->payload_length);
572  clib_net_to_host_u16 (udp0->
573  ping_data.sender_handle),
574  clib_net_to_host_u16 (udp0->udp.dst_port),
575  clib_net_to_host_u16 (udp0->udp.src_port),
576  opt0, limit0, p_len0);
577 
578  /* UDP Ping packet, so return */
579  return;
580  }
581  }
582 
583  /* If next header is SR, then destination may get overwritten to
584  * remote address. So pass it to SR processing as it may be local packet
585  * afterall
586  */
588  goto end;
589 
590  /* Other case remove hbh-ioam headers */
591  u64 *copy_dst0, *copy_src0;
592  u16 new_l0;
593 
594  vlib_buffer_advance (b0, (hbh0->length + 1) << 3);
595 
596  new_l0 = clib_net_to_host_u16 (ip0->payload_length) -
597  ((hbh0->length + 1) << 3);
598 
599  ip0->payload_length = clib_host_to_net_u16 (new_l0);
600 
601  ip0->protocol = hbh0->protocol;
602 
603  copy_src0 = (u64 *) ip0;
604  copy_dst0 = copy_src0 + (hbh0->length + 1);
605  copy_dst0[4] = copy_src0[4];
606  copy_dst0[3] = copy_src0[3];
607  copy_dst0[2] = copy_src0[2];
608  copy_dst0[1] = copy_src0[1];
609  copy_dst0[0] = copy_src0[0];
610 
611 end:
612  *next0 = lm->local_next_by_ip_protocol[hbh0->protocol];
613  return;
614 }
615 
616 /**
617  * @brief udp ping request/response packet receive node.
618  * @node udp-ping-local
619  *
620  * This function receives udp ping request/response packets and process them.
621  * For request packets, response is created and sent.
622  * For response packets, they are analysed and results stored.
623  *
624  * @param vm vlib_main_t corresponding to the current thread.
625  * @param node vlib_node_runtime_t data for this node.
626  * @param frame vlib_frame_t whose contents should be dispatched.
627  *
628  * @par Graph mechanics: buffer, next index usage
629  *
630  * <em>Uses:</em>
631  * - <code>udp_ping_local_analyse(node, p0, ip0, hbh0, &next0)</code>
632  * - Checks packet type - request/respnse and process them.
633  *
634  * <em>Next Index:</em>
635  * - Dispatches the packet to ip6-lookup/ip6-drop depending on type of packet.
636  */
637 static uword
639  vlib_node_runtime_t * node, vlib_frame_t * frame)
640 {
641  udp_ping_next_t next_index;
642  u32 *from, *to_next, n_left_from, n_left_to_next;
643 
644  from = vlib_frame_vector_args (frame);
645  n_left_from = frame->n_vectors;
646  next_index = node->cached_next_index;
647 
648  while (n_left_from > 0)
649  {
650  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
651 
652  while (n_left_from >= 4 && n_left_to_next >= 2)
653  {
654  vlib_buffer_t *p0, *p1;
655  ip6_header_t *ip0, *ip1;
656  ip6_hop_by_hop_header_t *hbh0, *hbh1;
657  u16 next0, next1;
658  u32 pi0, pi1;
659 
660  /* Prefetch next iteration. */
661  {
662  vlib_buffer_t *p2, *p3;
663 
664  p2 = vlib_get_buffer (vm, from[2]);
665  p3 = vlib_get_buffer (vm, from[3]);
666 
667  vlib_prefetch_buffer_header (p2, LOAD);
668  vlib_prefetch_buffer_header (p3, LOAD);
669 
670  /* Prefetch 3 cache lines as we need to look deep into packet */
671  CLIB_PREFETCH (p2->data, 3 * CLIB_CACHE_LINE_BYTES, STORE);
672  CLIB_PREFETCH (p3->data, 3 * CLIB_CACHE_LINE_BYTES, STORE);
673  }
674 
675  pi0 = to_next[0] = from[0];
676  pi1 = to_next[1] = from[1];
677  from += 2;
678  n_left_from -= 2;
679  to_next += 2;
680  n_left_to_next -= 2;
681 
682  p0 = vlib_get_buffer (vm, pi0);
683  p1 = vlib_get_buffer (vm, pi1);
684 
685  ip0 = vlib_buffer_get_current (p0);
686  ip1 = vlib_buffer_get_current (p1);
687 
688  hbh0 = (ip6_hop_by_hop_header_t *) (ip0 + 1);
689  hbh1 = (ip6_hop_by_hop_header_t *) (ip1 + 1);
690 
691  udp_ping_local_analyse (node, p0, ip0, hbh0, &next0);
692  udp_ping_local_analyse (node, p1, ip1, hbh1, &next1);
693 
694  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
695  {
696  if (p0->flags & VLIB_BUFFER_IS_TRACED)
697  {
698  udp_ping_trace_t *t0 =
699  vlib_add_trace (vm, node, p0, sizeof (*t0));
700  udp_ping_t *udp0;
701 
702  /* Check for udp ping packet */
703  udp0 =
704  (udp_ping_t *) ((u8 *) hbh0 + ((hbh0->length + 1) << 3));
705  t0->src = ip0->src_address;
706  t0->dst = ip0->dst_address;
707  t0->src_port = clib_net_to_host_u16 (udp0->udp.src_port);
708  t0->dst_port = clib_net_to_host_u16 (udp0->udp.dst_port);
709  t0->handle =
710  clib_net_to_host_u16 (udp0->ping_data.sender_handle);
711  t0->msg_type = udp0->ping_data.msg_type;
712  t0->next_index = next0;
713  }
714  if (p1->flags & VLIB_BUFFER_IS_TRACED)
715  {
716  udp_ping_trace_t *t1 =
717  vlib_add_trace (vm, node, p1, sizeof (*t1));
718  udp_ping_t *udp1;
719 
720  /* Check for udp ping packet */
721  udp1 =
722  (udp_ping_t *) ((u8 *) hbh1 + ((hbh1->length + 1) << 3));
723  t1->src = ip1->src_address;
724  t1->dst = ip1->dst_address;
725  t1->src_port = clib_net_to_host_u16 (udp1->udp.src_port);
726  t1->dst_port = clib_net_to_host_u16 (udp1->udp.dst_port);
727  t1->handle =
728  clib_net_to_host_u16 (udp1->ping_data.sender_handle);
729  t1->msg_type = udp1->ping_data.msg_type;
730  t1->next_index = next1;
731  }
732  }
733 
734  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
735  to_next, n_left_to_next,
736  pi0, pi1, next0, next1);
737  }
738 
739  while (n_left_from > 0 && n_left_to_next > 0)
740  {
741  vlib_buffer_t *p0;
742  ip6_header_t *ip0;
744  u16 next0;
745  u32 pi0;
746 
747  pi0 = from[0];
748  to_next[0] = pi0;
749  from += 1;
750  to_next += 1;
751  n_left_from -= 1;
752  n_left_to_next -= 1;
753 
754  p0 = vlib_get_buffer (vm, pi0);
755  ip0 = vlib_buffer_get_current (p0);
756  hbh0 = (ip6_hop_by_hop_header_t *) (ip0 + 1);
757 
758  udp_ping_local_analyse (node, p0, ip0, hbh0, &next0);
759 
760  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
761  {
762  if (p0->flags & VLIB_BUFFER_IS_TRACED)
763  {
764  udp_ping_trace_t *t0 =
765  vlib_add_trace (vm, node, p0, sizeof (*t0));
766  udp_ping_t *udp0;
767 
768  /* Check for udp ping packet */
769  udp0 =
770  (udp_ping_t *) ((u8 *) hbh0 + ((hbh0->length + 1) << 3));
771  t0->src = ip0->src_address;
772  t0->dst = ip0->dst_address;
773  t0->src_port = clib_net_to_host_u16 (udp0->udp.src_port);
774  t0->dst_port = clib_net_to_host_u16 (udp0->udp.dst_port);
775  t0->handle =
776  clib_net_to_host_u16 (udp0->ping_data.sender_handle);
777  t0->msg_type = udp0->ping_data.msg_type;
778  t0->next_index = next0;
779  }
780  }
781 
782  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
783  to_next, n_left_to_next,
784  pi0, next0);
785  }
786 
787  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
788  }
789 
790  return frame->n_vectors;
791 }
792 
793 /* *INDENT-OFF* */
794 /*
795  * Node for udp-ping-local
796  */
798 {
799  .function = udp_ping_local_node_fn,
800  .name = "udp-ping-local",
801  .vector_size = sizeof (u32),
802  .format_trace = format_udp_ping_trace,
803  .type = VLIB_NODE_TYPE_INTERNAL,
804  .n_next_nodes = UDP_PING_N_NEXT,
805  .n_errors = UDP_PING_N_ERROR,
806  .error_strings = udp_ping_error_strings,
807  .next_nodes =
808  {
809  [UDP_PING_NEXT_DROP] = "error-drop",
810  [UDP_PING_NEXT_PUNT] = "error-punt",
811  [UDP_PING_NEXT_UDP_LOOKUP] = "ip6-udp-lookup",
812  [UDP_PING_NEXT_ICMP] = "ip6-icmp-input",
813  [UDP_PING_NEXT_IP6_LOOKUP] = "ip6-lookup",
814  [UDP_PING_NEXT_IP6_DROP] = "ip6-drop",
815  },
816 };
817 /* *INDENT-ON* */
818 
819 static clib_error_t *
821 {
822  clib_error_t *error = 0;
823 
824  udp_ping_main.vlib_main = vm;
825  udp_ping_main.vnet_main = vnet_get_main ();
826  udp_ping_main.timer_interval = 1e9;
827 
828  if ((error = vlib_call_init_function (vm, ip_main_init)))
829  return (error);
830 
831  ip6_register_protocol (IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS,
832  udp_ping_local.index);
833  return 0;
834 }
835 
837 
838 /*
839  * fd.io coding-style-patch-verification: ON
840  *
841  * Local Variables:
842  * eval: (c-set-style "gnu")
843  * End:
844  */
udp_ping_data ping_data
udp-ping main data-structure.
Definition: udp_ping.h:105
static vlib_cli_command_t trace
(constructor) VLIB_CLI_COMMAND (trace)
Definition: vlib_api_cli.c:862
vl_api_address_t src
Definition: vxlan_gbp.api:33
#define CLIB_UNUSED(x)
Definition: clib.h:81
ioam_analyser_data_t analyse_data
Analysed data.
Definition: udp_ping.h:44
static int ip6_ioam_analyse_hbh_e2e(ioam_analyser_data_t *data, ioam_e2e_packet_t *e2e, u16 len)
Definition: ioam_analyse.h:417
static u8 * print_analyse_flow(u8 *s, ioam_analyser_data_t *record)
Definition: ioam_analyse.h:451
static f64 vlib_process_wait_for_event_or_clock(vlib_main_t *vm, f64 dt)
Suspend a cooperative multi-tasking thread Waits for an event, or for the indicated number of seconds...
Definition: node_funcs.h:699
void ip6_register_protocol(u32 protocol, u32 node_index)
Definition: ip6_forward.c:1427
#define UDP_PING_PROBE_MARKER2
ip6_address_t src
Definition: udp_ping_node.c:70
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
static vlib_node_registration_t udp_ping_local
(constructor) VLIB_REGISTER_NODE (udp_ping_local)
static char * udp_ping_error_strings[]
Definition: udp_ping_node.c:52
static uword unformat_get_input(unformat_input_t *input)
Definition: format.h:191
#define PREDICT_TRUE(x)
Definition: clib.h:108
ip46_udp_ping_flow * ip46_flow
Vector od udp-ping data.
Definition: udp_ping.h:108
unsigned long u64
Definition: types.h:89
u32 bytes_counter
Num of bytes matching this flow.
Definition: ioam_analyse.h:111
u16 start_dst_port
Defines start port of the dest port range.
Definition: udp_ping.h:73
#define NULL
Definition: clib.h:57
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:227
void udp_ping_free_flow_data(ip46_udp_ping_flow *flow)
int i
format_function_t format_ip46_address
Definition: format.h:61
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
static u8 * format_udp_ping_trace(u8 *s, va_list *args)
Definition: udp_ping_node.c:81
static clib_error_t * show_udp_ping_summary_cmd_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
ip6_address_t dst
Definition: udp_ping_node.c:71
u16 interval
Interval for which ping packet to be sent.
Definition: udp_ping.h:62
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:472
udp_ping_flow udp_data
Per flow data.
Definition: udp_ping.h:97
void ip46_udp_ping_set_flow(ip46_address_t src, ip46_address_t dst, u16 start_src_port, u16 end_src_port, u16 start_dst_port, u16 end_dst_port, u16 interval, u8 fault_det, u8 is_disable)
int udp_ping_compare_flow(ip46_address_t src, ip46_address_t dst, u16 start_src_port, u16 end_src_port, u16 start_dst_port, u16 end_dst_port, ip46_udp_ping_flow *flow)
ip6_address_t src_address
Definition: ip6_packet.h:378
uword unformat_port_range(unformat_input_t *input, va_list *args)
unsigned char u8
Definition: types.h:56
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
u16 end_src_port
Defines end port of the src port range.
Definition: udp_ping.h:70
double f64
Definition: types.h:142
u16 src_port
Definition: udp.api:41
#define MAX_PING_RETRIES
Definition: udp_ping.h:21
f64 next_send_time
Time at which next udp-ping probe has to be sent out.
Definition: udp_ping.h:59
vnet_main_t * vnet_main
Pointer to vnet main for convenience.
Definition: udp_ping.h:117
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:163
#define HBH_OPTION_TYPE_IOAM_EDGE_TO_EDGE
static uword vlib_process_get_events(vlib_main_t *vm, uword **data_vector)
Return the first event type which has occurred and a vector of per-event data of that type...
Definition: node_funcs.h:542
void udp_ping_send_ip6_pak(vlib_main_t *vm, ip46_udp_ping_flow *flow)
Create and send ipv6 udp-ping probe packet.
uword udp_ping_process(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
UDP-Ping Process node.
udp_ping_error_t
Definition: udp_ping_node.c:44
udp-ping data.
Definition: udp_ping.h:85
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:187
u32 pkt_counter
Num of pkts matching this flow.
Definition: ioam_analyse.h:108
udp_ping_next_t
Definition: udp_ping_node.c:30
u16 start_src_port
Defines start port of the src port range.
Definition: udp_ping.h:67
#define IPPROTO_IPV6_ROUTE
Definition: sr_packet.h:113
unsigned int u32
Definition: types.h:88
udp_header_t udp
void udp_ping_create_rewrite(ip46_udp_ping_flow *flow, u16 ctx)
#define vlib_call_init_function(vm, x)
Definition: init.h:260
void udp_ping_analyse_hbh(vlib_buffer_t *b0, u32 flow_id, u16 src_port, u16 dst_port, ip6_hop_by_hop_option_t *opt0, ip6_hop_by_hop_option_t *limit0, u16 len)
HopByHop analyse function for udp-ping response.
static uword udp_ping_local_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
udp ping request/response packet receive node.
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:464
#define foreach_udp_ping_error
Definition: udp_ping_node.c:41
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:113
static void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
Definition: node_funcs.h:960
struct _unformat_input_t unformat_input_t
unsigned short u16
Definition: types.h:57
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:205
ip46_address_t dst
Remote destination IPv4/6 address to be used.
Definition: udp_ping.h:94
#define PREDICT_FALSE(x)
Definition: clib.h:107
u8 local_next_by_ip_protocol[256]
Table mapping ip protocol to ip[46]-local node next index.
Definition: lookup.h:151
#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
#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:218
#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:364
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:138
#define pool_get_aligned(P, E, A)
Allocate an object E from a pool P (general version).
Definition: pool.h:188
u32 flow_ctx
This is used by ioam e2e for identifying flow and add seq number.
Definition: udp_ping.h:47
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:155
clib_error_t * ip_main_init(vlib_main_t *vm)
Definition: ip_init.c:45
#define UNFORMAT_END_OF_INPUT
Definition: format.h:144
svmdb_client_t * c
u16 n_vectors
Definition: node.h:401
format_function_t format_ip6_address
Definition: format.h:93
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:79
vlib_main_t * vm
Definition: buffer.c:294
vl_api_address_t dst
Definition: vxlan_gbp.api:34
void udp_ping_populate_flow(ip46_address_t src, ip46_address_t dst, u16 start_src_port, u16 end_src_port, u16 start_dst_port, u16 end_dst_port, u16 interval, u8 fault_det, ip46_udp_ping_flow *flow)
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:339
static void udp_ping_create_reply_from_probe_ip6(ip6_header_t *ip, ip6_hop_by_hop_header_t *hbh, udp_ping_t *udp)
Create and send ipv6 udp-ping response packet.
Definition: udp_ping_util.h:48
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:271
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
Definition: main.c:455
#define UDP_PING_PROBE
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:155
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:513
u16 end_dst_port
Defines end port of the dest port range.
Definition: udp_ping.h:76
static clib_error_t * set_udp_ping_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
#define pool_put_index(p, i)
Free pool element with given index.
Definition: pool.h:299
vlib_main_t * vlib_main
Pointer to VLib main for the node - ipfix-collector.
Definition: udp_ping.h:114
ip6_main_t ip6_main
Definition: ip6_forward.c:2590
ip_lookup_main_t lookup_main
Definition: ip6.h:161
u64 timer_interval
Stores the time interval at which process node has to wake up.
Definition: udp_ping.h:111
udp-ping session data.
Definition: udp_ping.h:28
ip46_address_t src
Local source IPv4/6 address to be used.
Definition: udp_ping.h:91
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:218
#define BIT_LOOPBACK_REPLY
Definition: trace_util.h:95
void udp_ping_local_analyse(vlib_node_runtime_t *node, vlib_buffer_t *b0, ip6_header_t *ip0, ip6_hop_by_hop_header_t *hbh0, u16 *next0)
UDP-Ping request/response handler function.
#define HBH_OPTION_TYPE_IOAM_TRACE_DATA_LIST
unformat_function_t unformat_ip46_address
Definition: format.h:65
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace_funcs.h:57
Definition: defs.h:47
u16 payload_length
Definition: ip6_packet.h:369
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
Analysed iOAM data.
Definition: ioam_analyse.h:97
u64 uword
Definition: types.h:112
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:267
static int ip6_ioam_analyse_hbh_trace(ioam_analyser_data_t *data, ioam_trace_hdr_t *trace, u16 pak_len, u16 trace_len)
Definition: ioam_analyse.h:284
static clib_error_t * udp_ping_init(vlib_main_t *vm)
void udp_ping_calculate_timer_interval(void)
udp_ping_main_t udp_ping_main
Definition: udp_ping_node.c:58
#define vnet_buffer(b)
Definition: buffer.h:344
u8 data[0]
Packet data.
Definition: buffer.h:175
u16 retry
Number of times ping response was dropped.
Definition: udp_ping.h:39
u16 flags
Copy of main node flags.
Definition: node.h:507
udp_ping_flow_data * stats
Ping statistics.
Definition: udp_ping.h:79
static void ip6_ioam_analyse_hbh_trace_loopback(ioam_analyser_data_t *data, ioam_trace_hdr_t *trace, u16 trace_len)
Definition: ioam_analyse.h:215
u16 dst_port
Definition: udp.api:42
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:310
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
#define EVENT_SIG_RECHECK
Definition: udp_ping.h:23
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:116
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:725
#define UDP_PING_PROBE_MARKER1
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:58
static vlib_node_registration_t udp_ping_node
(constructor) VLIB_REGISTER_NODE (udp_ping_node)
Definition: udp_ping_node.c:97
icmpr_flow_t * flow
Definition: main.c:123
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
int ip6_hbh_ioam_trace_data_list_handler(vlib_buffer_t *b, ip6_header_t *ip, ip6_hop_by_hop_option_t *opt)
ip6_address_t dst_address
Definition: ip6_packet.h:378
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:170