FD.io VPP  v18.07-34-g55fbdb9
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  * If a packet encounters a lookup DPO more than the many times
33  * then we assume there is a loop in the forward graph and drop the packet
34  */
35 #define MAX_LUKPS_PER_PACKET 4
36 
37 /**
38  * @brief Enumeration of the lookup subtypes
39  */
40 typedef enum lookup_sub_type_t_
41 {
47 #define LOOKUP_SUB_TYPE_NUM (LOOKUP_SUB_TYPE_DST_TABLE_FROM_INTERFACE+1)
48 
49 #define FOR_EACH_LOOKUP_SUB_TYPE(_st) \
50  for (_st = LOOKUP_SUB_TYPE_IP4_SRC; _st < LOOKUP_SUB_TYPE_NUM; _st++)
51 
52 /**
53  * @brief pool of all MPLS Label DPOs
54  */
56 
57 /**
58  * @brief An array of registered DPO type values for the sub-types
59  */
61 
62 static lookup_dpo_t *
64 {
65  lookup_dpo_t *lkd;
66 
67  pool_get_aligned(lookup_dpo_pool, lkd, CLIB_CACHE_LINE_BYTES);
68 
69  return (lkd);
70 }
71 
72 static index_t
74 {
75  return (lkd - lookup_dpo_pool);
76 }
77 
78 static void
80  dpo_proto_t proto,
81  lookup_cast_t cast,
82  lookup_input_t input,
83  lookup_table_t table_config,
84  dpo_id_t *dpo)
85 {
86  lookup_dpo_t *lkd;
87  dpo_type_t type;
88 
89  lkd = lookup_dpo_alloc();
90  lkd->lkd_fib_index = fib_index;
91  lkd->lkd_proto = proto;
92  lkd->lkd_input = input;
93  lkd->lkd_table = table_config;
94  lkd->lkd_cast = cast;
95 
96  /*
97  * use the input type to select the lookup sub-type
98  */
99  type = 0;
100 
101  switch (input)
102  {
105  break;
107  switch (table_config)
108  {
111  break;
114  break;
115  }
116  if (LOOKUP_MULTICAST == cast)
117  {
119  }
120  }
121 
122  if (0 == type)
123  {
124  dpo_reset(dpo);
125  }
126  else
127  {
128  dpo_set(dpo, type, proto, lookup_dpo_get_index(lkd));
129  }
130 }
131 
132 void
134  dpo_proto_t proto,
135  lookup_cast_t cast,
136  lookup_input_t input,
137  lookup_table_t table_config,
138  dpo_id_t *dpo)
139 {
140  if (LOOKUP_TABLE_FROM_CONFIG == table_config)
141  {
142  if (LOOKUP_UNICAST == cast)
143  {
144  fib_table_lock(fib_index,
145  dpo_proto_to_fib(proto),
146  FIB_SOURCE_RR);
147  }
148  else
149  {
150  mfib_table_lock(fib_index,
151  dpo_proto_to_fib(proto),
153  }
154  }
155  lookup_dpo_add_or_lock_i(fib_index, proto, cast, input, table_config, dpo);
156 }
157 
158 void
160  dpo_proto_t proto,
161  lookup_cast_t cast,
162  lookup_input_t input,
163  lookup_table_t table_config,
164  dpo_id_t *dpo)
165 {
167 
168  if (LOOKUP_TABLE_FROM_CONFIG == table_config)
169  {
170  if (LOOKUP_UNICAST == cast)
171  {
172  fib_index =
174  table_id,
175  FIB_SOURCE_RR);
176  }
177  else
178  {
179  fib_index =
181  table_id,
183  }
184  }
185 
186  ASSERT(FIB_NODE_INDEX_INVALID != fib_index);
187  lookup_dpo_add_or_lock_i(fib_index, proto, cast, input, table_config, dpo);
188 }
189 
190 u8*
191 format_lookup_dpo (u8 *s, va_list *args)
192 {
193  index_t index = va_arg (*args, index_t);
194  lookup_dpo_t *lkd;
195 
196  lkd = lookup_dpo_get(index);
197 
199  {
200  s = format(s, "%s,%s lookup in interface's %U table",
204  }
205  else
206  {
207  if (LOOKUP_UNICAST == lkd->lkd_cast)
208  {
209  s = format(s, "%s,%s lookup in %U",
214  }
215  else
216  {
217  s = format(s, "%s,%s lookup in %U",
222  }
223  }
224  return (s);
225 }
226 
227 static void
229 {
230  lookup_dpo_t *lkd;
231 
232  lkd = lookup_dpo_get(dpo->dpoi_index);
233 
234  lkd->lkd_locks++;
235 }
236 
237 static void
239 {
240  lookup_dpo_t *lkd;
241 
242  lkd = lookup_dpo_get(dpo->dpoi_index);
243 
244  lkd->lkd_locks--;
245 
246  if (0 == lkd->lkd_locks)
247  {
249  {
250  if (LOOKUP_UNICAST == lkd->lkd_cast)
251  {
254  FIB_SOURCE_RR);
255  }
256  else
257  {
261  }
262  }
263  pool_put(lookup_dpo_pool, lkd);
264  }
265 }
266 
267 always_inline void
268 ip4_src_fib_lookup_one (u32 src_fib_index0,
269  const ip4_address_t * addr0,
270  u32 * src_adj_index0)
271 {
272  ip4_fib_mtrie_leaf_t leaf0;
273  ip4_fib_mtrie_t * mtrie0;
274 
275  mtrie0 = &ip4_fib_get (src_fib_index0)->mtrie;
276 
277  leaf0 = ip4_fib_mtrie_lookup_step_one (mtrie0, addr0);
278  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 2);
279  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 3);
280 
281  src_adj_index0[0] = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
282 }
283 
284 always_inline void
285 ip4_src_fib_lookup_two (u32 src_fib_index0,
286  u32 src_fib_index1,
287  const ip4_address_t * addr0,
288  const ip4_address_t * addr1,
289  u32 * src_adj_index0,
290  u32 * src_adj_index1)
291 {
292  ip4_fib_mtrie_leaf_t leaf0, leaf1;
293  ip4_fib_mtrie_t * mtrie0, * mtrie1;
294 
295  mtrie0 = &ip4_fib_get (src_fib_index0)->mtrie;
296  mtrie1 = &ip4_fib_get (src_fib_index1)->mtrie;
297 
298  leaf0 = ip4_fib_mtrie_lookup_step_one (mtrie0, addr0);
299  leaf1 = ip4_fib_mtrie_lookup_step_one (mtrie1, addr1);
300 
301  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 2);
302  leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 2);
303 
304  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 3);
305  leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 3);
306 
307  src_adj_index0[0] = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
308  src_adj_index1[0] = ip4_fib_mtrie_leaf_get_adj_index (leaf1);
309 }
310 
311 /**
312  * @brief Lookup trace data
313  */
314 typedef struct lookup_trace_t_
315 {
316  union {
317  ip46_address_t addr;
319  };
323 
324 
327  vlib_node_runtime_t * node,
328  vlib_frame_t * from_frame,
329  int input_src_addr,
330  int table_from_interface)
331 {
332  u32 n_left_from, next_index, * from, * to_next;
333  u32 thread_index = vlib_get_thread_index();
335 
336  from = vlib_frame_vector_args (from_frame);
337  n_left_from = from_frame->n_vectors;
338 
339  next_index = node->cached_next_index;
340 
341  while (n_left_from > 0)
342  {
343  u32 n_left_to_next;
344 
345  vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
346 
347  while (n_left_from >= 4 && n_left_to_next > 2)
348  {
349  u32 bi0, lkdi0, lbi0, fib_index0, next0, hash_c0;
350  flow_hash_config_t flow_hash_config0;
351  const ip4_address_t *input_addr0;
352  const load_balance_t *lb0;
353  const lookup_dpo_t * lkd0;
354  const ip4_header_t * ip0;
355  const dpo_id_t *dpo0;
356  vlib_buffer_t * b0;
357  u32 bi1, lkdi1, lbi1, fib_index1, next1, hash_c1;
358  flow_hash_config_t flow_hash_config1;
359  const ip4_address_t *input_addr1;
360  const load_balance_t *lb1;
361  const lookup_dpo_t * lkd1;
362  const ip4_header_t * ip1;
363  const dpo_id_t *dpo1;
364  vlib_buffer_t * b1;
365 
366  /* Prefetch next iteration. */
367  {
368  vlib_buffer_t * p2, * p3;
369 
370  p2 = vlib_get_buffer (vm, from[2]);
371  p3 = vlib_get_buffer (vm, from[3]);
372 
373  vlib_prefetch_buffer_header (p2, LOAD);
374  vlib_prefetch_buffer_header (p3, LOAD);
375 
378  }
379 
380  bi0 = from[0];
381  to_next[0] = bi0;
382  bi1 = from[1];
383  to_next[1] = bi1;
384  from += 2;
385  to_next += 2;
386  n_left_from -= 2;
387  n_left_to_next -= 2;
388 
389  b0 = vlib_get_buffer (vm, bi0);
390  ip0 = vlib_buffer_get_current (b0);
391  b1 = vlib_get_buffer (vm, bi1);
392  ip1 = vlib_buffer_get_current (b1);
393 
394  /* dst lookup was done by ip4 lookup */
395  lkdi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
396  lkdi1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
397  lkd0 = lookup_dpo_get(lkdi0);
398  lkd1 = lookup_dpo_get(lkdi1);
399 
400  /*
401  * choose between a lookup using the fib index in the DPO
402  * or getting the FIB index from the interface.
403  */
404  if (table_from_interface)
405  {
406  fib_index0 =
408  vnet_buffer(b0)->sw_if_index[VLIB_RX]);
409  fib_index1 =
411  vnet_buffer(b1)->sw_if_index[VLIB_RX]);
412  }
413  else
414  {
415  fib_index0 = lkd0->lkd_fib_index;
416  fib_index1 = lkd1->lkd_fib_index;
417  }
418 
419  /*
420  * choose between a source or destination address lookup in the table
421  */
422  if (input_src_addr)
423  {
424  input_addr0 = &ip0->src_address;
425  input_addr1 = &ip1->src_address;
426  }
427  else
428  {
429  input_addr0 = &ip0->dst_address;
430  input_addr1 = &ip1->dst_address;
431  }
432 
433  /* do lookup */
434  ip4_src_fib_lookup_two (fib_index0, fib_index1,
435  input_addr0, input_addr1,
436  &lbi0, &lbi1);
437  lb0 = load_balance_get(lbi0);
438  lb1 = load_balance_get(lbi1);
439 
440  vnet_buffer(b0)->sw_if_index[VLIB_TX] = fib_index0;
441  vnet_buffer(b1)->sw_if_index[VLIB_TX] = fib_index1;
442 
443  /* Use flow hash to compute multipath adjacency. */
444  hash_c0 = vnet_buffer (b0)->ip.flow_hash = 0;
445  hash_c1 = vnet_buffer (b1)->ip.flow_hash = 0;
446 
447  if (PREDICT_FALSE (lb0->lb_n_buckets > 1))
448  {
449  flow_hash_config0 = lb0->lb_hash_config;
450  hash_c0 = vnet_buffer (b0)->ip.flow_hash =
451  ip4_compute_flow_hash (ip0, flow_hash_config0);
452  }
453 
454  if (PREDICT_FALSE (lb1->lb_n_buckets > 1))
455  {
456  flow_hash_config1 = lb1->lb_hash_config;
457  hash_c1 = vnet_buffer (b1)->ip.flow_hash =
458  ip4_compute_flow_hash (ip1, flow_hash_config1);
459  }
460 
461  dpo0 = load_balance_get_bucket_i(lb0,
462  (hash_c0 &
463  (lb0->lb_n_buckets_minus_1)));
464  dpo1 = load_balance_get_bucket_i(lb1,
465  (hash_c1 &
466  (lb1->lb_n_buckets_minus_1)));
467 
468  next0 = dpo0->dpoi_next_node;
469  next1 = dpo1->dpoi_next_node;
470  vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
471  vnet_buffer(b1)->ip.adj_index[VLIB_TX] = dpo1->dpoi_index;
472 
474  (cm, thread_index, lbi0, 1,
475  vlib_buffer_length_in_chain (vm, b0));
477  (cm, thread_index, lbi1, 1,
478  vlib_buffer_length_in_chain (vm, b1));
479 
480  if (!(b0->flags & VNET_BUFFER_F_LOOP_COUNTER_VALID)) {
481  vnet_buffer2(b0)->loop_counter = 0;
482  b0->flags |= VNET_BUFFER_F_LOOP_COUNTER_VALID;
483  }
484  if (!(b1->flags & VNET_BUFFER_F_LOOP_COUNTER_VALID)) {
485  vnet_buffer2(b1)->loop_counter = 0;
486  b1->flags |= VNET_BUFFER_F_LOOP_COUNTER_VALID;
487  }
488 
489  vnet_buffer2(b0)->loop_counter++;
490  vnet_buffer2(b1)->loop_counter++;
491 
492  if (PREDICT_FALSE(vnet_buffer2(b0)->loop_counter > MAX_LUKPS_PER_PACKET))
493  next0 = IP_LOOKUP_NEXT_DROP;
494  if (PREDICT_FALSE(vnet_buffer2(b1)->loop_counter > MAX_LUKPS_PER_PACKET))
495  next1 = IP_LOOKUP_NEXT_DROP;
496 
497  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
498  {
499  lookup_trace_t *tr = vlib_add_trace (vm, node,
500  b0, sizeof (*tr));
501  tr->fib_index = fib_index0;
502  tr->lbi = lbi0;
503  tr->addr.ip4 = *input_addr0;
504  }
505  if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
506  {
507  lookup_trace_t *tr = vlib_add_trace (vm, node,
508  b1, sizeof (*tr));
509  tr->fib_index = fib_index1;
510  tr->lbi = lbi1;
511  tr->addr.ip4 = *input_addr1;
512  }
513 
514  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
515  to_next, n_left_to_next,
516  bi0, bi1, next0, next1);
517  }
518 
519  while (n_left_from > 0 && n_left_to_next > 0)
520  {
521  u32 bi0, lkdi0, lbi0, fib_index0, next0, hash_c0;
522  flow_hash_config_t flow_hash_config0;
523  const ip4_address_t *input_addr;
524  const load_balance_t *lb0;
525  const lookup_dpo_t * lkd0;
526  const ip4_header_t * ip0;
527  const dpo_id_t *dpo0;
528  vlib_buffer_t * b0;
529 
530  bi0 = from[0];
531  to_next[0] = bi0;
532  from += 1;
533  to_next += 1;
534  n_left_from -= 1;
535  n_left_to_next -= 1;
536 
537  b0 = vlib_get_buffer (vm, bi0);
538  ip0 = vlib_buffer_get_current (b0);
539 
540  /* dst lookup was done by ip4 lookup */
541  lkdi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
542  lkd0 = lookup_dpo_get(lkdi0);
543 
544  /*
545  * choose between a lookup using the fib index in the DPO
546  * or getting the FIB index from the interface.
547  */
548  if (table_from_interface)
549  {
550  fib_index0 =
552  vnet_buffer(b0)->sw_if_index[VLIB_RX]);
553  }
554  else
555  {
556  fib_index0 = lkd0->lkd_fib_index;
557  }
558 
559  /*
560  * choose between a source or destination address lookup in the table
561  */
562  if (input_src_addr)
563  {
564  input_addr = &ip0->src_address;
565  }
566  else
567  {
568  input_addr = &ip0->dst_address;
569  }
570 
571  /* do lookup */
572  ip4_src_fib_lookup_one (fib_index0, input_addr, &lbi0);
573  lb0 = load_balance_get(lbi0);
574 
575  vnet_buffer(b0)->sw_if_index[VLIB_TX] = fib_index0;
576 
577  /* Use flow hash to compute multipath adjacency. */
578  hash_c0 = vnet_buffer (b0)->ip.flow_hash = 0;
579 
580  if (PREDICT_FALSE (lb0->lb_n_buckets > 1))
581  {
582  flow_hash_config0 = lb0->lb_hash_config;
583  hash_c0 = vnet_buffer (b0)->ip.flow_hash =
584  ip4_compute_flow_hash (ip0, flow_hash_config0);
585  }
586 
587  dpo0 = load_balance_get_bucket_i(lb0,
588  (hash_c0 &
589  (lb0->lb_n_buckets_minus_1)));
590 
591  next0 = dpo0->dpoi_next_node;
592  vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
593 
595  (cm, thread_index, lbi0, 1,
596  vlib_buffer_length_in_chain (vm, b0));
597 
598  if (!(b0->flags & VNET_BUFFER_F_LOOP_COUNTER_VALID)) {
599  vnet_buffer2(b0)->loop_counter = 0;
600  b0->flags |= VNET_BUFFER_F_LOOP_COUNTER_VALID;
601  }
602 
603  vnet_buffer2(b0)->loop_counter++;
604 
605  if (PREDICT_FALSE(vnet_buffer2(b0)->loop_counter > MAX_LUKPS_PER_PACKET))
606  next0 = IP_LOOKUP_NEXT_DROP;
607 
608  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
609  {
610  lookup_trace_t *tr = vlib_add_trace (vm, node,
611  b0, sizeof (*tr));
612  tr->fib_index = fib_index0;
613  tr->lbi = lbi0;
614  tr->addr.ip4 = *input_addr;
615  }
616 
617  vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
618  n_left_to_next, bi0, next0);
619  }
620  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
621  }
622  return from_frame->n_vectors;
623 }
624 
625 static u8 *
626 format_lookup_trace (u8 * s, va_list * args)
627 {
628  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
629  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
630  lookup_trace_t * t = va_arg (*args, lookup_trace_t *);
631  u32 indent = format_get_indent (s);
632  s = format (s, "%U fib-index:%d addr:%U load-balance:%d",
633  format_white_space, indent,
634  t->fib_index,
636  t->lbi);
637  return s;
638 }
639 
640 static uword
642  vlib_node_runtime_t * node,
643  vlib_frame_t * from_frame)
644 {
645  return (lookup_dpo_ip4_inline(vm, node, from_frame, 0, 0));
646 }
647 
649  .function = lookup_ip4_dst,
650  .name = "lookup-ip4-dst",
651  .vector_size = sizeof (u32),
652  .sibling_of = "ip4-lookup",
653  .format_trace = format_lookup_trace,
654 };
656 
657 static uword
659  vlib_node_runtime_t * node,
660  vlib_frame_t * from_frame)
661 {
662  return (lookup_dpo_ip4_inline(vm, node, from_frame, 0, 1));
663 }
664 
666  .function = lookup_ip4_dst_itf,
667  .name = "lookup-ip4-dst-itf",
668  .vector_size = sizeof (u32),
669  .sibling_of = "ip4-lookup",
670  .format_trace = format_lookup_trace,
671 };
673 
674 static uword
676  vlib_node_runtime_t * node,
677  vlib_frame_t * from_frame)
678 {
679  return (lookup_dpo_ip4_inline(vm, node, from_frame, 1, 0));
680 }
681 
683  .function = lookup_ip4_src,
684  .name = "lookup-ip4-src",
685  .vector_size = sizeof (u32),
686  .format_trace = format_lookup_trace,
687  .sibling_of = "ip4-lookup",
688 };
690 
693  vlib_node_runtime_t * node,
694  vlib_frame_t * from_frame,
695  int input_src_addr,
696  int table_from_interface)
697 {
699  u32 n_left_from, next_index, * from, * to_next;
700  u32 thread_index = vlib_get_thread_index();
701 
702  from = vlib_frame_vector_args (from_frame);
703  n_left_from = from_frame->n_vectors;
704 
705  next_index = node->cached_next_index;
706 
707  while (n_left_from > 0)
708  {
709  u32 n_left_to_next;
710 
711  vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
712 
713  while (n_left_from >= 4 && n_left_to_next > 2)
714  {
715  u32 bi0, lkdi0, lbi0, fib_index0, next0, hash_c0;
716  flow_hash_config_t flow_hash_config0;
717  const ip6_address_t *input_addr0;
718  const load_balance_t *lb0;
719  const lookup_dpo_t * lkd0;
720  const ip6_header_t * ip0;
721  const dpo_id_t *dpo0;
722  vlib_buffer_t * b0;
723  u32 bi1, lkdi1, lbi1, fib_index1, next1, hash_c1;
724  flow_hash_config_t flow_hash_config1;
725  const ip6_address_t *input_addr1;
726  const load_balance_t *lb1;
727  const lookup_dpo_t * lkd1;
728  const ip6_header_t * ip1;
729  const dpo_id_t *dpo1;
730  vlib_buffer_t * b1;
731 
732  /* Prefetch next iteration. */
733  {
734  vlib_buffer_t * p2, * p3;
735 
736  p2 = vlib_get_buffer (vm, from[2]);
737  p3 = vlib_get_buffer (vm, from[3]);
738 
739  vlib_prefetch_buffer_header (p2, LOAD);
740  vlib_prefetch_buffer_header (p3, LOAD);
741 
744  }
745 
746  bi0 = from[0];
747  to_next[0] = bi0;
748  bi1 = from[1];
749  to_next[1] = bi1;
750  from += 2;
751  to_next += 2;
752  n_left_from -= 2;
753  n_left_to_next -= 2;
754 
755  b0 = vlib_get_buffer (vm, bi0);
756  ip0 = vlib_buffer_get_current (b0);
757  b1 = vlib_get_buffer (vm, bi1);
758  ip1 = vlib_buffer_get_current (b1);
759 
760  /* dst lookup was done by ip6 lookup */
761  lkdi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
762  lkdi1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
763  lkd0 = lookup_dpo_get(lkdi0);
764  lkd1 = lookup_dpo_get(lkdi1);
765 
766  /*
767  * choose between a lookup using the fib index in the DPO
768  * or getting the FIB index from the interface.
769  */
770  if (table_from_interface)
771  {
772  fib_index0 =
774  vnet_buffer(b0)->sw_if_index[VLIB_RX]);
775  fib_index1 =
777  vnet_buffer(b1)->sw_if_index[VLIB_RX]);
778  }
779  else
780  {
781  fib_index0 = lkd0->lkd_fib_index;
782  fib_index1 = lkd1->lkd_fib_index;
783  }
784 
785  /*
786  * choose between a source or destination address lookup in the table
787  */
788  if (input_src_addr)
789  {
790  input_addr0 = &ip0->src_address;
791  input_addr1 = &ip1->src_address;
792  }
793  else
794  {
795  input_addr0 = &ip0->dst_address;
796  input_addr1 = &ip1->dst_address;
797  }
798 
799  /* do src lookup */
801  fib_index0,
802  input_addr0);
804  fib_index1,
805  input_addr1);
806  lb0 = load_balance_get(lbi0);
807  lb1 = load_balance_get(lbi1);
808 
809  vnet_buffer(b0)->sw_if_index[VLIB_TX] = fib_index0;
810  vnet_buffer(b1)->sw_if_index[VLIB_TX] = fib_index1;
811 
812  /* Use flow hash to compute multipath adjacency. */
813  hash_c0 = vnet_buffer (b0)->ip.flow_hash = 0;
814  hash_c1 = vnet_buffer (b1)->ip.flow_hash = 0;
815 
816  if (!(b0->flags & VNET_BUFFER_F_LOOP_COUNTER_VALID)) {
817  vnet_buffer2(b0)->loop_counter = 0;
818  b0->flags |= VNET_BUFFER_F_LOOP_COUNTER_VALID;
819  }
820  if (!(b1->flags & VNET_BUFFER_F_LOOP_COUNTER_VALID)) {
821  vnet_buffer2(b1)->loop_counter = 0;
822  b1->flags |= VNET_BUFFER_F_LOOP_COUNTER_VALID;
823  }
824 
825  vnet_buffer2(b0)->loop_counter++;
826  vnet_buffer2(b1)->loop_counter++;
827 
828  if (PREDICT_FALSE(vnet_buffer2(b0)->loop_counter > MAX_LUKPS_PER_PACKET))
829  next0 = IP_LOOKUP_NEXT_DROP;
830  if (PREDICT_FALSE(vnet_buffer2(b1)->loop_counter > MAX_LUKPS_PER_PACKET))
831  next1 = IP_LOOKUP_NEXT_DROP;
832 
833  if (PREDICT_FALSE (lb0->lb_n_buckets > 1))
834  {
835  flow_hash_config0 = lb0->lb_hash_config;
836  hash_c0 = vnet_buffer (b0)->ip.flow_hash =
837  ip6_compute_flow_hash (ip0, flow_hash_config0);
838  }
839 
840  if (PREDICT_FALSE (lb1->lb_n_buckets > 1))
841  {
842  flow_hash_config1 = lb1->lb_hash_config;
843  hash_c1 = vnet_buffer (b1)->ip.flow_hash =
844  ip6_compute_flow_hash (ip1, flow_hash_config1);
845  }
846 
847  dpo0 = load_balance_get_bucket_i(lb0,
848  (hash_c0 &
849  (lb0->lb_n_buckets_minus_1)));
850  dpo1 = load_balance_get_bucket_i(lb1,
851  (hash_c1 &
852  (lb1->lb_n_buckets_minus_1)));
853 
854  next0 = dpo0->dpoi_next_node;
855  next1 = dpo1->dpoi_next_node;
856  vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
857  vnet_buffer(b1)->ip.adj_index[VLIB_TX] = dpo1->dpoi_index;
858 
860  (cm, thread_index, lbi0, 1,
861  vlib_buffer_length_in_chain (vm, b0));
863  (cm, thread_index, lbi1, 1,
864  vlib_buffer_length_in_chain (vm, b1));
865 
866  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
867  {
868  lookup_trace_t *tr = vlib_add_trace (vm, node,
869  b0, sizeof (*tr));
870  tr->fib_index = fib_index0;
871  tr->lbi = lbi0;
872  tr->addr.ip6 = *input_addr0;
873  }
874  if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
875  {
876  lookup_trace_t *tr = vlib_add_trace (vm, node,
877  b1, sizeof (*tr));
878  tr->fib_index = fib_index1;
879  tr->lbi = lbi1;
880  tr->addr.ip6 = *input_addr1;
881  }
882  vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next,
883  n_left_to_next, bi0, bi1,
884  next0, next1);
885  }
886  while (n_left_from > 0 && n_left_to_next > 0)
887  {
888  u32 bi0, lkdi0, lbi0, fib_index0, next0, hash_c0;
889  flow_hash_config_t flow_hash_config0;
890  const ip6_address_t *input_addr0;
891  const load_balance_t *lb0;
892  const lookup_dpo_t * lkd0;
893  const ip6_header_t * ip0;
894  const dpo_id_t *dpo0;
895  vlib_buffer_t * b0;
896 
897  bi0 = from[0];
898  to_next[0] = bi0;
899  from += 1;
900  to_next += 1;
901  n_left_from -= 1;
902  n_left_to_next -= 1;
903 
904  b0 = vlib_get_buffer (vm, bi0);
905  ip0 = vlib_buffer_get_current (b0);
906 
907  /* dst lookup was done by ip6 lookup */
908  lkdi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
909  lkd0 = lookup_dpo_get(lkdi0);
910 
911  /*
912  * choose between a lookup using the fib index in the DPO
913  * or getting the FIB index from the interface.
914  */
915  if (table_from_interface)
916  {
917  fib_index0 =
919  vnet_buffer(b0)->sw_if_index[VLIB_RX]);
920  }
921  else
922  {
923  fib_index0 = lkd0->lkd_fib_index;
924  }
925 
926  /*
927  * choose between a source or destination address lookup in the table
928  */
929  if (input_src_addr)
930  {
931  input_addr0 = &ip0->src_address;
932  }
933  else
934  {
935  input_addr0 = &ip0->dst_address;
936  }
937 
938  /* do src lookup */
940  fib_index0,
941  input_addr0);
942  lb0 = load_balance_get(lbi0);
943 
944  vnet_buffer(b0)->sw_if_index[VLIB_TX] = fib_index0;
945 
946  /* Use flow hash to compute multipath adjacency. */
947  hash_c0 = vnet_buffer (b0)->ip.flow_hash = 0;
948 
949  if (PREDICT_FALSE (lb0->lb_n_buckets > 1))
950  {
951  flow_hash_config0 = lb0->lb_hash_config;
952  hash_c0 = vnet_buffer (b0)->ip.flow_hash =
953  ip6_compute_flow_hash (ip0, flow_hash_config0);
954  }
955 
956  dpo0 = load_balance_get_bucket_i(lb0,
957  (hash_c0 &
958  (lb0->lb_n_buckets_minus_1)));
959 
960  next0 = dpo0->dpoi_next_node;
961  vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
962 
963  if (!(b0->flags & VNET_BUFFER_F_LOOP_COUNTER_VALID)) {
964  vnet_buffer2(b0)->loop_counter = 0;
965  b0->flags |= VNET_BUFFER_F_LOOP_COUNTER_VALID;
966  }
967 
968  vnet_buffer2(b0)->loop_counter++;
969 
970  if (PREDICT_FALSE(vnet_buffer2(b0)->loop_counter > MAX_LUKPS_PER_PACKET))
971  next0 = IP_LOOKUP_NEXT_DROP;
972 
974  (cm, thread_index, lbi0, 1,
975  vlib_buffer_length_in_chain (vm, b0));
976 
977  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
978  {
979  lookup_trace_t *tr = vlib_add_trace (vm, node,
980  b0, sizeof (*tr));
981  tr->fib_index = fib_index0;
982  tr->lbi = lbi0;
983  tr->addr.ip6 = *input_addr0;
984  }
985  vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
986  n_left_to_next, bi0, next0);
987  }
988  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
989  }
990  return from_frame->n_vectors;
991 }
992 
993 static uword
995  vlib_node_runtime_t * node,
996  vlib_frame_t * from_frame)
997 {
998  return (lookup_dpo_ip6_inline(vm, node, from_frame, 0 /*use src*/, 0));
999 }
1000 
1002  .function = lookup_ip6_dst,
1003  .name = "lookup-ip6-dst",
1004  .vector_size = sizeof (u32),
1005  .format_trace = format_lookup_trace,
1006  .sibling_of = "ip6-lookup",
1007 };
1009 
1010 static uword
1012  vlib_node_runtime_t * node,
1013  vlib_frame_t * from_frame)
1014 {
1015  return (lookup_dpo_ip6_inline(vm, node, from_frame, 0 /*use src*/, 1));
1016 }
1017 
1019  .function = lookup_ip6_dst_itf,
1020  .name = "lookup-ip6-dst-itf",
1021  .vector_size = sizeof (u32),
1022  .format_trace = format_lookup_trace,
1023  .sibling_of = "ip6-lookup",
1024 };
1026 
1027 static uword
1029  vlib_node_runtime_t * node,
1030  vlib_frame_t * from_frame)
1031 {
1032  return (lookup_dpo_ip6_inline(vm, node, from_frame, 1, 0));
1033 }
1034 
1036  .function = lookup_ip6_src,
1037  .name = "lookup-ip6-src",
1038  .vector_size = sizeof (u32),
1039  .format_trace = format_lookup_trace,
1040  .sibling_of = "ip6-lookup",
1041 };
1043 
1046  vlib_node_runtime_t * node,
1047  vlib_frame_t * from_frame,
1048  int table_from_interface)
1049 {
1050  u32 n_left_from, next_index, * from, * to_next;
1051  u32 thread_index = vlib_get_thread_index();
1053 
1054  from = vlib_frame_vector_args (from_frame);
1055  n_left_from = from_frame->n_vectors;
1056 
1057  next_index = node->cached_next_index;
1058 
1059  while (n_left_from > 0)
1060  {
1061  u32 n_left_to_next;
1062 
1063  vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
1064 
1065  /* while (n_left_from >= 4 && n_left_to_next >= 2) */
1066  /* } */
1067 
1068  while (n_left_from > 0 && n_left_to_next > 0)
1069  {
1070  u32 bi0, lkdi0, lbi0, fib_index0, next0, hash0;
1071  const mpls_unicast_header_t * hdr0;
1072  const load_balance_t *lb0;
1073  const lookup_dpo_t * lkd0;
1074  const dpo_id_t *dpo0;
1075  vlib_buffer_t * b0;
1076 
1077  bi0 = from[0];
1078  to_next[0] = bi0;
1079  from += 1;
1080  to_next += 1;
1081  n_left_from -= 1;
1082  n_left_to_next -= 1;
1083 
1084  b0 = vlib_get_buffer (vm, bi0);
1085  hdr0 = vlib_buffer_get_current (b0);
1086 
1087  /* dst lookup was done by mpls lookup */
1088  lkdi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
1089  lkd0 = lookup_dpo_get(lkdi0);
1090 
1091  /*
1092  * choose between a lookup using the fib index in the DPO
1093  * or getting the FIB index from the interface.
1094  */
1095  if (table_from_interface)
1096  {
1097  fib_index0 =
1099  vnet_buffer(b0)->sw_if_index[VLIB_RX]);
1100  }
1101  else
1102  {
1103  fib_index0 = lkd0->lkd_fib_index;
1104  }
1105 
1106  /* do lookup */
1107  lbi0 = mpls_fib_table_forwarding_lookup (fib_index0, hdr0);
1108  lb0 = load_balance_get(lbi0);
1109  dpo0 = load_balance_get_bucket_i(lb0, 0);
1110 
1111  next0 = dpo0->dpoi_next_node;
1112  vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
1113 
1114 
1115  if (MPLS_IS_REPLICATE & lbi0)
1116  {
1118  vnet_buffer (b0)->ip.adj_index[VLIB_TX] =
1119  (lbi0 & ~MPLS_IS_REPLICATE);
1120  }
1121  else
1122  {
1123  lb0 = load_balance_get(lbi0);
1124  ASSERT (lb0->lb_n_buckets > 0);
1125  ASSERT (is_pow2 (lb0->lb_n_buckets));
1126 
1127  if (PREDICT_FALSE(lb0->lb_n_buckets > 1))
1128  {
1129  hash0 = vnet_buffer (b0)->ip.flow_hash =
1132  (lb0,
1133  (hash0 & (lb0->lb_n_buckets_minus_1)));
1134  }
1135  else
1136  {
1137  dpo0 = load_balance_get_bucket_i (lb0, 0);
1138  }
1139  next0 = dpo0->dpoi_next_node;
1140 
1141  vnet_buffer (b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
1142 
1144  (cm, thread_index, lbi0, 1,
1145  vlib_buffer_length_in_chain (vm, b0));
1146  }
1147 
1148  vnet_buffer (b0)->mpls.ttl = ((char*)hdr0)[3];
1149  vnet_buffer (b0)->mpls.exp = (((char*)hdr0)[2] & 0xe) >> 1;
1150  vnet_buffer (b0)->mpls.first = 1;
1151  vlib_buffer_advance(b0, sizeof(*hdr0));
1152 
1153  if (!(b0->flags & VNET_BUFFER_F_LOOP_COUNTER_VALID)) {
1154  vnet_buffer2(b0)->loop_counter = 0;
1155  b0->flags |= VNET_BUFFER_F_LOOP_COUNTER_VALID;
1156  }
1157 
1158  vnet_buffer2(b0)->loop_counter++;
1159 
1160  if (PREDICT_FALSE(vnet_buffer2(b0)->loop_counter > MAX_LUKPS_PER_PACKET))
1161  next0 = MPLS_LOOKUP_NEXT_DROP;
1162 
1163  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
1164  {
1165  lookup_trace_t *tr = vlib_add_trace (vm, node,
1166  b0, sizeof (*tr));
1167  tr->fib_index = fib_index0;
1168  tr->lbi = lbi0;
1169  tr->hdr = *hdr0;
1170  }
1171 
1172  vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
1173  n_left_to_next, bi0, next0);
1174  }
1175  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1176  }
1177  return from_frame->n_vectors;
1178 }
1179 
1180 static u8 *
1181 format_lookup_mpls_trace (u8 * s, va_list * args)
1182 {
1183  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
1184  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
1185  lookup_trace_t * t = va_arg (*args, lookup_trace_t *);
1186  u32 indent = format_get_indent (s);
1188 
1189  hdr.label_exp_s_ttl = clib_net_to_host_u32(t->hdr.label_exp_s_ttl);
1190 
1191  s = format (s, "%U fib-index:%d hdr:%U load-balance:%d",
1192  format_white_space, indent,
1193  t->fib_index,
1194  format_mpls_header, hdr,
1195  t->lbi);
1196  return s;
1197 }
1198 
1199 static uword
1201  vlib_node_runtime_t * node,
1202  vlib_frame_t * from_frame)
1203 {
1204  return (lookup_dpo_mpls_inline(vm, node, from_frame, 0));
1205 }
1206 
1208  .function = lookup_mpls_dst,
1209  .name = "lookup-mpls-dst",
1210  .vector_size = sizeof (u32),
1211  .sibling_of = "mpls-lookup",
1212  .format_trace = format_lookup_mpls_trace,
1213  .n_next_nodes = 0,
1214 };
1216 
1217 static uword
1219  vlib_node_runtime_t * node,
1220  vlib_frame_t * from_frame)
1221 {
1222  return (lookup_dpo_mpls_inline(vm, node, from_frame, 1));
1223 }
1224 
1226  .function = lookup_mpls_dst_itf,
1227  .name = "lookup-mpls-dst-itf",
1228  .vector_size = sizeof (u32),
1229  .sibling_of = "mpls-lookup",
1230  .format_trace = format_lookup_mpls_trace,
1231  .n_next_nodes = 0,
1232 };
1234 
1240 
1243  vlib_node_runtime_t * node,
1244  vlib_frame_t * from_frame,
1245  int is_v4)
1246 {
1247  u32 n_left_from, next_index, * from, * to_next;
1248 
1249  from = vlib_frame_vector_args (from_frame);
1250  n_left_from = from_frame->n_vectors;
1251 
1252  next_index = LOOKUP_IP_DST_MCAST_NEXT_RPF;
1253 
1254  while (n_left_from > 0)
1255  {
1256  u32 n_left_to_next;
1257 
1258  vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
1259 
1260  /* while (n_left_from >= 4 && n_left_to_next >= 2) */
1261  /* } */
1262 
1263  while (n_left_from > 0 && n_left_to_next > 0)
1264  {
1265  u32 bi0, lkdi0, fib_index0, next0;
1266  const lookup_dpo_t * lkd0;
1267  fib_node_index_t mfei0;
1268  vlib_buffer_t * b0;
1269 
1270  bi0 = from[0];
1271  to_next[0] = bi0;
1272  from += 1;
1273  to_next += 1;
1274  n_left_from -= 1;
1275  n_left_to_next -= 1;
1276 
1277  b0 = vlib_get_buffer (vm, bi0);
1278 
1279  /* dst lookup was done by mpls lookup */
1280  lkdi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
1281  lkd0 = lookup_dpo_get(lkdi0);
1282  fib_index0 = lkd0->lkd_fib_index;
1284 
1285  if (is_v4)
1286  {
1287  ip4_header_t * ip0;
1288 
1289  ip0 = vlib_buffer_get_current (b0);
1290  mfei0 = ip4_mfib_table_lookup(ip4_mfib_get(fib_index0),
1291  &ip0->src_address,
1292  &ip0->dst_address,
1293  64);
1294  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
1295  {
1296  lookup_trace_t *tr = vlib_add_trace (vm, node,
1297  b0, sizeof (*tr));
1298  tr->fib_index = fib_index0;
1299  tr->lbi = mfei0;
1300  tr->addr.ip4 = ip0->dst_address;
1301  }
1302  }
1303  else
1304  {
1305  ip6_header_t * ip0;
1306 
1307  ip0 = vlib_buffer_get_current (b0);
1308  mfei0 = ip6_mfib_table_lookup2(ip6_mfib_get(fib_index0),
1309  &ip0->src_address,
1310  &ip0->dst_address);
1311  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
1312  {
1313  lookup_trace_t *tr = vlib_add_trace (vm, node,
1314  b0, sizeof (*tr));
1315  tr->fib_index = fib_index0;
1316  tr->lbi = mfei0;
1317  tr->addr.ip6 = ip0->dst_address;
1318  }
1319  }
1320 
1321  vnet_buffer (b0)->ip.adj_index[VLIB_TX] = mfei0;
1322 
1323  if (!(b0->flags & VNET_BUFFER_F_LOOP_COUNTER_VALID)) {
1324  vnet_buffer2(b0)->loop_counter = 0;
1325  b0->flags |= VNET_BUFFER_F_LOOP_COUNTER_VALID;
1326  }
1327 
1328  vnet_buffer2(b0)->loop_counter++;
1329 
1330  if (PREDICT_FALSE(vnet_buffer2(b0)->loop_counter > MAX_LUKPS_PER_PACKET))
1332 
1333  vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
1334  n_left_to_next, bi0, next0);
1335  }
1336  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1337  }
1338  return from_frame->n_vectors;
1339 }
1340 
1341 static uword
1343  vlib_node_runtime_t * node,
1344  vlib_frame_t * from_frame)
1345 {
1346  return (lookup_dpo_ip_dst_mcast_inline(vm, node, from_frame, 1));
1347 }
1348 
1350  .function = lookup_ip4_dst_mcast,
1351  .name = "lookup-ip4-dst-mcast",
1352  .vector_size = sizeof (u32),
1353 
1354  .format_trace = format_lookup_trace,
1355  .n_next_nodes = LOOKUP_IP_DST_MCAST_N_NEXT,
1356  .next_nodes = {
1357  [LOOKUP_IP_DST_MCAST_NEXT_DROP] = "ip4-drop",
1358  [LOOKUP_IP_DST_MCAST_NEXT_RPF] = "ip4-mfib-forward-rpf",
1359  },
1360 };
1363 
1364 static uword
1365 lookup_ip6_dst_mcast (vlib_main_t * vm,
1366  vlib_node_runtime_t * node,
1367  vlib_frame_t * from_frame)
1368 {
1369  return (lookup_dpo_ip_dst_mcast_inline(vm, node, from_frame, 0));
1370 }
1371 
1373  .function = lookup_ip6_dst_mcast,
1374  .name = "lookup-ip6-dst-mcast",
1375  .vector_size = sizeof (u32),
1376 
1377  .format_trace = format_lookup_trace,
1378  .n_next_nodes = LOOKUP_IP_DST_MCAST_N_NEXT,
1379  .next_nodes = {
1380  [LOOKUP_IP_DST_MCAST_NEXT_DROP] = "ip6-drop",
1381  [LOOKUP_IP_DST_MCAST_NEXT_RPF] = "ip6-mfib-forward-rpf",
1382  },
1383 };
1385  lookup_ip6_dst_mcast)
1386 
1387 static void
1388 lookup_dpo_mem_show (void)
1389 {
1390  fib_show_memory_usage("Lookup",
1391  pool_elts(lookup_dpo_pool),
1392  pool_len(lookup_dpo_pool),
1393  sizeof(lookup_dpo_t));
1394 }
1395 
1396 const static dpo_vft_t lkd_vft = {
1398  .dv_unlock = lookup_dpo_unlock,
1399  .dv_format = format_lookup_dpo,
1400 };
1401 const static dpo_vft_t lkd_vft_w_mem_show = {
1403  .dv_unlock = lookup_dpo_unlock,
1404  .dv_format = format_lookup_dpo,
1405  .dv_mem_show = lookup_dpo_mem_show,
1406 };
1407 
1408 const static char* const lookup_src_ip4_nodes[] =
1409 {
1410  "lookup-ip4-src",
1411  NULL,
1412 };
1413 const static char* const lookup_src_ip6_nodes[] =
1414 {
1415  "lookup-ip6-src",
1416  NULL,
1417 };
1418 const static char* const * const lookup_src_nodes[DPO_PROTO_NUM] =
1419 {
1422  [DPO_PROTO_MPLS] = NULL,
1423 };
1424 
1425 const static char* const lookup_dst_ip4_nodes[] =
1426 {
1427  "lookup-ip4-dst",
1428  NULL,
1429 };
1430 const static char* const lookup_dst_ip6_nodes[] =
1431 {
1432  "lookup-ip6-dst",
1433  NULL,
1434 };
1435 const static char* const lookup_dst_mpls_nodes[] =
1436 {
1437  "lookup-mpls-dst",
1438  NULL,
1439 };
1440 const static char* const * const lookup_dst_nodes[DPO_PROTO_NUM] =
1441 {
1445 };
1446 
1447 const static char* const lookup_dst_mcast_ip4_nodes[] =
1448 {
1449  "lookup-ip4-dst-mcast",
1450  NULL,
1451 };
1452 const static char* const lookup_dst_mcast_ip6_nodes[] =
1453 {
1454  "lookup-ip6-dst-mcast",
1455  NULL,
1456 };
1457 const static char* const * const lookup_dst_mcast_nodes[DPO_PROTO_NUM] =
1458 {
1461 };
1462 
1463 const static char* const lookup_dst_from_interface_ip4_nodes[] =
1464 {
1465  "lookup-ip4-dst-itf",
1466  NULL,
1467 };
1468 const static char* const lookup_dst_from_interface_ip6_nodes[] =
1469 {
1470  "lookup-ip6-dst-itf",
1471  NULL,
1472 };
1473 const static char* const lookup_dst_from_interface_mpls_nodes[] =
1474 {
1475  "lookup-mpls-dst-itf",
1476  NULL,
1477 };
1478 const static char* const * const lookup_dst_from_interface_nodes[DPO_PROTO_NUM] =
1479 {
1483 };
1484 
1485 
1486 void
1488 {
1489  dpo_register(DPO_LOOKUP, &lkd_vft_w_mem_show, NULL);
1490 
1491  /*
1492  * There are various sorts of lookup; src or dst addr v4 /v6 etc.
1493  * there isn't an object type for each (there is only the lookup_dpo_t),
1494  * but, for performance reasons, there is a data plane function, and hence
1495  * VLIB node for each. VLIB graph node construction is based on DPO types
1496  * so we create sub-types.
1497  */
1506 }
static uword lookup_ip6_dst_itf(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: lookup_dpo.c:1011
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:1242
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:55
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:125
static uword lookup_ip4_src(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: lookup_dpo.c:675
#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:159
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:1045
enum lookup_sub_type_t_ lookup_sub_type_t
Enumeration of the lookup subtypes.
fib_node_index_t fib_index
Definition: lookup_dpo.c:320
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:40
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:1342
#define vnet_buffer2(b)
Definition: buffer.h:403
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:1440
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:60
#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:1200
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:692
#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:47
static const char *const *const lookup_dst_mcast_nodes[DPO_PROTO_NUM]
Definition: lookup_dpo.c:1457
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:1225
u8 * format_lookup_dpo(u8 *s, va_list *args)
Definition: lookup_dpo.c:191
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:224
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:1468
static lookup_dpo_t * lookup_dpo_alloc(void)
Definition: lookup_dpo.c:63
#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:1028
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:1418
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:238
#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:317
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:658
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:253
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:1447
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:648
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:1035
static void lookup_dpo_lock(dpo_id_t *dpo)
Definition: lookup_dpo.c:228
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:40
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:318
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:274
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:1452
#define MAX_LUKPS_PER_PACKET
If a packet encounters a lookup DPO more than the many times then we assume there is a loop in the fo...
Definition: lookup_dpo.c:35
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:79
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:133
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:1487
#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:48
static const char *const lookup_src_ip6_nodes[]
Definition: lookup_dpo.c:1413
static const char *const lookup_dst_mpls_nodes[]
Definition: lookup_dpo.c:1435
#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:1018
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:285
static const char *const lookup_dst_from_interface_mpls_nodes[]
Definition: lookup_dpo.c:1473
Adjacency to drop this packet.
Definition: adj.h:53
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:153
Lookup trace data.
Definition: lookup_dpo.c:314
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:1218
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:113
vlib_node_registration_t lookup_ip4_dst_mcast_node
(constructor) VLIB_REGISTER_NODE (lookup_ip4_dst_mcast_node)
Definition: lookup_dpo.c:1349
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:1430
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:1207
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:1463
static uword lookup_ip6_dst(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: lookup_dpo.c:994
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:1001
#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:1408
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:1425
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:326
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:1372
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:1478
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:1235
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:1361
static u8 * format_lookup_mpls_trace(u8 *s, va_list *args)
Definition: lookup_dpo.c:1181
#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:665
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:268
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:682
static index_t lookup_dpo_get_index(lookup_dpo_t *lkd)
Definition: lookup_dpo.c:73
static uword lookup_ip4_dst(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: lookup_dpo.c:641
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:626
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