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