blob: ec2cd02653b0e9b82af2e568708fecae657d36b2 [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
Filip Tehlareb9a27f2019-03-07 01:42:11 -0800640VLIB_NODE_FN (lookup_ip4_dst_node) (vlib_main_t * vm,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100641 vlib_node_runtime_t * node,
642 vlib_frame_t * from_frame)
643{
644 return (lookup_dpo_ip4_inline(vm, node, from_frame, 0, 0));
645}
646
647VLIB_REGISTER_NODE (lookup_ip4_dst_node) = {
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100648 .name = "lookup-ip4-dst",
649 .vector_size = sizeof (u32),
650 .sibling_of = "ip4-lookup",
651 .format_trace = format_lookup_trace,
652};
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100653
Filip Tehlareb9a27f2019-03-07 01:42:11 -0800654VLIB_NODE_FN (lookup_ip4_dst_itf_node) (vlib_main_t * vm,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100655 vlib_node_runtime_t * node,
656 vlib_frame_t * from_frame)
657{
658 return (lookup_dpo_ip4_inline(vm, node, from_frame, 0, 1));
659}
660
661VLIB_REGISTER_NODE (lookup_ip4_dst_itf_node) = {
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100662 .name = "lookup-ip4-dst-itf",
663 .vector_size = sizeof (u32),
664 .sibling_of = "ip4-lookup",
665 .format_trace = format_lookup_trace,
666};
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100667
Filip Tehlareb9a27f2019-03-07 01:42:11 -0800668VLIB_NODE_FN (lookup_ip4_src_node) (vlib_main_t * vm,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100669 vlib_node_runtime_t * node,
670 vlib_frame_t * from_frame)
671{
672 return (lookup_dpo_ip4_inline(vm, node, from_frame, 1, 0));
673}
674
675VLIB_REGISTER_NODE (lookup_ip4_src_node) = {
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100676 .name = "lookup-ip4-src",
677 .vector_size = sizeof (u32),
678 .format_trace = format_lookup_trace,
679 .sibling_of = "ip4-lookup",
680};
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100681
682always_inline uword
683lookup_dpo_ip6_inline (vlib_main_t * vm,
684 vlib_node_runtime_t * node,
685 vlib_frame_t * from_frame,
Billy McFallcfcf1e22016-10-14 09:51:49 -0400686 int input_src_addr,
687 int table_from_interface)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100688{
689 vlib_combined_counter_main_t * cm = &load_balance_main.lbm_to_counters;
690 u32 n_left_from, next_index, * from, * to_next;
Damjan Marion586afd72017-04-05 19:18:20 +0200691 u32 thread_index = vlib_get_thread_index();
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100692
693 from = vlib_frame_vector_args (from_frame);
694 n_left_from = from_frame->n_vectors;
695
696 next_index = node->cached_next_index;
697
698 while (n_left_from > 0)
699 {
700 u32 n_left_to_next;
701
702 vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
703
Neale Rannsd3b85b02016-10-22 15:17:21 -0700704 while (n_left_from >= 4 && n_left_to_next > 2)
705 {
706 u32 bi0, lkdi0, lbi0, fib_index0, next0, hash_c0;
Neale Ranns5e575b12016-10-03 09:40:25 +0100707 flow_hash_config_t flow_hash_config0;
Neale Rannsd3b85b02016-10-22 15:17:21 -0700708 const ip6_address_t *input_addr0;
709 const load_balance_t *lb0;
710 const lookup_dpo_t * lkd0;
711 const ip6_header_t * ip0;
712 const dpo_id_t *dpo0;
713 vlib_buffer_t * b0;
714 u32 bi1, lkdi1, lbi1, fib_index1, next1, hash_c1;
715 flow_hash_config_t flow_hash_config1;
716 const ip6_address_t *input_addr1;
717 const load_balance_t *lb1;
718 const lookup_dpo_t * lkd1;
719 const ip6_header_t * ip1;
720 const dpo_id_t *dpo1;
721 vlib_buffer_t * b1;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100722
Neale Rannsd3b85b02016-10-22 15:17:21 -0700723 /* Prefetch next iteration. */
724 {
725 vlib_buffer_t * p2, * p3;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100726
Neale Rannsd3b85b02016-10-22 15:17:21 -0700727 p2 = vlib_get_buffer (vm, from[2]);
728 p3 = vlib_get_buffer (vm, from[3]);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100729
Neale Rannsd3b85b02016-10-22 15:17:21 -0700730 vlib_prefetch_buffer_header (p2, LOAD);
731 vlib_prefetch_buffer_header (p3, LOAD);
Billy McFallcfcf1e22016-10-14 09:51:49 -0400732
Neale Rannsd3b85b02016-10-22 15:17:21 -0700733 CLIB_PREFETCH (p2->data, CLIB_CACHE_LINE_BYTES, STORE);
734 CLIB_PREFETCH (p3->data, CLIB_CACHE_LINE_BYTES, STORE);
735 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100736
Neale Rannsd3b85b02016-10-22 15:17:21 -0700737 bi0 = from[0];
738 to_next[0] = bi0;
739 bi1 = from[1];
740 to_next[1] = bi1;
741 from += 2;
742 to_next += 2;
743 n_left_from -= 2;
744 n_left_to_next -= 2;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100745
Neale Rannsd3b85b02016-10-22 15:17:21 -0700746 b0 = vlib_get_buffer (vm, bi0);
747 ip0 = vlib_buffer_get_current (b0);
748 b1 = vlib_get_buffer (vm, bi1);
749 ip1 = vlib_buffer_get_current (b1);
750
751 /* dst lookup was done by ip6 lookup */
752 lkdi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
753 lkdi1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
754 lkd0 = lookup_dpo_get(lkdi0);
755 lkd1 = lookup_dpo_get(lkdi1);
756
757 /*
758 * choose between a lookup using the fib index in the DPO
759 * or getting the FIB index from the interface.
760 */
761 if (table_from_interface)
762 {
763 fib_index0 =
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000764 ip6_fib_table_get_index_for_sw_if_index(
Neale Rannsd3b85b02016-10-22 15:17:21 -0700765 vnet_buffer(b0)->sw_if_index[VLIB_RX]);
766 fib_index1 =
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000767 ip6_fib_table_get_index_for_sw_if_index(
Neale Rannsd3b85b02016-10-22 15:17:21 -0700768 vnet_buffer(b1)->sw_if_index[VLIB_RX]);
769 }
770 else
771 {
772 fib_index0 = lkd0->lkd_fib_index;
773 fib_index1 = lkd1->lkd_fib_index;
774 }
775
776 /*
777 * choose between a source or destination address lookup in the table
778 */
779 if (input_src_addr)
780 {
781 input_addr0 = &ip0->src_address;
782 input_addr1 = &ip1->src_address;
783 }
784 else
785 {
786 input_addr0 = &ip0->dst_address;
787 input_addr1 = &ip1->dst_address;
788 }
789
790 /* do src lookup */
Simon Zhange7eba482019-08-25 15:30:45 +0800791 lbi0 = ip6_fib_table_fwding_lookup(
Neale Rannsd3b85b02016-10-22 15:17:21 -0700792 fib_index0,
793 input_addr0);
Simon Zhange7eba482019-08-25 15:30:45 +0800794 lbi1 = ip6_fib_table_fwding_lookup(
Neale Rannsd3b85b02016-10-22 15:17:21 -0700795 fib_index1,
796 input_addr1);
797 lb0 = load_balance_get(lbi0);
798 lb1 = load_balance_get(lbi1);
799
Neale Rannscb630ff2016-12-14 13:31:29 +0100800 vnet_buffer(b0)->sw_if_index[VLIB_TX] = fib_index0;
801 vnet_buffer(b1)->sw_if_index[VLIB_TX] = fib_index1;
802
Neale Rannsd3b85b02016-10-22 15:17:21 -0700803 /* Use flow hash to compute multipath adjacency. */
804 hash_c0 = vnet_buffer (b0)->ip.flow_hash = 0;
805 hash_c1 = vnet_buffer (b1)->ip.flow_hash = 0;
806
Neale Rannsce9e0b42018-08-01 12:53:17 -0700807 if (!(b0->flags & VNET_BUFFER_F_LOOP_COUNTER_VALID)) {
808 vnet_buffer2(b0)->loop_counter = 0;
809 b0->flags |= VNET_BUFFER_F_LOOP_COUNTER_VALID;
810 }
811 if (!(b1->flags & VNET_BUFFER_F_LOOP_COUNTER_VALID)) {
812 vnet_buffer2(b1)->loop_counter = 0;
813 b1->flags |= VNET_BUFFER_F_LOOP_COUNTER_VALID;
814 }
815
816 vnet_buffer2(b0)->loop_counter++;
817 vnet_buffer2(b1)->loop_counter++;
818
819 if (PREDICT_FALSE(vnet_buffer2(b0)->loop_counter > MAX_LUKPS_PER_PACKET))
820 next0 = IP_LOOKUP_NEXT_DROP;
821 if (PREDICT_FALSE(vnet_buffer2(b1)->loop_counter > MAX_LUKPS_PER_PACKET))
822 next1 = IP_LOOKUP_NEXT_DROP;
823
Neale Rannsd3b85b02016-10-22 15:17:21 -0700824 if (PREDICT_FALSE (lb0->lb_n_buckets > 1))
825 {
826 flow_hash_config0 = lb0->lb_hash_config;
827 hash_c0 = vnet_buffer (b0)->ip.flow_hash =
828 ip6_compute_flow_hash (ip0, flow_hash_config0);
829 }
830
831 if (PREDICT_FALSE (lb1->lb_n_buckets > 1))
832 {
833 flow_hash_config1 = lb1->lb_hash_config;
834 hash_c1 = vnet_buffer (b1)->ip.flow_hash =
835 ip6_compute_flow_hash (ip1, flow_hash_config1);
836 }
837
838 dpo0 = load_balance_get_bucket_i(lb0,
839 (hash_c0 &
840 (lb0->lb_n_buckets_minus_1)));
841 dpo1 = load_balance_get_bucket_i(lb1,
842 (hash_c1 &
843 (lb1->lb_n_buckets_minus_1)));
844
845 next0 = dpo0->dpoi_next_node;
846 next1 = dpo1->dpoi_next_node;
847 vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
848 vnet_buffer(b1)->ip.adj_index[VLIB_TX] = dpo1->dpoi_index;
849
850 vlib_increment_combined_counter
Damjan Marion586afd72017-04-05 19:18:20 +0200851 (cm, thread_index, lbi0, 1,
Neale Rannsd3b85b02016-10-22 15:17:21 -0700852 vlib_buffer_length_in_chain (vm, b0));
853 vlib_increment_combined_counter
Damjan Marion586afd72017-04-05 19:18:20 +0200854 (cm, thread_index, lbi1, 1,
Neale Rannsd3b85b02016-10-22 15:17:21 -0700855 vlib_buffer_length_in_chain (vm, b1));
856
857 if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
858 {
859 lookup_trace_t *tr = vlib_add_trace (vm, node,
860 b0, sizeof (*tr));
861 tr->fib_index = fib_index0;
862 tr->lbi = lbi0;
863 tr->addr.ip6 = *input_addr0;
864 }
865 if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
866 {
867 lookup_trace_t *tr = vlib_add_trace (vm, node,
868 b1, sizeof (*tr));
869 tr->fib_index = fib_index1;
870 tr->lbi = lbi1;
871 tr->addr.ip6 = *input_addr1;
872 }
873 vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next,
874 n_left_to_next, bi0, bi1,
875 next0, next1);
876 }
877 while (n_left_from > 0 && n_left_to_next > 0)
878 {
879 u32 bi0, lkdi0, lbi0, fib_index0, next0, hash_c0;
880 flow_hash_config_t flow_hash_config0;
881 const ip6_address_t *input_addr0;
882 const load_balance_t *lb0;
883 const lookup_dpo_t * lkd0;
884 const ip6_header_t * ip0;
885 const dpo_id_t *dpo0;
886 vlib_buffer_t * b0;
887
888 bi0 = from[0];
889 to_next[0] = bi0;
890 from += 1;
891 to_next += 1;
892 n_left_from -= 1;
893 n_left_to_next -= 1;
894
895 b0 = vlib_get_buffer (vm, bi0);
896 ip0 = vlib_buffer_get_current (b0);
897
898 /* dst lookup was done by ip6 lookup */
899 lkdi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
900 lkd0 = lookup_dpo_get(lkdi0);
901
902 /*
903 * choose between a lookup using the fib index in the DPO
904 * or getting the FIB index from the interface.
905 */
906 if (table_from_interface)
907 {
908 fib_index0 =
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000909 ip6_fib_table_get_index_for_sw_if_index(
Neale Rannsd3b85b02016-10-22 15:17:21 -0700910 vnet_buffer(b0)->sw_if_index[VLIB_RX]);
911 }
912 else
913 {
914 fib_index0 = lkd0->lkd_fib_index;
915 }
916
917 /*
918 * choose between a source or destination address lookup in the table
919 */
920 if (input_src_addr)
921 {
922 input_addr0 = &ip0->src_address;
923 }
924 else
925 {
926 input_addr0 = &ip0->dst_address;
927 }
928
929 /* do src lookup */
Simon Zhange7eba482019-08-25 15:30:45 +0800930 lbi0 = ip6_fib_table_fwding_lookup(
Neale Rannsd3b85b02016-10-22 15:17:21 -0700931 fib_index0,
932 input_addr0);
933 lb0 = load_balance_get(lbi0);
Neale Ranns5e575b12016-10-03 09:40:25 +0100934
Neale Rannscb630ff2016-12-14 13:31:29 +0100935 vnet_buffer(b0)->sw_if_index[VLIB_TX] = fib_index0;
936
Neale Ranns5e575b12016-10-03 09:40:25 +0100937 /* Use flow hash to compute multipath adjacency. */
938 hash_c0 = vnet_buffer (b0)->ip.flow_hash = 0;
939
940 if (PREDICT_FALSE (lb0->lb_n_buckets > 1))
Neale Rannsd3b85b02016-10-22 15:17:21 -0700941 {
Neale Ranns5e575b12016-10-03 09:40:25 +0100942 flow_hash_config0 = lb0->lb_hash_config;
943 hash_c0 = vnet_buffer (b0)->ip.flow_hash =
944 ip6_compute_flow_hash (ip0, flow_hash_config0);
Neale Rannsd3b85b02016-10-22 15:17:21 -0700945 }
Neale Ranns5e575b12016-10-03 09:40:25 +0100946
947 dpo0 = load_balance_get_bucket_i(lb0,
948 (hash_c0 &
949 (lb0->lb_n_buckets_minus_1)));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100950
Neale Rannsd3b85b02016-10-22 15:17:21 -0700951 next0 = dpo0->dpoi_next_node;
952 vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100953
Neale Rannsce9e0b42018-08-01 12:53:17 -0700954 if (!(b0->flags & VNET_BUFFER_F_LOOP_COUNTER_VALID)) {
955 vnet_buffer2(b0)->loop_counter = 0;
956 b0->flags |= VNET_BUFFER_F_LOOP_COUNTER_VALID;
957 }
958
959 vnet_buffer2(b0)->loop_counter++;
960
961 if (PREDICT_FALSE(vnet_buffer2(b0)->loop_counter > MAX_LUKPS_PER_PACKET))
962 next0 = IP_LOOKUP_NEXT_DROP;
963
Neale Rannsd3b85b02016-10-22 15:17:21 -0700964 vlib_increment_combined_counter
Damjan Marion586afd72017-04-05 19:18:20 +0200965 (cm, thread_index, lbi0, 1,
Neale Rannsd3b85b02016-10-22 15:17:21 -0700966 vlib_buffer_length_in_chain (vm, b0));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100967
Neale Rannsd3b85b02016-10-22 15:17:21 -0700968 if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
969 {
970 lookup_trace_t *tr = vlib_add_trace (vm, node,
971 b0, sizeof (*tr));
972 tr->fib_index = fib_index0;
973 tr->lbi = lbi0;
974 tr->addr.ip6 = *input_addr0;
975 }
976 vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
977 n_left_to_next, bi0, next0);
978 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100979 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
980 }
981 return from_frame->n_vectors;
982}
983
Filip Tehlareb9a27f2019-03-07 01:42:11 -0800984VLIB_NODE_FN (lookup_ip6_dst_node) (vlib_main_t * vm,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100985 vlib_node_runtime_t * node,
986 vlib_frame_t * from_frame)
987{
Billy McFallcfcf1e22016-10-14 09:51:49 -0400988 return (lookup_dpo_ip6_inline(vm, node, from_frame, 0 /*use src*/, 0));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100989}
990
991VLIB_REGISTER_NODE (lookup_ip6_dst_node) = {
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100992 .name = "lookup-ip6-dst",
993 .vector_size = sizeof (u32),
994 .format_trace = format_lookup_trace,
995 .sibling_of = "ip6-lookup",
996};
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100997
Filip Tehlareb9a27f2019-03-07 01:42:11 -0800998VLIB_NODE_FN (lookup_ip6_dst_itf_node) (vlib_main_t * vm,
Billy McFallcfcf1e22016-10-14 09:51:49 -0400999 vlib_node_runtime_t * node,
1000 vlib_frame_t * from_frame)
1001{
1002 return (lookup_dpo_ip6_inline(vm, node, from_frame, 0 /*use src*/, 1));
1003}
1004
1005VLIB_REGISTER_NODE (lookup_ip6_dst_itf_node) = {
Billy McFallcfcf1e22016-10-14 09:51:49 -04001006 .name = "lookup-ip6-dst-itf",
1007 .vector_size = sizeof (u32),
1008 .format_trace = format_lookup_trace,
1009 .sibling_of = "ip6-lookup",
1010};
Billy McFallcfcf1e22016-10-14 09:51:49 -04001011
Filip Tehlareb9a27f2019-03-07 01:42:11 -08001012VLIB_NODE_FN (lookup_ip6_src_node) (vlib_main_t * vm,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001013 vlib_node_runtime_t * node,
1014 vlib_frame_t * from_frame)
1015{
Billy McFallcfcf1e22016-10-14 09:51:49 -04001016 return (lookup_dpo_ip6_inline(vm, node, from_frame, 1, 0));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001017}
1018
1019VLIB_REGISTER_NODE (lookup_ip6_src_node) = {
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001020 .name = "lookup-ip6-src",
1021 .vector_size = sizeof (u32),
1022 .format_trace = format_lookup_trace,
1023 .sibling_of = "ip6-lookup",
1024};
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001025
1026always_inline uword
1027lookup_dpo_mpls_inline (vlib_main_t * vm,
1028 vlib_node_runtime_t * node,
1029 vlib_frame_t * from_frame,
1030 int table_from_interface)
1031{
1032 u32 n_left_from, next_index, * from, * to_next;
Damjan Marion586afd72017-04-05 19:18:20 +02001033 u32 thread_index = vlib_get_thread_index();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001034 vlib_combined_counter_main_t * cm = &load_balance_main.lbm_to_counters;
1035
1036 from = vlib_frame_vector_args (from_frame);
1037 n_left_from = from_frame->n_vectors;
1038
1039 next_index = node->cached_next_index;
1040
1041 while (n_left_from > 0)
1042 {
1043 u32 n_left_to_next;
1044
1045 vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
1046
1047 /* while (n_left_from >= 4 && n_left_to_next >= 2) */
1048 /* } */
1049
1050 while (n_left_from > 0 && n_left_to_next > 0)
1051 {
Neale Ranns6af1c042017-05-26 03:48:53 -07001052 u32 bi0, lkdi0, lbi0, fib_index0, next0, hash0;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001053 const mpls_unicast_header_t * hdr0;
1054 const load_balance_t *lb0;
1055 const lookup_dpo_t * lkd0;
1056 const dpo_id_t *dpo0;
1057 vlib_buffer_t * b0;
1058
1059 bi0 = from[0];
1060 to_next[0] = bi0;
1061 from += 1;
1062 to_next += 1;
1063 n_left_from -= 1;
1064 n_left_to_next -= 1;
1065
1066 b0 = vlib_get_buffer (vm, bi0);
1067 hdr0 = vlib_buffer_get_current (b0);
1068
1069 /* dst lookup was done by mpls lookup */
1070 lkdi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
1071 lkd0 = lookup_dpo_get(lkdi0);
1072
1073 /*
1074 * choose between a lookup using the fib index in the DPO
1075 * or getting the FIB index from the interface.
1076 */
1077 if (table_from_interface)
1078 {
1079 fib_index0 =
1080 mpls_fib_table_get_index_for_sw_if_index(
1081 vnet_buffer(b0)->sw_if_index[VLIB_RX]);
1082 }
1083 else
1084 {
1085 fib_index0 = lkd0->lkd_fib_index;
1086 }
1087
1088 /* do lookup */
1089 lbi0 = mpls_fib_table_forwarding_lookup (fib_index0, hdr0);
1090 lb0 = load_balance_get(lbi0);
1091 dpo0 = load_balance_get_bucket_i(lb0, 0);
1092
1093 next0 = dpo0->dpoi_next_node;
1094 vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
1095
Neale Ranns6af1c042017-05-26 03:48:53 -07001096
1097 if (MPLS_IS_REPLICATE & lbi0)
1098 {
1099 next0 = mpls_lookup_to_replicate_edge;
1100 vnet_buffer (b0)->ip.adj_index[VLIB_TX] =
1101 (lbi0 & ~MPLS_IS_REPLICATE);
1102 }
1103 else
1104 {
1105 lb0 = load_balance_get(lbi0);
1106 ASSERT (lb0->lb_n_buckets > 0);
1107 ASSERT (is_pow2 (lb0->lb_n_buckets));
1108
1109 if (PREDICT_FALSE(lb0->lb_n_buckets > 1))
1110 {
1111 hash0 = vnet_buffer (b0)->ip.flow_hash =
1112 mpls_compute_flow_hash(hdr0, lb0->lb_hash_config);
1113 dpo0 = load_balance_get_fwd_bucket
1114 (lb0,
1115 (hash0 & (lb0->lb_n_buckets_minus_1)));
1116 }
1117 else
1118 {
1119 dpo0 = load_balance_get_bucket_i (lb0, 0);
1120 }
1121 next0 = dpo0->dpoi_next_node;
1122
1123 vnet_buffer (b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
1124
1125 vlib_increment_combined_counter
1126 (cm, thread_index, lbi0, 1,
1127 vlib_buffer_length_in_chain (vm, b0));
1128 }
1129
Neale Rannsce9e0b42018-08-01 12:53:17 -07001130 vnet_buffer (b0)->mpls.ttl = ((char*)hdr0)[3];
Neale Ranns6af1c042017-05-26 03:48:53 -07001131 vnet_buffer (b0)->mpls.exp = (((char*)hdr0)[2] & 0xe) >> 1;
1132 vnet_buffer (b0)->mpls.first = 1;
1133 vlib_buffer_advance(b0, sizeof(*hdr0));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001134
Neale Rannsce9e0b42018-08-01 12:53:17 -07001135 if (!(b0->flags & VNET_BUFFER_F_LOOP_COUNTER_VALID)) {
1136 vnet_buffer2(b0)->loop_counter = 0;
1137 b0->flags |= VNET_BUFFER_F_LOOP_COUNTER_VALID;
1138 }
1139
1140 vnet_buffer2(b0)->loop_counter++;
1141
1142 if (PREDICT_FALSE(vnet_buffer2(b0)->loop_counter > MAX_LUKPS_PER_PACKET))
1143 next0 = MPLS_LOOKUP_NEXT_DROP;
1144
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001145 if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
1146 {
1147 lookup_trace_t *tr = vlib_add_trace (vm, node,
1148 b0, sizeof (*tr));
1149 tr->fib_index = fib_index0;
1150 tr->lbi = lbi0;
1151 tr->hdr = *hdr0;
1152 }
1153
1154 vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
1155 n_left_to_next, bi0, next0);
1156 }
1157 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1158 }
1159 return from_frame->n_vectors;
1160}
1161
1162static u8 *
1163format_lookup_mpls_trace (u8 * s, va_list * args)
1164{
1165 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
1166 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
1167 lookup_trace_t * t = va_arg (*args, lookup_trace_t *);
Christophe Fontained3c008d2017-10-02 18:10:54 +02001168 u32 indent = format_get_indent (s);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001169 mpls_unicast_header_t hdr;
1170
1171 hdr.label_exp_s_ttl = clib_net_to_host_u32(t->hdr.label_exp_s_ttl);
1172
1173 s = format (s, "%U fib-index:%d hdr:%U load-balance:%d",
1174 format_white_space, indent,
1175 t->fib_index,
1176 format_mpls_header, hdr,
1177 t->lbi);
1178 return s;
1179}
1180
Filip Tehlareb9a27f2019-03-07 01:42:11 -08001181VLIB_NODE_FN (lookup_mpls_dst_node) (vlib_main_t * vm,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001182 vlib_node_runtime_t * node,
1183 vlib_frame_t * from_frame)
1184{
1185 return (lookup_dpo_mpls_inline(vm, node, from_frame, 0));
1186}
1187
1188VLIB_REGISTER_NODE (lookup_mpls_dst_node) = {
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001189 .name = "lookup-mpls-dst",
1190 .vector_size = sizeof (u32),
1191 .sibling_of = "mpls-lookup",
1192 .format_trace = format_lookup_mpls_trace,
1193 .n_next_nodes = 0,
1194};
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001195
Filip Tehlareb9a27f2019-03-07 01:42:11 -08001196VLIB_NODE_FN (lookup_mpls_dst_itf_node) (vlib_main_t * vm,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001197 vlib_node_runtime_t * node,
1198 vlib_frame_t * from_frame)
1199{
1200 return (lookup_dpo_mpls_inline(vm, node, from_frame, 1));
1201}
1202
1203VLIB_REGISTER_NODE (lookup_mpls_dst_itf_node) = {
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001204 .name = "lookup-mpls-dst-itf",
1205 .vector_size = sizeof (u32),
1206 .sibling_of = "mpls-lookup",
1207 .format_trace = format_lookup_mpls_trace,
1208 .n_next_nodes = 0,
1209};
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001210
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001211typedef enum lookup_ip_dst_mcast_next_t_ {
Neale Rannsce9e0b42018-08-01 12:53:17 -07001212 LOOKUP_IP_DST_MCAST_NEXT_DROP,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001213 LOOKUP_IP_DST_MCAST_NEXT_RPF,
1214 LOOKUP_IP_DST_MCAST_N_NEXT,
1215} mfib_forward_lookup_next_t;
1216
1217always_inline uword
1218lookup_dpo_ip_dst_mcast_inline (vlib_main_t * vm,
1219 vlib_node_runtime_t * node,
1220 vlib_frame_t * from_frame,
1221 int is_v4)
1222{
1223 u32 n_left_from, next_index, * from, * to_next;
1224
1225 from = vlib_frame_vector_args (from_frame);
1226 n_left_from = from_frame->n_vectors;
1227
1228 next_index = LOOKUP_IP_DST_MCAST_NEXT_RPF;
1229
1230 while (n_left_from > 0)
1231 {
1232 u32 n_left_to_next;
1233
1234 vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
1235
1236 /* while (n_left_from >= 4 && n_left_to_next >= 2) */
1237 /* } */
1238
1239 while (n_left_from > 0 && n_left_to_next > 0)
1240 {
1241 u32 bi0, lkdi0, fib_index0, next0;
1242 const lookup_dpo_t * lkd0;
1243 fib_node_index_t mfei0;
1244 vlib_buffer_t * b0;
1245
1246 bi0 = from[0];
1247 to_next[0] = bi0;
1248 from += 1;
1249 to_next += 1;
1250 n_left_from -= 1;
1251 n_left_to_next -= 1;
1252
1253 b0 = vlib_get_buffer (vm, bi0);
1254
1255 /* dst lookup was done by mpls lookup */
1256 lkdi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
1257 lkd0 = lookup_dpo_get(lkdi0);
1258 fib_index0 = lkd0->lkd_fib_index;
1259 next0 = LOOKUP_IP_DST_MCAST_NEXT_RPF;
1260
1261 if (is_v4)
1262 {
1263 ip4_header_t * ip0;
1264
1265 ip0 = vlib_buffer_get_current (b0);
1266 mfei0 = ip4_mfib_table_lookup(ip4_mfib_get(fib_index0),
1267 &ip0->src_address,
1268 &ip0->dst_address,
1269 64);
1270 if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
1271 {
1272 lookup_trace_t *tr = vlib_add_trace (vm, node,
1273 b0, sizeof (*tr));
1274 tr->fib_index = fib_index0;
1275 tr->lbi = mfei0;
1276 tr->addr.ip4 = ip0->dst_address;
1277 }
1278 }
1279 else
1280 {
1281 ip6_header_t * ip0;
1282
1283 ip0 = vlib_buffer_get_current (b0);
Neale Rannsae809832018-11-23 09:00:27 -08001284 mfei0 = ip6_mfib_table_fwd_lookup(ip6_mfib_get(fib_index0),
1285 &ip0->src_address,
1286 &ip0->dst_address);
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001287 if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
1288 {
1289 lookup_trace_t *tr = vlib_add_trace (vm, node,
1290 b0, sizeof (*tr));
1291 tr->fib_index = fib_index0;
1292 tr->lbi = mfei0;
1293 tr->addr.ip6 = ip0->dst_address;
1294 }
1295 }
1296
1297 vnet_buffer (b0)->ip.adj_index[VLIB_TX] = mfei0;
1298
Neale Rannsce9e0b42018-08-01 12:53:17 -07001299 if (!(b0->flags & VNET_BUFFER_F_LOOP_COUNTER_VALID)) {
1300 vnet_buffer2(b0)->loop_counter = 0;
1301 b0->flags |= VNET_BUFFER_F_LOOP_COUNTER_VALID;
1302 }
1303
1304 vnet_buffer2(b0)->loop_counter++;
1305
1306 if (PREDICT_FALSE(vnet_buffer2(b0)->loop_counter > MAX_LUKPS_PER_PACKET))
1307 next0 = LOOKUP_IP_DST_MCAST_NEXT_DROP;
1308
Neale Ranns31426c62017-05-24 10:32:58 -07001309 vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001310 n_left_to_next, bi0, next0);
1311 }
1312 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1313 }
1314 return from_frame->n_vectors;
1315}
1316
Filip Tehlareb9a27f2019-03-07 01:42:11 -08001317VLIB_NODE_FN (lookup_ip4_dst_mcast_node) (vlib_main_t * vm,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001318 vlib_node_runtime_t * node,
1319 vlib_frame_t * from_frame)
1320{
1321 return (lookup_dpo_ip_dst_mcast_inline(vm, node, from_frame, 1));
1322}
1323
1324VLIB_REGISTER_NODE (lookup_ip4_dst_mcast_node) = {
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001325 .name = "lookup-ip4-dst-mcast",
1326 .vector_size = sizeof (u32),
1327
1328 .format_trace = format_lookup_trace,
1329 .n_next_nodes = LOOKUP_IP_DST_MCAST_N_NEXT,
1330 .next_nodes = {
Neale Rannsce9e0b42018-08-01 12:53:17 -07001331 [LOOKUP_IP_DST_MCAST_NEXT_DROP] = "ip4-drop",
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001332 [LOOKUP_IP_DST_MCAST_NEXT_RPF] = "ip4-mfib-forward-rpf",
1333 },
1334};
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001335
Filip Tehlareb9a27f2019-03-07 01:42:11 -08001336VLIB_NODE_FN (lookup_ip6_dst_mcast_node) (vlib_main_t * vm,
Neale Ranns31426c62017-05-24 10:32:58 -07001337 vlib_node_runtime_t * node,
1338 vlib_frame_t * from_frame)
1339{
1340 return (lookup_dpo_ip_dst_mcast_inline(vm, node, from_frame, 0));
1341}
1342
1343VLIB_REGISTER_NODE (lookup_ip6_dst_mcast_node) = {
Neale Ranns31426c62017-05-24 10:32:58 -07001344 .name = "lookup-ip6-dst-mcast",
1345 .vector_size = sizeof (u32),
1346
1347 .format_trace = format_lookup_trace,
1348 .n_next_nodes = LOOKUP_IP_DST_MCAST_N_NEXT,
1349 .next_nodes = {
Neale Rannsce9e0b42018-08-01 12:53:17 -07001350 [LOOKUP_IP_DST_MCAST_NEXT_DROP] = "ip6-drop",
Neale Ranns31426c62017-05-24 10:32:58 -07001351 [LOOKUP_IP_DST_MCAST_NEXT_RPF] = "ip6-mfib-forward-rpf",
1352 },
1353};
Neale Ranns31426c62017-05-24 10:32:58 -07001354
Neale Ranns6c3ebcc2016-10-02 21:20:15 +01001355static void
1356lookup_dpo_mem_show (void)
1357{
1358 fib_show_memory_usage("Lookup",
1359 pool_elts(lookup_dpo_pool),
1360 pool_len(lookup_dpo_pool),
1361 sizeof(lookup_dpo_t));
1362}
1363
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001364const static dpo_vft_t lkd_vft = {
1365 .dv_lock = lookup_dpo_lock,
1366 .dv_unlock = lookup_dpo_unlock,
1367 .dv_format = format_lookup_dpo,
1368};
Neale Ranns6c3ebcc2016-10-02 21:20:15 +01001369const static dpo_vft_t lkd_vft_w_mem_show = {
1370 .dv_lock = lookup_dpo_lock,
1371 .dv_unlock = lookup_dpo_unlock,
1372 .dv_format = format_lookup_dpo,
1373 .dv_mem_show = lookup_dpo_mem_show,
1374};
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001375
1376const static char* const lookup_src_ip4_nodes[] =
1377{
1378 "lookup-ip4-src",
1379 NULL,
1380};
1381const static char* const lookup_src_ip6_nodes[] =
1382{
1383 "lookup-ip6-src",
1384 NULL,
1385};
1386const static char* const * const lookup_src_nodes[DPO_PROTO_NUM] =
1387{
1388 [DPO_PROTO_IP4] = lookup_src_ip4_nodes,
1389 [DPO_PROTO_IP6] = lookup_src_ip6_nodes,
1390 [DPO_PROTO_MPLS] = NULL,
1391};
1392
1393const static char* const lookup_dst_ip4_nodes[] =
1394{
1395 "lookup-ip4-dst",
1396 NULL,
1397};
1398const static char* const lookup_dst_ip6_nodes[] =
1399{
1400 "lookup-ip6-dst",
1401 NULL,
1402};
1403const static char* const lookup_dst_mpls_nodes[] =
1404{
1405 "lookup-mpls-dst",
1406 NULL,
1407};
1408const static char* const * const lookup_dst_nodes[DPO_PROTO_NUM] =
1409{
1410 [DPO_PROTO_IP4] = lookup_dst_ip4_nodes,
1411 [DPO_PROTO_IP6] = lookup_dst_ip6_nodes,
1412 [DPO_PROTO_MPLS] = lookup_dst_mpls_nodes,
1413};
1414
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001415const static char* const lookup_dst_mcast_ip4_nodes[] =
1416{
1417 "lookup-ip4-dst-mcast",
1418 NULL,
1419};
1420const static char* const lookup_dst_mcast_ip6_nodes[] =
1421{
1422 "lookup-ip6-dst-mcast",
1423 NULL,
1424};
1425const static char* const * const lookup_dst_mcast_nodes[DPO_PROTO_NUM] =
1426{
1427 [DPO_PROTO_IP4] = lookup_dst_mcast_ip4_nodes,
1428 [DPO_PROTO_IP6] = lookup_dst_mcast_ip6_nodes,
1429};
1430
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001431const static char* const lookup_dst_from_interface_ip4_nodes[] =
1432{
1433 "lookup-ip4-dst-itf",
1434 NULL,
1435};
1436const static char* const lookup_dst_from_interface_ip6_nodes[] =
1437{
1438 "lookup-ip6-dst-itf",
1439 NULL,
1440};
1441const static char* const lookup_dst_from_interface_mpls_nodes[] =
1442{
1443 "lookup-mpls-dst-itf",
1444 NULL,
1445};
1446const static char* const * const lookup_dst_from_interface_nodes[DPO_PROTO_NUM] =
1447{
1448 [DPO_PROTO_IP4] = lookup_dst_from_interface_ip4_nodes,
1449 [DPO_PROTO_IP6] = lookup_dst_from_interface_ip6_nodes,
1450 [DPO_PROTO_MPLS] = lookup_dst_from_interface_mpls_nodes,
1451};
1452
Neale Ranns5779a442018-08-22 09:50:25 -07001453static clib_error_t *
1454lookup_dpo_show (vlib_main_t * vm,
1455 unformat_input_t * input,
1456 vlib_cli_command_t * cmd)
1457{
1458 index_t lkdi = INDEX_INVALID;
1459
1460 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1461 {
1462 if (unformat (input, "%d", &lkdi))
1463 ;
1464 else
1465 break;
1466 }
1467
1468 if (INDEX_INVALID != lkdi)
1469 {
1470 vlib_cli_output (vm, "%U", format_lookup_dpo, lkdi);
1471 }
1472 else
1473 {
1474 lookup_dpo_t *lkd;
1475
1476 pool_foreach(lkd, lookup_dpo_pool,
1477 ({
1478 vlib_cli_output (vm, "[@%d] %U",
1479 lookup_dpo_get_index(lkd),
1480 format_lookup_dpo,
1481 lookup_dpo_get_index(lkd));
1482 }));
1483 }
1484
1485 return 0;
1486}
1487
1488VLIB_CLI_COMMAND (replicate_show_command, static) = {
1489 .path = "show lookup-dpo",
1490 .short_help = "show lookup-dpo [<index>]",
1491 .function = lookup_dpo_show,
1492};
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001493
1494void
1495lookup_dpo_module_init (void)
1496{
Neale Ranns6c3ebcc2016-10-02 21:20:15 +01001497 dpo_register(DPO_LOOKUP, &lkd_vft_w_mem_show, NULL);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001498
1499 /*
1500 * There are various sorts of lookup; src or dst addr v4 /v6 etc.
1501 * there isn't an object type for each (there is only the lookup_dpo_t),
1502 * but, for performance reasons, there is a data plane function, and hence
1503 * VLIB node for each. VLIB graph node construction is based on DPO types
1504 * so we create sub-types.
1505 */
1506 lookup_dpo_sub_types[LOOKUP_SUB_TYPE_SRC] =
1507 dpo_register_new_type(&lkd_vft, lookup_src_nodes);
1508 lookup_dpo_sub_types[LOOKUP_SUB_TYPE_DST] =
1509 dpo_register_new_type(&lkd_vft, lookup_dst_nodes);
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001510 lookup_dpo_sub_types[LOOKUP_SUB_TYPE_DST_MCAST] =
1511 dpo_register_new_type(&lkd_vft, lookup_dst_mcast_nodes);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001512 lookup_dpo_sub_types[LOOKUP_SUB_TYPE_DST_TABLE_FROM_INTERFACE] =
Billy McFallcfcf1e22016-10-14 09:51:49 -04001513 dpo_register_new_type(&lkd_vft, lookup_dst_from_interface_nodes);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001514}