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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 #include <vnet/ip/ip.h>
17 #include <vnet/dpo/lookup_dpo.h>
18 #include <vnet/dpo/load_balance.h>
19 #include <vnet/mpls/mpls.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>
25 static const char *const lookup_input_names[] = LOOKUP_INPUTS;
28 * @brief Enumeration of the lookup subtypes
30 typedef enum lookup_sub_type_t_
34 LOOKUP_SUB_TYPE_DST_TABLE_FROM_INTERFACE,
36 #define LOOKUP_SUB_TYPE_NUM (LOOKUP_SUB_TYPE_DST_TABLE_FROM_INTERFACE+1)
38 #define FOR_EACH_LOOKUP_SUB_TYPE(_st) \
39 for (_st = LOOKUP_SUB_TYPE_IP4_SRC; _st < LOOKUP_SUB_TYPE_NUM; _st++)
42 * @brief pool of all MPLS Label DPOs
44 lookup_dpo_t *lookup_dpo_pool;
47 * @brief An array of registered DPO type values for the sub-types
49 static dpo_type_t lookup_dpo_sub_types[LOOKUP_SUB_TYPE_NUM];
52 lookup_dpo_alloc (void)
56 pool_get_aligned(lookup_dpo_pool, lkd, CLIB_CACHE_LINE_BYTES);
62 lookup_dpo_get_index (lookup_dpo_t *lkd)
64 return (lkd - lookup_dpo_pool);
68 lookup_dpo_add_or_lock_i (fib_node_index_t fib_index,
71 lookup_table_t table_config,
77 lkd = lookup_dpo_alloc();
78 lkd->lkd_fib_index = fib_index;
79 lkd->lkd_proto = proto;
80 lkd->lkd_input = input;
81 lkd->lkd_table = table_config;
84 * use the input type to select the lookup sub-type
90 case LOOKUP_INPUT_SRC_ADDR:
91 type = lookup_dpo_sub_types[LOOKUP_SUB_TYPE_SRC];
93 case LOOKUP_INPUT_DST_ADDR:
96 case LOOKUP_TABLE_FROM_INPUT_INTERFACE:
97 type = lookup_dpo_sub_types[LOOKUP_SUB_TYPE_DST_TABLE_FROM_INTERFACE];
99 case LOOKUP_TABLE_FROM_CONFIG:
100 type = lookup_dpo_sub_types[LOOKUP_SUB_TYPE_DST];
111 dpo_set(dpo, type, proto, lookup_dpo_get_index(lkd));
116 lookup_dpo_add_or_lock_w_fib_index (fib_node_index_t fib_index,
118 lookup_input_t input,
119 lookup_table_t table_config,
122 if (LOOKUP_TABLE_FROM_CONFIG == table_config)
124 fib_table_lock(fib_index, dpo_proto_to_fib(proto));
126 lookup_dpo_add_or_lock_i(fib_index, proto, input, table_config, dpo);
130 lookup_dpo_add_or_lock_w_table_id (u32 table_id,
132 lookup_input_t input,
133 lookup_table_t table_config,
136 fib_node_index_t fib_index = FIB_NODE_INDEX_INVALID;
138 if (LOOKUP_TABLE_FROM_CONFIG == table_config)
141 fib_table_find_or_create_and_lock(dpo_proto_to_fib(proto),
145 ASSERT(FIB_NODE_INDEX_INVALID != fib_index);
146 lookup_dpo_add_or_lock_i(fib_index, proto, input, table_config, dpo);
150 format_lookup_dpo (u8 *s, va_list *args)
152 index_t index = va_arg (*args, index_t);
155 lkd = lookup_dpo_get(index);
157 if (LOOKUP_TABLE_FROM_INPUT_INTERFACE == lkd->lkd_table)
159 s = format(s, "%s lookup in interface's %U table",
160 lookup_input_names[lkd->lkd_input],
161 format_dpo_proto, lkd->lkd_proto);
165 s = format(s, "%s lookup in %U",
166 lookup_input_names[lkd->lkd_input],
167 format_fib_table_name, lkd->lkd_fib_index,
168 dpo_proto_to_fib(lkd->lkd_proto));
174 lookup_dpo_lock (dpo_id_t *dpo)
178 lkd = lookup_dpo_get(dpo->dpoi_index);
184 lookup_dpo_unlock (dpo_id_t *dpo)
188 lkd = lookup_dpo_get(dpo->dpoi_index);
192 if (0 == lkd->lkd_locks)
194 if (LOOKUP_TABLE_FROM_CONFIG == lkd->lkd_table)
196 fib_table_unlock(lkd->lkd_fib_index,
197 dpo_proto_to_fib(lkd->lkd_proto));
199 pool_put(lookup_dpo_pool, lkd);
204 ip4_src_fib_lookup_one (u32 src_fib_index0,
205 const ip4_address_t * addr0,
206 u32 * src_adj_index0)
208 ip4_fib_mtrie_leaf_t leaf0;
209 ip4_fib_mtrie_t * mtrie0;
211 mtrie0 = &ip4_fib_get (src_fib_index0)->mtrie;
213 leaf0 = ip4_fib_mtrie_lookup_step_one (mtrie0, addr0);
214 leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 1);
215 leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 2);
216 leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 3);
218 src_adj_index0[0] = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
222 ip4_src_fib_lookup_two (u32 src_fib_index0,
224 const ip4_address_t * addr0,
225 const ip4_address_t * addr1,
226 u32 * src_adj_index0,
227 u32 * src_adj_index1)
229 ip4_fib_mtrie_leaf_t leaf0, leaf1;
230 ip4_fib_mtrie_t * mtrie0, * mtrie1;
232 mtrie0 = &ip4_fib_get (src_fib_index0)->mtrie;
233 mtrie1 = &ip4_fib_get (src_fib_index1)->mtrie;
235 leaf0 = ip4_fib_mtrie_lookup_step_one (mtrie0, addr0);
236 leaf1 = ip4_fib_mtrie_lookup_step_one (mtrie1, addr1);
238 leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 1);
239 leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 1);
241 leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 2);
242 leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 2);
244 leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 3);
245 leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 3);
247 src_adj_index0[0] = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
248 src_adj_index1[0] = ip4_fib_mtrie_leaf_get_adj_index (leaf1);
252 * @brief Lookup trace data
254 typedef struct lookup_trace_t_
258 mpls_unicast_header_t hdr;
260 fib_node_index_t fib_index;
266 lookup_dpo_ip4_inline (vlib_main_t * vm,
267 vlib_node_runtime_t * node,
268 vlib_frame_t * from_frame,
270 int table_from_interface)
272 u32 n_left_from, next_index, * from, * to_next;
273 u32 cpu_index = os_get_cpu_number();
274 vlib_combined_counter_main_t * cm = &load_balance_main.lbm_to_counters;
276 from = vlib_frame_vector_args (from_frame);
277 n_left_from = from_frame->n_vectors;
279 next_index = node->cached_next_index;
281 while (n_left_from > 0)
285 vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
287 while (n_left_from >= 4 && n_left_to_next > 2)
289 u32 bi0, lkdi0, lbi0, fib_index0, next0, hash_c0;
290 flow_hash_config_t flow_hash_config0;
291 const ip4_address_t *input_addr0;
292 const load_balance_t *lb0;
293 const lookup_dpo_t * lkd0;
294 const ip4_header_t * ip0;
295 const dpo_id_t *dpo0;
297 u32 bi1, lkdi1, lbi1, fib_index1, next1, hash_c1;
298 flow_hash_config_t flow_hash_config1;
299 const ip4_address_t *input_addr1;
300 const load_balance_t *lb1;
301 const lookup_dpo_t * lkd1;
302 const ip4_header_t * ip1;
303 const dpo_id_t *dpo1;
306 /* Prefetch next iteration. */
308 vlib_buffer_t * p2, * p3;
310 p2 = vlib_get_buffer (vm, from[2]);
311 p3 = vlib_get_buffer (vm, from[3]);
313 vlib_prefetch_buffer_header (p2, LOAD);
314 vlib_prefetch_buffer_header (p3, LOAD);
316 CLIB_PREFETCH (p2->data, CLIB_CACHE_LINE_BYTES, STORE);
317 CLIB_PREFETCH (p3->data, CLIB_CACHE_LINE_BYTES, STORE);
329 b0 = vlib_get_buffer (vm, bi0);
330 ip0 = vlib_buffer_get_current (b0);
331 b1 = vlib_get_buffer (vm, bi1);
332 ip1 = vlib_buffer_get_current (b1);
334 /* dst lookup was done by ip4 lookup */
335 lkdi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
336 lkdi1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
337 lkd0 = lookup_dpo_get(lkdi0);
338 lkd1 = lookup_dpo_get(lkdi1);
341 * choose between a lookup using the fib index in the DPO
342 * or getting the FIB index from the interface.
344 if (table_from_interface)
347 ip4_fib_table_get_index_for_sw_if_index(
348 vnet_buffer(b0)->sw_if_index[VLIB_RX]);
350 ip4_fib_table_get_index_for_sw_if_index(
351 vnet_buffer(b1)->sw_if_index[VLIB_RX]);
355 fib_index0 = lkd0->lkd_fib_index;
356 fib_index1 = lkd1->lkd_fib_index;
360 * choose between a source or destination address lookup in the table
364 input_addr0 = &ip0->src_address;
365 input_addr1 = &ip1->src_address;
369 input_addr0 = &ip0->dst_address;
370 input_addr1 = &ip1->dst_address;
374 ip4_src_fib_lookup_two (fib_index0, fib_index1,
375 input_addr0, input_addr1,
377 lb0 = load_balance_get(lbi0);
378 lb1 = load_balance_get(lbi1);
380 vnet_buffer(b0)->sw_if_index[VLIB_TX] = fib_index0;
381 vnet_buffer(b1)->sw_if_index[VLIB_TX] = fib_index1;
383 /* Use flow hash to compute multipath adjacency. */
384 hash_c0 = vnet_buffer (b0)->ip.flow_hash = 0;
385 hash_c1 = vnet_buffer (b1)->ip.flow_hash = 0;
387 if (PREDICT_FALSE (lb0->lb_n_buckets > 1))
389 flow_hash_config0 = lb0->lb_hash_config;
390 hash_c0 = vnet_buffer (b0)->ip.flow_hash =
391 ip4_compute_flow_hash (ip0, flow_hash_config0);
394 if (PREDICT_FALSE (lb1->lb_n_buckets > 1))
396 flow_hash_config1 = lb1->lb_hash_config;
397 hash_c1 = vnet_buffer (b1)->ip.flow_hash =
398 ip4_compute_flow_hash (ip1, flow_hash_config1);
401 dpo0 = load_balance_get_bucket_i(lb0,
403 (lb0->lb_n_buckets_minus_1)));
404 dpo1 = load_balance_get_bucket_i(lb1,
406 (lb1->lb_n_buckets_minus_1)));
408 next0 = dpo0->dpoi_next_node;
409 next1 = dpo1->dpoi_next_node;
410 vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
411 vnet_buffer(b1)->ip.adj_index[VLIB_TX] = dpo1->dpoi_index;
413 vlib_increment_combined_counter
414 (cm, cpu_index, lbi0, 1,
415 vlib_buffer_length_in_chain (vm, b0));
416 vlib_increment_combined_counter
417 (cm, cpu_index, lbi1, 1,
418 vlib_buffer_length_in_chain (vm, b1));
420 if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
422 lookup_trace_t *tr = vlib_add_trace (vm, node,
424 tr->fib_index = fib_index0;
426 tr->addr.ip4 = *input_addr0;
428 if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
430 lookup_trace_t *tr = vlib_add_trace (vm, node,
432 tr->fib_index = fib_index1;
434 tr->addr.ip4 = *input_addr1;
437 vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
438 to_next, n_left_to_next,
439 bi0, bi1, next0, next1);
442 while (n_left_from > 0 && n_left_to_next > 0)
444 u32 bi0, lkdi0, lbi0, fib_index0, next0, hash_c0;
445 flow_hash_config_t flow_hash_config0;
446 const ip4_address_t *input_addr;
447 const load_balance_t *lb0;
448 const lookup_dpo_t * lkd0;
449 const ip4_header_t * ip0;
450 const dpo_id_t *dpo0;
460 b0 = vlib_get_buffer (vm, bi0);
461 ip0 = vlib_buffer_get_current (b0);
463 /* dst lookup was done by ip4 lookup */
464 lkdi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
465 lkd0 = lookup_dpo_get(lkdi0);
468 * choose between a lookup using the fib index in the DPO
469 * or getting the FIB index from the interface.
471 if (table_from_interface)
474 ip4_fib_table_get_index_for_sw_if_index(
475 vnet_buffer(b0)->sw_if_index[VLIB_RX]);
479 fib_index0 = lkd0->lkd_fib_index;
483 * choose between a source or destination address lookup in the table
487 input_addr = &ip0->src_address;
491 input_addr = &ip0->dst_address;
495 ip4_src_fib_lookup_one (fib_index0, input_addr, &lbi0);
496 lb0 = load_balance_get(lbi0);
498 vnet_buffer(b0)->sw_if_index[VLIB_TX] = fib_index0;
500 /* Use flow hash to compute multipath adjacency. */
501 hash_c0 = vnet_buffer (b0)->ip.flow_hash = 0;
503 if (PREDICT_FALSE (lb0->lb_n_buckets > 1))
505 flow_hash_config0 = lb0->lb_hash_config;
506 hash_c0 = vnet_buffer (b0)->ip.flow_hash =
507 ip4_compute_flow_hash (ip0, flow_hash_config0);
510 dpo0 = load_balance_get_bucket_i(lb0,
512 (lb0->lb_n_buckets_minus_1)));
514 next0 = dpo0->dpoi_next_node;
515 vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
517 vlib_increment_combined_counter
518 (cm, cpu_index, lbi0, 1,
519 vlib_buffer_length_in_chain (vm, b0));
521 if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
523 lookup_trace_t *tr = vlib_add_trace (vm, node,
525 tr->fib_index = fib_index0;
527 tr->addr.ip4 = *input_addr;
530 vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
531 n_left_to_next, bi0, next0);
533 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
535 return from_frame->n_vectors;
539 format_lookup_trace (u8 * s, va_list * args)
541 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
542 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
543 lookup_trace_t * t = va_arg (*args, lookup_trace_t *);
544 uword indent = format_get_indent (s);
545 s = format (s, "%U fib-index:%d addr:%U load-balance:%d",
546 format_white_space, indent,
548 format_ip46_address, &t->addr, IP46_TYPE_ANY,
554 lookup_ip4_dst (vlib_main_t * vm,
555 vlib_node_runtime_t * node,
556 vlib_frame_t * from_frame)
558 return (lookup_dpo_ip4_inline(vm, node, from_frame, 0, 0));
561 VLIB_REGISTER_NODE (lookup_ip4_dst_node) = {
562 .function = lookup_ip4_dst,
563 .name = "lookup-ip4-dst",
564 .vector_size = sizeof (u32),
565 .sibling_of = "ip4-lookup",
566 .format_trace = format_lookup_trace,
568 VLIB_NODE_FUNCTION_MULTIARCH (lookup_ip4_dst_node, lookup_ip4_dst)
571 lookup_ip4_dst_itf (vlib_main_t * vm,
572 vlib_node_runtime_t * node,
573 vlib_frame_t * from_frame)
575 return (lookup_dpo_ip4_inline(vm, node, from_frame, 0, 1));
578 VLIB_REGISTER_NODE (lookup_ip4_dst_itf_node) = {
579 .function = lookup_ip4_dst_itf,
580 .name = "lookup-ip4-dst-itf",
581 .vector_size = sizeof (u32),
582 .sibling_of = "ip4-lookup",
583 .format_trace = format_lookup_trace,
585 VLIB_NODE_FUNCTION_MULTIARCH (lookup_ip4_dst_itf_node, lookup_ip4_dst_itf)
588 lookup_ip4_src (vlib_main_t * vm,
589 vlib_node_runtime_t * node,
590 vlib_frame_t * from_frame)
592 return (lookup_dpo_ip4_inline(vm, node, from_frame, 1, 0));
595 VLIB_REGISTER_NODE (lookup_ip4_src_node) = {
596 .function = lookup_ip4_src,
597 .name = "lookup-ip4-src",
598 .vector_size = sizeof (u32),
599 .format_trace = format_lookup_trace,
600 .sibling_of = "ip4-lookup",
602 VLIB_NODE_FUNCTION_MULTIARCH (lookup_ip4_src_node, lookup_ip4_src)
605 lookup_dpo_ip6_inline (vlib_main_t * vm,
606 vlib_node_runtime_t * node,
607 vlib_frame_t * from_frame,
609 int table_from_interface)
611 vlib_combined_counter_main_t * cm = &load_balance_main.lbm_to_counters;
612 u32 n_left_from, next_index, * from, * to_next;
613 u32 cpu_index = os_get_cpu_number();
615 from = vlib_frame_vector_args (from_frame);
616 n_left_from = from_frame->n_vectors;
618 next_index = node->cached_next_index;
620 while (n_left_from > 0)
624 vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
626 while (n_left_from >= 4 && n_left_to_next > 2)
628 u32 bi0, lkdi0, lbi0, fib_index0, next0, hash_c0;
629 flow_hash_config_t flow_hash_config0;
630 const ip6_address_t *input_addr0;
631 const load_balance_t *lb0;
632 const lookup_dpo_t * lkd0;
633 const ip6_header_t * ip0;
634 const dpo_id_t *dpo0;
636 u32 bi1, lkdi1, lbi1, fib_index1, next1, hash_c1;
637 flow_hash_config_t flow_hash_config1;
638 const ip6_address_t *input_addr1;
639 const load_balance_t *lb1;
640 const lookup_dpo_t * lkd1;
641 const ip6_header_t * ip1;
642 const dpo_id_t *dpo1;
645 /* Prefetch next iteration. */
647 vlib_buffer_t * p2, * p3;
649 p2 = vlib_get_buffer (vm, from[2]);
650 p3 = vlib_get_buffer (vm, from[3]);
652 vlib_prefetch_buffer_header (p2, LOAD);
653 vlib_prefetch_buffer_header (p3, LOAD);
655 CLIB_PREFETCH (p2->data, CLIB_CACHE_LINE_BYTES, STORE);
656 CLIB_PREFETCH (p3->data, CLIB_CACHE_LINE_BYTES, STORE);
668 b0 = vlib_get_buffer (vm, bi0);
669 ip0 = vlib_buffer_get_current (b0);
670 b1 = vlib_get_buffer (vm, bi1);
671 ip1 = vlib_buffer_get_current (b1);
673 /* dst lookup was done by ip6 lookup */
674 lkdi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
675 lkdi1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
676 lkd0 = lookup_dpo_get(lkdi0);
677 lkd1 = lookup_dpo_get(lkdi1);
680 * choose between a lookup using the fib index in the DPO
681 * or getting the FIB index from the interface.
683 if (table_from_interface)
686 ip6_fib_table_get_index_for_sw_if_index(
687 vnet_buffer(b0)->sw_if_index[VLIB_RX]);
689 ip6_fib_table_get_index_for_sw_if_index(
690 vnet_buffer(b1)->sw_if_index[VLIB_RX]);
694 fib_index0 = lkd0->lkd_fib_index;
695 fib_index1 = lkd1->lkd_fib_index;
699 * choose between a source or destination address lookup in the table
703 input_addr0 = &ip0->src_address;
704 input_addr1 = &ip1->src_address;
708 input_addr0 = &ip0->dst_address;
709 input_addr1 = &ip1->dst_address;
713 lbi0 = ip6_fib_table_fwding_lookup(&ip6_main,
716 lbi1 = ip6_fib_table_fwding_lookup(&ip6_main,
719 lb0 = load_balance_get(lbi0);
720 lb1 = load_balance_get(lbi1);
722 vnet_buffer(b0)->sw_if_index[VLIB_TX] = fib_index0;
723 vnet_buffer(b1)->sw_if_index[VLIB_TX] = fib_index1;
725 /* Use flow hash to compute multipath adjacency. */
726 hash_c0 = vnet_buffer (b0)->ip.flow_hash = 0;
727 hash_c1 = vnet_buffer (b1)->ip.flow_hash = 0;
729 if (PREDICT_FALSE (lb0->lb_n_buckets > 1))
731 flow_hash_config0 = lb0->lb_hash_config;
732 hash_c0 = vnet_buffer (b0)->ip.flow_hash =
733 ip6_compute_flow_hash (ip0, flow_hash_config0);
736 if (PREDICT_FALSE (lb1->lb_n_buckets > 1))
738 flow_hash_config1 = lb1->lb_hash_config;
739 hash_c1 = vnet_buffer (b1)->ip.flow_hash =
740 ip6_compute_flow_hash (ip1, flow_hash_config1);
743 dpo0 = load_balance_get_bucket_i(lb0,
745 (lb0->lb_n_buckets_minus_1)));
746 dpo1 = load_balance_get_bucket_i(lb1,
748 (lb1->lb_n_buckets_minus_1)));
750 next0 = dpo0->dpoi_next_node;
751 next1 = dpo1->dpoi_next_node;
752 vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
753 vnet_buffer(b1)->ip.adj_index[VLIB_TX] = dpo1->dpoi_index;
755 vlib_increment_combined_counter
756 (cm, cpu_index, lbi0, 1,
757 vlib_buffer_length_in_chain (vm, b0));
758 vlib_increment_combined_counter
759 (cm, cpu_index, lbi1, 1,
760 vlib_buffer_length_in_chain (vm, b1));
762 if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
764 lookup_trace_t *tr = vlib_add_trace (vm, node,
766 tr->fib_index = fib_index0;
768 tr->addr.ip6 = *input_addr0;
770 if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
772 lookup_trace_t *tr = vlib_add_trace (vm, node,
774 tr->fib_index = fib_index1;
776 tr->addr.ip6 = *input_addr1;
778 vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next,
779 n_left_to_next, bi0, bi1,
782 while (n_left_from > 0 && n_left_to_next > 0)
784 u32 bi0, lkdi0, lbi0, fib_index0, next0, hash_c0;
785 flow_hash_config_t flow_hash_config0;
786 const ip6_address_t *input_addr0;
787 const load_balance_t *lb0;
788 const lookup_dpo_t * lkd0;
789 const ip6_header_t * ip0;
790 const dpo_id_t *dpo0;
800 b0 = vlib_get_buffer (vm, bi0);
801 ip0 = vlib_buffer_get_current (b0);
803 /* dst lookup was done by ip6 lookup */
804 lkdi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
805 lkd0 = lookup_dpo_get(lkdi0);
808 * choose between a lookup using the fib index in the DPO
809 * or getting the FIB index from the interface.
811 if (table_from_interface)
814 ip6_fib_table_get_index_for_sw_if_index(
815 vnet_buffer(b0)->sw_if_index[VLIB_RX]);
819 fib_index0 = lkd0->lkd_fib_index;
823 * choose between a source or destination address lookup in the table
827 input_addr0 = &ip0->src_address;
831 input_addr0 = &ip0->dst_address;
835 lbi0 = ip6_fib_table_fwding_lookup(&ip6_main,
838 lb0 = load_balance_get(lbi0);
840 vnet_buffer(b0)->sw_if_index[VLIB_TX] = fib_index0;
842 /* Use flow hash to compute multipath adjacency. */
843 hash_c0 = vnet_buffer (b0)->ip.flow_hash = 0;
845 if (PREDICT_FALSE (lb0->lb_n_buckets > 1))
847 flow_hash_config0 = lb0->lb_hash_config;
848 hash_c0 = vnet_buffer (b0)->ip.flow_hash =
849 ip6_compute_flow_hash (ip0, flow_hash_config0);
852 dpo0 = load_balance_get_bucket_i(lb0,
854 (lb0->lb_n_buckets_minus_1)));
856 next0 = dpo0->dpoi_next_node;
857 vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
859 vlib_increment_combined_counter
860 (cm, cpu_index, lbi0, 1,
861 vlib_buffer_length_in_chain (vm, b0));
863 if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
865 lookup_trace_t *tr = vlib_add_trace (vm, node,
867 tr->fib_index = fib_index0;
869 tr->addr.ip6 = *input_addr0;
871 vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
872 n_left_to_next, bi0, next0);
874 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
876 return from_frame->n_vectors;
880 lookup_ip6_dst (vlib_main_t * vm,
881 vlib_node_runtime_t * node,
882 vlib_frame_t * from_frame)
884 return (lookup_dpo_ip6_inline(vm, node, from_frame, 0 /*use src*/, 0));
887 VLIB_REGISTER_NODE (lookup_ip6_dst_node) = {
888 .function = lookup_ip6_dst,
889 .name = "lookup-ip6-dst",
890 .vector_size = sizeof (u32),
891 .format_trace = format_lookup_trace,
892 .sibling_of = "ip6-lookup",
894 VLIB_NODE_FUNCTION_MULTIARCH (lookup_ip6_dst_node, lookup_ip6_dst)
897 lookup_ip6_dst_itf (vlib_main_t * vm,
898 vlib_node_runtime_t * node,
899 vlib_frame_t * from_frame)
901 return (lookup_dpo_ip6_inline(vm, node, from_frame, 0 /*use src*/, 1));
904 VLIB_REGISTER_NODE (lookup_ip6_dst_itf_node) = {
905 .function = lookup_ip6_dst_itf,
906 .name = "lookup-ip6-dst-itf",
907 .vector_size = sizeof (u32),
908 .format_trace = format_lookup_trace,
909 .sibling_of = "ip6-lookup",
911 VLIB_NODE_FUNCTION_MULTIARCH (lookup_ip6_dst_itf_node, lookup_ip6_dst_itf)
914 lookup_ip6_src (vlib_main_t * vm,
915 vlib_node_runtime_t * node,
916 vlib_frame_t * from_frame)
918 return (lookup_dpo_ip6_inline(vm, node, from_frame, 1, 0));
921 VLIB_REGISTER_NODE (lookup_ip6_src_node) = {
922 .function = lookup_ip6_src,
923 .name = "lookup-ip6-src",
924 .vector_size = sizeof (u32),
925 .format_trace = format_lookup_trace,
926 .sibling_of = "ip6-lookup",
928 VLIB_NODE_FUNCTION_MULTIARCH (lookup_ip6_src_node, lookup_ip6_src)
931 lookup_dpo_mpls_inline (vlib_main_t * vm,
932 vlib_node_runtime_t * node,
933 vlib_frame_t * from_frame,
934 int table_from_interface)
936 u32 n_left_from, next_index, * from, * to_next;
937 u32 cpu_index = os_get_cpu_number();
938 vlib_combined_counter_main_t * cm = &load_balance_main.lbm_to_counters;
940 from = vlib_frame_vector_args (from_frame);
941 n_left_from = from_frame->n_vectors;
943 next_index = node->cached_next_index;
945 while (n_left_from > 0)
949 vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
951 /* while (n_left_from >= 4 && n_left_to_next >= 2) */
954 while (n_left_from > 0 && n_left_to_next > 0)
956 u32 bi0, lkdi0, lbi0, fib_index0, next0;
957 const mpls_unicast_header_t * hdr0;
958 const load_balance_t *lb0;
959 const lookup_dpo_t * lkd0;
960 const dpo_id_t *dpo0;
970 b0 = vlib_get_buffer (vm, bi0);
971 hdr0 = vlib_buffer_get_current (b0);
973 /* dst lookup was done by mpls lookup */
974 lkdi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
975 lkd0 = lookup_dpo_get(lkdi0);
978 * choose between a lookup using the fib index in the DPO
979 * or getting the FIB index from the interface.
981 if (table_from_interface)
984 mpls_fib_table_get_index_for_sw_if_index(
985 vnet_buffer(b0)->sw_if_index[VLIB_RX]);
989 fib_index0 = lkd0->lkd_fib_index;
993 lbi0 = mpls_fib_table_forwarding_lookup (fib_index0, hdr0);
994 lb0 = load_balance_get(lbi0);
995 dpo0 = load_balance_get_bucket_i(lb0, 0);
997 next0 = dpo0->dpoi_next_node;
998 vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
1000 vlib_increment_combined_counter
1001 (cm, cpu_index, lbi0, 1,
1002 vlib_buffer_length_in_chain (vm, b0));
1004 if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
1006 lookup_trace_t *tr = vlib_add_trace (vm, node,
1008 tr->fib_index = fib_index0;
1013 vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
1014 n_left_to_next, bi0, next0);
1016 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1018 return from_frame->n_vectors;
1022 format_lookup_mpls_trace (u8 * s, va_list * args)
1024 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
1025 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
1026 lookup_trace_t * t = va_arg (*args, lookup_trace_t *);
1027 uword indent = format_get_indent (s);
1028 mpls_unicast_header_t hdr;
1030 hdr.label_exp_s_ttl = clib_net_to_host_u32(t->hdr.label_exp_s_ttl);
1032 s = format (s, "%U fib-index:%d hdr:%U load-balance:%d",
1033 format_white_space, indent,
1035 format_mpls_header, hdr,
1041 lookup_mpls_dst (vlib_main_t * vm,
1042 vlib_node_runtime_t * node,
1043 vlib_frame_t * from_frame)
1045 return (lookup_dpo_mpls_inline(vm, node, from_frame, 0));
1048 VLIB_REGISTER_NODE (lookup_mpls_dst_node) = {
1049 .function = lookup_mpls_dst,
1050 .name = "lookup-mpls-dst",
1051 .vector_size = sizeof (u32),
1052 .sibling_of = "mpls-lookup",
1053 .format_trace = format_lookup_mpls_trace,
1056 VLIB_NODE_FUNCTION_MULTIARCH (lookup_mpls_dst_node, lookup_mpls_dst)
1059 lookup_mpls_dst_itf (vlib_main_t * vm,
1060 vlib_node_runtime_t * node,
1061 vlib_frame_t * from_frame)
1063 return (lookup_dpo_mpls_inline(vm, node, from_frame, 1));
1066 VLIB_REGISTER_NODE (lookup_mpls_dst_itf_node) = {
1067 .function = lookup_mpls_dst_itf,
1068 .name = "lookup-mpls-dst-itf",
1069 .vector_size = sizeof (u32),
1070 .sibling_of = "mpls-lookup",
1071 .format_trace = format_lookup_mpls_trace,
1074 VLIB_NODE_FUNCTION_MULTIARCH (lookup_mpls_dst_itf_node, lookup_mpls_dst_itf)
1077 lookup_dpo_mem_show (void)
1079 fib_show_memory_usage("Lookup",
1080 pool_elts(lookup_dpo_pool),
1081 pool_len(lookup_dpo_pool),
1082 sizeof(lookup_dpo_t));
1085 const static dpo_vft_t lkd_vft = {
1086 .dv_lock = lookup_dpo_lock,
1087 .dv_unlock = lookup_dpo_unlock,
1088 .dv_format = format_lookup_dpo,
1090 const static dpo_vft_t lkd_vft_w_mem_show = {
1091 .dv_lock = lookup_dpo_lock,
1092 .dv_unlock = lookup_dpo_unlock,
1093 .dv_format = format_lookup_dpo,
1094 .dv_mem_show = lookup_dpo_mem_show,
1097 const static char* const lookup_src_ip4_nodes[] =
1102 const static char* const lookup_src_ip6_nodes[] =
1107 const static char* const * const lookup_src_nodes[DPO_PROTO_NUM] =
1109 [DPO_PROTO_IP4] = lookup_src_ip4_nodes,
1110 [DPO_PROTO_IP6] = lookup_src_ip6_nodes,
1111 [DPO_PROTO_MPLS] = NULL,
1114 const static char* const lookup_dst_ip4_nodes[] =
1119 const static char* const lookup_dst_ip6_nodes[] =
1124 const static char* const lookup_dst_mpls_nodes[] =
1129 const static char* const * const lookup_dst_nodes[DPO_PROTO_NUM] =
1131 [DPO_PROTO_IP4] = lookup_dst_ip4_nodes,
1132 [DPO_PROTO_IP6] = lookup_dst_ip6_nodes,
1133 [DPO_PROTO_MPLS] = lookup_dst_mpls_nodes,
1136 const static char* const lookup_dst_from_interface_ip4_nodes[] =
1138 "lookup-ip4-dst-itf",
1141 const static char* const lookup_dst_from_interface_ip6_nodes[] =
1143 "lookup-ip6-dst-itf",
1146 const static char* const lookup_dst_from_interface_mpls_nodes[] =
1148 "lookup-mpls-dst-itf",
1151 const static char* const * const lookup_dst_from_interface_nodes[DPO_PROTO_NUM] =
1153 [DPO_PROTO_IP4] = lookup_dst_from_interface_ip4_nodes,
1154 [DPO_PROTO_IP6] = lookup_dst_from_interface_ip6_nodes,
1155 [DPO_PROTO_MPLS] = lookup_dst_from_interface_mpls_nodes,
1160 lookup_dpo_module_init (void)
1162 dpo_register(DPO_LOOKUP, &lkd_vft_w_mem_show, NULL);
1165 * There are various sorts of lookup; src or dst addr v4 /v6 etc.
1166 * there isn't an object type for each (there is only the lookup_dpo_t),
1167 * but, for performance reasons, there is a data plane function, and hence
1168 * VLIB node for each. VLIB graph node construction is based on DPO types
1169 * so we create sub-types.
1171 lookup_dpo_sub_types[LOOKUP_SUB_TYPE_SRC] =
1172 dpo_register_new_type(&lkd_vft, lookup_src_nodes);
1173 lookup_dpo_sub_types[LOOKUP_SUB_TYPE_DST] =
1174 dpo_register_new_type(&lkd_vft, lookup_dst_nodes);
1175 lookup_dpo_sub_types[LOOKUP_SUB_TYPE_DST_TABLE_FROM_INTERFACE] =
1176 dpo_register_new_type(&lkd_vft, lookup_dst_from_interface_nodes);