FD.io VPP  v19.01.3-6-g70449b9b9
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 
33 /**
34  * @brief Trace data for packets traversing the midchain tx node
35  */
37 {
38  /**
39  * @brief the midchain adj we are traversing
40  */
43 
46  vlib_node_runtime_t * node,
47  vlib_frame_t * frame,
48  int interface_count)
49 {
50  u32 * from, * to_next, n_left_from, n_left_to_next;
51  u32 next_index;
52  vnet_main_t *vnm = vnet_get_main ();
54  u32 thread_index = vm->thread_index;
55 
56  /* Vector of buffer / pkt indices we're supposed to process */
57  from = vlib_frame_vector_args (frame);
58 
59  /* Number of buffers / pkts */
60  n_left_from = frame->n_vectors;
61 
62  /* Speculatively send the first buffer to the last disposition we used */
63  next_index = node->cached_next_index;
64 
65  while (n_left_from > 0)
66  {
67  /* set up to enqueue to our disposition with index = next_index */
68  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
69 
70  while (n_left_from >= 8 && n_left_to_next > 4)
71  {
72  u32 bi0, adj_index0, next0;
73  const ip_adjacency_t * adj0;
74  const dpo_id_t *dpo0;
75  vlib_buffer_t * b0;
76  u32 bi1, adj_index1, next1;
77  const ip_adjacency_t * adj1;
78  const dpo_id_t *dpo1;
79  vlib_buffer_t * b1;
80  u32 bi2, adj_index2, next2;
81  const ip_adjacency_t * adj2;
82  const dpo_id_t *dpo2;
83  vlib_buffer_t * b2;
84  u32 bi3, adj_index3, next3;
85  const ip_adjacency_t * adj3;
86  const dpo_id_t *dpo3;
87  vlib_buffer_t * b3;
88 
89  /* Prefetch next iteration. */
90  {
91  vlib_buffer_t * p4, * p5;
92  vlib_buffer_t * p6, * p7;
93 
94  p4 = vlib_get_buffer (vm, from[4]);
95  p5 = vlib_get_buffer (vm, from[5]);
96  p6 = vlib_get_buffer (vm, from[6]);
97  p7 = vlib_get_buffer (vm, from[7]);
98 
99  vlib_prefetch_buffer_header (p4, LOAD);
100  vlib_prefetch_buffer_header (p5, LOAD);
101  vlib_prefetch_buffer_header (p6, LOAD);
102  vlib_prefetch_buffer_header (p7, LOAD);
103  }
104 
105  bi0 = from[0];
106  to_next[0] = bi0;
107  bi1 = from[1];
108  to_next[1] = bi1;
109  bi2 = from[2];
110  to_next[2] = bi2;
111  bi3 = from[3];
112  to_next[3] = bi3;
113 
114  from += 4;
115  to_next += 4;
116  n_left_from -= 4;
117  n_left_to_next -= 4;
118 
119  b0 = vlib_get_buffer(vm, bi0);
120  b1 = vlib_get_buffer(vm, bi1);
121  b2 = vlib_get_buffer(vm, bi2);
122  b3 = vlib_get_buffer(vm, bi3);
123 
124  /* Follow the DPO on which the midchain is stacked */
125  adj_index0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
126  adj_index1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
127  adj_index2 = vnet_buffer(b2)->ip.adj_index[VLIB_TX];
128  adj_index3 = vnet_buffer(b3)->ip.adj_index[VLIB_TX];
129 
130  adj0 = adj_get(adj_index0);
131  adj1 = adj_get(adj_index1);
132  adj2 = adj_get(adj_index2);
133  adj3 = adj_get(adj_index3);
134 
135  dpo0 = &adj0->sub_type.midchain.next_dpo;
136  dpo1 = &adj1->sub_type.midchain.next_dpo;
137  dpo2 = &adj2->sub_type.midchain.next_dpo;
138  dpo3 = &adj3->sub_type.midchain.next_dpo;
139 
140  next0 = dpo0->dpoi_next_node;
141  next1 = dpo1->dpoi_next_node;
142  next2 = dpo2->dpoi_next_node;
143  next3 = dpo3->dpoi_next_node;
144 
145  vnet_buffer(b1)->ip.adj_index[VLIB_TX] = dpo1->dpoi_index;
146  vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
147  vnet_buffer(b2)->ip.adj_index[VLIB_TX] = dpo2->dpoi_index;
148  vnet_buffer(b3)->ip.adj_index[VLIB_TX] = dpo3->dpoi_index;
149 
150  if (interface_count)
151  {
154  thread_index,
155  adj0->rewrite_header.sw_if_index,
156  1,
157  vlib_buffer_length_in_chain (vm, b0));
160  thread_index,
161  adj1->rewrite_header.sw_if_index,
162  1,
163  vlib_buffer_length_in_chain (vm, b1));
166  thread_index,
167  adj2->rewrite_header.sw_if_index,
168  1,
169  vlib_buffer_length_in_chain (vm, b2));
172  thread_index,
173  adj3->rewrite_header.sw_if_index,
174  1,
175  vlib_buffer_length_in_chain (vm, b3));
176  }
177 
178  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
179  {
180  adj_midchain_tx_trace_t *tr = vlib_add_trace (vm, node,
181  b0, sizeof (*tr));
182  tr->ai = adj_index0;
183  }
184  if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
185  {
186  adj_midchain_tx_trace_t *tr = vlib_add_trace (vm, node,
187  b1, sizeof (*tr));
188  tr->ai = adj_index1;
189  }
190  if (PREDICT_FALSE(b2->flags & VLIB_BUFFER_IS_TRACED))
191  {
192  adj_midchain_tx_trace_t *tr = vlib_add_trace (vm, node,
193  b2, sizeof (*tr));
194  tr->ai = adj_index2;
195  }
196  if (PREDICT_FALSE(b3->flags & VLIB_BUFFER_IS_TRACED))
197  {
198  adj_midchain_tx_trace_t *tr = vlib_add_trace (vm, node,
199  b3, sizeof (*tr));
200  tr->ai = adj_index3;
201  }
202 
203  vlib_validate_buffer_enqueue_x4 (vm, node, next_index,
204  to_next, n_left_to_next,
205  bi0, bi1, bi2, bi3,
206  next0, next1, next2, next3);
207  }
208  while (n_left_from > 0 && n_left_to_next > 0)
209  {
210  u32 bi0, adj_index0, next0;
211  const ip_adjacency_t * adj0;
212  const dpo_id_t *dpo0;
213  vlib_buffer_t * b0;
214 
215  bi0 = from[0];
216  to_next[0] = bi0;
217  from += 1;
218  to_next += 1;
219  n_left_from -= 1;
220  n_left_to_next -= 1;
221 
222  b0 = vlib_get_buffer(vm, bi0);
223 
224  /* Follow the DPO on which the midchain is stacked */
225  adj_index0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
226  adj0 = adj_get(adj_index0);
227  dpo0 = &adj0->sub_type.midchain.next_dpo;
228  next0 = dpo0->dpoi_next_node;
229  vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
230 
231  if (interface_count)
232  {
235  thread_index,
236  adj0->rewrite_header.sw_if_index,
237  1,
238  vlib_buffer_length_in_chain (vm, b0));
239  }
240 
241  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
242  {
243  adj_midchain_tx_trace_t *tr = vlib_add_trace (vm, node,
244  b0, sizeof (*tr));
245  tr->ai = adj_index0;
246  }
247 
248  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
249  to_next, n_left_to_next,
250  bi0, next0);
251  }
252 
253  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
254  }
255 
256  return frame->n_vectors;
257 }
258 
259 static u8 *
260 format_adj_midchain_tx_trace (u8 * s, va_list * args)
261 {
262  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
263  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
264  adj_midchain_tx_trace_t *tr = va_arg (*args, adj_midchain_tx_trace_t*);
265 
266  s = format(s, "adj-midchain:[%d]:%U", tr->ai,
267  format_ip_adjacency, tr->ai,
269 
270  return (s);
271 }
272 
273 static uword
275  vlib_node_runtime_t * node,
276  vlib_frame_t * frame)
277 {
278  return (adj_midchain_tx_inline(vm, node, frame, 1));
279 }
280 
282  .function = adj_midchain_tx,
283  .name = "adj-midchain-tx",
284  .vector_size = sizeof (u32),
285 
286  .format_trace = format_adj_midchain_tx_trace,
287 
288  .n_next_nodes = 1,
289  .next_nodes = {
290  [0] = "error-drop",
291  },
292 };
293 
294 static uword
296  vlib_node_runtime_t * node,
297  vlib_frame_t * frame)
298 {
299  return (adj_midchain_tx_inline(vm, node, frame, 0));
300 }
301 
303  .function = adj_midchain_tx_no_count,
304  .name = "adj-midchain-tx-no-count",
305  .vector_size = sizeof (u32),
306 
307  .format_trace = format_adj_midchain_tx_trace,
308 
309  .n_next_nodes = 1,
310  .next_nodes = {
311  [0] = "error-drop",
312  },
313 };
314 
315 VNET_FEATURE_INIT (adj_midchain_tx_ip4, static) = {
316  .arc_name = "ip4-output",
317  .node_name = "adj-midchain-tx",
318  .runs_before = VNET_FEATURES ("interface-output"),
319  .feature_index_ptr = &adj_midchain_tx_feature_node[VNET_LINK_IP4],
320 };
321 VNET_FEATURE_INIT (adj_midchain_tx_no_count_ip4, static) = {
322  .arc_name = "ip4-output",
323  .node_name = "adj-midchain-tx-no-count",
324  .runs_before = VNET_FEATURES ("interface-output"),
326 };
327 VNET_FEATURE_INIT (adj_midchain_tx_ip6, static) = {
328  .arc_name = "ip6-output",
329  .node_name = "adj-midchain-tx",
330  .runs_before = VNET_FEATURES ("interface-output"),
331  .feature_index_ptr = &adj_midchain_tx_feature_node[VNET_LINK_IP6],
332 };
333 VNET_FEATURE_INIT (adj_midchain_tx_no_count_ip6, static) = {
334  .arc_name = "ip6-output",
335  .node_name = "adj-midchain-tx-no-count",
336  .runs_before = VNET_FEATURES ("interface-output"),
338 };
339 VNET_FEATURE_INIT (adj_midchain_tx_mpls, static) = {
340  .arc_name = "mpls-output",
341  .node_name = "adj-midchain-tx",
342  .runs_before = VNET_FEATURES ("interface-output"),
343  .feature_index_ptr = &adj_midchain_tx_feature_node[VNET_LINK_MPLS],
344 };
345 VNET_FEATURE_INIT (adj_midchain_tx_no_count_mpls, static) = {
346  .arc_name = "mpls-output",
347  .node_name = "adj-midchain-tx-no-count",
348  .runs_before = VNET_FEATURES ("interface-output"),
350 };
351 VNET_FEATURE_INIT (adj_midchain_tx_ethernet, static) = {
352  .arc_name = "ethernet-output",
353  .node_name = "adj-midchain-tx",
354  .runs_before = VNET_FEATURES ("error-drop"),
355  .feature_index_ptr = &adj_midchain_tx_feature_node[VNET_LINK_ETHERNET],
356 };
357 VNET_FEATURE_INIT (adj_midchain_tx_no_count_ethernet, static) = {
358  .arc_name = "ethernet-output",
359  .node_name = "adj-midchain-tx-no-count",
360  .runs_before = VNET_FEATURES ("error-drop"),
362 };
363 VNET_FEATURE_INIT (adj_midchain_tx_nsh, static) = {
364  .arc_name = "nsh-output",
365  .node_name = "adj-midchain-tx",
366  .runs_before = VNET_FEATURES ("error-drop"),
367  .feature_index_ptr = &adj_midchain_tx_feature_node[VNET_LINK_NSH],
368 };
369 VNET_FEATURE_INIT (adj_midchain_tx_no_count_nsh, static) = {
370  .arc_name = "nsh-output",
371  .node_name = "adj-midchain-tx-no-count",
372  .runs_before = VNET_FEATURES ("error-drop"),
374 };
375 
376 static inline u32
378 {
379  switch (link) {
380  case VNET_LINK_IP4:
381  return (ip4_midchain_node.index);
382  case VNET_LINK_IP6:
383  return (ip6_midchain_node.index);
384  case VNET_LINK_MPLS:
385  return (mpls_midchain_node.index);
386  case VNET_LINK_ETHERNET:
387  return (adj_l2_midchain_node.index);
388  case VNET_LINK_NSH:
389  return (adj_nsh_midchain_node.index);
390  case VNET_LINK_ARP:
391  break;
392  }
393  ASSERT(0);
394  return (0);
395 }
396 
397 static u8
399 {
400  u8 arc = (u8) ~0;
401  switch (adj->ia_link)
402  {
403  case VNET_LINK_IP4:
404  {
406  break;
407  }
408  case VNET_LINK_IP6:
409  {
411  break;
412  }
413  case VNET_LINK_MPLS:
414  {
416  break;
417  }
418  case VNET_LINK_ETHERNET:
419  {
421  break;
422  }
423  case VNET_LINK_NSH:
424  {
425  arc = nsh_main_dummy.output_feature_arc_index;
426  break;
427  }
428  case VNET_LINK_ARP:
429  ASSERT(0);
430  break;
431  }
432 
433  ASSERT (arc != (u8) ~0);
434 
435  return (arc);
436 }
437 
438 static u32
440 {
441  return ((adj->ia_flags & ADJ_FLAG_MIDCHAIN_NO_COUNT) ?
443  adj_midchain_tx_node.index);
444 }
445 
446 static u32
448 {
450  {
452  }
453 
454  return (adj_midchain_tx_feature_node[adj->ia_link]);
455 }
456 
457 /**
458  * adj_midchain_setup
459  *
460  * Setup the adj as a mid-chain
461  */
462 void
464  adj_midchain_fixup_t fixup,
465  const void *data,
467 {
468  u32 feature_index, tx_node;
469  ip_adjacency_t *adj;
470  u8 arc_index;
471 
472  ASSERT(ADJ_INDEX_INVALID != adj_index);
473 
474  adj = adj_get(adj_index);
475 
476  adj->sub_type.midchain.fixup_func = fixup;
477  adj->sub_type.midchain.fixup_data = data;
479  adj->ia_flags |= flags;
480 
482  feature_index = adj_nbr_midchain_get_feature_node(adj);
483  tx_node = adj_nbr_midchain_get_tx_node(adj);
484 
485  vnet_feature_enable_disable_with_index (arc_index, feature_index,
486  adj->rewrite_header.sw_if_index,
487  1 /* enable */, 0, 0);
488 
489  /*
490  * stack the midchain on the drop so it's ready to forward in the adj-midchain-tx.
491  * The graph arc used/created here is from the midchain-tx node to the
492  * child's registered node. This is because post adj processing the next
493  * node are any output features, then the midchain-tx. from there we
494  * need to get to the stacked child's node.
495  */
496  dpo_stack_from_node(tx_node,
497  &adj->sub_type.midchain.next_dpo,
499 }
500 
501 /**
502  * adj_nbr_midchain_update_rewrite
503  *
504  * Update the adjacency's rewrite string. A NULL string implies the
505  * rewrite is reset (i.e. when ARP/ND etnry is gone).
506  * NB: the adj being updated may be handling traffic in the DP.
507  */
508 void
510  adj_midchain_fixup_t fixup,
511  const void *fixup_data,
513  u8 *rewrite)
514 {
515  ip_adjacency_t *adj;
516 
517  ASSERT(ADJ_INDEX_INVALID != adj_index);
518 
519  adj = adj_get(adj_index);
520 
521  /*
522  * one time only update. since we don't support chainging the tunnel
523  * src,dst, this is all we need.
524  */
528 
529  /*
530  * tunnels can always provide a rewrite.
531  */
532  ASSERT(NULL != rewrite);
533 
534  adj_midchain_setup(adj_index, fixup, fixup_data, flags);
535 
536  /*
537  * update the rewirte with the workers paused.
538  */
543  rewrite);
544 }
545 
546 /**
547  * adj_nbr_midchain_unstack
548  *
549  * Unstack the adj. stack it on drop
550  */
551 void
553 {
554  fib_node_index_t *entry_indicies, tmp;
555  ip_adjacency_t *adj;
556 
557  ASSERT(ADJ_INDEX_INVALID != adj_index);
558  adj = adj_get (adj_index);
559 
560  /*
561  * check to see if this unstacking breaks a recursion loop
562  */
563  entry_indicies = NULL;
564  tmp = adj->sub_type.midchain.fei;
566 
567  if (FIB_NODE_INDEX_INVALID != tmp)
568  {
569  fib_entry_recursive_loop_detect(tmp, &entry_indicies);
570  vec_free(entry_indicies);
571  }
572 
573  /*
574  * stack on the drop
575  */
578  &adj->sub_type.midchain.next_dpo,
581 }
582 
583 void
585  fib_node_index_t fei,
587 {
588  fib_node_index_t *entry_indicies;
589  dpo_id_t tmp = DPO_INVALID;
590  ip_adjacency_t *adj;
591 
592  adj = adj_get (ai);
593 
594  /*
595  * check to see if this stacking will form a recursion loop
596  */
597  entry_indicies = NULL;
598  adj->sub_type.midchain.fei = fei;
599 
600  if (fib_entry_recursive_loop_detect(adj->sub_type.midchain.fei, &entry_indicies))
601  {
602  /*
603  * loop formed, stack on the drop.
604  */
606  }
607  else
608  {
609  fib_entry_contribute_forwarding (fei, fct, &tmp);
610 
611  if ((adj->ia_flags & ADJ_FLAG_MIDCHAIN_IP_STACK) &&
612  (DPO_LOAD_BALANCE == tmp.dpoi_type))
613  {
614  /*
615  * do that hash now and stack on the choice.
616  * If the choice is an incomplete adj then we will need a poke when
617  * it becomes complete. This happens since the adj update walk propagates
618  * as far a recursive paths.
619  */
620  const dpo_id_t *choice;
621  load_balance_t *lb;
622  int hash;
623 
624  lb = load_balance_get (tmp.dpoi_index);
625 
627  {
629  lb->lb_hash_config);
630  }
631  else if (FIB_FORW_CHAIN_TYPE_UNICAST_IP6 == fct)
632  {
634  lb->lb_hash_config);
635  }
636  else
637  {
638  hash = 0;
639  ASSERT(0);
640  }
641 
642  choice = load_balance_get_bucket_i (lb, hash & lb->lb_n_buckets_minus_1);
643  dpo_copy (&tmp, choice);
644  }
645  }
646  adj_nbr_midchain_stack (ai, &tmp);
647  dpo_reset(&tmp);
648  vec_free(entry_indicies);
649 }
650 
651 /**
652  * adj_nbr_midchain_stack
653  */
654 void
656  const dpo_id_t *next)
657 {
658  ip_adjacency_t *adj;
659 
660  ASSERT(ADJ_INDEX_INVALID != adj_index);
661 
662  adj = adj_get(adj_index);
663 
666 
668  &adj->sub_type.midchain.next_dpo,
669  next);
670 }
671 
672 int
674  fib_node_index_t **entry_indicies)
675 {
676  fib_node_index_t *entry_index, *entries;
677  ip_adjacency_t * adj;
678 
679  adj = adj_get(ai);
680  entries = *entry_indicies;
681 
682  vec_foreach(entry_index, entries)
683  {
684  if (*entry_index == adj->sub_type.midchain.fei)
685  {
686  /*
687  * The entry this midchain links to is already in the set
688  * of visisted entries, this is a loop
689  */
691  return (1);
692  }
693  }
694 
696  return (0);
697 }
698 
699 u8*
700 format_adj_midchain (u8* s, va_list *ap)
701 {
702  index_t index = va_arg(*ap, index_t);
703  u32 indent = va_arg(*ap, u32);
704  ip_adjacency_t * adj = adj_get(index);
705 
706  s = format (s, "%U", format_vnet_link, adj->ia_link);
707  s = format (s, " via %U",
708  format_ip46_address, &adj->sub_type.nbr.next_hop,
710  s = format (s, " %U",
712  &adj->rewrite_header, sizeof (adj->rewrite_data), indent);
713  s = format (s, "\n%Ustacked-on",
714  format_white_space, indent);
715 
716  if (FIB_NODE_INDEX_INVALID != adj->sub_type.midchain.fei)
717  {
718  s = format (s, " entry:%d", adj->sub_type.midchain.fei);
719 
720  }
721  s = format (s, ":\n%U%U",
722  format_white_space, indent+2,
723  format_dpo_id, &adj->sub_type.midchain.next_dpo, indent+2);
724 
725  return (s);
726 }
727 
728 static void
730 {
731  adj_lock(dpo->dpoi_index);
732 }
733 static void
735 {
736  adj_unlock(dpo->dpoi_index);
737 }
738 
739 const static dpo_vft_t adj_midchain_dpo_vft = {
741  .dv_unlock = adj_dpo_unlock,
742  .dv_format = format_adj_midchain,
743  .dv_get_urpf = adj_dpo_get_urpf,
744 };
745 
746 /**
747  * @brief The per-protocol VLIB graph nodes that are assigned to a midchain
748  * object.
749  *
750  * this means that these graph nodes are ones from which a midchain is the
751  * parent object in the DPO-graph.
752  */
753 const static char* const midchain_ip4_nodes[] =
754 {
755  "ip4-midchain",
756  NULL,
757 };
758 const static char* const midchain_ip6_nodes[] =
759 {
760  "ip6-midchain",
761  NULL,
762 };
763 const static char* const midchain_mpls_nodes[] =
764 {
765  "mpls-midchain",
766  NULL,
767 };
768 const static char* const midchain_ethernet_nodes[] =
769 {
770  "adj-l2-midchain",
771  NULL,
772 };
773 const static char* const midchain_nsh_nodes[] =
774 {
775  "adj-nsh-midchain",
776  NULL,
777 };
778 
779 const static char* const * const midchain_nodes[DPO_PROTO_NUM] =
780 {
786 };
787 
788 void
790 {
791  dpo_register(DPO_ADJACENCY_MIDCHAIN, &adj_midchain_dpo_vft, midchain_nodes);
792 }
static uword adj_midchain_tx(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: adj_midchain.c:274
static const char *const midchain_nsh_nodes[]
Definition: adj_midchain.c:773
static const char *const midchain_ip6_nodes[]
Definition: adj_midchain.c:758
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:530
dpo_lock_fn_t dv_lock
A reference counting lock function.
Definition: dpo.h:404
#define VNET_LINK_NUM
Number of link types.
Definition: interface.h:367
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:2023
u32 flags
Definition: vhost_user.h:115
#define CLIB_UNUSED(x)
Definition: clib.h:82
A virtual function table regisitered for a DPO type.
Definition: dpo.h:399
static vlib_node_registration_t adj_midchain_tx_node
(constructor) VLIB_REGISTER_NODE (adj_midchain_tx_node)
Definition: adj_midchain.c:281
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:301
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
static uword adj_midchain_tx_no_count(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: adj_midchain.c:295
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:753
const u8 * adj_get_rewrite(adj_index_t ai)
Return the rewrite string of the adjacency.
Definition: adj.c:504
#define NULL
Definition: clib.h:58
static u32 ip4_compute_flow_hash(const ip4_header_t *ip, flow_hash_config_t flow_hash_config)
Definition: ip4.h:296
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:447
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:2593
u32 thread_index
Definition: main.h:179
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:410
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
#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:98
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
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:267
u32 adj_dpo_get_urpf(const dpo_id_t *dpo)
Definition: adj.c:291
unsigned char u8
Definition: types.h:56
vnet_link_t ia_link
link/ether-type 1 bytes
Definition: adj.h:242
const dpo_id_t * drop_dpo_get(dpo_proto_t proto)
Definition: drop_dpo.c:25
u8 output_feature_arc_index
Definition: lookup.h:140
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
union ip_adjacency_t_::@42 sub_type
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
vlib_node_registration_t adj_nsh_midchain_node
(constructor) VLIB_REGISTER_NODE (adj_nsh_midchain_node)
Definition: adj_nsh.c:183
dpo_proto_t vnet_link_to_dpo_proto(vnet_link_t linkt)
Definition: dpo.c:95
format_function_t format_ip_adjacency
Definition: format.h:58
#define always_inline
Definition: clib.h:98
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:839
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:113
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:222
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:188
static const char *const *const midchain_nodes[DPO_PROTO_NUM]
Definition: adj_midchain.c:779
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:584
u8 output_feature_arc_index
Definition: ethernet.h:329
void adj_unlock(adj_index_t adj_index)
Release a reference counting lock on the adjacency.
Definition: adj.c:318
vlib_node_registration_t mpls_midchain_node
(constructor) VLIB_REGISTER_NODE (mpls_midchain_node)
Definition: mpls_output.c:352
unsigned int u32
Definition: types.h:88
format_function_t format_vnet_rewrite
Definition: rewrite.h:331
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:45
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:186
static const char *const midchain_mpls_nodes[]
Definition: adj_midchain.c:763
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
#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:377
dpo_type_t dpoi_type
the type
Definition: dpo.h:172
static const dpo_id_t * load_balance_get_bucket_i(const load_balance_t *lb, u32 bucket)
Definition: load_balance.h:228
Trace data for packets traversing the midchain tx node.
Definition: adj_midchain.c:36
void adj_midchain_module_init(void)
Module initialisation.
Definition: adj_midchain.c:789
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:673
adj_index_t ai
the midchain adj we are traversing
Definition: adj_midchain.c:41
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:452
The FIB DPO provieds;.
Definition: load_balance.h:106
#define PREDICT_FALSE(x)
Definition: clib.h:111
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:398
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:302
#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
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:420
mpls_main_t mpls_main
Definition: mpls.c:25
vlib_main_t * vm
Definition: buffer.c:301
static void adj_dpo_unlock(dpo_id_t *dpo)
Definition: adj_midchain.c:734
#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:260
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:509
int fib_entry_recursive_loop_detect(fib_node_index_t entry_index, fib_node_index_t **entry_indicies)
Definition: fib_entry.c:1400
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
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:452
u8 * format_adj_midchain(u8 *s, va_list *ap)
Format a midchain adjacency.
Definition: adj_midchain.c:700
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:537
static u32 adj_nbr_midchain_get_tx_node(ip_adjacency_t *adj)
Definition: adj_midchain.c:439
#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:655
ip6_main_t ip6_main
Definition: ip6_forward.c:2624
ip_lookup_main_t lookup_main
Definition: ip6.h:178
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:219
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:552
u8 * format_dpo_id(u8 *s, va_list *args)
Format a DPO_id_t oject
Definition: dpo.c:147
#define VNET_FEATURES(...)
Definition: feature.h:435
u32 entries
static void adj_dpo_lock(dpo_id_t *dpo)
Definition: adj_midchain.c:729
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:57
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:184
#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
struct ip_adjacency_t_::@42::@44 midchain
IP_LOOKUP_NEXT_MIDCHAIN.
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:463
nsh_main_dummy_t nsh_main_dummy
Definition: adj_nsh.c:20
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:195
#define vnet_buffer(b)
Definition: buffer.h:368
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:903
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:115
u8 * format_vnet_link(u8 *s, va_list *ap)
Definition: fib_types.c:40
u16 dpoi_next_node
The next VLIB node to follow.
Definition: dpo.h:180
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:117
static const char *const midchain_ethernet_nodes[]
Definition: adj_midchain.c:768
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:62
struct ip_adjacency_t_::@42::@43 nbr
IP_LOOKUP_NEXT_ARP/IP_LOOKUP_NEXT_REWRITE.
VNET_FEATURE_INIT(adj_midchain_tx_ip4, static)
static u32 adj_nbr_midchain_get_feature_node(ip_adjacency_t *adj)
Definition: adj_midchain.c:447
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:515