blob: a3010149a4d98b2c252ab6f64017d788493cda9e [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/fib/fib_table.h>
17#include <vnet/fib/fib_entry.h>
18#include <vnet/fib/ip4_fib.h>
19
20/*
Lijian.Zhang33af8c12019-09-16 16:22:36 +080021 * A table of prefixes to be added to tables and the sources for them
Neale Ranns0bfe5d82016-08-25 15:29:12 +010022 */
23typedef struct ip4_fib_table_special_prefix_t_ {
24 fib_prefix_t ift_prefix;
25 fib_source_t ift_source;
26 fib_entry_flag_t ift_flag;
27} ip4_fib_table_special_prefix_t;
28
29static const ip4_fib_table_special_prefix_t ip4_specials[] = {
30 {
31 /* 0.0.0.0/0*/
32 .ift_prefix = {
33 .fp_addr = {
34 .ip4.data_u32 = 0,
35 },
36 .fp_len = 0,
37 .fp_proto = FIB_PROTOCOL_IP4,
38 },
39 .ift_source = FIB_SOURCE_DEFAULT_ROUTE,
40 .ift_flag = FIB_ENTRY_FLAG_DROP,
41 },
42 {
43 /* 0.0.0.0/32*/
44 .ift_prefix = {
45 .fp_addr = {
46 .ip4.data_u32 = 0,
47 },
48 .fp_len = 32,
49 .fp_proto = FIB_PROTOCOL_IP4,
50 },
51 .ift_source = FIB_SOURCE_DEFAULT_ROUTE,
52 .ift_flag = FIB_ENTRY_FLAG_DROP,
53 },
54 {
55 /*
Neale Ranns86fb04d2016-12-01 17:03:25 +000056 * 240.0.0.0/4
Neale Ranns0bfe5d82016-08-25 15:29:12 +010057 * drop class E
58 */
59 .ift_prefix = {
60 .fp_addr = {
61 .ip4.data_u32 = 0xf0000000,
62 },
Neale Ranns86fb04d2016-12-01 17:03:25 +000063 .fp_len = 4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +010064 .fp_proto = FIB_PROTOCOL_IP4,
65 },
66 .ift_source = FIB_SOURCE_SPECIAL,
67 .ift_flag = FIB_ENTRY_FLAG_DROP,
68
69 },
70 {
71 /*
Neale Ranns86fb04d2016-12-01 17:03:25 +000072 * 224.0.0.0/4
Neale Ranns0bfe5d82016-08-25 15:29:12 +010073 * drop all mcast
74 */
75 .ift_prefix = {
76 .fp_addr = {
77 .ip4.data_u32 = 0xe0000000,
78 },
Neale Ranns86fb04d2016-12-01 17:03:25 +000079 .fp_len = 4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +010080 .fp_proto = FIB_PROTOCOL_IP4,
81 },
82 .ift_source = FIB_SOURCE_SPECIAL,
83 .ift_flag = FIB_ENTRY_FLAG_DROP,
84 },
85 {
86 /*
87 * 255.255.255.255/32
88 * drop, but we'll allow it to be usurped by the likes of DHCP
89 */
90 .ift_prefix = {
91 .fp_addr = {
92 .ip4.data_u32 = 0xffffffff,
93 },
94 .fp_len = 32,
95 .fp_proto = FIB_PROTOCOL_IP4,
96 },
97 .ift_source = FIB_SOURCE_DEFAULT_ROUTE,
98 .ift_flag = FIB_ENTRY_FLAG_DROP,
99 }
100};
101
102
103static u32
Neale Ranns15002542017-09-10 04:39:11 -0700104ip4_create_fib_with_table_id (u32 table_id,
105 fib_source_t src)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100106{
107 fib_table_t *fib_table;
Neale Rannsa3af3372017-03-28 03:49:52 -0700108 ip4_fib_t *v4_fib;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100109
Dave Baracheb987d32018-05-03 08:26:39 -0400110 pool_get(ip4_main.fibs, fib_table);
Dave Barachb7b92992018-10-17 10:38:51 -0400111 clib_memset(fib_table, 0, sizeof(*fib_table));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100112
Neale Rannsa3af3372017-03-28 03:49:52 -0700113 pool_get_aligned(ip4_main.v4_fibs, v4_fib, CLIB_CACHE_LINE_BYTES);
114
115 ASSERT((fib_table - ip4_main.fibs) ==
116 (v4_fib - ip4_main.v4_fibs));
117
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100118 fib_table->ft_proto = FIB_PROTOCOL_IP4;
119 fib_table->ft_index =
Neale Rannsa3af3372017-03-28 03:49:52 -0700120 v4_fib->index =
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100121 (fib_table - ip4_main.fibs);
122
123 hash_set (ip4_main.fib_index_by_table_id, table_id, fib_table->ft_index);
124
125 fib_table->ft_table_id =
Neale Rannsa3af3372017-03-28 03:49:52 -0700126 v4_fib->table_id =
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100127 table_id;
Neale Ranns227038a2017-04-21 01:07:59 -0700128 fib_table->ft_flow_hash_config = IP_FLOW_HASH_DEFAULT;
Dave Barach2c8e0022020-02-11 15:06:34 -0500129
Neale Ranns15002542017-09-10 04:39:11 -0700130 fib_table_lock(fib_table->ft_index, FIB_PROTOCOL_IP4, src);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100131
Neale Rannsa3af3372017-03-28 03:49:52 -0700132 ip4_mtrie_init(&v4_fib->mtrie);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100133
134 /*
135 * add the special entries into the new FIB
136 */
137 int ii;
138
139 for (ii = 0; ii < ARRAY_LEN(ip4_specials); ii++)
140 {
141 fib_prefix_t prefix = ip4_specials[ii].ift_prefix;
142
143 prefix.fp_addr.ip4.data_u32 =
144 clib_host_to_net_u32(prefix.fp_addr.ip4.data_u32);
145
146 fib_table_entry_special_add(fib_table->ft_index,
147 &prefix,
148 ip4_specials[ii].ift_source,
Neale Rannsa0558302017-04-13 00:44:52 -0700149 ip4_specials[ii].ift_flag);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100150 }
151
152 return (fib_table->ft_index);
153}
154
155void
Neale Rannsa3af3372017-03-28 03:49:52 -0700156ip4_fib_table_destroy (u32 fib_index)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100157{
Neale Rannsa3af3372017-03-28 03:49:52 -0700158 fib_table_t *fib_table = pool_elt_at_index(ip4_main.fibs, fib_index);
159 ip4_fib_t *v4_fib = pool_elt_at_index(ip4_main.v4_fibs, fib_index);
Neale Ranns3bab8f92019-12-04 06:11:00 +0000160 u32 *n_locks;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100161 int ii;
162
163 /*
164 * remove all the specials we added when the table was created.
Neale Ranns04a75e32017-03-23 06:46:01 -0700165 * In reverse order so the default route is last.
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100166 */
Neale Ranns04a75e32017-03-23 06:46:01 -0700167 for (ii = ARRAY_LEN(ip4_specials) - 1; ii >= 0; ii--)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100168 {
169 fib_prefix_t prefix = ip4_specials[ii].ift_prefix;
170
171 prefix.fp_addr.ip4.data_u32 =
172 clib_host_to_net_u32(prefix.fp_addr.ip4.data_u32);
173
174 fib_table_entry_special_remove(fib_table->ft_index,
175 &prefix,
176 ip4_specials[ii].ift_source);
177 }
178
179 /*
180 * validate no more routes.
181 */
Matthew Smithee167e52020-07-02 17:24:17 -0500182#if CLIB_DEBUG > 0
Neale Rannscbe25aa2019-09-30 10:53:31 +0000183 if (0 != fib_table->ft_total_route_counts)
184 fib_table_assert_empty(fib_table);
185#endif
Neale Ranns3bab8f92019-12-04 06:11:00 +0000186
187 vec_foreach(n_locks, fib_table->ft_src_route_counts)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100188 {
Neale Ranns3bab8f92019-12-04 06:11:00 +0000189 ASSERT(0 == *n_locks);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100190 }
191
192 if (~0 != fib_table->ft_table_id)
193 {
194 hash_unset (ip4_main.fib_index_by_table_id, fib_table->ft_table_id);
195 }
Neale Rannsa3af3372017-03-28 03:49:52 -0700196
Neale Ranns3bab8f92019-12-04 06:11:00 +0000197 vec_free(fib_table->ft_src_route_counts);
Neale Rannsa3af3372017-03-28 03:49:52 -0700198 ip4_mtrie_free(&v4_fib->mtrie);
199
200 pool_put(ip4_main.v4_fibs, v4_fib);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100201 pool_put(ip4_main.fibs, fib_table);
202}
203
204
205u32
Neale Ranns15002542017-09-10 04:39:11 -0700206ip4_fib_table_find_or_create_and_lock (u32 table_id,
207 fib_source_t src)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100208{
209 u32 index;
210
211 index = ip4_fib_index_from_table_id(table_id);
212 if (~0 == index)
Neale Ranns15002542017-09-10 04:39:11 -0700213 return ip4_create_fib_with_table_id(table_id, src);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100214
Neale Ranns15002542017-09-10 04:39:11 -0700215 fib_table_lock(index, FIB_PROTOCOL_IP4, src);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100216
217 return (index);
218}
219
220u32
Neale Ranns15002542017-09-10 04:39:11 -0700221ip4_fib_table_create_and_lock (fib_source_t src)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100222{
Neale Ranns15002542017-09-10 04:39:11 -0700223 return (ip4_create_fib_with_table_id(~0, src));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100224}
225
226u32
227ip4_fib_table_get_index_for_sw_if_index (u32 sw_if_index)
228{
229 if (sw_if_index >= vec_len(ip4_main.fib_index_by_sw_if_index))
230 {
231 /*
232 * This is the case for interfaces that are not yet mapped to
233 * a IP table
234 */
235 return (~0);
236 }
237 return (ip4_main.fib_index_by_sw_if_index[sw_if_index]);
238}
239
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100240/*
241 * ip4_fib_table_lookup_exact_match
242 *
243 * Exact match prefix lookup
244 */
245fib_node_index_t
246ip4_fib_table_lookup_exact_match (const ip4_fib_t *fib,
247 const ip4_address_t *addr,
248 u32 len)
249{
250 uword * hash, * result;
251 u32 key;
252
253 hash = fib->fib_entry_by_dst_address[len];
254 key = (addr->data_u32 & ip4_main.fib_masks[len]);
255
256 result = hash_get(hash, key);
257
258 if (NULL != result) {
259 return (result[0]);
260 }
261 return (FIB_NODE_INDEX_INVALID);
262}
263
264/*
265 * ip4_fib_table_lookup_adj
266 *
267 * Longest prefix match
268 */
269index_t
270ip4_fib_table_lookup_lb (ip4_fib_t *fib,
271 const ip4_address_t *addr)
272{
273 fib_node_index_t fei;
274
275 fei = ip4_fib_table_lookup(fib, addr, 32);
276
277 if (FIB_NODE_INDEX_INVALID != fei)
278 {
279 const dpo_id_t *dpo;
280
281 dpo = fib_entry_contribute_ip_forwarding(fei);
282
283 return (dpo->dpoi_index);
284 }
285 return (INDEX_INVALID);
286}
287
288/*
289 * ip4_fib_table_lookup
290 *
291 * Longest prefix match
292 */
293fib_node_index_t
294ip4_fib_table_lookup (const ip4_fib_t *fib,
295 const ip4_address_t *addr,
296 u32 len)
297{
298 uword * hash, * result;
299 i32 mask_len;
300 u32 key;
301
302 for (mask_len = len; mask_len >= 0; mask_len--)
303 {
304 hash = fib->fib_entry_by_dst_address[mask_len];
305 key = (addr->data_u32 & ip4_main.fib_masks[mask_len]);
306
307 result = hash_get (hash, key);
308
309 if (NULL != result) {
310 return (result[0]);
311 }
312 }
313 return (FIB_NODE_INDEX_INVALID);
314}
315
316void
317ip4_fib_table_entry_insert (ip4_fib_t *fib,
318 const ip4_address_t *addr,
319 u32 len,
320 fib_node_index_t fib_entry_index)
321{
322 uword * hash, * result;
323 u32 key;
324
325 key = (addr->data_u32 & ip4_main.fib_masks[len]);
326 hash = fib->fib_entry_by_dst_address[len];
327 result = hash_get (hash, key);
328
329 if (NULL == result) {
330 /*
331 * adding a new entry
332 */
Neale Ranns1ec36522017-11-29 05:20:37 -0800333
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100334 if (NULL == hash) {
335 hash = hash_create (32 /* elts */, sizeof (uword));
336 hash_set_flags (hash, HASH_FLAG_NO_AUTO_SHRINK);
Neale Ranns1ec36522017-11-29 05:20:37 -0800337
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100338 }
339 hash = hash_set(hash, key, fib_entry_index);
340 fib->fib_entry_by_dst_address[len] = hash;
341 }
342 else
343 {
344 ASSERT(0);
345 }
346}
347
348void
349ip4_fib_table_entry_remove (ip4_fib_t *fib,
350 const ip4_address_t *addr,
351 u32 len)
352{
353 uword * hash, * result;
354 u32 key;
355
356 key = (addr->data_u32 & ip4_main.fib_masks[len]);
357 hash = fib->fib_entry_by_dst_address[len];
358 result = hash_get (hash, key);
359
360 if (NULL == result)
361 {
362 /*
Jim Thompsonf324dec2019-04-08 03:22:21 -0500363 * removing a non-existent entry. i'll allow it.
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100364 */
365 }
Dave Barach2c8e0022020-02-11 15:06:34 -0500366 else
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100367 {
368 hash_unset(hash, key);
369 }
370
371 fib->fib_entry_by_dst_address[len] = hash;
372}
373
374void
375ip4_fib_table_fwding_dpo_update (ip4_fib_t *fib,
376 const ip4_address_t *addr,
377 u32 len,
378 const dpo_id_t *dpo)
379{
Neale Rannsa3af3372017-03-28 03:49:52 -0700380 ip4_fib_mtrie_route_add(&fib->mtrie, addr, len, dpo->dpoi_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100381}
382
383void
384ip4_fib_table_fwding_dpo_remove (ip4_fib_t *fib,
385 const ip4_address_t *addr,
386 u32 len,
Neale Rannsa3af3372017-03-28 03:49:52 -0700387 const dpo_id_t *dpo,
388 u32 cover_index)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100389{
Neale Rannsc5d43172018-07-30 08:04:40 -0700390 const fib_prefix_t *cover_prefix;
Neale Rannsa3af3372017-03-28 03:49:52 -0700391 const dpo_id_t *cover_dpo;
392
393 /*
394 * We need to pass the MTRIE the LB index and address length of the
395 * covering prefix, so it can fill the plys with the correct replacement
396 * for the entry being removed
397 */
Neale Rannsc5d43172018-07-30 08:04:40 -0700398 cover_prefix = fib_entry_get_prefix(cover_index);
Neale Rannsa3af3372017-03-28 03:49:52 -0700399 cover_dpo = fib_entry_contribute_ip_forwarding(cover_index);
400
401 ip4_fib_mtrie_route_del(&fib->mtrie,
402 addr, len, dpo->dpoi_index,
Neale Rannsc5d43172018-07-30 08:04:40 -0700403 cover_prefix->fp_len,
Neale Rannsa3af3372017-03-28 03:49:52 -0700404 cover_dpo->dpoi_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100405}
406
Neale Ranns32e1c012016-11-22 17:07:28 +0000407void
408ip4_fib_table_walk (ip4_fib_t *fib,
409 fib_table_walk_fn_t fn,
410 void *ctx)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100411{
Neale Ranns89541992017-04-06 04:41:02 -0700412 fib_prefix_t root = {
413 .fp_proto = FIB_PROTOCOL_IP4,
414 // address and length default to all 0
415 };
416
417 /*
418 * A full tree walk is the dengenerate case of a sub-tree from
419 * the very root
420 */
421 return (ip4_fib_table_sub_tree_walk(fib, &root, fn, ctx));
422}
423
424void
425ip4_fib_table_sub_tree_walk (ip4_fib_t *fib,
426 const fib_prefix_t *root,
427 fib_table_walk_fn_t fn,
428 void *ctx)
429{
430 fib_prefix_t *sub_trees = NULL;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100431 int i;
432
Neale Ranns89541992017-04-06 04:41:02 -0700433 /*
Lijian.Zhang33af8c12019-09-16 16:22:36 +0800434 * There is no efficient way to walk this array of hash tables.
Neale Ranns89541992017-04-06 04:41:02 -0700435 * so we walk each table with a mask length greater than and equal to
436 * the required root and check it is covered by the root.
437 */
438 for (i = root->fp_len;
439 i < ARRAY_LEN (fib->fib_entry_by_dst_address);
440 i++)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100441 {
442 uword * hash = fib->fib_entry_by_dst_address[i];
443
444 if (NULL != hash)
445 {
Neale Ranns89541992017-04-06 04:41:02 -0700446 ip4_address_t key;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100447 hash_pair_t * p;
448
449 hash_foreach_pair (p, hash,
450 ({
Neale Ranns89541992017-04-06 04:41:02 -0700451 key.as_u32 = p->key;
452 if (ip4_destination_matches_route(&ip4_main,
453 &key,
454 &root->fp_addr.ip4,
455 root->fp_len))
456 {
457 const fib_prefix_t *sub_tree;
458 int skip = 0;
459
460 /*
461 * exclude sub-trees the walk does not want to explore
462 */
463 vec_foreach(sub_tree, sub_trees)
464 {
465 if (ip4_destination_matches_route(&ip4_main,
466 &key,
467 &sub_tree->fp_addr.ip4,
468 sub_tree->fp_len))
469 {
470 skip = 1;
471 break;
472 }
473 }
474
475 if (!skip)
476 {
477 switch (fn(p->value[0], ctx))
478 {
479 case FIB_TABLE_WALK_CONTINUE:
480 break;
481 case FIB_TABLE_WALK_SUB_TREE_STOP: {
482 fib_prefix_t pfx = {
483 .fp_proto = FIB_PROTOCOL_IP4,
484 .fp_len = i,
485 .fp_addr.ip4 = key,
486 };
487 vec_add1(sub_trees, pfx);
488 break;
489 }
490 case FIB_TABLE_WALK_STOP:
491 goto done;
492 }
493 }
494 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100495 }));
496 }
497 }
Neale Ranns89541992017-04-06 04:41:02 -0700498done:
499 vec_free(sub_trees);
500 return;
Neale Ranns32e1c012016-11-22 17:07:28 +0000501}
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100502
Neale Ranns32e1c012016-11-22 17:07:28 +0000503/**
504 * Walk show context
505 */
506typedef struct ip4_fib_show_walk_ctx_t_
507{
508 fib_node_index_t *ifsw_indicies;
509} ip4_fib_show_walk_ctx_t;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100510
Neale Ranns89541992017-04-06 04:41:02 -0700511static fib_table_walk_rc_t
Neale Ranns32e1c012016-11-22 17:07:28 +0000512ip4_fib_show_walk_cb (fib_node_index_t fib_entry_index,
513 void *arg)
514{
515 ip4_fib_show_walk_ctx_t *ctx = arg;
516
517 vec_add1(ctx->ifsw_indicies, fib_entry_index);
518
Neale Ranns89541992017-04-06 04:41:02 -0700519 return (FIB_TABLE_WALK_CONTINUE);
Neale Ranns32e1c012016-11-22 17:07:28 +0000520}
521
522static void
523ip4_fib_table_show_all (ip4_fib_t *fib,
524 vlib_main_t * vm)
525{
526 ip4_fib_show_walk_ctx_t ctx = {
527 .ifsw_indicies = NULL,
528 };
529 fib_node_index_t *fib_entry_index;
530
531 ip4_fib_table_walk(fib, ip4_fib_show_walk_cb, &ctx);
532 vec_sort_with_function(ctx.ifsw_indicies,
533 fib_entry_cmp_for_sort);
534
535 vec_foreach(fib_entry_index, ctx.ifsw_indicies)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100536 {
537 vlib_cli_output(vm, "%U",
538 format_fib_entry,
539 *fib_entry_index,
540 FIB_ENTRY_FORMAT_BRIEF);
541 }
542
Neale Ranns32e1c012016-11-22 17:07:28 +0000543 vec_free(ctx.ifsw_indicies);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100544}
545
546static void
547ip4_fib_table_show_one (ip4_fib_t *fib,
548 vlib_main_t * vm,
549 ip4_address_t *address,
Neale Ranns88fc83e2017-04-05 08:11:14 -0700550 u32 mask_len,
551 int detail)
Dave Barach2c8e0022020-02-11 15:06:34 -0500552{
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100553 vlib_cli_output(vm, "%U",
554 format_fib_entry,
555 ip4_fib_table_lookup(fib, address, mask_len),
Neale Ranns88fc83e2017-04-05 08:11:14 -0700556 (detail ?
557 FIB_ENTRY_FORMAT_DETAIL2 :
558 FIB_ENTRY_FORMAT_DETAIL));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100559}
560
Neale Rannsc87aafa2017-11-29 00:59:31 -0800561u8 *
562format_ip4_fib_table_memory (u8 * s, va_list * args)
563{
Damjan Marion8157a162020-09-16 17:06:45 +0200564 s = format(s, "%=30s %=6d\n",
Dave Barach6a5adc32018-07-04 10:56:23 -0400565 "IPv4 unicast",
Damjan Marion8157a162020-09-16 17:06:45 +0200566 pool_elts(ip4_main.fibs));
Neale Rannsc87aafa2017-11-29 00:59:31 -0800567 return (s);
568}
569
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100570static clib_error_t *
571ip4_show_fib (vlib_main_t * vm,
572 unformat_input_t * input,
573 vlib_cli_command_t * cmd)
574{
575 ip4_main_t * im4 = &ip4_main;
576 fib_table_t * fib_table;
Neale Rannsc87aafa2017-11-29 00:59:31 -0800577 u64 total_mtrie_memory, total_hash_memory;
578 int verbose, matching, mtrie, memory;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100579 ip4_address_t matching_address;
580 u32 matching_mask = 32;
581 int i, table_id = -1, fib_index = ~0;
Neale Ranns88fc83e2017-04-05 08:11:14 -0700582 int detail = 0;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100583
584 verbose = 1;
Neale Rannsc87aafa2017-11-29 00:59:31 -0800585 matching = mtrie = memory = 0;
586 total_hash_memory = total_mtrie_memory = 0;
587
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100588 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
589 {
590 if (unformat (input, "brief") || unformat (input, "summary")
591 || unformat (input, "sum"))
592 verbose = 0;
593
Neale Ranns88fc83e2017-04-05 08:11:14 -0700594 else if (unformat (input, "detail") || unformat (input, "det"))
595 detail = 1;
596
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100597 else if (unformat (input, "mtrie"))
598 mtrie = 1;
599
Neale Rannsc87aafa2017-11-29 00:59:31 -0800600 else if (unformat (input, "mem") ||
601 unformat (input, "memory"))
602 memory = 1;
603
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100604 else if (unformat (input, "%U/%d",
605 unformat_ip4_address, &matching_address, &matching_mask))
606 matching = 1;
607
608 else if (unformat (input, "%U", unformat_ip4_address, &matching_address))
609 matching = 1;
610
611 else if (unformat (input, "table %d", &table_id))
612 ;
613 else if (unformat (input, "index %d", &fib_index))
614 ;
615 else
616 break;
617 }
618
Damjan Marionb2c31b62020-12-13 21:47:40 +0100619 pool_foreach (fib_table, im4->fibs)
620 {
Neale Rannsa3af3372017-03-28 03:49:52 -0700621 ip4_fib_t *fib = pool_elt_at_index(im4->v4_fibs, fib_table->ft_index);
Neale Ranns15002542017-09-10 04:39:11 -0700622 fib_source_t source;
623 u8 *s = NULL;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100624
625 if (table_id >= 0 && table_id != (int)fib->table_id)
626 continue;
627 if (fib_index != ~0 && fib_index != (int)fib->index)
628 continue;
629
Neale Rannsc87aafa2017-11-29 00:59:31 -0800630 if (memory)
631 {
Damjan Marion8157a162020-09-16 17:06:45 +0200632 uword mtrie_size, hash_size;
Lollita Liue18b45c2019-01-11 05:23:12 -0500633
Neale Rannsc87aafa2017-11-29 00:59:31 -0800634
635 mtrie_size = ip4_fib_mtrie_memory_usage(&fib->mtrie);
636 hash_size = 0;
637
638 for (i = 0; i < ARRAY_LEN (fib->fib_entry_by_dst_address); i++)
639 {
640 uword * hash = fib->fib_entry_by_dst_address[i];
641 if (NULL != hash)
642 {
643 hash_size += hash_bytes(hash);
644 }
645 }
Lollita Liue18b45c2019-01-11 05:23:12 -0500646
Neale Rannsc87aafa2017-11-29 00:59:31 -0800647 if (verbose)
648 vlib_cli_output (vm, "%U mtrie:%d hash:%d",
649 format_fib_table_name, fib->index,
650 FIB_PROTOCOL_IP4,
651 mtrie_size,
652 hash_size);
653 total_mtrie_memory += mtrie_size;
654 total_hash_memory += hash_size;
655 continue;
656 }
657
Neale Ranns9db6ada2019-11-08 12:42:31 +0000658 s = format(s, "%U, fib_index:%d, flow hash:[%U] epoch:%d flags:%U locks:[",
Neale Ranns15002542017-09-10 04:39:11 -0700659 format_fib_table_name, fib->index,
660 FIB_PROTOCOL_IP4,
661 fib->index,
662 format_ip_flow_hash_config,
Neale Ranns9db6ada2019-11-08 12:42:31 +0000663 fib_table->ft_flow_hash_config,
664 fib_table->ft_epoch,
665 format_fib_table_flags, fib_table->ft_flags);
Neale Ranns3bab8f92019-12-04 06:11:00 +0000666 vec_foreach_index(source, fib_table->ft_locks)
Neale Ranns15002542017-09-10 04:39:11 -0700667 {
668 if (0 != fib_table->ft_locks[source])
669 {
670 s = format(s, "%U:%d, ",
671 format_fib_source, source,
672 fib_table->ft_locks[source]);
673 }
674 }
675 s = format (s, "]");
Neale Ranns2297af02017-09-12 09:45:04 -0700676 vlib_cli_output (vm, "%v", s);
Neale Ranns15002542017-09-10 04:39:11 -0700677 vec_free(s);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100678
679 /* Show summary? */
Neale Ranns39194252017-11-27 01:03:25 -0800680 if (mtrie)
681 {
682 vlib_cli_output (vm, "%U", format_ip4_fib_mtrie, &fib->mtrie, verbose);
683 continue;
684 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100685 if (! verbose)
686 {
687 vlib_cli_output (vm, "%=20s%=16s", "Prefix length", "Count");
688 for (i = 0; i < ARRAY_LEN (fib->fib_entry_by_dst_address); i++)
689 {
690 uword * hash = fib->fib_entry_by_dst_address[i];
691 uword n_elts = hash_elts (hash);
692 if (n_elts > 0)
693 vlib_cli_output (vm, "%20d%16d", i, n_elts);
694 }
695 continue;
696 }
697
698 if (!matching)
699 {
700 ip4_fib_table_show_all(fib, vm);
701 }
702 else
703 {
Neale Ranns88fc83e2017-04-05 08:11:14 -0700704 ip4_fib_table_show_one(fib, vm, &matching_address,
705 matching_mask, detail);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100706 }
Damjan Marionb2c31b62020-12-13 21:47:40 +0100707 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100708
Neale Rannsc87aafa2017-11-29 00:59:31 -0800709 if (memory)
Lollita Liue18b45c2019-01-11 05:23:12 -0500710 {
Neale Rannsc87aafa2017-11-29 00:59:31 -0800711 vlib_cli_output (vm, "totals: mtrie:%ld hash:%ld all:%ld",
712 total_mtrie_memory,
713 total_hash_memory,
714 total_mtrie_memory + total_hash_memory);
Lollita Liue18b45c2019-01-11 05:23:12 -0500715 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100716 return 0;
717}
718
719/*?
Billy McFall0683c9c2016-10-13 08:27:31 -0400720 * This command displays the IPv4 FIB Tables (VRF Tables) and the route
721 * entries for each table.
722 *
723 * @note This command will run for a long time when the FIB tables are
724 * comprised of millions of entries. For those senarios, consider displaying
725 * a single table or summary mode.
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100726 *
727 * @cliexpar
Billy McFall0683c9c2016-10-13 08:27:31 -0400728 * Example of how to display all the IPv4 FIB tables:
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100729 * @cliexstart{show ip fib}
Billy McFallebb9a6a2016-10-17 11:35:32 -0400730 * ipv4-VRF:0, fib_index 0, flow hash: src dst sport dport proto
731 * 0.0.0.0/0
732 * unicast-ip4-chain
733 * [@0]: dpo-load-balance: [index:0 buckets:1 uRPF:0 to:[0:0]]
734 * [0] [@0]: dpo-drop ip6
735 * 0.0.0.0/32
736 * unicast-ip4-chain
737 * [@0]: dpo-load-balance: [index:1 buckets:1 uRPF:1 to:[0:0]]
738 * [0] [@0]: dpo-drop ip6
739 * 6.0.1.2/32
740 * unicast-ip4-chain
741 * [@0]: dpo-load-balance: [index:30 buckets:1 uRPF:29 to:[0:0]]
742 * [0] [@3]: arp-ipv4: via 6.0.0.1 af_packet0
743 * 7.0.0.1/32
744 * unicast-ip4-chain
745 * [@0]: dpo-load-balance: [index:31 buckets:4 uRPF:30 to:[0:0]]
746 * [0] [@3]: arp-ipv4: via 6.0.0.2 af_packet0
747 * [1] [@3]: arp-ipv4: via 6.0.0.2 af_packet0
748 * [2] [@3]: arp-ipv4: via 6.0.0.2 af_packet0
749 * [3] [@3]: arp-ipv4: via 6.0.0.1 af_packet0
750 * 224.0.0.0/8
751 * unicast-ip4-chain
752 * [@0]: dpo-load-balance: [index:3 buckets:1 uRPF:3 to:[0:0]]
753 * [0] [@0]: dpo-drop ip6
754 * 240.0.0.0/8
755 * unicast-ip4-chain
756 * [@0]: dpo-load-balance: [index:2 buckets:1 uRPF:2 to:[0:0]]
757 * [0] [@0]: dpo-drop ip6
758 * 255.255.255.255/32
759 * unicast-ip4-chain
760 * [@0]: dpo-load-balance: [index:4 buckets:1 uRPF:4 to:[0:0]]
761 * [0] [@0]: dpo-drop ip6
762 * ipv4-VRF:7, fib_index 1, flow hash: src dst sport dport proto
763 * 0.0.0.0/0
764 * unicast-ip4-chain
765 * [@0]: dpo-load-balance: [index:12 buckets:1 uRPF:11 to:[0:0]]
766 * [0] [@0]: dpo-drop ip6
767 * 0.0.0.0/32
768 * unicast-ip4-chain
769 * [@0]: dpo-load-balance: [index:13 buckets:1 uRPF:12 to:[0:0]]
770 * [0] [@0]: dpo-drop ip6
771 * 172.16.1.0/24
772 * unicast-ip4-chain
773 * [@0]: dpo-load-balance: [index:17 buckets:1 uRPF:16 to:[0:0]]
774 * [0] [@4]: ipv4-glean: af_packet0
775 * 172.16.1.1/32
776 * unicast-ip4-chain
777 * [@0]: dpo-load-balance: [index:18 buckets:1 uRPF:17 to:[1:84]]
778 * [0] [@2]: dpo-receive: 172.16.1.1 on af_packet0
779 * 172.16.1.2/32
780 * unicast-ip4-chain
781 * [@0]: dpo-load-balance: [index:21 buckets:1 uRPF:20 to:[0:0]]
782 * [0] [@5]: ipv4 via 172.16.1.2 af_packet0: IP4: 02:fe:9e:70:7a:2b -> 26:a5:f6:9c:3a:36
783 * 172.16.2.0/24
784 * unicast-ip4-chain
785 * [@0]: dpo-load-balance: [index:19 buckets:1 uRPF:18 to:[0:0]]
786 * [0] [@4]: ipv4-glean: af_packet1
787 * 172.16.2.1/32
788 * unicast-ip4-chain
789 * [@0]: dpo-load-balance: [index:20 buckets:1 uRPF:19 to:[0:0]]
790 * [0] [@2]: dpo-receive: 172.16.2.1 on af_packet1
791 * 224.0.0.0/8
792 * unicast-ip4-chain
793 * [@0]: dpo-load-balance: [index:15 buckets:1 uRPF:14 to:[0:0]]
794 * [0] [@0]: dpo-drop ip6
795 * 240.0.0.0/8
796 * unicast-ip4-chain
797 * [@0]: dpo-load-balance: [index:14 buckets:1 uRPF:13 to:[0:0]]
798 * [0] [@0]: dpo-drop ip6
799 * 255.255.255.255/32
800 * unicast-ip4-chain
801 * [@0]: dpo-load-balance: [index:16 buckets:1 uRPF:15 to:[0:0]]
802 * [0] [@0]: dpo-drop ip6
Billy McFall0683c9c2016-10-13 08:27:31 -0400803 * @cliexend
804 * Example of how to display a single IPv4 FIB table:
805 * @cliexstart{show ip fib table 7}
Billy McFallebb9a6a2016-10-17 11:35:32 -0400806 * ipv4-VRF:7, fib_index 1, flow hash: src dst sport dport proto
807 * 0.0.0.0/0
808 * unicast-ip4-chain
809 * [@0]: dpo-load-balance: [index:12 buckets:1 uRPF:11 to:[0:0]]
810 * [0] [@0]: dpo-drop ip6
811 * 0.0.0.0/32
812 * unicast-ip4-chain
813 * [@0]: dpo-load-balance: [index:13 buckets:1 uRPF:12 to:[0:0]]
814 * [0] [@0]: dpo-drop ip6
815 * 172.16.1.0/24
816 * unicast-ip4-chain
817 * [@0]: dpo-load-balance: [index:17 buckets:1 uRPF:16 to:[0:0]]
818 * [0] [@4]: ipv4-glean: af_packet0
819 * 172.16.1.1/32
820 * unicast-ip4-chain
821 * [@0]: dpo-load-balance: [index:18 buckets:1 uRPF:17 to:[1:84]]
822 * [0] [@2]: dpo-receive: 172.16.1.1 on af_packet0
823 * 172.16.1.2/32
824 * unicast-ip4-chain
825 * [@0]: dpo-load-balance: [index:21 buckets:1 uRPF:20 to:[0:0]]
826 * [0] [@5]: ipv4 via 172.16.1.2 af_packet0: IP4: 02:fe:9e:70:7a:2b -> 26:a5:f6:9c:3a:36
827 * 172.16.2.0/24
828 * unicast-ip4-chain
829 * [@0]: dpo-load-balance: [index:19 buckets:1 uRPF:18 to:[0:0]]
830 * [0] [@4]: ipv4-glean: af_packet1
831 * 172.16.2.1/32
832 * unicast-ip4-chain
833 * [@0]: dpo-load-balance: [index:20 buckets:1 uRPF:19 to:[0:0]]
834 * [0] [@2]: dpo-receive: 172.16.2.1 on af_packet1
835 * 224.0.0.0/8
836 * unicast-ip4-chain
837 * [@0]: dpo-load-balance: [index:15 buckets:1 uRPF:14 to:[0:0]]
838 * [0] [@0]: dpo-drop ip6
839 * 240.0.0.0/8
840 * unicast-ip4-chain
841 * [@0]: dpo-load-balance: [index:14 buckets:1 uRPF:13 to:[0:0]]
842 * [0] [@0]: dpo-drop ip6
843 * 255.255.255.255/32
844 * unicast-ip4-chain
845 * [@0]: dpo-load-balance: [index:16 buckets:1 uRPF:15 to:[0:0]]
846 * [0] [@0]: dpo-drop ip6
Billy McFall0683c9c2016-10-13 08:27:31 -0400847 * @cliexend
848 * Example of how to display a summary of all IPv4 FIB tables:
849 * @cliexstart{show ip fib summary}
Billy McFallebb9a6a2016-10-17 11:35:32 -0400850 * ipv4-VRF:0, fib_index 0, flow hash: src dst sport dport proto
Billy McFall0683c9c2016-10-13 08:27:31 -0400851 * Prefix length Count
Billy McFallebb9a6a2016-10-17 11:35:32 -0400852 * 0 1
853 * 8 2
854 * 32 4
855 * ipv4-VRF:7, fib_index 1, flow hash: src dst sport dport proto
Billy McFall0683c9c2016-10-13 08:27:31 -0400856 * Prefix length Count
Billy McFallebb9a6a2016-10-17 11:35:32 -0400857 * 0 1
858 * 8 2
859 * 24 2
860 * 32 4
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100861 * @cliexend
862 ?*/
Billy McFall0683c9c2016-10-13 08:27:31 -0400863/* *INDENT-OFF* */
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100864VLIB_CLI_COMMAND (ip4_show_fib_command, static) = {
865 .path = "show ip fib",
Neale Ranns88fc83e2017-04-05 08:11:14 -0700866 .short_help = "show ip fib [summary] [table <table-id>] [index <fib-id>] [<ip4-addr>[/<mask>]] [mtrie] [detail]",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100867 .function = ip4_show_fib,
868};
Billy McFall0683c9c2016-10-13 08:27:31 -0400869/* *INDENT-ON* */