FD.io VPP  v16.12-rc0-308-g931be3a
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_midchain.h>
21 #include <vnet/dpo/drop_dpo.h>
22 #include <vnet/fib/fib_walk.h>
23 
24 /**
25  * The two midchain tx feature node indices
26  */
29 
30 /**
31  * @brief Trace data for packets traversing the midchain tx node
32  */
34 {
35  /**
36  * @brief the midchain adj we are traversing
37  */
40 
43  vlib_node_runtime_t * node,
44  vlib_frame_t * frame,
45  int interface_count)
46 {
47  u32 * from, * to_next, n_left_from, n_left_to_next;
48  u32 next_index;
49  vnet_main_t *vnm = vnet_get_main ();
51  u32 cpu_index = vm->cpu_index;
52 
53  /* Vector of buffer / pkt indices we're supposed to process */
54  from = vlib_frame_vector_args (frame);
55 
56  /* Number of buffers / pkts */
57  n_left_from = frame->n_vectors;
58 
59  /* Speculatively send the first buffer to the last disposition we used */
60  next_index = node->cached_next_index;
61 
62  while (n_left_from > 0)
63  {
64  /* set up to enqueue to our disposition with index = next_index */
65  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
66 
67 
68  while (n_left_from >= 4 && n_left_to_next > 2)
69  {
70  u32 bi0, adj_index0, next0;
71  const ip_adjacency_t * adj0;
72  const dpo_id_t *dpo0;
73  vlib_buffer_t * b0;
74  u32 bi1, adj_index1, next1;
75  const ip_adjacency_t * adj1;
76  const dpo_id_t *dpo1;
77  vlib_buffer_t * b1;
78 
79  /* Prefetch next iteration. */
80  {
81  vlib_buffer_t * p2, * p3;
82 
83  p2 = vlib_get_buffer (vm, from[2]);
84  p3 = vlib_get_buffer (vm, from[3]);
85 
86  vlib_prefetch_buffer_header (p2, LOAD);
87  vlib_prefetch_buffer_header (p3, LOAD);
88 
91  }
92 
93  bi0 = from[0];
94  to_next[0] = bi0;
95  bi1 = from[1];
96  to_next[1] = bi1;
97 
98  from += 2;
99  to_next += 2;
100  n_left_from -= 2;
101  n_left_to_next -= 2;
102 
103  b0 = vlib_get_buffer(vm, bi0);
104  b1 = vlib_get_buffer(vm, bi1);
105 
106  /* Follow the DPO on which the midchain is stacked */
107  adj_index0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
108  adj_index1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
109 
110  adj0 = adj_get(adj_index0);
111  adj1 = adj_get(adj_index1);
112 
113  dpo0 = &adj0->sub_type.midchain.next_dpo;
114  dpo1 = &adj1->sub_type.midchain.next_dpo;
115 
116  next0 = dpo0->dpoi_next_node;
117  next1 = dpo1->dpoi_next_node;
118 
119  vnet_buffer(b1)->ip.adj_index[VLIB_TX] = dpo1->dpoi_index;
120  vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
121 
122  if (interface_count)
123  {
126  cpu_index,
127  adj0->rewrite_header.sw_if_index,
128  1,
129  vlib_buffer_length_in_chain (vm, b0));
132  cpu_index,
133  adj1->rewrite_header.sw_if_index,
134  1,
135  vlib_buffer_length_in_chain (vm, b1));
136  }
137 
139  {
140  adj_midchain_tx_trace_t *tr = vlib_add_trace (vm, node,
141  b0, sizeof (*tr));
142  tr->ai = adj_index0;
143  }
145  {
146  adj_midchain_tx_trace_t *tr = vlib_add_trace (vm, node,
147  b1, sizeof (*tr));
148  tr->ai = adj_index1;
149  }
150 
151  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
152  to_next, n_left_to_next,
153  bi0, bi1,
154  next0, next1);
155  }
156  while (n_left_from > 0 && n_left_to_next > 0)
157  {
158  u32 bi0, adj_index0, next0;
159  const ip_adjacency_t * adj0;
160  const dpo_id_t *dpo0;
161  vlib_buffer_t * b0;
162 
163  bi0 = from[0];
164  to_next[0] = bi0;
165  from += 1;
166  to_next += 1;
167  n_left_from -= 1;
168  n_left_to_next -= 1;
169 
170  b0 = vlib_get_buffer(vm, bi0);
171 
172  /* Follow the DPO on which the midchain is stacked */
173  adj_index0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
174  adj0 = adj_get(adj_index0);
175  dpo0 = &adj0->sub_type.midchain.next_dpo;
176  next0 = dpo0->dpoi_next_node;
177  vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
178 
179  if (interface_count)
180  {
183  cpu_index,
184  adj0->rewrite_header.sw_if_index,
185  1,
186  vlib_buffer_length_in_chain (vm, b0));
187  }
188 
190  {
191  adj_midchain_tx_trace_t *tr = vlib_add_trace (vm, node,
192  b0, sizeof (*tr));
193  tr->ai = adj_index0;
194  }
195 
196  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
197  to_next, n_left_to_next,
198  bi0, next0);
199  }
200 
201  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
202  }
203 
204  return frame->n_vectors;
205 }
206 
207 static u8 *
208 format_adj_midchain_tx_trace (u8 * s, va_list * args)
209 {
210  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
211  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
212  adj_midchain_tx_trace_t *tr = va_arg (*args, adj_midchain_tx_trace_t*);
213 
214  s = format(s, "adj-midchain:[%d]:%U", tr->ai,
215  format_ip_adjacency, tr->ai,
217 
218  return (s);
219 }
220 
221 static uword
223  vlib_node_runtime_t * node,
224  vlib_frame_t * frame)
225 {
226  return (adj_midchain_tx_inline(vm, node, frame, 1));
227 }
228 
230  .function = adj_midchain_tx,
231  .name = "adj-midchain-tx",
232  .vector_size = sizeof (u32),
233 
234  .format_trace = format_adj_midchain_tx_trace,
235 
236  .n_next_nodes = 1,
237  .next_nodes = {
238  [0] = "error-drop",
239  },
240 };
241 
242 static uword
244  vlib_node_runtime_t * node,
245  vlib_frame_t * frame)
246 {
247  return (adj_midchain_tx_inline(vm, node, frame, 0));
248 }
249 
251  .function = adj_midchain_tx_no_count,
252  .name = "adj-midchain-tx-no-count",
253  .vector_size = sizeof (u32),
254 
255  .format_trace = format_adj_midchain_tx_trace,
256 
257  .n_next_nodes = 1,
258  .next_nodes = {
259  [0] = "error-drop",
260  },
261 };
262 
263 VNET_IP4_TX_FEATURE_INIT (adj_midchain_tx_ip4, static) = {
264  .node_name = "adj-midchain-tx",
265  .runs_before = ORDER_CONSTRAINTS {"interface-output", 0},
266  .feature_index = &adj_midchain_tx_feature_node[VNET_LINK_IP4],
267 };
268 VNET_IP4_TX_FEATURE_INIT (adj_midchain_tx_no_count_ip4, static) = {
269  .node_name = "adj-midchain-tx-no-count",
270  .runs_before = ORDER_CONSTRAINTS {"interface-output", 0},
272 };
273 VNET_IP6_TX_FEATURE_INIT (adj_midchain_tx_ip6, static) = {
274  .node_name = "adj-midchain-tx",
275  .runs_before = ORDER_CONSTRAINTS {"interface-output", 0},
276  .feature_index = &adj_midchain_tx_feature_node[VNET_LINK_IP6],
277 };
278 VNET_IP6_TX_FEATURE_INIT (adj_midchain_tx_no_count_ip6, static) = {
279  .node_name = "adj-midchain-tx-no-count",
280  .runs_before = ORDER_CONSTRAINTS {"interface-output", 0},
282 };
283 VNET_MPLS_TX_FEATURE_INIT (adj_midchain_tx_mpls, static) = {
284  .node_name = "adj-midchain-tx",
285  .runs_before = ORDER_CONSTRAINTS {"interface-output", 0},
286  .feature_index = &adj_midchain_tx_feature_node[VNET_LINK_MPLS],
287 };
288 VNET_MPLS_TX_FEATURE_INIT (adj_midchain_tx_no_count_mpls, static) = {
289  .node_name = "adj-midchain-tx-no-count",
290  .runs_before = ORDER_CONSTRAINTS {"interface-output", 0},
292 };
293 VNET_ETHERNET_TX_FEATURE_INIT (adj_midchain_tx_ethernet, static) = {
294  .node_name = "adj-midchain-tx",
295  .runs_before = ORDER_CONSTRAINTS {"error-drop", 0},
297 };
298 VNET_ETHERNET_TX_FEATURE_INIT (adj_midchain_tx_no_count_ethernet, static) = {
299  .node_name = "adj-midchain-tx-no-count",
300  .runs_before = ORDER_CONSTRAINTS {"error-drop", 0},
302 };
303 
304 static inline u32
306 {
307  switch (link) {
308  case VNET_LINK_IP4:
309  return (ip4_midchain_node.index);
310  case VNET_LINK_IP6:
311  return (ip6_midchain_node.index);
312  case VNET_LINK_MPLS:
313  return (mpls_midchain_node.index);
314  case VNET_LINK_ETHERNET:
315  return (adj_l2_midchain_node.index);
316  case VNET_LINK_ARP:
317  break;
318  }
319  ASSERT(0);
320  return (0);
321 }
322 
325 {
327 
328  switch (adj->ia_link)
329  {
330  case VNET_LINK_IP4:
331  {
332  ip4_main_t * im = &ip4_main;
333  ip_lookup_main_t * lm = &im->lookup_main;
335  break;
336  }
337  case VNET_LINK_IP6:
338  {
339  ip6_main_t * im = &ip6_main;
340  ip_lookup_main_t * lm = &im->lookup_main;
342  break;
343  }
344  case VNET_LINK_MPLS:
345  {
346  mpls_main_t * mm = &mpls_main;
348  break;
349  }
350  case VNET_LINK_ETHERNET:
351  {
353  break;
354  }
355  case VNET_LINK_ARP:
356  ASSERT(0);
357  break;
358  }
359 
360  return (cm);
361 }
362 
363 /**
364  * adj_nbr_midchain_update_rewrite
365  *
366  * Update the adjacency's rewrite string. A NULL string implies the
367  * rewrite is reset (i.e. when ARP/ND etnry is gone).
368  * NB: the adj being updated may be handling traffic in the DP.
369  */
370 void
372  adj_midchain_fixup_t fixup,
374  u8 *rewrite)
375 {
376  vnet_config_main_t * vcm;
378  ip_adjacency_t *adj;
379  u32 ci;
380 
381  ASSERT(ADJ_INDEX_INVALID != adj_index);
382 
383  adj = adj_get(adj_index);
384 
385  /*
386  * one time only update. since we don't support chainging the tunnel
387  * src,dst, this is all we need.
388  */
390  /*
391  * tunnels can always provide a rewrite.
392  */
393  ASSERT(NULL != rewrite);
394 
395  adj->sub_type.midchain.fixup_func = fixup;
396 
398  vcm = &(cm->config_main);
400  adj->rewrite_header.sw_if_index, ~0);
401  ci = cm->config_index_by_sw_if_index[adj->rewrite_header.sw_if_index];
402 
403  /*
404  * Choose the adj tx function based on whether the client wants
405  * to count against the interface or not and insert the appropriate
406  * TX feature.
407  */
408  if (flags & ADJ_MIDCHAIN_FLAG_NO_COUNT)
409  {
410  adj->sub_type.midchain.tx_function_node =
412 
414  vlib_get_main(),
415  vcm, ci,
417  /* config data */ 0,
418  /* # bytes of config data */ 0);
419  }
420  else
421  {
422  adj->sub_type.midchain.tx_function_node =
423  adj_midchain_tx_node.index;
425  vlib_get_main(),
426  vcm, ci,
428  /* config data */ 0,
429  /* # bytes of config data */ 0);
430  }
431 
432  cm->config_index_by_sw_if_index[adj->rewrite_header.sw_if_index] = ci;
433 
434 
435  /*
436  * stack the midchain on the drop so it's ready to forward in the adj-midchain-tx.
437  * The graph arc used/created here is from the midchain-tx node to the
438  * child's registered node. This is because post adj processing the next
439  * node are any output features, then the midchain-tx. from there we
440  * need to get to the stacked child's node.
441  */
442  dpo_stack_from_node(adj->sub_type.midchain.tx_function_node,
443  &adj->sub_type.midchain.next_dpo,
445 
446  /*
447  * update the rewirte with the workers paused.
448  */
452  adj->sub_type.midchain.tx_function_node,
453  rewrite);
454 
455  /*
456  * time for walkies fido.
457  */
458  fib_node_back_walk_ctx_t bw_ctx = {
460  };
461 
463 }
464 
465 /**
466  * adj_nbr_midchain_unstack
467  *
468  * Unstack the adj. stack it on drop
469  */
470 void
472 {
473  ip_adjacency_t *adj;
474 
475  ASSERT(ADJ_INDEX_INVALID != adj_index);
476 
477  adj = adj_get(adj_index);
478 
479  /*
480  * stack on the drop
481  */
484  &adj->sub_type.midchain.next_dpo,
486 
488 }
489 
490 /**
491  * adj_nbr_midchain_stack
492  */
493 void
495  const dpo_id_t *next)
496 {
497  ip_adjacency_t *adj;
498 
499  ASSERT(ADJ_INDEX_INVALID != adj_index);
500 
501  adj = adj_get(adj_index);
502 
504 
505  dpo_stack_from_node(adj->sub_type.midchain.tx_function_node,
506  &adj->sub_type.midchain.next_dpo,
507  next);
508 }
509 
510 u8*
511 format_adj_midchain (u8* s, va_list *ap)
512 {
513  index_t index = va_arg(*ap, index_t);
514  u32 indent = va_arg(*ap, u32);
515  vnet_main_t * vnm = vnet_get_main();
516  ip_adjacency_t * adj = adj_get(index);
517 
518  s = format (s, "%U", format_vnet_link, adj->ia_link);
519  s = format (s, " via %U ",
520  format_ip46_address, &adj->sub_type.nbr.next_hop);
521  s = format (s, " %U",
523  vnm->vlib_main, &adj->rewrite_header,
524  sizeof (adj->rewrite_data), indent);
525  s = format (s, "\n%Ustacked-on:\n%U%U",
526  format_white_space, indent,
527  format_white_space, indent+2,
528  format_dpo_id, &adj->sub_type.midchain.next_dpo, indent+2);
529 
530  return (s);
531 }
532 
533 static void
535 {
536  adj_lock(dpo->dpoi_index);
537 }
538 static void
540 {
541  adj_unlock(dpo->dpoi_index);
542 }
543 
544 const static dpo_vft_t adj_midchain_dpo_vft = {
546  .dv_unlock = adj_dpo_unlock,
547  .dv_format = format_adj_midchain,
548 };
549 
550 /**
551  * @brief The per-protocol VLIB graph nodes that are assigned to a midchain
552  * object.
553  *
554  * this means that these graph nodes are ones from which a midchain is the
555  * parent object in the DPO-graph.
556  */
557 const static char* const midchain_ip4_nodes[] =
558 {
559  "ip4-midchain",
560  NULL,
561 };
562 const static char* const midchain_ip6_nodes[] =
563 {
564  "ip6-midchain",
565  NULL,
566 };
567 const static char* const midchain_mpls_nodes[] =
568 {
569  "mpls-midchain",
570  NULL,
571 };
572 const static char* const midchain_ethernet_nodes[] =
573 {
574  "adj-l2-midchain",
575  NULL,
576 };
577 
578 const static char* const * const midchain_nodes[DPO_PROTO_NUM] =
579 {
584 };
585 
586 void
588 {
589  dpo_register(DPO_ADJACENCY_MIDCHAIN, &adj_midchain_dpo_vft, midchain_nodes);
590 }
static uword adj_midchain_tx(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: adj_midchain.c:222
format_function_t format_ip46_address
Definition: format.h:61
vnet_config_main_t config_main
Definition: feature.h:55
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
Definition: main.c:457
vnet_feature_config_main_t feature_config_mains[VNET_N_IP_FEAT]
per-interface features
Definition: ethernet.h:267
static const char *const midchain_ip6_nodes[]
Definition: adj_midchain.c:562
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:388
dpo_lock_fn_t dv_lock
A reference counting lock function.
Definition: dpo.h:318
#define VNET_LINK_NUM
Number of link types.
Definition: interface.h:231
static u32 adj_midchain_tx_no_count_feature_node[VNET_LINK_NUM]
Definition: adj_midchain.c:28
vlib_node_registration_t ip6_midchain_node
(constructor) VLIB_REGISTER_NODE (ip6_midchain_node)
Definition: ip6_forward.c:2176
#define CLIB_UNUSED(x)
Definition: clib.h:79
A virtual function table regisitered for a DPO type.
Definition: dpo.h:313
static vlib_node_registration_t adj_midchain_tx_node
(constructor) VLIB_REGISTER_NODE (adj_midchain_tx_node)
Definition: adj_midchain.c:229
void adj_lock(adj_index_t adj_index)
An adjacency is a representation of an attached L3 peer.
Definition: adj.c:189
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
static uword adj_midchain_tx_no_count(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: adj_midchain.c:243
vnet_interface_main_t interface_main
Definition: vnet.h:72
static const char *const midchain_ip4_nodes[]
The per-protocol VLIB graph nodes that are assigned to a midchain object.
Definition: adj_midchain.c:557
u8 * format_vnet_link(u8 *s, va_list ap)
Definition: fib_types.c:38
#define NULL
Definition: clib.h:55
IP unicast adjacency.
Definition: lookup.h:174
vlib_node_registration_t ip4_midchain_node
(constructor) VLIB_REGISTER_NODE (ip4_midchain_node)
Definition: ip4_forward.c:2674
struct ip_adjacency_t_::@164::@165 nbr
IP_LOOKUP_NEXT_ARP/IP_LOOKUP_NEXT_REWRITE.
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
void adj_nbr_update_rewrite_internal(ip_adjacency_t *adj, adj_nbr_rewrite_flag_t flags, u32 complete_next_index, u32 next_index, u8 *rewrite)
ip_lookup_main_t lookup_main
Definition: ip4.h:96
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:112
Walk to re-collapse the multipath adjs when the rewrite of a unipath adjacency changes.
Definition: fib_node.h:97
vnet_feature_config_main_t feature_config_mains[VNET_N_IP_FEAT]
Definition: mpls.h:98
vnet_link_t ia_link
Definition: lookup.h:199
void adj_nbr_midchain_update_rewrite(adj_index_t adj_index, adj_midchain_fixup_t fixup, adj_midchain_flag_t flags, u8 *rewrite)
adj_nbr_midchain_update_rewrite
Definition: adj_midchain.c:371
const dpo_id_t * drop_dpo_get(dpo_proto_t proto)
Definition: drop_dpo.c:25
ethernet_main_t ethernet_main
Definition: ethernet.h:279
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
static ip_adjacency_t * adj_get(adj_index_t adj_index)
Get a pointer to an adjacency object from its index.
Definition: adj.h:117
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:221
#define always_inline
Definition: clib.h:84
void fib_walk_sync(fib_node_type_t parent_type, fib_node_index_t parent_index, fib_node_back_walk_ctx_t *ctx)
Back walk all the children of a FIB node.
Definition: fib_walk.c:624
vlib_combined_counter_main_t * combined_sw_if_counters
Definition: interface.h:577
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:113
static const char *const *const midchain_nodes[DPO_PROTO_NUM]
Definition: adj_midchain.c:578
u32 cpu_index
Definition: main.h:159
void adj_unlock(adj_index_t adj_index)
Release a reference counting lock on the adjacency.
Definition: adj.c:206
vlib_node_registration_t mpls_midchain_node
(constructor) VLIB_REGISTER_NODE (mpls_midchain_node)
Definition: mpls_output.c:206
format_function_t format_vnet_rewrite
Definition: rewrite.h:292
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:42
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:567
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:138
fib_node_bw_reason_flag_t fnbw_reason
The reason/trigger for the backwalk.
Definition: fib_node.h:164
#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
VNET_IP4_TX_FEATURE_INIT(adj_midchain_tx_ip4, static)
vlib_main_t * vlib_main
Definition: vnet.h:88
#define ORDER_CONSTRAINTS
Definition: feature.h:188
static u32 adj_get_midchain_node(vnet_link_t link)
Definition: adj_midchain.c:305
Trace data for packets traversing the midchain tx node.
Definition: adj_midchain.c:33
void adj_midchain_module_init(void)
Module initialisation.
Definition: adj_midchain.c:587
adj_index_t ai
the midchain adj we are traversing
Definition: adj_midchain.c:38
static adj_index_t adj_get_index(ip_adjacency_t *adj)
Get a pointer to an adjacency object from its index.
Definition: adj_internal.h:83
#define PREDICT_FALSE(x)
Definition: clib.h:97
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:250
#define vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next, n_left_to_next, bi0, bi1, next0, next1)
Finish enqueueing two buffers forward in the graph.
Definition: buffer_node.h:70
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
Definition: buffer_node.h:216
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:350
Packets TX through the midchain do not increment the interface counters.
Definition: adj_midchain.h:44
union ip_adjacency_t_::@164 sub_type
vnet_feature_config_main_t feature_config_mains[VNET_N_IP_FEAT]
rx unicast, multicast, tx interface/feature configuration.
Definition: lookup.h:360
u16 n_vectors
Definition: node.h:344
mpls_main_t mpls_main
Definition: mpls.c:25
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:82
static void adj_dpo_unlock(dpo_id_t *dpo)
Definition: adj_midchain.c:539
static u8 * format_adj_midchain_tx_trace(u8 *s, va_list *args)
Definition: adj_midchain.c:208
u32 adj_index_t
An index for adjacencies.
Definition: adj_types.h:30
This packet matches an "incomplete adjacency" and packets need to be passed to ARP to find rewrite st...
Definition: lookup.h:72
Context passed between object during a back walk.
Definition: fib_node.h:160
u8 * format_adj_midchain(u8 *s, va_list *ap)
Format a midchain adjacency.
Definition: adj_midchain.c:511
u16 cached_next_index
Definition: node.h:463
static void vlib_increment_combined_counter(vlib_combined_counter_main_t *cm, u32 cpu_index, u32 index, u32 packet_increment, u32 byte_increment)
Increment a combined counter.
Definition: counter.h:241
#define ASSERT(truth)
VNET_ETHERNET_TX_FEATURE_INIT(adj_midchain_tx_ethernet, static)
void adj_nbr_midchain_stack(adj_index_t adj_index, const dpo_id_t *next)
adj_nbr_midchain_stack
Definition: adj_midchain.c:494
unsigned int u32
Definition: types.h:88
dpo_proto_t vnet_link_to_dpo_proto(vnet_link_t linkt)
Definition: fib_types.c:218
#define vnet_buffer(b)
Definition: buffer.h:333
ip6_main_t ip6_main
Definition: ip6_forward.c:2655
ip_lookup_main_t lookup_main
Definition: ip6.h:132
enum vnet_link_t_ vnet_link_t
Link Type: A description of the protocol of packets on the link.
IPv4 main type.
Definition: ip4.h:95
This packets follow a mid-chain adjacency.
Definition: lookup.h:88
void(* adj_midchain_fixup_t)(vlib_main_t *vm, struct ip_adjacency_t_ *adj, vlib_buffer_t *b0)
A function type for post-rewrite fixups on midchain adjacency.
Definition: lookup.h:167
u32 vnet_config_add_feature(vlib_main_t *vm, vnet_config_main_t *cm, u32 config_string_heap_index, u32 feature_index, void *feature_config, u32 n_feature_config_bytes)
Definition: config.c:239
void adj_nbr_midchain_unstack(adj_index_t adj_index)
adj_nbr_midchain_unstack
Definition: adj_midchain.c:471
u8 * format_dpo_id(u8 *s, va_list *args)
Format a DPO_id_t oject
Definition: dpo.c:98
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:95
VNET_IP6_TX_FEATURE_INIT(adj_midchain_tx_ip6, static)
static void adj_dpo_lock(dpo_id_t *dpo)
Definition: adj_midchain.c:534
u64 uword
Definition: types.h:112
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace_funcs.h:55
enum adj_midchain_flag_t_ adj_midchain_flag_t
Midchain Adjacency sub-type.
Definition: defs.h:47
#define DPO_PROTO_NUM
Definition: dpo.h:72
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:154
unsigned char u8
Definition: types.h:56
ip_lookup_next_t lookup_next_index
Definition: lookup.h:183
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:27
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:253
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:166
VNET_MPLS_TX_FEATURE_INIT(adj_midchain_tx_mpls, static)
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:143
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:418
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1060
u8 data[0]
Packet data.
Definition: buffer.h:154
#define CLIB_MEMORY_BARRIER()
Definition: clib.h:101
static vnet_feature_config_main_t * adj_midchain_get_config_for_link_type(const ip_adjacency_t *adj)
Definition: adj_midchain.c:324
u16 dpoi_next_node
The next VLIB node to follow.
Definition: dpo.h:150
u32 flags
Definition: vhost-user.h:75
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header, unspecified alignment)
Definition: vec.h:445
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:85
static const char *const midchain_ethernet_nodes[]
Definition: adj_midchain.c:572
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:69
struct ip_adjacency_t_::@164::@166 midchain
IP_LOOKUP_NEXT_MIDCHAIN.
format_function_t format_ip_adjacency
Definition: format.h:58
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:373