FD.io VPP  v18.10-32-g1161dda
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  */
62 replicate_main_t replicate_main = {
63  .repm_counters = {
64  .name = "mroutes",
65  .stat_segment_name = "/net/mroute",
66  },
67 };
68 
69 static inline index_t
71 {
72  return (rep - replicate_pool);
73 }
74 
75 static inline dpo_id_t*
77 {
78  if (REP_HAS_INLINE_BUCKETS(rep))
79  {
80  return (rep->rep_buckets_inline);
81  }
82  else
83  {
84  return (rep->rep_buckets);
85  }
86 }
87 
88 static replicate_t *
90 {
91  replicate_t *rep;
92 
93  pool_get_aligned(replicate_pool, rep, CLIB_CACHE_LINE_BYTES);
94  memset(rep, 0, sizeof(*rep));
95 
97  replicate_get_index(rep));
98  vlib_zero_combined_counter(&(replicate_main.repm_counters),
99  replicate_get_index(rep));
100 
101  return (rep);
102 }
103 
104 static u8*
107  u32 indent,
108  u8 *s)
109 {
110  vlib_counter_t to;
111  replicate_t *rep;
112  dpo_id_t *buckets;
113  u32 i;
114 
115  repi &= ~MPLS_IS_REPLICATE;
116  rep = replicate_get(repi);
117  vlib_get_combined_counter(&(replicate_main.repm_counters), repi, &to);
118  buckets = replicate_get_buckets(rep);
119 
120  s = format(s, "%U: ", format_dpo_type, DPO_REPLICATE);
121  s = format(s, "[index:%d buckets:%d ", repi, rep->rep_n_buckets);
122  s = format(s, "to:[%Ld:%Ld]]", to.packets, to.bytes);
123 
124  for (i = 0; i < rep->rep_n_buckets; i++)
125  {
126  s = format(s, "\n%U", format_white_space, indent+2);
127  s = format(s, "[%d]", i);
128  s = format(s, " %U", format_dpo_id, &buckets[i], indent+6);
129  }
130  return (s);
131 }
132 
133 u8*
134 format_replicate (u8 * s, va_list * args)
135 {
136  index_t repi = va_arg(*args, index_t);
138 
139  return (replicate_format(repi, flags, 0, s));
140 }
141 static u8*
142 format_replicate_dpo (u8 * s, va_list * args)
143 {
144  index_t repi = va_arg(*args, index_t);
145  u32 indent = va_arg(*args, u32);
146 
147  return (replicate_format(repi, REPLICATE_FORMAT_DETAIL, indent, s));
148 }
149 
150 
151 static replicate_t *
152 replicate_create_i (u32 num_buckets,
153  dpo_proto_t rep_proto)
154 {
155  replicate_t *rep;
156 
157  rep = replicate_alloc_i();
158  rep->rep_n_buckets = num_buckets;
159  rep->rep_proto = rep_proto;
160 
161  if (!REP_HAS_INLINE_BUCKETS(rep))
162  {
164  rep->rep_n_buckets - 1,
166  }
167 
168  REP_DBG(rep, "create");
169 
170  return (rep);
171 }
172 
173 index_t
175  dpo_proto_t rep_proto)
176 {
177  return (replicate_get_index(replicate_create_i(n_buckets, rep_proto)));
178 }
179 
180 static inline void
182  u32 bucket,
183  dpo_id_t *buckets,
184  const dpo_id_t *next)
185 {
186  dpo_stack(DPO_REPLICATE, rep->rep_proto, &buckets[bucket], next);
187 }
188 
189 void
191  u32 bucket,
192  const dpo_id_t *next)
193 {
194  replicate_t *rep;
195  dpo_id_t *buckets;
196 
197  repi &= ~MPLS_IS_REPLICATE;
198  rep = replicate_get(repi);
199  buckets = replicate_get_buckets(rep);
200 
201  ASSERT(bucket < rep->rep_n_buckets);
202 
203  replicate_set_bucket_i(rep, bucket, buckets, next);
204 }
205 
206 int
208 {
209  replicate_t *rep;
210  index_t repi;
211 
212  if (DPO_REPLICATE != dpo->dpoi_type)
213  return (0);
214 
215  repi = dpo->dpoi_index & ~MPLS_IS_REPLICATE;
216  rep = replicate_get(repi);
217 
218  if (1 == rep->rep_n_buckets)
219  {
220  return (dpo_is_drop(replicate_get_bucket_i(rep, 0)));
221  }
222  return (0);
223 }
224 
225 const dpo_id_t *
227  u32 bucket)
228 {
229  replicate_t *rep;
230 
231  repi &= ~MPLS_IS_REPLICATE;
232  rep = replicate_get(repi);
233 
234  return (replicate_get_bucket_i(rep, bucket));
235 }
236 
237 
238 static load_balance_path_t *
240  dpo_proto_t drop_proto)
241 {
242  if (0 == vec_len(nhs))
243  {
245 
246  /*
247  * we need something for the replicate. so use the drop
248  */
249  vec_add2(nhs, nh, 1);
250 
251  nh->path_weight = 1;
252  dpo_copy(&nh->path_dpo, drop_dpo_get(drop_proto));
253  }
254 
255  return (nhs);
256 }
257 
258 /*
259  * Fill in adjacencies in block based on corresponding
260  * next hop adjacencies.
261  */
262 static void
264  load_balance_path_t *nhs,
265  dpo_id_t *buckets,
266  u32 n_buckets)
267 {
268  load_balance_path_t * nh;
269  u16 bucket;
270 
271  bucket = 0;
272 
273  /*
274  * the next-hops have normalised weights. that means their sum is the number
275  * of buckets we need to fill.
276  */
277  vec_foreach (nh, nhs)
278  {
279  ASSERT(bucket < n_buckets);
280  replicate_set_bucket_i(rep, bucket++, buckets, &nh->path_dpo);
281  }
282 }
283 
284 static inline void
286  u32 n_buckets)
287 {
288  rep->rep_n_buckets = n_buckets;
289 }
290 
291 void
293  load_balance_path_t * next_hops)
294 {
295  load_balance_path_t * nh, * nhs;
296  dpo_id_t *tmp_dpo;
297  u32 ii, n_buckets;
298  replicate_t *rep;
299  index_t repi;
300 
301  ASSERT(DPO_REPLICATE == dpo->dpoi_type);
302  repi = dpo->dpoi_index & ~MPLS_IS_REPLICATE;
303  rep = replicate_get(repi);
304  nhs = replicate_multipath_next_hop_fixup(next_hops,
305  rep->rep_proto);
306  n_buckets = vec_len(nhs);
307 
308  if (0 == rep->rep_n_buckets)
309  {
310  /*
311  * first time initialisation. no packets inflight, so we can write
312  * at leisure.
313  */
314  replicate_set_n_buckets(rep, n_buckets);
315 
316  if (!REP_HAS_INLINE_BUCKETS(rep))
318  rep->rep_n_buckets - 1,
320 
321  replicate_fill_buckets(rep, nhs,
323  n_buckets);
324  }
325  else
326  {
327  /*
328  * This is a modification of an existing replicate.
329  * We need to ensure that packets in flight see a consistent state, that
330  * is the number of reported buckets the REP has
331  * is not more than it actually has. So if the
332  * number of buckets is increasing, we must update the bucket array first,
333  * then the reported number. vice-versa if the number of buckets goes down.
334  */
335  if (n_buckets == rep->rep_n_buckets)
336  {
337  /*
338  * no change in the number of buckets. we can simply fill what
339  * is new over what is old.
340  */
341  replicate_fill_buckets(rep, nhs,
343  n_buckets);
344  }
345  else if (n_buckets > rep->rep_n_buckets)
346  {
347  /*
348  * we have more buckets. the old replicate map (if there is one)
349  * will remain valid, i.e. mapping to indices within range, so we
350  * update it last.
351  */
352  if (n_buckets > REP_NUM_INLINE_BUCKETS &&
354  {
355  /*
356  * the new increased number of buckets is crossing the threshold
357  * from the inline storage to out-line. Alloc the outline buckets
358  * first, then fixup the number. then reset the inlines.
359  */
360  ASSERT(NULL == rep->rep_buckets);
362  n_buckets - 1,
364 
365  replicate_fill_buckets(rep, nhs,
366  rep->rep_buckets,
367  n_buckets);
369  replicate_set_n_buckets(rep, n_buckets);
370 
372 
373  for (ii = 0; ii < REP_NUM_INLINE_BUCKETS; ii++)
374  {
375  dpo_reset(&rep->rep_buckets_inline[ii]);
376  }
377  }
378  else
379  {
380  if (n_buckets <= REP_NUM_INLINE_BUCKETS)
381  {
382  /*
383  * we are not crossing the threshold and it's still inline buckets.
384  * we can write the new on the old..
385  */
386  replicate_fill_buckets(rep, nhs,
388  n_buckets);
390  replicate_set_n_buckets(rep, n_buckets);
391  }
392  else
393  {
394  /*
395  * we are not crossing the threshold. We need a new bucket array to
396  * hold the increased number of choices.
397  */
398  dpo_id_t *new_buckets, *old_buckets, *tmp_dpo;
399 
400  new_buckets = NULL;
401  old_buckets = replicate_get_buckets(rep);
402 
403  vec_validate_aligned(new_buckets,
404  n_buckets - 1,
406 
407  replicate_fill_buckets(rep, nhs, new_buckets, n_buckets);
409  rep->rep_buckets = new_buckets;
411  replicate_set_n_buckets(rep, n_buckets);
412 
413  vec_foreach(tmp_dpo, old_buckets)
414  {
415  dpo_reset(tmp_dpo);
416  }
417  vec_free(old_buckets);
418  }
419  }
420  }
421  else
422  {
423  /*
424  * bucket size shrinkage.
425  */
426  if (n_buckets <= REP_NUM_INLINE_BUCKETS &&
428  {
429  /*
430  * the new decreased number of buckets is crossing the threshold
431  * from out-line storage to inline:
432  * 1 - Fill the inline buckets,
433  * 2 - fixup the number (and this point the inline buckets are
434  * used).
435  * 3 - free the outline buckets
436  */
437  replicate_fill_buckets(rep, nhs,
438  rep->rep_buckets_inline,
439  n_buckets);
441  replicate_set_n_buckets(rep, n_buckets);
443 
444  vec_foreach(tmp_dpo, rep->rep_buckets)
445  {
446  dpo_reset(tmp_dpo);
447  }
448  vec_free(rep->rep_buckets);
449  }
450  else
451  {
452  /*
453  * not crossing the threshold.
454  * 1 - update the number to the smaller size
455  * 2 - write the new buckets
456  * 3 - reset those no longer used.
457  */
458  dpo_id_t *buckets;
459  u32 old_n_buckets;
460 
461  old_n_buckets = rep->rep_n_buckets;
462  buckets = replicate_get_buckets(rep);
463 
464  replicate_set_n_buckets(rep, n_buckets);
466 
467  replicate_fill_buckets(rep, nhs,
468  buckets,
469  n_buckets);
470 
471  for (ii = n_buckets; ii < old_n_buckets; ii++)
472  {
473  dpo_reset(&buckets[ii]);
474  }
475  }
476  }
477  }
478 
479  vec_foreach (nh, nhs)
480  {
481  dpo_reset(&nh->path_dpo);
482  }
483  vec_free(nhs);
484 }
485 
486 static void
488 {
489  replicate_t *rep;
490 
491  rep = replicate_get(dpo->dpoi_index);
492 
493  rep->rep_locks++;
494 }
495 
496 static void
498 {
499  dpo_id_t *buckets;
500  int i;
501 
502  buckets = replicate_get_buckets(rep);
503 
504  for (i = 0; i < rep->rep_n_buckets; i++)
505  {
506  dpo_reset(&buckets[i]);
507  }
508 
509  REP_DBG(rep, "destroy");
510  if (!REP_HAS_INLINE_BUCKETS(rep))
511  {
512  vec_free(rep->rep_buckets);
513  }
514 
515  pool_put(replicate_pool, rep);
516 }
517 
518 static void
520 {
521  replicate_t *rep;
522 
523  rep = replicate_get(dpo->dpoi_index);
524 
525  rep->rep_locks--;
526 
527  if (0 == rep->rep_locks)
528  {
529  replicate_destroy(rep);
530  }
531 }
532 
533 static void
535 {
536  fib_show_memory_usage("replicate",
537  pool_elts(replicate_pool),
538  pool_len(replicate_pool),
539  sizeof(replicate_t));
540 }
541 
542 const static dpo_vft_t rep_vft = {
544  .dv_unlock = replicate_unlock,
545  .dv_format = format_replicate_dpo,
546  .dv_mem_show = replicate_mem_show,
547 };
548 
549 /**
550  * @brief The per-protocol VLIB graph nodes that are assigned to a replicate
551  * object.
552  *
553  * this means that these graph nodes are ones from which a replicate is the
554  * parent object in the DPO-graph.
555  */
556 const static char* const replicate_ip4_nodes[] =
557 {
558  "ip4-replicate",
559  NULL,
560 };
561 const static char* const replicate_ip6_nodes[] =
562 {
563  "ip6-replicate",
564  NULL,
565 };
566 const static char* const replicate_mpls_nodes[] =
567 {
568  "mpls-replicate",
569  NULL,
570 };
571 
572 const static char* const * const replicate_nodes[DPO_PROTO_NUM] =
573 {
577 };
578 
579 void
581 {
583 }
584 
585 static clib_error_t *
587  unformat_input_t * input,
588  vlib_cli_command_t * cmd)
589 {
590  index_t repi = INDEX_INVALID;
591 
593  {
594  if (unformat (input, "%d", &repi))
595  ;
596  else
597  break;
598  }
599 
600  if (INDEX_INVALID != repi)
601  {
602  vlib_cli_output (vm, "%U", format_replicate, repi,
604  }
605  else
606  {
607  replicate_t *rep;
608 
609  pool_foreach(rep, replicate_pool,
610  ({
612  replicate_get_index(rep),
614  }));
615  }
616 
617  return 0;
618 }
619 
620 VLIB_CLI_COMMAND (replicate_show_command, static) = {
621  .path = "show replicate",
622  .short_help = "show replicate [<index>]",
623  .function = replicate_show,
624 };
625 
626 typedef struct replicate_trace_t_
627 {
631 
632 static uword
634  vlib_node_runtime_t * node,
635  vlib_frame_t * frame)
636 {
637  vlib_combined_counter_main_t * cm = &replicate_main.repm_counters;
639  u32 n_left_from, * from, * to_next, next_index;
640  u32 thread_index = vlib_get_thread_index();
641 
642  from = vlib_frame_vector_args (frame);
643  n_left_from = frame->n_vectors;
644  next_index = node->cached_next_index;
645 
646  while (n_left_from > 0)
647  {
648  u32 n_left_to_next;
649 
650  vlib_get_next_frame (vm, node, next_index,
651  to_next, n_left_to_next);
652 
653  while (n_left_from > 0 && n_left_to_next > 0)
654  {
655  u32 next0, ci0, bi0, bucket, repi0;
656  const replicate_t *rep0;
657  vlib_buffer_t * b0, *c0;
658  const dpo_id_t *dpo0;
659  u8 num_cloned;
660 
661  bi0 = from[0];
662  from += 1;
663  n_left_from -= 1;
664 
665  b0 = vlib_get_buffer (vm, bi0);
666  repi0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX];
667  rep0 = replicate_get(repi0);
668 
670  cm, thread_index, repi0, 1,
672 
673  vec_validate (rm->clones[thread_index], rep0->rep_n_buckets - 1);
674 
675  num_cloned = vlib_buffer_clone (vm, bi0, rm->clones[thread_index],
676  rep0->rep_n_buckets,
678 
679  if (num_cloned != rep0->rep_n_buckets)
680  {
682  (vm, node->node_index,
683  REPLICATE_DPO_ERROR_BUFFER_ALLOCATION_FAILURE, 1);
684  }
685 
686  for (bucket = 0; bucket < num_cloned; bucket++)
687  {
688  ci0 = rm->clones[thread_index][bucket];
689  c0 = vlib_get_buffer(vm, ci0);
690 
691  to_next[0] = ci0;
692  to_next += 1;
693  n_left_to_next -= 1;
694 
695  dpo0 = replicate_get_bucket_i(rep0, bucket);
696  next0 = dpo0->dpoi_next_node;
697  vnet_buffer (c0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
698 
699  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
700  {
702 
703  if (c0 != b0)
704  {
705  vlib_buffer_copy_trace_flag (vm, b0, ci0);
707  }
708  t = vlib_add_trace (vm, node, c0, sizeof (*t));
709  t->rep_index = repi0;
710  t->dpo = *dpo0;
711  }
712 
713  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
714  to_next, n_left_to_next,
715  ci0, next0);
716  if (PREDICT_FALSE (n_left_to_next == 0))
717  {
718  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
719  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
720  }
721  }
722  vec_reset_length (rm->clones[thread_index]);
723  }
724 
725  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
726  }
727 
728  return frame->n_vectors;
729 }
730 
731 static u8 *
732 format_replicate_trace (u8 * s, va_list * args)
733 {
734  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
735  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
736  replicate_trace_t *t = va_arg (*args, replicate_trace_t *);
737 
738  s = format (s, "replicate: %d via %U",
739  t->rep_index,
740  format_dpo_id, &t->dpo, 0);
741  return s;
742 }
743 
744 static uword
746  vlib_node_runtime_t * node,
747  vlib_frame_t * frame)
748 {
749  return (replicate_inline (vm, node, frame));
750 }
751 
752 /**
753  * @brief IP4 replication node
754  */
756  .function = ip4_replicate,
757  .name = "ip4-replicate",
758  .vector_size = sizeof (u32),
759 
761  .error_strings = replicate_dpo_error_strings,
762 
763  .format_trace = format_replicate_trace,
764  .n_next_nodes = 1,
765  .next_nodes = {
766  [0] = "ip4-drop",
767  },
768 };
769 
770 static uword
772  vlib_node_runtime_t * node,
773  vlib_frame_t * frame)
774 {
775  return (replicate_inline (vm, node, frame));
776 }
777 
778 /**
779  * @brief IPv6 replication node
780  */
782  .function = ip6_replicate,
783  .name = "ip6-replicate",
784  .vector_size = sizeof (u32),
785 
787  .error_strings = replicate_dpo_error_strings,
788 
789  .format_trace = format_replicate_trace,
790  .n_next_nodes = 1,
791  .next_nodes = {
792  [0] = "ip6-drop",
793  },
794 };
795 
796 static uword
798  vlib_node_runtime_t * node,
799  vlib_frame_t * frame)
800 {
801  return (replicate_inline (vm, node, frame));
802 }
803 
804 /**
805  * @brief MPLS replication node
806  */
808  .function = mpls_replicate,
809  .name = "mpls-replicate",
810  .vector_size = sizeof (u32),
811 
813  .error_strings = replicate_dpo_error_strings,
814 
815  .format_trace = format_replicate_trace,
816  .n_next_nodes = 1,
817  .next_nodes = {
818  [0] = "mpls-drop",
819  },
820 };
821 
822 clib_error_t *
824 {
826 
828 
829  return 0;
830 }
831 
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:437
dpo_lock_fn_t dv_lock
A reference counting lock function.
Definition: dpo.h:404
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:76
#define CLIB_UNUSED(x)
Definition: clib.h:81
A virtual function table regisitered for a DPO type.
Definition: dpo.h:399
void vlib_validate_combined_counter(vlib_combined_counter_main_t *cm, u32 index)
validate a combined counter
Definition: counter.c:106
#define VLIB_BUFFER_CLONE_HEAD_SIZE
Definition: buffer.h:60
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:204
static void replicate_unlock(dpo_id_t *dpo)
u8 * format_dpo_type(u8 *s, va_list *args)
format a DPO type
Definition: dpo.c:137
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:57
u32 rep_locks
The number of locks, which is approximately the number of users, of this load-balance.
Definition: replicate_dpo.h:79
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:261
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:71
Combined counter to hold both packets and byte differences.
Definition: counter_types.h:26
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:562
int i
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:84
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
Definition: vec.h:448
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:263
unsigned char u8
Definition: types.h:56
#define pool_len(p)
Number of elements in pool vector.
Definition: pool.h:140
#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)
memset(h->entries, 0, sizeof(h->entries[0])*entries)
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:321
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:443
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:163
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:66
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:220
static const char *const replicate_ip6_nodes[]
unsigned int u32
Definition: types.h:88
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:70
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:168
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:269
counter_t packets
packet counter
Definition: counter_types.h:28
dpo_type_t dpoi_type
the type
Definition: dpo.h:172
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
unsigned short u16
Definition: types.h:57
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:274
vlib_combined_counter_main_t repm_counters
Definition: replicate_dpo.h:35
#define PREDICT_FALSE(x)
Definition: clib.h:107
u32 node_index
Node index.
Definition: node.h:494
#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
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:1176
u32 flags
Definition: vhost_user.h:115
#define pool_get_aligned(P, E, A)
Allocate an object E from a pool P (general version).
Definition: pool.h:188
void replicate_multipath_update(const dpo_id_t *dpo, load_balance_path_t *next_hops)
static const char *const replicate_mpls_nodes[]
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:155
static void vlib_buffer_copy_trace_flag(vlib_main_t *vm, vlib_buffer_t *b, u32 bi_target)
Definition: trace_funcs.h:147
#define UNFORMAT_END_OF_INPUT
Definition: format.h:144
static u16 vlib_buffer_clone(vlib_main_t *vm, u32 src_buffer, u32 *buffers, u16 n_buffers, u16 head_end_offset)
Create multiple clones of buffer and store them in the supplied array.
Definition: buffer_funcs.h:879
u16 n_vectors
Definition: node.h:401
static_always_inline uword vlib_get_thread_index(void)
Definition: threads.h:211
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:243
vlib_main_t * vm
Definition: buffer.c:294
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:339
vlib_node_registration_t ip4_replicate_node
IP4 replication node.
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:61
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
Definition: main.c:455
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:155
dpo_id_t rep_buckets_inline[REP_NUM_INLINE_BUCKETS]
The rest of the cache line is used for buckets.
Definition: replicate_dpo.h:92
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:513
#define ASSERT(truth)
int replicate_is_drop(const dpo_id_t *dpo)
static replicate_t * replicate_alloc_i(void)
Definition: replicate_dpo.c:89
u16 rep_n_buckets
number of buckets in the replicate.
Definition: replicate_dpo.h:64
u8 * format_dpo_id(u8 *s, va_list *args)
Format a DPO_id_t oject
Definition: dpo.c:147
static void replicate_lock(dpo_id_t *dpo)
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace_funcs.h:57
counter_t bytes
byte counter
Definition: counter_types.h:29
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
#define DPO_PROTO_NUM
Definition: dpo.h:70
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:184
#define foreach_replicate_dpo_error
Definition: replicate_dpo.c:38
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
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 VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b)
Definition: buffer.h:547
u64 uword
Definition: types.h:112
#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:267
char * name
The counter collection&#39;s name.
Definition: counter.h:177
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:172
#define vnet_buffer(b)
Definition: buffer.h:344
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:365
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:231
#define vec_foreach(var, vec)
Vector iterator.
#define CLIB_MEMORY_BARRIER()
Definition: clib.h:111
u16 dpoi_next_node
The next VLIB node to follow.
Definition: dpo.h:180
struct replicate_trace_t_ replicate_trace_t
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:116
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:725
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:58
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:170
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:515
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128