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