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