FD.io VPP  v18.07.1-19-g511ce25
Vector Packet Processing
oam.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 #include <vpp/oam/oam.h>
16 
18 
20 
21 static void
23 {
24  oam_template_t *h;
25  int i;
26  ip_csum_t sum;
27  u16 csum;
28 
29  vec_validate (t->template, 0);
30 
31  h = t->template;
32  memset (h, 0, sizeof (*h));
33 
34  h->ip4.src_address.as_u32 = t->src_address.as_u32;
35  h->ip4.dst_address.as_u32 = t->dst_address.as_u32;
36  h->ip4.ip_version_and_header_length = 0x45;
37  h->ip4.length = clib_host_to_net_u16 (sizeof (*h));
38  h->ip4.ttl = 64; /* as in linux */
39  h->ip4.protocol = IP_PROTOCOL_ICMP;
40  h->ip4.checksum = ip4_header_checksum (&h->ip4);
41 
42  /*
43  * Template has seq = 0. Each time we send one of these puppies,
44  * change the sequence number and fix the execrated checksum
45  */
46  h->icmp.type = ICMP4_echo_request;
47  h->id = clib_host_to_net_u16 (t->id);
48 
49  for (i = 0; i < ARRAY_LEN (h->data); i++)
50  h->data[i] = 'A' + i;
51 
52  sum = ip_incremental_checksum (0, &h->icmp,
53  sizeof (h->icmp) + sizeof (h->id) +
54  sizeof (h->seq) + sizeof (h->data));
55  csum = ~ip_csum_fold (sum);
56  h->icmp.checksum = csum;
57 }
58 
59 int
61  ip4_address_t * dst_address, u32 fib_id, int is_add)
62 {
63  u64 key;
64  uword *p;
65  oam_main_t *om = &oam_main;
66  oam_target_t *t;
67  ip4_main_t *im = &ip4_main;
68  u32 fib_index;
69 
70  /* Make sure the FIB actually exists */
71  p = hash_get (im->fib_index_by_table_id, fib_id);
72  if (!p)
73  return VNET_API_ERROR_NO_SUCH_FIB;
74 
75  fib_index = p[0];
76 
77  key = ((u64) fib_index << 32) | (dst_address->as_u32);
79 
80  if (is_add)
81  {
82  if (p)
83  return VNET_API_ERROR_INVALID_REGISTRATION; /* already there... */
84 
85  pool_get (om->targets, t);
86  memset (t, 0, sizeof (*t));
87  t->src_address.as_u32 = src_address->as_u32;
88  t->dst_address.as_u32 = dst_address->as_u32;
89  t->fib_id = fib_id;
90  t->fib_index = fib_index;
91  t->state = OAM_STATE_DEAD;
93  t->last_heard_seq = (u16) ~ om->misses_allowed;
94  t->id = (u16) random_u32 (&om->random_seed);
95  t->seq = 1;
97  hash_set (om->target_by_address_and_fib_id, key, t - om->targets);
98  }
99  else
100  {
101  if (!p)
102  return VNET_API_ERROR_NO_SUCH_ENTRY; /* no such oam target */
103  t = pool_elt_at_index (om->targets, p[0]);
104  vec_free (t->template);
106  pool_put (om->targets, t);
107  }
108  return 0;
109 }
110 
111 static clib_error_t *
113  unformat_input_t * input,
114  vlib_cli_command_t * cmd)
115 {
116  int is_add = -1;
117  ip4_address_t src_address;
118  int src_set = 0;
119  ip4_address_t dst_address;
120  int dst_set = 0;
121  u32 fib_id = 0;
122 
124  {
125  if (unformat (input, "add"))
126  is_add = 1;
127  else if (unformat (input, "del"))
128  is_add = 0;
129  else if (unformat (input, "src %U", unformat_ip4_address, &src_address))
130  src_set = 1;
131  else if (unformat (input, "dst %U", unformat_ip4_address, &dst_address))
132  dst_set = 1;
133  else if (unformat (input, "fib %d", &fib_id))
134  ;
135  else
136  return clib_error_return (0, "unknown input `%U'",
137  format_unformat_error, input);
138  }
139 
140  if (is_add == -1)
141  return clib_error_return (0, "missing add / del qualifier");
142  if (src_set == 0)
143  return clib_error_return (0, "src address not set");
144  if (dst_set == 0)
145  return clib_error_return (0, "dst address not set");
146 
147  (void) vpe_oam_add_del_target (&src_address, &dst_address, fib_id, is_add);
148 
149  return 0;
150 }
151 
152 /* *INDENT-OFF* */
153 VLIB_CLI_COMMAND (oam_add_del_target_command, static) = {
154  .path = "oam",
155  .short_help = "oam [add|del] target <ip4-address> fib <fib-id>",
156  .function = oam_add_del_target_command_fn,
157 };
158 /* *INDENT-ON* */
159 
160 static uword
162 {
163  oam_main_t *om = &oam_main;
164  uword *event_data = 0;
165  oam_target_t *t;
166  oam_template_t *h0;
167  u32 bi0;
168  u16 new_seq;
169  ip_csum_t sum0;
170  vlib_frame_t *f;
171  u32 *to_next, *from;
172  u32 ip4_lookup_node_index;
174  vlib_buffer_t *b0;
175  static u32 *buffers;
176  oam_template_copy_t *copy_src, *copy_dst;
177  void send_oam_event (oam_target_t * t);
178  u32 nalloc;
179 
180  /* Enqueue pkts to ip4-lookup */
181  ip4_lookup_node = vlib_get_node_by_name (vm, (u8 *) "ip4-lookup");
182  ip4_lookup_node_index = ip4_lookup_node->index;
183 
184  while (1)
185  {
186  /* Only timeout events at the moment */
188  vec_reset_length (event_data);
189 
190  if (pool_elts (om->targets) == 0)
191  continue;
192 
193  if (vec_len (buffers) < pool_elts (om->targets))
194  vec_validate (buffers, pool_elts (om->targets) - 1);
195 
196  nalloc = vlib_buffer_alloc (vm, buffers, pool_elts (om->targets));
197  if (nalloc < pool_elts (om->targets))
198  {
199  vlib_buffer_free (vm, buffers, nalloc);
200  continue;
201  }
202 
203  f = vlib_get_frame_to_node (vm, ip4_lookup_node_index);
204  f->n_vectors = 0;
205  to_next = vlib_frame_vector_args (f);
206  from = buffers;
207 
208  /* *INDENT-OFF* */
209  pool_foreach (t, om->targets,
210  ({
211  /* State transition announcement... */
212  if ((t->seq - t->last_heard_seq) >= om->misses_allowed)
213  {
214  if (t->state == OAM_STATE_ALIVE)
215  {
216  if (CLIB_DEBUG > 0)
217  clib_warning ("oam target %U now DEAD",
218  format_ip4_address, &t->dst_address);
219  t->state = OAM_STATE_DEAD;
220  send_oam_event (t);
221  }
222  }
223  else
224  {
225  if (t->state == OAM_STATE_DEAD)
226  {
227  if (CLIB_DEBUG > 0)
228  clib_warning ("oam target %U now ALIVE",
229  format_ip4_address, &t->dst_address);
230  t->state = OAM_STATE_ALIVE;
231  send_oam_event (t);
232  }
233  }
234 
235  /* Send a new icmp */
236  t->seq++;
237  new_seq = clib_host_to_net_u16 (t->seq);
238 
239  bi0 = from[0];
240  from++;
241 
242  b0 = vlib_get_buffer (vm, bi0);
243  vnet_buffer (b0)->sw_if_index[VLIB_RX] = 0;
244  vnet_buffer (b0)->sw_if_index [VLIB_TX] = t->fib_index;
245 
246  /* Marginally faster than memcpy, probably */
247  copy_dst = (oam_template_copy_t *) b0->data;
248  copy_src = (oam_template_copy_t *) t->template;
249 
250  copy_dst->v8[0] = copy_src->v8[0];
251  copy_dst->v8[1] = copy_src->v8[1];
252  copy_dst->v8[2] = copy_src->v8[2];
253  copy_dst->v8[3] = copy_src->v8[3];
254  copy_dst->v4 = copy_src->v4;
255 
256  b0->current_data = 0;
257  b0->current_length = sizeof (*t->template);
258  h0 = vlib_buffer_get_current (b0);
259 
260  sum0 = h0->icmp.checksum;
261  sum0 = ip_csum_update(sum0, 0 /* old seq */,
262  new_seq, oam_template_t, seq);
263  h0->seq = new_seq;
264  h0->icmp.checksum = ip_csum_fold (sum0);
265 
266  to_next[0] = bi0;
267  to_next++;
268  f->n_vectors++;
269  if (f->n_vectors == VLIB_FRAME_SIZE)
270  {
271  clib_warning ("Too many OAM clients...");
272  goto out;
273  }
274  }));
275  /* *INDENT-ON* */
276 
277  out:
278  vlib_put_frame_to_node (vm, ip4_lookup_node_index, f);
279  }
280  return 0; /* not so much */
281 }
282 
283 /* *INDENT-OFF* */
285  .function = oam_process,
286  .type = VLIB_NODE_TYPE_PROCESS,
287  .name = "vpe-oam-process",
288 };
289 /* *INDENT-ON* */
290 
291 static clib_error_t *
293 {
294  oam_main_t *om = &oam_main;
295  f64 interval;
296  u32 misses_allowed;
297 
299  {
300  if (unformat (input, "interval %f", &interval))
301  om->interval = interval;
302  else if (unformat (input, "misses-allowed %d", &misses_allowed))
303  om->interval = misses_allowed;
304  else
305  return clib_error_return (0, "unknown input `%U'",
306  format_unformat_error, input);
307  }
308  return 0;
309 }
310 
312 
313 static clib_error_t *
315 {
316  oam_main_t *om = &oam_main;
317 
318  om->vlib_main = vm;
319  om->vnet_main = vnet_get_main ();
320  om->interval = 2.04;
321  om->misses_allowed = 3;
322  om->random_seed = (u32) (vlib_time_now (vm) * 1e6);
323  om->target_by_address_and_fib_id = hash_create (0, sizeof (uword));
324  om->icmp_id = random_u32 (&om->random_seed);
325 
326  ip4_icmp_register_type (vm, ICMP4_echo_reply, oam_node.index);
327 
328  return 0;
329 }
330 
332 
333 static u8 *
334 format_oam_target (u8 * s, va_list * args)
335 {
336  oam_target_t *t = va_arg (*args, oam_target_t *);
337  int verbose = va_arg (*args, int);
338 
339  if (t == 0)
340  return format (s, "%=6s%=14s%=14s%=12s%=10s",
341  "Fib", "Src", "Dst", "Last Heard", "State");
342 
343  s = format (s, "%=6d%=14U%=14U%=12.2f%=10s",
344  t->fib_id,
347  t->last_heard_time,
348  (t->state == OAM_STATE_ALIVE) ? "alive" : "dead");
349  if (verbose)
350  s = format (s, " seq %d last_heard_seq %d", t->seq, t->last_heard_seq);
351 
352  return s;
353 }
354 
355 static clib_error_t *
357  unformat_input_t * input, vlib_cli_command_t * cmd)
358 {
359  oam_main_t *om = &oam_main;
360  oam_target_t *t;
361  int verbose = 0;
362 
363  if (unformat (input, "verbose") || unformat (input, "v"))
364  verbose = 1;
365 
366  /* print header */
367  vlib_cli_output (vm, "%U", format_oam_target, 0, verbose);
368 
369  /* *INDENT-OFF* */
370  pool_foreach (t, om->targets,
371  ({
372  vlib_cli_output (vm, "%U", format_oam_target, t, verbose);
373  }));
374  /* *INDENT-ON* */
375 
376  return 0;
377 }
378 
379 /* *INDENT-OFF* */
380 VLIB_CLI_COMMAND (show_oam_command, static) = {
381  .path = "show oam",
382  .short_help = "show oam",
383  .function = show_oam_command_fn,
384 };
385 /* *INDENT-ON* */
386 
387 typedef struct
388 {
391 } oam_trace_t;
392 
393 /* packet trace format function */
394 static u8 *
395 format_swap_trace (u8 * s, va_list * args)
396 {
397  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
398  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
399  oam_trace_t *t = va_arg (*args, oam_trace_t *);
400 
401  s = format (s, "OAM: rx from address %U, target index %d",
403  return s;
404 }
405 
406 
407 #define foreach_oam_error \
408 _(PROCESSED, "vpe icmp4 oam replies processed") \
409 _(DROPPED, "icmp4 replies dropped (no registration)")
410 
411 typedef enum
412 {
413 #define _(sym,str) OAM_ERROR_##sym,
415 #undef _
417 } oam_error_t;
418 
419 static char *oam_error_strings[] = {
420 #define _(sym,string) string,
422 #undef _
423 };
424 
425 /*
426  * To drop a pkt and increment one of the previous counters:
427  *
428  * set b0->error = error_node->errors[OAM_ERROR_EXAMPLE];
429  * set next0 to a disposition index bound to "error-drop".
430  *
431  * To manually increment the specific counter OAM_ERROR_EXAMPLE:
432  *
433  * vlib_node_t *n = vlib_get_node (vm, oam.index);
434  * u32 node_counter_base_index = n->error_heap_index;
435  * vlib_error_main_t * em = &vm->error_main;
436  * em->counters[node_counter_base_index + OAM_ERROR_EXAMPLE] += 1;
437  *
438  */
439 
440 typedef enum
441 {
445 } oam_next_t;
446 
447 static uword
449  vlib_node_runtime_t * node, vlib_frame_t * frame)
450 {
451  u32 n_left_from, *from, *to_next;
452  oam_next_t next_index;
453  oam_main_t *om = &oam_main;
454  u32 next0 = OAM_NEXT_DROP; /* all pkts go to the hopper... */
455  u32 next1 = OAM_NEXT_DROP;
456  uword *u0, *u1;
457  oam_template_t *oam0, *oam1;
458  u32 fib_index0, fib_index1;
459  u64 key0, key1;
460  oam_target_t *t0, *t1;
461  ip4_main_t *im = &ip4_main;
462 
463  from = vlib_frame_vector_args (frame);
464  n_left_from = frame->n_vectors;
465  next_index = node->cached_next_index;
466 
467  while (n_left_from > 0)
468  {
469  u32 n_left_to_next;
470 
471  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
472 
473  while (n_left_from >= 4 && n_left_to_next >= 2)
474  {
475  u32 bi0, bi1;
476  vlib_buffer_t *b0, *b1;
477  u32 sw_if_index0, sw_if_index1;
478 
479  /* Prefetch next iteration. */
480  {
481  vlib_buffer_t *p2, *p3;
482 
483  p2 = vlib_get_buffer (vm, from[2]);
484  p3 = vlib_get_buffer (vm, from[3]);
485 
486  vlib_prefetch_buffer_header (p2, LOAD);
487  vlib_prefetch_buffer_header (p3, LOAD);
488 
491  }
492 
493  /* speculatively enqueue b0 and b1 to the current next frame */
494  to_next[0] = bi0 = from[0];
495  to_next[1] = bi1 = from[1];
496  from += 2;
497  to_next += 2;
498  n_left_from -= 2;
499  n_left_to_next -= 2;
500 
501  b0 = vlib_get_buffer (vm, bi0);
502  b1 = vlib_get_buffer (vm, bi1);
503 
504  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
505  sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
506 
507  oam0 = vlib_buffer_get_current (b0);
508  oam1 = vlib_buffer_get_current (b1);
509  fib_index0 = vec_elt (im->fib_index_by_sw_if_index, sw_if_index0);
510  fib_index1 = vec_elt (im->fib_index_by_sw_if_index, sw_if_index1);
511 
512  key0 = ((u64) fib_index0 << 32) | oam0->ip4.src_address.as_u32;
513  u0 = hash_get (om->target_by_address_and_fib_id, key0);
514  if (u0)
515  {
516  t0 = pool_elt_at_index (om->targets, u0[0]);
517  t0->last_heard_time = vlib_time_now (vm);
518  t0->last_heard_seq = clib_net_to_host_u16 (oam0->seq);
519  b0->error = node->errors[OAM_ERROR_PROCESSED];
520  }
521  else
522  b0->error = node->errors[OAM_ERROR_DROPPED];
523 
524  key1 = ((u64) fib_index1 << 32) | oam1->ip4.src_address.as_u32;
525  u1 = hash_get (om->target_by_address_and_fib_id, key1);
526  if (u1)
527  {
528  t1 = pool_elt_at_index (om->targets, u1[0]);
529  t1->last_heard_time = vlib_time_now (vm);
530  t1->last_heard_seq = clib_net_to_host_u16 (oam1->seq);
531  b1->error = node->errors[OAM_ERROR_PROCESSED];
532  }
533  else
534  b1->error = node->errors[OAM_ERROR_DROPPED];
535 
536  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
537  {
538  if (b0->flags & VLIB_BUFFER_IS_TRACED)
539  {
540  oam_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t));
541  t->target_pool_index = u0 ? u0[0] : (u32) ~ 0;
542  t->address.as_u32 = oam0->ip4.src_address.as_u32;
543  }
544  if (b1->flags & VLIB_BUFFER_IS_TRACED)
545  {
546  oam_trace_t *t = vlib_add_trace (vm, node, b1, sizeof (*t));
547  t->target_pool_index = u1 ? u1[0] : (u32) ~ 0;
548  t->address.as_u32 = oam1->ip4.src_address.as_u32;
549 
550  }
551  }
552 
553  if (vm->os_punt_frame)
554  next0 = next1 = OAM_NEXT_PUNT;
555 
556  /* verify speculative enqueues, maybe switch current next frame */
557  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
558  to_next, n_left_to_next,
559  bi0, bi1, next0, next1);
560  }
561 
562  while (n_left_from > 0 && n_left_to_next > 0)
563  {
564  u32 bi0, sw_if_index0;
565  vlib_buffer_t *b0;
566 
567  /* speculatively enqueue b0 to the current next frame */
568  bi0 = from[0];
569  to_next[0] = bi0;
570  from += 1;
571  to_next += 1;
572  n_left_from -= 1;
573  n_left_to_next -= 1;
574 
575  b0 = vlib_get_buffer (vm, bi0);
576 
577  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
578 
579  oam0 = vlib_buffer_get_current (b0);
580  fib_index0 = vec_elt (im->fib_index_by_sw_if_index, sw_if_index0);
581 
582  key0 = ((u64) fib_index0 << 32) | oam0->ip4.src_address.as_u32;
583  u0 = hash_get (om->target_by_address_and_fib_id, key0);
584  if (u0)
585  {
586  t0 = pool_elt_at_index (om->targets, u0[0]);
587  t0->last_heard_time = vlib_time_now (vm);
588  t0->last_heard_seq = clib_net_to_host_u16 (oam0->seq);
589  b0->error = node->errors[OAM_ERROR_PROCESSED];
590  }
591  else
592  b0->error = node->errors[OAM_ERROR_DROPPED];
593 
595  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
596  {
597  oam_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t));
598  t->target_pool_index = u0 ? u0[0] : (u32) ~ 0;
599  t->address.as_u32 = oam0->ip4.src_address.as_u32;
600  }
601 
602  if (vm->os_punt_frame)
603  next0 = OAM_NEXT_PUNT;
604 
605  /* verify speculative enqueue, maybe switch current next frame */
606  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
607  to_next, n_left_to_next,
608  bi0, next0);
609  }
610 
611  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
612  }
613 
614  return frame->n_vectors;
615 }
616 
617 /* *INDENT-OFF* */
618 VLIB_REGISTER_NODE (oam_node,static) = {
619  .function = oam_node_fn,
620  .name = "vpe-icmp4-oam",
621  .vector_size = sizeof (u32),
622  .format_trace = format_swap_trace,
623  .type = VLIB_NODE_TYPE_INTERNAL,
624 
625  .n_errors = ARRAY_LEN(oam_error_strings),
626  .error_strings = oam_error_strings,
627 
628  .n_next_nodes = OAM_N_NEXT,
629 
630  /* edit / add dispositions here */
631  .next_nodes = {
632  [OAM_NEXT_DROP] = "error-drop",
633  [OAM_NEXT_PUNT] = "error-punt",
634  },
635 };
636 /* *INDENT-ON* */
637 
638 /*
639  * fd.io coding-style-patch-verification: ON
640  *
641  * Local Variables:
642  * eval: (c-set-style "gnu")
643  * End:
644  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:437
static clib_error_t * oam_config(vlib_main_t *vm, unformat_input_t *input)
Definition: oam.c:292
static void init_oam_packet_template(oam_main_t *om, oam_target_t *t)
Definition: oam.c:22
#define hash_set(h, key, value)
Definition: hash.h:255
#define CLIB_UNUSED(x)
Definition: clib.h:79
u16 id
Definition: oam.h:57
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
#define hash_unset(h, key)
Definition: hash.h:261
f64 interval
Definition: oam.h:69
static void vlib_buffer_free(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Free buffers Frees the entire buffer chain for each buffer.
Definition: buffer_funcs.h:534
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
ip4_address_t address
Definition: oam.c:390
unsigned long u64
Definition: types.h:89
u32 index
Definition: node.h:273
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:228
oam_error_t
Definition: oam.c:411
u16 icmp_id
Definition: oam.h:74
f64 last_heard_time
Definition: oam.h:54
int i
uword ip_csum_t
Definition: ip_packet.h:181
u32 * fib_index_by_sw_if_index
Table index indexed by software interface.
Definition: ip4.h:111
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:451
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:228
unsigned char u8
Definition: types.h:56
oam_next_t
Definition: oam.c:440
oam_template_t * template
Definition: oam.h:59
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
double f64
Definition: types.h:142
u32 misses_allowed
Definition: oam.h:70
vlib_node_registration_t ip4_lookup_node
(constructor) VLIB_REGISTER_NODE (ip4_lookup_node)
Definition: ip4_forward.c:104
format_function_t format_ip4_address
Definition: format.h:81
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:104
void send_oam_event(oam_target_t *t)
Definition: oam_api.c:47
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:443
unformat_function_t unformat_ip4_address
Definition: format.h:76
u16 last_heard_seq
Definition: oam.h:56
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:156
oam_main_t oam_main
Definition: oam.c:17
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:184
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:182
#define clib_error_return(e, args...)
Definition: error.h:99
unsigned int u32
Definition: types.h:88
static clib_error_t * oam_init(vlib_main_t *vm)
Definition: oam.c:314
u32 target_pool_index
Definition: oam.c:389
vlib_main_t * vlib_main
Definition: oam.h:80
#define VLIB_FRAME_SIZE
Definition: node.h:364
static vlib_node_registration_t oam_node
(constructor) VLIB_REGISTER_NODE (oam_node)
Definition: oam.c:19
uword * target_by_address_and_fib_id
Definition: oam.h:66
void ip4_icmp_register_type(vlib_main_t *vm, icmp4_type_t type, u32 node_index)
Definition: icmp4.c:733
#define hash_get(h, key)
Definition: hash.h:249
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:464
Definition: oam.h:62
uword * fib_index_by_table_id
Hash table mapping table id to fib index.
Definition: ip4.h:121
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:108
struct _unformat_input_t unformat_input_t
unsigned short u16
Definition: types.h:57
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:191
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:202
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:274
#define PREDICT_FALSE(x)
Definition: clib.h:105
#define VLIB_CONFIG_FUNCTION(x, n,...)
Definition: init.h:164
#define foreach_oam_error
Definition: oam.c:407
#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:135
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:153
#define UNFORMAT_END_OF_INPUT
Definition: format.h:144
u16 n_vectors
Definition: node.h:380
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:77
vlib_main_t * vm
Definition: buffer.c:294
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:339
u32 fib_id
Definition: oam.h:52
static ip_csum_t ip_incremental_checksum(ip_csum_t sum, void *_data, uword n_bytes)
Definition: ip_packet.h:254
#define clib_warning(format, args...)
Definition: error.h:59
static vlib_node_registration_t oam_process_node
(constructor) VLIB_REGISTER_NODE (oam_process_node)
Definition: oam.c:284
#define ARRAY_LEN(x)
Definition: clib.h:59
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:454
vlib_node_t * vlib_get_node_by_name(vlib_main_t *vm, u8 *name)
Definition: node.c:45
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
static uword oam_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: oam.c:448
static uword oam_process(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f_arg)
Definition: oam.c:161
#define hash_create(elts, value_bytes)
Definition: hash.h:696
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:492
int vpe_oam_add_del_target(ip4_address_t *src_address, ip4_address_t *dst_address, u32 fib_id, int is_add)
Definition: oam.c:60
IPv4 main type.
Definition: ip4.h:95
static char * oam_error_strings[]
Definition: oam.c:419
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:55
#define vec_elt(v, i)
Get vector value at index i.
struct _vlib_node_registration vlib_node_registration_t
Definition: defs.h:47
static clib_error_t * show_oam_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: oam.c:356
ip4_address_t src_address
Definition: oam.h:50
u32 fib_index
Definition: oam.h:53
static u8 * format_swap_trace(u8 *s, va_list *args)
Definition: oam.c:395
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
u32 random_seed
Definition: oam.h:73
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
#define ip_csum_update(sum, old, new, type, field)
Definition: ip_packet.h:231
static u8 * format_oam_target(u8 *s, va_list *args)
Definition: oam.c:334
oam_target_t * targets
Definition: oam.h:65
#define vnet_buffer(b)
Definition: buffer.h:360
static u32 random_u32(u32 *seed)
32-bit random number generator
Definition: random.h:69
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:832
u8 data[0]
Packet data.
Definition: buffer.h:172
u16 seq
Definition: oam.h:55
void(* os_punt_frame)(struct vlib_main_t *vm, struct vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: main.h:148
u16 flags
Copy of main node flags.
Definition: node.h:486
vnet_main_t * vnet_main
Definition: oam.h:81
u8 state
Definition: oam.h:58
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:295
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:62
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:111
static u32 vlib_buffer_alloc(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Allocate buffers into supplied array.
Definition: buffer_funcs.h:490
static clib_error_t * oam_add_del_target_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: oam.c:112
ip4_address_t dst_address
Definition: oam.h:51
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:681
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:57
static u16 ip4_header_checksum(ip4_header_t *i)
Definition: ip4_packet.h:246
static u16 ip_csum_fold(ip_csum_t c)
Definition: ip_packet.h:237
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
Definition: defs.h:46
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:170
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128