Line data Source code
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 <vlib/vlib.h>
17 : #include <vnet/dpo/drop_dpo.h>
18 :
19 : #include <vnet/mfib/mfib_table.h>
20 : #include <vnet/mfib/ip4_mfib.h>
21 : #include <vnet/mfib/ip6_mfib.h>
22 : #include <vnet/mfib/mfib_entry.h>
23 : #include <vnet/mfib/mfib_entry_src.h>
24 : #include <vnet/mfib/mfib_entry_cover.h>
25 : #include <vnet/mfib/mfib_signal.h>
26 :
27 : const static char * mfib_table_flags_strings[] = MFIB_TABLE_ATTRIBUTES;
28 :
29 : mfib_table_t *
30 76099 : mfib_table_get (fib_node_index_t index,
31 : fib_protocol_t proto)
32 : {
33 76099 : switch (proto)
34 : {
35 34263 : case FIB_PROTOCOL_IP4:
36 34263 : return (pool_elt_at_index(ip4_main.mfibs, index));
37 41836 : case FIB_PROTOCOL_IP6:
38 41836 : return (pool_elt_at_index(ip6_main.mfibs, index));
39 0 : case FIB_PROTOCOL_MPLS:
40 0 : break;
41 : }
42 0 : ASSERT(0);
43 0 : return (NULL);
44 : }
45 :
46 : static inline fib_node_index_t
47 10 : mfib_table_lookup_i (const mfib_table_t *mfib_table,
48 : const mfib_prefix_t *prefix)
49 : {
50 10 : switch (prefix->fp_proto)
51 : {
52 5 : case FIB_PROTOCOL_IP4:
53 5 : return (ip4_mfib_table_lookup(&mfib_table->v4,
54 : &prefix->fp_src_addr.ip4,
55 : &prefix->fp_grp_addr.ip4,
56 5 : prefix->fp_len));
57 5 : case FIB_PROTOCOL_IP6:
58 5 : return (ip6_mfib_table_lookup(&mfib_table->v6,
59 : &prefix->fp_src_addr.ip6,
60 : &prefix->fp_grp_addr.ip6,
61 5 : prefix->fp_len));
62 0 : case FIB_PROTOCOL_MPLS:
63 0 : break;
64 : }
65 0 : return (FIB_NODE_INDEX_INVALID);
66 : }
67 :
68 : fib_node_index_t
69 10 : mfib_table_lookup (u32 fib_index,
70 : const mfib_prefix_t *prefix)
71 : {
72 10 : return (mfib_table_lookup_i(mfib_table_get(fib_index, prefix->fp_proto), prefix));
73 : }
74 :
75 : static inline fib_node_index_t
76 62970 : mfib_table_lookup_exact_match_i (const mfib_table_t *mfib_table,
77 : const mfib_prefix_t *prefix)
78 : {
79 62970 : switch (prefix->fp_proto)
80 : {
81 26054 : case FIB_PROTOCOL_IP4:
82 26054 : return (ip4_mfib_table_lookup_exact_match(&mfib_table->v4,
83 : &prefix->fp_grp_addr.ip4,
84 : &prefix->fp_src_addr.ip4,
85 26054 : prefix->fp_len));
86 36916 : case FIB_PROTOCOL_IP6:
87 36916 : return (ip6_mfib_table_lookup_exact_match(&mfib_table->v6,
88 : &prefix->fp_grp_addr.ip6,
89 : &prefix->fp_src_addr.ip6,
90 36916 : prefix->fp_len));
91 0 : case FIB_PROTOCOL_MPLS:
92 0 : break;
93 : }
94 0 : return (FIB_NODE_INDEX_INVALID);
95 : }
96 :
97 : fib_node_index_t
98 417 : mfib_table_lookup_exact_match (u32 fib_index,
99 : const mfib_prefix_t *prefix)
100 : {
101 417 : return (mfib_table_lookup_exact_match_i(mfib_table_get(fib_index,
102 417 : prefix->fp_proto),
103 : prefix));
104 : }
105 :
106 : static fib_node_index_t
107 8581 : mfib_table_get_less_specific_i (const mfib_table_t *mfib_table,
108 : const mfib_prefix_t *prefix)
109 : {
110 8581 : switch (prefix->fp_proto)
111 : {
112 4949 : case FIB_PROTOCOL_IP4:
113 4949 : return (ip4_mfib_table_get_less_specific(&mfib_table->v4,
114 : &prefix->fp_src_addr.ip4,
115 : &prefix->fp_grp_addr.ip4,
116 4949 : prefix->fp_len));
117 3632 : case FIB_PROTOCOL_IP6:
118 3632 : return (ip6_mfib_table_get_less_specific(&mfib_table->v6,
119 : &prefix->fp_src_addr.ip6,
120 : &prefix->fp_grp_addr.ip6,
121 3632 : prefix->fp_len));
122 0 : case FIB_PROTOCOL_MPLS:
123 0 : break;
124 : }
125 0 : return (FIB_NODE_INDEX_INVALID);
126 : }
127 :
128 : fib_node_index_t
129 8 : mfib_table_get_less_specific (u32 fib_index,
130 : const mfib_prefix_t *prefix)
131 : {
132 8 : return (mfib_table_get_less_specific_i(mfib_table_get(fib_index,
133 8 : prefix->fp_proto),
134 : prefix));
135 : }
136 :
137 : static void
138 3987 : mfib_table_entry_remove (mfib_table_t *mfib_table,
139 : const mfib_prefix_t *prefix,
140 : fib_node_index_t mfib_entry_index)
141 : {
142 3987 : vlib_smp_unsafe_warning();
143 :
144 3987 : mfib_table->mft_total_route_counts--;
145 :
146 3987 : switch (prefix->fp_proto)
147 : {
148 3196 : case FIB_PROTOCOL_IP4:
149 3196 : ip4_mfib_table_entry_remove(&mfib_table->v4,
150 : &prefix->fp_grp_addr.ip4,
151 : &prefix->fp_src_addr.ip4,
152 3196 : prefix->fp_len);
153 3196 : break;
154 791 : case FIB_PROTOCOL_IP6:
155 791 : ip6_mfib_table_entry_remove(&mfib_table->v6,
156 : &prefix->fp_grp_addr.ip6,
157 : &prefix->fp_src_addr.ip6,
158 791 : prefix->fp_len);
159 791 : break;
160 0 : case FIB_PROTOCOL_MPLS:
161 0 : ASSERT(0);
162 0 : break;
163 : }
164 :
165 3987 : mfib_entry_cover_change_notify(mfib_entry_index,
166 : FIB_NODE_INDEX_INVALID);
167 3987 : mfib_entry_unlock(mfib_entry_index);
168 3987 : }
169 :
170 : static void
171 8573 : mfib_table_post_insert_actions (mfib_table_t *mfib_table,
172 : const mfib_prefix_t *prefix,
173 : fib_node_index_t mfib_entry_index)
174 : {
175 : fib_node_index_t mfib_entry_cover_index;
176 :
177 : /*
178 : * find the covering entry
179 : */
180 8573 : mfib_entry_cover_index = mfib_table_get_less_specific_i(mfib_table,
181 : prefix);
182 : /*
183 : * the indicies are the same when the default route is first added
184 : */
185 8573 : if (mfib_entry_cover_index != mfib_entry_index)
186 : {
187 : /*
188 : * inform the covering entry that a new more specific
189 : * has been inserted beneath it.
190 : * If the prefix that has been inserted is a host route
191 : * then it is not possible that it will be the cover for any
192 : * other entry, so we can elide the walk.
193 : */
194 7073 : if (!mfib_entry_is_host(mfib_entry_index))
195 : {
196 7059 : mfib_entry_cover_change_notify(mfib_entry_cover_index,
197 : mfib_entry_index);
198 : }
199 : }
200 8573 : }
201 :
202 :
203 : static void
204 8573 : mfib_table_entry_insert (mfib_table_t *mfib_table,
205 : const mfib_prefix_t *prefix,
206 : fib_node_index_t mfib_entry_index)
207 : {
208 8573 : vlib_smp_unsafe_warning();
209 :
210 8573 : mfib_entry_lock(mfib_entry_index);
211 8573 : mfib_table->mft_total_route_counts++;
212 :
213 8573 : switch (prefix->fp_proto)
214 : {
215 4945 : case FIB_PROTOCOL_IP4:
216 4945 : ip4_mfib_table_entry_insert(&mfib_table->v4,
217 : &prefix->fp_grp_addr.ip4,
218 : &prefix->fp_src_addr.ip4,
219 4945 : prefix->fp_len,
220 : mfib_entry_index);
221 4945 : break;
222 3628 : case FIB_PROTOCOL_IP6:
223 3628 : ip6_mfib_table_entry_insert(&mfib_table->v6,
224 : &prefix->fp_grp_addr.ip6,
225 : &prefix->fp_src_addr.ip6,
226 3628 : prefix->fp_len,
227 : mfib_entry_index);
228 3628 : break;
229 0 : case FIB_PROTOCOL_MPLS:
230 0 : break;
231 : }
232 :
233 8573 : mfib_table_post_insert_actions(mfib_table, prefix, mfib_entry_index);
234 8573 : }
235 :
236 : fib_node_index_t
237 1524 : mfib_table_entry_update (u32 fib_index,
238 : const mfib_prefix_t *prefix,
239 : mfib_source_t source,
240 : fib_rpf_id_t rpf_id,
241 : mfib_entry_flags_t entry_flags)
242 : {
243 : fib_node_index_t mfib_entry_index;
244 : mfib_table_t *mfib_table;
245 :
246 1524 : mfib_table = mfib_table_get(fib_index, prefix->fp_proto);
247 1524 : mfib_entry_index = mfib_table_lookup_exact_match_i(mfib_table, prefix);
248 :
249 1524 : if (FIB_NODE_INDEX_INVALID == mfib_entry_index)
250 : {
251 1500 : if (MFIB_ENTRY_FLAG_NONE != entry_flags)
252 : {
253 : /*
254 : * update to a non-existing entry with non-zero flags
255 : */
256 1500 : mfib_entry_index = mfib_entry_create(fib_index, source,
257 : prefix, rpf_id,
258 : entry_flags,
259 : INDEX_INVALID);
260 :
261 1500 : mfib_table_entry_insert(mfib_table, prefix, mfib_entry_index);
262 : }
263 : /*
264 : * else
265 : * the entry doesn't exist and the request is to set no flags
266 : * the result would be an entry that doesn't exist - so do nothing
267 : */
268 : }
269 : else
270 : {
271 24 : mfib_entry_lock(mfib_entry_index);
272 :
273 24 : if (mfib_entry_update(mfib_entry_index,
274 : source,
275 : entry_flags,
276 : rpf_id,
277 : INDEX_INVALID))
278 : {
279 : /*
280 : * this update means we can now remove the entry.
281 : */
282 2 : mfib_table_entry_remove(mfib_table, prefix, mfib_entry_index);
283 : }
284 :
285 24 : mfib_entry_unlock(mfib_entry_index);
286 : }
287 :
288 1524 : return (mfib_entry_index);
289 : }
290 :
291 : static fib_node_index_t
292 22994 : mfib_table_entry_paths_update_i (u32 fib_index,
293 : const mfib_prefix_t *prefix,
294 : mfib_source_t source,
295 : mfib_entry_flags_t entry_flags,
296 : const fib_route_path_t *rpaths)
297 : {
298 : fib_node_index_t mfib_entry_index;
299 : mfib_table_t *mfib_table;
300 :
301 22994 : mfib_table = mfib_table_get(fib_index, prefix->fp_proto);
302 22994 : mfib_entry_index = mfib_table_lookup_exact_match_i(mfib_table, prefix);
303 :
304 22994 : if (FIB_NODE_INDEX_INVALID == mfib_entry_index)
305 : {
306 7067 : mfib_entry_index = mfib_entry_create(fib_index,
307 : source,
308 : prefix,
309 : MFIB_RPF_ID_NONE,
310 : entry_flags,
311 : INDEX_INVALID);
312 :
313 7067 : mfib_entry_path_update(mfib_entry_index, source, rpaths);
314 :
315 7067 : mfib_table_entry_insert(mfib_table, prefix, mfib_entry_index);
316 : }
317 : else
318 : {
319 15927 : mfib_entry_path_update(mfib_entry_index, source, rpaths);
320 : }
321 22994 : return (mfib_entry_index);
322 : }
323 :
324 :
325 : fib_node_index_t
326 22096 : mfib_table_entry_path_update (u32 fib_index,
327 : const mfib_prefix_t *prefix,
328 : mfib_source_t source,
329 : mfib_entry_flags_t entry_flags,
330 : const fib_route_path_t *rpath)
331 : {
332 : fib_node_index_t mfib_entry_index;
333 22096 : fib_route_path_t *rpaths = NULL;
334 :
335 22096 : vec_add1(rpaths, *rpath);
336 :
337 22096 : mfib_entry_index = mfib_table_entry_paths_update_i(fib_index, prefix,
338 : source, entry_flags,
339 : rpaths);
340 :
341 22096 : vec_free(rpaths);
342 22096 : return (mfib_entry_index);
343 : }
344 :
345 : fib_node_index_t
346 898 : mfib_table_entry_paths_update (u32 fib_index,
347 : const mfib_prefix_t *prefix,
348 : mfib_source_t source,
349 : mfib_entry_flags_t entry_flags,
350 : const fib_route_path_t *rpaths)
351 : {
352 898 : return (mfib_table_entry_paths_update_i(fib_index, prefix,
353 : source, entry_flags, rpaths));
354 : }
355 :
356 : static void
357 38023 : mfib_table_entry_paths_remove_i (u32 fib_index,
358 : const mfib_prefix_t *prefix,
359 : mfib_source_t source,
360 : const fib_route_path_t *rpaths)
361 : {
362 : fib_node_index_t mfib_entry_index;
363 : mfib_table_t *mfib_table;
364 :
365 38023 : mfib_table = mfib_table_get(fib_index, prefix->fp_proto);
366 38023 : mfib_entry_index = mfib_table_lookup_exact_match_i(mfib_table, prefix);
367 :
368 38023 : if (FIB_NODE_INDEX_INVALID == mfib_entry_index)
369 : {
370 : /*
371 : * removing an entry that does not exist. i'll allow it.
372 : */
373 : }
374 : else
375 : {
376 : int no_more_sources;
377 :
378 : /*
379 : * don't nobody go nowhere
380 : */
381 38017 : mfib_entry_lock(mfib_entry_index);
382 :
383 38017 : no_more_sources = mfib_entry_path_remove(mfib_entry_index,
384 : source,
385 : rpaths);
386 :
387 38017 : if (no_more_sources)
388 : {
389 : /*
390 : * last source gone. remove from the table
391 : */
392 971 : mfib_table_entry_remove(mfib_table, prefix, mfib_entry_index);
393 : }
394 :
395 38017 : mfib_entry_unlock(mfib_entry_index);
396 : }
397 38023 : }
398 : void
399 29 : mfib_table_entry_paths_remove (u32 fib_index,
400 : const mfib_prefix_t *prefix,
401 : mfib_source_t source,
402 : const fib_route_path_t *rpaths)
403 : {
404 29 : mfib_table_entry_paths_remove_i(fib_index,
405 : prefix,
406 : source,
407 : rpaths);
408 29 : }
409 :
410 : void
411 37994 : mfib_table_entry_path_remove (u32 fib_index,
412 : const mfib_prefix_t *prefix,
413 : mfib_source_t source,
414 : const fib_route_path_t *rpath)
415 : {
416 37994 : fib_route_path_t *rpaths = NULL;
417 :
418 37994 : vec_add1(rpaths, *rpath);
419 :
420 37994 : mfib_table_entry_paths_remove_i(fib_index,
421 : prefix,
422 : source,
423 : rpaths);
424 :
425 37994 : vec_free(rpaths);
426 37994 : }
427 :
428 : fib_node_index_t
429 12 : mfib_table_entry_special_add (u32 fib_index,
430 : const mfib_prefix_t *prefix,
431 : mfib_source_t source,
432 : mfib_entry_flags_t entry_flags,
433 : index_t repi)
434 : {
435 : fib_node_index_t mfib_entry_index;
436 : mfib_table_t *mfib_table;
437 :
438 12 : mfib_table = mfib_table_get(fib_index, prefix->fp_proto);
439 12 : mfib_entry_index = mfib_table_lookup_exact_match_i(mfib_table, prefix);
440 :
441 12 : if (INDEX_INVALID != repi)
442 : {
443 2 : entry_flags |= MFIB_ENTRY_FLAG_EXCLUSIVE;
444 : }
445 :
446 12 : if (FIB_NODE_INDEX_INVALID == mfib_entry_index)
447 : {
448 6 : mfib_entry_index = mfib_entry_create(fib_index,
449 : source,
450 : prefix,
451 : MFIB_RPF_ID_NONE,
452 : entry_flags,
453 : repi);
454 :
455 6 : mfib_table_entry_insert(mfib_table, prefix, mfib_entry_index);
456 : }
457 : else
458 : {
459 6 : mfib_entry_special_add(mfib_entry_index, source, entry_flags,
460 : MFIB_RPF_ID_NONE, repi);
461 : }
462 :
463 12 : return (mfib_entry_index);
464 : }
465 :
466 : static void
467 3027 : mfib_table_entry_delete_i (u32 fib_index,
468 : fib_node_index_t mfib_entry_index,
469 : const mfib_prefix_t *prefix,
470 : mfib_source_t source)
471 : {
472 : mfib_table_t *mfib_table;
473 :
474 3027 : mfib_table = mfib_table_get(fib_index, prefix->fp_proto);
475 :
476 : /*
477 : * don't nobody go nowhere
478 : */
479 3027 : mfib_entry_lock(mfib_entry_index);
480 :
481 3027 : if (mfib_entry_delete(mfib_entry_index, source))
482 : {
483 : /*
484 : * last source gone. remove from the table
485 : */
486 3014 : mfib_table_entry_remove(mfib_table, prefix, mfib_entry_index);
487 : }
488 : /*
489 : * else
490 : * still has sources, leave it be.
491 : */
492 :
493 3027 : mfib_entry_unlock(mfib_entry_index);
494 3027 : }
495 :
496 : void
497 268 : mfib_table_entry_delete (u32 fib_index,
498 : const mfib_prefix_t *prefix,
499 : mfib_source_t source)
500 : {
501 : fib_node_index_t mfib_entry_index;
502 :
503 268 : mfib_entry_index = mfib_table_lookup_exact_match(fib_index, prefix);
504 :
505 268 : if (FIB_NODE_INDEX_INVALID == mfib_entry_index)
506 : {
507 : /*
508 : * removing an etry that does not exist.
509 : * i'll allow it, but i won't like it.
510 : */
511 2 : clib_warning("%U not in FIB", format_mfib_prefix, prefix);
512 : }
513 : else
514 : {
515 266 : mfib_table_entry_delete_i(fib_index, mfib_entry_index,
516 : prefix, source);
517 : }
518 268 : }
519 :
520 : void
521 2761 : mfib_table_entry_delete_index (fib_node_index_t mfib_entry_index,
522 : mfib_source_t source)
523 : {
524 2761 : mfib_table_entry_delete_i(mfib_entry_get_fib_index(mfib_entry_index),
525 : mfib_entry_index,
526 : mfib_entry_get_prefix(mfib_entry_index),
527 : source);
528 2761 : }
529 :
530 : u32
531 63 : mfib_table_get_index_for_sw_if_index (fib_protocol_t proto,
532 : u32 sw_if_index)
533 : {
534 63 : switch (proto)
535 : {
536 55 : case FIB_PROTOCOL_IP4:
537 55 : return (ip4_mfib_table_get_index_for_sw_if_index(sw_if_index));
538 8 : case FIB_PROTOCOL_IP6:
539 8 : return (ip6_mfib_table_get_index_for_sw_if_index(sw_if_index));
540 0 : case FIB_PROTOCOL_MPLS:
541 0 : ASSERT(0);
542 0 : break;
543 : }
544 0 : return (~0);
545 : }
546 :
547 : u32
548 4053 : mfib_table_get_table_id (u32 fib_index,
549 : fib_protocol_t proto)
550 : {
551 : mfib_table_t *mfib_table;
552 :
553 4053 : mfib_table = mfib_table_get(fib_index, proto);
554 :
555 4053 : return ((NULL != mfib_table ? mfib_table->mft_table_id : ~0));
556 : }
557 :
558 : u32
559 4098 : mfib_table_find (fib_protocol_t proto,
560 : u32 table_id)
561 : {
562 4098 : switch (proto)
563 : {
564 2560 : case FIB_PROTOCOL_IP4:
565 2560 : return (ip4_mfib_index_from_table_id(table_id));
566 1538 : case FIB_PROTOCOL_IP6:
567 1538 : return (ip6_mfib_index_from_table_id(table_id));
568 0 : case FIB_PROTOCOL_MPLS:
569 0 : ASSERT(0);
570 0 : break;
571 : }
572 0 : return (~0);
573 : }
574 :
575 : static u32
576 1924 : mfib_table_find_or_create_and_lock_i (fib_protocol_t proto,
577 : u32 table_id,
578 : mfib_source_t src,
579 : const u8 *name)
580 : {
581 : mfib_table_t *mfib_table;
582 : fib_node_index_t fi;
583 :
584 1924 : switch (proto)
585 : {
586 1182 : case FIB_PROTOCOL_IP4:
587 1182 : fi = ip4_mfib_table_find_or_create_and_lock(table_id, src);
588 1182 : break;
589 742 : case FIB_PROTOCOL_IP6:
590 742 : fi = ip6_mfib_table_find_or_create_and_lock(table_id, src);
591 742 : break;
592 0 : case FIB_PROTOCOL_MPLS:
593 : default:
594 0 : return (~0);
595 : }
596 :
597 1924 : mfib_table = mfib_table_get(fi, proto);
598 :
599 1924 : if (NULL == mfib_table->mft_desc)
600 : {
601 1500 : if (name && name[0])
602 : {
603 0 : mfib_table->mft_desc = format(NULL, "%s", name);
604 : }
605 : else
606 : {
607 1500 : mfib_table->mft_desc = format(NULL, "%U-VRF:%d",
608 : format_fib_protocol, proto,
609 : table_id);
610 : }
611 : }
612 :
613 1924 : return (fi);
614 : }
615 :
616 : u32
617 1483 : mfib_table_find_or_create_and_lock (fib_protocol_t proto,
618 : u32 table_id,
619 : mfib_source_t src)
620 : {
621 1483 : return (mfib_table_find_or_create_and_lock_i(proto, table_id,
622 : src, NULL));
623 : }
624 :
625 : u32
626 441 : mfib_table_find_or_create_and_lock_w_name (fib_protocol_t proto,
627 : u32 table_id,
628 : mfib_source_t src,
629 : const u8 *name)
630 : {
631 441 : return (mfib_table_find_or_create_and_lock_i(proto, table_id,
632 : src, name));
633 : }
634 :
635 : /**
636 : * @brief Table flush context. Store the indicies of matching FIB entries
637 : * that need to be removed.
638 : */
639 : typedef struct mfib_table_flush_ctx_t_
640 : {
641 : /**
642 : * The list of entries to flush
643 : */
644 : fib_node_index_t *mftf_entries;
645 :
646 : /**
647 : * The source we are flushing
648 : */
649 : mfib_source_t mftf_source;
650 : } mfib_table_flush_ctx_t;
651 :
652 : static walk_rc_t
653 3185 : mfib_table_flush_cb (fib_node_index_t mfib_entry_index,
654 : void *arg)
655 : {
656 3185 : mfib_table_flush_ctx_t *ctx = arg;
657 :
658 3185 : if (mfib_entry_is_sourced(mfib_entry_index, ctx->mftf_source))
659 : {
660 166 : vec_add1(ctx->mftf_entries, mfib_entry_index);
661 : }
662 3185 : return (WALK_CONTINUE);
663 : }
664 :
665 : void
666 805 : mfib_table_flush (u32 mfib_index,
667 : fib_protocol_t proto,
668 : mfib_source_t source)
669 : {
670 : fib_node_index_t *mfib_entry_index;
671 805 : mfib_table_flush_ctx_t ctx = {
672 : .mftf_entries = NULL,
673 : .mftf_source = source,
674 : };
675 :
676 805 : mfib_table_walk(mfib_index, proto,
677 : mfib_table_flush_cb,
678 : &ctx);
679 :
680 971 : vec_foreach(mfib_entry_index, ctx.mftf_entries)
681 : {
682 166 : mfib_table_entry_delete_index(*mfib_entry_index, source);
683 : }
684 :
685 805 : vec_free(ctx.mftf_entries);
686 805 : }
687 :
688 : static walk_rc_t
689 564 : mfib_table_mark_cb (fib_node_index_t fib_entry_index,
690 : void *arg)
691 : {
692 564 : mfib_table_flush_ctx_t *ctx = arg;
693 :
694 564 : if (mfib_entry_is_sourced(fib_entry_index, ctx->mftf_source))
695 : {
696 468 : mfib_entry_mark(fib_entry_index, ctx->mftf_source);
697 : }
698 564 : return (WALK_CONTINUE);
699 : }
700 :
701 : void
702 24 : mfib_table_mark (u32 fib_index,
703 : fib_protocol_t proto,
704 : mfib_source_t source)
705 : {
706 24 : mfib_table_flush_ctx_t ctx = {
707 : .mftf_source = source,
708 : };
709 : mfib_table_t *mfib_table;
710 :
711 24 : mfib_table = mfib_table_get(fib_index, proto);
712 :
713 24 : mfib_table->mft_epoch++;
714 24 : mfib_table->mft_flags |= MFIB_TABLE_FLAG_RESYNC;
715 :
716 24 : mfib_table_walk(fib_index, proto,
717 : mfib_table_mark_cb,
718 : &ctx);
719 24 : }
720 :
721 : static walk_rc_t
722 564 : mfib_table_sweep_cb (fib_node_index_t fib_entry_index,
723 : void *arg)
724 : {
725 564 : mfib_table_flush_ctx_t *ctx = arg;
726 :
727 564 : if (mfib_entry_is_marked(fib_entry_index, ctx->mftf_source))
728 : {
729 228 : vec_add1(ctx->mftf_entries, fib_entry_index);
730 : }
731 564 : return (WALK_CONTINUE);
732 : }
733 :
734 : void
735 24 : mfib_table_sweep (u32 fib_index,
736 : fib_protocol_t proto,
737 : mfib_source_t source)
738 : {
739 24 : mfib_table_flush_ctx_t ctx = {
740 : .mftf_source = source,
741 : };
742 : fib_node_index_t *fib_entry_index;
743 : mfib_table_t *mfib_table;
744 :
745 24 : mfib_table = mfib_table_get(fib_index, proto);
746 :
747 24 : mfib_table->mft_flags &= ~MFIB_TABLE_FLAG_RESYNC;
748 :
749 24 : mfib_table_walk(fib_index, proto,
750 : mfib_table_sweep_cb,
751 : &ctx);
752 :
753 252 : vec_foreach(fib_entry_index, ctx.mftf_entries)
754 : {
755 228 : mfib_table_entry_delete_index(*fib_entry_index, source);
756 : }
757 :
758 24 : vec_free(ctx.mftf_entries);
759 24 : }
760 :
761 : static void
762 351 : mfib_table_destroy (mfib_table_t *mfib_table)
763 : {
764 351 : vec_free(mfib_table->mft_desc);
765 :
766 351 : switch (mfib_table->mft_proto)
767 : {
768 236 : case FIB_PROTOCOL_IP4:
769 236 : ip4_mfib_table_destroy(&mfib_table->v4);
770 236 : break;
771 115 : case FIB_PROTOCOL_IP6:
772 115 : ip6_mfib_table_destroy(&mfib_table->v6);
773 115 : break;
774 0 : case FIB_PROTOCOL_MPLS:
775 0 : ASSERT(0);
776 0 : break;
777 : }
778 351 : }
779 :
780 : void
781 974 : mfib_table_unlock (u32 fib_index,
782 : fib_protocol_t proto,
783 : mfib_source_t source)
784 : {
785 : mfib_table_t *mfib_table;
786 :
787 974 : mfib_table = mfib_table_get(fib_index, proto);
788 974 : mfib_table->mft_locks[source]--;
789 974 : mfib_table->mft_locks[MFIB_TABLE_TOTAL_LOCKS]--;
790 :
791 974 : if (0 == mfib_table->mft_locks[source])
792 : {
793 : /*
794 : * The source no longer needs the table. flush any routes
795 : * from it just in case
796 : */
797 771 : mfib_table_flush(fib_index, proto, source);
798 : }
799 :
800 974 : if (0 == mfib_table->mft_locks[MFIB_TABLE_TOTAL_LOCKS])
801 : {
802 : /*
803 : * no more locak from any source - kill it
804 : */
805 351 : mfib_table_destroy(mfib_table);
806 : }
807 974 : }
808 :
809 : void
810 2198 : mfib_table_lock (u32 fib_index,
811 : fib_protocol_t proto,
812 : mfib_source_t source)
813 : {
814 : mfib_table_t *mfib_table;
815 :
816 2198 : mfib_table = mfib_table_get(fib_index, proto);
817 2198 : mfib_table->mft_locks[source]++;
818 2198 : mfib_table->mft_locks[MFIB_TABLE_TOTAL_LOCKS]++;
819 2198 : }
820 :
821 : u32
822 2 : mfib_table_get_n_routes (fib_node_index_t fib_index,
823 : fib_protocol_t proto)
824 : {
825 : mfib_table_t *mfib_table;
826 :
827 2 : mfib_table = mfib_table_get(fib_index, proto);
828 :
829 2 : return (mfib_table->mft_total_route_counts);
830 : }
831 :
832 : void
833 1163 : mfib_table_walk (u32 fib_index,
834 : fib_protocol_t proto,
835 : mfib_table_walk_fn_t fn,
836 : void *ctx)
837 : {
838 1163 : switch (proto)
839 : {
840 707 : case FIB_PROTOCOL_IP4:
841 707 : ip4_mfib_table_walk(ip4_mfib_get(fib_index), fn, ctx);
842 707 : break;
843 456 : case FIB_PROTOCOL_IP6:
844 456 : ip6_mfib_table_walk(ip6_mfib_get(fib_index), fn, ctx);
845 456 : break;
846 0 : case FIB_PROTOCOL_MPLS:
847 0 : break;
848 : }
849 1163 : }
850 :
851 : u8*
852 2 : format_mfib_table_flags (u8 *s, va_list *args)
853 : {
854 2 : mfib_table_flags_t flags = va_arg(*args, int);
855 : mfib_table_attribute_t attr;
856 :
857 2 : if (!flags)
858 : {
859 2 : return format(s, "none");
860 : }
861 :
862 0 : FOR_EACH_MFIB_TABLE_ATTRIBUTE(attr) {
863 0 : if (1 << attr & flags) {
864 0 : s = format(s, "%s", mfib_table_flags_strings[attr]);
865 : }
866 : }
867 :
868 0 : return (s);
869 : }
870 :
871 : u8*
872 867 : format_mfib_table_name (u8* s, va_list *ap)
873 : {
874 867 : fib_node_index_t fib_index = va_arg(*ap, fib_node_index_t);
875 867 : fib_protocol_t proto = va_arg(*ap, int); // int promotion
876 : mfib_table_t *mfib_table;
877 :
878 867 : mfib_table = mfib_table_get(fib_index, proto);
879 :
880 867 : s = format(s, "%v", mfib_table->mft_desc);
881 :
882 867 : return (s);
883 : }
884 :
885 : u8 *
886 1 : format_mfib_table_memory (u8 *s, va_list *args)
887 : {
888 1 : s = format(s, "%U", format_ip4_mfib_table_memory);
889 1 : s = format(s, "%U", format_ip6_mfib_table_memory);
890 :
891 1 : return (s);
892 : }
893 :
894 : static clib_error_t *
895 559 : mfib_module_init (vlib_main_t * vm)
896 : {
897 : clib_error_t * error;
898 :
899 559 : mfib_entry_src_module_init();
900 559 : mfib_entry_module_init();
901 559 : mfib_signal_module_init();
902 :
903 559 : if ((error = vlib_call_init_function (vm, fib_module_init)))
904 0 : return (error);
905 559 : if ((error = vlib_call_init_function (vm, rn_module_init)))
906 0 : return (error);
907 :
908 559 : return (error);
909 : }
910 :
911 14559 : VLIB_INIT_FUNCTION(mfib_module_init);
|