blob: 343ff55e80a5aa1d84f8bfd8fd0032733c5c7e25 [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/ip6_fib.h>
17#include <vnet/fib/fib_table.h>
18
19static void
20vnet_ip6_fib_init (u32 fib_index)
21{
22 fib_prefix_t pfx = {
23 .fp_proto = FIB_PROTOCOL_IP6,
24 .fp_len = 0,
25 .fp_addr = {
26 .ip6 = {
27 { 0, 0, },
28 },
29 }
30 };
31
32 /*
33 * Add the default route.
34 */
35 fib_table_entry_special_add(fib_index,
36 &pfx,
37 FIB_SOURCE_DEFAULT_ROUTE,
38 FIB_ENTRY_FLAG_DROP,
39 ADJ_INDEX_INVALID);
40
41 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +010042 * all link local for us
43 */
44 pfx.fp_addr.ip6.as_u64[0] = clib_host_to_net_u64 (0xFE80000000000000ULL);
45 pfx.fp_addr.ip6.as_u64[1] = 0;
46 pfx.fp_len = 10;
47 fib_table_entry_special_add(fib_index,
48 &pfx,
49 FIB_SOURCE_SPECIAL,
50 FIB_ENTRY_FLAG_LOCAL,
51 ADJ_INDEX_INVALID);
52}
53
54static u32
55create_fib_with_table_id (u32 table_id)
56{
57 fib_table_t *fib_table;
58
59 pool_get_aligned(ip6_main.fibs, fib_table, CLIB_CACHE_LINE_BYTES);
60 memset(fib_table, 0, sizeof(*fib_table));
61
62 fib_table->ft_proto = FIB_PROTOCOL_IP6;
63 fib_table->ft_index =
64 fib_table->v6.index =
65 (fib_table - ip6_main.fibs);
66
67 hash_set(ip6_main.fib_index_by_table_id, table_id, fib_table->ft_index);
68
69 fib_table->ft_table_id =
70 fib_table->v6.table_id =
71 table_id;
72 fib_table->ft_flow_hash_config =
73 fib_table->v6.flow_hash_config =
74 IP_FLOW_HASH_DEFAULT;
75
76 vnet_ip6_fib_init(fib_table->ft_index);
77 fib_table_lock(fib_table->ft_index, FIB_PROTOCOL_IP6);
78
79 return (fib_table->ft_index);
80}
81
82u32
83ip6_fib_table_find_or_create_and_lock (u32 table_id)
84{
85 uword * p;
86
87 p = hash_get (ip6_main.fib_index_by_table_id, table_id);
88 if (NULL == p)
89 return create_fib_with_table_id(table_id);
90
91 fib_table_lock(p[0], FIB_PROTOCOL_IP6);
92
93 return (p[0]);
94}
95
96u32
97ip6_fib_table_create_and_lock (void)
98{
99 return (create_fib_with_table_id(~0));
100}
101
102void
103ip6_fib_table_destroy (u32 fib_index)
104{
105 fib_prefix_t pfx = {
106 .fp_proto = FIB_PROTOCOL_IP6,
107 .fp_len = 0,
108 .fp_addr = {
109 .ip6 = {
110 { 0, 0, },
111 },
112 }
113 };
114
115 /*
116 * the default route.
117 */
118 fib_table_entry_special_remove(fib_index,
119 &pfx,
120 FIB_SOURCE_DEFAULT_ROUTE);
121
122
123 /*
124 * ff02::1:ff00:0/104
125 */
126 ip6_set_solicited_node_multicast_address(&pfx.fp_addr.ip6, 0);
127 pfx.fp_len = 104;
128 fib_table_entry_special_remove(fib_index,
129 &pfx,
130 FIB_SOURCE_SPECIAL);
131
132 /*
133 * all-routers multicast address
134 */
135 ip6_set_reserved_multicast_address (&pfx.fp_addr.ip6,
136 IP6_MULTICAST_SCOPE_link_local,
137 IP6_MULTICAST_GROUP_ID_all_routers);
138 pfx.fp_len = 128;
139 fib_table_entry_special_remove(fib_index,
140 &pfx,
141 FIB_SOURCE_SPECIAL);
142
143 /*
144 * all-nodes multicast address
145 */
146 ip6_set_reserved_multicast_address (&pfx.fp_addr.ip6,
147 IP6_MULTICAST_SCOPE_link_local,
148 IP6_MULTICAST_GROUP_ID_all_hosts);
149 pfx.fp_len = 128;
150 fib_table_entry_special_remove(fib_index,
151 &pfx,
152 FIB_SOURCE_SPECIAL);
153
154 /*
155 * all-mldv2 multicast address
156 */
157 ip6_set_reserved_multicast_address (&pfx.fp_addr.ip6,
158 IP6_MULTICAST_SCOPE_link_local,
159 IP6_MULTICAST_GROUP_ID_mldv2_routers);
160 pfx.fp_len = 128;
161 fib_table_entry_special_remove(fib_index,
162 &pfx,
163 FIB_SOURCE_SPECIAL);
164
165 /*
166 * all link local
167 */
168 pfx.fp_addr.ip6.as_u64[0] = clib_host_to_net_u64 (0xFE80000000000000ULL);
169 pfx.fp_addr.ip6.as_u64[1] = 0;
170 pfx.fp_len = 10;
171 fib_table_entry_special_remove(fib_index,
172 &pfx,
173 FIB_SOURCE_SPECIAL);
174
175 fib_table_t *fib_table = fib_table_get(fib_index, FIB_PROTOCOL_IP6);
176 fib_source_t source;
177
178 /*
179 * validate no more routes.
180 */
181 ASSERT(0 == fib_table->ft_total_route_counts);
182 FOR_EACH_FIB_SOURCE(source)
183 {
184 ASSERT(0 == fib_table->ft_src_route_counts[source]);
185 }
186
187 if (~0 != fib_table->ft_table_id)
188 {
189 hash_unset (ip6_main.fib_index_by_table_id, fib_table->ft_table_id);
190 }
191 pool_put(ip6_main.fibs, fib_table);
192}
193
194fib_node_index_t
195ip6_fib_table_lookup (u32 fib_index,
196 const ip6_address_t *addr,
197 u32 len)
198{
199 const ip6_fib_table_instance_t *table;
200 BVT(clib_bihash_kv) kv, value;
201 int i, n_p, rv;
202 u64 fib;
203
204 table = &ip6_main.ip6_table[IP6_FIB_TABLE_NON_FWDING];
205 n_p = vec_len (table->prefix_lengths_in_search_order);
206
207 kv.key[0] = addr->as_u64[0];
208 kv.key[1] = addr->as_u64[1];
209 fib = ((u64)((fib_index))<<32);
210
211 /*
212 * start search from a mask length same length or shorter.
213 * we don't want matches longer than the mask passed
214 */
215 i = 0;
216 while (i < n_p && table->prefix_lengths_in_search_order[i] > len)
217 {
218 i++;
219 }
220
221 for (; i < n_p; i++)
222 {
223 int dst_address_length = table->prefix_lengths_in_search_order[i];
224 ip6_address_t * mask = &ip6_main.fib_masks[dst_address_length];
225
226 ASSERT(dst_address_length >= 0 && dst_address_length <= 128);
227 //As lengths are decreasing, masks are increasingly specific.
228 kv.key[0] &= mask->as_u64[0];
229 kv.key[1] &= mask->as_u64[1];
230 kv.key[2] = fib | dst_address_length;
231
232 rv = BV(clib_bihash_search_inline_2)(&table->ip6_hash, &kv, &value);
233 if (rv == 0)
234 return value.value;
235 }
236
237 return (FIB_NODE_INDEX_INVALID);
238}
239
240fib_node_index_t
241ip6_fib_table_lookup_exact_match (u32 fib_index,
242 const ip6_address_t *addr,
243 u32 len)
244{
245 const ip6_fib_table_instance_t *table;
246 BVT(clib_bihash_kv) kv, value;
247 ip6_address_t *mask;
248 u64 fib;
249 int rv;
250
251 table = &ip6_main.ip6_table[IP6_FIB_TABLE_NON_FWDING];
252 mask = &ip6_main.fib_masks[len];
253 fib = ((u64)((fib_index))<<32);
254
255 kv.key[0] = addr->as_u64[0] & mask->as_u64[0];
256 kv.key[1] = addr->as_u64[1] & mask->as_u64[1];
257 kv.key[2] = fib | len;
258
259 rv = BV(clib_bihash_search_inline_2)(&table->ip6_hash, &kv, &value);
260 if (rv == 0)
261 return value.value;
262
263 return (FIB_NODE_INDEX_INVALID);
264}
265
266static void
267compute_prefix_lengths_in_search_order (ip6_fib_table_instance_t *table)
268{
269 int i;
270 vec_reset_length (table->prefix_lengths_in_search_order);
271 /* Note: bitmap reversed so this is in fact a longest prefix match */
272 clib_bitmap_foreach (i, table->non_empty_dst_address_length_bitmap,
273 ({
274 int dst_address_length = 128 - i;
275 vec_add1(table->prefix_lengths_in_search_order, dst_address_length);
276 }));
277}
278
279void
280ip6_fib_table_entry_remove (u32 fib_index,
281 const ip6_address_t *addr,
282 u32 len)
283{
284 ip6_fib_table_instance_t *table;
285 BVT(clib_bihash_kv) kv;
286 ip6_address_t *mask;
287 u64 fib;
288
289 table = &ip6_main.ip6_table[IP6_FIB_TABLE_NON_FWDING];
290 mask = &ip6_main.fib_masks[len];
291 fib = ((u64)((fib_index))<<32);
292
293 kv.key[0] = addr->as_u64[0] & mask->as_u64[0];
294 kv.key[1] = addr->as_u64[1] & mask->as_u64[1];
295 kv.key[2] = fib | len;
296
297 BV(clib_bihash_add_del)(&table->ip6_hash, &kv, 0);
298
299 /* refcount accounting */
300 ASSERT (table->dst_address_length_refcounts[len] > 0);
301 if (--table->dst_address_length_refcounts[len] == 0)
302 {
303 table->non_empty_dst_address_length_bitmap =
304 clib_bitmap_set (table->non_empty_dst_address_length_bitmap,
305 128 - len, 0);
306 compute_prefix_lengths_in_search_order (table);
307 }
308}
309
310void
311ip6_fib_table_entry_insert (u32 fib_index,
312 const ip6_address_t *addr,
313 u32 len,
314 fib_node_index_t fib_entry_index)
315{
316 ip6_fib_table_instance_t *table;
317 BVT(clib_bihash_kv) kv;
318 ip6_address_t *mask;
319 u64 fib;
320
321 table = &ip6_main.ip6_table[IP6_FIB_TABLE_NON_FWDING];
322 mask = &ip6_main.fib_masks[len];
323 fib = ((u64)((fib_index))<<32);
324
325 kv.key[0] = addr->as_u64[0] & mask->as_u64[0];
326 kv.key[1] = addr->as_u64[1] & mask->as_u64[1];
327 kv.key[2] = fib | len;
328 kv.value = fib_entry_index;
329
330 BV(clib_bihash_add_del)(&table->ip6_hash, &kv, 1);
331
332 table->dst_address_length_refcounts[len]++;
333
334 table->non_empty_dst_address_length_bitmap =
335 clib_bitmap_set (table->non_empty_dst_address_length_bitmap,
336 128 - len, 1);
337 compute_prefix_lengths_in_search_order (table);
338}
339
340u32
341ip6_fib_table_fwding_lookup (ip6_main_t * im,
342 u32 fib_index,
343 const ip6_address_t * dst)
344{
345 const ip6_fib_table_instance_t *table;
346 int i, len;
347 int rv;
348 BVT(clib_bihash_kv) kv, value;
349 u64 fib;
350
351 table = &ip6_main.ip6_table[IP6_FIB_TABLE_FWDING];
352 len = vec_len (table->prefix_lengths_in_search_order);
353
354 kv.key[0] = dst->as_u64[0];
355 kv.key[1] = dst->as_u64[1];
356 fib = ((u64)((fib_index))<<32);
357
358 for (i = 0; i < len; i++)
359 {
360 int dst_address_length = table->prefix_lengths_in_search_order[i];
361 ip6_address_t * mask = &ip6_main.fib_masks[dst_address_length];
362
363 ASSERT(dst_address_length >= 0 && dst_address_length <= 128);
364 //As lengths are decreasing, masks are increasingly specific.
365 kv.key[0] &= mask->as_u64[0];
366 kv.key[1] &= mask->as_u64[1];
367 kv.key[2] = fib | dst_address_length;
368
369 rv = BV(clib_bihash_search_inline_2)(&table->ip6_hash, &kv, &value);
370 if (rv == 0)
371 return value.value;
372 }
373
374 /* default route is always present */
375 ASSERT(0);
376 return 0;
377}
378
379u32 ip6_fib_table_fwding_lookup_with_if_index (ip6_main_t * im,
380 u32 sw_if_index,
381 const ip6_address_t * dst)
382{
383 u32 fib_index = vec_elt (im->fib_index_by_sw_if_index, sw_if_index);
384 return ip6_fib_table_fwding_lookup(im, fib_index, dst);
385}
386
387flow_hash_config_t
388ip6_fib_table_get_flow_hash_config (u32 fib_index)
389{
390 return (ip6_fib_get(fib_index)->flow_hash_config);
391}
392
393u32
394ip6_fib_table_get_index_for_sw_if_index (u32 sw_if_index)
395{
396 if (sw_if_index >= vec_len(ip6_main.fib_index_by_sw_if_index))
397 {
398 /*
399 * This is the case for interfaces that are not yet mapped to
400 * a IP table
401 */
402 return (~0);
403 }
404 return (ip6_main.fib_index_by_sw_if_index[sw_if_index]);
405}
406
407void
408ip6_fib_table_fwding_dpo_update (u32 fib_index,
409 const ip6_address_t *addr,
410 u32 len,
411 const dpo_id_t *dpo)
412{
413 ip6_fib_table_instance_t *table;
414 BVT(clib_bihash_kv) kv;
415 ip6_address_t *mask;
416 u64 fib;
417
418 table = &ip6_main.ip6_table[IP6_FIB_TABLE_FWDING];
419 mask = &ip6_main.fib_masks[len];
420 fib = ((u64)((fib_index))<<32);
421
422 kv.key[0] = addr->as_u64[0] & mask->as_u64[0];
423 kv.key[1] = addr->as_u64[1] & mask->as_u64[1];
424 kv.key[2] = fib | len;
425 kv.value = dpo->dpoi_index;
426
427 BV(clib_bihash_add_del)(&table->ip6_hash, &kv, 1);
428
429 table->dst_address_length_refcounts[len]++;
430
431 table->non_empty_dst_address_length_bitmap =
432 clib_bitmap_set (table->non_empty_dst_address_length_bitmap,
433 128 - len, 1);
434 compute_prefix_lengths_in_search_order (table);
435}
436
437void
438ip6_fib_table_fwding_dpo_remove (u32 fib_index,
439 const ip6_address_t *addr,
440 u32 len,
441 const dpo_id_t *dpo)
442{
443 ip6_fib_table_instance_t *table;
444 BVT(clib_bihash_kv) kv;
445 ip6_address_t *mask;
446 u64 fib;
447
448 table = &ip6_main.ip6_table[IP6_FIB_TABLE_FWDING];
449 mask = &ip6_main.fib_masks[len];
450 fib = ((u64)((fib_index))<<32);
451
452 kv.key[0] = addr->as_u64[0] & mask->as_u64[0];
453 kv.key[1] = addr->as_u64[1] & mask->as_u64[1];
454 kv.key[2] = fib | len;
455 kv.value = dpo->dpoi_index;
456
457 BV(clib_bihash_add_del)(&table->ip6_hash, &kv, 0);
458
459 /* refcount accounting */
460 ASSERT (table->dst_address_length_refcounts[len] > 0);
461 if (--table->dst_address_length_refcounts[len] == 0)
462 {
463 table->non_empty_dst_address_length_bitmap =
Neale Ranns32e1c012016-11-22 17:07:28 +0000464 clib_bitmap_set (table->non_empty_dst_address_length_bitmap,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100465 128 - len, 0);
466 compute_prefix_lengths_in_search_order (table);
467 }
468}
469
Neale Ranns32e1c012016-11-22 17:07:28 +0000470/**
471 * @brief Context when walking the IPv6 table. Since all VRFs are in the
472 * same hash table, we need to filter only those we need as we walk
473 */
474typedef struct ip6_fib_walk_ctx_t_
475{
476 u32 i6w_fib_index;
477 fib_table_walk_fn_t i6w_fn;
478 void *i6w_ctx;
479} ip6_fib_walk_ctx_t;
480
481static int
482ip6_fib_walk_cb (clib_bihash_kv_24_8_t * kvp,
483 void *arg)
484{
485 ip6_fib_walk_ctx_t *ctx = arg;
486
487 if ((kvp->key[2] >> 32) == ctx->i6w_fib_index)
488 {
489 ctx->i6w_fn(kvp->value, ctx->i6w_ctx);
490 }
491
492 return (1);
493}
494
495void
496ip6_fib_table_walk (u32 fib_index,
497 fib_table_walk_fn_t fn,
498 void *arg)
499{
500 ip6_fib_walk_ctx_t ctx = {
501 .i6w_fib_index = fib_index,
502 .i6w_fn = fn,
503 .i6w_ctx = arg,
504 };
505 ip6_main_t *im = &ip6_main;
506
507 BV(clib_bihash_foreach_key_value_pair)(&im->ip6_table[IP6_FIB_TABLE_NON_FWDING].ip6_hash,
508 ip6_fib_walk_cb,
509 &ctx);
510
511}
512
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100513typedef struct ip6_fib_show_ctx_t_ {
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100514 fib_node_index_t *entries;
515} ip6_fib_show_ctx_t;
516
Neale Ranns32e1c012016-11-22 17:07:28 +0000517static int
518ip6_fib_table_show_walk (fib_node_index_t fib_entry_index,
519 void *arg)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100520{
521 ip6_fib_show_ctx_t *ctx = arg;
522
Neale Ranns32e1c012016-11-22 17:07:28 +0000523 vec_add1(ctx->entries, fib_entry_index);
524
525 return (1);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100526}
527
528static void
529ip6_fib_table_show_all (ip6_fib_t *fib,
530 vlib_main_t * vm)
531{
532 fib_node_index_t *fib_entry_index;
533 ip6_fib_show_ctx_t ctx = {
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100534 .entries = NULL,
535 };
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100536
Neale Ranns32e1c012016-11-22 17:07:28 +0000537 ip6_fib_table_walk(fib->index, ip6_fib_table_show_walk, &ctx);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100538 vec_sort_with_function(ctx.entries, fib_entry_cmp_for_sort);
539
540 vec_foreach(fib_entry_index, ctx.entries)
541 {
542 vlib_cli_output(vm, "%U",
543 format_fib_entry,
544 *fib_entry_index,
545 FIB_ENTRY_FORMAT_BRIEF);
546 }
547
548 vec_free(ctx.entries);
549}
550
551static void
552ip6_fib_table_show_one (ip6_fib_t *fib,
553 vlib_main_t * vm,
554 ip6_address_t *address,
555 u32 mask_len)
556{
557 vlib_cli_output(vm, "%U",
558 format_fib_entry,
559 ip6_fib_table_lookup(fib->index, address, mask_len),
560 FIB_ENTRY_FORMAT_DETAIL);
561}
562
563typedef struct {
564 u32 fib_index;
565 u64 count_by_prefix_length[129];
566} count_routes_in_fib_at_prefix_length_arg_t;
567
568static void count_routes_in_fib_at_prefix_length
569(BVT(clib_bihash_kv) * kvp, void *arg)
570{
571 count_routes_in_fib_at_prefix_length_arg_t * ap = arg;
572 int mask_width;
573
574 if ((kvp->key[2]>>32) != ap->fib_index)
575 return;
576
577 mask_width = kvp->key[2] & 0xFF;
578
579 ap->count_by_prefix_length[mask_width]++;
580}
581
582static clib_error_t *
583ip6_show_fib (vlib_main_t * vm,
584 unformat_input_t * input,
585 vlib_cli_command_t * cmd)
586{
587 count_routes_in_fib_at_prefix_length_arg_t _ca, *ca = &_ca;
588 ip6_main_t * im6 = &ip6_main;
589 fib_table_t *fib_table;
590 ip6_fib_t * fib;
591 int verbose, matching;
592 ip6_address_t matching_address;
593 u32 mask_len = 128;
594 int table_id = -1, fib_index = ~0;
595
596 verbose = 1;
597 matching = 0;
598
599 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
600 {
601 if (unformat (input, "brief") ||
602 unformat (input, "summary") ||
603 unformat (input, "sum"))
604 verbose = 0;
605
606 else if (unformat (input, "%U/%d",
607 unformat_ip6_address, &matching_address, &mask_len))
608 matching = 1;
609
610 else if (unformat (input, "%U", unformat_ip6_address, &matching_address))
611 matching = 1;
612
613 else if (unformat (input, "table %d", &table_id))
614 ;
615 else if (unformat (input, "index %d", &fib_index))
616 ;
617 else
618 break;
619 }
620
621 pool_foreach (fib_table, im6->fibs,
622 ({
623 fib = &(fib_table->v6);
624 if (table_id >= 0 && table_id != (int)fib->table_id)
625 continue;
626 if (fib_index != ~0 && fib_index != (int)fib->index)
627 continue;
628
629 vlib_cli_output (vm, "%s, fib_index %d, flow hash: %U",
630 fib_table->ft_desc, fib->index,
631 format_ip_flow_hash_config, fib->flow_hash_config);
632
633 /* Show summary? */
634 if (! verbose)
635 {
636 BVT(clib_bihash) * h = &im6->ip6_table[IP6_FIB_TABLE_NON_FWDING].ip6_hash;
637 int len;
638
639 vlib_cli_output (vm, "%=20s%=16s", "Prefix length", "Count");
640
641 memset (ca, 0, sizeof(*ca));
642 ca->fib_index = fib->index;
643
644 BV(clib_bihash_foreach_key_value_pair)
645 (h, count_routes_in_fib_at_prefix_length, ca);
646
647 for (len = 128; len >= 0; len--)
648 {
649 if (ca->count_by_prefix_length[len])
650 vlib_cli_output (vm, "%=20d%=16lld",
651 len, ca->count_by_prefix_length[len]);
652 }
653 continue;
654 }
655
656 if (!matching)
657 {
658 ip6_fib_table_show_all(fib, vm);
659 }
660 else
661 {
662 ip6_fib_table_show_one(fib, vm, &matching_address, mask_len);
663 }
664 }));
665
666 return 0;
667}
668
669/*?
Billy McFall0683c9c2016-10-13 08:27:31 -0400670 * This command displays the IPv6 FIB Tables (VRF Tables) and the route
671 * entries for each table.
672 *
673 * @note This command will run for a long time when the FIB tables are
674 * comprised of millions of entries. For those senarios, consider displaying
675 * in summary mode.
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100676 *
677 * @cliexpar
Billy McFall0683c9c2016-10-13 08:27:31 -0400678 * @parblock
679 * Example of how to display all the IPv6 FIB tables:
680 * @cliexstart{show ip6 fib}
Billy McFallebb9a6a2016-10-17 11:35:32 -0400681 * ipv6-VRF:0, fib_index 0, flow hash: src dst sport dport proto
682 * @::/0
683 * unicast-ip6-chain
684 * [@0]: dpo-load-balance: [index:5 buckets:1 uRPF:5 to:[0:0]]
685 * [0] [@0]: dpo-drop ip6
686 * fe80::/10
687 * unicast-ip6-chain
688 * [@0]: dpo-load-balance: [index:10 buckets:1 uRPF:10 to:[0:0]]
689 * [0] [@2]: dpo-receive
690 * ff02::1/128
691 * unicast-ip6-chain
692 * [@0]: dpo-load-balance: [index:8 buckets:1 uRPF:8 to:[0:0]]
693 * [0] [@2]: dpo-receive
694 * ff02::2/128
695 * unicast-ip6-chain
696 * [@0]: dpo-load-balance: [index:7 buckets:1 uRPF:7 to:[0:0]]
697 * [0] [@2]: dpo-receive
698 * ff02::16/128
699 * unicast-ip6-chain
700 * [@0]: dpo-load-balance: [index:9 buckets:1 uRPF:9 to:[0:0]]
701 * [0] [@2]: dpo-receive
702 * ff02::1:ff00:0/104
703 * unicast-ip6-chain
704 * [@0]: dpo-load-balance: [index:6 buckets:1 uRPF:6 to:[0:0]]
705 * [0] [@2]: dpo-receive
706 * ipv6-VRF:8, fib_index 1, flow hash: src dst sport dport proto
707 * @::/0
708 * unicast-ip6-chain
709 * [@0]: dpo-load-balance: [index:21 buckets:1 uRPF:20 to:[0:0]]
710 * [0] [@0]: dpo-drop ip6
711 * @::a:1:1:0:4/126
712 * unicast-ip6-chain
713 * [@0]: dpo-load-balance: [index:27 buckets:1 uRPF:26 to:[0:0]]
714 * [0] [@4]: ipv6-glean: af_packet0
715 * @::a:1:1:0:7/128
716 * unicast-ip6-chain
717 * [@0]: dpo-load-balance: [index:28 buckets:1 uRPF:27 to:[0:0]]
718 * [0] [@2]: dpo-receive: @::a:1:1:0:7 on af_packet0
719 * fe80::/10
720 * unicast-ip6-chain
721 * [@0]: dpo-load-balance: [index:26 buckets:1 uRPF:25 to:[0:0]]
722 * [0] [@2]: dpo-receive
723 * fe80::fe:3eff:fe3e:9222/128
724 * unicast-ip6-chain
725 * [@0]: dpo-load-balance: [index:29 buckets:1 uRPF:28 to:[0:0]]
726 * [0] [@2]: dpo-receive: fe80::fe:3eff:fe3e:9222 on af_packet0
727 * ff02::1/128
728 * unicast-ip6-chain
729 * [@0]: dpo-load-balance: [index:24 buckets:1 uRPF:23 to:[0:0]]
730 * [0] [@2]: dpo-receive
731 * ff02::2/128
732 * unicast-ip6-chain
733 * [@0]: dpo-load-balance: [index:23 buckets:1 uRPF:22 to:[0:0]]
734 * [0] [@2]: dpo-receive
735 * ff02::16/128
736 * unicast-ip6-chain
737 * [@0]: dpo-load-balance: [index:25 buckets:1 uRPF:24 to:[0:0]]
738 * [0] [@2]: dpo-receive
739 * ff02::1:ff00:0/104
740 * unicast-ip6-chain
741 * [@0]: dpo-load-balance: [index:22 buckets:1 uRPF:21 to:[0:0]]
742 * [0] [@2]: dpo-receive
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100743 * @cliexend
Billy McFallebb9a6a2016-10-17 11:35:32 -0400744 *
Billy McFall0683c9c2016-10-13 08:27:31 -0400745 * Example of how to display a summary of all IPv6 FIB tables:
746 * @cliexstart{show ip6 fib summary}
Billy McFallebb9a6a2016-10-17 11:35:32 -0400747 * ipv6-VRF:0, fib_index 0, flow hash: src dst sport dport proto
Billy McFall0683c9c2016-10-13 08:27:31 -0400748 * Prefix length Count
749 * 128 3
750 * 104 1
Billy McFallebb9a6a2016-10-17 11:35:32 -0400751 * 10 1
752 * 0 1
753 * ipv6-VRF:8, fib_index 1, flow hash: src dst sport dport proto
Billy McFall0683c9c2016-10-13 08:27:31 -0400754 * Prefix length Count
755 * 128 5
756 * 126 1
757 * 104 1
Billy McFallebb9a6a2016-10-17 11:35:32 -0400758 * 10 1
759 * 0 1
Billy McFall0683c9c2016-10-13 08:27:31 -0400760 * @cliexend
761 * @endparblock
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100762 ?*/
Billy McFall0683c9c2016-10-13 08:27:31 -0400763/* *INDENT-OFF* */
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100764VLIB_CLI_COMMAND (ip6_show_fib_command, static) = {
765 .path = "show ip6 fib",
Billy McFall0683c9c2016-10-13 08:27:31 -0400766 .short_help = "show ip6 fib [summary] [table <table-id>] [index <fib-id>] [<ip6-addr>[/<width>]]",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100767 .function = ip6_show_fib,
768};
Billy McFall0683c9c2016-10-13 08:27:31 -0400769/* *INDENT-ON* */