blob: d0bc33639b982bdb11e6a314ab0069d10857a47a [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 /*
Neale Ranns89541992017-04-06 04:41:02 -0700184 * find the covering entry
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100185 */
186 fib_entry_cover_index = fib_table_get_less_specific_i(fib_table, prefix);
187 /*
188 * the indicies are the same when the default route is first added
189 */
190 if (fib_entry_cover_index != fib_entry_index)
191 {
Neale Ranns89541992017-04-06 04:41:02 -0700192 /*
193 * push any inherting sources from the cover onto the covered
194 */
195 fib_entry_inherit(fib_entry_cover_index,
196 fib_entry_index);
197
198 /*
199 * inform the covering entry that a new more specific
200 * has been inserted beneath it
201 */
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100202 fib_entry_cover_change_notify(fib_entry_cover_index,
203 fib_entry_index);
204 }
205}
206
207static void
208fib_table_entry_insert (fib_table_t *fib_table,
209 const fib_prefix_t *prefix,
210 fib_node_index_t fib_entry_index)
211{
212 vlib_smp_unsafe_warning();
213
214 fib_entry_lock(fib_entry_index);
215 fib_table->ft_total_route_counts++;
216
217 switch (prefix->fp_proto)
218 {
219 case FIB_PROTOCOL_IP4:
Neale Rannsa3af3372017-03-28 03:49:52 -0700220 ip4_fib_table_entry_insert(ip4_fib_get(fib_table->ft_index),
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100221 &prefix->fp_addr.ip4,
222 prefix->fp_len,
223 fib_entry_index);
224 break;
225 case FIB_PROTOCOL_IP6:
226 ip6_fib_table_entry_insert(fib_table->ft_index,
227 &prefix->fp_addr.ip6,
228 prefix->fp_len,
229 fib_entry_index);
230 break;
231 case FIB_PROTOCOL_MPLS:
Neale Rannsa3af3372017-03-28 03:49:52 -0700232 mpls_fib_table_entry_insert(mpls_fib_get(fib_table->ft_index),
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100233 prefix->fp_label,
234 prefix->fp_eos,
235 fib_entry_index);
236 break;
237 }
238
239 fib_table_post_insert_actions(fib_table, prefix, fib_entry_index);
240}
241
242void
243fib_table_fwding_dpo_update (u32 fib_index,
244 const fib_prefix_t *prefix,
245 const dpo_id_t *dpo)
246{
247 vlib_smp_unsafe_warning();
248
249 switch (prefix->fp_proto)
250 {
251 case FIB_PROTOCOL_IP4:
252 return (ip4_fib_table_fwding_dpo_update(ip4_fib_get(fib_index),
253 &prefix->fp_addr.ip4,
254 prefix->fp_len,
255 dpo));
256 case FIB_PROTOCOL_IP6:
257 return (ip6_fib_table_fwding_dpo_update(fib_index,
258 &prefix->fp_addr.ip6,
259 prefix->fp_len,
260 dpo));
261 case FIB_PROTOCOL_MPLS:
262 return (mpls_fib_forwarding_table_update(mpls_fib_get(fib_index),
263 prefix->fp_label,
264 prefix->fp_eos,
265 dpo));
266 }
267}
268
269void
270fib_table_fwding_dpo_remove (u32 fib_index,
271 const fib_prefix_t *prefix,
272 const dpo_id_t *dpo)
273{
274 vlib_smp_unsafe_warning();
275
276 switch (prefix->fp_proto)
277 {
278 case FIB_PROTOCOL_IP4:
279 return (ip4_fib_table_fwding_dpo_remove(ip4_fib_get(fib_index),
280 &prefix->fp_addr.ip4,
281 prefix->fp_len,
Neale Rannsa3af3372017-03-28 03:49:52 -0700282 dpo,
283 fib_table_get_less_specific(fib_index,
284 prefix)));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100285 case FIB_PROTOCOL_IP6:
286 return (ip6_fib_table_fwding_dpo_remove(fib_index,
287 &prefix->fp_addr.ip6,
288 prefix->fp_len,
289 dpo));
290 case FIB_PROTOCOL_MPLS:
291 return (mpls_fib_forwarding_table_reset(mpls_fib_get(fib_index),
292 prefix->fp_label,
293 prefix->fp_eos));
294 }
295}
296
297
298fib_node_index_t
299fib_table_entry_special_dpo_add (u32 fib_index,
300 const fib_prefix_t *prefix,
301 fib_source_t source,
302 fib_entry_flag_t flags,
303 const dpo_id_t *dpo)
304{
305 fib_node_index_t fib_entry_index;
306 fib_table_t *fib_table;
307
308 fib_table = fib_table_get(fib_index, prefix->fp_proto);
309 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
310
311 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
312 {
313 fib_entry_index = fib_entry_create_special(fib_index, prefix,
314 source, flags,
315 dpo);
316
317 fib_table_entry_insert(fib_table, prefix, fib_entry_index);
318 fib_table->ft_src_route_counts[source]++;
319 }
320 else
321 {
322 int was_sourced;
323
324 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
325 fib_entry_special_add(fib_entry_index, source, flags, dpo);
326
327 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
328 {
329 fib_table->ft_src_route_counts[source]++;
330 }
331 }
332
333
334 return (fib_entry_index);
335}
336
337fib_node_index_t
Neale Ranns948e00f2016-10-20 13:39:34 +0100338fib_table_entry_special_dpo_update (u32 fib_index,
339 const fib_prefix_t *prefix,
340 fib_source_t source,
341 fib_entry_flag_t flags,
342 const dpo_id_t *dpo)
343{
344 fib_node_index_t fib_entry_index;
345 fib_table_t *fib_table;
346
347 fib_table = fib_table_get(fib_index, prefix->fp_proto);
348 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
349
350 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
351 {
352 fib_entry_index = fib_entry_create_special(fib_index, prefix,
353 source, flags,
354 dpo);
355
356 fib_table_entry_insert(fib_table, prefix, fib_entry_index);
357 fib_table->ft_src_route_counts[source]++;
358 }
359 else
360 {
361 int was_sourced;
362
363 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
364
365 if (was_sourced)
366 fib_entry_special_update(fib_entry_index, source, flags, dpo);
367 else
368 fib_entry_special_add(fib_entry_index, source, flags, dpo);
369
370 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
371 {
372 fib_table->ft_src_route_counts[source]++;
373 }
374 }
375
376 return (fib_entry_index);
377}
378
379fib_node_index_t
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100380fib_table_entry_special_add (u32 fib_index,
381 const fib_prefix_t *prefix,
382 fib_source_t source,
Neale Rannsa0558302017-04-13 00:44:52 -0700383 fib_entry_flag_t flags)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100384{
385 fib_node_index_t fib_entry_index;
Neale Ranns948e00f2016-10-20 13:39:34 +0100386 dpo_id_t tmp_dpo = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100387
Neale Rannsa0558302017-04-13 00:44:52 -0700388 dpo_copy(&tmp_dpo, drop_dpo_get(fib_proto_to_dpo(prefix->fp_proto)));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100389
390 fib_entry_index = fib_table_entry_special_dpo_add(fib_index, prefix, source,
391 flags, &tmp_dpo);
392
393 dpo_unlock(&tmp_dpo);
394
395 return (fib_entry_index);
396}
397
398void
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100399fib_table_entry_special_remove (u32 fib_index,
400 const fib_prefix_t *prefix,
401 fib_source_t source)
402{
403 /*
404 * 1 is it present
405 * yes => remove source
406 * 2 - is it still sourced?
407 * no => cover walk
408 */
409 fib_node_index_t fib_entry_index;
410 fib_table_t *fib_table;
411
412 fib_table = fib_table_get(fib_index, prefix->fp_proto);
413 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
414
415 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
416 {
417 /*
418 * removing an etry that does not exist. i'll allow it.
419 */
420 }
421 else
422 {
423 fib_entry_src_flag_t src_flag;
424 int was_sourced;
425
426 /*
427 * don't nobody go nowhere
428 */
429 fib_entry_lock(fib_entry_index);
430 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
431
432 src_flag = fib_entry_special_remove(fib_entry_index, source);
433
434 if (!(FIB_ENTRY_SRC_FLAG_ADDED & src_flag))
435 {
436 /*
437 * last source gone. remove from the table
438 */
439 fib_table_entry_remove(fib_table, prefix, fib_entry_index);
440
441 /*
442 * now the entry is no longer in the table, we can
443 * inform the entries that it covers to re-calculate their cover
444 */
445 fib_entry_cover_change_notify(fib_entry_index,
446 FIB_NODE_INDEX_INVALID);
447 }
448 /*
449 * else
450 * still has sources, leave it be.
451 */
452 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
453 {
454 fib_table->ft_src_route_counts[source]--;
455 }
456
457 fib_entry_unlock(fib_entry_index);
458 }
459}
460
461/**
462 * fib_table_route_path_fixup
463 *
464 * Convert attached hosts to attached next-hops.
465 *
466 * This special case is required because an attached path will link to a
467 * glean, and the FIB entry will have the interface or API/CLI source. When
468 * the ARP/ND process is completes then that source (which will provide a
469 * complete adjacency) will be lower priority and so the FIB entry will
470 * remain linked to a glean and traffic will never reach the hosts. For
471 * an ATTAHCED_HOST path we can link the path directly to the [incomplete]
472 * adjacency.
473 */
474static void
475fib_table_route_path_fixup (const fib_prefix_t *prefix,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800476 fib_entry_flag_t eflags,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100477 fib_route_path_t *path)
478{
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800479 /*
480 * not all zeros next hop &&
481 * is recursive path &&
482 * nexthop is same as the route's address
483 */
484 if ((!ip46_address_is_zero(&path->frp_addr)) &&
485 (~0 == path->frp_sw_if_index) &&
486 (0 == ip46_address_cmp(&path->frp_addr, &prefix->fp_addr)))
487 {
488 /* Prefix recurses via itse;f */
489 path->frp_flags |= FIB_ROUTE_PATH_DROP;
490 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100491 if (fib_prefix_is_host(prefix) &&
492 ip46_address_is_zero(&path->frp_addr) &&
Neale Ranns6f631152017-10-03 08:20:21 -0700493 path->frp_sw_if_index != ~0 &&
494 path->frp_proto != DPO_PROTO_ETHERNET)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100495 {
496 path->frp_addr = prefix->fp_addr;
Neale Ranns4b919a52017-03-11 05:55:21 -0800497 path->frp_flags |= FIB_ROUTE_PATH_ATTACHED;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100498 }
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800499 if (eflags & FIB_ENTRY_FLAG_DROP)
500 {
501 path->frp_flags |= FIB_ROUTE_PATH_DROP;
502 }
503 if (eflags & FIB_ENTRY_FLAG_LOCAL)
504 {
505 path->frp_flags |= FIB_ROUTE_PATH_LOCAL;
506 }
507 if (eflags & FIB_ENTRY_FLAG_EXCLUSIVE)
508 {
509 path->frp_flags |= FIB_ROUTE_PATH_EXCLUSIVE;
510 }
511}
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100512
513fib_node_index_t
514fib_table_entry_path_add (u32 fib_index,
515 const fib_prefix_t *prefix,
516 fib_source_t source,
517 fib_entry_flag_t flags,
Neale Rannsda78f952017-05-24 09:15:43 -0700518 dpo_proto_t next_hop_proto,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100519 const ip46_address_t *next_hop,
520 u32 next_hop_sw_if_index,
521 u32 next_hop_fib_index,
522 u32 next_hop_weight,
Neale Ranns31ed7442018-02-23 05:29:09 -0800523 fib_mpls_label_t *next_hop_labels,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100524 fib_route_path_flags_t path_flags)
525{
526 fib_route_path_t path = {
527 .frp_proto = next_hop_proto,
528 .frp_addr = (NULL == next_hop? zero_addr : *next_hop),
529 .frp_sw_if_index = next_hop_sw_if_index,
530 .frp_fib_index = next_hop_fib_index,
531 .frp_weight = next_hop_weight,
532 .frp_flags = path_flags,
Neale Rannsad422ed2016-11-02 14:20:04 +0000533 .frp_label_stack = next_hop_labels,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100534 };
535 fib_node_index_t fib_entry_index;
536 fib_route_path_t *paths = NULL;
537
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100538 vec_add1(paths, path);
539
540 fib_entry_index = fib_table_entry_path_add2(fib_index, prefix,
541 source, flags, paths);
542
543 vec_free(paths);
544 return (fib_entry_index);
545}
546
547fib_node_index_t
548fib_table_entry_path_add2 (u32 fib_index,
549 const fib_prefix_t *prefix,
550 fib_source_t source,
551 fib_entry_flag_t flags,
Neale Rannsad422ed2016-11-02 14:20:04 +0000552 fib_route_path_t *rpath)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100553{
554 fib_node_index_t fib_entry_index;
555 fib_table_t *fib_table;
Neale Rannsad422ed2016-11-02 14:20:04 +0000556 u32 ii;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100557
558 fib_table = fib_table_get(fib_index, prefix->fp_proto);
559 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
560
Neale Rannsad422ed2016-11-02 14:20:04 +0000561 for (ii = 0; ii < vec_len(rpath); ii++)
562 {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800563 fib_table_route_path_fixup(prefix, flags, &rpath[ii]);
Neale Rannsad422ed2016-11-02 14:20:04 +0000564 }
565
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100566 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
567 {
568 fib_entry_index = fib_entry_create(fib_index, prefix,
569 source, flags,
570 rpath);
571
572 fib_table_entry_insert(fib_table, prefix, fib_entry_index);
573 fib_table->ft_src_route_counts[source]++;
574 }
575 else
576 {
577 int was_sourced;
578
579 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
580 fib_entry_path_add(fib_entry_index, source, flags, rpath);;
581
582 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
583 {
584 fib_table->ft_src_route_counts[source]++;
585 }
586 }
587
588 return (fib_entry_index);
589}
590
591void
592fib_table_entry_path_remove2 (u32 fib_index,
Neale Rannsad422ed2016-11-02 14:20:04 +0000593 const fib_prefix_t *prefix,
594 fib_source_t source,
595 fib_route_path_t *rpath)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100596{
597 /*
598 * 1 is it present
599 * yes => remove source
600 * 2 - is it still sourced?
601 * no => cover walk
602 */
603 fib_node_index_t fib_entry_index;
604 fib_table_t *fib_table;
Neale Rannsad422ed2016-11-02 14:20:04 +0000605 u32 ii;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100606
607 fib_table = fib_table_get(fib_index, prefix->fp_proto);
608 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
609
610 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
611 {
612 /*
613 * removing an etry that does not exist. i'll allow it.
614 */
615 }
616 else
617 {
618 fib_entry_src_flag_t src_flag;
619 int was_sourced;
620
Neale Rannsf12a83f2017-04-18 09:09:40 -0700621 /*
622 * if it's not sourced, then there's nowt to remove
623 */
624 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
625 if (!was_sourced)
626 {
627 return;
628 }
629
630 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100631 * don't nobody go nowhere
632 */
633 fib_entry_lock(fib_entry_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100634
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800635 for (ii = 0; ii < vec_len(rpath); ii++)
636 {
637 fib_table_route_path_fixup(
638 prefix,
639 fib_entry_get_flags_for_source(fib_entry_index,
640 source),
641 &rpath[ii]);
642 }
643
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100644 src_flag = fib_entry_path_remove(fib_entry_index, source, rpath);
645
646 if (!(FIB_ENTRY_SRC_FLAG_ADDED & src_flag))
647 {
648 /*
649 * last source gone. remove from the table
650 */
651 fib_table_entry_remove(fib_table, prefix, fib_entry_index);
652
653 /*
654 * now the entry is no longer in the table, we can
655 * inform the entries that it covers to re-calculate their cover
656 */
657 fib_entry_cover_change_notify(fib_entry_index,
658 FIB_NODE_INDEX_INVALID);
659 }
660 /*
661 * else
662 * still has sources, leave it be.
663 */
664 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
665 {
666 fib_table->ft_src_route_counts[source]--;
667 }
668
669 fib_entry_unlock(fib_entry_index);
670 }
671}
672
673void
674fib_table_entry_path_remove (u32 fib_index,
675 const fib_prefix_t *prefix,
676 fib_source_t source,
Neale Rannsda78f952017-05-24 09:15:43 -0700677 dpo_proto_t next_hop_proto,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100678 const ip46_address_t *next_hop,
679 u32 next_hop_sw_if_index,
680 u32 next_hop_fib_index,
681 u32 next_hop_weight,
682 fib_route_path_flags_t path_flags)
683{
684 /*
685 * 1 is it present
686 * yes => remove source
687 * 2 - is it still sourced?
688 * no => cover walk
689 */
690 fib_route_path_t path = {
691 .frp_proto = next_hop_proto,
692 .frp_addr = (NULL == next_hop? zero_addr : *next_hop),
693 .frp_sw_if_index = next_hop_sw_if_index,
694 .frp_fib_index = next_hop_fib_index,
695 .frp_weight = next_hop_weight,
696 .frp_flags = path_flags,
697 };
698 fib_route_path_t *paths = NULL;
699
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100700 vec_add1(paths, path);
701
702 fib_table_entry_path_remove2(fib_index, prefix, source, paths);
703
704 vec_free(paths);
705}
706
707static int
708fib_route_path_cmp_for_sort (void * v1,
709 void * v2)
710{
711 return (fib_route_path_cmp(v1, v2));
712}
713
714fib_node_index_t
715fib_table_entry_update (u32 fib_index,
716 const fib_prefix_t *prefix,
717 fib_source_t source,
718 fib_entry_flag_t flags,
Neale Rannsad422ed2016-11-02 14:20:04 +0000719 fib_route_path_t *paths)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100720{
721 fib_node_index_t fib_entry_index;
722 fib_table_t *fib_table;
Neale Rannsad422ed2016-11-02 14:20:04 +0000723 u32 ii;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100724
725 fib_table = fib_table_get(fib_index, prefix->fp_proto);
726 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
727
Neale Rannsad422ed2016-11-02 14:20:04 +0000728 for (ii = 0; ii < vec_len(paths); ii++)
729 {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800730 fib_table_route_path_fixup(prefix, flags, &paths[ii]);
Neale Rannsad422ed2016-11-02 14:20:04 +0000731 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100732 /*
733 * sort the paths provided by the control plane. this means
734 * the paths and the extension on the entry will be sorted.
735 */
Neale Rannsad422ed2016-11-02 14:20:04 +0000736 vec_sort_with_function(paths, fib_route_path_cmp_for_sort);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100737
738 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
739 {
740 fib_entry_index = fib_entry_create(fib_index, prefix,
741 source, flags,
742 paths);
743
744 fib_table_entry_insert(fib_table, prefix, fib_entry_index);
745 fib_table->ft_src_route_counts[source]++;
746 }
747 else
748 {
749 int was_sourced;
750
751 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
752 fib_entry_update(fib_entry_index, source, flags, paths);
753
754 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
755 {
756 fib_table->ft_src_route_counts[source]++;
757 }
758 }
759
760 return (fib_entry_index);
761}
762
763fib_node_index_t
764fib_table_entry_update_one_path (u32 fib_index,
765 const fib_prefix_t *prefix,
766 fib_source_t source,
767 fib_entry_flag_t flags,
Neale Rannsda78f952017-05-24 09:15:43 -0700768 dpo_proto_t next_hop_proto,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100769 const ip46_address_t *next_hop,
770 u32 next_hop_sw_if_index,
771 u32 next_hop_fib_index,
772 u32 next_hop_weight,
Neale Ranns31ed7442018-02-23 05:29:09 -0800773 fib_mpls_label_t *next_hop_labels,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100774 fib_route_path_flags_t path_flags)
775{
776 fib_node_index_t fib_entry_index;
777 fib_route_path_t path = {
778 .frp_proto = next_hop_proto,
779 .frp_addr = (NULL == next_hop? zero_addr : *next_hop),
780 .frp_sw_if_index = next_hop_sw_if_index,
781 .frp_fib_index = next_hop_fib_index,
782 .frp_weight = next_hop_weight,
783 .frp_flags = path_flags,
Neale Rannsad422ed2016-11-02 14:20:04 +0000784 .frp_label_stack = next_hop_labels,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100785 };
786 fib_route_path_t *paths = NULL;
787
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100788 vec_add1(paths, path);
789
790 fib_entry_index =
791 fib_table_entry_update(fib_index, prefix, source, flags, paths);
792
793 vec_free(paths);
794
795 return (fib_entry_index);
796}
797
798static void
799fib_table_entry_delete_i (u32 fib_index,
800 fib_node_index_t fib_entry_index,
801 const fib_prefix_t *prefix,
802 fib_source_t source)
803{
804 fib_entry_src_flag_t src_flag;
805 fib_table_t *fib_table;
806 int was_sourced;
807
808 fib_table = fib_table_get(fib_index, prefix->fp_proto);
809 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
810
811 /*
812 * don't nobody go nowhere
813 */
814 fib_entry_lock(fib_entry_index);
815
816 src_flag = fib_entry_delete(fib_entry_index, source);
817
818 if (!(FIB_ENTRY_SRC_FLAG_ADDED & src_flag))
819 {
820 /*
821 * last source gone. remove from the table
822 */
823 fib_table_entry_remove(fib_table, prefix, fib_entry_index);
824
825 /*
826 * now the entry is no longer in the table, we can
827 * inform the entries that it covers to re-calculate their cover
828 */
829 fib_entry_cover_change_notify(fib_entry_index,
830 FIB_NODE_INDEX_INVALID);
831 }
832 /*
833 * else
834 * still has sources, leave it be.
835 */
836 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
837 {
838 fib_table->ft_src_route_counts[source]--;
839 }
840
841 fib_entry_unlock(fib_entry_index);
842}
843
844void
845fib_table_entry_delete (u32 fib_index,
846 const fib_prefix_t *prefix,
847 fib_source_t source)
848{
849 fib_node_index_t fib_entry_index;
850
851 fib_entry_index = fib_table_lookup_exact_match(fib_index, prefix);
852
853 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
854 {
855 /*
856 * removing an etry that does not exist.
857 * i'll allow it, but i won't like it.
858 */
Dave Barach59b25652017-09-10 15:04:27 -0400859 if (0)
860 clib_warning("%U not in FIB", format_fib_prefix, prefix);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100861 }
862 else
863 {
864 fib_table_entry_delete_i(fib_index, fib_entry_index, prefix, source);
865 }
866}
867
868void
869fib_table_entry_delete_index (fib_node_index_t fib_entry_index,
870 fib_source_t source)
871{
872 fib_prefix_t prefix;
873
874 fib_entry_get_prefix(fib_entry_index, &prefix);
875
876 fib_table_entry_delete_i(fib_entry_get_fib_index(fib_entry_index),
877 fib_entry_index, &prefix, source);
878}
879
880fib_node_index_t
881fib_table_entry_local_label_add (u32 fib_index,
882 const fib_prefix_t *prefix,
883 mpls_label_t label)
884{
885 fib_node_index_t fib_entry_index;
886
Neale Ranns1357f3b2016-10-16 12:01:42 -0700887 fib_entry_index = fib_table_lookup_exact_match(fib_index, prefix);
888
889 if (FIB_NODE_INDEX_INVALID == fib_entry_index ||
890 !fib_entry_is_sourced(fib_entry_index, FIB_SOURCE_MPLS))
891 {
892 /*
893 * only source the prefix once. this allows the label change
894 * operation to work
895 */
896 fib_entry_index = fib_table_entry_special_dpo_add(fib_index, prefix,
897 FIB_SOURCE_MPLS,
898 FIB_ENTRY_FLAG_NONE,
899 NULL);
900 }
901
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100902 fib_entry_set_source_data(fib_entry_index, FIB_SOURCE_MPLS, &label);
903
904 return (fib_entry_index);
905}
906
907void
908fib_table_entry_local_label_remove (u32 fib_index,
909 const fib_prefix_t *prefix,
910 mpls_label_t label)
911{
912 fib_node_index_t fib_entry_index;
913 const void *data;
914 mpls_label_t pl;
915
916 fib_entry_index = fib_table_lookup_exact_match(fib_index, prefix);
917
918 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
919 return;
920
921 data = fib_entry_get_source_data(fib_entry_index, FIB_SOURCE_MPLS);
922
923 if (NULL == data)
924 return;
925
926 pl = *(mpls_label_t*)data;
927
928 if (pl != label)
929 return;
930
931 pl = MPLS_LABEL_INVALID;
932
933 fib_entry_set_source_data(fib_entry_index, FIB_SOURCE_MPLS, &pl);
934 fib_table_entry_special_remove(fib_index,
935 prefix,
936 FIB_SOURCE_MPLS);
937}
938
939u32
940fib_table_get_index_for_sw_if_index (fib_protocol_t proto,
941 u32 sw_if_index)
942{
943 switch (proto)
944 {
945 case FIB_PROTOCOL_IP4:
946 return (ip4_fib_table_get_index_for_sw_if_index(sw_if_index));
947 case FIB_PROTOCOL_IP6:
948 return (ip6_fib_table_get_index_for_sw_if_index(sw_if_index));
949 case FIB_PROTOCOL_MPLS:
950 return (mpls_fib_table_get_index_for_sw_if_index(sw_if_index));
951 }
952 return (~0);
953}
954
955flow_hash_config_t
956fib_table_get_flow_hash_config (u32 fib_index,
957 fib_protocol_t proto)
958{
Neale Ranns227038a2017-04-21 01:07:59 -0700959 fib_table_t *fib;
960
961 fib = fib_table_get(fib_index, proto);
962
963 return (fib->ft_flow_hash_config);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100964}
Neale Rannsd792d9c2017-10-21 10:53:20 -0700965
Neale Ranns41da54f2017-05-02 10:15:19 -0700966flow_hash_config_t
967fib_table_get_default_flow_hash_config (fib_protocol_t proto)
968{
969 switch (proto)
970 {
971 case FIB_PROTOCOL_IP4:
972 case FIB_PROTOCOL_IP6:
973 return (IP_FLOW_HASH_DEFAULT);
974
975 case FIB_PROTOCOL_MPLS:
976 return (MPLS_FLOW_HASH_DEFAULT);
977 }
978
979 ASSERT(0);
980 return (IP_FLOW_HASH_DEFAULT);
981}
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100982
Neale Ranns227038a2017-04-21 01:07:59 -0700983/**
984 * @brief Table set flow hash config context.
985 */
986typedef struct fib_table_set_flow_hash_config_ctx_t_
987{
988 /**
989 * the flow hash config to set
990 */
991 flow_hash_config_t hash_config;
992} fib_table_set_flow_hash_config_ctx_t;
993
Neale Ranns89541992017-04-06 04:41:02 -0700994static fib_table_walk_rc_t
Neale Ranns227038a2017-04-21 01:07:59 -0700995fib_table_set_flow_hash_config_cb (fib_node_index_t fib_entry_index,
996 void *arg)
997{
998 fib_table_set_flow_hash_config_ctx_t *ctx = arg;
999
1000 fib_entry_set_flow_hash_config(fib_entry_index, ctx->hash_config);
1001
Neale Ranns89541992017-04-06 04:41:02 -07001002 return (FIB_TABLE_WALK_CONTINUE);
Neale Ranns227038a2017-04-21 01:07:59 -07001003}
1004
1005void
1006fib_table_set_flow_hash_config (u32 fib_index,
1007 fib_protocol_t proto,
1008 flow_hash_config_t hash_config)
1009{
1010 fib_table_set_flow_hash_config_ctx_t ctx = {
1011 .hash_config = hash_config,
1012 };
1013 fib_table_t *fib;
1014
1015 fib = fib_table_get(fib_index, proto);
1016 fib->ft_flow_hash_config = hash_config;
1017
1018 fib_table_walk(fib_index, proto,
1019 fib_table_set_flow_hash_config_cb,
1020 &ctx);
1021}
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001022
1023u32
1024fib_table_get_table_id_for_sw_if_index (fib_protocol_t proto,
1025 u32 sw_if_index)
1026{
1027 fib_table_t *fib_table;
1028
1029 fib_table = fib_table_get(fib_table_get_index_for_sw_if_index(
1030 proto, sw_if_index),
1031 proto);
1032
1033 return ((NULL != fib_table ? fib_table->ft_table_id : ~0));
1034}
1035
1036u32
Neale Ranns25b04942018-04-04 09:34:50 -07001037fib_table_get_table_id (u32 fib_index,
1038 fib_protocol_t proto)
1039{
1040 fib_table_t *fib_table;
1041
1042 fib_table = fib_table_get(fib_index, proto);
1043
1044 return ((NULL != fib_table ? fib_table->ft_table_id : ~0));
1045}
1046
1047u32
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001048fib_table_find (fib_protocol_t proto,
1049 u32 table_id)
1050{
1051 switch (proto)
1052 {
1053 case FIB_PROTOCOL_IP4:
1054 return (ip4_fib_index_from_table_id(table_id));
1055 case FIB_PROTOCOL_IP6:
1056 return (ip6_fib_index_from_table_id(table_id));
1057 case FIB_PROTOCOL_MPLS:
1058 return (mpls_fib_index_from_table_id(table_id));
1059 }
1060 return (~0);
1061}
1062
Neale Ranns2297af02017-09-12 09:45:04 -07001063static u32
1064fib_table_find_or_create_and_lock_i (fib_protocol_t proto,
1065 u32 table_id,
1066 fib_source_t src,
1067 const u8 *name)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001068{
1069 fib_table_t *fib_table;
1070 fib_node_index_t fi;
1071
1072 switch (proto)
1073 {
1074 case FIB_PROTOCOL_IP4:
Neale Ranns15002542017-09-10 04:39:11 -07001075 fi = ip4_fib_table_find_or_create_and_lock(table_id, src);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001076 break;
1077 case FIB_PROTOCOL_IP6:
Neale Ranns15002542017-09-10 04:39:11 -07001078 fi = ip6_fib_table_find_or_create_and_lock(table_id, src);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001079 break;
1080 case FIB_PROTOCOL_MPLS:
Neale Ranns15002542017-09-10 04:39:11 -07001081 fi = mpls_fib_table_find_or_create_and_lock(table_id, src);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001082 break;
1083 default:
1084 return (~0);
1085 }
1086
1087 fib_table = fib_table_get(fi, proto);
1088
Neale Ranns2297af02017-09-12 09:45:04 -07001089 if (NULL == fib_table->ft_desc)
1090 {
1091 if (name && name[0])
1092 {
1093 fib_table->ft_desc = format(NULL, "%s", name);
1094 }
1095 else
1096 {
1097 fib_table->ft_desc = format(NULL, "%U-VRF:%d",
1098 format_fib_protocol, proto,
1099 table_id);
1100 }
1101 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001102
1103 return (fi);
1104}
1105
1106u32
Neale Ranns2297af02017-09-12 09:45:04 -07001107fib_table_find_or_create_and_lock (fib_protocol_t proto,
1108 u32 table_id,
1109 fib_source_t src)
1110{
1111 return (fib_table_find_or_create_and_lock_i(proto, table_id,
1112 src, NULL));
1113}
1114
1115u32
1116fib_table_find_or_create_and_lock_w_name (fib_protocol_t proto,
1117 u32 table_id,
1118 fib_source_t src,
1119 const u8 *name)
1120{
1121 return (fib_table_find_or_create_and_lock_i(proto, table_id,
1122 src, name));
1123}
1124
1125u32
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001126fib_table_create_and_lock (fib_protocol_t proto,
Neale Ranns15002542017-09-10 04:39:11 -07001127 fib_source_t src,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001128 const char *const fmt,
1129 ...)
1130{
1131 fib_table_t *fib_table;
1132 fib_node_index_t fi;
1133 va_list ap;
1134
1135 va_start(ap, fmt);
1136
1137 switch (proto)
1138 {
1139 case FIB_PROTOCOL_IP4:
Neale Ranns15002542017-09-10 04:39:11 -07001140 fi = ip4_fib_table_create_and_lock(src);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001141 break;
1142 case FIB_PROTOCOL_IP6:
Neale Ranns53da2212018-02-24 02:11:19 -08001143 fi = ip6_fib_table_create_and_lock(src, FIB_TABLE_FLAG_NONE, NULL);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001144 break;
1145 case FIB_PROTOCOL_MPLS:
Neale Ranns15002542017-09-10 04:39:11 -07001146 fi = mpls_fib_table_create_and_lock(src);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001147 break;
1148 default:
1149 return (~0);
1150 }
1151
1152 fib_table = fib_table_get(fi, proto);
1153
1154 fib_table->ft_desc = va_format(fib_table->ft_desc, fmt, &ap);
1155
1156 va_end(ap);
1157 return (fi);
1158}
1159
1160static void
1161fib_table_destroy (fib_table_t *fib_table)
1162{
1163 vec_free(fib_table->ft_desc);
1164
1165 switch (fib_table->ft_proto)
1166 {
1167 case FIB_PROTOCOL_IP4:
Neale Rannsa3af3372017-03-28 03:49:52 -07001168 ip4_fib_table_destroy(fib_table->ft_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001169 break;
1170 case FIB_PROTOCOL_IP6:
1171 ip6_fib_table_destroy(fib_table->ft_index);
1172 break;
1173 case FIB_PROTOCOL_MPLS:
Neale Rannsa3af3372017-03-28 03:49:52 -07001174 mpls_fib_table_destroy(fib_table->ft_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001175 break;
1176 }
1177}
Neale Ranns5a8123b2017-01-26 01:18:23 -08001178
Neale Ranns32e1c012016-11-22 17:07:28 +00001179void
1180fib_table_walk (u32 fib_index,
1181 fib_protocol_t proto,
1182 fib_table_walk_fn_t fn,
1183 void *ctx)
1184{
1185 switch (proto)
1186 {
1187 case FIB_PROTOCOL_IP4:
1188 ip4_fib_table_walk(ip4_fib_get(fib_index), fn, ctx);
1189 break;
1190 case FIB_PROTOCOL_IP6:
1191 ip6_fib_table_walk(fib_index, fn, ctx);
1192 break;
1193 case FIB_PROTOCOL_MPLS:
1194 mpls_fib_table_walk(mpls_fib_get(fib_index), fn, ctx);
1195 break;
1196 }
1197}
1198
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001199void
Neale Ranns89541992017-04-06 04:41:02 -07001200fib_table_sub_tree_walk (u32 fib_index,
1201 fib_protocol_t proto,
1202 const fib_prefix_t *root,
1203 fib_table_walk_fn_t fn,
1204 void *ctx)
1205{
1206 switch (proto)
1207 {
1208 case FIB_PROTOCOL_IP4:
1209 ip4_fib_table_sub_tree_walk(ip4_fib_get(fib_index), root, fn, ctx);
1210 break;
1211 case FIB_PROTOCOL_IP6:
1212 ip6_fib_table_sub_tree_walk(fib_index, root, fn, ctx);
1213 break;
1214 case FIB_PROTOCOL_MPLS:
1215 break;
1216 }
1217}
1218
1219void
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001220fib_table_unlock (u32 fib_index,
Neale Ranns15002542017-09-10 04:39:11 -07001221 fib_protocol_t proto,
1222 fib_source_t source)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001223{
1224 fib_table_t *fib_table;
1225
1226 fib_table = fib_table_get(fib_index, proto);
Neale Ranns15002542017-09-10 04:39:11 -07001227 fib_table->ft_locks[source]--;
1228 fib_table->ft_locks[FIB_TABLE_TOTAL_LOCKS]--;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001229
Neale Ranns15002542017-09-10 04:39:11 -07001230 if (0 == fib_table->ft_locks[source])
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001231 {
Neale Ranns15002542017-09-10 04:39:11 -07001232 /*
1233 * The source no longer needs the table. flush any routes
1234 * from it just in case
1235 */
1236 fib_table_flush(fib_index, proto, source);
1237 }
1238
1239 if (0 == fib_table->ft_locks[FIB_TABLE_TOTAL_LOCKS])
1240 {
1241 /*
1242 * no more locak from any source - kill it
1243 */
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001244 fib_table_destroy(fib_table);
1245 }
1246}
Neale Ranns15002542017-09-10 04:39:11 -07001247
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001248void
1249fib_table_lock (u32 fib_index,
Neale Ranns15002542017-09-10 04:39:11 -07001250 fib_protocol_t proto,
1251 fib_source_t source)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001252{
1253 fib_table_t *fib_table;
1254
1255 fib_table = fib_table_get(fib_index, proto);
Neale Ranns15002542017-09-10 04:39:11 -07001256 fib_table->ft_locks[source]++;
1257 fib_table->ft_locks[FIB_TABLE_TOTAL_LOCKS]++;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001258}
1259
1260u32
1261fib_table_get_num_entries (u32 fib_index,
1262 fib_protocol_t proto,
1263 fib_source_t source)
1264{
1265 fib_table_t *fib_table;
1266
1267 fib_table = fib_table_get(fib_index, proto);
1268
1269 return (fib_table->ft_src_route_counts[source]);
1270}
1271
1272u8*
Christophe Fontained3c008d2017-10-02 18:10:54 +02001273format_fib_table_name (u8* s, va_list* ap)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001274{
Christophe Fontained3c008d2017-10-02 18:10:54 +02001275 fib_node_index_t fib_index = va_arg(*ap, fib_node_index_t);
1276 fib_protocol_t proto = va_arg(*ap, int); // int promotion
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001277 fib_table_t *fib_table;
1278
1279 fib_table = fib_table_get(fib_index, proto);
1280
1281 s = format(s, "%v", fib_table->ft_desc);
1282
1283 return (s);
1284}
1285
Neale Ranns32e1c012016-11-22 17:07:28 +00001286/**
1287 * @brief Table flush context. Store the indicies of matching FIB entries
1288 * that need to be removed.
1289 */
1290typedef struct fib_table_flush_ctx_t_
1291{
1292 /**
1293 * The list of entries to flush
1294 */
1295 fib_node_index_t *ftf_entries;
1296
1297 /**
1298 * The source we are flushing
1299 */
1300 fib_source_t ftf_source;
1301} fib_table_flush_ctx_t;
1302
Neale Ranns89541992017-04-06 04:41:02 -07001303static fib_table_walk_rc_t
Neale Ranns32e1c012016-11-22 17:07:28 +00001304fib_table_flush_cb (fib_node_index_t fib_entry_index,
1305 void *arg)
1306{
1307 fib_table_flush_ctx_t *ctx = arg;
1308
1309 if (fib_entry_is_sourced(fib_entry_index, ctx->ftf_source))
1310 {
1311 vec_add1(ctx->ftf_entries, fib_entry_index);
1312 }
Neale Ranns89541992017-04-06 04:41:02 -07001313 return (FIB_TABLE_WALK_CONTINUE);
Neale Ranns32e1c012016-11-22 17:07:28 +00001314}
1315
1316
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001317void
1318fib_table_flush (u32 fib_index,
1319 fib_protocol_t proto,
1320 fib_source_t source)
1321{
Neale Ranns32e1c012016-11-22 17:07:28 +00001322 fib_node_index_t *fib_entry_index;
1323 fib_table_flush_ctx_t ctx = {
1324 .ftf_entries = NULL,
1325 .ftf_source = source,
1326 };
1327
1328 fib_table_walk(fib_index, proto,
1329 fib_table_flush_cb,
1330 &ctx);
1331
1332 vec_foreach(fib_entry_index, ctx.ftf_entries)
1333 {
Neale Rannsa8d9f302017-02-20 09:17:02 -08001334 fib_table_entry_delete_index(*fib_entry_index, source);
Neale Ranns32e1c012016-11-22 17:07:28 +00001335 }
1336
1337 vec_free(ctx.ftf_entries);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001338}
Neale Rannsc87aafa2017-11-29 00:59:31 -08001339
1340u8 *
1341format_fib_table_memory (u8 *s, va_list *args)
1342{
1343 s = format(s, "%U", format_ip4_fib_table_memory);
1344 s = format(s, "%U", format_ip6_fib_table_memory);
1345 s = format(s, "%U", format_mpls_fib_table_memory);
1346
1347 return (s);
1348}