blob: 80e5a0fe1a0b107120cbc25cde8e0a48711c48a5 [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 <vlib/vlib.h>
17#include <vnet/dpo/drop_dpo.h>
18
19#include <vnet/fib/fib_table.h>
20#include <vnet/fib/fib_entry_cover.h>
21#include <vnet/fib/fib_internal.h>
22#include <vnet/fib/ip4_fib.h>
23#include <vnet/fib/ip6_fib.h>
24#include <vnet/fib/mpls_fib.h>
25
26fib_table_t *
27fib_table_get (fib_node_index_t index,
28 fib_protocol_t proto)
29{
30 switch (proto)
31 {
32 case FIB_PROTOCOL_IP4:
33 return (pool_elt_at_index(ip4_main.fibs, index));
34 case FIB_PROTOCOL_IP6:
35 return (pool_elt_at_index(ip6_main.fibs, index));
36 case FIB_PROTOCOL_MPLS:
37 return (pool_elt_at_index(mpls_main.fibs, index));
38 }
39 ASSERT(0);
40 return (NULL);
41}
42
43static inline fib_node_index_t
44fib_table_lookup_i (fib_table_t *fib_table,
45 const fib_prefix_t *prefix)
46{
47 switch (prefix->fp_proto)
48 {
49 case FIB_PROTOCOL_IP4:
Neale Rannsa3af3372017-03-28 03:49:52 -070050 return (ip4_fib_table_lookup(ip4_fib_get(fib_table->ft_index),
Neale Ranns0bfe5d82016-08-25 15:29:12 +010051 &prefix->fp_addr.ip4,
52 prefix->fp_len));
53 case FIB_PROTOCOL_IP6:
54 return (ip6_fib_table_lookup(fib_table->ft_index,
55 &prefix->fp_addr.ip6,
56 prefix->fp_len));
57 case FIB_PROTOCOL_MPLS:
Neale Rannsa3af3372017-03-28 03:49:52 -070058 return (mpls_fib_table_lookup(mpls_fib_get(fib_table->ft_index),
Neale Ranns0bfe5d82016-08-25 15:29:12 +010059 prefix->fp_label,
60 prefix->fp_eos));
61 }
62 return (FIB_NODE_INDEX_INVALID);
63}
64
65fib_node_index_t
66fib_table_lookup (u32 fib_index,
67 const fib_prefix_t *prefix)
68{
69 return (fib_table_lookup_i(fib_table_get(fib_index, prefix->fp_proto), prefix));
70}
71
72static inline fib_node_index_t
73fib_table_lookup_exact_match_i (const fib_table_t *fib_table,
74 const fib_prefix_t *prefix)
75{
76 switch (prefix->fp_proto)
77 {
78 case FIB_PROTOCOL_IP4:
Neale Rannsa3af3372017-03-28 03:49:52 -070079 return (ip4_fib_table_lookup_exact_match(ip4_fib_get(fib_table->ft_index),
Neale Ranns0bfe5d82016-08-25 15:29:12 +010080 &prefix->fp_addr.ip4,
81 prefix->fp_len));
82 case FIB_PROTOCOL_IP6:
83 return (ip6_fib_table_lookup_exact_match(fib_table->ft_index,
84 &prefix->fp_addr.ip6,
85 prefix->fp_len));
86 case FIB_PROTOCOL_MPLS:
Neale Rannsa3af3372017-03-28 03:49:52 -070087 return (mpls_fib_table_lookup(mpls_fib_get(fib_table->ft_index),
Neale Ranns0bfe5d82016-08-25 15:29:12 +010088 prefix->fp_label,
89 prefix->fp_eos));
90 }
91 return (FIB_NODE_INDEX_INVALID);
92}
93
94fib_node_index_t
95fib_table_lookup_exact_match (u32 fib_index,
96 const fib_prefix_t *prefix)
97{
98 return (fib_table_lookup_exact_match_i(fib_table_get(fib_index,
99 prefix->fp_proto),
100 prefix));
101}
102
103static fib_node_index_t
104fib_table_get_less_specific_i (fib_table_t *fib_table,
105 const fib_prefix_t *prefix)
106{
107 fib_prefix_t pfx;
108
109 pfx = *prefix;
110
111 if (FIB_PROTOCOL_MPLS == pfx.fp_proto)
112 {
113 return (FIB_NODE_INDEX_INVALID);
114 }
115
116 /*
117 * in the absence of a tree structure for the table that allows for an O(1)
118 * parent get, a cheeky way to find the cover is to LPM for the prefix with
119 * mask-1.
120 * there should always be a cover, though it may be the default route. the
121 * default route's cover is the default route.
122 */
123 if (pfx.fp_len != 0) {
124 pfx.fp_len -= 1;
125 }
126
127 return (fib_table_lookup_i(fib_table, &pfx));
128}
129
130fib_node_index_t
131fib_table_get_less_specific (u32 fib_index,
132 const fib_prefix_t *prefix)
133{
134 return (fib_table_get_less_specific_i(fib_table_get(fib_index,
135 prefix->fp_proto),
136 prefix));
137}
138
139static void
140fib_table_entry_remove (fib_table_t *fib_table,
141 const fib_prefix_t *prefix,
142 fib_node_index_t fib_entry_index)
143{
144 vlib_smp_unsafe_warning();
145
146 fib_table->ft_total_route_counts--;
147
148 switch (prefix->fp_proto)
149 {
150 case FIB_PROTOCOL_IP4:
Neale Rannsa3af3372017-03-28 03:49:52 -0700151 ip4_fib_table_entry_remove(ip4_fib_get(fib_table->ft_index),
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100152 &prefix->fp_addr.ip4,
153 prefix->fp_len);
154 break;
155 case FIB_PROTOCOL_IP6:
156 ip6_fib_table_entry_remove(fib_table->ft_index,
157 &prefix->fp_addr.ip6,
158 prefix->fp_len);
159 break;
160 case FIB_PROTOCOL_MPLS:
Neale Rannsa3af3372017-03-28 03:49:52 -0700161 mpls_fib_table_entry_remove(mpls_fib_get(fib_table->ft_index),
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100162 prefix->fp_label,
163 prefix->fp_eos);
164 break;
165 }
166
167 fib_entry_unlock(fib_entry_index);
168}
169
170static void
171fib_table_post_insert_actions (fib_table_t *fib_table,
172 const fib_prefix_t *prefix,
173 fib_node_index_t fib_entry_index)
174{
175 fib_node_index_t fib_entry_cover_index;
176
177 /*
178 * no cover relationships in the MPLS FIB
179 */
180 if (FIB_PROTOCOL_MPLS == prefix->fp_proto)
181 return;
182
183 /*
184 * find and inform the covering entry that a new more specific
185 * has been inserted beneath it
186 */
187 fib_entry_cover_index = fib_table_get_less_specific_i(fib_table, prefix);
188 /*
189 * the indicies are the same when the default route is first added
190 */
191 if (fib_entry_cover_index != fib_entry_index)
192 {
193 fib_entry_cover_change_notify(fib_entry_cover_index,
194 fib_entry_index);
195 }
196}
197
198static void
199fib_table_entry_insert (fib_table_t *fib_table,
200 const fib_prefix_t *prefix,
201 fib_node_index_t fib_entry_index)
202{
203 vlib_smp_unsafe_warning();
204
205 fib_entry_lock(fib_entry_index);
206 fib_table->ft_total_route_counts++;
207
208 switch (prefix->fp_proto)
209 {
210 case FIB_PROTOCOL_IP4:
Neale Rannsa3af3372017-03-28 03:49:52 -0700211 ip4_fib_table_entry_insert(ip4_fib_get(fib_table->ft_index),
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100212 &prefix->fp_addr.ip4,
213 prefix->fp_len,
214 fib_entry_index);
215 break;
216 case FIB_PROTOCOL_IP6:
217 ip6_fib_table_entry_insert(fib_table->ft_index,
218 &prefix->fp_addr.ip6,
219 prefix->fp_len,
220 fib_entry_index);
221 break;
222 case FIB_PROTOCOL_MPLS:
Neale Rannsa3af3372017-03-28 03:49:52 -0700223 mpls_fib_table_entry_insert(mpls_fib_get(fib_table->ft_index),
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100224 prefix->fp_label,
225 prefix->fp_eos,
226 fib_entry_index);
227 break;
228 }
229
230 fib_table_post_insert_actions(fib_table, prefix, fib_entry_index);
231}
232
233void
234fib_table_fwding_dpo_update (u32 fib_index,
235 const fib_prefix_t *prefix,
236 const dpo_id_t *dpo)
237{
238 vlib_smp_unsafe_warning();
239
240 switch (prefix->fp_proto)
241 {
242 case FIB_PROTOCOL_IP4:
243 return (ip4_fib_table_fwding_dpo_update(ip4_fib_get(fib_index),
244 &prefix->fp_addr.ip4,
245 prefix->fp_len,
246 dpo));
247 case FIB_PROTOCOL_IP6:
248 return (ip6_fib_table_fwding_dpo_update(fib_index,
249 &prefix->fp_addr.ip6,
250 prefix->fp_len,
251 dpo));
252 case FIB_PROTOCOL_MPLS:
253 return (mpls_fib_forwarding_table_update(mpls_fib_get(fib_index),
254 prefix->fp_label,
255 prefix->fp_eos,
256 dpo));
257 }
258}
259
260void
261fib_table_fwding_dpo_remove (u32 fib_index,
262 const fib_prefix_t *prefix,
263 const dpo_id_t *dpo)
264{
265 vlib_smp_unsafe_warning();
266
267 switch (prefix->fp_proto)
268 {
269 case FIB_PROTOCOL_IP4:
270 return (ip4_fib_table_fwding_dpo_remove(ip4_fib_get(fib_index),
271 &prefix->fp_addr.ip4,
272 prefix->fp_len,
Neale Rannsa3af3372017-03-28 03:49:52 -0700273 dpo,
274 fib_table_get_less_specific(fib_index,
275 prefix)));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100276 case FIB_PROTOCOL_IP6:
277 return (ip6_fib_table_fwding_dpo_remove(fib_index,
278 &prefix->fp_addr.ip6,
279 prefix->fp_len,
280 dpo));
281 case FIB_PROTOCOL_MPLS:
282 return (mpls_fib_forwarding_table_reset(mpls_fib_get(fib_index),
283 prefix->fp_label,
284 prefix->fp_eos));
285 }
286}
287
288
289fib_node_index_t
290fib_table_entry_special_dpo_add (u32 fib_index,
291 const fib_prefix_t *prefix,
292 fib_source_t source,
293 fib_entry_flag_t flags,
294 const dpo_id_t *dpo)
295{
296 fib_node_index_t fib_entry_index;
297 fib_table_t *fib_table;
298
299 fib_table = fib_table_get(fib_index, prefix->fp_proto);
300 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
301
302 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
303 {
304 fib_entry_index = fib_entry_create_special(fib_index, prefix,
305 source, flags,
306 dpo);
307
308 fib_table_entry_insert(fib_table, prefix, fib_entry_index);
309 fib_table->ft_src_route_counts[source]++;
310 }
311 else
312 {
313 int was_sourced;
314
315 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
316 fib_entry_special_add(fib_entry_index, source, flags, dpo);
317
318 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
319 {
320 fib_table->ft_src_route_counts[source]++;
321 }
322 }
323
324
325 return (fib_entry_index);
326}
327
328fib_node_index_t
Neale Ranns948e00f2016-10-20 13:39:34 +0100329fib_table_entry_special_dpo_update (u32 fib_index,
330 const fib_prefix_t *prefix,
331 fib_source_t source,
332 fib_entry_flag_t flags,
333 const dpo_id_t *dpo)
334{
335 fib_node_index_t fib_entry_index;
336 fib_table_t *fib_table;
337
338 fib_table = fib_table_get(fib_index, prefix->fp_proto);
339 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
340
341 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
342 {
343 fib_entry_index = fib_entry_create_special(fib_index, prefix,
344 source, flags,
345 dpo);
346
347 fib_table_entry_insert(fib_table, prefix, fib_entry_index);
348 fib_table->ft_src_route_counts[source]++;
349 }
350 else
351 {
352 int was_sourced;
353
354 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
355
356 if (was_sourced)
357 fib_entry_special_update(fib_entry_index, source, flags, dpo);
358 else
359 fib_entry_special_add(fib_entry_index, source, flags, dpo);
360
361 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
362 {
363 fib_table->ft_src_route_counts[source]++;
364 }
365 }
366
367 return (fib_entry_index);
368}
369
370fib_node_index_t
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100371fib_table_entry_special_add (u32 fib_index,
372 const fib_prefix_t *prefix,
373 fib_source_t source,
Neale Rannsa0558302017-04-13 00:44:52 -0700374 fib_entry_flag_t flags)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100375{
376 fib_node_index_t fib_entry_index;
Neale Ranns948e00f2016-10-20 13:39:34 +0100377 dpo_id_t tmp_dpo = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100378
Neale Rannsa0558302017-04-13 00:44:52 -0700379 dpo_copy(&tmp_dpo, drop_dpo_get(fib_proto_to_dpo(prefix->fp_proto)));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100380
381 fib_entry_index = fib_table_entry_special_dpo_add(fib_index, prefix, source,
382 flags, &tmp_dpo);
383
384 dpo_unlock(&tmp_dpo);
385
386 return (fib_entry_index);
387}
388
389void
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100390fib_table_entry_special_remove (u32 fib_index,
391 const fib_prefix_t *prefix,
392 fib_source_t source)
393{
394 /*
395 * 1 is it present
396 * yes => remove source
397 * 2 - is it still sourced?
398 * no => cover walk
399 */
400 fib_node_index_t fib_entry_index;
401 fib_table_t *fib_table;
402
403 fib_table = fib_table_get(fib_index, prefix->fp_proto);
404 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
405
406 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
407 {
408 /*
409 * removing an etry that does not exist. i'll allow it.
410 */
411 }
412 else
413 {
414 fib_entry_src_flag_t src_flag;
415 int was_sourced;
416
417 /*
418 * don't nobody go nowhere
419 */
420 fib_entry_lock(fib_entry_index);
421 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
422
423 src_flag = fib_entry_special_remove(fib_entry_index, source);
424
425 if (!(FIB_ENTRY_SRC_FLAG_ADDED & src_flag))
426 {
427 /*
428 * last source gone. remove from the table
429 */
430 fib_table_entry_remove(fib_table, prefix, fib_entry_index);
431
432 /*
433 * now the entry is no longer in the table, we can
434 * inform the entries that it covers to re-calculate their cover
435 */
436 fib_entry_cover_change_notify(fib_entry_index,
437 FIB_NODE_INDEX_INVALID);
438 }
439 /*
440 * else
441 * still has sources, leave it be.
442 */
443 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
444 {
445 fib_table->ft_src_route_counts[source]--;
446 }
447
448 fib_entry_unlock(fib_entry_index);
449 }
450}
451
452/**
453 * fib_table_route_path_fixup
454 *
455 * Convert attached hosts to attached next-hops.
456 *
457 * This special case is required because an attached path will link to a
458 * glean, and the FIB entry will have the interface or API/CLI source. When
459 * the ARP/ND process is completes then that source (which will provide a
460 * complete adjacency) will be lower priority and so the FIB entry will
461 * remain linked to a glean and traffic will never reach the hosts. For
462 * an ATTAHCED_HOST path we can link the path directly to the [incomplete]
463 * adjacency.
464 */
465static void
466fib_table_route_path_fixup (const fib_prefix_t *prefix,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800467 fib_entry_flag_t eflags,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100468 fib_route_path_t *path)
469{
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800470 /*
471 * not all zeros next hop &&
472 * is recursive path &&
473 * nexthop is same as the route's address
474 */
475 if ((!ip46_address_is_zero(&path->frp_addr)) &&
476 (~0 == path->frp_sw_if_index) &&
477 (0 == ip46_address_cmp(&path->frp_addr, &prefix->fp_addr)))
478 {
479 /* Prefix recurses via itse;f */
480 path->frp_flags |= FIB_ROUTE_PATH_DROP;
481 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100482 if (fib_prefix_is_host(prefix) &&
483 ip46_address_is_zero(&path->frp_addr) &&
Neale Ranns6f631152017-10-03 08:20:21 -0700484 path->frp_sw_if_index != ~0 &&
485 path->frp_proto != DPO_PROTO_ETHERNET)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100486 {
487 path->frp_addr = prefix->fp_addr;
Neale Ranns4b919a52017-03-11 05:55:21 -0800488 path->frp_flags |= FIB_ROUTE_PATH_ATTACHED;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100489 }
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800490 if (eflags & FIB_ENTRY_FLAG_DROP)
491 {
492 path->frp_flags |= FIB_ROUTE_PATH_DROP;
493 }
494 if (eflags & FIB_ENTRY_FLAG_LOCAL)
495 {
496 path->frp_flags |= FIB_ROUTE_PATH_LOCAL;
497 }
498 if (eflags & FIB_ENTRY_FLAG_EXCLUSIVE)
499 {
500 path->frp_flags |= FIB_ROUTE_PATH_EXCLUSIVE;
501 }
502}
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100503
504fib_node_index_t
505fib_table_entry_path_add (u32 fib_index,
506 const fib_prefix_t *prefix,
507 fib_source_t source,
508 fib_entry_flag_t flags,
Neale Rannsda78f952017-05-24 09:15:43 -0700509 dpo_proto_t next_hop_proto,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100510 const ip46_address_t *next_hop,
511 u32 next_hop_sw_if_index,
512 u32 next_hop_fib_index,
513 u32 next_hop_weight,
Neale Rannsad422ed2016-11-02 14:20:04 +0000514 mpls_label_t *next_hop_labels,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100515 fib_route_path_flags_t path_flags)
516{
517 fib_route_path_t path = {
518 .frp_proto = next_hop_proto,
519 .frp_addr = (NULL == next_hop? zero_addr : *next_hop),
520 .frp_sw_if_index = next_hop_sw_if_index,
521 .frp_fib_index = next_hop_fib_index,
522 .frp_weight = next_hop_weight,
523 .frp_flags = path_flags,
Neale Rannsad422ed2016-11-02 14:20:04 +0000524 .frp_label_stack = next_hop_labels,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100525 };
526 fib_node_index_t fib_entry_index;
527 fib_route_path_t *paths = NULL;
528
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100529 vec_add1(paths, path);
530
531 fib_entry_index = fib_table_entry_path_add2(fib_index, prefix,
532 source, flags, paths);
533
534 vec_free(paths);
535 return (fib_entry_index);
536}
537
538fib_node_index_t
539fib_table_entry_path_add2 (u32 fib_index,
540 const fib_prefix_t *prefix,
541 fib_source_t source,
542 fib_entry_flag_t flags,
Neale Rannsad422ed2016-11-02 14:20:04 +0000543 fib_route_path_t *rpath)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100544{
545 fib_node_index_t fib_entry_index;
546 fib_table_t *fib_table;
Neale Rannsad422ed2016-11-02 14:20:04 +0000547 u32 ii;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100548
549 fib_table = fib_table_get(fib_index, prefix->fp_proto);
550 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
551
Neale Rannsad422ed2016-11-02 14:20:04 +0000552 for (ii = 0; ii < vec_len(rpath); ii++)
553 {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800554 fib_table_route_path_fixup(prefix, flags, &rpath[ii]);
Neale Rannsad422ed2016-11-02 14:20:04 +0000555 }
556
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100557 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
558 {
559 fib_entry_index = fib_entry_create(fib_index, prefix,
560 source, flags,
561 rpath);
562
563 fib_table_entry_insert(fib_table, prefix, fib_entry_index);
564 fib_table->ft_src_route_counts[source]++;
565 }
566 else
567 {
568 int was_sourced;
569
570 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
571 fib_entry_path_add(fib_entry_index, source, flags, rpath);;
572
573 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
574 {
575 fib_table->ft_src_route_counts[source]++;
576 }
577 }
578
579 return (fib_entry_index);
580}
581
582void
583fib_table_entry_path_remove2 (u32 fib_index,
Neale Rannsad422ed2016-11-02 14:20:04 +0000584 const fib_prefix_t *prefix,
585 fib_source_t source,
586 fib_route_path_t *rpath)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100587{
588 /*
589 * 1 is it present
590 * yes => remove source
591 * 2 - is it still sourced?
592 * no => cover walk
593 */
594 fib_node_index_t fib_entry_index;
595 fib_table_t *fib_table;
Neale Rannsad422ed2016-11-02 14:20:04 +0000596 u32 ii;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100597
598 fib_table = fib_table_get(fib_index, prefix->fp_proto);
599 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
600
601 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
602 {
603 /*
604 * removing an etry that does not exist. i'll allow it.
605 */
606 }
607 else
608 {
609 fib_entry_src_flag_t src_flag;
610 int was_sourced;
611
Neale Rannsf12a83f2017-04-18 09:09:40 -0700612 /*
613 * if it's not sourced, then there's nowt to remove
614 */
615 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
616 if (!was_sourced)
617 {
618 return;
619 }
620
621 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100622 * don't nobody go nowhere
623 */
624 fib_entry_lock(fib_entry_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100625
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800626 for (ii = 0; ii < vec_len(rpath); ii++)
627 {
628 fib_table_route_path_fixup(
629 prefix,
630 fib_entry_get_flags_for_source(fib_entry_index,
631 source),
632 &rpath[ii]);
633 }
634
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100635 src_flag = fib_entry_path_remove(fib_entry_index, source, rpath);
636
637 if (!(FIB_ENTRY_SRC_FLAG_ADDED & src_flag))
638 {
639 /*
640 * last source gone. remove from the table
641 */
642 fib_table_entry_remove(fib_table, prefix, fib_entry_index);
643
644 /*
645 * now the entry is no longer in the table, we can
646 * inform the entries that it covers to re-calculate their cover
647 */
648 fib_entry_cover_change_notify(fib_entry_index,
649 FIB_NODE_INDEX_INVALID);
650 }
651 /*
652 * else
653 * still has sources, leave it be.
654 */
655 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
656 {
657 fib_table->ft_src_route_counts[source]--;
658 }
659
660 fib_entry_unlock(fib_entry_index);
661 }
662}
663
664void
665fib_table_entry_path_remove (u32 fib_index,
666 const fib_prefix_t *prefix,
667 fib_source_t source,
Neale Rannsda78f952017-05-24 09:15:43 -0700668 dpo_proto_t next_hop_proto,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100669 const ip46_address_t *next_hop,
670 u32 next_hop_sw_if_index,
671 u32 next_hop_fib_index,
672 u32 next_hop_weight,
673 fib_route_path_flags_t path_flags)
674{
675 /*
676 * 1 is it present
677 * yes => remove source
678 * 2 - is it still sourced?
679 * no => cover walk
680 */
681 fib_route_path_t path = {
682 .frp_proto = next_hop_proto,
683 .frp_addr = (NULL == next_hop? zero_addr : *next_hop),
684 .frp_sw_if_index = next_hop_sw_if_index,
685 .frp_fib_index = next_hop_fib_index,
686 .frp_weight = next_hop_weight,
687 .frp_flags = path_flags,
688 };
689 fib_route_path_t *paths = NULL;
690
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100691 vec_add1(paths, path);
692
693 fib_table_entry_path_remove2(fib_index, prefix, source, paths);
694
695 vec_free(paths);
696}
697
698static int
699fib_route_path_cmp_for_sort (void * v1,
700 void * v2)
701{
702 return (fib_route_path_cmp(v1, v2));
703}
704
705fib_node_index_t
706fib_table_entry_update (u32 fib_index,
707 const fib_prefix_t *prefix,
708 fib_source_t source,
709 fib_entry_flag_t flags,
Neale Rannsad422ed2016-11-02 14:20:04 +0000710 fib_route_path_t *paths)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100711{
712 fib_node_index_t fib_entry_index;
713 fib_table_t *fib_table;
Neale Rannsad422ed2016-11-02 14:20:04 +0000714 u32 ii;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100715
716 fib_table = fib_table_get(fib_index, prefix->fp_proto);
717 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
718
Neale Rannsad422ed2016-11-02 14:20:04 +0000719 for (ii = 0; ii < vec_len(paths); ii++)
720 {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800721 fib_table_route_path_fixup(prefix, flags, &paths[ii]);
Neale Rannsad422ed2016-11-02 14:20:04 +0000722 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100723 /*
724 * sort the paths provided by the control plane. this means
725 * the paths and the extension on the entry will be sorted.
726 */
Neale Rannsad422ed2016-11-02 14:20:04 +0000727 vec_sort_with_function(paths, fib_route_path_cmp_for_sort);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100728
729 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
730 {
731 fib_entry_index = fib_entry_create(fib_index, prefix,
732 source, flags,
733 paths);
734
735 fib_table_entry_insert(fib_table, prefix, fib_entry_index);
736 fib_table->ft_src_route_counts[source]++;
737 }
738 else
739 {
740 int was_sourced;
741
742 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
743 fib_entry_update(fib_entry_index, source, flags, paths);
744
745 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
746 {
747 fib_table->ft_src_route_counts[source]++;
748 }
749 }
750
751 return (fib_entry_index);
752}
753
754fib_node_index_t
755fib_table_entry_update_one_path (u32 fib_index,
756 const fib_prefix_t *prefix,
757 fib_source_t source,
758 fib_entry_flag_t flags,
Neale Rannsda78f952017-05-24 09:15:43 -0700759 dpo_proto_t next_hop_proto,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100760 const ip46_address_t *next_hop,
761 u32 next_hop_sw_if_index,
762 u32 next_hop_fib_index,
763 u32 next_hop_weight,
Neale Rannsad422ed2016-11-02 14:20:04 +0000764 mpls_label_t *next_hop_labels,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100765 fib_route_path_flags_t path_flags)
766{
767 fib_node_index_t fib_entry_index;
768 fib_route_path_t path = {
769 .frp_proto = next_hop_proto,
770 .frp_addr = (NULL == next_hop? zero_addr : *next_hop),
771 .frp_sw_if_index = next_hop_sw_if_index,
772 .frp_fib_index = next_hop_fib_index,
773 .frp_weight = next_hop_weight,
774 .frp_flags = path_flags,
Neale Rannsad422ed2016-11-02 14:20:04 +0000775 .frp_label_stack = next_hop_labels,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100776 };
777 fib_route_path_t *paths = NULL;
778
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100779 vec_add1(paths, path);
780
781 fib_entry_index =
782 fib_table_entry_update(fib_index, prefix, source, flags, paths);
783
784 vec_free(paths);
785
786 return (fib_entry_index);
787}
788
789static void
790fib_table_entry_delete_i (u32 fib_index,
791 fib_node_index_t fib_entry_index,
792 const fib_prefix_t *prefix,
793 fib_source_t source)
794{
795 fib_entry_src_flag_t src_flag;
796 fib_table_t *fib_table;
797 int was_sourced;
798
799 fib_table = fib_table_get(fib_index, prefix->fp_proto);
800 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
801
802 /*
803 * don't nobody go nowhere
804 */
805 fib_entry_lock(fib_entry_index);
806
807 src_flag = fib_entry_delete(fib_entry_index, source);
808
809 if (!(FIB_ENTRY_SRC_FLAG_ADDED & src_flag))
810 {
811 /*
812 * last source gone. remove from the table
813 */
814 fib_table_entry_remove(fib_table, prefix, fib_entry_index);
815
816 /*
817 * now the entry is no longer in the table, we can
818 * inform the entries that it covers to re-calculate their cover
819 */
820 fib_entry_cover_change_notify(fib_entry_index,
821 FIB_NODE_INDEX_INVALID);
822 }
823 /*
824 * else
825 * still has sources, leave it be.
826 */
827 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
828 {
829 fib_table->ft_src_route_counts[source]--;
830 }
831
832 fib_entry_unlock(fib_entry_index);
833}
834
835void
836fib_table_entry_delete (u32 fib_index,
837 const fib_prefix_t *prefix,
838 fib_source_t source)
839{
840 fib_node_index_t fib_entry_index;
841
842 fib_entry_index = fib_table_lookup_exact_match(fib_index, prefix);
843
844 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
845 {
846 /*
847 * removing an etry that does not exist.
848 * i'll allow it, but i won't like it.
849 */
Dave Barach59b25652017-09-10 15:04:27 -0400850 if (0)
851 clib_warning("%U not in FIB", format_fib_prefix, prefix);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100852 }
853 else
854 {
855 fib_table_entry_delete_i(fib_index, fib_entry_index, prefix, source);
856 }
857}
858
859void
860fib_table_entry_delete_index (fib_node_index_t fib_entry_index,
861 fib_source_t source)
862{
863 fib_prefix_t prefix;
864
865 fib_entry_get_prefix(fib_entry_index, &prefix);
866
867 fib_table_entry_delete_i(fib_entry_get_fib_index(fib_entry_index),
868 fib_entry_index, &prefix, source);
869}
870
871fib_node_index_t
872fib_table_entry_local_label_add (u32 fib_index,
873 const fib_prefix_t *prefix,
874 mpls_label_t label)
875{
876 fib_node_index_t fib_entry_index;
877
Neale Ranns1357f3b2016-10-16 12:01:42 -0700878 fib_entry_index = fib_table_lookup_exact_match(fib_index, prefix);
879
880 if (FIB_NODE_INDEX_INVALID == fib_entry_index ||
881 !fib_entry_is_sourced(fib_entry_index, FIB_SOURCE_MPLS))
882 {
883 /*
884 * only source the prefix once. this allows the label change
885 * operation to work
886 */
887 fib_entry_index = fib_table_entry_special_dpo_add(fib_index, prefix,
888 FIB_SOURCE_MPLS,
889 FIB_ENTRY_FLAG_NONE,
890 NULL);
891 }
892
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100893 fib_entry_set_source_data(fib_entry_index, FIB_SOURCE_MPLS, &label);
894
895 return (fib_entry_index);
896}
897
898void
899fib_table_entry_local_label_remove (u32 fib_index,
900 const fib_prefix_t *prefix,
901 mpls_label_t label)
902{
903 fib_node_index_t fib_entry_index;
904 const void *data;
905 mpls_label_t pl;
906
907 fib_entry_index = fib_table_lookup_exact_match(fib_index, prefix);
908
909 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
910 return;
911
912 data = fib_entry_get_source_data(fib_entry_index, FIB_SOURCE_MPLS);
913
914 if (NULL == data)
915 return;
916
917 pl = *(mpls_label_t*)data;
918
919 if (pl != label)
920 return;
921
922 pl = MPLS_LABEL_INVALID;
923
924 fib_entry_set_source_data(fib_entry_index, FIB_SOURCE_MPLS, &pl);
925 fib_table_entry_special_remove(fib_index,
926 prefix,
927 FIB_SOURCE_MPLS);
928}
929
930u32
931fib_table_get_index_for_sw_if_index (fib_protocol_t proto,
932 u32 sw_if_index)
933{
934 switch (proto)
935 {
936 case FIB_PROTOCOL_IP4:
937 return (ip4_fib_table_get_index_for_sw_if_index(sw_if_index));
938 case FIB_PROTOCOL_IP6:
939 return (ip6_fib_table_get_index_for_sw_if_index(sw_if_index));
940 case FIB_PROTOCOL_MPLS:
941 return (mpls_fib_table_get_index_for_sw_if_index(sw_if_index));
942 }
943 return (~0);
944}
945
946flow_hash_config_t
947fib_table_get_flow_hash_config (u32 fib_index,
948 fib_protocol_t proto)
949{
Neale Ranns227038a2017-04-21 01:07:59 -0700950 fib_table_t *fib;
951
952 fib = fib_table_get(fib_index, proto);
953
954 return (fib->ft_flow_hash_config);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100955}
Neale Rannsd792d9c2017-10-21 10:53:20 -0700956
Neale Ranns41da54f2017-05-02 10:15:19 -0700957flow_hash_config_t
958fib_table_get_default_flow_hash_config (fib_protocol_t proto)
959{
960 switch (proto)
961 {
962 case FIB_PROTOCOL_IP4:
963 case FIB_PROTOCOL_IP6:
964 return (IP_FLOW_HASH_DEFAULT);
965
966 case FIB_PROTOCOL_MPLS:
967 return (MPLS_FLOW_HASH_DEFAULT);
968 }
969
970 ASSERT(0);
971 return (IP_FLOW_HASH_DEFAULT);
972}
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100973
Neale Ranns227038a2017-04-21 01:07:59 -0700974/**
975 * @brief Table set flow hash config context.
976 */
977typedef struct fib_table_set_flow_hash_config_ctx_t_
978{
979 /**
980 * the flow hash config to set
981 */
982 flow_hash_config_t hash_config;
983} fib_table_set_flow_hash_config_ctx_t;
984
985static int
986fib_table_set_flow_hash_config_cb (fib_node_index_t fib_entry_index,
987 void *arg)
988{
989 fib_table_set_flow_hash_config_ctx_t *ctx = arg;
990
991 fib_entry_set_flow_hash_config(fib_entry_index, ctx->hash_config);
992
993 return (1);
994}
995
996void
997fib_table_set_flow_hash_config (u32 fib_index,
998 fib_protocol_t proto,
999 flow_hash_config_t hash_config)
1000{
1001 fib_table_set_flow_hash_config_ctx_t ctx = {
1002 .hash_config = hash_config,
1003 };
1004 fib_table_t *fib;
1005
1006 fib = fib_table_get(fib_index, proto);
1007 fib->ft_flow_hash_config = hash_config;
1008
1009 fib_table_walk(fib_index, proto,
1010 fib_table_set_flow_hash_config_cb,
1011 &ctx);
1012}
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001013
1014u32
1015fib_table_get_table_id_for_sw_if_index (fib_protocol_t proto,
1016 u32 sw_if_index)
1017{
1018 fib_table_t *fib_table;
1019
1020 fib_table = fib_table_get(fib_table_get_index_for_sw_if_index(
1021 proto, sw_if_index),
1022 proto);
1023
1024 return ((NULL != fib_table ? fib_table->ft_table_id : ~0));
1025}
1026
1027u32
1028fib_table_find (fib_protocol_t proto,
1029 u32 table_id)
1030{
1031 switch (proto)
1032 {
1033 case FIB_PROTOCOL_IP4:
1034 return (ip4_fib_index_from_table_id(table_id));
1035 case FIB_PROTOCOL_IP6:
1036 return (ip6_fib_index_from_table_id(table_id));
1037 case FIB_PROTOCOL_MPLS:
1038 return (mpls_fib_index_from_table_id(table_id));
1039 }
1040 return (~0);
1041}
1042
Neale Ranns2297af02017-09-12 09:45:04 -07001043static u32
1044fib_table_find_or_create_and_lock_i (fib_protocol_t proto,
1045 u32 table_id,
1046 fib_source_t src,
1047 const u8 *name)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001048{
1049 fib_table_t *fib_table;
1050 fib_node_index_t fi;
1051
1052 switch (proto)
1053 {
1054 case FIB_PROTOCOL_IP4:
Neale Ranns15002542017-09-10 04:39:11 -07001055 fi = ip4_fib_table_find_or_create_and_lock(table_id, src);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001056 break;
1057 case FIB_PROTOCOL_IP6:
Neale Ranns15002542017-09-10 04:39:11 -07001058 fi = ip6_fib_table_find_or_create_and_lock(table_id, src);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001059 break;
1060 case FIB_PROTOCOL_MPLS:
Neale Ranns15002542017-09-10 04:39:11 -07001061 fi = mpls_fib_table_find_or_create_and_lock(table_id, src);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001062 break;
1063 default:
1064 return (~0);
1065 }
1066
1067 fib_table = fib_table_get(fi, proto);
1068
Neale Ranns2297af02017-09-12 09:45:04 -07001069 if (NULL == fib_table->ft_desc)
1070 {
1071 if (name && name[0])
1072 {
1073 fib_table->ft_desc = format(NULL, "%s", name);
1074 }
1075 else
1076 {
1077 fib_table->ft_desc = format(NULL, "%U-VRF:%d",
1078 format_fib_protocol, proto,
1079 table_id);
1080 }
1081 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001082
1083 return (fi);
1084}
1085
1086u32
Neale Ranns2297af02017-09-12 09:45:04 -07001087fib_table_find_or_create_and_lock (fib_protocol_t proto,
1088 u32 table_id,
1089 fib_source_t src)
1090{
1091 return (fib_table_find_or_create_and_lock_i(proto, table_id,
1092 src, NULL));
1093}
1094
1095u32
1096fib_table_find_or_create_and_lock_w_name (fib_protocol_t proto,
1097 u32 table_id,
1098 fib_source_t src,
1099 const u8 *name)
1100{
1101 return (fib_table_find_or_create_and_lock_i(proto, table_id,
1102 src, name));
1103}
1104
1105u32
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001106fib_table_create_and_lock (fib_protocol_t proto,
Neale Ranns15002542017-09-10 04:39:11 -07001107 fib_source_t src,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001108 const char *const fmt,
1109 ...)
1110{
1111 fib_table_t *fib_table;
1112 fib_node_index_t fi;
1113 va_list ap;
1114
1115 va_start(ap, fmt);
1116
1117 switch (proto)
1118 {
1119 case FIB_PROTOCOL_IP4:
Neale Ranns15002542017-09-10 04:39:11 -07001120 fi = ip4_fib_table_create_and_lock(src);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001121 break;
1122 case FIB_PROTOCOL_IP6:
Neale Ranns15002542017-09-10 04:39:11 -07001123 fi = ip6_fib_table_create_and_lock(src);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001124 break;
1125 case FIB_PROTOCOL_MPLS:
Neale Ranns15002542017-09-10 04:39:11 -07001126 fi = mpls_fib_table_create_and_lock(src);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001127 break;
1128 default:
1129 return (~0);
1130 }
1131
1132 fib_table = fib_table_get(fi, proto);
1133
1134 fib_table->ft_desc = va_format(fib_table->ft_desc, fmt, &ap);
1135
1136 va_end(ap);
1137 return (fi);
1138}
1139
1140static void
1141fib_table_destroy (fib_table_t *fib_table)
1142{
1143 vec_free(fib_table->ft_desc);
1144
1145 switch (fib_table->ft_proto)
1146 {
1147 case FIB_PROTOCOL_IP4:
Neale Rannsa3af3372017-03-28 03:49:52 -07001148 ip4_fib_table_destroy(fib_table->ft_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001149 break;
1150 case FIB_PROTOCOL_IP6:
1151 ip6_fib_table_destroy(fib_table->ft_index);
1152 break;
1153 case FIB_PROTOCOL_MPLS:
Neale Rannsa3af3372017-03-28 03:49:52 -07001154 mpls_fib_table_destroy(fib_table->ft_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001155 break;
1156 }
1157}
Neale Ranns5a8123b2017-01-26 01:18:23 -08001158
Neale Ranns32e1c012016-11-22 17:07:28 +00001159void
1160fib_table_walk (u32 fib_index,
1161 fib_protocol_t proto,
1162 fib_table_walk_fn_t fn,
1163 void *ctx)
1164{
1165 switch (proto)
1166 {
1167 case FIB_PROTOCOL_IP4:
1168 ip4_fib_table_walk(ip4_fib_get(fib_index), fn, ctx);
1169 break;
1170 case FIB_PROTOCOL_IP6:
1171 ip6_fib_table_walk(fib_index, fn, ctx);
1172 break;
1173 case FIB_PROTOCOL_MPLS:
1174 mpls_fib_table_walk(mpls_fib_get(fib_index), fn, ctx);
1175 break;
1176 }
1177}
1178
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001179void
1180fib_table_unlock (u32 fib_index,
Neale Ranns15002542017-09-10 04:39:11 -07001181 fib_protocol_t proto,
1182 fib_source_t source)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001183{
1184 fib_table_t *fib_table;
1185
1186 fib_table = fib_table_get(fib_index, proto);
Neale Ranns15002542017-09-10 04:39:11 -07001187 fib_table->ft_locks[source]--;
1188 fib_table->ft_locks[FIB_TABLE_TOTAL_LOCKS]--;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001189
Neale Ranns15002542017-09-10 04:39:11 -07001190 if (0 == fib_table->ft_locks[source])
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001191 {
Neale Ranns15002542017-09-10 04:39:11 -07001192 /*
1193 * The source no longer needs the table. flush any routes
1194 * from it just in case
1195 */
1196 fib_table_flush(fib_index, proto, source);
1197 }
1198
1199 if (0 == fib_table->ft_locks[FIB_TABLE_TOTAL_LOCKS])
1200 {
1201 /*
1202 * no more locak from any source - kill it
1203 */
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001204 fib_table_destroy(fib_table);
1205 }
1206}
Neale Ranns15002542017-09-10 04:39:11 -07001207
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001208void
1209fib_table_lock (u32 fib_index,
Neale Ranns15002542017-09-10 04:39:11 -07001210 fib_protocol_t proto,
1211 fib_source_t source)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001212{
1213 fib_table_t *fib_table;
1214
1215 fib_table = fib_table_get(fib_index, proto);
Neale Ranns15002542017-09-10 04:39:11 -07001216 fib_table->ft_locks[source]++;
1217 fib_table->ft_locks[FIB_TABLE_TOTAL_LOCKS]++;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001218}
1219
1220u32
1221fib_table_get_num_entries (u32 fib_index,
1222 fib_protocol_t proto,
1223 fib_source_t source)
1224{
1225 fib_table_t *fib_table;
1226
1227 fib_table = fib_table_get(fib_index, proto);
1228
1229 return (fib_table->ft_src_route_counts[source]);
1230}
1231
1232u8*
Christophe Fontained3c008d2017-10-02 18:10:54 +02001233format_fib_table_name (u8* s, va_list* ap)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001234{
Christophe Fontained3c008d2017-10-02 18:10:54 +02001235 fib_node_index_t fib_index = va_arg(*ap, fib_node_index_t);
1236 fib_protocol_t proto = va_arg(*ap, int); // int promotion
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001237 fib_table_t *fib_table;
1238
1239 fib_table = fib_table_get(fib_index, proto);
1240
1241 s = format(s, "%v", fib_table->ft_desc);
1242
1243 return (s);
1244}
1245
Neale Ranns32e1c012016-11-22 17:07:28 +00001246/**
1247 * @brief Table flush context. Store the indicies of matching FIB entries
1248 * that need to be removed.
1249 */
1250typedef struct fib_table_flush_ctx_t_
1251{
1252 /**
1253 * The list of entries to flush
1254 */
1255 fib_node_index_t *ftf_entries;
1256
1257 /**
1258 * The source we are flushing
1259 */
1260 fib_source_t ftf_source;
1261} fib_table_flush_ctx_t;
1262
1263static int
1264fib_table_flush_cb (fib_node_index_t fib_entry_index,
1265 void *arg)
1266{
1267 fib_table_flush_ctx_t *ctx = arg;
1268
1269 if (fib_entry_is_sourced(fib_entry_index, ctx->ftf_source))
1270 {
1271 vec_add1(ctx->ftf_entries, fib_entry_index);
1272 }
1273 return (1);
1274}
1275
1276
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001277void
1278fib_table_flush (u32 fib_index,
1279 fib_protocol_t proto,
1280 fib_source_t source)
1281{
Neale Ranns32e1c012016-11-22 17:07:28 +00001282 fib_node_index_t *fib_entry_index;
1283 fib_table_flush_ctx_t ctx = {
1284 .ftf_entries = NULL,
1285 .ftf_source = source,
1286 };
1287
1288 fib_table_walk(fib_index, proto,
1289 fib_table_flush_cb,
1290 &ctx);
1291
1292 vec_foreach(fib_entry_index, ctx.ftf_entries)
1293 {
Neale Rannsa8d9f302017-02-20 09:17:02 -08001294 fib_table_entry_delete_index(*fib_entry_index, source);
Neale Ranns32e1c012016-11-22 17:07:28 +00001295 }
1296
1297 vec_free(ctx.ftf_entries);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001298}
Neale Rannsc87aafa2017-11-29 00:59:31 -08001299
1300u8 *
1301format_fib_table_memory (u8 *s, va_list *args)
1302{
1303 s = format(s, "%U", format_ip4_fib_table_memory);
1304 s = format(s, "%U", format_ip6_fib_table_memory);
1305 s = format(s, "%U", format_mpls_fib_table_memory);
1306
1307 return (s);
1308}