fib: Always install all routers mcast addresses
[vpp.git] / src / vnet / mfib / ip4_mfib.c
1 /*
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/mfib/ip4_mfib.h>
17
18 #include <vnet/mfib/mfib_table.h>
19 #include <vnet/mfib/mfib_entry.h>
20
21 static const mfib_prefix_t all_zeros =
22 {
23     .fp_proto = FIB_PROTOCOL_IP4,
24 };
25 static const mfib_prefix_t ip4_specials[] =
26 {
27     /* ALL prefixes are in network order */
28     {
29         /* (*,224.0.0.1)/32 - all hosts */
30         .fp_grp_addr = {
31             .ip4.data_u32 = 0x010000e0,
32         },
33         .fp_len = 32,
34         .fp_proto = FIB_PROTOCOL_IP4,
35     },
36     {
37         /* (*,224.0.0.2)/32 - all routers */
38         .fp_grp_addr = {
39             .ip4.data_u32 = 0x020000e0,
40         },
41         .fp_len = 32,
42         .fp_proto = FIB_PROTOCOL_IP4,
43     },
44 };
45
46 static u32
47 ip4_create_mfib_with_table_id (u32 table_id,
48                                mfib_source_t src)
49 {
50     mfib_table_t *mfib_table;
51
52     pool_get_aligned(ip4_main.mfibs, mfib_table, CLIB_CACHE_LINE_BYTES);
53     clib_memset(mfib_table, 0, sizeof(*mfib_table));
54
55     mfib_table->mft_proto = FIB_PROTOCOL_IP4;
56     mfib_table->mft_index =
57         mfib_table->v4.index =
58             (mfib_table - ip4_main.mfibs);
59
60     hash_set (ip4_main.mfib_index_by_table_id,
61               table_id,
62               mfib_table->mft_index);
63
64     mfib_table->mft_table_id =
65         mfib_table->v4.table_id =
66             table_id;
67
68     mfib_table_lock(mfib_table->mft_index, FIB_PROTOCOL_IP4, src);
69
70     /*
71      * add the default route into the new FIB
72      */
73     mfib_table_entry_update(mfib_table->mft_index,
74                             &all_zeros,
75                             MFIB_SOURCE_DEFAULT_ROUTE,
76                             MFIB_RPF_ID_NONE,
77                             MFIB_ENTRY_FLAG_DROP);
78
79     const fib_route_path_t path = {
80         .frp_proto = DPO_PROTO_IP4,
81         .frp_addr = zero_addr,
82         .frp_sw_if_index = ~0,
83         .frp_fib_index = ~0,
84         .frp_weight = 1,
85         .frp_flags = FIB_ROUTE_PATH_LOCAL,
86         .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
87     };
88     int ii;
89
90     for (ii = 0; ii < ARRAY_LEN(ip4_specials); ii++)
91     {
92         mfib_table_entry_path_update(mfib_table->mft_index,
93                                      &ip4_specials[ii],
94                                      MFIB_SOURCE_SPECIAL,
95                                      &path);
96     }
97
98     return (mfib_table->mft_index);
99 }
100
101 void
102 ip4_mfib_table_destroy (ip4_mfib_t *mfib)
103 {
104     mfib_table_t *mfib_table = (mfib_table_t*)mfib;
105     int ii;
106
107     /*
108      * remove all the specials we added when the table was created.
109      */
110     mfib_table_entry_delete(mfib_table->mft_index,
111                             &all_zeros,
112                             MFIB_SOURCE_DEFAULT_ROUTE);
113
114     for (ii = 0; ii < ARRAY_LEN(ip4_specials); ii++)
115     {
116         mfib_table_entry_delete(mfib_table->mft_index,
117                                 &ip4_specials[ii],
118                                 MFIB_SOURCE_SPECIAL);
119     }
120
121     /*
122      * validate no more routes.
123      */
124     ASSERT(0 == mfib_table->mft_total_route_counts);
125     ASSERT(~0 != mfib_table->mft_table_id);
126
127     hash_unset (ip4_main.mfib_index_by_table_id, mfib_table->mft_table_id);
128     pool_put(ip4_main.mfibs, mfib_table);
129 }
130
131 void
132 ip4_mfib_interface_enable_disable (u32 sw_if_index, int is_enable)
133 {
134     const fib_route_path_t path = {
135         .frp_proto = DPO_PROTO_IP4,
136         .frp_addr = zero_addr,
137         .frp_sw_if_index = sw_if_index,
138         .frp_fib_index = ~0,
139         .frp_weight = 1,
140         .frp_mitf_flags = MFIB_ITF_FLAG_ACCEPT,
141     };
142     u32 mfib_index;
143     int ii;
144
145     vec_validate (ip4_main.mfib_index_by_sw_if_index, sw_if_index);
146     mfib_index = ip4_mfib_table_get_index_for_sw_if_index(sw_if_index);
147
148     for (ii = 0; ii < ARRAY_LEN(ip4_specials); ii++)
149     {
150         if (is_enable)
151         {
152             mfib_table_entry_path_update(mfib_index,
153                                          &ip4_specials[ii],
154                                          MFIB_SOURCE_SPECIAL,
155                                          &path);
156         }
157         else
158         {
159             mfib_table_entry_path_remove(mfib_index,
160                                          &ip4_specials[ii],
161                                          MFIB_SOURCE_SPECIAL,
162                                          &path);
163         }
164     }
165 }
166
167 u32
168 ip4_mfib_table_find_or_create_and_lock (u32 table_id,
169                                         mfib_source_t src)
170 {
171     u32 index;
172
173     index = ip4_mfib_index_from_table_id(table_id);
174     if (~0 == index)
175         return ip4_create_mfib_with_table_id(table_id, src);
176     mfib_table_lock(index, FIB_PROTOCOL_IP4, src);
177
178     return (index);
179 }
180
181 u32
182 ip4_mfib_table_get_index_for_sw_if_index (u32 sw_if_index)
183 {
184     if (sw_if_index >= vec_len(ip4_main.mfib_index_by_sw_if_index))
185     {
186         /*
187          * This is the case for interfaces that are not yet mapped to
188          * a IP table
189          */
190         return (~0);
191     }
192     return (ip4_main.mfib_index_by_sw_if_index[sw_if_index]);
193 }
194
195 #define IPV4_MFIB_GRP_LEN(_len)\
196     (_len > 32 ? 32 : _len)
197
198 #define IP4_MFIB_MK_KEY(_grp, _src, _len, _key)                         \
199 {                                                                       \
200     _key  = ((u64)(_grp->data_u32 &                                     \
201                    ip4_main.fib_masks[IPV4_MFIB_GRP_LEN(_len)])) << 32; \
202     _key |= _src->data_u32;                                             \
203 }
204 #define IP4_MFIB_MK_GRP_KEY(_grp, _len, _key)                           \
205 {                                                                       \
206     _key  = ((u64)(_grp->data_u32 &                                     \
207                    ip4_main.fib_masks[IPV4_MFIB_GRP_LEN(_len)])) << 32; \
208 }
209
210 /*
211  * ip4_fib_table_lookup_exact_match
212  *
213  * Exact match prefix lookup
214  */
215 fib_node_index_t
216 ip4_mfib_table_lookup_exact_match (const ip4_mfib_t *mfib,
217                                    const ip4_address_t *grp,
218                                    const ip4_address_t *src,
219                                    u32 len)
220 {
221     uword * hash, * result;
222     u64 key;
223
224     hash = mfib->fib_entry_by_dst_address[len];
225     IP4_MFIB_MK_KEY(grp, src, len, key);
226
227     result = hash_get(hash, key);
228
229     if (NULL != result) {
230         return (result[0]);
231     }
232     return (FIB_NODE_INDEX_INVALID);
233 }
234
235 /*
236  * ip4_fib_table_lookup
237  *
238  * Longest prefix match
239  */
240 fib_node_index_t
241 ip4_mfib_table_lookup (const ip4_mfib_t *mfib,
242                        const ip4_address_t *src,
243                        const ip4_address_t *grp,
244                        u32 len)
245 {
246     uword * hash, * result;
247     i32 mask_len;
248     u64 key;
249
250     mask_len = len;
251
252     if (PREDICT_TRUE(64 == mask_len))
253     {
254         hash = mfib->fib_entry_by_dst_address[mask_len];
255         IP4_MFIB_MK_KEY(grp, src, mask_len, key);
256
257         result = hash_get (hash, key);
258
259         if (NULL != result) {
260             return (result[0]);
261         }
262     }
263
264     for (mask_len = (len == 64 ? 32 : len); mask_len >= 0; mask_len--)
265     {
266         hash = mfib->fib_entry_by_dst_address[mask_len];
267         IP4_MFIB_MK_GRP_KEY(grp, mask_len, key);
268
269         result = hash_get (hash, key);
270
271         if (NULL != result) {
272             return (result[0]);
273         }
274     }
275     return (FIB_NODE_INDEX_INVALID);
276 }
277
278 fib_node_index_t
279 ip4_mfib_table_get_less_specific (const ip4_mfib_t *mfib,
280                                   const ip4_address_t *src,
281                                   const ip4_address_t *grp,
282                                   u32 len)
283 {
284     u32 mask_len;
285
286     /*
287      * in the absence of a tree structure for the table that allows for an O(1)
288      * parent get, a cheeky way to find the cover is to LPM for the prefix with
289      * mask-1.
290      * there should always be a cover, though it may be the default route. the
291      * default route's cover is the default route.
292      */
293     if (len == 64)
294     {
295         /* go from (S,G) to (*,G*) */
296         mask_len = 32;
297     }
298     else if (len != 0)
299     {
300         mask_len = len - 1;
301     }
302     else
303     {
304         mask_len = len;
305     }
306
307     return (ip4_mfib_table_lookup(mfib, src, grp, mask_len));
308 }
309
310 void
311 ip4_mfib_table_entry_insert (ip4_mfib_t *mfib,
312                              const ip4_address_t *grp,
313                              const ip4_address_t *src,
314                              u32 len,
315                              fib_node_index_t fib_entry_index)
316 {
317     uword * hash, * result;
318     u64 key;
319
320     IP4_MFIB_MK_KEY(grp, src, len, key);
321     hash = mfib->fib_entry_by_dst_address[len];
322     result = hash_get (hash, key);
323
324     if (NULL == result) {
325         /*
326          * adding a new entry
327          */
328         if (NULL == hash) {
329             hash = hash_create (32 /* elts */, sizeof (uword));
330             hash_set_flags (hash, HASH_FLAG_NO_AUTO_SHRINK);
331         }
332         hash = hash_set(hash, key, fib_entry_index);
333         mfib->fib_entry_by_dst_address[len] = hash;
334     }
335     else
336     {
337         ASSERT(0);
338     }
339 }
340
341 void
342 ip4_mfib_table_entry_remove (ip4_mfib_t *mfib,
343                              const ip4_address_t *grp,
344                              const ip4_address_t *src,
345                              u32 len)
346 {
347     uword * hash, * result;
348     u64 key;
349
350     IP4_MFIB_MK_KEY(grp, src, len, key);
351     hash = mfib->fib_entry_by_dst_address[len];
352     result = hash_get (hash, key);
353
354     if (NULL == result)
355     {
356         /*
357          * removing a non-existent entry. i'll allow it.
358          */
359     }
360     else
361     {
362         hash_unset(hash, key);
363     }
364
365     mfib->fib_entry_by_dst_address[len] = hash;
366 }
367
368 void
369 ip4_mfib_table_walk (ip4_mfib_t *mfib,
370                      mfib_table_walk_fn_t fn,
371                      void *ctx)
372 {
373     int i;
374
375     for (i = 0; i < ARRAY_LEN (mfib->fib_entry_by_dst_address); i++)
376     {
377         uword * hash = mfib->fib_entry_by_dst_address[i];
378
379         if (NULL != hash)
380         {
381             hash_pair_t * p;
382
383             hash_foreach_pair (p, hash,
384             ({
385                 fn(p->value[0], ctx);
386             }));
387         }
388     }
389 }
390
391 u8 *
392 format_ip4_mfib_table_memory (u8 * s, va_list * args)
393 {
394     mfib_table_t *mfib_table;
395     u64 total_memory;
396
397     total_memory = 0;
398
399     pool_foreach (mfib_table, ip4_main.mfibs,
400     ({
401         ip4_mfib_t *mfib = &mfib_table->v4;
402         uword mfib_size;
403         int i;
404
405         mfib_size = 0;
406
407         for (i = 0; i < ARRAY_LEN (mfib->fib_entry_by_dst_address); i++)
408         {
409             uword * hash = mfib->fib_entry_by_dst_address[i];
410
411             if (NULL != hash)
412             {
413                 mfib_size += hash_bytes(hash);
414             }
415         }
416
417         total_memory += mfib_size;
418     }));
419
420     s = format(s, "%=30s %=6d %=12ld\n",
421                "IPv4 multicast",
422                pool_elts(ip4_main.mfibs), total_memory);
423
424     return (s);
425 }
426
427 static void
428 ip4_mfib_table_show_all (ip4_mfib_t *mfib,
429                          vlib_main_t * vm)
430 {
431     fib_node_index_t *mfib_entry_indicies;
432     fib_node_index_t *mfib_entry_index;
433     int i;
434
435     mfib_entry_indicies = NULL;
436
437     for (i = 0; i < ARRAY_LEN (mfib->fib_entry_by_dst_address); i++)
438     {
439         uword * hash = mfib->fib_entry_by_dst_address[i];
440
441         if (NULL != hash)
442         {
443             hash_pair_t * p;
444
445             hash_foreach_pair (p, hash,
446             ({
447                 vec_add1(mfib_entry_indicies, p->value[0]);
448             }));
449         }
450     }
451
452     vec_sort_with_function(mfib_entry_indicies, mfib_entry_cmp_for_sort);
453
454     vec_foreach(mfib_entry_index, mfib_entry_indicies)
455     {
456         vlib_cli_output(vm, "%U",
457                         format_mfib_entry,
458                         *mfib_entry_index,
459                         MFIB_ENTRY_FORMAT_BRIEF);
460     }
461
462     vec_free(mfib_entry_indicies);
463 }
464
465 static void
466 ip4_mfib_table_show_one (ip4_mfib_t *mfib,
467                          vlib_main_t * vm,
468                          ip4_address_t *src,
469                          ip4_address_t *grp,
470                          u32 mask_len)
471 {
472     vlib_cli_output(vm, "%U",
473                     format_mfib_entry,
474                     ip4_mfib_table_lookup(mfib, src, grp, mask_len),
475                     MFIB_ENTRY_FORMAT_DETAIL);
476 }
477
478 static clib_error_t *
479 ip4_show_mfib (vlib_main_t * vm,
480                unformat_input_t * input,
481                vlib_cli_command_t * cmd)
482 {
483     ip4_main_t * im4 = &ip4_main;
484     mfib_table_t *mfib_table;
485     int verbose, matching, memory;
486     ip4_address_t grp, src = {{0}};
487     u32 mask = 32;
488     u64 total_hash_memory;
489     int i, table_id = -1, fib_index = ~0;
490
491     verbose = 1;
492     memory = matching = 0;
493     total_hash_memory = 0;
494
495     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
496     {
497         if (unformat (input, "brief") || unformat (input, "summary")
498             || unformat (input, "sum"))
499             verbose = 0;
500         else if (unformat (input, "mem") || unformat (input, "memory"))
501             memory = 1;
502         else if (unformat (input, "%U %U",
503                            unformat_ip4_address, &src,
504                            unformat_ip4_address, &grp))
505         {
506             matching = 1;
507             mask = 64;
508         }
509         else if (unformat (input, "%U/%d", unformat_ip4_address, &grp, &mask))
510         {
511             clib_memset(&src, 0, sizeof(src));
512             matching = 1;
513         }
514         else if (unformat (input, "%U", unformat_ip4_address, &grp))
515         {
516             clib_memset(&src, 0, sizeof(src));
517             matching = 1;
518             mask = 32;
519         }
520         else if (unformat (input, "table %d", &table_id))
521             ;
522         else if (unformat (input, "index %d", &fib_index))
523             ;
524         else
525             break;
526     }
527
528     pool_foreach (mfib_table, im4->mfibs,
529     ({
530         ip4_mfib_t *mfib = &mfib_table->v4;
531
532         if (table_id >= 0 && table_id != (int)mfib->table_id)
533             continue;
534         if (fib_index != ~0 && fib_index != (int)mfib->index)
535             continue;
536
537         if (memory)
538         {
539             uword hash_size;
540
541             hash_size = 0;
542
543             for (i = 0; i < ARRAY_LEN (mfib->fib_entry_by_dst_address); i++)
544             {
545                 uword * hash = mfib->fib_entry_by_dst_address[i];
546                 if (NULL != hash)
547                 {
548                     hash_size += hash_bytes(hash);
549                 }
550             }
551             if (verbose)
552                 vlib_cli_output (vm, "%U hash:%d",
553                                  format_mfib_table_name, mfib->index,
554                                  FIB_PROTOCOL_IP4,
555                                  hash_size);
556             total_hash_memory += hash_size;
557             continue;
558         }
559
560         vlib_cli_output (vm, "%U, fib_index:%d flags:%U",
561                          format_mfib_table_name, mfib->index, FIB_PROTOCOL_IP4,
562                          mfib->index,
563                          format_mfib_table_flags, mfib_table->mft_flags);
564
565         /* Show summary? */
566         if (! verbose)
567         {
568             vlib_cli_output (vm, "%=20s%=16s", "Prefix length", "Count");
569             for (i = 0; i < ARRAY_LEN (mfib->fib_entry_by_dst_address); i++)
570             {
571                 uword * hash = mfib->fib_entry_by_dst_address[i];
572                 uword n_elts = hash_elts (hash);
573                 if (n_elts > 0)
574                     vlib_cli_output (vm, "%20d%16d", i, n_elts);
575             }
576             continue;
577         }
578
579         if (!matching)
580         {
581             ip4_mfib_table_show_all(mfib, vm);
582         }
583         else
584         {
585             ip4_mfib_table_show_one(mfib, vm, &src, &grp, mask);
586         }
587     }));
588     if (memory)
589         vlib_cli_output (vm, "totals: hash:%ld", total_hash_memory);
590
591     return 0;
592 }
593
594 /*?
595  * This command displays the IPv4 MulticasrFIB Tables (VRF Tables) and
596  * the route entries for each table.
597  *
598  * @note This command will run for a long time when the FIB tables are
599  * comprised of millions of entries. For those senarios, consider displaying
600  * a single table or summary mode.
601  *
602  * @cliexpar
603  * Example of how to display all the IPv4 Multicast FIB tables:
604  * @cliexstart{show ip fib}
605  * ipv4-VRF:0, fib_index 0
606  * (*, 0.0.0.0/0):  flags:D,
607  *  Interfaces:
608  *  multicast-ip4-chain
609  *   [@1]: dpo-drop ip4
610  * (*, 232.1.1.1/32):
611  * Interfaces:
612  *  test-eth1: Forward,
613  *  test-eth2: Forward,
614  *  test-eth0: Accept,
615  * multicast-ip4-chain
616  * [@2]: dpo-replicate: [index:1 buckets:2 to:[0:0]]
617  *   [0] [@1]: ipv4-mcast: test-eth1: IP4: d0:d1:d2:d3:d4:01 -> 01:00:05:00:00:00
618  *   [1] [@1]: ipv4-mcast: test-eth2: IP4: d0:d1:d2:d3:d4:02 -> 01:00:05:00:00:00
619  *
620  * @cliexend
621  * Example of how to display a summary of all IPv4 FIB tables:
622  * @cliexstart{show ip fib summary}
623  * ipv4-VRF:0, fib_index 0, flow hash: src dst sport dport proto
624  *     Prefix length         Count
625  *                    0               1
626  *                    8               2
627  *                   32               4
628  * ipv4-VRF:7, fib_index 1, flow hash: src dst sport dport proto
629  *     Prefix length         Count
630  *                    0               1
631  *                    8               2
632  *                   24               2
633  *                   32               4
634  * @cliexend
635  ?*/
636 /* *INDENT-OFF* */
637 VLIB_CLI_COMMAND (ip4_show_mfib_command, static) = {
638     .path = "show ip mfib",
639     .short_help = "show ip mfib [summary] [table <table-id>] [index <fib-id>] [<grp-addr>[/<mask>]] [<grp-addr>] [<src-addr> <grp-addr>]",
640     .function = ip4_show_mfib,
641 };
642 /* *INDENT-ON* */