blob: 96fedd27ce99e31a34339e7d87f3b7aced7606bc [file] [log] [blame]
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001/*
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>
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>
24
25static const char *const lookup_input_names[] = LOOKUP_INPUTS;
26
27/**
28 * @brief Enumeration of the lookup subtypes
29 */
30typedef enum lookup_sub_type_t_
31{
32 LOOKUP_SUB_TYPE_SRC,
33 LOOKUP_SUB_TYPE_DST,
34 LOOKUP_SUB_TYPE_DST_TABLE_FROM_INTERFACE,
35} lookup_sub_type_t;
36#define LOOKUP_SUB_TYPE_NUM (LOOKUP_SUB_TYPE_DST_TABLE_FROM_INTERFACE+1)
37
38#define FOR_EACH_LOOKUP_SUB_TYPE(_st) \
39 for (_st = LOOKUP_SUB_TYPE_IP4_SRC; _st < LOOKUP_SUB_TYPE_NUM; _st++)
40
41/**
42 * @brief pool of all MPLS Label DPOs
43 */
44lookup_dpo_t *lookup_dpo_pool;
45
46/**
47 * @brief An array of registered DPO type values for the sub-types
48 */
49static dpo_type_t lookup_dpo_sub_types[LOOKUP_SUB_TYPE_NUM];
50
51static lookup_dpo_t *
52lookup_dpo_alloc (void)
53{
54 lookup_dpo_t *lkd;
55
56 pool_get_aligned(lookup_dpo_pool, lkd, CLIB_CACHE_LINE_BYTES);
57
58 return (lkd);
59}
60
61static index_t
62lookup_dpo_get_index (lookup_dpo_t *lkd)
63{
64 return (lkd - lookup_dpo_pool);
65}
66
67static void
68lookup_dpo_add_or_lock_i (fib_node_index_t fib_index,
69 dpo_proto_t proto,
70 lookup_input_t input,
71 lookup_table_t table_config,
72 dpo_id_t *dpo)
73{
74 lookup_dpo_t *lkd;
75 dpo_type_t type;
76
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;
82
83 /*
84 * use the input type to select the lookup sub-type
85 */
86 type = 0;
87
88 switch (input)
89 {
90 case LOOKUP_INPUT_SRC_ADDR:
91 type = lookup_dpo_sub_types[LOOKUP_SUB_TYPE_SRC];
92 break;
93 case LOOKUP_INPUT_DST_ADDR:
94 switch (table_config)
95 {
96 case LOOKUP_TABLE_FROM_INPUT_INTERFACE:
97 type = lookup_dpo_sub_types[LOOKUP_SUB_TYPE_DST_TABLE_FROM_INTERFACE];
98 break;
99 case LOOKUP_TABLE_FROM_CONFIG:
100 type = lookup_dpo_sub_types[LOOKUP_SUB_TYPE_DST];
101 break;
102 }
103 }
104
105 if (0 == type)
106 {
107 dpo_reset(dpo);
108 }
109 else
110 {
111 dpo_set(dpo, type, proto, lookup_dpo_get_index(lkd));
112 }
113}
114
115void
116lookup_dpo_add_or_lock_w_fib_index (fib_node_index_t fib_index,
117 dpo_proto_t proto,
118 lookup_input_t input,
119 lookup_table_t table_config,
120 dpo_id_t *dpo)
121{
122 if (LOOKUP_TABLE_FROM_CONFIG == table_config)
123 {
124 fib_table_lock(fib_index, dpo_proto_to_fib(proto));
125 }
126 lookup_dpo_add_or_lock_i(fib_index, proto, input, table_config, dpo);
127}
128
129void
130lookup_dpo_add_or_lock_w_table_id (u32 table_id,
131 dpo_proto_t proto,
132 lookup_input_t input,
133 lookup_table_t table_config,
134 dpo_id_t *dpo)
135{
136 fib_node_index_t fib_index = FIB_NODE_INDEX_INVALID;
137
138 if (LOOKUP_TABLE_FROM_CONFIG == table_config)
139 {
140 fib_index =
141 fib_table_find_or_create_and_lock(dpo_proto_to_fib(proto),
142 table_id);
143 }
144
145 ASSERT(FIB_NODE_INDEX_INVALID != fib_index);
146 lookup_dpo_add_or_lock_i(fib_index, proto, input, table_config, dpo);
147}
148
149u8*
150format_lookup_dpo (u8 *s, va_list *args)
151{
152 index_t index = va_arg (*args, index_t);
153 lookup_dpo_t *lkd;
154
155 lkd = lookup_dpo_get(index);
156
157 if (LOOKUP_TABLE_FROM_INPUT_INTERFACE == lkd->lkd_table)
158 {
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);
162 }
163 else
164 {
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));
169 }
170 return (s);
171}
172
173static void
174lookup_dpo_lock (dpo_id_t *dpo)
175{
176 lookup_dpo_t *lkd;
177
178 lkd = lookup_dpo_get(dpo->dpoi_index);
179
180 lkd->lkd_locks++;
181}
182
183static void
184lookup_dpo_unlock (dpo_id_t *dpo)
185{
186 lookup_dpo_t *lkd;
187
188 lkd = lookup_dpo_get(dpo->dpoi_index);
189
190 lkd->lkd_locks--;
191
192 if (0 == lkd->lkd_locks)
193 {
194 if (LOOKUP_TABLE_FROM_CONFIG == lkd->lkd_table)
195 {
196 fib_table_unlock(lkd->lkd_fib_index,
197 dpo_proto_to_fib(lkd->lkd_proto));
198 }
199 pool_put(lookup_dpo_pool, lkd);
200 }
201}
202
203always_inline void
204ip4_src_fib_lookup_one (u32 src_fib_index0,
205 const ip4_address_t * addr0,
206 u32 * src_adj_index0)
207{
208 ip4_fib_mtrie_leaf_t leaf0, leaf1;
209 ip4_fib_mtrie_t * mtrie0;
210
211 mtrie0 = &ip4_fib_get (src_fib_index0)->mtrie;
212
213 leaf0 = leaf1 = IP4_FIB_MTRIE_LEAF_ROOT;
214 leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 0);
215 leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 1);
216 leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 2);
217 leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 3);
218
219 /* Handle default route. */
220 leaf0 = (leaf0 == IP4_FIB_MTRIE_LEAF_EMPTY ? mtrie0->default_leaf : leaf0);
221 src_adj_index0[0] = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
222}
223
224always_inline void
225ip4_src_fib_lookup_two (u32 src_fib_index0,
226 u32 src_fib_index1,
227 const ip4_address_t * addr0,
228 const ip4_address_t * addr1,
229 u32 * src_adj_index0,
230 u32 * src_adj_index1)
231{
232 ip4_fib_mtrie_leaf_t leaf0, leaf1;
233 ip4_fib_mtrie_t * mtrie0, * mtrie1;
234
235 mtrie0 = &ip4_fib_get (src_fib_index0)->mtrie;
236 mtrie1 = &ip4_fib_get (src_fib_index1)->mtrie;
237
238 leaf0 = leaf1 = IP4_FIB_MTRIE_LEAF_ROOT;
239
240 leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 0);
241 leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 0);
242
243 leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 1);
244 leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 1);
245
246 leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 2);
247 leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 2);
248
249 leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 3);
250 leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 3);
251
252 /* Handle default route. */
253 leaf0 = (leaf0 == IP4_FIB_MTRIE_LEAF_EMPTY ? mtrie0->default_leaf : leaf0);
254 leaf1 = (leaf1 == IP4_FIB_MTRIE_LEAF_EMPTY ? mtrie1->default_leaf : leaf1);
255 src_adj_index0[0] = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
256 src_adj_index1[0] = ip4_fib_mtrie_leaf_get_adj_index (leaf1);
257}
258
259/**
260 * @brief Lookup trace data
261 */
262typedef struct lookup_trace_t_
263{
264 union {
265 ip46_address_t addr;
266 mpls_unicast_header_t hdr;
267 };
268 fib_node_index_t fib_index;
269 index_t lbi;
270} lookup_trace_t;
271
272
273always_inline uword
274lookup_dpo_ip4_inline (vlib_main_t * vm,
275 vlib_node_runtime_t * node,
276 vlib_frame_t * from_frame,
277 int input_src_addr,
278 int table_from_interface)
279{
280 u32 n_left_from, next_index, * from, * to_next;
281 u32 cpu_index = os_get_cpu_number();
282 vlib_combined_counter_main_t * cm = &load_balance_main.lbm_to_counters;
283
284 from = vlib_frame_vector_args (from_frame);
285 n_left_from = from_frame->n_vectors;
286
287 next_index = node->cached_next_index;
288
289 while (n_left_from > 0)
290 {
291 u32 n_left_to_next;
292
293 vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
294
Neale Rannsd3b85b02016-10-22 15:17:21 -0700295 while (n_left_from >= 4 && n_left_to_next > 2)
296 {
Neale Ranns5e575b12016-10-03 09:40:25 +0100297 u32 bi0, lkdi0, lbi0, fib_index0, next0, hash_c0;
298 flow_hash_config_t flow_hash_config0;
Neale Rannsd3b85b02016-10-22 15:17:21 -0700299 const ip4_address_t *input_addr0;
300 const load_balance_t *lb0;
301 const lookup_dpo_t * lkd0;
302 const ip4_header_t * ip0;
303 const dpo_id_t *dpo0;
304 vlib_buffer_t * b0;
305 u32 bi1, lkdi1, lbi1, fib_index1, next1, hash_c1;
306 flow_hash_config_t flow_hash_config1;
307 const ip4_address_t *input_addr1;
308 const load_balance_t *lb1;
309 const lookup_dpo_t * lkd1;
310 const ip4_header_t * ip1;
311 const dpo_id_t *dpo1;
312 vlib_buffer_t * b1;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100313
Neale Rannsd3b85b02016-10-22 15:17:21 -0700314 /* Prefetch next iteration. */
315 {
316 vlib_buffer_t * p2, * p3;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100317
Neale Rannsd3b85b02016-10-22 15:17:21 -0700318 p2 = vlib_get_buffer (vm, from[2]);
319 p3 = vlib_get_buffer (vm, from[3]);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100320
Neale Rannsd3b85b02016-10-22 15:17:21 -0700321 vlib_prefetch_buffer_header (p2, LOAD);
322 vlib_prefetch_buffer_header (p3, LOAD);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100323
Neale Rannsd3b85b02016-10-22 15:17:21 -0700324 CLIB_PREFETCH (p2->data, CLIB_CACHE_LINE_BYTES, STORE);
325 CLIB_PREFETCH (p3->data, CLIB_CACHE_LINE_BYTES, STORE);
326 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100327
Neale Rannsd3b85b02016-10-22 15:17:21 -0700328 bi0 = from[0];
329 to_next[0] = bi0;
330 bi1 = from[1];
331 to_next[1] = bi1;
332 from += 2;
333 to_next += 2;
334 n_left_from -= 2;
335 n_left_to_next -= 2;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100336
Neale Rannsd3b85b02016-10-22 15:17:21 -0700337 b0 = vlib_get_buffer (vm, bi0);
338 ip0 = vlib_buffer_get_current (b0);
339 b1 = vlib_get_buffer (vm, bi1);
340 ip1 = vlib_buffer_get_current (b1);
341
342 /* dst lookup was done by ip4 lookup */
343 lkdi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
344 lkdi1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
345 lkd0 = lookup_dpo_get(lkdi0);
346 lkd1 = lookup_dpo_get(lkdi1);
347
348 /*
349 * choose between a lookup using the fib index in the DPO
350 * or getting the FIB index from the interface.
351 */
352 if (table_from_interface)
353 {
354 fib_index0 =
355 ip4_fib_table_get_index_for_sw_if_index(
356 vnet_buffer(b0)->sw_if_index[VLIB_RX]);
357 fib_index1 =
358 ip4_fib_table_get_index_for_sw_if_index(
359 vnet_buffer(b1)->sw_if_index[VLIB_RX]);
360 }
361 else
362 {
363 fib_index0 = lkd0->lkd_fib_index;
364 fib_index1 = lkd1->lkd_fib_index;
365 }
366
367 /*
368 * choose between a source or destination address lookup in the table
369 */
370 if (input_src_addr)
371 {
372 input_addr0 = &ip0->src_address;
373 input_addr1 = &ip1->src_address;
374 }
375 else
376 {
377 input_addr0 = &ip0->dst_address;
378 input_addr1 = &ip1->dst_address;
379 }
380
381 /* do lookup */
Neale Ranns450cd302016-11-09 17:49:42 +0000382 ip4_src_fib_lookup_two (fib_index0, fib_index1,
383 input_addr0, input_addr1,
384 &lbi0, &lbi1);
Neale Rannsd3b85b02016-10-22 15:17:21 -0700385 lb0 = load_balance_get(lbi0);
386 lb1 = load_balance_get(lbi1);
387
Neale Rannscb630ff2016-12-14 13:31:29 +0100388 vnet_buffer(b0)->sw_if_index[VLIB_TX] = fib_index0;
389 vnet_buffer(b1)->sw_if_index[VLIB_TX] = fib_index1;
390
Neale Rannsd3b85b02016-10-22 15:17:21 -0700391 /* Use flow hash to compute multipath adjacency. */
392 hash_c0 = vnet_buffer (b0)->ip.flow_hash = 0;
393 hash_c1 = vnet_buffer (b1)->ip.flow_hash = 0;
394
395 if (PREDICT_FALSE (lb0->lb_n_buckets > 1))
396 {
397 flow_hash_config0 = lb0->lb_hash_config;
398 hash_c0 = vnet_buffer (b0)->ip.flow_hash =
399 ip4_compute_flow_hash (ip0, flow_hash_config0);
400 }
401
402 if (PREDICT_FALSE (lb1->lb_n_buckets > 1))
403 {
404 flow_hash_config1 = lb1->lb_hash_config;
405 hash_c1 = vnet_buffer (b1)->ip.flow_hash =
406 ip4_compute_flow_hash (ip1, flow_hash_config1);
407 }
408
409 dpo0 = load_balance_get_bucket_i(lb0,
410 (hash_c0 &
411 (lb0->lb_n_buckets_minus_1)));
412 dpo1 = load_balance_get_bucket_i(lb1,
413 (hash_c1 &
414 (lb1->lb_n_buckets_minus_1)));
415
416 next0 = dpo0->dpoi_next_node;
417 next1 = dpo1->dpoi_next_node;
418 vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
419 vnet_buffer(b1)->ip.adj_index[VLIB_TX] = dpo1->dpoi_index;
420
421 vlib_increment_combined_counter
422 (cm, cpu_index, lbi0, 1,
423 vlib_buffer_length_in_chain (vm, b0));
424 vlib_increment_combined_counter
425 (cm, cpu_index, lbi1, 1,
426 vlib_buffer_length_in_chain (vm, b1));
427
428 if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
429 {
430 lookup_trace_t *tr = vlib_add_trace (vm, node,
431 b0, sizeof (*tr));
432 tr->fib_index = fib_index0;
433 tr->lbi = lbi0;
434 tr->addr.ip4 = *input_addr0;
435 }
436 if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
437 {
438 lookup_trace_t *tr = vlib_add_trace (vm, node,
439 b1, sizeof (*tr));
440 tr->fib_index = fib_index1;
441 tr->lbi = lbi1;
442 tr->addr.ip4 = *input_addr1;
443 }
444
445 vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
446 to_next, n_left_to_next,
447 bi0, bi1, next0, next1);
448 }
449
450 while (n_left_from > 0 && n_left_to_next > 0)
451 {
452 u32 bi0, lkdi0, lbi0, fib_index0, next0, hash_c0;
453 flow_hash_config_t flow_hash_config0;
454 const ip4_address_t *input_addr;
455 const load_balance_t *lb0;
456 const lookup_dpo_t * lkd0;
457 const ip4_header_t * ip0;
458 const dpo_id_t *dpo0;
459 vlib_buffer_t * b0;
460
461 bi0 = from[0];
462 to_next[0] = bi0;
463 from += 1;
464 to_next += 1;
465 n_left_from -= 1;
466 n_left_to_next -= 1;
467
468 b0 = vlib_get_buffer (vm, bi0);
469 ip0 = vlib_buffer_get_current (b0);
470
471 /* dst lookup was done by ip4 lookup */
472 lkdi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
473 lkd0 = lookup_dpo_get(lkdi0);
474
475 /*
476 * choose between a lookup using the fib index in the DPO
477 * or getting the FIB index from the interface.
478 */
479 if (table_from_interface)
480 {
481 fib_index0 =
482 ip4_fib_table_get_index_for_sw_if_index(
483 vnet_buffer(b0)->sw_if_index[VLIB_RX]);
484 }
485 else
486 {
487 fib_index0 = lkd0->lkd_fib_index;
488 }
489
490 /*
491 * choose between a source or destination address lookup in the table
492 */
493 if (input_src_addr)
494 {
495 input_addr = &ip0->src_address;
496 }
497 else
498 {
499 input_addr = &ip0->dst_address;
500 }
501
502 /* do lookup */
503 ip4_src_fib_lookup_one (fib_index0, input_addr, &lbi0);
504 lb0 = load_balance_get(lbi0);
Neale Ranns5e575b12016-10-03 09:40:25 +0100505
Neale Rannscb630ff2016-12-14 13:31:29 +0100506 vnet_buffer(b0)->sw_if_index[VLIB_TX] = fib_index0;
507
Neale Ranns5e575b12016-10-03 09:40:25 +0100508 /* Use flow hash to compute multipath adjacency. */
509 hash_c0 = vnet_buffer (b0)->ip.flow_hash = 0;
510
511 if (PREDICT_FALSE (lb0->lb_n_buckets > 1))
Neale Rannsd3b85b02016-10-22 15:17:21 -0700512 {
Neale Ranns5e575b12016-10-03 09:40:25 +0100513 flow_hash_config0 = lb0->lb_hash_config;
514 hash_c0 = vnet_buffer (b0)->ip.flow_hash =
515 ip4_compute_flow_hash (ip0, flow_hash_config0);
Neale Rannsd3b85b02016-10-22 15:17:21 -0700516 }
Neale Ranns5e575b12016-10-03 09:40:25 +0100517
518 dpo0 = load_balance_get_bucket_i(lb0,
519 (hash_c0 &
520 (lb0->lb_n_buckets_minus_1)));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100521
Neale Rannsd3b85b02016-10-22 15:17:21 -0700522 next0 = dpo0->dpoi_next_node;
523 vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100524
Neale Rannsd3b85b02016-10-22 15:17:21 -0700525 vlib_increment_combined_counter
526 (cm, cpu_index, lbi0, 1,
527 vlib_buffer_length_in_chain (vm, b0));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100528
Neale Rannsd3b85b02016-10-22 15:17:21 -0700529 if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
530 {
531 lookup_trace_t *tr = vlib_add_trace (vm, node,
532 b0, sizeof (*tr));
533 tr->fib_index = fib_index0;
534 tr->lbi = lbi0;
535 tr->addr.ip4 = *input_addr;
536 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100537
Neale Rannsd3b85b02016-10-22 15:17:21 -0700538 vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
539 n_left_to_next, bi0, next0);
540 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100541 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
542 }
543 return from_frame->n_vectors;
544}
545
546static u8 *
547format_lookup_trace (u8 * s, va_list * args)
548{
549 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
550 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
551 lookup_trace_t * t = va_arg (*args, lookup_trace_t *);
552 uword indent = format_get_indent (s);
553 s = format (s, "%U fib-index:%d addr:%U load-balance:%d",
554 format_white_space, indent,
555 t->fib_index,
556 format_ip46_address, &t->addr, IP46_TYPE_ANY,
557 t->lbi);
558 return s;
559}
560
561always_inline uword
562lookup_ip4_dst (vlib_main_t * vm,
563 vlib_node_runtime_t * node,
564 vlib_frame_t * from_frame)
565{
566 return (lookup_dpo_ip4_inline(vm, node, from_frame, 0, 0));
567}
568
569VLIB_REGISTER_NODE (lookup_ip4_dst_node) = {
570 .function = lookup_ip4_dst,
571 .name = "lookup-ip4-dst",
572 .vector_size = sizeof (u32),
573 .sibling_of = "ip4-lookup",
574 .format_trace = format_lookup_trace,
575};
576VLIB_NODE_FUNCTION_MULTIARCH (lookup_ip4_dst_node, lookup_ip4_dst)
577
578always_inline uword
579lookup_ip4_dst_itf (vlib_main_t * vm,
580 vlib_node_runtime_t * node,
581 vlib_frame_t * from_frame)
582{
583 return (lookup_dpo_ip4_inline(vm, node, from_frame, 0, 1));
584}
585
586VLIB_REGISTER_NODE (lookup_ip4_dst_itf_node) = {
587 .function = lookup_ip4_dst_itf,
588 .name = "lookup-ip4-dst-itf",
589 .vector_size = sizeof (u32),
590 .sibling_of = "ip4-lookup",
591 .format_trace = format_lookup_trace,
592};
593VLIB_NODE_FUNCTION_MULTIARCH (lookup_ip4_dst_itf_node, lookup_ip4_dst_itf)
594
595always_inline uword
596lookup_ip4_src (vlib_main_t * vm,
597 vlib_node_runtime_t * node,
598 vlib_frame_t * from_frame)
599{
600 return (lookup_dpo_ip4_inline(vm, node, from_frame, 1, 0));
601}
602
603VLIB_REGISTER_NODE (lookup_ip4_src_node) = {
604 .function = lookup_ip4_src,
605 .name = "lookup-ip4-src",
606 .vector_size = sizeof (u32),
607 .format_trace = format_lookup_trace,
608 .sibling_of = "ip4-lookup",
609};
610VLIB_NODE_FUNCTION_MULTIARCH (lookup_ip4_src_node, lookup_ip4_src)
611
612always_inline uword
613lookup_dpo_ip6_inline (vlib_main_t * vm,
614 vlib_node_runtime_t * node,
615 vlib_frame_t * from_frame,
Billy McFallcfcf1e22016-10-14 09:51:49 -0400616 int input_src_addr,
617 int table_from_interface)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100618{
619 vlib_combined_counter_main_t * cm = &load_balance_main.lbm_to_counters;
620 u32 n_left_from, next_index, * from, * to_next;
621 u32 cpu_index = os_get_cpu_number();
622
623 from = vlib_frame_vector_args (from_frame);
624 n_left_from = from_frame->n_vectors;
625
626 next_index = node->cached_next_index;
627
628 while (n_left_from > 0)
629 {
630 u32 n_left_to_next;
631
632 vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
633
Neale Rannsd3b85b02016-10-22 15:17:21 -0700634 while (n_left_from >= 4 && n_left_to_next > 2)
635 {
636 u32 bi0, lkdi0, lbi0, fib_index0, next0, hash_c0;
Neale Ranns5e575b12016-10-03 09:40:25 +0100637 flow_hash_config_t flow_hash_config0;
Neale Rannsd3b85b02016-10-22 15:17:21 -0700638 const ip6_address_t *input_addr0;
639 const load_balance_t *lb0;
640 const lookup_dpo_t * lkd0;
641 const ip6_header_t * ip0;
642 const dpo_id_t *dpo0;
643 vlib_buffer_t * b0;
644 u32 bi1, lkdi1, lbi1, fib_index1, next1, hash_c1;
645 flow_hash_config_t flow_hash_config1;
646 const ip6_address_t *input_addr1;
647 const load_balance_t *lb1;
648 const lookup_dpo_t * lkd1;
649 const ip6_header_t * ip1;
650 const dpo_id_t *dpo1;
651 vlib_buffer_t * b1;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100652
Neale Rannsd3b85b02016-10-22 15:17:21 -0700653 /* Prefetch next iteration. */
654 {
655 vlib_buffer_t * p2, * p3;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100656
Neale Rannsd3b85b02016-10-22 15:17:21 -0700657 p2 = vlib_get_buffer (vm, from[2]);
658 p3 = vlib_get_buffer (vm, from[3]);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100659
Neale Rannsd3b85b02016-10-22 15:17:21 -0700660 vlib_prefetch_buffer_header (p2, LOAD);
661 vlib_prefetch_buffer_header (p3, LOAD);
Billy McFallcfcf1e22016-10-14 09:51:49 -0400662
Neale Rannsd3b85b02016-10-22 15:17:21 -0700663 CLIB_PREFETCH (p2->data, CLIB_CACHE_LINE_BYTES, STORE);
664 CLIB_PREFETCH (p3->data, CLIB_CACHE_LINE_BYTES, STORE);
665 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100666
Neale Rannsd3b85b02016-10-22 15:17:21 -0700667 bi0 = from[0];
668 to_next[0] = bi0;
669 bi1 = from[1];
670 to_next[1] = bi1;
671 from += 2;
672 to_next += 2;
673 n_left_from -= 2;
674 n_left_to_next -= 2;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100675
Neale Rannsd3b85b02016-10-22 15:17:21 -0700676 b0 = vlib_get_buffer (vm, bi0);
677 ip0 = vlib_buffer_get_current (b0);
678 b1 = vlib_get_buffer (vm, bi1);
679 ip1 = vlib_buffer_get_current (b1);
680
681 /* dst lookup was done by ip6 lookup */
682 lkdi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
683 lkdi1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
684 lkd0 = lookup_dpo_get(lkdi0);
685 lkd1 = lookup_dpo_get(lkdi1);
686
687 /*
688 * choose between a lookup using the fib index in the DPO
689 * or getting the FIB index from the interface.
690 */
691 if (table_from_interface)
692 {
693 fib_index0 =
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000694 ip6_fib_table_get_index_for_sw_if_index(
Neale Rannsd3b85b02016-10-22 15:17:21 -0700695 vnet_buffer(b0)->sw_if_index[VLIB_RX]);
696 fib_index1 =
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000697 ip6_fib_table_get_index_for_sw_if_index(
Neale Rannsd3b85b02016-10-22 15:17:21 -0700698 vnet_buffer(b1)->sw_if_index[VLIB_RX]);
699 }
700 else
701 {
702 fib_index0 = lkd0->lkd_fib_index;
703 fib_index1 = lkd1->lkd_fib_index;
704 }
705
706 /*
707 * choose between a source or destination address lookup in the table
708 */
709 if (input_src_addr)
710 {
711 input_addr0 = &ip0->src_address;
712 input_addr1 = &ip1->src_address;
713 }
714 else
715 {
716 input_addr0 = &ip0->dst_address;
717 input_addr1 = &ip1->dst_address;
718 }
719
720 /* do src lookup */
721 lbi0 = ip6_fib_table_fwding_lookup(&ip6_main,
722 fib_index0,
723 input_addr0);
724 lbi1 = ip6_fib_table_fwding_lookup(&ip6_main,
725 fib_index1,
726 input_addr1);
727 lb0 = load_balance_get(lbi0);
728 lb1 = load_balance_get(lbi1);
729
Neale Rannscb630ff2016-12-14 13:31:29 +0100730 vnet_buffer(b0)->sw_if_index[VLIB_TX] = fib_index0;
731 vnet_buffer(b1)->sw_if_index[VLIB_TX] = fib_index1;
732
Neale Rannsd3b85b02016-10-22 15:17:21 -0700733 /* Use flow hash to compute multipath adjacency. */
734 hash_c0 = vnet_buffer (b0)->ip.flow_hash = 0;
735 hash_c1 = vnet_buffer (b1)->ip.flow_hash = 0;
736
737 if (PREDICT_FALSE (lb0->lb_n_buckets > 1))
738 {
739 flow_hash_config0 = lb0->lb_hash_config;
740 hash_c0 = vnet_buffer (b0)->ip.flow_hash =
741 ip6_compute_flow_hash (ip0, flow_hash_config0);
742 }
743
744 if (PREDICT_FALSE (lb1->lb_n_buckets > 1))
745 {
746 flow_hash_config1 = lb1->lb_hash_config;
747 hash_c1 = vnet_buffer (b1)->ip.flow_hash =
748 ip6_compute_flow_hash (ip1, flow_hash_config1);
749 }
750
751 dpo0 = load_balance_get_bucket_i(lb0,
752 (hash_c0 &
753 (lb0->lb_n_buckets_minus_1)));
754 dpo1 = load_balance_get_bucket_i(lb1,
755 (hash_c1 &
756 (lb1->lb_n_buckets_minus_1)));
757
758 next0 = dpo0->dpoi_next_node;
759 next1 = dpo1->dpoi_next_node;
760 vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
761 vnet_buffer(b1)->ip.adj_index[VLIB_TX] = dpo1->dpoi_index;
762
763 vlib_increment_combined_counter
764 (cm, cpu_index, lbi0, 1,
765 vlib_buffer_length_in_chain (vm, b0));
766 vlib_increment_combined_counter
767 (cm, cpu_index, lbi1, 1,
768 vlib_buffer_length_in_chain (vm, b1));
769
770 if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
771 {
772 lookup_trace_t *tr = vlib_add_trace (vm, node,
773 b0, sizeof (*tr));
774 tr->fib_index = fib_index0;
775 tr->lbi = lbi0;
776 tr->addr.ip6 = *input_addr0;
777 }
778 if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
779 {
780 lookup_trace_t *tr = vlib_add_trace (vm, node,
781 b1, sizeof (*tr));
782 tr->fib_index = fib_index1;
783 tr->lbi = lbi1;
784 tr->addr.ip6 = *input_addr1;
785 }
786 vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next,
787 n_left_to_next, bi0, bi1,
788 next0, next1);
789 }
790 while (n_left_from > 0 && n_left_to_next > 0)
791 {
792 u32 bi0, lkdi0, lbi0, fib_index0, next0, hash_c0;
793 flow_hash_config_t flow_hash_config0;
794 const ip6_address_t *input_addr0;
795 const load_balance_t *lb0;
796 const lookup_dpo_t * lkd0;
797 const ip6_header_t * ip0;
798 const dpo_id_t *dpo0;
799 vlib_buffer_t * b0;
800
801 bi0 = from[0];
802 to_next[0] = bi0;
803 from += 1;
804 to_next += 1;
805 n_left_from -= 1;
806 n_left_to_next -= 1;
807
808 b0 = vlib_get_buffer (vm, bi0);
809 ip0 = vlib_buffer_get_current (b0);
810
811 /* dst lookup was done by ip6 lookup */
812 lkdi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
813 lkd0 = lookup_dpo_get(lkdi0);
814
815 /*
816 * choose between a lookup using the fib index in the DPO
817 * or getting the FIB index from the interface.
818 */
819 if (table_from_interface)
820 {
821 fib_index0 =
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000822 ip6_fib_table_get_index_for_sw_if_index(
Neale Rannsd3b85b02016-10-22 15:17:21 -0700823 vnet_buffer(b0)->sw_if_index[VLIB_RX]);
824 }
825 else
826 {
827 fib_index0 = lkd0->lkd_fib_index;
828 }
829
830 /*
831 * choose between a source or destination address lookup in the table
832 */
833 if (input_src_addr)
834 {
835 input_addr0 = &ip0->src_address;
836 }
837 else
838 {
839 input_addr0 = &ip0->dst_address;
840 }
841
842 /* do src lookup */
843 lbi0 = ip6_fib_table_fwding_lookup(&ip6_main,
844 fib_index0,
845 input_addr0);
846 lb0 = load_balance_get(lbi0);
Neale Ranns5e575b12016-10-03 09:40:25 +0100847
Neale Rannscb630ff2016-12-14 13:31:29 +0100848 vnet_buffer(b0)->sw_if_index[VLIB_TX] = fib_index0;
849
Neale Ranns5e575b12016-10-03 09:40:25 +0100850 /* Use flow hash to compute multipath adjacency. */
851 hash_c0 = vnet_buffer (b0)->ip.flow_hash = 0;
852
853 if (PREDICT_FALSE (lb0->lb_n_buckets > 1))
Neale Rannsd3b85b02016-10-22 15:17:21 -0700854 {
Neale Ranns5e575b12016-10-03 09:40:25 +0100855 flow_hash_config0 = lb0->lb_hash_config;
856 hash_c0 = vnet_buffer (b0)->ip.flow_hash =
857 ip6_compute_flow_hash (ip0, flow_hash_config0);
Neale Rannsd3b85b02016-10-22 15:17:21 -0700858 }
Neale Ranns5e575b12016-10-03 09:40:25 +0100859
860 dpo0 = load_balance_get_bucket_i(lb0,
861 (hash_c0 &
862 (lb0->lb_n_buckets_minus_1)));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100863
Neale Rannsd3b85b02016-10-22 15:17:21 -0700864 next0 = dpo0->dpoi_next_node;
865 vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100866
Neale Rannsd3b85b02016-10-22 15:17:21 -0700867 vlib_increment_combined_counter
868 (cm, cpu_index, lbi0, 1,
869 vlib_buffer_length_in_chain (vm, b0));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100870
Neale Rannsd3b85b02016-10-22 15:17:21 -0700871 if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
872 {
873 lookup_trace_t *tr = vlib_add_trace (vm, node,
874 b0, sizeof (*tr));
875 tr->fib_index = fib_index0;
876 tr->lbi = lbi0;
877 tr->addr.ip6 = *input_addr0;
878 }
879 vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
880 n_left_to_next, bi0, next0);
881 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100882 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
883 }
884 return from_frame->n_vectors;
885}
886
887always_inline uword
888lookup_ip6_dst (vlib_main_t * vm,
889 vlib_node_runtime_t * node,
890 vlib_frame_t * from_frame)
891{
Billy McFallcfcf1e22016-10-14 09:51:49 -0400892 return (lookup_dpo_ip6_inline(vm, node, from_frame, 0 /*use src*/, 0));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100893}
894
895VLIB_REGISTER_NODE (lookup_ip6_dst_node) = {
896 .function = lookup_ip6_dst,
897 .name = "lookup-ip6-dst",
898 .vector_size = sizeof (u32),
899 .format_trace = format_lookup_trace,
900 .sibling_of = "ip6-lookup",
901};
902VLIB_NODE_FUNCTION_MULTIARCH (lookup_ip6_dst_node, lookup_ip6_dst)
903
904always_inline uword
Billy McFallcfcf1e22016-10-14 09:51:49 -0400905lookup_ip6_dst_itf (vlib_main_t * vm,
906 vlib_node_runtime_t * node,
907 vlib_frame_t * from_frame)
908{
909 return (lookup_dpo_ip6_inline(vm, node, from_frame, 0 /*use src*/, 1));
910}
911
912VLIB_REGISTER_NODE (lookup_ip6_dst_itf_node) = {
913 .function = lookup_ip6_dst_itf,
914 .name = "lookup-ip6-dst-itf",
915 .vector_size = sizeof (u32),
916 .format_trace = format_lookup_trace,
917 .sibling_of = "ip6-lookup",
918};
919VLIB_NODE_FUNCTION_MULTIARCH (lookup_ip6_dst_itf_node, lookup_ip6_dst_itf)
920
921always_inline uword
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100922lookup_ip6_src (vlib_main_t * vm,
923 vlib_node_runtime_t * node,
924 vlib_frame_t * from_frame)
925{
Billy McFallcfcf1e22016-10-14 09:51:49 -0400926 return (lookup_dpo_ip6_inline(vm, node, from_frame, 1, 0));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100927}
928
929VLIB_REGISTER_NODE (lookup_ip6_src_node) = {
930 .function = lookup_ip6_src,
931 .name = "lookup-ip6-src",
932 .vector_size = sizeof (u32),
933 .format_trace = format_lookup_trace,
934 .sibling_of = "ip6-lookup",
935};
936VLIB_NODE_FUNCTION_MULTIARCH (lookup_ip6_src_node, lookup_ip6_src)
937
938always_inline uword
939lookup_dpo_mpls_inline (vlib_main_t * vm,
940 vlib_node_runtime_t * node,
941 vlib_frame_t * from_frame,
942 int table_from_interface)
943{
944 u32 n_left_from, next_index, * from, * to_next;
945 u32 cpu_index = os_get_cpu_number();
946 vlib_combined_counter_main_t * cm = &load_balance_main.lbm_to_counters;
947
948 from = vlib_frame_vector_args (from_frame);
949 n_left_from = from_frame->n_vectors;
950
951 next_index = node->cached_next_index;
952
953 while (n_left_from > 0)
954 {
955 u32 n_left_to_next;
956
957 vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
958
959 /* while (n_left_from >= 4 && n_left_to_next >= 2) */
960 /* } */
961
962 while (n_left_from > 0 && n_left_to_next > 0)
963 {
964 u32 bi0, lkdi0, lbi0, fib_index0, next0;
965 const mpls_unicast_header_t * hdr0;
966 const load_balance_t *lb0;
967 const lookup_dpo_t * lkd0;
968 const dpo_id_t *dpo0;
969 vlib_buffer_t * b0;
970
971 bi0 = from[0];
972 to_next[0] = bi0;
973 from += 1;
974 to_next += 1;
975 n_left_from -= 1;
976 n_left_to_next -= 1;
977
978 b0 = vlib_get_buffer (vm, bi0);
979 hdr0 = vlib_buffer_get_current (b0);
980
981 /* dst lookup was done by mpls lookup */
982 lkdi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
983 lkd0 = lookup_dpo_get(lkdi0);
984
985 /*
986 * choose between a lookup using the fib index in the DPO
987 * or getting the FIB index from the interface.
988 */
989 if (table_from_interface)
990 {
991 fib_index0 =
992 mpls_fib_table_get_index_for_sw_if_index(
993 vnet_buffer(b0)->sw_if_index[VLIB_RX]);
994 }
995 else
996 {
997 fib_index0 = lkd0->lkd_fib_index;
998 }
999
1000 /* do lookup */
1001 lbi0 = mpls_fib_table_forwarding_lookup (fib_index0, hdr0);
1002 lb0 = load_balance_get(lbi0);
1003 dpo0 = load_balance_get_bucket_i(lb0, 0);
1004
1005 next0 = dpo0->dpoi_next_node;
1006 vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
1007
1008 vlib_increment_combined_counter
1009 (cm, cpu_index, lbi0, 1,
1010 vlib_buffer_length_in_chain (vm, b0));
1011
1012 if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
1013 {
1014 lookup_trace_t *tr = vlib_add_trace (vm, node,
1015 b0, sizeof (*tr));
1016 tr->fib_index = fib_index0;
1017 tr->lbi = lbi0;
1018 tr->hdr = *hdr0;
1019 }
1020
1021 vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
1022 n_left_to_next, bi0, next0);
1023 }
1024 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1025 }
1026 return from_frame->n_vectors;
1027}
1028
1029static u8 *
1030format_lookup_mpls_trace (u8 * s, va_list * args)
1031{
1032 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
1033 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
1034 lookup_trace_t * t = va_arg (*args, lookup_trace_t *);
1035 uword indent = format_get_indent (s);
1036 mpls_unicast_header_t hdr;
1037
1038 hdr.label_exp_s_ttl = clib_net_to_host_u32(t->hdr.label_exp_s_ttl);
1039
1040 s = format (s, "%U fib-index:%d hdr:%U load-balance:%d",
1041 format_white_space, indent,
1042 t->fib_index,
1043 format_mpls_header, hdr,
1044 t->lbi);
1045 return s;
1046}
1047
1048always_inline uword
1049lookup_mpls_dst (vlib_main_t * vm,
1050 vlib_node_runtime_t * node,
1051 vlib_frame_t * from_frame)
1052{
1053 return (lookup_dpo_mpls_inline(vm, node, from_frame, 0));
1054}
1055
1056VLIB_REGISTER_NODE (lookup_mpls_dst_node) = {
1057 .function = lookup_mpls_dst,
1058 .name = "lookup-mpls-dst",
1059 .vector_size = sizeof (u32),
1060 .sibling_of = "mpls-lookup",
1061 .format_trace = format_lookup_mpls_trace,
1062 .n_next_nodes = 0,
1063};
1064VLIB_NODE_FUNCTION_MULTIARCH (lookup_mpls_dst_node, lookup_mpls_dst)
1065
1066always_inline uword
1067lookup_mpls_dst_itf (vlib_main_t * vm,
1068 vlib_node_runtime_t * node,
1069 vlib_frame_t * from_frame)
1070{
1071 return (lookup_dpo_mpls_inline(vm, node, from_frame, 1));
1072}
1073
1074VLIB_REGISTER_NODE (lookup_mpls_dst_itf_node) = {
1075 .function = lookup_mpls_dst_itf,
1076 .name = "lookup-mpls-dst-itf",
1077 .vector_size = sizeof (u32),
1078 .sibling_of = "mpls-lookup",
1079 .format_trace = format_lookup_mpls_trace,
1080 .n_next_nodes = 0,
1081};
1082VLIB_NODE_FUNCTION_MULTIARCH (lookup_mpls_dst_itf_node, lookup_mpls_dst_itf)
1083
Neale Ranns6c3ebcc2016-10-02 21:20:15 +01001084static void
1085lookup_dpo_mem_show (void)
1086{
1087 fib_show_memory_usage("Lookup",
1088 pool_elts(lookup_dpo_pool),
1089 pool_len(lookup_dpo_pool),
1090 sizeof(lookup_dpo_t));
1091}
1092
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001093const static dpo_vft_t lkd_vft = {
1094 .dv_lock = lookup_dpo_lock,
1095 .dv_unlock = lookup_dpo_unlock,
1096 .dv_format = format_lookup_dpo,
1097};
Neale Ranns6c3ebcc2016-10-02 21:20:15 +01001098const static dpo_vft_t lkd_vft_w_mem_show = {
1099 .dv_lock = lookup_dpo_lock,
1100 .dv_unlock = lookup_dpo_unlock,
1101 .dv_format = format_lookup_dpo,
1102 .dv_mem_show = lookup_dpo_mem_show,
1103};
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001104
1105const static char* const lookup_src_ip4_nodes[] =
1106{
1107 "lookup-ip4-src",
1108 NULL,
1109};
1110const static char* const lookup_src_ip6_nodes[] =
1111{
1112 "lookup-ip6-src",
1113 NULL,
1114};
1115const static char* const * const lookup_src_nodes[DPO_PROTO_NUM] =
1116{
1117 [DPO_PROTO_IP4] = lookup_src_ip4_nodes,
1118 [DPO_PROTO_IP6] = lookup_src_ip6_nodes,
1119 [DPO_PROTO_MPLS] = NULL,
1120};
1121
1122const static char* const lookup_dst_ip4_nodes[] =
1123{
1124 "lookup-ip4-dst",
1125 NULL,
1126};
1127const static char* const lookup_dst_ip6_nodes[] =
1128{
1129 "lookup-ip6-dst",
1130 NULL,
1131};
1132const static char* const lookup_dst_mpls_nodes[] =
1133{
1134 "lookup-mpls-dst",
1135 NULL,
1136};
1137const static char* const * const lookup_dst_nodes[DPO_PROTO_NUM] =
1138{
1139 [DPO_PROTO_IP4] = lookup_dst_ip4_nodes,
1140 [DPO_PROTO_IP6] = lookup_dst_ip6_nodes,
1141 [DPO_PROTO_MPLS] = lookup_dst_mpls_nodes,
1142};
1143
1144const static char* const lookup_dst_from_interface_ip4_nodes[] =
1145{
1146 "lookup-ip4-dst-itf",
1147 NULL,
1148};
1149const static char* const lookup_dst_from_interface_ip6_nodes[] =
1150{
1151 "lookup-ip6-dst-itf",
1152 NULL,
1153};
1154const static char* const lookup_dst_from_interface_mpls_nodes[] =
1155{
1156 "lookup-mpls-dst-itf",
1157 NULL,
1158};
1159const static char* const * const lookup_dst_from_interface_nodes[DPO_PROTO_NUM] =
1160{
1161 [DPO_PROTO_IP4] = lookup_dst_from_interface_ip4_nodes,
1162 [DPO_PROTO_IP6] = lookup_dst_from_interface_ip6_nodes,
1163 [DPO_PROTO_MPLS] = lookup_dst_from_interface_mpls_nodes,
1164};
1165
1166
1167void
1168lookup_dpo_module_init (void)
1169{
Neale Ranns6c3ebcc2016-10-02 21:20:15 +01001170 dpo_register(DPO_LOOKUP, &lkd_vft_w_mem_show, NULL);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001171
1172 /*
1173 * There are various sorts of lookup; src or dst addr v4 /v6 etc.
1174 * there isn't an object type for each (there is only the lookup_dpo_t),
1175 * but, for performance reasons, there is a data plane function, and hence
1176 * VLIB node for each. VLIB graph node construction is based on DPO types
1177 * so we create sub-types.
1178 */
1179 lookup_dpo_sub_types[LOOKUP_SUB_TYPE_SRC] =
1180 dpo_register_new_type(&lkd_vft, lookup_src_nodes);
1181 lookup_dpo_sub_types[LOOKUP_SUB_TYPE_DST] =
1182 dpo_register_new_type(&lkd_vft, lookup_dst_nodes);
1183 lookup_dpo_sub_types[LOOKUP_SUB_TYPE_DST_TABLE_FROM_INTERFACE] =
Billy McFallcfcf1e22016-10-14 09:51:49 -04001184 dpo_register_new_type(&lkd_vft, lookup_dst_from_interface_nodes);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001185}