blob: 1ac917cb0de0713126f67e97820cb0aaa86e1693 [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>
Neale Ranns6af1c042017-05-26 03:48:53 -070018#include <vnet/dpo/load_balance_map.h>
19#include <vnet/mpls/mpls_lookup.h>
Neale Ranns0bfe5d82016-08-25 15:29:12 +010020#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>
Neale Ranns0f26c5a2017-03-01 15:12:11 -080024#include <vnet/mfib/mfib_table.h>
25#include <vnet/mfib/ip4_mfib.h>
26#include <vnet/mfib/ip6_mfib.h>
Neale Ranns0bfe5d82016-08-25 15:29:12 +010027
28static const char *const lookup_input_names[] = LOOKUP_INPUTS;
Neale Ranns0f26c5a2017-03-01 15:12:11 -080029static const char *const lookup_cast_names[] = LOOKUP_CASTS;
Neale Ranns0bfe5d82016-08-25 15:29:12 +010030
31/**
Neale Rannsce9e0b42018-08-01 12:53:17 -070032 * 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/**
Neale Ranns0bfe5d82016-08-25 15:29:12 +010038 * @brief Enumeration of the lookup subtypes
39 */
40typedef enum lookup_sub_type_t_
41{
42 LOOKUP_SUB_TYPE_SRC,
43 LOOKUP_SUB_TYPE_DST,
Neale Ranns0f26c5a2017-03-01 15:12:11 -080044 LOOKUP_SUB_TYPE_DST_MCAST,
Neale Ranns0bfe5d82016-08-25 15:29:12 +010045 LOOKUP_SUB_TYPE_DST_TABLE_FROM_INTERFACE,
46} lookup_sub_type_t;
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 */
55lookup_dpo_t *lookup_dpo_pool;
56
57/**
58 * @brief An array of registered DPO type values for the sub-types
59 */
60static dpo_type_t lookup_dpo_sub_types[LOOKUP_SUB_TYPE_NUM];
61
62static lookup_dpo_t *
63lookup_dpo_alloc (void)
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
72static index_t
73lookup_dpo_get_index (lookup_dpo_t *lkd)
74{
75 return (lkd - lookup_dpo_pool);
76}
77
78static void
79lookup_dpo_add_or_lock_i (fib_node_index_t fib_index,
80 dpo_proto_t proto,
Neale Ranns0f26c5a2017-03-01 15:12:11 -080081 lookup_cast_t cast,
Neale Ranns0bfe5d82016-08-25 15:29:12 +010082 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;
Neale Ranns0f26c5a2017-03-01 15:12:11 -080094 lkd->lkd_cast = cast;
Neale Ranns0bfe5d82016-08-25 15:29:12 +010095
96 /*
97 * use the input type to select the lookup sub-type
98 */
99 type = 0;
100
101 switch (input)
102 {
103 case LOOKUP_INPUT_SRC_ADDR:
104 type = lookup_dpo_sub_types[LOOKUP_SUB_TYPE_SRC];
105 break;
106 case LOOKUP_INPUT_DST_ADDR:
107 switch (table_config)
108 {
109 case LOOKUP_TABLE_FROM_INPUT_INTERFACE:
110 type = lookup_dpo_sub_types[LOOKUP_SUB_TYPE_DST_TABLE_FROM_INTERFACE];
111 break;
112 case LOOKUP_TABLE_FROM_CONFIG:
113 type = lookup_dpo_sub_types[LOOKUP_SUB_TYPE_DST];
114 break;
115 }
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800116 if (LOOKUP_MULTICAST == cast)
117 {
118 type = lookup_dpo_sub_types[LOOKUP_SUB_TYPE_DST_MCAST];
119 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100120 }
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
132void
133lookup_dpo_add_or_lock_w_fib_index (fib_node_index_t fib_index,
134 dpo_proto_t proto,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800135 lookup_cast_t cast,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100136 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 {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800142 if (LOOKUP_UNICAST == cast)
143 {
Neale Ranns15002542017-09-10 04:39:11 -0700144 fib_table_lock(fib_index,
145 dpo_proto_to_fib(proto),
146 FIB_SOURCE_RR);
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800147 }
148 else
149 {
Neale Ranns15002542017-09-10 04:39:11 -0700150 mfib_table_lock(fib_index,
151 dpo_proto_to_fib(proto),
152 MFIB_SOURCE_RR);
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800153 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100154 }
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800155 lookup_dpo_add_or_lock_i(fib_index, proto, cast, input, table_config, dpo);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100156}
157
158void
159lookup_dpo_add_or_lock_w_table_id (u32 table_id,
160 dpo_proto_t proto,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800161 lookup_cast_t cast,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100162 lookup_input_t input,
163 lookup_table_t table_config,
164 dpo_id_t *dpo)
165{
166 fib_node_index_t fib_index = FIB_NODE_INDEX_INVALID;
167
168 if (LOOKUP_TABLE_FROM_CONFIG == table_config)
169 {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800170 if (LOOKUP_UNICAST == cast)
171 {
172 fib_index =
173 fib_table_find_or_create_and_lock(dpo_proto_to_fib(proto),
Neale Ranns15002542017-09-10 04:39:11 -0700174 table_id,
175 FIB_SOURCE_RR);
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800176 }
177 else
178 {
179 fib_index =
180 mfib_table_find_or_create_and_lock(dpo_proto_to_fib(proto),
Neale Ranns15002542017-09-10 04:39:11 -0700181 table_id,
182 MFIB_SOURCE_RR);
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800183 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100184 }
185
186 ASSERT(FIB_NODE_INDEX_INVALID != fib_index);
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800187 lookup_dpo_add_or_lock_i(fib_index, proto, cast, input, table_config, dpo);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100188}
189
190u8*
191format_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
198 if (LOOKUP_TABLE_FROM_INPUT_INTERFACE == lkd->lkd_table)
199 {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800200 s = format(s, "%s,%s lookup in interface's %U table",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100201 lookup_input_names[lkd->lkd_input],
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800202 lookup_cast_names[lkd->lkd_cast],
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100203 format_dpo_proto, lkd->lkd_proto);
204 }
205 else
206 {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800207 if (LOOKUP_UNICAST == lkd->lkd_cast)
208 {
209 s = format(s, "%s,%s lookup in %U",
210 lookup_input_names[lkd->lkd_input],
211 lookup_cast_names[lkd->lkd_cast],
212 format_fib_table_name, lkd->lkd_fib_index,
213 dpo_proto_to_fib(lkd->lkd_proto));
214 }
215 else
216 {
217 s = format(s, "%s,%s lookup in %U",
218 lookup_input_names[lkd->lkd_input],
219 lookup_cast_names[lkd->lkd_cast],
220 format_mfib_table_name, lkd->lkd_fib_index,
221 dpo_proto_to_fib(lkd->lkd_proto));
222 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100223 }
224 return (s);
225}
226
227static void
228lookup_dpo_lock (dpo_id_t *dpo)
229{
230 lookup_dpo_t *lkd;
231
232 lkd = lookup_dpo_get(dpo->dpoi_index);
233
234 lkd->lkd_locks++;
235}
236
237static void
238lookup_dpo_unlock (dpo_id_t *dpo)
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 {
248 if (LOOKUP_TABLE_FROM_CONFIG == lkd->lkd_table)
249 {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800250 if (LOOKUP_UNICAST == lkd->lkd_cast)
251 {
252 fib_table_unlock(lkd->lkd_fib_index,
Neale Ranns15002542017-09-10 04:39:11 -0700253 dpo_proto_to_fib(lkd->lkd_proto),
254 FIB_SOURCE_RR);
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800255 }
256 else
257 {
258 mfib_table_unlock(lkd->lkd_fib_index,
Neale Ranns15002542017-09-10 04:39:11 -0700259 dpo_proto_to_fib(lkd->lkd_proto),
260 MFIB_SOURCE_RR);
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800261 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100262 }
263 pool_put(lookup_dpo_pool, lkd);
264 }
265}
266
267always_inline void
268ip4_src_fib_lookup_one (u32 src_fib_index0,
269 const ip4_address_t * addr0,
270 u32 * src_adj_index0)
271{
Neale Ranns04a75e32017-03-23 06:46:01 -0700272 ip4_fib_mtrie_leaf_t leaf0;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100273 ip4_fib_mtrie_t * mtrie0;
274
275 mtrie0 = &ip4_fib_get (src_fib_index0)->mtrie;
276
Neale Ranns04a75e32017-03-23 06:46:01 -0700277 leaf0 = ip4_fib_mtrie_lookup_step_one (mtrie0, addr0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100278 leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 2);
279 leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 3);
280
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100281 src_adj_index0[0] = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
282}
283
284always_inline void
285ip4_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
Neale Ranns04a75e32017-03-23 06:46:01 -0700298 leaf0 = ip4_fib_mtrie_lookup_step_one (mtrie0, addr0);
299 leaf1 = ip4_fib_mtrie_lookup_step_one (mtrie1, addr1);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100300
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100301 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
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100307 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 */
314typedef struct lookup_trace_t_
315{
316 union {
317 ip46_address_t addr;
318 mpls_unicast_header_t hdr;
319 };
320 fib_node_index_t fib_index;
321 index_t lbi;
322} lookup_trace_t;
323
324
325always_inline uword
326lookup_dpo_ip4_inline (vlib_main_t * vm,
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;
Damjan Marion586afd72017-04-05 19:18:20 +0200333 u32 thread_index = vlib_get_thread_index();
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100334 vlib_combined_counter_main_t * cm = &load_balance_main.lbm_to_counters;
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
Neale Rannsd3b85b02016-10-22 15:17:21 -0700347 while (n_left_from >= 4 && n_left_to_next > 2)
348 {
Neale Ranns5e575b12016-10-03 09:40:25 +0100349 u32 bi0, lkdi0, lbi0, fib_index0, next0, hash_c0;
350 flow_hash_config_t flow_hash_config0;
Neale Rannsd3b85b02016-10-22 15:17:21 -0700351 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;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100365
Neale Rannsd3b85b02016-10-22 15:17:21 -0700366 /* Prefetch next iteration. */
367 {
368 vlib_buffer_t * p2, * p3;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100369
Neale Rannsd3b85b02016-10-22 15:17:21 -0700370 p2 = vlib_get_buffer (vm, from[2]);
371 p3 = vlib_get_buffer (vm, from[3]);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100372
Neale Rannsd3b85b02016-10-22 15:17:21 -0700373 vlib_prefetch_buffer_header (p2, LOAD);
374 vlib_prefetch_buffer_header (p3, LOAD);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100375
Neale Rannsd3b85b02016-10-22 15:17:21 -0700376 CLIB_PREFETCH (p2->data, CLIB_CACHE_LINE_BYTES, STORE);
377 CLIB_PREFETCH (p3->data, CLIB_CACHE_LINE_BYTES, STORE);
378 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100379
Neale Rannsd3b85b02016-10-22 15:17:21 -0700380 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;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100388
Neale Rannsd3b85b02016-10-22 15:17:21 -0700389 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 =
407 ip4_fib_table_get_index_for_sw_if_index(
408 vnet_buffer(b0)->sw_if_index[VLIB_RX]);
409 fib_index1 =
410 ip4_fib_table_get_index_for_sw_if_index(
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 */
Neale Ranns450cd302016-11-09 17:49:42 +0000434 ip4_src_fib_lookup_two (fib_index0, fib_index1,
435 input_addr0, input_addr1,
436 &lbi0, &lbi1);
Neale Rannsd3b85b02016-10-22 15:17:21 -0700437 lb0 = load_balance_get(lbi0);
438 lb1 = load_balance_get(lbi1);
439
Neale Rannscb630ff2016-12-14 13:31:29 +0100440 vnet_buffer(b0)->sw_if_index[VLIB_TX] = fib_index0;
441 vnet_buffer(b1)->sw_if_index[VLIB_TX] = fib_index1;
442
Neale Rannsd3b85b02016-10-22 15:17:21 -0700443 /* 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
473 vlib_increment_combined_counter
Damjan Marion586afd72017-04-05 19:18:20 +0200474 (cm, thread_index, lbi0, 1,
Neale Rannsd3b85b02016-10-22 15:17:21 -0700475 vlib_buffer_length_in_chain (vm, b0));
476 vlib_increment_combined_counter
Damjan Marion586afd72017-04-05 19:18:20 +0200477 (cm, thread_index, lbi1, 1,
Neale Rannsd3b85b02016-10-22 15:17:21 -0700478 vlib_buffer_length_in_chain (vm, b1));
479
Neale Rannsce9e0b42018-08-01 12:53:17 -0700480 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
Neale Rannsd3b85b02016-10-22 15:17:21 -0700497 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 =
551 ip4_fib_table_get_index_for_sw_if_index(
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);
Neale Ranns5e575b12016-10-03 09:40:25 +0100574
Neale Rannscb630ff2016-12-14 13:31:29 +0100575 vnet_buffer(b0)->sw_if_index[VLIB_TX] = fib_index0;
576
Neale Ranns5e575b12016-10-03 09:40:25 +0100577 /* 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))
Neale Rannsd3b85b02016-10-22 15:17:21 -0700581 {
Neale Ranns5e575b12016-10-03 09:40:25 +0100582 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);
Neale Rannsd3b85b02016-10-22 15:17:21 -0700585 }
Neale Ranns5e575b12016-10-03 09:40:25 +0100586
587 dpo0 = load_balance_get_bucket_i(lb0,
588 (hash_c0 &
589 (lb0->lb_n_buckets_minus_1)));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100590
Neale Rannsd3b85b02016-10-22 15:17:21 -0700591 next0 = dpo0->dpoi_next_node;
592 vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100593
Neale Rannsd3b85b02016-10-22 15:17:21 -0700594 vlib_increment_combined_counter
Damjan Marion586afd72017-04-05 19:18:20 +0200595 (cm, thread_index, lbi0, 1,
Neale Rannsd3b85b02016-10-22 15:17:21 -0700596 vlib_buffer_length_in_chain (vm, b0));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100597
Neale Rannsce9e0b42018-08-01 12:53:17 -0700598 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
Neale Rannsd3b85b02016-10-22 15:17:21 -0700608 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 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100616
Neale Rannsd3b85b02016-10-22 15:17:21 -0700617 vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
618 n_left_to_next, bi0, next0);
619 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100620 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
621 }
622 return from_frame->n_vectors;
623}
624
625static u8 *
626format_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 *);
Christophe Fontained3c008d2017-10-02 18:10:54 +0200631 u32 indent = format_get_indent (s);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100632 s = format (s, "%U fib-index:%d addr:%U load-balance:%d",
633 format_white_space, indent,
634 t->fib_index,
635 format_ip46_address, &t->addr, IP46_TYPE_ANY,
636 t->lbi);
637 return s;
638}
639
Damjan Marion2574d9f2018-06-26 14:45:49 +0200640static uword
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100641lookup_ip4_dst (vlib_main_t * vm,
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
648VLIB_REGISTER_NODE (lookup_ip4_dst_node) = {
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};
655VLIB_NODE_FUNCTION_MULTIARCH (lookup_ip4_dst_node, lookup_ip4_dst)
656
Damjan Marion2574d9f2018-06-26 14:45:49 +0200657static uword
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100658lookup_ip4_dst_itf (vlib_main_t * vm,
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
665VLIB_REGISTER_NODE (lookup_ip4_dst_itf_node) = {
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};
672VLIB_NODE_FUNCTION_MULTIARCH (lookup_ip4_dst_itf_node, lookup_ip4_dst_itf)
673
Damjan Marion2574d9f2018-06-26 14:45:49 +0200674static uword
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100675lookup_ip4_src (vlib_main_t * vm,
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
682VLIB_REGISTER_NODE (lookup_ip4_src_node) = {
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};
689VLIB_NODE_FUNCTION_MULTIARCH (lookup_ip4_src_node, lookup_ip4_src)
690
691always_inline uword
692lookup_dpo_ip6_inline (vlib_main_t * vm,
693 vlib_node_runtime_t * node,
694 vlib_frame_t * from_frame,
Billy McFallcfcf1e22016-10-14 09:51:49 -0400695 int input_src_addr,
696 int table_from_interface)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100697{
698 vlib_combined_counter_main_t * cm = &load_balance_main.lbm_to_counters;
699 u32 n_left_from, next_index, * from, * to_next;
Damjan Marion586afd72017-04-05 19:18:20 +0200700 u32 thread_index = vlib_get_thread_index();
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100701
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
Neale Rannsd3b85b02016-10-22 15:17:21 -0700713 while (n_left_from >= 4 && n_left_to_next > 2)
714 {
715 u32 bi0, lkdi0, lbi0, fib_index0, next0, hash_c0;
Neale Ranns5e575b12016-10-03 09:40:25 +0100716 flow_hash_config_t flow_hash_config0;
Neale Rannsd3b85b02016-10-22 15:17:21 -0700717 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;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100731
Neale Rannsd3b85b02016-10-22 15:17:21 -0700732 /* Prefetch next iteration. */
733 {
734 vlib_buffer_t * p2, * p3;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100735
Neale Rannsd3b85b02016-10-22 15:17:21 -0700736 p2 = vlib_get_buffer (vm, from[2]);
737 p3 = vlib_get_buffer (vm, from[3]);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100738
Neale Rannsd3b85b02016-10-22 15:17:21 -0700739 vlib_prefetch_buffer_header (p2, LOAD);
740 vlib_prefetch_buffer_header (p3, LOAD);
Billy McFallcfcf1e22016-10-14 09:51:49 -0400741
Neale Rannsd3b85b02016-10-22 15:17:21 -0700742 CLIB_PREFETCH (p2->data, CLIB_CACHE_LINE_BYTES, STORE);
743 CLIB_PREFETCH (p3->data, CLIB_CACHE_LINE_BYTES, STORE);
744 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100745
Neale Rannsd3b85b02016-10-22 15:17:21 -0700746 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;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100754
Neale Rannsd3b85b02016-10-22 15:17:21 -0700755 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 =
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000773 ip6_fib_table_get_index_for_sw_if_index(
Neale Rannsd3b85b02016-10-22 15:17:21 -0700774 vnet_buffer(b0)->sw_if_index[VLIB_RX]);
775 fib_index1 =
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000776 ip6_fib_table_get_index_for_sw_if_index(
Neale Rannsd3b85b02016-10-22 15:17:21 -0700777 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 */
800 lbi0 = ip6_fib_table_fwding_lookup(&ip6_main,
801 fib_index0,
802 input_addr0);
803 lbi1 = ip6_fib_table_fwding_lookup(&ip6_main,
804 fib_index1,
805 input_addr1);
806 lb0 = load_balance_get(lbi0);
807 lb1 = load_balance_get(lbi1);
808
Neale Rannscb630ff2016-12-14 13:31:29 +0100809 vnet_buffer(b0)->sw_if_index[VLIB_TX] = fib_index0;
810 vnet_buffer(b1)->sw_if_index[VLIB_TX] = fib_index1;
811
Neale Rannsd3b85b02016-10-22 15:17:21 -0700812 /* 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
Neale Rannsce9e0b42018-08-01 12:53:17 -0700816 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
Neale Rannsd3b85b02016-10-22 15:17:21 -0700833 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
859 vlib_increment_combined_counter
Damjan Marion586afd72017-04-05 19:18:20 +0200860 (cm, thread_index, lbi0, 1,
Neale Rannsd3b85b02016-10-22 15:17:21 -0700861 vlib_buffer_length_in_chain (vm, b0));
862 vlib_increment_combined_counter
Damjan Marion586afd72017-04-05 19:18:20 +0200863 (cm, thread_index, lbi1, 1,
Neale Rannsd3b85b02016-10-22 15:17:21 -0700864 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 =
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000918 ip6_fib_table_get_index_for_sw_if_index(
Neale Rannsd3b85b02016-10-22 15:17:21 -0700919 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 */
939 lbi0 = ip6_fib_table_fwding_lookup(&ip6_main,
940 fib_index0,
941 input_addr0);
942 lb0 = load_balance_get(lbi0);
Neale Ranns5e575b12016-10-03 09:40:25 +0100943
Neale Rannscb630ff2016-12-14 13:31:29 +0100944 vnet_buffer(b0)->sw_if_index[VLIB_TX] = fib_index0;
945
Neale Ranns5e575b12016-10-03 09:40:25 +0100946 /* 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))
Neale Rannsd3b85b02016-10-22 15:17:21 -0700950 {
Neale Ranns5e575b12016-10-03 09:40:25 +0100951 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);
Neale Rannsd3b85b02016-10-22 15:17:21 -0700954 }
Neale Ranns5e575b12016-10-03 09:40:25 +0100955
956 dpo0 = load_balance_get_bucket_i(lb0,
957 (hash_c0 &
958 (lb0->lb_n_buckets_minus_1)));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100959
Neale Rannsd3b85b02016-10-22 15:17:21 -0700960 next0 = dpo0->dpoi_next_node;
961 vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100962
Neale Rannsce9e0b42018-08-01 12:53:17 -0700963 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
Neale Rannsd3b85b02016-10-22 15:17:21 -0700973 vlib_increment_combined_counter
Damjan Marion586afd72017-04-05 19:18:20 +0200974 (cm, thread_index, lbi0, 1,
Neale Rannsd3b85b02016-10-22 15:17:21 -0700975 vlib_buffer_length_in_chain (vm, b0));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100976
Neale Rannsd3b85b02016-10-22 15:17:21 -0700977 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 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100988 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
989 }
990 return from_frame->n_vectors;
991}
992
Damjan Marion2574d9f2018-06-26 14:45:49 +0200993static uword
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100994lookup_ip6_dst (vlib_main_t * vm,
995 vlib_node_runtime_t * node,
996 vlib_frame_t * from_frame)
997{
Billy McFallcfcf1e22016-10-14 09:51:49 -0400998 return (lookup_dpo_ip6_inline(vm, node, from_frame, 0 /*use src*/, 0));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100999}
1000
1001VLIB_REGISTER_NODE (lookup_ip6_dst_node) = {
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};
1008VLIB_NODE_FUNCTION_MULTIARCH (lookup_ip6_dst_node, lookup_ip6_dst)
1009
Damjan Marion2574d9f2018-06-26 14:45:49 +02001010static uword
Billy McFallcfcf1e22016-10-14 09:51:49 -04001011lookup_ip6_dst_itf (vlib_main_t * vm,
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
1018VLIB_REGISTER_NODE (lookup_ip6_dst_itf_node) = {
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};
1025VLIB_NODE_FUNCTION_MULTIARCH (lookup_ip6_dst_itf_node, lookup_ip6_dst_itf)
1026
Damjan Marion2574d9f2018-06-26 14:45:49 +02001027static uword
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001028lookup_ip6_src (vlib_main_t * vm,
1029 vlib_node_runtime_t * node,
1030 vlib_frame_t * from_frame)
1031{
Billy McFallcfcf1e22016-10-14 09:51:49 -04001032 return (lookup_dpo_ip6_inline(vm, node, from_frame, 1, 0));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001033}
1034
1035VLIB_REGISTER_NODE (lookup_ip6_src_node) = {
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};
1042VLIB_NODE_FUNCTION_MULTIARCH (lookup_ip6_src_node, lookup_ip6_src)
1043
1044always_inline uword
1045lookup_dpo_mpls_inline (vlib_main_t * vm,
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;
Damjan Marion586afd72017-04-05 19:18:20 +02001051 u32 thread_index = vlib_get_thread_index();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001052 vlib_combined_counter_main_t * cm = &load_balance_main.lbm_to_counters;
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 {
Neale Ranns6af1c042017-05-26 03:48:53 -07001070 u32 bi0, lkdi0, lbi0, fib_index0, next0, hash0;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001071 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 =
1098 mpls_fib_table_get_index_for_sw_if_index(
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
Neale Ranns6af1c042017-05-26 03:48:53 -07001114
1115 if (MPLS_IS_REPLICATE & lbi0)
1116 {
1117 next0 = mpls_lookup_to_replicate_edge;
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 =
1130 mpls_compute_flow_hash(hdr0, lb0->lb_hash_config);
1131 dpo0 = load_balance_get_fwd_bucket
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
1143 vlib_increment_combined_counter
1144 (cm, thread_index, lbi0, 1,
1145 vlib_buffer_length_in_chain (vm, b0));
1146 }
1147
Neale Rannsce9e0b42018-08-01 12:53:17 -07001148 vnet_buffer (b0)->mpls.ttl = ((char*)hdr0)[3];
Neale Ranns6af1c042017-05-26 03:48:53 -07001149 vnet_buffer (b0)->mpls.exp = (((char*)hdr0)[2] & 0xe) >> 1;
1150 vnet_buffer (b0)->mpls.first = 1;
1151 vlib_buffer_advance(b0, sizeof(*hdr0));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001152
Neale Rannsce9e0b42018-08-01 12:53:17 -07001153 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
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001163 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
1180static u8 *
1181format_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 *);
Christophe Fontained3c008d2017-10-02 18:10:54 +02001186 u32 indent = format_get_indent (s);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001187 mpls_unicast_header_t hdr;
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
Damjan Marion2574d9f2018-06-26 14:45:49 +02001199static uword
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001200lookup_mpls_dst (vlib_main_t * vm,
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
1207VLIB_REGISTER_NODE (lookup_mpls_dst_node) = {
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};
1215VLIB_NODE_FUNCTION_MULTIARCH (lookup_mpls_dst_node, lookup_mpls_dst)
1216
Damjan Marion2574d9f2018-06-26 14:45:49 +02001217static uword
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001218lookup_mpls_dst_itf (vlib_main_t * vm,
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
1225VLIB_REGISTER_NODE (lookup_mpls_dst_itf_node) = {
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};
1233VLIB_NODE_FUNCTION_MULTIARCH (lookup_mpls_dst_itf_node, lookup_mpls_dst_itf)
1234
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001235typedef enum lookup_ip_dst_mcast_next_t_ {
Neale Rannsce9e0b42018-08-01 12:53:17 -07001236 LOOKUP_IP_DST_MCAST_NEXT_DROP,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001237 LOOKUP_IP_DST_MCAST_NEXT_RPF,
1238 LOOKUP_IP_DST_MCAST_N_NEXT,
1239} mfib_forward_lookup_next_t;
1240
1241always_inline uword
1242lookup_dpo_ip_dst_mcast_inline (vlib_main_t * vm,
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;
1283 next0 = LOOKUP_IP_DST_MCAST_NEXT_RPF;
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
Neale Rannsce9e0b42018-08-01 12:53:17 -07001323 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))
1331 next0 = LOOKUP_IP_DST_MCAST_NEXT_DROP;
1332
Neale Ranns31426c62017-05-24 10:32:58 -07001333 vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001334 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
Damjan Marion2574d9f2018-06-26 14:45:49 +02001341static uword
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001342lookup_ip4_dst_mcast (vlib_main_t * vm,
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
1349VLIB_REGISTER_NODE (lookup_ip4_dst_mcast_node) = {
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 = {
Neale Rannsce9e0b42018-08-01 12:53:17 -07001357 [LOOKUP_IP_DST_MCAST_NEXT_DROP] = "ip4-drop",
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001358 [LOOKUP_IP_DST_MCAST_NEXT_RPF] = "ip4-mfib-forward-rpf",
1359 },
1360};
1361VLIB_NODE_FUNCTION_MULTIARCH (lookup_ip4_dst_mcast_node,
1362 lookup_ip4_dst_mcast)
1363
Damjan Marion2574d9f2018-06-26 14:45:49 +02001364static uword
Neale Ranns31426c62017-05-24 10:32:58 -07001365lookup_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
1372VLIB_REGISTER_NODE (lookup_ip6_dst_mcast_node) = {
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 = {
Neale Rannsce9e0b42018-08-01 12:53:17 -07001380 [LOOKUP_IP_DST_MCAST_NEXT_DROP] = "ip6-drop",
Neale Ranns31426c62017-05-24 10:32:58 -07001381 [LOOKUP_IP_DST_MCAST_NEXT_RPF] = "ip6-mfib-forward-rpf",
1382 },
1383};
1384VLIB_NODE_FUNCTION_MULTIARCH (lookup_ip6_dst_mcast_node,
1385 lookup_ip6_dst_mcast)
1386
Neale Ranns6c3ebcc2016-10-02 21:20:15 +01001387static void
1388lookup_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
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001396const static dpo_vft_t lkd_vft = {
1397 .dv_lock = lookup_dpo_lock,
1398 .dv_unlock = lookup_dpo_unlock,
1399 .dv_format = format_lookup_dpo,
1400};
Neale Ranns6c3ebcc2016-10-02 21:20:15 +01001401const static dpo_vft_t lkd_vft_w_mem_show = {
1402 .dv_lock = lookup_dpo_lock,
1403 .dv_unlock = lookup_dpo_unlock,
1404 .dv_format = format_lookup_dpo,
1405 .dv_mem_show = lookup_dpo_mem_show,
1406};
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001407
1408const static char* const lookup_src_ip4_nodes[] =
1409{
1410 "lookup-ip4-src",
1411 NULL,
1412};
1413const static char* const lookup_src_ip6_nodes[] =
1414{
1415 "lookup-ip6-src",
1416 NULL,
1417};
1418const static char* const * const lookup_src_nodes[DPO_PROTO_NUM] =
1419{
1420 [DPO_PROTO_IP4] = lookup_src_ip4_nodes,
1421 [DPO_PROTO_IP6] = lookup_src_ip6_nodes,
1422 [DPO_PROTO_MPLS] = NULL,
1423};
1424
1425const static char* const lookup_dst_ip4_nodes[] =
1426{
1427 "lookup-ip4-dst",
1428 NULL,
1429};
1430const static char* const lookup_dst_ip6_nodes[] =
1431{
1432 "lookup-ip6-dst",
1433 NULL,
1434};
1435const static char* const lookup_dst_mpls_nodes[] =
1436{
1437 "lookup-mpls-dst",
1438 NULL,
1439};
1440const static char* const * const lookup_dst_nodes[DPO_PROTO_NUM] =
1441{
1442 [DPO_PROTO_IP4] = lookup_dst_ip4_nodes,
1443 [DPO_PROTO_IP6] = lookup_dst_ip6_nodes,
1444 [DPO_PROTO_MPLS] = lookup_dst_mpls_nodes,
1445};
1446
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001447const static char* const lookup_dst_mcast_ip4_nodes[] =
1448{
1449 "lookup-ip4-dst-mcast",
1450 NULL,
1451};
1452const static char* const lookup_dst_mcast_ip6_nodes[] =
1453{
1454 "lookup-ip6-dst-mcast",
1455 NULL,
1456};
1457const static char* const * const lookup_dst_mcast_nodes[DPO_PROTO_NUM] =
1458{
1459 [DPO_PROTO_IP4] = lookup_dst_mcast_ip4_nodes,
1460 [DPO_PROTO_IP6] = lookup_dst_mcast_ip6_nodes,
1461};
1462
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001463const static char* const lookup_dst_from_interface_ip4_nodes[] =
1464{
1465 "lookup-ip4-dst-itf",
1466 NULL,
1467};
1468const static char* const lookup_dst_from_interface_ip6_nodes[] =
1469{
1470 "lookup-ip6-dst-itf",
1471 NULL,
1472};
1473const static char* const lookup_dst_from_interface_mpls_nodes[] =
1474{
1475 "lookup-mpls-dst-itf",
1476 NULL,
1477};
1478const static char* const * const lookup_dst_from_interface_nodes[DPO_PROTO_NUM] =
1479{
1480 [DPO_PROTO_IP4] = lookup_dst_from_interface_ip4_nodes,
1481 [DPO_PROTO_IP6] = lookup_dst_from_interface_ip6_nodes,
1482 [DPO_PROTO_MPLS] = lookup_dst_from_interface_mpls_nodes,
1483};
1484
Neale Ranns5779a442018-08-22 09:50:25 -07001485static clib_error_t *
1486lookup_dpo_show (vlib_main_t * vm,
1487 unformat_input_t * input,
1488 vlib_cli_command_t * cmd)
1489{
1490 index_t lkdi = INDEX_INVALID;
1491
1492 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1493 {
1494 if (unformat (input, "%d", &lkdi))
1495 ;
1496 else
1497 break;
1498 }
1499
1500 if (INDEX_INVALID != lkdi)
1501 {
1502 vlib_cli_output (vm, "%U", format_lookup_dpo, lkdi);
1503 }
1504 else
1505 {
1506 lookup_dpo_t *lkd;
1507
1508 pool_foreach(lkd, lookup_dpo_pool,
1509 ({
1510 vlib_cli_output (vm, "[@%d] %U",
1511 lookup_dpo_get_index(lkd),
1512 format_lookup_dpo,
1513 lookup_dpo_get_index(lkd));
1514 }));
1515 }
1516
1517 return 0;
1518}
1519
1520VLIB_CLI_COMMAND (replicate_show_command, static) = {
1521 .path = "show lookup-dpo",
1522 .short_help = "show lookup-dpo [<index>]",
1523 .function = lookup_dpo_show,
1524};
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001525
1526void
1527lookup_dpo_module_init (void)
1528{
Neale Ranns6c3ebcc2016-10-02 21:20:15 +01001529 dpo_register(DPO_LOOKUP, &lkd_vft_w_mem_show, NULL);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001530
1531 /*
1532 * There are various sorts of lookup; src or dst addr v4 /v6 etc.
1533 * there isn't an object type for each (there is only the lookup_dpo_t),
1534 * but, for performance reasons, there is a data plane function, and hence
1535 * VLIB node for each. VLIB graph node construction is based on DPO types
1536 * so we create sub-types.
1537 */
1538 lookup_dpo_sub_types[LOOKUP_SUB_TYPE_SRC] =
1539 dpo_register_new_type(&lkd_vft, lookup_src_nodes);
1540 lookup_dpo_sub_types[LOOKUP_SUB_TYPE_DST] =
1541 dpo_register_new_type(&lkd_vft, lookup_dst_nodes);
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001542 lookup_dpo_sub_types[LOOKUP_SUB_TYPE_DST_MCAST] =
1543 dpo_register_new_type(&lkd_vft, lookup_dst_mcast_nodes);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001544 lookup_dpo_sub_types[LOOKUP_SUB_TYPE_DST_TABLE_FROM_INTERFACE] =
Billy McFallcfcf1e22016-10-14 09:51:49 -04001545 dpo_register_new_type(&lkd_vft, lookup_dst_from_interface_nodes);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001546}