FD.io VPP  v19.08.3-2-gbabecb413
Vector Packet Processing
adj_midchain.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/adj/adj_nbr.h>
17 #include <vnet/adj/adj_internal.h>
18 #include <vnet/adj/adj_l2.h>
19 #include <vnet/adj/adj_nsh.h>
20 #include <vnet/adj/adj_midchain.h>
22 #include <vnet/dpo/drop_dpo.h>
23 #include <vnet/dpo/load_balance.h>
24 #include <vnet/fib/fib_walk.h>
25 #include <vnet/fib/fib_entry.h>
26 
27 /**
28  * The two midchain tx feature node indices
29  */
32 
34 
35 /**
36  * @brief Trace data for packets traversing the midchain tx node
37  */
39 {
40  /**
41  * @brief the midchain adj we are traversing
42  */
45 
48  vlib_node_runtime_t * node,
49  vlib_frame_t * frame,
50  int interface_count)
51 {
52  u32 * from, * to_next, n_left_from, n_left_to_next;
53  u32 next_index;
54  vnet_main_t *vnm = vnet_get_main ();
56  u32 thread_index = vm->thread_index;
57 
58  /* Vector of buffer / pkt indices we're supposed to process */
59  from = vlib_frame_vector_args (frame);
60 
61  /* Number of buffers / pkts */
62  n_left_from = frame->n_vectors;
63 
64  /* Speculatively send the first buffer to the last disposition we used */
65  next_index = node->cached_next_index;
66 
67  while (n_left_from > 0)
68  {
69  /* set up to enqueue to our disposition with index = next_index */
70  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
71 
72  while (n_left_from >= 8 && n_left_to_next > 4)
73  {
74  const ip_adjacency_t *adj0, *adj1, *adj2, *adj3;
75  const dpo_id_t *dpo0, *dpo1, *dpo2, *dpo3;
76  vlib_buffer_t * b0, *b1, *b2, *b3;
77  u32 bi0, adj_index0, next0;
78  u32 bi1, adj_index1, next1;
79  u32 bi2, adj_index2, next2;
80  u32 bi3, adj_index3, next3;
81 
82  /* Prefetch next iteration. */
83  {
84  vlib_buffer_t * p4, * p5;
85  vlib_buffer_t * p6, * p7;
86 
87  p4 = vlib_get_buffer (vm, from[4]);
88  p5 = vlib_get_buffer (vm, from[5]);
89  p6 = vlib_get_buffer (vm, from[6]);
90  p7 = vlib_get_buffer (vm, from[7]);
91 
92  vlib_prefetch_buffer_header (p4, LOAD);
93  vlib_prefetch_buffer_header (p5, LOAD);
94  vlib_prefetch_buffer_header (p6, LOAD);
95  vlib_prefetch_buffer_header (p7, LOAD);
96  }
97 
98  bi0 = from[0];
99  to_next[0] = bi0;
100  bi1 = from[1];
101  to_next[1] = bi1;
102  bi2 = from[2];
103  to_next[2] = bi2;
104  bi3 = from[3];
105  to_next[3] = bi3;
106 
107  from += 4;
108  to_next += 4;
109  n_left_from -= 4;
110  n_left_to_next -= 4;
111 
112  b0 = vlib_get_buffer(vm, bi0);
113  b1 = vlib_get_buffer(vm, bi1);
114  b2 = vlib_get_buffer(vm, bi2);
115  b3 = vlib_get_buffer(vm, bi3);
116 
117  /* Follow the DPO on which the midchain is stacked */
118  adj_index0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
119  adj_index1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
120  adj_index2 = vnet_buffer(b2)->ip.adj_index[VLIB_TX];
121  adj_index3 = vnet_buffer(b3)->ip.adj_index[VLIB_TX];
122 
123  adj0 = adj_get(adj_index0);
124  adj1 = adj_get(adj_index1);
125  adj2 = adj_get(adj_index2);
126  adj3 = adj_get(adj_index3);
127 
128  dpo0 = &adj0->sub_type.midchain.next_dpo;
129  dpo1 = &adj1->sub_type.midchain.next_dpo;
130  dpo2 = &adj2->sub_type.midchain.next_dpo;
131  dpo3 = &adj3->sub_type.midchain.next_dpo;
132 
133  next0 = dpo0->dpoi_next_node;
134  next1 = dpo1->dpoi_next_node;
135  next2 = dpo2->dpoi_next_node;
136  next3 = dpo3->dpoi_next_node;
137 
138  vnet_buffer(b1)->ip.adj_index[VLIB_TX] = dpo1->dpoi_index;
139  vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
140  vnet_buffer(b2)->ip.adj_index[VLIB_TX] = dpo2->dpoi_index;
141  vnet_buffer(b3)->ip.adj_index[VLIB_TX] = dpo3->dpoi_index;
142 
143  if (interface_count)
144  {
147  thread_index,
148  adj0->rewrite_header.sw_if_index,
149  1,
150  vlib_buffer_length_in_chain (vm, b0));
153  thread_index,
154  adj1->rewrite_header.sw_if_index,
155  1,
156  vlib_buffer_length_in_chain (vm, b1));
159  thread_index,
160  adj2->rewrite_header.sw_if_index,
161  1,
162  vlib_buffer_length_in_chain (vm, b2));
165  thread_index,
166  adj3->rewrite_header.sw_if_index,
167  1,
168  vlib_buffer_length_in_chain (vm, b3));
169  }
170 
171  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
172  {
173  adj_midchain_tx_trace_t *tr = vlib_add_trace (vm, node,
174  b0, sizeof (*tr));
175  tr->ai = adj_index0;
176  }
177  if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
178  {
179  adj_midchain_tx_trace_t *tr = vlib_add_trace (vm, node,
180  b1, sizeof (*tr));
181  tr->ai = adj_index1;
182  }
183  if (PREDICT_FALSE(b2->flags & VLIB_BUFFER_IS_TRACED))
184  {
185  adj_midchain_tx_trace_t *tr = vlib_add_trace (vm, node,
186  b2, sizeof (*tr));
187  tr->ai = adj_index2;
188  }
189  if (PREDICT_FALSE(b3->flags & VLIB_BUFFER_IS_TRACED))
190  {
191  adj_midchain_tx_trace_t *tr = vlib_add_trace (vm, node,
192  b3, sizeof (*tr));
193  tr->ai = adj_index3;
194  }
195 
196  vlib_validate_buffer_enqueue_x4 (vm, node, next_index,
197  to_next, n_left_to_next,
198  bi0, bi1, bi2, bi3,
199  next0, next1, next2, next3);
200  }
201  while (n_left_from > 0 && n_left_to_next > 0)
202  {
203  u32 bi0, adj_index0, next0;
204  const ip_adjacency_t * adj0;
205  const dpo_id_t *dpo0;
206  vlib_buffer_t * b0;
207 
208  bi0 = from[0];
209  to_next[0] = bi0;
210  from += 1;
211  to_next += 1;
212  n_left_from -= 1;
213  n_left_to_next -= 1;
214 
215  b0 = vlib_get_buffer(vm, bi0);
216 
217  /* Follow the DPO on which the midchain is stacked */
218  adj_index0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
219  adj0 = adj_get(adj_index0);
220  dpo0 = &adj0->sub_type.midchain.next_dpo;
221  next0 = dpo0->dpoi_next_node;
222  vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
223 
224  if (interface_count)
225  {
228  thread_index,
229  adj0->rewrite_header.sw_if_index,
230  1,
231  vlib_buffer_length_in_chain (vm, b0));
232  }
233 
234  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
235  {
236  adj_midchain_tx_trace_t *tr = vlib_add_trace (vm, node,
237  b0, sizeof (*tr));
238  tr->ai = adj_index0;
239  }
240 
241  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
242  to_next, n_left_to_next,
243  bi0, next0);
244  }
245 
246  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
247  }
248 
249  return frame->n_vectors;
250 }
251 
252 static u8 *
253 format_adj_midchain_tx_trace (u8 * s, va_list * args)
254 {
255  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
256  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
257  adj_midchain_tx_trace_t *tr = va_arg (*args, adj_midchain_tx_trace_t*);
258 
259  s = format(s, "adj-midchain:[%d]:%U", tr->ai,
260  format_ip_adjacency, tr->ai,
262 
263  return (s);
264 }
265 
266 static uword
268  vlib_node_runtime_t * node,
269  vlib_frame_t * frame)
270 {
271  return (adj_midchain_tx_inline(vm, node, frame, 1));
272 }
273 
275  .function = adj_midchain_tx,
276  .name = "adj-midchain-tx",
277  .vector_size = sizeof (u32),
278 
279  .format_trace = format_adj_midchain_tx_trace,
280 
281  .n_next_nodes = 1,
282  .next_nodes = {
283  [0] = "error-drop",
284  },
285 };
286 
287 static uword
289  vlib_node_runtime_t * node,
290  vlib_frame_t * frame)
291 {
292  return (adj_midchain_tx_inline(vm, node, frame, 0));
293 }
294 
296  .function = adj_midchain_tx_no_count,
297  .name = "adj-midchain-tx-no-count",
298  .vector_size = sizeof (u32),
299 
300  .format_trace = format_adj_midchain_tx_trace,
301 
302  .n_next_nodes = 1,
303  .next_nodes = {
304  [0] = "error-drop",
305  },
306 };
307 
308 VNET_FEATURE_INIT (adj_midchain_tx_ip4, static) = {
309  .arc_name = "ip4-output",
310  .node_name = "adj-midchain-tx",
311  .runs_before = VNET_FEATURES ("interface-output"),
312  .feature_index_ptr = &adj_midchain_tx_feature_node[VNET_LINK_IP4],
313 };
314 VNET_FEATURE_INIT (adj_midchain_tx_no_count_ip4, static) = {
315  .arc_name = "ip4-output",
316  .node_name = "adj-midchain-tx-no-count",
317  .runs_before = VNET_FEATURES ("interface-output"),
319 };
320 VNET_FEATURE_INIT (adj_midchain_tx_ip6, static) = {
321  .arc_name = "ip6-output",
322  .node_name = "adj-midchain-tx",
323  .runs_before = VNET_FEATURES ("interface-output"),
324  .feature_index_ptr = &adj_midchain_tx_feature_node[VNET_LINK_IP6],
325 };
326 VNET_FEATURE_INIT (adj_midchain_tx_no_count_ip6, static) = {
327  .arc_name = "ip6-output",
328  .node_name = "adj-midchain-tx-no-count",
329  .runs_before = VNET_FEATURES ("interface-output"),
331 };
332 VNET_FEATURE_INIT (adj_midchain_tx_mpls, static) = {
333  .arc_name = "mpls-output",
334  .node_name = "adj-midchain-tx",
335  .runs_before = VNET_FEATURES ("interface-output"),
336  .feature_index_ptr = &adj_midchain_tx_feature_node[VNET_LINK_MPLS],
337 };
338 VNET_FEATURE_INIT (adj_midchain_tx_no_count_mpls, static) = {
339  .arc_name = "mpls-output",
340  .node_name = "adj-midchain-tx-no-count",
341  .runs_before = VNET_FEATURES ("interface-output"),
343 };
344 VNET_FEATURE_INIT (adj_midchain_tx_ethernet, static) = {
345  .arc_name = "ethernet-output",
346  .node_name = "adj-midchain-tx",
347  .runs_before = VNET_FEATURES ("error-drop"),
348  .feature_index_ptr = &adj_midchain_tx_feature_node[VNET_LINK_ETHERNET],
349 };
350 VNET_FEATURE_INIT (adj_midchain_tx_no_count_ethernet, static) = {
351  .arc_name = "ethernet-output",
352  .node_name = "adj-midchain-tx-no-count",
353  .runs_before = VNET_FEATURES ("error-drop"),
355 };
356 VNET_FEATURE_INIT (adj_midchain_tx_nsh, static) = {
357  .arc_name = "nsh-output",
358  .node_name = "adj-midchain-tx",
359  .runs_before = VNET_FEATURES ("error-drop"),
360  .feature_index_ptr = &adj_midchain_tx_feature_node[VNET_LINK_NSH],
361 };
362 VNET_FEATURE_INIT (adj_midchain_tx_no_count_nsh, static) = {
363  .arc_name = "nsh-output",
364  .node_name = "adj-midchain-tx-no-count",
365  .runs_before = VNET_FEATURES ("error-drop"),
367 };
368 
369 static inline u32
371 {
372  switch (link) {
373  case VNET_LINK_IP4:
374  return (ip4_midchain_node.index);
375  case VNET_LINK_IP6:
376  return (ip6_midchain_node.index);
377  case VNET_LINK_MPLS:
378  return (mpls_midchain_node.index);
379  case VNET_LINK_ETHERNET:
380  return (adj_l2_midchain_node.index);
381  case VNET_LINK_NSH:
382  return (adj_nsh_midchain_node.index);
383  case VNET_LINK_ARP:
384  break;
385  }
386  ASSERT(0);
387  return (0);
388 }
389 
390 static u8
392 {
393  u8 arc = (u8) ~0;
394  switch (adj->ia_link)
395  {
396  case VNET_LINK_IP4:
397  {
399  break;
400  }
401  case VNET_LINK_IP6:
402  {
404  break;
405  }
406  case VNET_LINK_MPLS:
407  {
409  break;
410  }
411  case VNET_LINK_ETHERNET:
412  {
414  break;
415  }
416  case VNET_LINK_NSH:
417  {
418  arc = nsh_main_dummy.output_feature_arc_index;
419  break;
420  }
421  case VNET_LINK_ARP:
422  ASSERT(0);
423  break;
424  }
425 
426  ASSERT (arc != (u8) ~0);
427 
428  return (arc);
429 }
430 
431 static u32
433 {
434  return ((adj->ia_flags & ADJ_FLAG_MIDCHAIN_NO_COUNT) ?
436  adj_midchain_tx_node.index);
437 }
438 
439 static u32
441 {
443  {
445  }
446 
447  return (adj_midchain_tx_feature_node[adj->ia_link]);
448 }
449 
450 /**
451  * adj_midchain_setup
452  *
453  * Setup the adj as a mid-chain
454  */
455 void
457 {
458  u32 feature_index;
459  u8 arc_index;
460 
461  dpo_reset(&adj->sub_type.midchain.next_dpo);
462 
464  feature_index = adj_nbr_midchain_get_feature_node(adj);
465 
466  if (0 == --adj_midchain_feat_count_per_sw_if_index[adj->ia_link][adj->rewrite_header.sw_if_index])
467  {
468  vnet_feature_enable_disable_with_index (arc_index, feature_index,
469  adj->rewrite_header.sw_if_index,
470  0, 0, 0);
471  }
472 }
473 
474 /**
475  * adj_midchain_setup
476  *
477  * Setup the adj as a mid-chain
478  */
479 void
481  adj_midchain_fixup_t fixup,
482  const void *data,
484 {
485  u32 feature_index, tx_node;
486  ip_adjacency_t *adj;
487  u8 arc_index;
488 
489  ASSERT(ADJ_INDEX_INVALID != adj_index);
490 
491  adj = adj_get(adj_index);
492 
493  adj->sub_type.midchain.fixup_func = fixup;
494  adj->sub_type.midchain.fixup_data = data;
496  adj->ia_flags |= flags;
497 
499  feature_index = adj_nbr_midchain_get_feature_node(adj);
500  tx_node = adj_nbr_midchain_get_tx_node(adj);
501 
503  adj->rewrite_header.sw_if_index);
504 
505  if (0 == adj_midchain_feat_count_per_sw_if_index[adj->ia_link][adj->rewrite_header.sw_if_index]++)
506  {
507  vnet_feature_enable_disable_with_index (arc_index, feature_index,
508  adj->rewrite_header.sw_if_index,
509  1 /* enable */, 0, 0);
510  }
511 
512  /*
513  * stack the midchain on the drop so it's ready to forward in the adj-midchain-tx.
514  * The graph arc used/created here is from the midchain-tx node to the
515  * child's registered node. This is because post adj processing the next
516  * node are any output features, then the midchain-tx. from there we
517  * need to get to the stacked child's node.
518  */
519  dpo_stack_from_node(tx_node,
520  &adj->sub_type.midchain.next_dpo,
522 }
523 
524 /**
525  * adj_nbr_midchain_update_rewrite
526  *
527  * Update the adjacency's rewrite string. A NULL string implies the
528  * rewrite is reset (i.e. when ARP/ND entry is gone).
529  * NB: the adj being updated may be handling traffic in the DP.
530  */
531 void
533  adj_midchain_fixup_t fixup,
534  const void *fixup_data,
536  u8 *rewrite)
537 {
538  ip_adjacency_t *adj;
539 
540  ASSERT(ADJ_INDEX_INVALID != adj_index);
541 
542  adj = adj_get(adj_index);
543 
544  /*
545  * one time only update. since we don't support changing the tunnel
546  * src,dst, this is all we need.
547  */
552 
553  adj_midchain_setup(adj_index, fixup, fixup_data, flags);
554 
555  /*
556  * update the rewrite with the workers paused.
557  */
562  rewrite);
563 }
564 
565 /**
566  * adj_nbr_midchain_unstack
567  *
568  * Unstack the adj. stack it on drop
569  */
570 void
572 {
573  fib_node_index_t *entry_indicies, tmp;
574  ip_adjacency_t *adj;
575 
576  ASSERT(ADJ_INDEX_INVALID != adj_index);
577  adj = adj_get (adj_index);
578 
579  /*
580  * check to see if this unstacking breaks a recursion loop
581  */
582  entry_indicies = NULL;
583  tmp = adj->sub_type.midchain.fei;
585 
586  if (FIB_NODE_INDEX_INVALID != tmp)
587  {
588  fib_entry_recursive_loop_detect(tmp, &entry_indicies);
589  vec_free(entry_indicies);
590  }
591 
592  /*
593  * stack on the drop
594  */
597  &adj->sub_type.midchain.next_dpo,
600 }
601 
602 void
604  fib_node_index_t fei,
606 {
607  fib_node_index_t *entry_indicies;
608  dpo_id_t tmp = DPO_INVALID;
609  ip_adjacency_t *adj;
610 
611  adj = adj_get (ai);
612 
613  /*
614  * check to see if this stacking will form a recursion loop
615  */
616  entry_indicies = NULL;
617  adj->sub_type.midchain.fei = fei;
618 
619  if (fib_entry_recursive_loop_detect(adj->sub_type.midchain.fei, &entry_indicies))
620  {
621  /*
622  * loop formed, stack on the drop.
623  */
625  }
626  else
627  {
628  fib_entry_contribute_forwarding (fei, fct, &tmp);
629 
630  if ((adj->ia_flags & ADJ_FLAG_MIDCHAIN_IP_STACK) &&
631  (DPO_LOAD_BALANCE == tmp.dpoi_type))
632  {
633  /*
634  * do that hash now and stack on the choice.
635  * If the choice is an incomplete adj then we will need a poke when
636  * it becomes complete. This happens since the adj update walk propagates
637  * as far a recursive paths.
638  */
639  const dpo_id_t *choice;
640  load_balance_t *lb;
641  int hash;
642 
643  lb = load_balance_get (tmp.dpoi_index);
644 
646  {
648  lb->lb_hash_config);
649  }
650  else if (FIB_FORW_CHAIN_TYPE_UNICAST_IP6 == fct)
651  {
653  lb->lb_hash_config);
654  }
655  else
656  {
657  hash = 0;
658  ASSERT(0);
659  }
660 
661  choice = load_balance_get_bucket_i (lb, hash & lb->lb_n_buckets_minus_1);
662  dpo_copy (&tmp, choice);
663  }
664  }
665  adj_nbr_midchain_stack (ai, &tmp);
666  dpo_reset(&tmp);
667  vec_free(entry_indicies);
668 }
669 
670 /**
671  * adj_nbr_midchain_stack
672  */
673 void
675  const dpo_id_t *next)
676 {
677  ip_adjacency_t *adj;
678 
679  ASSERT(ADJ_INDEX_INVALID != adj_index);
680 
681  adj = adj_get(adj_index);
682 
685 
687  &adj->sub_type.midchain.next_dpo,
688  next);
689 }
690 
691 int
693  fib_node_index_t **entry_indicies)
694 {
695  fib_node_index_t *entry_index, *entries;
696  ip_adjacency_t * adj;
697 
698  adj = adj_get(ai);
699  entries = *entry_indicies;
700 
701  vec_foreach(entry_index, entries)
702  {
703  if (*entry_index == adj->sub_type.midchain.fei)
704  {
705  /*
706  * The entry this midchain links to is already in the set
707  * of visited entries, this is a loop
708  */
710  return (1);
711  }
712  }
713 
715  return (0);
716 }
717 
718 u8*
719 format_adj_midchain (u8* s, va_list *ap)
720 {
721  index_t index = va_arg(*ap, index_t);
722  u32 indent = va_arg(*ap, u32);
723  ip_adjacency_t * adj = adj_get(index);
724 
725  s = format (s, "%U", format_vnet_link, adj->ia_link);
726  if (adj->rewrite_header.flags & VNET_REWRITE_HAS_FEATURES)
727  s = format(s, " [features]");
728  s = format (s, " via %U",
729  format_ip46_address, &adj->sub_type.nbr.next_hop,
731  s = format (s, " %U",
733  &adj->rewrite_header, sizeof (adj->rewrite_data), indent);
734  s = format (s, "\n%Ustacked-on",
735  format_white_space, indent);
736 
737  if (FIB_NODE_INDEX_INVALID != adj->sub_type.midchain.fei)
738  {
739  s = format (s, " entry:%d", adj->sub_type.midchain.fei);
740 
741  }
742  s = format (s, ":\n%U%U",
743  format_white_space, indent+2,
744  format_dpo_id, &adj->sub_type.midchain.next_dpo, indent+2);
745 
746  return (s);
747 }
748 
749 static void
751 {
752  adj_lock(dpo->dpoi_index);
753 }
754 static void
756 {
757  adj_unlock(dpo->dpoi_index);
758 }
759 
760 const static dpo_vft_t adj_midchain_dpo_vft = {
762  .dv_unlock = adj_dpo_unlock,
763  .dv_format = format_adj_midchain,
764  .dv_get_urpf = adj_dpo_get_urpf,
765 };
766 
767 /**
768  * @brief The per-protocol VLIB graph nodes that are assigned to a midchain
769  * object.
770  *
771  * this means that these graph nodes are ones from which a midchain is the
772  * parent object in the DPO-graph.
773  */
774 const static char* const midchain_ip4_nodes[] =
775 {
776  "ip4-midchain",
777  NULL,
778 };
779 const static char* const midchain_ip6_nodes[] =
780 {
781  "ip6-midchain",
782  NULL,
783 };
784 const static char* const midchain_mpls_nodes[] =
785 {
786  "mpls-midchain",
787  NULL,
788 };
789 const static char* const midchain_ethernet_nodes[] =
790 {
791  "adj-l2-midchain",
792  NULL,
793 };
794 const static char* const midchain_nsh_nodes[] =
795 {
796  "adj-nsh-midchain",
797  NULL,
798 };
799 
800 const static char* const * const midchain_nodes[DPO_PROTO_NUM] =
801 {
807 };
808 
809 void
811 {
812  dpo_register(DPO_ADJACENCY_MIDCHAIN, &adj_midchain_dpo_vft, midchain_nodes);
813 }
static uword adj_midchain_tx(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: adj_midchain.c:267
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:439
static const char *const midchain_nsh_nodes[]
Definition: adj_midchain.c:794
static const char *const midchain_ip6_nodes[]
Definition: adj_midchain.c:779
void dpo_stack_from_node(u32 child_node_index, 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:531
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:124
dpo_lock_fn_t dv_lock
A reference counting lock function.
Definition: dpo.h:406
#define VNET_LINK_NUM
Number of link types.
Definition: interface.h:353
static u32 adj_midchain_tx_no_count_feature_node[VNET_LINK_NUM]
Definition: adj_midchain.c:31
adj_flags_t ia_flags
Flags on the adjacency 1-bytes.
Definition: adj.h:255
Contribute an object that is to be used to forward IP6 packets.
Definition: fib_types.h:113
vlib_node_registration_t ip6_midchain_node
(constructor) VLIB_REGISTER_NODE (ip6_midchain_node)
Definition: ip6_forward.c:2214
u32 flags
Definition: vhost_user.h:141
#define CLIB_UNUSED(x)
Definition: clib.h:83
A virtual function table regisitered for a DPO type.
Definition: dpo.h:401
static vlib_node_registration_t adj_midchain_tx_node
(constructor) VLIB_REGISTER_NODE (adj_midchain_tx_node)
Definition: adj_midchain.c:274
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:220
void adj_lock(adj_index_t adj_index)
Take a reference counting lock on the adjacency.
Definition: adj.c:330
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
static uword adj_midchain_tx_no_count(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: adj_midchain.c:288
vnet_interface_main_t interface_main
Definition: vnet.h:56
static const char *const midchain_ip4_nodes[]
The per-protocol VLIB graph nodes that are assigned to a midchain object.
Definition: adj_midchain.c:774
const u8 * adj_get_rewrite(adj_index_t ai)
Return the rewrite string of the adjacency.
Definition: adj.c:533
Multicast Adjacency.
Definition: adj.h:82
static u32 ip4_compute_flow_hash(const ip4_header_t *ip, flow_hash_config_t flow_hash_config)
Definition: ip4.h:312
Broadcasr Adjacency.
Definition: adj.h:85
IP unicast adjacency.
Definition: adj.h:221
void fib_entry_contribute_forwarding(fib_node_index_t fib_entry_index, fib_forward_chain_type_t fct, dpo_id_t *dpo)
Definition: fib_entry.c:448
flow_hash_config_t lb_hash_config
the hash config to use when selecting a bucket.
Definition: load_balance.h:161
vlib_node_registration_t ip4_midchain_node
(constructor) VLIB_REGISTER_NODE (ip4_midchain_node)
Definition: ip4_forward.c:2812
u32 thread_index
Definition: main.h:218
dpo_proto_t fib_forw_chain_type_to_dpo_proto(fib_forward_chain_type_t fct)
Convert from a chain type to the DPO proto it will install.
Definition: fib_types.c:420
void dpo_copy(dpo_id_t *dst, const dpo_id_t *src)
atomic copy a data-plane object.
Definition: dpo.c:262
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
#define vlib_validate_buffer_enqueue_x4(vm, node, next_index, to_next, n_left_to_next, bi0, bi1, bi2, bi3, next0, next1, next2, next3)
Finish enqueueing four buffers forward in the graph.
Definition: buffer_node.h:138
format_function_t format_ip46_address
Definition: format.h:61
Contribute an object that is to be used to forward IP4 packets.
Definition: fib_types.h:109
ip_lookup_main_t lookup_main
Definition: ip4.h:107
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
u8 data[128]
Definition: ipsec.api:251
void adj_nbr_update_rewrite_internal(ip_adjacency_t *adj, ip_lookup_next_t adj_next_index, u32 complete_next_index, u32 next_index, u8 *rewrite)
adj_nbr_update_rewrite_internal
Definition: adj_nbr.c:340
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:366
u32 adj_dpo_get_urpf(const dpo_id_t *dpo)
Definition: adj.c:320
unsigned char u8
Definition: types.h:56
vnet_link_t ia_link
link/ether-type 1 bytes
Definition: adj.h:242
union ip_adjacency_t_::@48 sub_type
const dpo_id_t * drop_dpo_get(dpo_proto_t proto)
Definition: drop_dpo.c:25
u8 output_feature_arc_index
Definition: lookup.h:164
ethernet_main_t ethernet_main
Definition: init.c:45
static ip_adjacency_t * adj_get(adj_index_t adj_index)
Get a pointer to an adjacency object from its index.
Definition: adj.h:433
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:322
vlib_node_registration_t adj_nsh_midchain_node
(constructor) VLIB_REGISTER_NODE (adj_nsh_midchain_node)
Definition: adj_nsh.c:180
dpo_proto_t vnet_link_to_dpo_proto(vnet_link_t linkt)
Definition: dpo.c:96
format_function_t format_ip_adjacency
Definition: format.h:58
#define always_inline
Definition: clib.h:99
u16 lb_n_buckets_minus_1
number of buckets in the load-balance - 1.
Definition: load_balance.h:121
vlib_combined_counter_main_t * combined_sw_if_counters
Definition: interface.h:846
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:129
int vnet_feature_enable_disable_with_index(u8 arc_index, u32 feature_index, u32 sw_if_index, int enable_disable, void *feature_config, u32 n_feature_config_bytes)
Definition: feature.c:223
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:203
static const char *const *const midchain_nodes[DPO_PROTO_NUM]
Definition: adj_midchain.c:800
void adj_nbr_midchain_stack_on_fib_entry(adj_index_t ai, fib_node_index_t fei, fib_forward_chain_type_t fct)
[re]stack a midchain.
Definition: adj_midchain.c:603
u8 output_feature_arc_index
Definition: ethernet.h:296
void adj_unlock(adj_index_t adj_index)
Release a reference counting lock on the adjacency.
Definition: adj.c:347
vlib_node_registration_t mpls_midchain_node
(constructor) VLIB_REGISTER_NODE (mpls_midchain_node)
Definition: mpls_output.c:389
unsigned int u32
Definition: types.h:88
struct ip_adjacency_t_::@48::@50 midchain
IP_LOOKUP_NEXT_MIDCHAIN.
format_function_t format_vnet_rewrite
Definition: rewrite.h:250
static uword adj_midchain_tx_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, int interface_count)
Definition: adj_midchain.c:47
u8 output_feature_arc_index
Definition: mpls.h:57
vlib_node_registration_t adj_l2_midchain_node
(constructor) VLIB_REGISTER_NODE (adj_l2_midchain_node)
Definition: adj_l2.c:181
static const char *const midchain_mpls_nodes[]
Definition: adj_midchain.c:784
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:170
#define ADJ_INDEX_INVALID
Invalid ADJ index - used when no adj is known likewise blazoned capitals INVALID speak volumes where ...
Definition: adj_types.h:36
static u32 adj_get_midchain_node(vnet_link_t link)
Definition: adj_midchain.c:370
dpo_type_t dpoi_type
the type
Definition: dpo.h:174
static const dpo_id_t * load_balance_get_bucket_i(const load_balance_t *lb, u32 bucket)
Definition: load_balance.h:229
Trace data for packets traversing the midchain tx node.
Definition: adj_midchain.c:38
void adj_midchain_module_init(void)
Module initialisation.
Definition: adj_midchain.c:810
int adj_ndr_midchain_recursive_loop_detect(adj_index_t ai, fib_node_index_t **entry_indicies)
descend the FIB graph looking for loops
Definition: adj_midchain.c:692
adj_index_t ai
the midchain adj we are traversing
Definition: adj_midchain.c:43
load-balancing over a choice of [un]equal cost paths
Definition: dpo.h:102
static u32 ip6_compute_flow_hash(const ip6_header_t *ip, flow_hash_config_t flow_hash_config)
Definition: ip6.h:483
The FIB DPO provieds;.
Definition: load_balance.h:106
#define PREDICT_FALSE(x)
Definition: clib.h:112
This packet matches an "interface route" and packets need to be passed to ARP to find rewrite string ...
Definition: adj.h:68
static u8 adj_midchain_get_feature_arc_index_for_link_type(const ip_adjacency_t *adj)
Definition: adj_midchain.c:391
static vlib_node_registration_t adj_midchain_tx_no_count_node
(constructor) VLIB_REGISTER_NODE (adj_midchain_tx_no_count_node)
Definition: adj_midchain.c:295
#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:338
struct ip_adjacency_t_::@48::@49 nbr
IP_LOOKUP_NEXT_ARP/IP_LOOKUP_NEXT_REWRITE.
This packet matches an "incomplete adjacency" and packets need to be passed to ARP to find rewrite st...
Definition: adj.h:63
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
u16 n_vectors
Definition: node.h:397
mpls_main_t mpls_main
Definition: mpls.c:25
vlib_main_t * vm
Definition: buffer.c:323
static void adj_dpo_unlock(dpo_id_t *dpo)
Definition: adj_midchain.c:755
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:341
Multicast Midchain Adjacency.
Definition: adj.h:89
static u8 * format_adj_midchain_tx_trace(u8 *s, va_list *args)
Definition: adj_midchain.c:253
void adj_nbr_midchain_update_rewrite(adj_index_t adj_index, adj_midchain_fixup_t fixup, const void *fixup_data, adj_flags_t flags, u8 *rewrite)
adj_nbr_midchain_update_rewrite
Definition: adj_midchain.c:532
int fib_entry_recursive_loop_detect(fib_node_index_t entry_index, fib_node_index_t **entry_indicies)
Definition: fib_entry.c:1415
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:30
void(* adj_midchain_fixup_t)(vlib_main_t *vm, struct ip_adjacency_t_ *adj, vlib_buffer_t *b0, const void *data)
A function type for post-rewrite fixups on midchain adjacency.
Definition: adj.h:152
void adj_midchain_teardown(ip_adjacency_t *adj)
adj_midchain_setup
Definition: adj_midchain.c:456
u32 adj_index_t
An index for adjacencies.
Definition: adj_types.h:30
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:456
u8 * format_adj_midchain(u8 *s, va_list *ap)
Format a midchain adjacency.
Definition: adj_midchain.c:719
This packets follow a mid-chain adjacency.
Definition: adj.h:76
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:515
static u32 adj_nbr_midchain_get_tx_node(ip_adjacency_t *adj)
Definition: adj_midchain.c:432
#define ASSERT(truth)
void adj_nbr_midchain_stack(adj_index_t adj_index, const dpo_id_t *next)
adj_nbr_midchain_stack
Definition: adj_midchain.c:674
ip6_main_t ip6_main
Definition: ip6_forward.c:2805
ip_lookup_main_t lookup_main
Definition: ip6.h:179
enum vnet_link_t_ vnet_link_t
Link Type: A description of the protocol of packets on the link.
static load_balance_t * load_balance_get(index_t lbi)
Definition: load_balance.h:220
enum fib_forward_chain_type_t_ fib_forward_chain_type_t
FIB output chain type.
void adj_nbr_midchain_unstack(adj_index_t adj_index)
adj_nbr_midchain_unstack
Definition: adj_midchain.c:571
u8 * format_dpo_id(u8 *s, va_list *args)
Format a DPO_id_t oject
Definition: dpo.c:148
#define VNET_FEATURES(...)
Definition: feature.h:442
u32 entries
static void adj_dpo_lock(dpo_id_t *dpo)
Definition: adj_midchain.c:750
enum adj_flags_t_ adj_flags_t
Flags on an IP adjacency.
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
fib_protocol_t ia_nh_proto
The protocol of the neighbor/peer.
Definition: adj.h:249
Definition: defs.h:47
#define DPO_PROTO_NUM
Definition: dpo.h:70
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:186
#define FIB_NODE_INDEX_INVALID
Definition: fib_types.h:31
ip_lookup_next_t lookup_next_index
Next hop after ip4-lookup.
Definition: adj.h:236
void adj_midchain_setup(adj_index_t adj_index, adj_midchain_fixup_t fixup, const void *data, adj_flags_t flags)
adj_midchain_setup
Definition: adj_midchain.c:480
VLIB buffer representation.
Definition: buffer.h:102
nsh_main_dummy_t nsh_main_dummy
Definition: adj_nsh.c:21
u64 uword
Definition: types.h:112
struct adj_midchain_tx_trace_t_ adj_midchain_tx_trace_t
Trace data for packets traversing the midchain tx node.
static u32 adj_midchain_tx_feature_node[VNET_LINK_NUM]
The two midchain tx feature node indices.
Definition: adj_midchain.c:30
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:244
#define DPO_INVALID
An initialiser for DPOs declared on the stack.
Definition: dpo.h:197
#define vnet_buffer(b)
Definition: buffer.h:365
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1076
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
Definition: dpo.c:232
#define vec_foreach(var, vec)
Vector iterator.
#define CLIB_MEMORY_BARRIER()
Definition: clib.h:116
u8 * format_vnet_link(u8 *s, va_list *ap)
Definition: fib_types.c:41
u16 dpoi_next_node
The next VLIB node to follow.
Definition: dpo.h:182
This adjacency/interface has output features configured.
Definition: rewrite.h:57
static const char *const midchain_ethernet_nodes[]
Definition: adj_midchain.c:789
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:85
VNET_FEATURE_INIT(adj_midchain_tx_ip4, static)
static u32 * adj_midchain_feat_count_per_sw_if_index[VNET_LINK_NUM]
Definition: adj_midchain.c:33
static u32 adj_nbr_midchain_get_feature_node(ip_adjacency_t *adj)
Definition: adj_midchain.c:440
static ip46_type_t adj_proto_to_46(fib_protocol_t proto)
Definition: adj_internal.h:82
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:516