FD.io VPP  v17.07.01-10-g3be13f0
Vector Packet Processing
replicate_dpo.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 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/ip/lookup.h>
17 #include <vnet/dpo/replicate_dpo.h>
18 #include <vnet/dpo/drop_dpo.h>
19 #include <vnet/adj/adj.h>
20 #include <vnet/mpls/mpls_types.h>
21 
22 #undef REP_DEBUG
23 
24 #ifdef REP_DEBUG
25 #define REP_DBG(_rep, _fmt, _args...) \
26 { \
27  u8* _tmp =NULL; \
28  clib_warning("rep:[%s]:" _fmt, \
29  replicate_format(replicate_get_index((_rep)), \
30  0, _tmp), \
31  ##_args); \
32  vec_free(_tmp); \
33 }
34 #else
35 #define REP_DBG(_p, _fmt, _args...)
36 #endif
37 
38 #define foreach_replicate_dpo_error \
39 _(BUFFER_ALLOCATION_FAILURE, "Buffer Allocation Failure")
40 
41 typedef enum {
42 #define _(sym,str) REPLICATE_DPO_ERROR_##sym,
44 #undef _
47 
48 static char * replicate_dpo_error_strings[] = {
49 #define _(sym,string) string,
51 #undef _
52 };
53 
54 /**
55  * Pool of all DPOs. It's not static so the DP can have fast access
56  */
58 
59 /**
60  * The one instance of replicate main
61  */
63 
64 static inline index_t
66 {
67  return (rep - replicate_pool);
68 }
69 
70 static inline dpo_id_t*
72 {
73  if (REP_HAS_INLINE_BUCKETS(rep))
74  {
75  return (rep->rep_buckets_inline);
76  }
77  else
78  {
79  return (rep->rep_buckets);
80  }
81 }
82 
83 static replicate_t *
85 {
86  replicate_t *rep;
87 
88  pool_get_aligned(replicate_pool, rep, CLIB_CACHE_LINE_BYTES);
89  memset(rep, 0, sizeof(*rep));
90 
92  replicate_get_index(rep));
93  vlib_zero_combined_counter(&(replicate_main.repm_counters),
94  replicate_get_index(rep));
95 
96  return (rep);
97 }
98 
99 static u8*
102  u32 indent,
103  u8 *s)
104 {
105  vlib_counter_t to;
106  replicate_t *rep;
107  dpo_id_t *buckets;
108  u32 i;
109 
110  repi &= ~MPLS_IS_REPLICATE;
111  rep = replicate_get(repi);
112  vlib_get_combined_counter(&(replicate_main.repm_counters), repi, &to);
113  buckets = replicate_get_buckets(rep);
114 
115  s = format(s, "%U: ", format_dpo_type, DPO_REPLICATE);
116  s = format(s, "[index:%d buckets:%d ", repi, rep->rep_n_buckets);
117  s = format(s, "to:[%Ld:%Ld]]", to.packets, to.bytes);
118 
119  for (i = 0; i < rep->rep_n_buckets; i++)
120  {
121  s = format(s, "\n%U", format_white_space, indent+2);
122  s = format(s, "[%d]", i);
123  s = format(s, " %U", format_dpo_id, &buckets[i], indent+6);
124  }
125  return (s);
126 }
127 
128 u8*
129 format_replicate (u8 * s, va_list * args)
130 {
131  index_t repi = va_arg(*args, index_t);
133 
134  return (replicate_format(repi, flags, 0, s));
135 }
136 static u8*
137 format_replicate_dpo (u8 * s, va_list * args)
138 {
139  index_t repi = va_arg(*args, index_t);
140  u32 indent = va_arg(*args, u32);
141 
142  return (replicate_format(repi, REPLICATE_FORMAT_DETAIL, indent, s));
143 }
144 
145 
146 static replicate_t *
147 replicate_create_i (u32 num_buckets,
148  dpo_proto_t rep_proto)
149 {
150  replicate_t *rep;
151 
152  rep = replicate_alloc_i();
153  rep->rep_n_buckets = num_buckets;
154  rep->rep_proto = rep_proto;
155 
156  if (!REP_HAS_INLINE_BUCKETS(rep))
157  {
159  rep->rep_n_buckets - 1,
161  }
162 
163  REP_DBG(rep, "create");
164 
165  return (rep);
166 }
167 
168 index_t
170  dpo_proto_t rep_proto)
171 {
172  return (replicate_get_index(replicate_create_i(n_buckets, rep_proto)));
173 }
174 
175 static inline void
177  u32 bucket,
178  dpo_id_t *buckets,
179  const dpo_id_t *next)
180 {
181  dpo_stack(DPO_REPLICATE, rep->rep_proto, &buckets[bucket], next);
182 }
183 
184 void
186  u32 bucket,
187  const dpo_id_t *next)
188 {
189  replicate_t *rep;
190  dpo_id_t *buckets;
191 
192  repi &= ~MPLS_IS_REPLICATE;
193  rep = replicate_get(repi);
194  buckets = replicate_get_buckets(rep);
195 
196  ASSERT(bucket < rep->rep_n_buckets);
197 
198  replicate_set_bucket_i(rep, bucket, buckets, next);
199 }
200 
201 int
203 {
204  replicate_t *rep;
205  index_t repi;
206 
207  if (DPO_REPLICATE != dpo->dpoi_type)
208  return (0);
209 
210  repi = dpo->dpoi_index & ~MPLS_IS_REPLICATE;
211  rep = replicate_get(repi);
212 
213  if (1 == rep->rep_n_buckets)
214  {
215  return (dpo_is_drop(replicate_get_bucket_i(rep, 0)));
216  }
217  return (0);
218 }
219 
220 const dpo_id_t *
222  u32 bucket)
223 {
224  replicate_t *rep;
225 
226  repi &= ~MPLS_IS_REPLICATE;
227  rep = replicate_get(repi);
228 
229  return (replicate_get_bucket_i(rep, bucket));
230 }
231 
232 
233 static load_balance_path_t *
235  dpo_proto_t drop_proto)
236 {
237  if (0 == vec_len(nhs))
238  {
240 
241  /*
242  * we need something for the replicate. so use the drop
243  */
244  vec_add2(nhs, nh, 1);
245 
246  nh->path_weight = 1;
247  dpo_copy(&nh->path_dpo, drop_dpo_get(drop_proto));
248  }
249 
250  return (nhs);
251 }
252 
253 /*
254  * Fill in adjacencies in block based on corresponding
255  * next hop adjacencies.
256  */
257 static void
259  load_balance_path_t *nhs,
260  dpo_id_t *buckets,
261  u32 n_buckets)
262 {
263  load_balance_path_t * nh;
264  u16 ii, bucket;
265 
266  bucket = 0;
267 
268  /*
269  * the next-hops have normalised weights. that means their sum is the number
270  * of buckets we need to fill.
271  */
272  vec_foreach (nh, nhs)
273  {
274  for (ii = 0; ii < nh->path_weight; ii++)
275  {
276  ASSERT(bucket < n_buckets);
277  replicate_set_bucket_i(rep, bucket++, buckets, &nh->path_dpo);
278  }
279  }
280 }
281 
282 static inline void
284  u32 n_buckets)
285 {
286  rep->rep_n_buckets = n_buckets;
287 }
288 
289 void
291  load_balance_path_t * next_hops)
292 {
293  load_balance_path_t * nh, * nhs;
294  dpo_id_t *tmp_dpo;
295  u32 ii, n_buckets;
296  replicate_t *rep;
297  index_t repi;
298 
299  ASSERT(DPO_REPLICATE == dpo->dpoi_type);
300  repi = dpo->dpoi_index & ~MPLS_IS_REPLICATE;
301  rep = replicate_get(repi);
302  nhs = replicate_multipath_next_hop_fixup(next_hops,
303  rep->rep_proto);
304  n_buckets = vec_len(nhs);
305 
306  if (0 == rep->rep_n_buckets)
307  {
308  /*
309  * first time initialisation. no packets inflight, so we can write
310  * at leisure.
311  */
312  replicate_set_n_buckets(rep, n_buckets);
313 
314  if (!REP_HAS_INLINE_BUCKETS(rep))
316  rep->rep_n_buckets - 1,
318 
319  replicate_fill_buckets(rep, nhs,
321  n_buckets);
322  }
323  else
324  {
325  /*
326  * This is a modification of an existing replicate.
327  * We need to ensure that packets in flight see a consistent state, that
328  * is the number of reported buckets the REP has
329  * is not more than it actually has. So if the
330  * number of buckets is increasing, we must update the bucket array first,
331  * then the reported number. vice-versa if the number of buckets goes down.
332  */
333  if (n_buckets == rep->rep_n_buckets)
334  {
335  /*
336  * no change in the number of buckets. we can simply fill what
337  * is new over what is old.
338  */
339  replicate_fill_buckets(rep, nhs,
341  n_buckets);
342  }
343  else if (n_buckets > rep->rep_n_buckets)
344  {
345  /*
346  * we have more buckets. the old replicate map (if there is one)
347  * will remain valid, i.e. mapping to indices within range, so we
348  * update it last.
349  */
350  if (n_buckets > REP_NUM_INLINE_BUCKETS &&
352  {
353  /*
354  * the new increased number of buckets is crossing the threshold
355  * from the inline storage to out-line. Alloc the outline buckets
356  * first, then fixup the number. then reset the inlines.
357  */
358  ASSERT(NULL == rep->rep_buckets);
360  n_buckets - 1,
362 
363  replicate_fill_buckets(rep, nhs,
364  rep->rep_buckets,
365  n_buckets);
367  replicate_set_n_buckets(rep, n_buckets);
368 
370 
371  for (ii = 0; ii < REP_NUM_INLINE_BUCKETS; ii++)
372  {
373  dpo_reset(&rep->rep_buckets_inline[ii]);
374  }
375  }
376  else
377  {
378  if (n_buckets <= REP_NUM_INLINE_BUCKETS)
379  {
380  /*
381  * we are not crossing the threshold and it's still inline buckets.
382  * we can write the new on the old..
383  */
384  replicate_fill_buckets(rep, nhs,
386  n_buckets);
388  replicate_set_n_buckets(rep, n_buckets);
389  }
390  else
391  {
392  /*
393  * we are not crossing the threshold. We need a new bucket array to
394  * hold the increased number of choices.
395  */
396  dpo_id_t *new_buckets, *old_buckets, *tmp_dpo;
397 
398  new_buckets = NULL;
399  old_buckets = replicate_get_buckets(rep);
400 
401  vec_validate_aligned(new_buckets,
402  n_buckets - 1,
404 
405  replicate_fill_buckets(rep, nhs, new_buckets, n_buckets);
407  rep->rep_buckets = new_buckets;
409  replicate_set_n_buckets(rep, n_buckets);
410 
411  vec_foreach(tmp_dpo, old_buckets)
412  {
413  dpo_reset(tmp_dpo);
414  }
415  vec_free(old_buckets);
416  }
417  }
418  }
419  else
420  {
421  /*
422  * bucket size shrinkage.
423  */
424  if (n_buckets <= REP_NUM_INLINE_BUCKETS &&
426  {
427  /*
428  * the new decreased number of buckets is crossing the threshold
429  * from out-line storage to inline:
430  * 1 - Fill the inline buckets,
431  * 2 - fixup the number (and this point the inline buckets are
432  * used).
433  * 3 - free the outline buckets
434  */
435  replicate_fill_buckets(rep, nhs,
436  rep->rep_buckets_inline,
437  n_buckets);
439  replicate_set_n_buckets(rep, n_buckets);
441 
442  vec_foreach(tmp_dpo, rep->rep_buckets)
443  {
444  dpo_reset(tmp_dpo);
445  }
446  vec_free(rep->rep_buckets);
447  }
448  else
449  {
450  /*
451  * not crossing the threshold.
452  * 1 - update the number to the smaller size
453  * 2 - write the new buckets
454  * 3 - reset those no longer used.
455  */
456  dpo_id_t *buckets;
457  u32 old_n_buckets;
458 
459  old_n_buckets = rep->rep_n_buckets;
460  buckets = replicate_get_buckets(rep);
461 
462  replicate_set_n_buckets(rep, n_buckets);
464 
465  replicate_fill_buckets(rep, nhs,
466  buckets,
467  n_buckets);
468 
469  for (ii = n_buckets; ii < old_n_buckets; ii++)
470  {
471  dpo_reset(&buckets[ii]);
472  }
473  }
474  }
475  }
476 
477  vec_foreach (nh, nhs)
478  {
479  dpo_reset(&nh->path_dpo);
480  }
481  vec_free(nhs);
482 }
483 
484 static void
486 {
487  replicate_t *rep;
488 
489  rep = replicate_get(dpo->dpoi_index);
490 
491  rep->rep_locks++;
492 }
493 
494 static void
496 {
497  dpo_id_t *buckets;
498  int i;
499 
500  buckets = replicate_get_buckets(rep);
501 
502  for (i = 0; i < rep->rep_n_buckets; i++)
503  {
504  dpo_reset(&buckets[i]);
505  }
506 
507  REP_DBG(rep, "destroy");
508  if (!REP_HAS_INLINE_BUCKETS(rep))
509  {
510  vec_free(rep->rep_buckets);
511  }
512 
513  pool_put(replicate_pool, rep);
514 }
515 
516 static void
518 {
519  replicate_t *rep;
520 
521  rep = replicate_get(dpo->dpoi_index);
522 
523  rep->rep_locks--;
524 
525  if (0 == rep->rep_locks)
526  {
527  replicate_destroy(rep);
528  }
529 }
530 
531 static void
533 {
534  fib_show_memory_usage("replicate",
535  pool_elts(replicate_pool),
536  pool_len(replicate_pool),
537  sizeof(replicate_t));
538 }
539 
540 const static dpo_vft_t rep_vft = {
542  .dv_unlock = replicate_unlock,
543  .dv_format = format_replicate_dpo,
544  .dv_mem_show = replicate_mem_show,
545 };
546 
547 /**
548  * @brief The per-protocol VLIB graph nodes that are assigned to a replicate
549  * object.
550  *
551  * this means that these graph nodes are ones from which a replicate is the
552  * parent object in the DPO-graph.
553  */
554 const static char* const replicate_ip4_nodes[] =
555 {
556  "ip4-replicate",
557  NULL,
558 };
559 const static char* const replicate_ip6_nodes[] =
560 {
561  "ip6-replicate",
562  NULL,
563 };
564 const static char* const replicate_mpls_nodes[] =
565 {
566  "mpls-replicate",
567  NULL,
568 };
569 
570 const static char* const * const replicate_nodes[DPO_PROTO_NUM] =
571 {
575 };
576 
577 void
579 {
581 }
582 
583 static clib_error_t *
585  unformat_input_t * input,
586  vlib_cli_command_t * cmd)
587 {
588  index_t repi = INDEX_INVALID;
589 
591  {
592  if (unformat (input, "%d", &repi))
593  ;
594  else
595  break;
596  }
597 
598  if (INDEX_INVALID != repi)
599  {
600  vlib_cli_output (vm, "%U", format_replicate, repi,
602  }
603  else
604  {
605  replicate_t *rep;
606 
607  pool_foreach(rep, replicate_pool,
608  ({
610  replicate_get_index(rep),
612  }));
613  }
614 
615  return 0;
616 }
617 
618 VLIB_CLI_COMMAND (replicate_show_command, static) = {
619  .path = "show replicate",
620  .short_help = "show replicate [<index>]",
621  .function = replicate_show,
622 };
623 
624 typedef struct replicate_trace_t_
625 {
629 
630 static uword
632  vlib_node_runtime_t * node,
633  vlib_frame_t * frame)
634 {
635  vlib_combined_counter_main_t * cm = &replicate_main.repm_counters;
637  u32 n_left_from, * from, * to_next, next_index;
638  u32 thread_index = vlib_get_thread_index();
639 
640  from = vlib_frame_vector_args (frame);
641  n_left_from = frame->n_vectors;
642  next_index = node->cached_next_index;
643 
644  while (n_left_from > 0)
645  {
646  u32 n_left_to_next;
647 
648  vlib_get_next_frame (vm, node, next_index,
649  to_next, n_left_to_next);
650 
651  while (n_left_from > 0 && n_left_to_next > 0)
652  {
653  u32 next0, ci0, bi0, bucket, repi0;
654  const replicate_t *rep0;
655  vlib_buffer_t * b0, *c0;
656  const dpo_id_t *dpo0;
657  u8 num_cloned;
658 
659  bi0 = from[0];
660  from += 1;
661  n_left_from -= 1;
662 
663  b0 = vlib_get_buffer (vm, bi0);
664  repi0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX];
665  rep0 = replicate_get(repi0);
666 
668  cm, thread_index, repi0, 1,
670 
671  vec_validate (rm->clones[thread_index], rep0->rep_n_buckets - 1);
672 
673  num_cloned = vlib_buffer_clone (vm, bi0, rm->clones[thread_index], rep0->rep_n_buckets, 128);
674 
675  if (num_cloned != rep0->rep_n_buckets)
676  {
678  (vm, node->node_index,
679  REPLICATE_DPO_ERROR_BUFFER_ALLOCATION_FAILURE, 1);
680  }
681 
682  for (bucket = 0; bucket < num_cloned; bucket++)
683  {
684  ci0 = rm->clones[thread_index][bucket];
685  c0 = vlib_get_buffer(vm, ci0);
686 
687  to_next[0] = ci0;
688  to_next += 1;
689  n_left_to_next -= 1;
690 
691  dpo0 = replicate_get_bucket_i(rep0, bucket);
692  next0 = dpo0->dpoi_next_node;
693  vnet_buffer (c0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
694 
696  {
697  replicate_trace_t *t = vlib_add_trace (vm, node, c0, sizeof (*t));
698  t->rep_index = repi0;
699  t->dpo = *dpo0;
700  }
701 
702  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
703  to_next, n_left_to_next,
704  ci0, next0);
705  if (PREDICT_FALSE (n_left_to_next == 0))
706  {
707  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
708  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
709  }
710  }
711  vec_reset_length (rm->clones[thread_index]);
712  }
713 
714  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
715  }
716 
717  return frame->n_vectors;
718 }
719 
720 static u8 *
721 format_replicate_trace (u8 * s, va_list * args)
722 {
723  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
724  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
725  replicate_trace_t *t = va_arg (*args, replicate_trace_t *);
726 
727  s = format (s, "replicate: %d via %U",
728  t->rep_index,
729  format_dpo_id, &t->dpo, 0);
730  return s;
731 }
732 
733 static uword
735  vlib_node_runtime_t * node,
736  vlib_frame_t * frame)
737 {
738  return (replicate_inline (vm, node, frame));
739 }
740 
741 /**
742  * @brief IP4 replication node
743  */
745  .function = ip4_replicate,
746  .name = "ip4-replicate",
747  .vector_size = sizeof (u32),
748 
750  .error_strings = replicate_dpo_error_strings,
751 
752  .format_trace = format_replicate_trace,
753  .n_next_nodes = 1,
754  .next_nodes = {
755  [0] = "ip4-drop",
756  },
757 };
758 
759 static uword
761  vlib_node_runtime_t * node,
762  vlib_frame_t * frame)
763 {
764  return (replicate_inline (vm, node, frame));
765 }
766 
767 /**
768  * @brief IPv6 replication node
769  */
771  .function = ip6_replicate,
772  .name = "ip6-replicate",
773  .vector_size = sizeof (u32),
774 
776  .error_strings = replicate_dpo_error_strings,
777 
778  .format_trace = format_replicate_trace,
779  .n_next_nodes = 1,
780  .next_nodes = {
781  [0] = "ip6-drop",
782  },
783 };
784 
785 static uword
787  vlib_node_runtime_t * node,
788  vlib_frame_t * frame)
789 {
790  return (replicate_inline (vm, node, frame));
791 }
792 
793 /**
794  * @brief MPLS replication node
795  */
797  .function = mpls_replicate,
798  .name = "mpls-replicate",
799  .vector_size = sizeof (u32),
800 
802  .error_strings = replicate_dpo_error_strings,
803 
804  .format_trace = format_replicate_trace,
805  .n_next_nodes = 1,
806  .next_nodes = {
807  [0] = "mpls-drop",
808  },
809 };
810 
811 clib_error_t *
813 {
815 
817 
818  return 0;
819 }
820 
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:436
dpo_lock_fn_t dv_lock
A reference counting lock function.
Definition: dpo.h:341
static void replicate_destroy(replicate_t *rep)
#define REP_DBG(_p, _fmt, _args...)
Definition: replicate_dpo.c:35
static dpo_id_t * replicate_get_buckets(replicate_t *rep)
Definition: replicate_dpo.c:71
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:337
#define CLIB_UNUSED(x)
Definition: clib.h:79
A virtual function table regisitered for a DPO type.
Definition: dpo.h:336
void vlib_validate_combined_counter(vlib_combined_counter_main_t *cm, u32 index)
validate a combined counter
Definition: counter.c:89
static void vlib_increment_combined_counter(vlib_combined_counter_main_t *cm, u32 thread_index, u32 index, u64 n_packets, u64 n_bytes)
Increment a combined counter.
Definition: counter.h:211
static void replicate_unlock(dpo_id_t *dpo)
u8 * format_dpo_type(u8 *s, va_list *args)
format a DPO type
Definition: dpo.c:113
dpo_id_t path_dpo
ID of the Data-path object.
Definition: load_balance.h:66
The FIB DPO provieds;.
Definition: replicate_dpo.h:54
replicate_t * replicate_pool
Pool of all DPOs.
Definition: replicate_dpo.c:57
static void replicate_fill_buckets(replicate_t *rep, load_balance_path_t *nhs, dpo_id_t *buckets, u32 n_buckets)
Definitions for all things IP (v4|v6) unicast and multicast lookup related.
#define NULL
Definition: clib.h:55
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
u32 rep_locks
The number of locks, which is approximately the number of users, of this load-balance.
Definition: replicate_dpo.h:73
static void replicate_set_bucket_i(replicate_t *rep, u32 bucket, dpo_id_t *buckets, const dpo_id_t *next)
enum replicate_format_flags_t_ replicate_format_flags_t
Flags controlling load-balance formatting/display.
void dpo_copy(dpo_id_t *dst, const dpo_id_t *src)
atomic copy a data-plane object.
Definition: dpo.c:235
u32 index_t
A Data-Path Object is an object that represents actions that are applied to packets are they are swit...
Definition: dpo.h:41
dpo_proto_t rep_proto
The protocol of packets that traverse this REP.
Definition: replicate_dpo.h:65
Combined counter to hold both packets and byte differences.
Definition: counter.h:139
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:561
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
dpo_id_t * rep_buckets
Vector of buckets containing the next DPOs, sized as repo_num.
Definition: replicate_dpo.h:78
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
Definition: vec.h:447
static u8 vlib_buffer_clone(vlib_main_t *vm, u32 src_buffer, u32 *buffers, u8 n_buffers, u16 head_end_offset)
Create multiple clones of buffer and store them in the supplied array.
Definition: buffer_funcs.h:543
static replicate_t * replicate_get(index_t repi)
static uword vlib_buffer_length_in_chain(vlib_main_t *vm, vlib_buffer_t *b)
Get length in bytes of the buffer chain.
Definition: buffer_funcs.h:100
#define pool_len(p)
Number of elements in pool vector.
Definition: pool.h:121
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
const dpo_id_t * drop_dpo_get(dpo_proto_t proto)
Definition: drop_dpo.c:25
void replicate_set_bucket(index_t repi, u32 bucket, const dpo_id_t *next)
static const char *const *const replicate_nodes[DPO_PROTO_NUM]
replicate_dpo_error_t
Definition: replicate_dpo.c:41
void dpo_register(dpo_type_t type, const dpo_vft_t *vft, const char *const *const *nodes)
For a given DPO type Register:
Definition: dpo.c:260
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:376
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
static u8 * format_replicate_trace(u8 *s, va_list *args)
static char * replicate_dpo_error_strings[]
Definition: replicate_dpo.c:48
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:113
#define MPLS_IS_REPLICATE
The top bit of the index, which is the result of the MPLS lookup is used to determine if the DPO is a...
Definition: mpls_types.h:58
void fib_show_memory_usage(const char *name, u32 in_use_elts, u32 allocd_elts, size_t size_elt)
Show the memory usage for a type.
Definition: fib_node.c:221
static const char *const replicate_ip6_nodes[]
static replicate_t * replicate_create_i(u32 num_buckets, dpo_proto_t rep_proto)
#define REP_HAS_INLINE_BUCKETS(_rep)
enum dpo_proto_t_ dpo_proto_t
Data path protocol.
static clib_error_t * replicate_show(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
static const char *const replicate_ip4_nodes[]
The per-protocol VLIB graph nodes that are assigned to a replicate object.
static index_t replicate_get_index(const replicate_t *rep)
Definition: replicate_dpo.c:65
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:152
replicate main
Definition: replicate_dpo.h:33
static void replicate_mem_show(void)
static void vlib_zero_combined_counter(vlib_combined_counter_main_t *cm, u32 index)
Clear a combined counter Clears the set of per-thread counters.
Definition: counter.h:276
counter_t packets
packet counter
Definition: counter.h:141
dpo_type_t dpoi_type
the type
Definition: dpo.h:156
clib_error_t * replicate_dpo_init(vlib_main_t *vm)
static load_balance_path_t * replicate_multipath_next_hop_fixup(load_balance_path_t *nhs, dpo_proto_t drop_proto)
struct _unformat_input_t unformat_input_t
static u8 * replicate_format(index_t repi, replicate_format_flags_t flags, u32 indent, u8 *s)
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:241
vlib_combined_counter_main_t repm_counters
Definition: replicate_dpo.h:35
#define PREDICT_FALSE(x)
Definition: clib.h:97
u32 node_index
Node index.
Definition: node.h:441
#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:366
static uword replicate_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1131
#define pool_get_aligned(P, E, A)
Allocate an object E from a pool P (general version).
Definition: pool.h:169
void replicate_multipath_update(const dpo_id_t *dpo, load_balance_path_t *next_hops)
static const char *const replicate_mpls_nodes[]
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
u16 n_vectors
Definition: node.h:345
static_always_inline uword vlib_get_thread_index(void)
Definition: threads.h:185
static void vlib_get_combined_counter(const vlib_combined_counter_main_t *cm, u32 index, vlib_counter_t *result)
Get the value of a combined counter, never called in the speed path Scrapes the entire set of per-thr...
Definition: counter.h:250
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:340
vlib_node_registration_t ip4_replicate_node
IP4 replication node.
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:85
u8 * format_replicate(u8 *s, va_list *args)
static uword ip6_replicate(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
#define ARRAY_LEN(x)
Definition: clib.h:59
index_t replicate_create(u32 n_buckets, dpo_proto_t rep_proto)
vlib_node_registration_t mpls_replicate_node
MPLS replication node.
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
dpo_id_t rep_buckets_inline[REP_NUM_INLINE_BUCKETS]
The rest of the cache line is used for buckets.
Definition: replicate_dpo.h:86
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:460
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
int replicate_is_drop(const dpo_id_t *dpo)
static replicate_t * replicate_alloc_i(void)
Definition: replicate_dpo.c:84
u16 rep_n_buckets
number of buckets in the load-balance.
Definition: replicate_dpo.h:58
u8 * format_dpo_id(u8 *s, va_list *args)
Format a DPO_id_t oject
Definition: dpo.c:123
static void replicate_lock(dpo_id_t *dpo)
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
counter_t bytes
byte counter
Definition: counter.h:142
static u8 * format_replicate_dpo(u8 *s, va_list *args)
const dpo_id_t * replicate_get_bucket(index_t repi, u32 bucket)
Definition: defs.h:47
unsigned short u16
Definition: types.h:57
#define DPO_PROTO_NUM
Definition: dpo.h:73
static void replicate_set_n_buckets(replicate_t *rep, u32 n_buckets)
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:168
#define foreach_replicate_dpo_error
Definition: replicate_dpo.c:38
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
u32 path_weight
weight for the path.
Definition: load_balance.h:76
#define INDEX_INVALID
Invalid index - used when no index is known blazoned capitals INVALID speak volumes where ~0 does not...
Definition: dpo.h:47
#define REP_NUM_INLINE_BUCKETS
The number of buckets that a load-balance object can have and still fit in one cache-line.
Definition: replicate_dpo.h:47
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:269
replicate_main_t replicate_main
The one instance of replicate main.
Definition: replicate_dpo.c:62
static const dpo_id_t * replicate_get_bucket_i(const replicate_t *rep, u32 bucket)
One path from an [EU]CMP set that the client wants to add to a load-balance object.
Definition: load_balance.h:62
A collection of combined counters.
Definition: counter.h:180
#define vnet_buffer(b)
Definition: buffer.h:304
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:144
int dpo_is_drop(const dpo_id_t *dpo)
The Drop DPO will drop all packets, no questions asked.
Definition: drop_dpo.c:33
static u32 vlib_num_workers()
Definition: threads.h:332
vlib_node_registration_t ip6_replicate_node
IPv6 replication node.
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
Definition: dpo.c:205
#define vec_foreach(var, vec)
Vector iterator.
#define CLIB_MEMORY_BARRIER()
Definition: clib.h:101
u16 dpoi_next_node
The next VLIB node to follow.
Definition: dpo.h:164
struct replicate_trace_t_ replicate_trace_t
u32 flags
Definition: vhost-user.h:76
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:74
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:680
void replicate_module_init(void)
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 uword ip4_replicate(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
static uword mpls_replicate(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
void dpo_stack(dpo_type_t child_type, dpo_proto_t child_proto, dpo_id_t *dpo, const dpo_id_t *parent)
Stack one DPO object on another, and thus establish a child-parent relationship.
Definition: dpo.c:416
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:109