blob: e5b00a79e520e9f850d7fc7ec0b0a69644d6b104 [file] [log] [blame]
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001/*
2 * Copyright (c) 2016 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include <vnet/ip/ip.h>
17#include <vnet/dpo/lookup_dpo.h>
18#include <vnet/dpo/load_balance.h>
19#include <vnet/mpls/mpls.h>
20#include <vnet/fib/fib_table.h>
21#include <vnet/fib/ip4_fib.h>
22#include <vnet/fib/ip6_fib.h>
23#include <vnet/fib/mpls_fib.h>
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/**
32 * @brief Enumeration of the lookup subtypes
33 */
34typedef enum lookup_sub_type_t_
35{
36 LOOKUP_SUB_TYPE_SRC,
37 LOOKUP_SUB_TYPE_DST,
Neale Ranns0f26c5a2017-03-01 15:12:11 -080038 LOOKUP_SUB_TYPE_DST_MCAST,
Neale Ranns0bfe5d82016-08-25 15:29:12 +010039 LOOKUP_SUB_TYPE_DST_TABLE_FROM_INTERFACE,
40} lookup_sub_type_t;
41#define LOOKUP_SUB_TYPE_NUM (LOOKUP_SUB_TYPE_DST_TABLE_FROM_INTERFACE+1)
42
43#define FOR_EACH_LOOKUP_SUB_TYPE(_st) \
44 for (_st = LOOKUP_SUB_TYPE_IP4_SRC; _st < LOOKUP_SUB_TYPE_NUM; _st++)
45
46/**
47 * @brief pool of all MPLS Label DPOs
48 */
49lookup_dpo_t *lookup_dpo_pool;
50
51/**
52 * @brief An array of registered DPO type values for the sub-types
53 */
54static dpo_type_t lookup_dpo_sub_types[LOOKUP_SUB_TYPE_NUM];
55
56static lookup_dpo_t *
57lookup_dpo_alloc (void)
58{
59 lookup_dpo_t *lkd;
60
61 pool_get_aligned(lookup_dpo_pool, lkd, CLIB_CACHE_LINE_BYTES);
62
63 return (lkd);
64}
65
66static index_t
67lookup_dpo_get_index (lookup_dpo_t *lkd)
68{
69 return (lkd - lookup_dpo_pool);
70}
71
72static void
73lookup_dpo_add_or_lock_i (fib_node_index_t fib_index,
74 dpo_proto_t proto,
Neale Ranns0f26c5a2017-03-01 15:12:11 -080075 lookup_cast_t cast,
Neale Ranns0bfe5d82016-08-25 15:29:12 +010076 lookup_input_t input,
77 lookup_table_t table_config,
78 dpo_id_t *dpo)
79{
80 lookup_dpo_t *lkd;
81 dpo_type_t type;
82
83 lkd = lookup_dpo_alloc();
84 lkd->lkd_fib_index = fib_index;
85 lkd->lkd_proto = proto;
86 lkd->lkd_input = input;
87 lkd->lkd_table = table_config;
Neale Ranns0f26c5a2017-03-01 15:12:11 -080088 lkd->lkd_cast = cast;
Neale Ranns0bfe5d82016-08-25 15:29:12 +010089
90 /*
91 * use the input type to select the lookup sub-type
92 */
93 type = 0;
94
95 switch (input)
96 {
97 case LOOKUP_INPUT_SRC_ADDR:
98 type = lookup_dpo_sub_types[LOOKUP_SUB_TYPE_SRC];
99 break;
100 case LOOKUP_INPUT_DST_ADDR:
101 switch (table_config)
102 {
103 case LOOKUP_TABLE_FROM_INPUT_INTERFACE:
104 type = lookup_dpo_sub_types[LOOKUP_SUB_TYPE_DST_TABLE_FROM_INTERFACE];
105 break;
106 case LOOKUP_TABLE_FROM_CONFIG:
107 type = lookup_dpo_sub_types[LOOKUP_SUB_TYPE_DST];
108 break;
109 }
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800110 if (LOOKUP_MULTICAST == cast)
111 {
112 type = lookup_dpo_sub_types[LOOKUP_SUB_TYPE_DST_MCAST];
113 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100114 }
115
116 if (0 == type)
117 {
118 dpo_reset(dpo);
119 }
120 else
121 {
122 dpo_set(dpo, type, proto, lookup_dpo_get_index(lkd));
123 }
124}
125
126void
127lookup_dpo_add_or_lock_w_fib_index (fib_node_index_t fib_index,
128 dpo_proto_t proto,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800129 lookup_cast_t cast,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100130 lookup_input_t input,
131 lookup_table_t table_config,
132 dpo_id_t *dpo)
133{
134 if (LOOKUP_TABLE_FROM_CONFIG == table_config)
135 {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800136 if (LOOKUP_UNICAST == cast)
137 {
138 fib_table_lock(fib_index, dpo_proto_to_fib(proto));
139 }
140 else
141 {
142 mfib_table_lock(fib_index, dpo_proto_to_fib(proto));
143 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100144 }
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800145 lookup_dpo_add_or_lock_i(fib_index, proto, cast, input, table_config, dpo);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100146}
147
148void
149lookup_dpo_add_or_lock_w_table_id (u32 table_id,
150 dpo_proto_t proto,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800151 lookup_cast_t cast,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100152 lookup_input_t input,
153 lookup_table_t table_config,
154 dpo_id_t *dpo)
155{
156 fib_node_index_t fib_index = FIB_NODE_INDEX_INVALID;
157
158 if (LOOKUP_TABLE_FROM_CONFIG == table_config)
159 {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800160 if (LOOKUP_UNICAST == cast)
161 {
162 fib_index =
163 fib_table_find_or_create_and_lock(dpo_proto_to_fib(proto),
164 table_id);
165 }
166 else
167 {
168 fib_index =
169 mfib_table_find_or_create_and_lock(dpo_proto_to_fib(proto),
170 table_id);
171 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100172 }
173
174 ASSERT(FIB_NODE_INDEX_INVALID != fib_index);
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800175 lookup_dpo_add_or_lock_i(fib_index, proto, cast, input, table_config, dpo);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100176}
177
178u8*
179format_lookup_dpo (u8 *s, va_list *args)
180{
181 index_t index = va_arg (*args, index_t);
182 lookup_dpo_t *lkd;
183
184 lkd = lookup_dpo_get(index);
185
186 if (LOOKUP_TABLE_FROM_INPUT_INTERFACE == lkd->lkd_table)
187 {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800188 s = format(s, "%s,%s lookup in interface's %U table",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100189 lookup_input_names[lkd->lkd_input],
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800190 lookup_cast_names[lkd->lkd_cast],
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100191 format_dpo_proto, lkd->lkd_proto);
192 }
193 else
194 {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800195 if (LOOKUP_UNICAST == lkd->lkd_cast)
196 {
197 s = format(s, "%s,%s lookup in %U",
198 lookup_input_names[lkd->lkd_input],
199 lookup_cast_names[lkd->lkd_cast],
200 format_fib_table_name, lkd->lkd_fib_index,
201 dpo_proto_to_fib(lkd->lkd_proto));
202 }
203 else
204 {
205 s = format(s, "%s,%s lookup in %U",
206 lookup_input_names[lkd->lkd_input],
207 lookup_cast_names[lkd->lkd_cast],
208 format_mfib_table_name, lkd->lkd_fib_index,
209 dpo_proto_to_fib(lkd->lkd_proto));
210 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100211 }
212 return (s);
213}
214
215static void
216lookup_dpo_lock (dpo_id_t *dpo)
217{
218 lookup_dpo_t *lkd;
219
220 lkd = lookup_dpo_get(dpo->dpoi_index);
221
222 lkd->lkd_locks++;
223}
224
225static void
226lookup_dpo_unlock (dpo_id_t *dpo)
227{
228 lookup_dpo_t *lkd;
229
230 lkd = lookup_dpo_get(dpo->dpoi_index);
231
232 lkd->lkd_locks--;
233
234 if (0 == lkd->lkd_locks)
235 {
236 if (LOOKUP_TABLE_FROM_CONFIG == lkd->lkd_table)
237 {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800238 if (LOOKUP_UNICAST == lkd->lkd_cast)
239 {
240 fib_table_unlock(lkd->lkd_fib_index,
241 dpo_proto_to_fib(lkd->lkd_proto));
242 }
243 else
244 {
245 mfib_table_unlock(lkd->lkd_fib_index,
246 dpo_proto_to_fib(lkd->lkd_proto));
247 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100248 }
249 pool_put(lookup_dpo_pool, lkd);
250 }
251}
252
253always_inline void
254ip4_src_fib_lookup_one (u32 src_fib_index0,
255 const ip4_address_t * addr0,
256 u32 * src_adj_index0)
257{
Neale Ranns04a75e32017-03-23 06:46:01 -0700258 ip4_fib_mtrie_leaf_t leaf0;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100259 ip4_fib_mtrie_t * mtrie0;
260
261 mtrie0 = &ip4_fib_get (src_fib_index0)->mtrie;
262
Neale Ranns04a75e32017-03-23 06:46:01 -0700263 leaf0 = ip4_fib_mtrie_lookup_step_one (mtrie0, addr0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100264 leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 2);
265 leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 3);
266
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100267 src_adj_index0[0] = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
268}
269
270always_inline void
271ip4_src_fib_lookup_two (u32 src_fib_index0,
272 u32 src_fib_index1,
273 const ip4_address_t * addr0,
274 const ip4_address_t * addr1,
275 u32 * src_adj_index0,
276 u32 * src_adj_index1)
277{
278 ip4_fib_mtrie_leaf_t leaf0, leaf1;
279 ip4_fib_mtrie_t * mtrie0, * mtrie1;
280
281 mtrie0 = &ip4_fib_get (src_fib_index0)->mtrie;
282 mtrie1 = &ip4_fib_get (src_fib_index1)->mtrie;
283
Neale Ranns04a75e32017-03-23 06:46:01 -0700284 leaf0 = ip4_fib_mtrie_lookup_step_one (mtrie0, addr0);
285 leaf1 = ip4_fib_mtrie_lookup_step_one (mtrie1, addr1);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100286
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100287 leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 2);
288 leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 2);
289
290 leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, addr0, 3);
291 leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, addr1, 3);
292
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100293 src_adj_index0[0] = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
294 src_adj_index1[0] = ip4_fib_mtrie_leaf_get_adj_index (leaf1);
295}
296
297/**
298 * @brief Lookup trace data
299 */
300typedef struct lookup_trace_t_
301{
302 union {
303 ip46_address_t addr;
304 mpls_unicast_header_t hdr;
305 };
306 fib_node_index_t fib_index;
307 index_t lbi;
308} lookup_trace_t;
309
310
311always_inline uword
312lookup_dpo_ip4_inline (vlib_main_t * vm,
313 vlib_node_runtime_t * node,
314 vlib_frame_t * from_frame,
315 int input_src_addr,
316 int table_from_interface)
317{
318 u32 n_left_from, next_index, * from, * to_next;
Damjan Marion586afd72017-04-05 19:18:20 +0200319 u32 thread_index = vlib_get_thread_index();
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100320 vlib_combined_counter_main_t * cm = &load_balance_main.lbm_to_counters;
321
322 from = vlib_frame_vector_args (from_frame);
323 n_left_from = from_frame->n_vectors;
324
325 next_index = node->cached_next_index;
326
327 while (n_left_from > 0)
328 {
329 u32 n_left_to_next;
330
331 vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
332
Neale Rannsd3b85b02016-10-22 15:17:21 -0700333 while (n_left_from >= 4 && n_left_to_next > 2)
334 {
Neale Ranns5e575b12016-10-03 09:40:25 +0100335 u32 bi0, lkdi0, lbi0, fib_index0, next0, hash_c0;
336 flow_hash_config_t flow_hash_config0;
Neale Rannsd3b85b02016-10-22 15:17:21 -0700337 const ip4_address_t *input_addr0;
338 const load_balance_t *lb0;
339 const lookup_dpo_t * lkd0;
340 const ip4_header_t * ip0;
341 const dpo_id_t *dpo0;
342 vlib_buffer_t * b0;
343 u32 bi1, lkdi1, lbi1, fib_index1, next1, hash_c1;
344 flow_hash_config_t flow_hash_config1;
345 const ip4_address_t *input_addr1;
346 const load_balance_t *lb1;
347 const lookup_dpo_t * lkd1;
348 const ip4_header_t * ip1;
349 const dpo_id_t *dpo1;
350 vlib_buffer_t * b1;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100351
Neale Rannsd3b85b02016-10-22 15:17:21 -0700352 /* Prefetch next iteration. */
353 {
354 vlib_buffer_t * p2, * p3;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100355
Neale Rannsd3b85b02016-10-22 15:17:21 -0700356 p2 = vlib_get_buffer (vm, from[2]);
357 p3 = vlib_get_buffer (vm, from[3]);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100358
Neale Rannsd3b85b02016-10-22 15:17:21 -0700359 vlib_prefetch_buffer_header (p2, LOAD);
360 vlib_prefetch_buffer_header (p3, LOAD);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100361
Neale Rannsd3b85b02016-10-22 15:17:21 -0700362 CLIB_PREFETCH (p2->data, CLIB_CACHE_LINE_BYTES, STORE);
363 CLIB_PREFETCH (p3->data, CLIB_CACHE_LINE_BYTES, STORE);
364 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100365
Neale Rannsd3b85b02016-10-22 15:17:21 -0700366 bi0 = from[0];
367 to_next[0] = bi0;
368 bi1 = from[1];
369 to_next[1] = bi1;
370 from += 2;
371 to_next += 2;
372 n_left_from -= 2;
373 n_left_to_next -= 2;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100374
Neale Rannsd3b85b02016-10-22 15:17:21 -0700375 b0 = vlib_get_buffer (vm, bi0);
376 ip0 = vlib_buffer_get_current (b0);
377 b1 = vlib_get_buffer (vm, bi1);
378 ip1 = vlib_buffer_get_current (b1);
379
380 /* dst lookup was done by ip4 lookup */
381 lkdi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
382 lkdi1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
383 lkd0 = lookup_dpo_get(lkdi0);
384 lkd1 = lookup_dpo_get(lkdi1);
385
386 /*
387 * choose between a lookup using the fib index in the DPO
388 * or getting the FIB index from the interface.
389 */
390 if (table_from_interface)
391 {
392 fib_index0 =
393 ip4_fib_table_get_index_for_sw_if_index(
394 vnet_buffer(b0)->sw_if_index[VLIB_RX]);
395 fib_index1 =
396 ip4_fib_table_get_index_for_sw_if_index(
397 vnet_buffer(b1)->sw_if_index[VLIB_RX]);
398 }
399 else
400 {
401 fib_index0 = lkd0->lkd_fib_index;
402 fib_index1 = lkd1->lkd_fib_index;
403 }
404
405 /*
406 * choose between a source or destination address lookup in the table
407 */
408 if (input_src_addr)
409 {
410 input_addr0 = &ip0->src_address;
411 input_addr1 = &ip1->src_address;
412 }
413 else
414 {
415 input_addr0 = &ip0->dst_address;
416 input_addr1 = &ip1->dst_address;
417 }
418
419 /* do lookup */
Neale Ranns450cd302016-11-09 17:49:42 +0000420 ip4_src_fib_lookup_two (fib_index0, fib_index1,
421 input_addr0, input_addr1,
422 &lbi0, &lbi1);
Neale Rannsd3b85b02016-10-22 15:17:21 -0700423 lb0 = load_balance_get(lbi0);
424 lb1 = load_balance_get(lbi1);
425
Neale Rannscb630ff2016-12-14 13:31:29 +0100426 vnet_buffer(b0)->sw_if_index[VLIB_TX] = fib_index0;
427 vnet_buffer(b1)->sw_if_index[VLIB_TX] = fib_index1;
428
Neale Rannsd3b85b02016-10-22 15:17:21 -0700429 /* Use flow hash to compute multipath adjacency. */
430 hash_c0 = vnet_buffer (b0)->ip.flow_hash = 0;
431 hash_c1 = vnet_buffer (b1)->ip.flow_hash = 0;
432
433 if (PREDICT_FALSE (lb0->lb_n_buckets > 1))
434 {
435 flow_hash_config0 = lb0->lb_hash_config;
436 hash_c0 = vnet_buffer (b0)->ip.flow_hash =
437 ip4_compute_flow_hash (ip0, flow_hash_config0);
438 }
439
440 if (PREDICT_FALSE (lb1->lb_n_buckets > 1))
441 {
442 flow_hash_config1 = lb1->lb_hash_config;
443 hash_c1 = vnet_buffer (b1)->ip.flow_hash =
444 ip4_compute_flow_hash (ip1, flow_hash_config1);
445 }
446
447 dpo0 = load_balance_get_bucket_i(lb0,
448 (hash_c0 &
449 (lb0->lb_n_buckets_minus_1)));
450 dpo1 = load_balance_get_bucket_i(lb1,
451 (hash_c1 &
452 (lb1->lb_n_buckets_minus_1)));
453
454 next0 = dpo0->dpoi_next_node;
455 next1 = dpo1->dpoi_next_node;
456 vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
457 vnet_buffer(b1)->ip.adj_index[VLIB_TX] = dpo1->dpoi_index;
458
459 vlib_increment_combined_counter
Damjan Marion586afd72017-04-05 19:18:20 +0200460 (cm, thread_index, lbi0, 1,
Neale Rannsd3b85b02016-10-22 15:17:21 -0700461 vlib_buffer_length_in_chain (vm, b0));
462 vlib_increment_combined_counter
Damjan Marion586afd72017-04-05 19:18:20 +0200463 (cm, thread_index, lbi1, 1,
Neale Rannsd3b85b02016-10-22 15:17:21 -0700464 vlib_buffer_length_in_chain (vm, b1));
465
466 if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
467 {
468 lookup_trace_t *tr = vlib_add_trace (vm, node,
469 b0, sizeof (*tr));
470 tr->fib_index = fib_index0;
471 tr->lbi = lbi0;
472 tr->addr.ip4 = *input_addr0;
473 }
474 if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
475 {
476 lookup_trace_t *tr = vlib_add_trace (vm, node,
477 b1, sizeof (*tr));
478 tr->fib_index = fib_index1;
479 tr->lbi = lbi1;
480 tr->addr.ip4 = *input_addr1;
481 }
482
483 vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
484 to_next, n_left_to_next,
485 bi0, bi1, next0, next1);
486 }
487
488 while (n_left_from > 0 && n_left_to_next > 0)
489 {
490 u32 bi0, lkdi0, lbi0, fib_index0, next0, hash_c0;
491 flow_hash_config_t flow_hash_config0;
492 const ip4_address_t *input_addr;
493 const load_balance_t *lb0;
494 const lookup_dpo_t * lkd0;
495 const ip4_header_t * ip0;
496 const dpo_id_t *dpo0;
497 vlib_buffer_t * b0;
498
499 bi0 = from[0];
500 to_next[0] = bi0;
501 from += 1;
502 to_next += 1;
503 n_left_from -= 1;
504 n_left_to_next -= 1;
505
506 b0 = vlib_get_buffer (vm, bi0);
507 ip0 = vlib_buffer_get_current (b0);
508
509 /* dst lookup was done by ip4 lookup */
510 lkdi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
511 lkd0 = lookup_dpo_get(lkdi0);
512
513 /*
514 * choose between a lookup using the fib index in the DPO
515 * or getting the FIB index from the interface.
516 */
517 if (table_from_interface)
518 {
519 fib_index0 =
520 ip4_fib_table_get_index_for_sw_if_index(
521 vnet_buffer(b0)->sw_if_index[VLIB_RX]);
522 }
523 else
524 {
525 fib_index0 = lkd0->lkd_fib_index;
526 }
527
528 /*
529 * choose between a source or destination address lookup in the table
530 */
531 if (input_src_addr)
532 {
533 input_addr = &ip0->src_address;
534 }
535 else
536 {
537 input_addr = &ip0->dst_address;
538 }
539
540 /* do lookup */
541 ip4_src_fib_lookup_one (fib_index0, input_addr, &lbi0);
542 lb0 = load_balance_get(lbi0);
Neale Ranns5e575b12016-10-03 09:40:25 +0100543
Neale Rannscb630ff2016-12-14 13:31:29 +0100544 vnet_buffer(b0)->sw_if_index[VLIB_TX] = fib_index0;
545
Neale Ranns5e575b12016-10-03 09:40:25 +0100546 /* Use flow hash to compute multipath adjacency. */
547 hash_c0 = vnet_buffer (b0)->ip.flow_hash = 0;
548
549 if (PREDICT_FALSE (lb0->lb_n_buckets > 1))
Neale Rannsd3b85b02016-10-22 15:17:21 -0700550 {
Neale Ranns5e575b12016-10-03 09:40:25 +0100551 flow_hash_config0 = lb0->lb_hash_config;
552 hash_c0 = vnet_buffer (b0)->ip.flow_hash =
553 ip4_compute_flow_hash (ip0, flow_hash_config0);
Neale Rannsd3b85b02016-10-22 15:17:21 -0700554 }
Neale Ranns5e575b12016-10-03 09:40:25 +0100555
556 dpo0 = load_balance_get_bucket_i(lb0,
557 (hash_c0 &
558 (lb0->lb_n_buckets_minus_1)));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100559
Neale Rannsd3b85b02016-10-22 15:17:21 -0700560 next0 = dpo0->dpoi_next_node;
561 vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100562
Neale Rannsd3b85b02016-10-22 15:17:21 -0700563 vlib_increment_combined_counter
Damjan Marion586afd72017-04-05 19:18:20 +0200564 (cm, thread_index, lbi0, 1,
Neale Rannsd3b85b02016-10-22 15:17:21 -0700565 vlib_buffer_length_in_chain (vm, b0));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100566
Neale Rannsd3b85b02016-10-22 15:17:21 -0700567 if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
568 {
569 lookup_trace_t *tr = vlib_add_trace (vm, node,
570 b0, sizeof (*tr));
571 tr->fib_index = fib_index0;
572 tr->lbi = lbi0;
573 tr->addr.ip4 = *input_addr;
574 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100575
Neale Rannsd3b85b02016-10-22 15:17:21 -0700576 vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
577 n_left_to_next, bi0, next0);
578 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100579 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
580 }
581 return from_frame->n_vectors;
582}
583
584static u8 *
585format_lookup_trace (u8 * s, va_list * args)
586{
587 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
588 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
589 lookup_trace_t * t = va_arg (*args, lookup_trace_t *);
590 uword indent = format_get_indent (s);
591 s = format (s, "%U fib-index:%d addr:%U load-balance:%d",
592 format_white_space, indent,
593 t->fib_index,
594 format_ip46_address, &t->addr, IP46_TYPE_ANY,
595 t->lbi);
596 return s;
597}
598
599always_inline uword
600lookup_ip4_dst (vlib_main_t * vm,
601 vlib_node_runtime_t * node,
602 vlib_frame_t * from_frame)
603{
604 return (lookup_dpo_ip4_inline(vm, node, from_frame, 0, 0));
605}
606
607VLIB_REGISTER_NODE (lookup_ip4_dst_node) = {
608 .function = lookup_ip4_dst,
609 .name = "lookup-ip4-dst",
610 .vector_size = sizeof (u32),
611 .sibling_of = "ip4-lookup",
612 .format_trace = format_lookup_trace,
613};
614VLIB_NODE_FUNCTION_MULTIARCH (lookup_ip4_dst_node, lookup_ip4_dst)
615
616always_inline uword
617lookup_ip4_dst_itf (vlib_main_t * vm,
618 vlib_node_runtime_t * node,
619 vlib_frame_t * from_frame)
620{
621 return (lookup_dpo_ip4_inline(vm, node, from_frame, 0, 1));
622}
623
624VLIB_REGISTER_NODE (lookup_ip4_dst_itf_node) = {
625 .function = lookup_ip4_dst_itf,
626 .name = "lookup-ip4-dst-itf",
627 .vector_size = sizeof (u32),
628 .sibling_of = "ip4-lookup",
629 .format_trace = format_lookup_trace,
630};
631VLIB_NODE_FUNCTION_MULTIARCH (lookup_ip4_dst_itf_node, lookup_ip4_dst_itf)
632
633always_inline uword
634lookup_ip4_src (vlib_main_t * vm,
635 vlib_node_runtime_t * node,
636 vlib_frame_t * from_frame)
637{
638 return (lookup_dpo_ip4_inline(vm, node, from_frame, 1, 0));
639}
640
641VLIB_REGISTER_NODE (lookup_ip4_src_node) = {
642 .function = lookup_ip4_src,
643 .name = "lookup-ip4-src",
644 .vector_size = sizeof (u32),
645 .format_trace = format_lookup_trace,
646 .sibling_of = "ip4-lookup",
647};
648VLIB_NODE_FUNCTION_MULTIARCH (lookup_ip4_src_node, lookup_ip4_src)
649
650always_inline uword
651lookup_dpo_ip6_inline (vlib_main_t * vm,
652 vlib_node_runtime_t * node,
653 vlib_frame_t * from_frame,
Billy McFallcfcf1e22016-10-14 09:51:49 -0400654 int input_src_addr,
655 int table_from_interface)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100656{
657 vlib_combined_counter_main_t * cm = &load_balance_main.lbm_to_counters;
658 u32 n_left_from, next_index, * from, * to_next;
Damjan Marion586afd72017-04-05 19:18:20 +0200659 u32 thread_index = vlib_get_thread_index();
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100660
661 from = vlib_frame_vector_args (from_frame);
662 n_left_from = from_frame->n_vectors;
663
664 next_index = node->cached_next_index;
665
666 while (n_left_from > 0)
667 {
668 u32 n_left_to_next;
669
670 vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
671
Neale Rannsd3b85b02016-10-22 15:17:21 -0700672 while (n_left_from >= 4 && n_left_to_next > 2)
673 {
674 u32 bi0, lkdi0, lbi0, fib_index0, next0, hash_c0;
Neale Ranns5e575b12016-10-03 09:40:25 +0100675 flow_hash_config_t flow_hash_config0;
Neale Rannsd3b85b02016-10-22 15:17:21 -0700676 const ip6_address_t *input_addr0;
677 const load_balance_t *lb0;
678 const lookup_dpo_t * lkd0;
679 const ip6_header_t * ip0;
680 const dpo_id_t *dpo0;
681 vlib_buffer_t * b0;
682 u32 bi1, lkdi1, lbi1, fib_index1, next1, hash_c1;
683 flow_hash_config_t flow_hash_config1;
684 const ip6_address_t *input_addr1;
685 const load_balance_t *lb1;
686 const lookup_dpo_t * lkd1;
687 const ip6_header_t * ip1;
688 const dpo_id_t *dpo1;
689 vlib_buffer_t * b1;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100690
Neale Rannsd3b85b02016-10-22 15:17:21 -0700691 /* Prefetch next iteration. */
692 {
693 vlib_buffer_t * p2, * p3;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100694
Neale Rannsd3b85b02016-10-22 15:17:21 -0700695 p2 = vlib_get_buffer (vm, from[2]);
696 p3 = vlib_get_buffer (vm, from[3]);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100697
Neale Rannsd3b85b02016-10-22 15:17:21 -0700698 vlib_prefetch_buffer_header (p2, LOAD);
699 vlib_prefetch_buffer_header (p3, LOAD);
Billy McFallcfcf1e22016-10-14 09:51:49 -0400700
Neale Rannsd3b85b02016-10-22 15:17:21 -0700701 CLIB_PREFETCH (p2->data, CLIB_CACHE_LINE_BYTES, STORE);
702 CLIB_PREFETCH (p3->data, CLIB_CACHE_LINE_BYTES, STORE);
703 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100704
Neale Rannsd3b85b02016-10-22 15:17:21 -0700705 bi0 = from[0];
706 to_next[0] = bi0;
707 bi1 = from[1];
708 to_next[1] = bi1;
709 from += 2;
710 to_next += 2;
711 n_left_from -= 2;
712 n_left_to_next -= 2;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100713
Neale Rannsd3b85b02016-10-22 15:17:21 -0700714 b0 = vlib_get_buffer (vm, bi0);
715 ip0 = vlib_buffer_get_current (b0);
716 b1 = vlib_get_buffer (vm, bi1);
717 ip1 = vlib_buffer_get_current (b1);
718
719 /* dst lookup was done by ip6 lookup */
720 lkdi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
721 lkdi1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
722 lkd0 = lookup_dpo_get(lkdi0);
723 lkd1 = lookup_dpo_get(lkdi1);
724
725 /*
726 * choose between a lookup using the fib index in the DPO
727 * or getting the FIB index from the interface.
728 */
729 if (table_from_interface)
730 {
731 fib_index0 =
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000732 ip6_fib_table_get_index_for_sw_if_index(
Neale Rannsd3b85b02016-10-22 15:17:21 -0700733 vnet_buffer(b0)->sw_if_index[VLIB_RX]);
734 fib_index1 =
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000735 ip6_fib_table_get_index_for_sw_if_index(
Neale Rannsd3b85b02016-10-22 15:17:21 -0700736 vnet_buffer(b1)->sw_if_index[VLIB_RX]);
737 }
738 else
739 {
740 fib_index0 = lkd0->lkd_fib_index;
741 fib_index1 = lkd1->lkd_fib_index;
742 }
743
744 /*
745 * choose between a source or destination address lookup in the table
746 */
747 if (input_src_addr)
748 {
749 input_addr0 = &ip0->src_address;
750 input_addr1 = &ip1->src_address;
751 }
752 else
753 {
754 input_addr0 = &ip0->dst_address;
755 input_addr1 = &ip1->dst_address;
756 }
757
758 /* do src lookup */
759 lbi0 = ip6_fib_table_fwding_lookup(&ip6_main,
760 fib_index0,
761 input_addr0);
762 lbi1 = ip6_fib_table_fwding_lookup(&ip6_main,
763 fib_index1,
764 input_addr1);
765 lb0 = load_balance_get(lbi0);
766 lb1 = load_balance_get(lbi1);
767
Neale Rannscb630ff2016-12-14 13:31:29 +0100768 vnet_buffer(b0)->sw_if_index[VLIB_TX] = fib_index0;
769 vnet_buffer(b1)->sw_if_index[VLIB_TX] = fib_index1;
770
Neale Rannsd3b85b02016-10-22 15:17:21 -0700771 /* Use flow hash to compute multipath adjacency. */
772 hash_c0 = vnet_buffer (b0)->ip.flow_hash = 0;
773 hash_c1 = vnet_buffer (b1)->ip.flow_hash = 0;
774
775 if (PREDICT_FALSE (lb0->lb_n_buckets > 1))
776 {
777 flow_hash_config0 = lb0->lb_hash_config;
778 hash_c0 = vnet_buffer (b0)->ip.flow_hash =
779 ip6_compute_flow_hash (ip0, flow_hash_config0);
780 }
781
782 if (PREDICT_FALSE (lb1->lb_n_buckets > 1))
783 {
784 flow_hash_config1 = lb1->lb_hash_config;
785 hash_c1 = vnet_buffer (b1)->ip.flow_hash =
786 ip6_compute_flow_hash (ip1, flow_hash_config1);
787 }
788
789 dpo0 = load_balance_get_bucket_i(lb0,
790 (hash_c0 &
791 (lb0->lb_n_buckets_minus_1)));
792 dpo1 = load_balance_get_bucket_i(lb1,
793 (hash_c1 &
794 (lb1->lb_n_buckets_minus_1)));
795
796 next0 = dpo0->dpoi_next_node;
797 next1 = dpo1->dpoi_next_node;
798 vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
799 vnet_buffer(b1)->ip.adj_index[VLIB_TX] = dpo1->dpoi_index;
800
801 vlib_increment_combined_counter
Damjan Marion586afd72017-04-05 19:18:20 +0200802 (cm, thread_index, lbi0, 1,
Neale Rannsd3b85b02016-10-22 15:17:21 -0700803 vlib_buffer_length_in_chain (vm, b0));
804 vlib_increment_combined_counter
Damjan Marion586afd72017-04-05 19:18:20 +0200805 (cm, thread_index, lbi1, 1,
Neale Rannsd3b85b02016-10-22 15:17:21 -0700806 vlib_buffer_length_in_chain (vm, b1));
807
808 if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
809 {
810 lookup_trace_t *tr = vlib_add_trace (vm, node,
811 b0, sizeof (*tr));
812 tr->fib_index = fib_index0;
813 tr->lbi = lbi0;
814 tr->addr.ip6 = *input_addr0;
815 }
816 if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
817 {
818 lookup_trace_t *tr = vlib_add_trace (vm, node,
819 b1, sizeof (*tr));
820 tr->fib_index = fib_index1;
821 tr->lbi = lbi1;
822 tr->addr.ip6 = *input_addr1;
823 }
824 vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next,
825 n_left_to_next, bi0, bi1,
826 next0, next1);
827 }
828 while (n_left_from > 0 && n_left_to_next > 0)
829 {
830 u32 bi0, lkdi0, lbi0, fib_index0, next0, hash_c0;
831 flow_hash_config_t flow_hash_config0;
832 const ip6_address_t *input_addr0;
833 const load_balance_t *lb0;
834 const lookup_dpo_t * lkd0;
835 const ip6_header_t * ip0;
836 const dpo_id_t *dpo0;
837 vlib_buffer_t * b0;
838
839 bi0 = from[0];
840 to_next[0] = bi0;
841 from += 1;
842 to_next += 1;
843 n_left_from -= 1;
844 n_left_to_next -= 1;
845
846 b0 = vlib_get_buffer (vm, bi0);
847 ip0 = vlib_buffer_get_current (b0);
848
849 /* dst lookup was done by ip6 lookup */
850 lkdi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
851 lkd0 = lookup_dpo_get(lkdi0);
852
853 /*
854 * choose between a lookup using the fib index in the DPO
855 * or getting the FIB index from the interface.
856 */
857 if (table_from_interface)
858 {
859 fib_index0 =
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000860 ip6_fib_table_get_index_for_sw_if_index(
Neale Rannsd3b85b02016-10-22 15:17:21 -0700861 vnet_buffer(b0)->sw_if_index[VLIB_RX]);
862 }
863 else
864 {
865 fib_index0 = lkd0->lkd_fib_index;
866 }
867
868 /*
869 * choose between a source or destination address lookup in the table
870 */
871 if (input_src_addr)
872 {
873 input_addr0 = &ip0->src_address;
874 }
875 else
876 {
877 input_addr0 = &ip0->dst_address;
878 }
879
880 /* do src lookup */
881 lbi0 = ip6_fib_table_fwding_lookup(&ip6_main,
882 fib_index0,
883 input_addr0);
884 lb0 = load_balance_get(lbi0);
Neale Ranns5e575b12016-10-03 09:40:25 +0100885
Neale Rannscb630ff2016-12-14 13:31:29 +0100886 vnet_buffer(b0)->sw_if_index[VLIB_TX] = fib_index0;
887
Neale Ranns5e575b12016-10-03 09:40:25 +0100888 /* Use flow hash to compute multipath adjacency. */
889 hash_c0 = vnet_buffer (b0)->ip.flow_hash = 0;
890
891 if (PREDICT_FALSE (lb0->lb_n_buckets > 1))
Neale Rannsd3b85b02016-10-22 15:17:21 -0700892 {
Neale Ranns5e575b12016-10-03 09:40:25 +0100893 flow_hash_config0 = lb0->lb_hash_config;
894 hash_c0 = vnet_buffer (b0)->ip.flow_hash =
895 ip6_compute_flow_hash (ip0, flow_hash_config0);
Neale Rannsd3b85b02016-10-22 15:17:21 -0700896 }
Neale Ranns5e575b12016-10-03 09:40:25 +0100897
898 dpo0 = load_balance_get_bucket_i(lb0,
899 (hash_c0 &
900 (lb0->lb_n_buckets_minus_1)));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100901
Neale Rannsd3b85b02016-10-22 15:17:21 -0700902 next0 = dpo0->dpoi_next_node;
903 vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100904
Neale Rannsd3b85b02016-10-22 15:17:21 -0700905 vlib_increment_combined_counter
Damjan Marion586afd72017-04-05 19:18:20 +0200906 (cm, thread_index, lbi0, 1,
Neale Rannsd3b85b02016-10-22 15:17:21 -0700907 vlib_buffer_length_in_chain (vm, b0));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100908
Neale Rannsd3b85b02016-10-22 15:17:21 -0700909 if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
910 {
911 lookup_trace_t *tr = vlib_add_trace (vm, node,
912 b0, sizeof (*tr));
913 tr->fib_index = fib_index0;
914 tr->lbi = lbi0;
915 tr->addr.ip6 = *input_addr0;
916 }
917 vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
918 n_left_to_next, bi0, next0);
919 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100920 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
921 }
922 return from_frame->n_vectors;
923}
924
925always_inline uword
926lookup_ip6_dst (vlib_main_t * vm,
927 vlib_node_runtime_t * node,
928 vlib_frame_t * from_frame)
929{
Billy McFallcfcf1e22016-10-14 09:51:49 -0400930 return (lookup_dpo_ip6_inline(vm, node, from_frame, 0 /*use src*/, 0));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100931}
932
933VLIB_REGISTER_NODE (lookup_ip6_dst_node) = {
934 .function = lookup_ip6_dst,
935 .name = "lookup-ip6-dst",
936 .vector_size = sizeof (u32),
937 .format_trace = format_lookup_trace,
938 .sibling_of = "ip6-lookup",
939};
940VLIB_NODE_FUNCTION_MULTIARCH (lookup_ip6_dst_node, lookup_ip6_dst)
941
942always_inline uword
Billy McFallcfcf1e22016-10-14 09:51:49 -0400943lookup_ip6_dst_itf (vlib_main_t * vm,
944 vlib_node_runtime_t * node,
945 vlib_frame_t * from_frame)
946{
947 return (lookup_dpo_ip6_inline(vm, node, from_frame, 0 /*use src*/, 1));
948}
949
950VLIB_REGISTER_NODE (lookup_ip6_dst_itf_node) = {
951 .function = lookup_ip6_dst_itf,
952 .name = "lookup-ip6-dst-itf",
953 .vector_size = sizeof (u32),
954 .format_trace = format_lookup_trace,
955 .sibling_of = "ip6-lookup",
956};
957VLIB_NODE_FUNCTION_MULTIARCH (lookup_ip6_dst_itf_node, lookup_ip6_dst_itf)
958
959always_inline uword
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100960lookup_ip6_src (vlib_main_t * vm,
961 vlib_node_runtime_t * node,
962 vlib_frame_t * from_frame)
963{
Billy McFallcfcf1e22016-10-14 09:51:49 -0400964 return (lookup_dpo_ip6_inline(vm, node, from_frame, 1, 0));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100965}
966
967VLIB_REGISTER_NODE (lookup_ip6_src_node) = {
968 .function = lookup_ip6_src,
969 .name = "lookup-ip6-src",
970 .vector_size = sizeof (u32),
971 .format_trace = format_lookup_trace,
972 .sibling_of = "ip6-lookup",
973};
974VLIB_NODE_FUNCTION_MULTIARCH (lookup_ip6_src_node, lookup_ip6_src)
975
976always_inline uword
977lookup_dpo_mpls_inline (vlib_main_t * vm,
978 vlib_node_runtime_t * node,
979 vlib_frame_t * from_frame,
980 int table_from_interface)
981{
982 u32 n_left_from, next_index, * from, * to_next;
Damjan Marion586afd72017-04-05 19:18:20 +0200983 u32 thread_index = vlib_get_thread_index();
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100984 vlib_combined_counter_main_t * cm = &load_balance_main.lbm_to_counters;
985
986 from = vlib_frame_vector_args (from_frame);
987 n_left_from = from_frame->n_vectors;
988
989 next_index = node->cached_next_index;
990
991 while (n_left_from > 0)
992 {
993 u32 n_left_to_next;
994
995 vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
996
997 /* while (n_left_from >= 4 && n_left_to_next >= 2) */
998 /* } */
999
1000 while (n_left_from > 0 && n_left_to_next > 0)
1001 {
1002 u32 bi0, lkdi0, lbi0, fib_index0, next0;
1003 const mpls_unicast_header_t * hdr0;
1004 const load_balance_t *lb0;
1005 const lookup_dpo_t * lkd0;
1006 const dpo_id_t *dpo0;
1007 vlib_buffer_t * b0;
1008
1009 bi0 = from[0];
1010 to_next[0] = bi0;
1011 from += 1;
1012 to_next += 1;
1013 n_left_from -= 1;
1014 n_left_to_next -= 1;
1015
1016 b0 = vlib_get_buffer (vm, bi0);
1017 hdr0 = vlib_buffer_get_current (b0);
1018
1019 /* dst lookup was done by mpls lookup */
1020 lkdi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
1021 lkd0 = lookup_dpo_get(lkdi0);
1022
1023 /*
1024 * choose between a lookup using the fib index in the DPO
1025 * or getting the FIB index from the interface.
1026 */
1027 if (table_from_interface)
1028 {
1029 fib_index0 =
1030 mpls_fib_table_get_index_for_sw_if_index(
1031 vnet_buffer(b0)->sw_if_index[VLIB_RX]);
1032 }
1033 else
1034 {
1035 fib_index0 = lkd0->lkd_fib_index;
1036 }
1037
1038 /* do lookup */
1039 lbi0 = mpls_fib_table_forwarding_lookup (fib_index0, hdr0);
1040 lb0 = load_balance_get(lbi0);
1041 dpo0 = load_balance_get_bucket_i(lb0, 0);
1042
1043 next0 = dpo0->dpoi_next_node;
1044 vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
1045
1046 vlib_increment_combined_counter
Damjan Marion586afd72017-04-05 19:18:20 +02001047 (cm, thread_index, lbi0, 1,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001048 vlib_buffer_length_in_chain (vm, b0));
1049
1050 if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
1051 {
1052 lookup_trace_t *tr = vlib_add_trace (vm, node,
1053 b0, sizeof (*tr));
1054 tr->fib_index = fib_index0;
1055 tr->lbi = lbi0;
1056 tr->hdr = *hdr0;
1057 }
1058
1059 vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
1060 n_left_to_next, bi0, next0);
1061 }
1062 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1063 }
1064 return from_frame->n_vectors;
1065}
1066
1067static u8 *
1068format_lookup_mpls_trace (u8 * s, va_list * args)
1069{
1070 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
1071 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
1072 lookup_trace_t * t = va_arg (*args, lookup_trace_t *);
1073 uword indent = format_get_indent (s);
1074 mpls_unicast_header_t hdr;
1075
1076 hdr.label_exp_s_ttl = clib_net_to_host_u32(t->hdr.label_exp_s_ttl);
1077
1078 s = format (s, "%U fib-index:%d hdr:%U load-balance:%d",
1079 format_white_space, indent,
1080 t->fib_index,
1081 format_mpls_header, hdr,
1082 t->lbi);
1083 return s;
1084}
1085
1086always_inline uword
1087lookup_mpls_dst (vlib_main_t * vm,
1088 vlib_node_runtime_t * node,
1089 vlib_frame_t * from_frame)
1090{
1091 return (lookup_dpo_mpls_inline(vm, node, from_frame, 0));
1092}
1093
1094VLIB_REGISTER_NODE (lookup_mpls_dst_node) = {
1095 .function = lookup_mpls_dst,
1096 .name = "lookup-mpls-dst",
1097 .vector_size = sizeof (u32),
1098 .sibling_of = "mpls-lookup",
1099 .format_trace = format_lookup_mpls_trace,
1100 .n_next_nodes = 0,
1101};
1102VLIB_NODE_FUNCTION_MULTIARCH (lookup_mpls_dst_node, lookup_mpls_dst)
1103
1104always_inline uword
1105lookup_mpls_dst_itf (vlib_main_t * vm,
1106 vlib_node_runtime_t * node,
1107 vlib_frame_t * from_frame)
1108{
1109 return (lookup_dpo_mpls_inline(vm, node, from_frame, 1));
1110}
1111
1112VLIB_REGISTER_NODE (lookup_mpls_dst_itf_node) = {
1113 .function = lookup_mpls_dst_itf,
1114 .name = "lookup-mpls-dst-itf",
1115 .vector_size = sizeof (u32),
1116 .sibling_of = "mpls-lookup",
1117 .format_trace = format_lookup_mpls_trace,
1118 .n_next_nodes = 0,
1119};
1120VLIB_NODE_FUNCTION_MULTIARCH (lookup_mpls_dst_itf_node, lookup_mpls_dst_itf)
1121
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001122typedef enum lookup_ip_dst_mcast_next_t_ {
1123 LOOKUP_IP_DST_MCAST_NEXT_RPF,
1124 LOOKUP_IP_DST_MCAST_N_NEXT,
1125} mfib_forward_lookup_next_t;
1126
1127always_inline uword
1128lookup_dpo_ip_dst_mcast_inline (vlib_main_t * vm,
1129 vlib_node_runtime_t * node,
1130 vlib_frame_t * from_frame,
1131 int is_v4)
1132{
1133 u32 n_left_from, next_index, * from, * to_next;
1134
1135 from = vlib_frame_vector_args (from_frame);
1136 n_left_from = from_frame->n_vectors;
1137
1138 next_index = LOOKUP_IP_DST_MCAST_NEXT_RPF;
1139
1140 while (n_left_from > 0)
1141 {
1142 u32 n_left_to_next;
1143
1144 vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
1145
1146 /* while (n_left_from >= 4 && n_left_to_next >= 2) */
1147 /* } */
1148
1149 while (n_left_from > 0 && n_left_to_next > 0)
1150 {
1151 u32 bi0, lkdi0, fib_index0, next0;
1152 const lookup_dpo_t * lkd0;
1153 fib_node_index_t mfei0;
1154 vlib_buffer_t * b0;
1155
1156 bi0 = from[0];
1157 to_next[0] = bi0;
1158 from += 1;
1159 to_next += 1;
1160 n_left_from -= 1;
1161 n_left_to_next -= 1;
1162
1163 b0 = vlib_get_buffer (vm, bi0);
1164
1165 /* dst lookup was done by mpls lookup */
1166 lkdi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
1167 lkd0 = lookup_dpo_get(lkdi0);
1168 fib_index0 = lkd0->lkd_fib_index;
1169 next0 = LOOKUP_IP_DST_MCAST_NEXT_RPF;
1170
1171 if (is_v4)
1172 {
1173 ip4_header_t * ip0;
1174
1175 ip0 = vlib_buffer_get_current (b0);
1176 mfei0 = ip4_mfib_table_lookup(ip4_mfib_get(fib_index0),
1177 &ip0->src_address,
1178 &ip0->dst_address,
1179 64);
1180 if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
1181 {
1182 lookup_trace_t *tr = vlib_add_trace (vm, node,
1183 b0, sizeof (*tr));
1184 tr->fib_index = fib_index0;
1185 tr->lbi = mfei0;
1186 tr->addr.ip4 = ip0->dst_address;
1187 }
1188 }
1189 else
1190 {
1191 ip6_header_t * ip0;
1192
1193 ip0 = vlib_buffer_get_current (b0);
1194 mfei0 = ip6_mfib_table_lookup2(ip6_mfib_get(fib_index0),
1195 &ip0->src_address,
1196 &ip0->dst_address);
1197 if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
1198 {
1199 lookup_trace_t *tr = vlib_add_trace (vm, node,
1200 b0, sizeof (*tr));
1201 tr->fib_index = fib_index0;
1202 tr->lbi = mfei0;
1203 tr->addr.ip6 = ip0->dst_address;
1204 }
1205 }
1206
1207 vnet_buffer (b0)->ip.adj_index[VLIB_TX] = mfei0;
1208
1209 vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
1210 n_left_to_next, bi0, next0);
1211 }
1212 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1213 }
1214 return from_frame->n_vectors;
1215}
1216
1217always_inline uword
1218lookup_ip4_dst_mcast (vlib_main_t * vm,
1219 vlib_node_runtime_t * node,
1220 vlib_frame_t * from_frame)
1221{
1222 return (lookup_dpo_ip_dst_mcast_inline(vm, node, from_frame, 1));
1223}
1224
1225VLIB_REGISTER_NODE (lookup_ip4_dst_mcast_node) = {
1226 .function = lookup_ip4_dst_mcast,
1227 .name = "lookup-ip4-dst-mcast",
1228 .vector_size = sizeof (u32),
1229
1230 .format_trace = format_lookup_trace,
1231 .n_next_nodes = LOOKUP_IP_DST_MCAST_N_NEXT,
1232 .next_nodes = {
1233 [LOOKUP_IP_DST_MCAST_NEXT_RPF] = "ip4-mfib-forward-rpf",
1234 },
1235};
1236VLIB_NODE_FUNCTION_MULTIARCH (lookup_ip4_dst_mcast_node,
1237 lookup_ip4_dst_mcast)
1238
Neale Ranns6c3ebcc2016-10-02 21:20:15 +01001239static void
1240lookup_dpo_mem_show (void)
1241{
1242 fib_show_memory_usage("Lookup",
1243 pool_elts(lookup_dpo_pool),
1244 pool_len(lookup_dpo_pool),
1245 sizeof(lookup_dpo_t));
1246}
1247
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001248const static dpo_vft_t lkd_vft = {
1249 .dv_lock = lookup_dpo_lock,
1250 .dv_unlock = lookup_dpo_unlock,
1251 .dv_format = format_lookup_dpo,
1252};
Neale Ranns6c3ebcc2016-10-02 21:20:15 +01001253const static dpo_vft_t lkd_vft_w_mem_show = {
1254 .dv_lock = lookup_dpo_lock,
1255 .dv_unlock = lookup_dpo_unlock,
1256 .dv_format = format_lookup_dpo,
1257 .dv_mem_show = lookup_dpo_mem_show,
1258};
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001259
1260const static char* const lookup_src_ip4_nodes[] =
1261{
1262 "lookup-ip4-src",
1263 NULL,
1264};
1265const static char* const lookup_src_ip6_nodes[] =
1266{
1267 "lookup-ip6-src",
1268 NULL,
1269};
1270const static char* const * const lookup_src_nodes[DPO_PROTO_NUM] =
1271{
1272 [DPO_PROTO_IP4] = lookup_src_ip4_nodes,
1273 [DPO_PROTO_IP6] = lookup_src_ip6_nodes,
1274 [DPO_PROTO_MPLS] = NULL,
1275};
1276
1277const static char* const lookup_dst_ip4_nodes[] =
1278{
1279 "lookup-ip4-dst",
1280 NULL,
1281};
1282const static char* const lookup_dst_ip6_nodes[] =
1283{
1284 "lookup-ip6-dst",
1285 NULL,
1286};
1287const static char* const lookup_dst_mpls_nodes[] =
1288{
1289 "lookup-mpls-dst",
1290 NULL,
1291};
1292const static char* const * const lookup_dst_nodes[DPO_PROTO_NUM] =
1293{
1294 [DPO_PROTO_IP4] = lookup_dst_ip4_nodes,
1295 [DPO_PROTO_IP6] = lookup_dst_ip6_nodes,
1296 [DPO_PROTO_MPLS] = lookup_dst_mpls_nodes,
1297};
1298
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001299const static char* const lookup_dst_mcast_ip4_nodes[] =
1300{
1301 "lookup-ip4-dst-mcast",
1302 NULL,
1303};
1304const static char* const lookup_dst_mcast_ip6_nodes[] =
1305{
1306 "lookup-ip6-dst-mcast",
1307 NULL,
1308};
1309const static char* const * const lookup_dst_mcast_nodes[DPO_PROTO_NUM] =
1310{
1311 [DPO_PROTO_IP4] = lookup_dst_mcast_ip4_nodes,
1312 [DPO_PROTO_IP6] = lookup_dst_mcast_ip6_nodes,
1313};
1314
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001315const static char* const lookup_dst_from_interface_ip4_nodes[] =
1316{
1317 "lookup-ip4-dst-itf",
1318 NULL,
1319};
1320const static char* const lookup_dst_from_interface_ip6_nodes[] =
1321{
1322 "lookup-ip6-dst-itf",
1323 NULL,
1324};
1325const static char* const lookup_dst_from_interface_mpls_nodes[] =
1326{
1327 "lookup-mpls-dst-itf",
1328 NULL,
1329};
1330const static char* const * const lookup_dst_from_interface_nodes[DPO_PROTO_NUM] =
1331{
1332 [DPO_PROTO_IP4] = lookup_dst_from_interface_ip4_nodes,
1333 [DPO_PROTO_IP6] = lookup_dst_from_interface_ip6_nodes,
1334 [DPO_PROTO_MPLS] = lookup_dst_from_interface_mpls_nodes,
1335};
1336
1337
1338void
1339lookup_dpo_module_init (void)
1340{
Neale Ranns6c3ebcc2016-10-02 21:20:15 +01001341 dpo_register(DPO_LOOKUP, &lkd_vft_w_mem_show, NULL);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001342
1343 /*
1344 * There are various sorts of lookup; src or dst addr v4 /v6 etc.
1345 * there isn't an object type for each (there is only the lookup_dpo_t),
1346 * but, for performance reasons, there is a data plane function, and hence
1347 * VLIB node for each. VLIB graph node construction is based on DPO types
1348 * so we create sub-types.
1349 */
1350 lookup_dpo_sub_types[LOOKUP_SUB_TYPE_SRC] =
1351 dpo_register_new_type(&lkd_vft, lookup_src_nodes);
1352 lookup_dpo_sub_types[LOOKUP_SUB_TYPE_DST] =
1353 dpo_register_new_type(&lkd_vft, lookup_dst_nodes);
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001354 lookup_dpo_sub_types[LOOKUP_SUB_TYPE_DST_MCAST] =
1355 dpo_register_new_type(&lkd_vft, lookup_dst_mcast_nodes);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001356 lookup_dpo_sub_types[LOOKUP_SUB_TYPE_DST_TABLE_FROM_INTERFACE] =
Billy McFallcfcf1e22016-10-14 09:51:49 -04001357 dpo_register_new_type(&lkd_vft, lookup_dst_from_interface_nodes);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001358}