FD.io VPP  v17.07.01-10-g3be13f0
Vector Packet Processing
lookup_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/ip.h>
17 #include <vnet/dpo/lookup_dpo.h>
19 #include <vnet/mpls/mpls_lookup.h>
20 #include <vnet/fib/fib_table.h>
21 #include <vnet/fib/ip4_fib.h>
22 #include <vnet/fib/ip6_fib.h>
23 #include <vnet/fib/mpls_fib.h>
24 #include <vnet/mfib/mfib_table.h>
25 #include <vnet/mfib/ip4_mfib.h>
26 #include <vnet/mfib/ip6_mfib.h>
27 
28 static const char *const lookup_input_names[] = LOOKUP_INPUTS;
29 static const char *const lookup_cast_names[] = LOOKUP_CASTS;
30 
31 /**
32  * @brief Enumeration of the lookup subtypes
33  */
34 typedef enum lookup_sub_type_t_
35 {
41 #define LOOKUP_SUB_TYPE_NUM (LOOKUP_SUB_TYPE_DST_TABLE_FROM_INTERFACE+1)
42 
43 #define FOR_EACH_LOOKUP_SUB_TYPE(_st) \
44  for (_st = LOOKUP_SUB_TYPE_IP4_SRC; _st < LOOKUP_SUB_TYPE_NUM; _st++)
45 
46 /**
47  * @brief pool of all MPLS Label DPOs
48  */
50 
51 /**
52  * @brief An array of registered DPO type values for the sub-types
53  */
55 
56 static lookup_dpo_t *
58 {
59  lookup_dpo_t *lkd;
60 
61  pool_get_aligned(lookup_dpo_pool, lkd, CLIB_CACHE_LINE_BYTES);
62 
63  return (lkd);
64 }
65 
66 static index_t
68 {
69  return (lkd - lookup_dpo_pool);
70 }
71 
72 static void
74  dpo_proto_t proto,
75  lookup_cast_t cast,
76  lookup_input_t input,
77  lookup_table_t table_config,
78  dpo_id_t *dpo)
79 {
80  lookup_dpo_t *lkd;
81  dpo_type_t type;
82 
83  lkd = lookup_dpo_alloc();
84  lkd->lkd_fib_index = fib_index;
85  lkd->lkd_proto = proto;
86  lkd->lkd_input = input;
87  lkd->lkd_table = table_config;
88  lkd->lkd_cast = cast;
89 
90  /*
91  * use the input type to select the lookup sub-type
92  */
93  type = 0;
94 
95  switch (input)
96  {
99  break;
101  switch (table_config)
102  {
105  break;
108  break;
109  }
110  if (LOOKUP_MULTICAST == cast)
111  {
113  }
114  }
115 
116  if (0 == type)
117  {
118  dpo_reset(dpo);
119  }
120  else
121  {
122  dpo_set(dpo, type, proto, lookup_dpo_get_index(lkd));
123  }
124 }
125 
126 void
128  dpo_proto_t proto,
129  lookup_cast_t cast,
130  lookup_input_t input,
131  lookup_table_t table_config,
132  dpo_id_t *dpo)
133 {
134  if (LOOKUP_TABLE_FROM_CONFIG == table_config)
135  {
136  if (LOOKUP_UNICAST == cast)
137  {
138  fib_table_lock(fib_index, dpo_proto_to_fib(proto));
139  }
140  else
141  {
142  mfib_table_lock(fib_index, dpo_proto_to_fib(proto));
143  }
144  }
145  lookup_dpo_add_or_lock_i(fib_index, proto, cast, input, table_config, dpo);
146 }
147 
148 void
150  dpo_proto_t proto,
151  lookup_cast_t cast,
152  lookup_input_t input,
153  lookup_table_t table_config,
154  dpo_id_t *dpo)
155 {
157 
158  if (LOOKUP_TABLE_FROM_CONFIG == table_config)
159  {
160  if (LOOKUP_UNICAST == cast)
161  {
162  fib_index =
164  table_id);
165  }
166  else
167  {
168  fib_index =
170  table_id);
171  }
172  }
173 
174  ASSERT(FIB_NODE_INDEX_INVALID != fib_index);
175  lookup_dpo_add_or_lock_i(fib_index, proto, cast, input, table_config, dpo);
176 }
177 
178 u8*
179 format_lookup_dpo (u8 *s, va_list *args)
180 {
181  index_t index = va_arg (*args, index_t);
182  lookup_dpo_t *lkd;
183 
184  lkd = lookup_dpo_get(index);
185 
187  {
188  s = format(s, "%s,%s lookup in interface's %U table",
192  }
193  else
194  {
195  if (LOOKUP_UNICAST == lkd->lkd_cast)
196  {
197  s = format(s, "%s,%s lookup in %U",
202  }
203  else
204  {
205  s = format(s, "%s,%s lookup in %U",
210  }
211  }
212  return (s);
213 }
214 
215 static void
217 {
218  lookup_dpo_t *lkd;
219 
220  lkd = lookup_dpo_get(dpo->dpoi_index);
221 
222  lkd->lkd_locks++;
223 }
224 
225 static void
227 {
228  lookup_dpo_t *lkd;
229 
230  lkd = lookup_dpo_get(dpo->dpoi_index);
231 
232  lkd->lkd_locks--;
233 
234  if (0 == lkd->lkd_locks)
235  {
237  {
238  if (LOOKUP_UNICAST == lkd->lkd_cast)
239  {
242  }
243  else
244  {
247  }
248  }
249  pool_put(lookup_dpo_pool, lkd);
250  }
251 }
252 
253 always_inline void
254 ip4_src_fib_lookup_one (u32 src_fib_index0,
255  const ip4_address_t * addr0,
256  u32 * src_adj_index0)
257 {
258  ip4_fib_mtrie_leaf_t leaf0;
259  ip4_fib_mtrie_t * mtrie0;
260 
261  mtrie0 = &ip4_fib_get (src_fib_index0)->mtrie;
262 
263  leaf0 = ip4_fib_mtrie_lookup_step_one (mtrie0, addr0);
264  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 2);
265  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 3);
266 
267  src_adj_index0[0] = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
268 }
269 
270 always_inline void
271 ip4_src_fib_lookup_two (u32 src_fib_index0,
272  u32 src_fib_index1,
273  const ip4_address_t * addr0,
274  const ip4_address_t * addr1,
275  u32 * src_adj_index0,
276  u32 * src_adj_index1)
277 {
278  ip4_fib_mtrie_leaf_t leaf0, leaf1;
279  ip4_fib_mtrie_t * mtrie0, * mtrie1;
280 
281  mtrie0 = &ip4_fib_get (src_fib_index0)->mtrie;
282  mtrie1 = &ip4_fib_get (src_fib_index1)->mtrie;
283 
284  leaf0 = ip4_fib_mtrie_lookup_step_one (mtrie0, addr0);
285  leaf1 = ip4_fib_mtrie_lookup_step_one (mtrie1, addr1);
286 
287  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 2);
288  leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 2);
289 
290  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 3);
291  leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 3);
292 
293  src_adj_index0[0] = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
294  src_adj_index1[0] = ip4_fib_mtrie_leaf_get_adj_index (leaf1);
295 }
296 
297 /**
298  * @brief Lookup trace data
299  */
300 typedef struct lookup_trace_t_
301 {
302  union {
303  ip46_address_t addr;
305  };
309 
310 
313  vlib_node_runtime_t * node,
314  vlib_frame_t * from_frame,
315  int input_src_addr,
316  int table_from_interface)
317 {
318  u32 n_left_from, next_index, * from, * to_next;
319  u32 thread_index = vlib_get_thread_index();
321 
322  from = vlib_frame_vector_args (from_frame);
323  n_left_from = from_frame->n_vectors;
324 
325  next_index = node->cached_next_index;
326 
327  while (n_left_from > 0)
328  {
329  u32 n_left_to_next;
330 
331  vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
332 
333  while (n_left_from >= 4 && n_left_to_next > 2)
334  {
335  u32 bi0, lkdi0, lbi0, fib_index0, next0, hash_c0;
336  flow_hash_config_t flow_hash_config0;
337  const ip4_address_t *input_addr0;
338  const load_balance_t *lb0;
339  const lookup_dpo_t * lkd0;
340  const ip4_header_t * ip0;
341  const dpo_id_t *dpo0;
342  vlib_buffer_t * b0;
343  u32 bi1, lkdi1, lbi1, fib_index1, next1, hash_c1;
344  flow_hash_config_t flow_hash_config1;
345  const ip4_address_t *input_addr1;
346  const load_balance_t *lb1;
347  const lookup_dpo_t * lkd1;
348  const ip4_header_t * ip1;
349  const dpo_id_t *dpo1;
350  vlib_buffer_t * b1;
351 
352  /* Prefetch next iteration. */
353  {
354  vlib_buffer_t * p2, * p3;
355 
356  p2 = vlib_get_buffer (vm, from[2]);
357  p3 = vlib_get_buffer (vm, from[3]);
358 
359  vlib_prefetch_buffer_header (p2, LOAD);
360  vlib_prefetch_buffer_header (p3, LOAD);
361 
364  }
365 
366  bi0 = from[0];
367  to_next[0] = bi0;
368  bi1 = from[1];
369  to_next[1] = bi1;
370  from += 2;
371  to_next += 2;
372  n_left_from -= 2;
373  n_left_to_next -= 2;
374 
375  b0 = vlib_get_buffer (vm, bi0);
376  ip0 = vlib_buffer_get_current (b0);
377  b1 = vlib_get_buffer (vm, bi1);
378  ip1 = vlib_buffer_get_current (b1);
379 
380  /* dst lookup was done by ip4 lookup */
381  lkdi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
382  lkdi1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
383  lkd0 = lookup_dpo_get(lkdi0);
384  lkd1 = lookup_dpo_get(lkdi1);
385 
386  /*
387  * choose between a lookup using the fib index in the DPO
388  * or getting the FIB index from the interface.
389  */
390  if (table_from_interface)
391  {
392  fib_index0 =
394  vnet_buffer(b0)->sw_if_index[VLIB_RX]);
395  fib_index1 =
397  vnet_buffer(b1)->sw_if_index[VLIB_RX]);
398  }
399  else
400  {
401  fib_index0 = lkd0->lkd_fib_index;
402  fib_index1 = lkd1->lkd_fib_index;
403  }
404 
405  /*
406  * choose between a source or destination address lookup in the table
407  */
408  if (input_src_addr)
409  {
410  input_addr0 = &ip0->src_address;
411  input_addr1 = &ip1->src_address;
412  }
413  else
414  {
415  input_addr0 = &ip0->dst_address;
416  input_addr1 = &ip1->dst_address;
417  }
418 
419  /* do lookup */
420  ip4_src_fib_lookup_two (fib_index0, fib_index1,
421  input_addr0, input_addr1,
422  &lbi0, &lbi1);
423  lb0 = load_balance_get(lbi0);
424  lb1 = load_balance_get(lbi1);
425 
426  vnet_buffer(b0)->sw_if_index[VLIB_TX] = fib_index0;
427  vnet_buffer(b1)->sw_if_index[VLIB_TX] = fib_index1;
428 
429  /* Use flow hash to compute multipath adjacency. */
430  hash_c0 = vnet_buffer (b0)->ip.flow_hash = 0;
431  hash_c1 = vnet_buffer (b1)->ip.flow_hash = 0;
432 
433  if (PREDICT_FALSE (lb0->lb_n_buckets > 1))
434  {
435  flow_hash_config0 = lb0->lb_hash_config;
436  hash_c0 = vnet_buffer (b0)->ip.flow_hash =
437  ip4_compute_flow_hash (ip0, flow_hash_config0);
438  }
439 
440  if (PREDICT_FALSE (lb1->lb_n_buckets > 1))
441  {
442  flow_hash_config1 = lb1->lb_hash_config;
443  hash_c1 = vnet_buffer (b1)->ip.flow_hash =
444  ip4_compute_flow_hash (ip1, flow_hash_config1);
445  }
446 
447  dpo0 = load_balance_get_bucket_i(lb0,
448  (hash_c0 &
449  (lb0->lb_n_buckets_minus_1)));
450  dpo1 = load_balance_get_bucket_i(lb1,
451  (hash_c1 &
452  (lb1->lb_n_buckets_minus_1)));
453 
454  next0 = dpo0->dpoi_next_node;
455  next1 = dpo1->dpoi_next_node;
456  vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
457  vnet_buffer(b1)->ip.adj_index[VLIB_TX] = dpo1->dpoi_index;
458 
460  (cm, thread_index, lbi0, 1,
461  vlib_buffer_length_in_chain (vm, b0));
463  (cm, thread_index, lbi1, 1,
464  vlib_buffer_length_in_chain (vm, b1));
465 
467  {
468  lookup_trace_t *tr = vlib_add_trace (vm, node,
469  b0, sizeof (*tr));
470  tr->fib_index = fib_index0;
471  tr->lbi = lbi0;
472  tr->addr.ip4 = *input_addr0;
473  }
475  {
476  lookup_trace_t *tr = vlib_add_trace (vm, node,
477  b1, sizeof (*tr));
478  tr->fib_index = fib_index1;
479  tr->lbi = lbi1;
480  tr->addr.ip4 = *input_addr1;
481  }
482 
483  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
484  to_next, n_left_to_next,
485  bi0, bi1, next0, next1);
486  }
487 
488  while (n_left_from > 0 && n_left_to_next > 0)
489  {
490  u32 bi0, lkdi0, lbi0, fib_index0, next0, hash_c0;
491  flow_hash_config_t flow_hash_config0;
492  const ip4_address_t *input_addr;
493  const load_balance_t *lb0;
494  const lookup_dpo_t * lkd0;
495  const ip4_header_t * ip0;
496  const dpo_id_t *dpo0;
497  vlib_buffer_t * b0;
498 
499  bi0 = from[0];
500  to_next[0] = bi0;
501  from += 1;
502  to_next += 1;
503  n_left_from -= 1;
504  n_left_to_next -= 1;
505 
506  b0 = vlib_get_buffer (vm, bi0);
507  ip0 = vlib_buffer_get_current (b0);
508 
509  /* dst lookup was done by ip4 lookup */
510  lkdi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
511  lkd0 = lookup_dpo_get(lkdi0);
512 
513  /*
514  * choose between a lookup using the fib index in the DPO
515  * or getting the FIB index from the interface.
516  */
517  if (table_from_interface)
518  {
519  fib_index0 =
521  vnet_buffer(b0)->sw_if_index[VLIB_RX]);
522  }
523  else
524  {
525  fib_index0 = lkd0->lkd_fib_index;
526  }
527 
528  /*
529  * choose between a source or destination address lookup in the table
530  */
531  if (input_src_addr)
532  {
533  input_addr = &ip0->src_address;
534  }
535  else
536  {
537  input_addr = &ip0->dst_address;
538  }
539 
540  /* do lookup */
541  ip4_src_fib_lookup_one (fib_index0, input_addr, &lbi0);
542  lb0 = load_balance_get(lbi0);
543 
544  vnet_buffer(b0)->sw_if_index[VLIB_TX] = fib_index0;
545 
546  /* Use flow hash to compute multipath adjacency. */
547  hash_c0 = vnet_buffer (b0)->ip.flow_hash = 0;
548 
549  if (PREDICT_FALSE (lb0->lb_n_buckets > 1))
550  {
551  flow_hash_config0 = lb0->lb_hash_config;
552  hash_c0 = vnet_buffer (b0)->ip.flow_hash =
553  ip4_compute_flow_hash (ip0, flow_hash_config0);
554  }
555 
556  dpo0 = load_balance_get_bucket_i(lb0,
557  (hash_c0 &
558  (lb0->lb_n_buckets_minus_1)));
559 
560  next0 = dpo0->dpoi_next_node;
561  vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
562 
564  (cm, thread_index, lbi0, 1,
565  vlib_buffer_length_in_chain (vm, b0));
566 
568  {
569  lookup_trace_t *tr = vlib_add_trace (vm, node,
570  b0, sizeof (*tr));
571  tr->fib_index = fib_index0;
572  tr->lbi = lbi0;
573  tr->addr.ip4 = *input_addr;
574  }
575 
576  vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
577  n_left_to_next, bi0, next0);
578  }
579  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
580  }
581  return from_frame->n_vectors;
582 }
583 
584 static u8 *
585 format_lookup_trace (u8 * s, va_list * args)
586 {
587  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
588  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
589  lookup_trace_t * t = va_arg (*args, lookup_trace_t *);
590  uword indent = format_get_indent (s);
591  s = format (s, "%U fib-index:%d addr:%U load-balance:%d",
592  format_white_space, indent,
593  t->fib_index,
595  t->lbi);
596  return s;
597 }
598 
601  vlib_node_runtime_t * node,
602  vlib_frame_t * from_frame)
603 {
604  return (lookup_dpo_ip4_inline(vm, node, from_frame, 0, 0));
605 }
606 
608  .function = lookup_ip4_dst,
609  .name = "lookup-ip4-dst",
610  .vector_size = sizeof (u32),
611  .sibling_of = "ip4-lookup",
612  .format_trace = format_lookup_trace,
613 };
615 
618  vlib_node_runtime_t * node,
619  vlib_frame_t * from_frame)
620 {
621  return (lookup_dpo_ip4_inline(vm, node, from_frame, 0, 1));
622 }
623 
625  .function = lookup_ip4_dst_itf,
626  .name = "lookup-ip4-dst-itf",
627  .vector_size = sizeof (u32),
628  .sibling_of = "ip4-lookup",
629  .format_trace = format_lookup_trace,
630 };
632 
635  vlib_node_runtime_t * node,
636  vlib_frame_t * from_frame)
637 {
638  return (lookup_dpo_ip4_inline(vm, node, from_frame, 1, 0));
639 }
640 
642  .function = lookup_ip4_src,
643  .name = "lookup-ip4-src",
644  .vector_size = sizeof (u32),
645  .format_trace = format_lookup_trace,
646  .sibling_of = "ip4-lookup",
647 };
649 
652  vlib_node_runtime_t * node,
653  vlib_frame_t * from_frame,
654  int input_src_addr,
655  int table_from_interface)
656 {
658  u32 n_left_from, next_index, * from, * to_next;
659  u32 thread_index = vlib_get_thread_index();
660 
661  from = vlib_frame_vector_args (from_frame);
662  n_left_from = from_frame->n_vectors;
663 
664  next_index = node->cached_next_index;
665 
666  while (n_left_from > 0)
667  {
668  u32 n_left_to_next;
669 
670  vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
671 
672  while (n_left_from >= 4 && n_left_to_next > 2)
673  {
674  u32 bi0, lkdi0, lbi0, fib_index0, next0, hash_c0;
675  flow_hash_config_t flow_hash_config0;
676  const ip6_address_t *input_addr0;
677  const load_balance_t *lb0;
678  const lookup_dpo_t * lkd0;
679  const ip6_header_t * ip0;
680  const dpo_id_t *dpo0;
681  vlib_buffer_t * b0;
682  u32 bi1, lkdi1, lbi1, fib_index1, next1, hash_c1;
683  flow_hash_config_t flow_hash_config1;
684  const ip6_address_t *input_addr1;
685  const load_balance_t *lb1;
686  const lookup_dpo_t * lkd1;
687  const ip6_header_t * ip1;
688  const dpo_id_t *dpo1;
689  vlib_buffer_t * b1;
690 
691  /* Prefetch next iteration. */
692  {
693  vlib_buffer_t * p2, * p3;
694 
695  p2 = vlib_get_buffer (vm, from[2]);
696  p3 = vlib_get_buffer (vm, from[3]);
697 
698  vlib_prefetch_buffer_header (p2, LOAD);
699  vlib_prefetch_buffer_header (p3, LOAD);
700 
703  }
704 
705  bi0 = from[0];
706  to_next[0] = bi0;
707  bi1 = from[1];
708  to_next[1] = bi1;
709  from += 2;
710  to_next += 2;
711  n_left_from -= 2;
712  n_left_to_next -= 2;
713 
714  b0 = vlib_get_buffer (vm, bi0);
715  ip0 = vlib_buffer_get_current (b0);
716  b1 = vlib_get_buffer (vm, bi1);
717  ip1 = vlib_buffer_get_current (b1);
718 
719  /* dst lookup was done by ip6 lookup */
720  lkdi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
721  lkdi1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
722  lkd0 = lookup_dpo_get(lkdi0);
723  lkd1 = lookup_dpo_get(lkdi1);
724 
725  /*
726  * choose between a lookup using the fib index in the DPO
727  * or getting the FIB index from the interface.
728  */
729  if (table_from_interface)
730  {
731  fib_index0 =
733  vnet_buffer(b0)->sw_if_index[VLIB_RX]);
734  fib_index1 =
736  vnet_buffer(b1)->sw_if_index[VLIB_RX]);
737  }
738  else
739  {
740  fib_index0 = lkd0->lkd_fib_index;
741  fib_index1 = lkd1->lkd_fib_index;
742  }
743 
744  /*
745  * choose between a source or destination address lookup in the table
746  */
747  if (input_src_addr)
748  {
749  input_addr0 = &ip0->src_address;
750  input_addr1 = &ip1->src_address;
751  }
752  else
753  {
754  input_addr0 = &ip0->dst_address;
755  input_addr1 = &ip1->dst_address;
756  }
757 
758  /* do src lookup */
760  fib_index0,
761  input_addr0);
763  fib_index1,
764  input_addr1);
765  lb0 = load_balance_get(lbi0);
766  lb1 = load_balance_get(lbi1);
767 
768  vnet_buffer(b0)->sw_if_index[VLIB_TX] = fib_index0;
769  vnet_buffer(b1)->sw_if_index[VLIB_TX] = fib_index1;
770 
771  /* Use flow hash to compute multipath adjacency. */
772  hash_c0 = vnet_buffer (b0)->ip.flow_hash = 0;
773  hash_c1 = vnet_buffer (b1)->ip.flow_hash = 0;
774 
775  if (PREDICT_FALSE (lb0->lb_n_buckets > 1))
776  {
777  flow_hash_config0 = lb0->lb_hash_config;
778  hash_c0 = vnet_buffer (b0)->ip.flow_hash =
779  ip6_compute_flow_hash (ip0, flow_hash_config0);
780  }
781 
782  if (PREDICT_FALSE (lb1->lb_n_buckets > 1))
783  {
784  flow_hash_config1 = lb1->lb_hash_config;
785  hash_c1 = vnet_buffer (b1)->ip.flow_hash =
786  ip6_compute_flow_hash (ip1, flow_hash_config1);
787  }
788 
789  dpo0 = load_balance_get_bucket_i(lb0,
790  (hash_c0 &
791  (lb0->lb_n_buckets_minus_1)));
792  dpo1 = load_balance_get_bucket_i(lb1,
793  (hash_c1 &
794  (lb1->lb_n_buckets_minus_1)));
795 
796  next0 = dpo0->dpoi_next_node;
797  next1 = dpo1->dpoi_next_node;
798  vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
799  vnet_buffer(b1)->ip.adj_index[VLIB_TX] = dpo1->dpoi_index;
800 
802  (cm, thread_index, lbi0, 1,
803  vlib_buffer_length_in_chain (vm, b0));
805  (cm, thread_index, lbi1, 1,
806  vlib_buffer_length_in_chain (vm, b1));
807 
809  {
810  lookup_trace_t *tr = vlib_add_trace (vm, node,
811  b0, sizeof (*tr));
812  tr->fib_index = fib_index0;
813  tr->lbi = lbi0;
814  tr->addr.ip6 = *input_addr0;
815  }
817  {
818  lookup_trace_t *tr = vlib_add_trace (vm, node,
819  b1, sizeof (*tr));
820  tr->fib_index = fib_index1;
821  tr->lbi = lbi1;
822  tr->addr.ip6 = *input_addr1;
823  }
824  vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next,
825  n_left_to_next, bi0, bi1,
826  next0, next1);
827  }
828  while (n_left_from > 0 && n_left_to_next > 0)
829  {
830  u32 bi0, lkdi0, lbi0, fib_index0, next0, hash_c0;
831  flow_hash_config_t flow_hash_config0;
832  const ip6_address_t *input_addr0;
833  const load_balance_t *lb0;
834  const lookup_dpo_t * lkd0;
835  const ip6_header_t * ip0;
836  const dpo_id_t *dpo0;
837  vlib_buffer_t * b0;
838 
839  bi0 = from[0];
840  to_next[0] = bi0;
841  from += 1;
842  to_next += 1;
843  n_left_from -= 1;
844  n_left_to_next -= 1;
845 
846  b0 = vlib_get_buffer (vm, bi0);
847  ip0 = vlib_buffer_get_current (b0);
848 
849  /* dst lookup was done by ip6 lookup */
850  lkdi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
851  lkd0 = lookup_dpo_get(lkdi0);
852 
853  /*
854  * choose between a lookup using the fib index in the DPO
855  * or getting the FIB index from the interface.
856  */
857  if (table_from_interface)
858  {
859  fib_index0 =
861  vnet_buffer(b0)->sw_if_index[VLIB_RX]);
862  }
863  else
864  {
865  fib_index0 = lkd0->lkd_fib_index;
866  }
867 
868  /*
869  * choose between a source or destination address lookup in the table
870  */
871  if (input_src_addr)
872  {
873  input_addr0 = &ip0->src_address;
874  }
875  else
876  {
877  input_addr0 = &ip0->dst_address;
878  }
879 
880  /* do src lookup */
882  fib_index0,
883  input_addr0);
884  lb0 = load_balance_get(lbi0);
885 
886  vnet_buffer(b0)->sw_if_index[VLIB_TX] = fib_index0;
887 
888  /* Use flow hash to compute multipath adjacency. */
889  hash_c0 = vnet_buffer (b0)->ip.flow_hash = 0;
890 
891  if (PREDICT_FALSE (lb0->lb_n_buckets > 1))
892  {
893  flow_hash_config0 = lb0->lb_hash_config;
894  hash_c0 = vnet_buffer (b0)->ip.flow_hash =
895  ip6_compute_flow_hash (ip0, flow_hash_config0);
896  }
897 
898  dpo0 = load_balance_get_bucket_i(lb0,
899  (hash_c0 &
900  (lb0->lb_n_buckets_minus_1)));
901 
902  next0 = dpo0->dpoi_next_node;
903  vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
904 
906  (cm, thread_index, lbi0, 1,
907  vlib_buffer_length_in_chain (vm, b0));
908 
910  {
911  lookup_trace_t *tr = vlib_add_trace (vm, node,
912  b0, sizeof (*tr));
913  tr->fib_index = fib_index0;
914  tr->lbi = lbi0;
915  tr->addr.ip6 = *input_addr0;
916  }
917  vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
918  n_left_to_next, bi0, next0);
919  }
920  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
921  }
922  return from_frame->n_vectors;
923 }
924 
927  vlib_node_runtime_t * node,
928  vlib_frame_t * from_frame)
929 {
930  return (lookup_dpo_ip6_inline(vm, node, from_frame, 0 /*use src*/, 0));
931 }
932 
934  .function = lookup_ip6_dst,
935  .name = "lookup-ip6-dst",
936  .vector_size = sizeof (u32),
937  .format_trace = format_lookup_trace,
938  .sibling_of = "ip6-lookup",
939 };
941 
944  vlib_node_runtime_t * node,
945  vlib_frame_t * from_frame)
946 {
947  return (lookup_dpo_ip6_inline(vm, node, from_frame, 0 /*use src*/, 1));
948 }
949 
951  .function = lookup_ip6_dst_itf,
952  .name = "lookup-ip6-dst-itf",
953  .vector_size = sizeof (u32),
954  .format_trace = format_lookup_trace,
955  .sibling_of = "ip6-lookup",
956 };
958 
961  vlib_node_runtime_t * node,
962  vlib_frame_t * from_frame)
963 {
964  return (lookup_dpo_ip6_inline(vm, node, from_frame, 1, 0));
965 }
966 
968  .function = lookup_ip6_src,
969  .name = "lookup-ip6-src",
970  .vector_size = sizeof (u32),
971  .format_trace = format_lookup_trace,
972  .sibling_of = "ip6-lookup",
973 };
975 
978  vlib_node_runtime_t * node,
979  vlib_frame_t * from_frame,
980  int table_from_interface)
981 {
982  u32 n_left_from, next_index, * from, * to_next;
983  u32 thread_index = vlib_get_thread_index();
985 
986  from = vlib_frame_vector_args (from_frame);
987  n_left_from = from_frame->n_vectors;
988 
989  next_index = node->cached_next_index;
990 
991  while (n_left_from > 0)
992  {
993  u32 n_left_to_next;
994 
995  vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
996 
997  /* while (n_left_from >= 4 && n_left_to_next >= 2) */
998  /* } */
999 
1000  while (n_left_from > 0 && n_left_to_next > 0)
1001  {
1002  u32 bi0, lkdi0, lbi0, fib_index0, next0, hash0;
1003  const mpls_unicast_header_t * hdr0;
1004  const load_balance_t *lb0;
1005  const lookup_dpo_t * lkd0;
1006  const dpo_id_t *dpo0;
1007  vlib_buffer_t * b0;
1008 
1009  bi0 = from[0];
1010  to_next[0] = bi0;
1011  from += 1;
1012  to_next += 1;
1013  n_left_from -= 1;
1014  n_left_to_next -= 1;
1015 
1016  b0 = vlib_get_buffer (vm, bi0);
1017  hdr0 = vlib_buffer_get_current (b0);
1018 
1019  /* dst lookup was done by mpls lookup */
1020  lkdi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
1021  lkd0 = lookup_dpo_get(lkdi0);
1022 
1023  /*
1024  * choose between a lookup using the fib index in the DPO
1025  * or getting the FIB index from the interface.
1026  */
1027  if (table_from_interface)
1028  {
1029  fib_index0 =
1031  vnet_buffer(b0)->sw_if_index[VLIB_RX]);
1032  }
1033  else
1034  {
1035  fib_index0 = lkd0->lkd_fib_index;
1036  }
1037 
1038  /* do lookup */
1039  lbi0 = mpls_fib_table_forwarding_lookup (fib_index0, hdr0);
1040  lb0 = load_balance_get(lbi0);
1041  dpo0 = load_balance_get_bucket_i(lb0, 0);
1042 
1043  next0 = dpo0->dpoi_next_node;
1044  vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
1045 
1046 
1047  if (MPLS_IS_REPLICATE & lbi0)
1048  {
1050  vnet_buffer (b0)->ip.adj_index[VLIB_TX] =
1051  (lbi0 & ~MPLS_IS_REPLICATE);
1052  }
1053  else
1054  {
1055  lb0 = load_balance_get(lbi0);
1056  ASSERT (lb0->lb_n_buckets > 0);
1057  ASSERT (is_pow2 (lb0->lb_n_buckets));
1058 
1059  if (PREDICT_FALSE(lb0->lb_n_buckets > 1))
1060  {
1061  hash0 = vnet_buffer (b0)->ip.flow_hash =
1064  (lb0,
1065  (hash0 & (lb0->lb_n_buckets_minus_1)));
1066  }
1067  else
1068  {
1069  dpo0 = load_balance_get_bucket_i (lb0, 0);
1070  }
1071  next0 = dpo0->dpoi_next_node;
1072 
1073  vnet_buffer (b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
1074 
1076  (cm, thread_index, lbi0, 1,
1077  vlib_buffer_length_in_chain (vm, b0));
1078  }
1079 
1080  vnet_buffer (b0)->mpls.ttl = ((char*)hdr0)[3];
1081  vnet_buffer (b0)->mpls.exp = (((char*)hdr0)[2] & 0xe) >> 1;
1082  vnet_buffer (b0)->mpls.first = 1;
1083  vlib_buffer_advance(b0, sizeof(*hdr0));
1084 
1086  {
1087  lookup_trace_t *tr = vlib_add_trace (vm, node,
1088  b0, sizeof (*tr));
1089  tr->fib_index = fib_index0;
1090  tr->lbi = lbi0;
1091  tr->hdr = *hdr0;
1092  }
1093 
1094  vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
1095  n_left_to_next, bi0, next0);
1096  }
1097  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1098  }
1099  return from_frame->n_vectors;
1100 }
1101 
1102 static u8 *
1103 format_lookup_mpls_trace (u8 * s, va_list * args)
1104 {
1105  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
1106  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
1107  lookup_trace_t * t = va_arg (*args, lookup_trace_t *);
1108  uword indent = format_get_indent (s);
1110 
1111  hdr.label_exp_s_ttl = clib_net_to_host_u32(t->hdr.label_exp_s_ttl);
1112 
1113  s = format (s, "%U fib-index:%d hdr:%U load-balance:%d",
1114  format_white_space, indent,
1115  t->fib_index,
1116  format_mpls_header, hdr,
1117  t->lbi);
1118  return s;
1119 }
1120 
1123  vlib_node_runtime_t * node,
1124  vlib_frame_t * from_frame)
1125 {
1126  return (lookup_dpo_mpls_inline(vm, node, from_frame, 0));
1127 }
1128 
1130  .function = lookup_mpls_dst,
1131  .name = "lookup-mpls-dst",
1132  .vector_size = sizeof (u32),
1133  .sibling_of = "mpls-lookup",
1134  .format_trace = format_lookup_mpls_trace,
1135  .n_next_nodes = 0,
1136 };
1138 
1141  vlib_node_runtime_t * node,
1142  vlib_frame_t * from_frame)
1143 {
1144  return (lookup_dpo_mpls_inline(vm, node, from_frame, 1));
1145 }
1146 
1148  .function = lookup_mpls_dst_itf,
1149  .name = "lookup-mpls-dst-itf",
1150  .vector_size = sizeof (u32),
1151  .sibling_of = "mpls-lookup",
1152  .format_trace = format_lookup_mpls_trace,
1153  .n_next_nodes = 0,
1154 };
1156 
1161 
1164  vlib_node_runtime_t * node,
1165  vlib_frame_t * from_frame,
1166  int is_v4)
1167 {
1168  u32 n_left_from, next_index, * from, * to_next;
1169 
1170  from = vlib_frame_vector_args (from_frame);
1171  n_left_from = from_frame->n_vectors;
1172 
1173  next_index = LOOKUP_IP_DST_MCAST_NEXT_RPF;
1174 
1175  while (n_left_from > 0)
1176  {
1177  u32 n_left_to_next;
1178 
1179  vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
1180 
1181  /* while (n_left_from >= 4 && n_left_to_next >= 2) */
1182  /* } */
1183 
1184  while (n_left_from > 0 && n_left_to_next > 0)
1185  {
1186  u32 bi0, lkdi0, fib_index0, next0;
1187  const lookup_dpo_t * lkd0;
1188  fib_node_index_t mfei0;
1189  vlib_buffer_t * b0;
1190 
1191  bi0 = from[0];
1192  to_next[0] = bi0;
1193  from += 1;
1194  to_next += 1;
1195  n_left_from -= 1;
1196  n_left_to_next -= 1;
1197 
1198  b0 = vlib_get_buffer (vm, bi0);
1199 
1200  /* dst lookup was done by mpls lookup */
1201  lkdi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
1202  lkd0 = lookup_dpo_get(lkdi0);
1203  fib_index0 = lkd0->lkd_fib_index;
1205 
1206  if (is_v4)
1207  {
1208  ip4_header_t * ip0;
1209 
1210  ip0 = vlib_buffer_get_current (b0);
1211  mfei0 = ip4_mfib_table_lookup(ip4_mfib_get(fib_index0),
1212  &ip0->src_address,
1213  &ip0->dst_address,
1214  64);
1216  {
1217  lookup_trace_t *tr = vlib_add_trace (vm, node,
1218  b0, sizeof (*tr));
1219  tr->fib_index = fib_index0;
1220  tr->lbi = mfei0;
1221  tr->addr.ip4 = ip0->dst_address;
1222  }
1223  }
1224  else
1225  {
1226  ip6_header_t * ip0;
1227 
1228  ip0 = vlib_buffer_get_current (b0);
1229  mfei0 = ip6_mfib_table_lookup2(ip6_mfib_get(fib_index0),
1230  &ip0->src_address,
1231  &ip0->dst_address);
1233  {
1234  lookup_trace_t *tr = vlib_add_trace (vm, node,
1235  b0, sizeof (*tr));
1236  tr->fib_index = fib_index0;
1237  tr->lbi = mfei0;
1238  tr->addr.ip6 = ip0->dst_address;
1239  }
1240  }
1241 
1242  vnet_buffer (b0)->ip.adj_index[VLIB_TX] = mfei0;
1243 
1244  vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
1245  n_left_to_next, bi0, next0);
1246  }
1247  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1248  }
1249  return from_frame->n_vectors;
1250 }
1251 
1254  vlib_node_runtime_t * node,
1255  vlib_frame_t * from_frame)
1256 {
1257  return (lookup_dpo_ip_dst_mcast_inline(vm, node, from_frame, 1));
1258 }
1259 
1261  .function = lookup_ip4_dst_mcast,
1262  .name = "lookup-ip4-dst-mcast",
1263  .vector_size = sizeof (u32),
1264 
1265  .format_trace = format_lookup_trace,
1266  .n_next_nodes = LOOKUP_IP_DST_MCAST_N_NEXT,
1267  .next_nodes = {
1268  [LOOKUP_IP_DST_MCAST_NEXT_RPF] = "ip4-mfib-forward-rpf",
1269  },
1270 };
1273 
1275 lookup_ip6_dst_mcast (vlib_main_t * vm,
1276  vlib_node_runtime_t * node,
1277  vlib_frame_t * from_frame)
1278 {
1279  return (lookup_dpo_ip_dst_mcast_inline(vm, node, from_frame, 0));
1280 }
1281 
1283  .function = lookup_ip6_dst_mcast,
1284  .name = "lookup-ip6-dst-mcast",
1285  .vector_size = sizeof (u32),
1286 
1287  .format_trace = format_lookup_trace,
1288  .n_next_nodes = LOOKUP_IP_DST_MCAST_N_NEXT,
1289  .next_nodes = {
1290  [LOOKUP_IP_DST_MCAST_NEXT_RPF] = "ip6-mfib-forward-rpf",
1291  },
1292 };
1294  lookup_ip6_dst_mcast)
1295 
1296 static void
1297 lookup_dpo_mem_show (void)
1298 {
1299  fib_show_memory_usage("Lookup",
1300  pool_elts(lookup_dpo_pool),
1301  pool_len(lookup_dpo_pool),
1302  sizeof(lookup_dpo_t));
1303 }
1304 
1305 const static dpo_vft_t lkd_vft = {
1307  .dv_unlock = lookup_dpo_unlock,
1308  .dv_format = format_lookup_dpo,
1309 };
1310 const static dpo_vft_t lkd_vft_w_mem_show = {
1312  .dv_unlock = lookup_dpo_unlock,
1313  .dv_format = format_lookup_dpo,
1314  .dv_mem_show = lookup_dpo_mem_show,
1315 };
1316 
1317 const static char* const lookup_src_ip4_nodes[] =
1318 {
1319  "lookup-ip4-src",
1320  NULL,
1321 };
1322 const static char* const lookup_src_ip6_nodes[] =
1323 {
1324  "lookup-ip6-src",
1325  NULL,
1326 };
1327 const static char* const * const lookup_src_nodes[DPO_PROTO_NUM] =
1328 {
1331  [DPO_PROTO_MPLS] = NULL,
1332 };
1333 
1334 const static char* const lookup_dst_ip4_nodes[] =
1335 {
1336  "lookup-ip4-dst",
1337  NULL,
1338 };
1339 const static char* const lookup_dst_ip6_nodes[] =
1340 {
1341  "lookup-ip6-dst",
1342  NULL,
1343 };
1344 const static char* const lookup_dst_mpls_nodes[] =
1345 {
1346  "lookup-mpls-dst",
1347  NULL,
1348 };
1349 const static char* const * const lookup_dst_nodes[DPO_PROTO_NUM] =
1350 {
1354 };
1355 
1356 const static char* const lookup_dst_mcast_ip4_nodes[] =
1357 {
1358  "lookup-ip4-dst-mcast",
1359  NULL,
1360 };
1361 const static char* const lookup_dst_mcast_ip6_nodes[] =
1362 {
1363  "lookup-ip6-dst-mcast",
1364  NULL,
1365 };
1366 const static char* const * const lookup_dst_mcast_nodes[DPO_PROTO_NUM] =
1367 {
1370 };
1371 
1372 const static char* const lookup_dst_from_interface_ip4_nodes[] =
1373 {
1374  "lookup-ip4-dst-itf",
1375  NULL,
1376 };
1377 const static char* const lookup_dst_from_interface_ip6_nodes[] =
1378 {
1379  "lookup-ip6-dst-itf",
1380  NULL,
1381 };
1382 const static char* const lookup_dst_from_interface_mpls_nodes[] =
1383 {
1384  "lookup-mpls-dst-itf",
1385  NULL,
1386 };
1387 const static char* const * const lookup_dst_from_interface_nodes[DPO_PROTO_NUM] =
1388 {
1392 };
1393 
1394 
1395 void
1397 {
1398  dpo_register(DPO_LOOKUP, &lkd_vft_w_mem_show, NULL);
1399 
1400  /*
1401  * There are various sorts of lookup; src or dst addr v4 /v6 etc.
1402  * there isn't an object type for each (there is only the lookup_dpo_t),
1403  * but, for performance reasons, there is a data plane function, and hence
1404  * VLIB node for each. VLIB graph node construction is based on DPO types
1405  * so we create sub-types.
1406  */
1415 }
static uword lookup_ip6_dst_itf(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: lookup_dpo.c:943
u16 lb_n_buckets
number of buckets in the load-balance.
Definition: load_balance.h:88
dpo_lock_fn_t dv_lock
A reference counting lock function.
Definition: dpo.h:341
static uword lookup_dpo_ip_dst_mcast_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame, int is_v4)
Definition: lookup_dpo.c:1163
lookup_input_t lkd_input
Switch to use src or dst address.
Definition: lookup_dpo.h:82
lookup_dpo_t * lookup_dpo_pool
pool of all MPLS Label DPOs
Definition: lookup_dpo.c:49
vlib_combined_counter_main_t lbm_to_counters
Definition: load_balance.h:46
A representation of an MPLS label for imposition in the data-path.
Definition: lookup_dpo.h:65
static uword lookup_ip4_src(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: lookup_dpo.c:634
#define CLIB_UNUSED(x)
Definition: clib.h:79
A virtual function table regisitered for a DPO type.
Definition: dpo.h:336
struct lookup_trace_t_ lookup_trace_t
Lookup trace data.
void lookup_dpo_add_or_lock_w_table_id(u32 table_id, dpo_proto_t proto, lookup_cast_t cast, lookup_input_t input, lookup_table_t table_config, dpo_id_t *dpo)
Definition: lookup_dpo.c:149
static uword lookup_dpo_mpls_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame, int table_from_interface)
Definition: lookup_dpo.c:977
enum lookup_sub_type_t_ lookup_sub_type_t
Enumeration of the lookup subtypes.
fib_node_index_t fib_index
Definition: lookup_dpo.c:306
format_function_t format_mpls_header
Definition: mpls.h:72
static void vlib_increment_combined_counter(vlib_combined_counter_main_t *cm, u32 thread_index, u32 index, u64 n_packets, u64 n_bytes)
Increment a combined counter.
Definition: counter.h:211
The mutiway-TRIE.
Definition: ip4_mtrie.h:129
lookup_sub_type_t_
Enumeration of the lookup subtypes.
Definition: lookup_dpo.c:34
ip4_address_t src_address
Definition: ip4_packet.h:164
static uword lookup_ip4_dst_mcast(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: lookup_dpo.c:1253
void fib_table_lock(u32 fib_index, fib_protocol_t proto)
Release a reference counting lock on the table.
Definition: fib_table.c:1159
static ip4_fib_mtrie_leaf_t ip4_fib_mtrie_lookup_step(const ip4_fib_mtrie_t *m, ip4_fib_mtrie_leaf_t current_leaf, const ip4_address_t *dst_address, u32 dst_address_byte_index)
Lookup step.
Definition: ip4_mtrie.h:197
static const char *const *const lookup_dst_nodes[DPO_PROTO_NUM]
Definition: lookup_dpo.c:1349
static dpo_type_t lookup_dpo_sub_types[LOOKUP_SUB_TYPE_NUM]
An array of registered DPO type values for the sub-types.
Definition: lookup_dpo.c:54
void mfib_table_unlock(u32 fib_index, fib_protocol_t proto)
Take a reference counting lock on the table.
Definition: mfib_table.c:474
#define NULL
Definition: clib.h:55
static u32 ip4_compute_flow_hash(const ip4_header_t *ip, flow_hash_config_t flow_hash_config)
Definition: ip4.h:272
static uword lookup_mpls_dst(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: lookup_dpo.c:1122
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
Definition: main.c:459
flow_hash_config_t lb_hash_config
the hash config to use when selecting a bucket.
Definition: load_balance.h:128
static const dpo_id_t * load_balance_get_fwd_bucket(const load_balance_t *lb, u16 bucket)
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
static uword lookup_dpo_ip6_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame, int input_src_addr, int table_from_interface)
Definition: lookup_dpo.c:651
#define LOOKUP_CASTS
Definition: lookup_dpo.h:57
format_function_t format_ip46_address
Definition: format.h:61
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
fib_node_index_t ip6_mfib_table_lookup2(const ip6_mfib_t *mfib, const ip6_address_t *src, const ip6_address_t *grp)
Data-plane lookup function.
Definition: ip6_mfib.c:409
#define LOOKUP_SUB_TYPE_NUM
Definition: lookup_dpo.c:41
static const char *const *const lookup_dst_mcast_nodes[DPO_PROTO_NUM]
Definition: lookup_dpo.c:1366
lookup_cast_t lkd_cast
Unicast of rmulticast FIB lookup.
Definition: lookup_dpo.h:92
static u32 ip6_fib_table_fwding_lookup(ip6_main_t *im, u32 fib_index, const ip6_address_t *dst)
Definition: ip6_fib.h:67
vlib_node_registration_t lookup_mpls_dst_itf_node
(constructor) VLIB_REGISTER_NODE (lookup_mpls_dst_itf_node)
Definition: lookup_dpo.c:1147
u8 * format_lookup_dpo(u8 *s, va_list *args)
Definition: lookup_dpo.c:179
u16 lkd_locks
Number of locks.
Definition: lookup_dpo.h:97
static uword vlib_buffer_length_in_chain(vlib_main_t *vm, vlib_buffer_t *b)
Get length in bytes of the buffer chain.
Definition: buffer_funcs.h:100
ip6_address_t src_address
Definition: ip6_packet.h:341
#define pool_len(p)
Number of elements in pool vector.
Definition: pool.h:121
static ip4_mfib_t * ip4_mfib_get(u32 index)
Get the FIB at the given index.
Definition: ip4_mfib.h:58
u32 ip4_fib_table_get_index_for_sw_if_index(u32 sw_if_index)
Definition: ip4_fib.c:221
void dpo_register(dpo_type_t type, const dpo_vft_t *vft, const char *const *const *nodes)
For a given DPO type Register:
Definition: dpo.c:260
enum dpo_type_t_ dpo_type_t
Common types of data-path objects New types can be dynamically added using dpo_register_new_type() ...
static const char *const lookup_dst_from_interface_ip6_nodes[]
Definition: lookup_dpo.c:1377
static lookup_dpo_t * lookup_dpo_alloc(void)
Definition: lookup_dpo.c:57
#define always_inline
Definition: clib.h:84
static uword format_get_indent(u8 *s)
Definition: format.h:72
u16 lb_n_buckets_minus_1
number of buckets in the load-balance - 1.
Definition: load_balance.h:93
ip4_address_t dst_address
Definition: ip4_packet.h:164
static uword lookup_ip6_src(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: lookup_dpo.c:960
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:113
static const char *const *const lookup_src_nodes[DPO_PROTO_NUM]
Definition: lookup_dpo.c:1327
dpo_proto_t lkd_proto
The protocol of the FIB for the lookup, and hence the protocol of the packet.
Definition: lookup_dpo.h:77
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:164
u32 ip4_fib_mtrie_leaf_t
Definition: ip4_mtrie.h:52
static void lookup_dpo_unlock(dpo_id_t *dpo)
Definition: lookup_dpo.c:226
#define MPLS_IS_REPLICATE
The top bit of the index, which is the result of the MPLS lookup is used to determine if the DPO is a...
Definition: mpls_types.h:58
u8 * format_mfib_table_name(u8 *s, va_list ap)
Format the description/name of the table.
Definition: mfib_table.c:518
ip46_address_t addr
Definition: lookup_dpo.c:303
void fib_show_memory_usage(const char *name, u32 in_use_elts, u32 allocd_elts, size_t size_elt)
Show the memory usage for a type.
Definition: fib_node.c:221
static uword lookup_ip4_dst_itf(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: lookup_dpo.c:617
enum dpo_proto_t_ dpo_proto_t
Data path protocol.
fib_protocol_t dpo_proto_to_fib(dpo_proto_t dpo_proto)
Definition: fib_types.c:227
enum lookup_cast_t_ lookup_cast_t
Switch to use the packet&#39;s source or destination address for lookup.
u32 ip6_fib_table_get_index_for_sw_if_index(u32 sw_if_index)
Definition: ip6_fib.c:353
dpo_type_t dpo_register_new_type(const dpo_vft_t *vft, const char *const *const *nodes)
Create and register a new DPO type.
Definition: dpo.c:272
static const char *const lookup_dst_mcast_ip4_nodes[]
Definition: lookup_dpo.c:1356
static u32 ip4_fib_mtrie_leaf_get_adj_index(ip4_fib_mtrie_leaf_t n)
From the stored slot value extract the LB index value.
Definition: ip4_mtrie.h:187
vlib_node_registration_t lookup_ip4_dst_node
(constructor) VLIB_REGISTER_NODE (lookup_ip4_dst_node)
Definition: lookup_dpo.c:607
static u32 mpls_fib_table_get_index_for_sw_if_index(u32 sw_if_index)
Definition: mpls_fib.h:129
vlib_node_registration_t lookup_ip6_src_node
(constructor) VLIB_REGISTER_NODE (lookup_ip6_src_node)
Definition: lookup_dpo.c:967
static void lookup_dpo_lock(dpo_id_t *dpo)
Definition: lookup_dpo.c:216
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:152
void fib_table_unlock(u32 fib_index, fib_protocol_t proto)
Take a reference counting lock on the table.
Definition: fib_table.c:1145
static lookup_dpo_t * lookup_dpo_get(index_t index)
Definition: lookup_dpo.h:121
static const dpo_id_t * load_balance_get_bucket_i(const load_balance_t *lb, u32 bucket)
Definition: load_balance.h:202
static u32 mpls_compute_flow_hash(const mpls_unicast_header_t *hdr, flow_hash_config_t flow_hash_config)
Definition: mpls_lookup.h:32
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:188
static u32 ip6_compute_flow_hash(const ip6_header_t *ip, flow_hash_config_t flow_hash_config)
Definition: ip6.h:391
mpls_unicast_header_t hdr
Definition: lookup_dpo.c:304
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:241
The FIB DPO provieds;.
Definition: load_balance.h:84
#define PREDICT_FALSE(x)
Definition: clib.h:97
static const char *const lookup_dst_mcast_ip6_nodes[]
Definition: lookup_dpo.c:1361
static void lookup_dpo_add_or_lock_i(fib_node_index_t fib_index, dpo_proto_t proto, lookup_cast_t cast, lookup_input_t input, lookup_table_t table_config, dpo_id_t *dpo)
Definition: lookup_dpo.c:73
void lookup_dpo_add_or_lock_w_fib_index(fib_node_index_t fib_index, dpo_proto_t proto, lookup_cast_t cast, lookup_input_t input, lookup_table_t table_config, dpo_id_t *dpo)
Definition: lookup_dpo.c:127
load_balance_main_t load_balance_main
The one instance of load-balance main.
Definition: load_balance.c:55
#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
void lookup_dpo_module_init(void)
Definition: lookup_dpo.c:1396
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
Definition: buffer_node.h:216
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:366
ip4_fib_mtrie_t mtrie
Mtrie for fast lookups.
Definition: ip4_fib.h:45
static const char *const lookup_src_ip6_nodes[]
Definition: lookup_dpo.c:1322
static const char *const lookup_dst_mpls_nodes[]
Definition: lookup_dpo.c:1344
#define pool_get_aligned(P, E, A)
Allocate an object E from a pool P (general version).
Definition: pool.h:169
vlib_node_registration_t lookup_ip6_dst_itf_node
(constructor) VLIB_REGISTER_NODE (lookup_ip6_dst_itf_node)
Definition: lookup_dpo.c:950
u32 mpls_lookup_to_replicate_edge
The arc/edge from the MPLS lookup node to the MPLS replicate node.
Definition: mpls_lookup.c:33
enum lookup_ip_dst_mcast_next_t_ mfib_forward_lookup_next_t
static void ip4_src_fib_lookup_two(u32 src_fib_index0, u32 src_fib_index1, const ip4_address_t *addr0, const ip4_address_t *addr1, u32 *src_adj_index0, u32 *src_adj_index1)
Definition: lookup_dpo.c:271
static const char *const lookup_dst_from_interface_mpls_nodes[]
Definition: lookup_dpo.c:1382
Lookup trace data.
Definition: lookup_dpo.c:300
u16 n_vectors
Definition: node.h:345
static_always_inline uword vlib_get_thread_index(void)
Definition: threads.h:185
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:82
static uword lookup_mpls_dst_itf(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: lookup_dpo.c:1140
enum lookup_table_t_ lookup_table_t
Switch to use the packet&#39;s source or destination address for lookup.
static ip4_fib_t * ip4_fib_get(u32 index)
Get the FIB at the given index.
Definition: ip4_fib.h:105
vlib_node_registration_t lookup_ip4_dst_mcast_node
(constructor) VLIB_REGISTER_NODE (lookup_ip4_dst_mcast_node)
Definition: lookup_dpo.c:1260
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:85
static const char *const lookup_input_names[]
Definition: lookup_dpo.c:28
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:28
static const char *const lookup_dst_ip6_nodes[]
Definition: lookup_dpo.c:1339
void dpo_set(dpo_id_t *dpo, dpo_type_t type, dpo_proto_t proto, index_t index)
Set/create a DPO ID The DPO will be locked.
Definition: dpo.c:159
vlib_node_registration_t lookup_mpls_dst_node
(constructor) VLIB_REGISTER_NODE (lookup_mpls_dst_node)
Definition: lookup_dpo.c:1129
enum lookup_input_t_ lookup_input_t
Switch to use the packet&#39;s source or destination address for lookup.
static const char *const lookup_dst_from_interface_ip4_nodes[]
Definition: lookup_dpo.c:1372
static uword lookup_ip6_dst(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: lookup_dpo.c:926
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:460
vlib_node_registration_t lookup_ip6_dst_node
(constructor) VLIB_REGISTER_NODE (lookup_ip6_dst_node)
Definition: lookup_dpo.c:933
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
static ip4_fib_mtrie_leaf_t ip4_fib_mtrie_lookup_step_one(const ip4_fib_mtrie_t *m, const ip4_address_t *dst_address)
Lookup step number 1.
Definition: ip4_mtrie.h:219
ip6_main_t ip6_main
Definition: ip6_forward.c:2926
static const char *const lookup_src_ip4_nodes[]
Definition: lookup_dpo.c:1317
static load_balance_t * load_balance_get(index_t lbi)
Definition: load_balance.h:193
static const char *const lookup_dst_ip4_nodes[]
Definition: lookup_dpo.c:1334
static uword lookup_dpo_ip4_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame, int input_src_addr, int table_from_interface)
Definition: lookup_dpo.c:312
vlib_node_registration_t lookup_ip6_dst_mcast_node
(constructor) VLIB_REGISTER_NODE (lookup_ip6_dst_mcast_node)
Definition: lookup_dpo.c:1282
fib_node_index_t ip4_mfib_table_lookup(const ip4_mfib_t *mfib, const ip4_address_t *src, const ip4_address_t *grp, u32 len)
The IPv4 Multicast-FIB.
Definition: ip4_mfib.c:188
mpls_label_t label_exp_s_ttl
Definition: packet.h:31
u32 fib_table_find_or_create_and_lock(fib_protocol_t proto, u32 table_id)
Get the index of the FIB for a Table-ID.
Definition: fib_table.c:1041
static const char *const *const lookup_dst_from_interface_nodes[DPO_PROTO_NUM]
Definition: lookup_dpo.c:1387
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:201
lookup_ip_dst_mcast_next_t_
Definition: lookup_dpo.c:1157
u32 flow_hash_config_t
A flow hash configuration is a mask of the flow hash options.
Definition: lookup.h:82
static uword is_pow2(uword x)
Definition: clib.h:272
u64 uword
Definition: types.h:112
lookup_table_t lkd_table
Switch to use the table index passed, or the table of the input interface.
Definition: lookup_dpo.h:87
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
Definition: defs.h:47
#define DPO_PROTO_NUM
Definition: dpo.h:73
u32 mfib_table_find_or_create_and_lock(fib_protocol_t proto, u32 table_id)
Get the index of the FIB for a Table-ID.
Definition: mfib_table.c:426
u8 * format_fib_table_name(u8 *s, va_list ap)
Format the description/name of the table.
Definition: fib_table.c:1181
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:168
#define FIB_NODE_INDEX_INVALID
Definition: fib_types.h:29
VLIB_NODE_FUNCTION_MULTIARCH(lookup_ip4_dst_mcast_node, lookup_ip4_dst_mcast)
Definition: lookup_dpo.c:1271
static u8 * format_lookup_mpls_trace(u8 *s, va_list *args)
Definition: lookup_dpo.c:1103
#define LOOKUP_INPUTS
Definition: lookup_dpo.h:31
unsigned char u8
Definition: types.h:56
void mfib_table_lock(u32 fib_index, fib_protocol_t proto)
Release a reference counting lock on the table.
Definition: mfib_table.c:489
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:269
A collection of combined counters.
Definition: counter.h:180
static index_t mpls_fib_table_forwarding_lookup(u32 mpls_fib_index, const mpls_unicast_header_t *hdr)
Lookup a label and EOS bit in the MPLS_FIB table to retrieve the load-balance index to be used for pa...
Definition: mpls_fib.h:113
u8 * format_dpo_proto(u8 *s, va_list *args)
format a DPO protocol
Definition: dpo.c:151
vlib_node_registration_t lookup_ip4_dst_itf_node
(constructor) VLIB_REGISTER_NODE (lookup_ip4_dst_itf_node)
Definition: lookup_dpo.c:624
static ip6_mfib_t * ip6_mfib_get(u32 index)
Get the FIB at the given index.
Definition: ip6_mfib.h:65
#define vnet_buffer(b)
Definition: buffer.h:304
static const char *const lookup_cast_names[]
Definition: lookup_dpo.c:29
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:144
u8 data[0]
Packet data.
Definition: buffer.h:152
static void ip4_src_fib_lookup_one(u32 src_fib_index0, const ip4_address_t *addr0, u32 *src_adj_index0)
Definition: lookup_dpo.c:254
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
Definition: dpo.c:205
vlib_node_registration_t lookup_ip4_src_node
(constructor) VLIB_REGISTER_NODE (lookup_ip4_src_node)
Definition: lookup_dpo.c:641
static index_t lookup_dpo_get_index(lookup_dpo_t *lkd)
Definition: lookup_dpo.c:67
static uword lookup_ip4_dst(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: lookup_dpo.c:600
u16 dpoi_next_node
The next VLIB node to follow.
Definition: dpo.h:164
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:74
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:57
fib_node_index_t lkd_fib_index
The FIB, or interface from which to get a FIB, in which to perform the next lookup;.
Definition: lookup_dpo.h:71
Definition: defs.h:46
static u8 * format_lookup_trace(u8 *s, va_list *args)
Definition: lookup_dpo.c:585
ip6_address_t dst_address
Definition: ip6_packet.h:341
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:109