blob: 3778fa9a9445b210ee7741b61ed2406f5b753fe0 [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
Neale Ranns56f949b2018-04-25 01:41:24 -0700200 * has been inserted beneath it.
201 * If the prefix that has been inserted is a host route
202 * then it is not possible that it will be the cover for any
203 * other entry, so we can elide the walk. This is particularly
204 * beneficial since there are often many host entries sharing the
205 * same cover (i.e. ADJ or RR sourced entries).
Neale Ranns89541992017-04-06 04:41:02 -0700206 */
Neale Ranns56f949b2018-04-25 01:41:24 -0700207 if (!fib_entry_is_host(fib_entry_index))
208 {
209 fib_entry_cover_change_notify(fib_entry_cover_index,
210 fib_entry_index);
211 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100212 }
213}
214
215static void
216fib_table_entry_insert (fib_table_t *fib_table,
217 const fib_prefix_t *prefix,
218 fib_node_index_t fib_entry_index)
219{
220 vlib_smp_unsafe_warning();
221
222 fib_entry_lock(fib_entry_index);
223 fib_table->ft_total_route_counts++;
224
225 switch (prefix->fp_proto)
226 {
227 case FIB_PROTOCOL_IP4:
Neale Rannsa3af3372017-03-28 03:49:52 -0700228 ip4_fib_table_entry_insert(ip4_fib_get(fib_table->ft_index),
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100229 &prefix->fp_addr.ip4,
230 prefix->fp_len,
231 fib_entry_index);
232 break;
233 case FIB_PROTOCOL_IP6:
234 ip6_fib_table_entry_insert(fib_table->ft_index,
235 &prefix->fp_addr.ip6,
236 prefix->fp_len,
237 fib_entry_index);
238 break;
239 case FIB_PROTOCOL_MPLS:
Neale Rannsa3af3372017-03-28 03:49:52 -0700240 mpls_fib_table_entry_insert(mpls_fib_get(fib_table->ft_index),
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100241 prefix->fp_label,
242 prefix->fp_eos,
243 fib_entry_index);
244 break;
245 }
246
247 fib_table_post_insert_actions(fib_table, prefix, fib_entry_index);
248}
249
250void
251fib_table_fwding_dpo_update (u32 fib_index,
252 const fib_prefix_t *prefix,
253 const dpo_id_t *dpo)
254{
255 vlib_smp_unsafe_warning();
256
257 switch (prefix->fp_proto)
258 {
259 case FIB_PROTOCOL_IP4:
260 return (ip4_fib_table_fwding_dpo_update(ip4_fib_get(fib_index),
261 &prefix->fp_addr.ip4,
262 prefix->fp_len,
263 dpo));
264 case FIB_PROTOCOL_IP6:
265 return (ip6_fib_table_fwding_dpo_update(fib_index,
266 &prefix->fp_addr.ip6,
267 prefix->fp_len,
268 dpo));
269 case FIB_PROTOCOL_MPLS:
270 return (mpls_fib_forwarding_table_update(mpls_fib_get(fib_index),
271 prefix->fp_label,
272 prefix->fp_eos,
273 dpo));
274 }
275}
276
277void
278fib_table_fwding_dpo_remove (u32 fib_index,
279 const fib_prefix_t *prefix,
280 const dpo_id_t *dpo)
281{
282 vlib_smp_unsafe_warning();
283
284 switch (prefix->fp_proto)
285 {
286 case FIB_PROTOCOL_IP4:
287 return (ip4_fib_table_fwding_dpo_remove(ip4_fib_get(fib_index),
288 &prefix->fp_addr.ip4,
289 prefix->fp_len,
Neale Rannsa3af3372017-03-28 03:49:52 -0700290 dpo,
291 fib_table_get_less_specific(fib_index,
292 prefix)));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100293 case FIB_PROTOCOL_IP6:
294 return (ip6_fib_table_fwding_dpo_remove(fib_index,
295 &prefix->fp_addr.ip6,
296 prefix->fp_len,
297 dpo));
298 case FIB_PROTOCOL_MPLS:
299 return (mpls_fib_forwarding_table_reset(mpls_fib_get(fib_index),
300 prefix->fp_label,
301 prefix->fp_eos));
302 }
303}
304
305
306fib_node_index_t
307fib_table_entry_special_dpo_add (u32 fib_index,
308 const fib_prefix_t *prefix,
309 fib_source_t source,
310 fib_entry_flag_t flags,
311 const dpo_id_t *dpo)
312{
313 fib_node_index_t fib_entry_index;
314 fib_table_t *fib_table;
315
316 fib_table = fib_table_get(fib_index, prefix->fp_proto);
317 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
318
319 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
320 {
321 fib_entry_index = fib_entry_create_special(fib_index, prefix,
322 source, flags,
323 dpo);
324
325 fib_table_entry_insert(fib_table, prefix, fib_entry_index);
326 fib_table->ft_src_route_counts[source]++;
327 }
328 else
329 {
330 int was_sourced;
331
332 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
333 fib_entry_special_add(fib_entry_index, source, flags, dpo);
334
335 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
336 {
337 fib_table->ft_src_route_counts[source]++;
338 }
339 }
340
341
342 return (fib_entry_index);
343}
344
345fib_node_index_t
Neale Ranns948e00f2016-10-20 13:39:34 +0100346fib_table_entry_special_dpo_update (u32 fib_index,
347 const fib_prefix_t *prefix,
348 fib_source_t source,
349 fib_entry_flag_t flags,
350 const dpo_id_t *dpo)
351{
352 fib_node_index_t fib_entry_index;
353 fib_table_t *fib_table;
354
355 fib_table = fib_table_get(fib_index, prefix->fp_proto);
356 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
357
358 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
359 {
360 fib_entry_index = fib_entry_create_special(fib_index, prefix,
361 source, flags,
362 dpo);
363
364 fib_table_entry_insert(fib_table, prefix, fib_entry_index);
365 fib_table->ft_src_route_counts[source]++;
366 }
367 else
368 {
369 int was_sourced;
370
371 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
372
373 if (was_sourced)
374 fib_entry_special_update(fib_entry_index, source, flags, dpo);
375 else
376 fib_entry_special_add(fib_entry_index, source, flags, dpo);
377
378 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
379 {
380 fib_table->ft_src_route_counts[source]++;
381 }
382 }
383
384 return (fib_entry_index);
385}
386
387fib_node_index_t
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100388fib_table_entry_special_add (u32 fib_index,
389 const fib_prefix_t *prefix,
390 fib_source_t source,
Neale Rannsa0558302017-04-13 00:44:52 -0700391 fib_entry_flag_t flags)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100392{
393 fib_node_index_t fib_entry_index;
Neale Ranns948e00f2016-10-20 13:39:34 +0100394 dpo_id_t tmp_dpo = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100395
Neale Rannsa0558302017-04-13 00:44:52 -0700396 dpo_copy(&tmp_dpo, drop_dpo_get(fib_proto_to_dpo(prefix->fp_proto)));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100397
398 fib_entry_index = fib_table_entry_special_dpo_add(fib_index, prefix, source,
399 flags, &tmp_dpo);
400
401 dpo_unlock(&tmp_dpo);
402
403 return (fib_entry_index);
404}
405
406void
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100407fib_table_entry_special_remove (u32 fib_index,
408 const fib_prefix_t *prefix,
409 fib_source_t source)
410{
411 /*
412 * 1 is it present
413 * yes => remove source
414 * 2 - is it still sourced?
415 * no => cover walk
416 */
417 fib_node_index_t fib_entry_index;
418 fib_table_t *fib_table;
419
420 fib_table = fib_table_get(fib_index, prefix->fp_proto);
421 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
422
423 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
424 {
425 /*
426 * removing an etry that does not exist. i'll allow it.
427 */
428 }
429 else
430 {
431 fib_entry_src_flag_t src_flag;
432 int was_sourced;
433
434 /*
435 * don't nobody go nowhere
436 */
437 fib_entry_lock(fib_entry_index);
438 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
439
440 src_flag = fib_entry_special_remove(fib_entry_index, source);
441
442 if (!(FIB_ENTRY_SRC_FLAG_ADDED & src_flag))
443 {
444 /*
445 * last source gone. remove from the table
446 */
447 fib_table_entry_remove(fib_table, prefix, fib_entry_index);
448
449 /*
450 * now the entry is no longer in the table, we can
451 * inform the entries that it covers to re-calculate their cover
452 */
453 fib_entry_cover_change_notify(fib_entry_index,
454 FIB_NODE_INDEX_INVALID);
455 }
456 /*
457 * else
458 * still has sources, leave it be.
459 */
460 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
461 {
462 fib_table->ft_src_route_counts[source]--;
463 }
464
465 fib_entry_unlock(fib_entry_index);
466 }
467}
468
469/**
470 * fib_table_route_path_fixup
471 *
472 * Convert attached hosts to attached next-hops.
473 *
474 * This special case is required because an attached path will link to a
475 * glean, and the FIB entry will have the interface or API/CLI source. When
476 * the ARP/ND process is completes then that source (which will provide a
477 * complete adjacency) will be lower priority and so the FIB entry will
478 * remain linked to a glean and traffic will never reach the hosts. For
479 * an ATTAHCED_HOST path we can link the path directly to the [incomplete]
480 * adjacency.
481 */
482static void
483fib_table_route_path_fixup (const fib_prefix_t *prefix,
Neale Ranns097fa662018-05-01 05:17:55 -0700484 fib_entry_flag_t *eflags,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100485 fib_route_path_t *path)
486{
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800487 /*
488 * not all zeros next hop &&
489 * is recursive path &&
490 * nexthop is same as the route's address
491 */
492 if ((!ip46_address_is_zero(&path->frp_addr)) &&
493 (~0 == path->frp_sw_if_index) &&
494 (0 == ip46_address_cmp(&path->frp_addr, &prefix->fp_addr)))
495 {
496 /* Prefix recurses via itse;f */
497 path->frp_flags |= FIB_ROUTE_PATH_DROP;
498 }
Neale Ranns097fa662018-05-01 05:17:55 -0700499 if (!(path->frp_flags & FIB_ROUTE_PATH_LOCAL) &&
500 fib_prefix_is_host(prefix) &&
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100501 ip46_address_is_zero(&path->frp_addr) &&
Neale Ranns6f631152017-10-03 08:20:21 -0700502 path->frp_sw_if_index != ~0 &&
503 path->frp_proto != DPO_PROTO_ETHERNET)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100504 {
505 path->frp_addr = prefix->fp_addr;
Neale Ranns4b919a52017-03-11 05:55:21 -0800506 path->frp_flags |= FIB_ROUTE_PATH_ATTACHED;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100507 }
Neale Ranns097fa662018-05-01 05:17:55 -0700508 if (*eflags & FIB_ENTRY_FLAG_DROP)
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800509 {
510 path->frp_flags |= FIB_ROUTE_PATH_DROP;
511 }
Neale Ranns097fa662018-05-01 05:17:55 -0700512 if (*eflags & FIB_ENTRY_FLAG_LOCAL)
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800513 {
514 path->frp_flags |= FIB_ROUTE_PATH_LOCAL;
515 }
Neale Ranns097fa662018-05-01 05:17:55 -0700516 if (*eflags & FIB_ENTRY_FLAG_EXCLUSIVE)
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800517 {
518 path->frp_flags |= FIB_ROUTE_PATH_EXCLUSIVE;
519 }
Neale Ranns097fa662018-05-01 05:17:55 -0700520 if (path->frp_flags & FIB_ROUTE_PATH_LOCAL)
521 {
522 *eflags |= FIB_ENTRY_FLAG_LOCAL;
523
524 if (path->frp_sw_if_index != ~0)
525 {
526 *eflags |= FIB_ENTRY_FLAG_CONNECTED;
527 }
528 }
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800529}
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100530
531fib_node_index_t
532fib_table_entry_path_add (u32 fib_index,
533 const fib_prefix_t *prefix,
534 fib_source_t source,
535 fib_entry_flag_t flags,
Neale Rannsda78f952017-05-24 09:15:43 -0700536 dpo_proto_t next_hop_proto,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100537 const ip46_address_t *next_hop,
538 u32 next_hop_sw_if_index,
539 u32 next_hop_fib_index,
540 u32 next_hop_weight,
Neale Ranns31ed7442018-02-23 05:29:09 -0800541 fib_mpls_label_t *next_hop_labels,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100542 fib_route_path_flags_t path_flags)
543{
544 fib_route_path_t path = {
545 .frp_proto = next_hop_proto,
546 .frp_addr = (NULL == next_hop? zero_addr : *next_hop),
547 .frp_sw_if_index = next_hop_sw_if_index,
548 .frp_fib_index = next_hop_fib_index,
549 .frp_weight = next_hop_weight,
550 .frp_flags = path_flags,
Neale Ranns097fa662018-05-01 05:17:55 -0700551 .frp_rpf_id = INDEX_INVALID,
Neale Rannsad422ed2016-11-02 14:20:04 +0000552 .frp_label_stack = next_hop_labels,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100553 };
554 fib_node_index_t fib_entry_index;
555 fib_route_path_t *paths = NULL;
556
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100557 vec_add1(paths, path);
558
559 fib_entry_index = fib_table_entry_path_add2(fib_index, prefix,
560 source, flags, paths);
561
562 vec_free(paths);
563 return (fib_entry_index);
564}
565
566fib_node_index_t
567fib_table_entry_path_add2 (u32 fib_index,
568 const fib_prefix_t *prefix,
569 fib_source_t source,
570 fib_entry_flag_t flags,
Neale Ranns097fa662018-05-01 05:17:55 -0700571 fib_route_path_t *rpaths)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100572{
573 fib_node_index_t fib_entry_index;
574 fib_table_t *fib_table;
Neale Rannsad422ed2016-11-02 14:20:04 +0000575 u32 ii;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100576
577 fib_table = fib_table_get(fib_index, prefix->fp_proto);
578 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
579
Neale Ranns097fa662018-05-01 05:17:55 -0700580 for (ii = 0; ii < vec_len(rpaths); ii++)
Neale Rannsad422ed2016-11-02 14:20:04 +0000581 {
Neale Ranns097fa662018-05-01 05:17:55 -0700582 fib_table_route_path_fixup(prefix, &flags, &rpaths[ii]);
Neale Rannsad422ed2016-11-02 14:20:04 +0000583 }
584
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100585 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
586 {
587 fib_entry_index = fib_entry_create(fib_index, prefix,
588 source, flags,
Neale Ranns097fa662018-05-01 05:17:55 -0700589 rpaths);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100590
591 fib_table_entry_insert(fib_table, prefix, fib_entry_index);
592 fib_table->ft_src_route_counts[source]++;
593 }
594 else
595 {
596 int was_sourced;
597
598 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
Neale Ranns097fa662018-05-01 05:17:55 -0700599 fib_entry_path_add(fib_entry_index, source, flags, rpaths);;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100600
601 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
602 {
603 fib_table->ft_src_route_counts[source]++;
604 }
605 }
606
607 return (fib_entry_index);
608}
609
610void
611fib_table_entry_path_remove2 (u32 fib_index,
Neale Rannsad422ed2016-11-02 14:20:04 +0000612 const fib_prefix_t *prefix,
613 fib_source_t source,
Neale Ranns097fa662018-05-01 05:17:55 -0700614 fib_route_path_t *rpaths)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100615{
616 /*
617 * 1 is it present
618 * yes => remove source
619 * 2 - is it still sourced?
620 * no => cover walk
621 */
622 fib_node_index_t fib_entry_index;
Neale Ranns097fa662018-05-01 05:17:55 -0700623 fib_route_path_t *rpath;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100624 fib_table_t *fib_table;
625
626 fib_table = fib_table_get(fib_index, prefix->fp_proto);
627 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
628
629 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
630 {
631 /*
632 * removing an etry that does not exist. i'll allow it.
633 */
634 }
635 else
636 {
637 fib_entry_src_flag_t src_flag;
638 int was_sourced;
639
Neale Rannsf12a83f2017-04-18 09:09:40 -0700640 /*
641 * if it's not sourced, then there's nowt to remove
642 */
643 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
644 if (!was_sourced)
645 {
646 return;
647 }
648
649 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100650 * don't nobody go nowhere
651 */
652 fib_entry_lock(fib_entry_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100653
Neale Ranns097fa662018-05-01 05:17:55 -0700654 vec_foreach(rpath, rpaths)
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800655 {
Neale Ranns097fa662018-05-01 05:17:55 -0700656 fib_entry_flag_t eflags;
657
658 eflags = fib_entry_get_flags_for_source(fib_entry_index,
659 source);
660 fib_table_route_path_fixup(prefix, &eflags, rpath);
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800661 }
662
Neale Ranns097fa662018-05-01 05:17:55 -0700663 src_flag = fib_entry_path_remove(fib_entry_index, source, rpaths);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100664
665 if (!(FIB_ENTRY_SRC_FLAG_ADDED & src_flag))
666 {
667 /*
668 * last source gone. remove from the table
669 */
670 fib_table_entry_remove(fib_table, prefix, fib_entry_index);
671
672 /*
673 * now the entry is no longer in the table, we can
674 * inform the entries that it covers to re-calculate their cover
675 */
676 fib_entry_cover_change_notify(fib_entry_index,
677 FIB_NODE_INDEX_INVALID);
678 }
679 /*
680 * else
681 * still has sources, leave it be.
682 */
683 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
684 {
685 fib_table->ft_src_route_counts[source]--;
686 }
687
688 fib_entry_unlock(fib_entry_index);
689 }
690}
691
692void
693fib_table_entry_path_remove (u32 fib_index,
694 const fib_prefix_t *prefix,
695 fib_source_t source,
Neale Rannsda78f952017-05-24 09:15:43 -0700696 dpo_proto_t next_hop_proto,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100697 const ip46_address_t *next_hop,
698 u32 next_hop_sw_if_index,
699 u32 next_hop_fib_index,
700 u32 next_hop_weight,
701 fib_route_path_flags_t path_flags)
702{
703 /*
704 * 1 is it present
705 * yes => remove source
706 * 2 - is it still sourced?
707 * no => cover walk
708 */
709 fib_route_path_t path = {
710 .frp_proto = next_hop_proto,
711 .frp_addr = (NULL == next_hop? zero_addr : *next_hop),
712 .frp_sw_if_index = next_hop_sw_if_index,
713 .frp_fib_index = next_hop_fib_index,
714 .frp_weight = next_hop_weight,
715 .frp_flags = path_flags,
716 };
717 fib_route_path_t *paths = NULL;
718
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100719 vec_add1(paths, path);
720
721 fib_table_entry_path_remove2(fib_index, prefix, source, paths);
722
723 vec_free(paths);
724}
725
726static int
727fib_route_path_cmp_for_sort (void * v1,
728 void * v2)
729{
730 return (fib_route_path_cmp(v1, v2));
731}
732
733fib_node_index_t
734fib_table_entry_update (u32 fib_index,
735 const fib_prefix_t *prefix,
736 fib_source_t source,
737 fib_entry_flag_t flags,
Neale Rannsad422ed2016-11-02 14:20:04 +0000738 fib_route_path_t *paths)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100739{
740 fib_node_index_t fib_entry_index;
741 fib_table_t *fib_table;
Neale Rannsad422ed2016-11-02 14:20:04 +0000742 u32 ii;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100743
744 fib_table = fib_table_get(fib_index, prefix->fp_proto);
745 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
746
Neale Rannsad422ed2016-11-02 14:20:04 +0000747 for (ii = 0; ii < vec_len(paths); ii++)
748 {
Neale Ranns097fa662018-05-01 05:17:55 -0700749 fib_table_route_path_fixup(prefix, &flags, &paths[ii]);
Neale Rannsad422ed2016-11-02 14:20:04 +0000750 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100751 /*
752 * sort the paths provided by the control plane. this means
753 * the paths and the extension on the entry will be sorted.
754 */
Neale Rannsad422ed2016-11-02 14:20:04 +0000755 vec_sort_with_function(paths, fib_route_path_cmp_for_sort);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100756
757 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
758 {
759 fib_entry_index = fib_entry_create(fib_index, prefix,
760 source, flags,
761 paths);
762
763 fib_table_entry_insert(fib_table, prefix, fib_entry_index);
764 fib_table->ft_src_route_counts[source]++;
765 }
766 else
767 {
768 int was_sourced;
769
770 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
771 fib_entry_update(fib_entry_index, source, flags, paths);
772
773 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
774 {
775 fib_table->ft_src_route_counts[source]++;
776 }
777 }
778
779 return (fib_entry_index);
780}
781
782fib_node_index_t
783fib_table_entry_update_one_path (u32 fib_index,
784 const fib_prefix_t *prefix,
785 fib_source_t source,
786 fib_entry_flag_t flags,
Neale Rannsda78f952017-05-24 09:15:43 -0700787 dpo_proto_t next_hop_proto,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100788 const ip46_address_t *next_hop,
789 u32 next_hop_sw_if_index,
790 u32 next_hop_fib_index,
791 u32 next_hop_weight,
Neale Ranns31ed7442018-02-23 05:29:09 -0800792 fib_mpls_label_t *next_hop_labels,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100793 fib_route_path_flags_t path_flags)
794{
795 fib_node_index_t fib_entry_index;
796 fib_route_path_t path = {
797 .frp_proto = next_hop_proto,
798 .frp_addr = (NULL == next_hop? zero_addr : *next_hop),
799 .frp_sw_if_index = next_hop_sw_if_index,
800 .frp_fib_index = next_hop_fib_index,
801 .frp_weight = next_hop_weight,
802 .frp_flags = path_flags,
Neale Rannsad422ed2016-11-02 14:20:04 +0000803 .frp_label_stack = next_hop_labels,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100804 };
805 fib_route_path_t *paths = NULL;
806
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100807 vec_add1(paths, path);
808
809 fib_entry_index =
810 fib_table_entry_update(fib_index, prefix, source, flags, paths);
811
812 vec_free(paths);
813
814 return (fib_entry_index);
815}
816
817static void
818fib_table_entry_delete_i (u32 fib_index,
819 fib_node_index_t fib_entry_index,
820 const fib_prefix_t *prefix,
821 fib_source_t source)
822{
823 fib_entry_src_flag_t src_flag;
824 fib_table_t *fib_table;
825 int was_sourced;
826
827 fib_table = fib_table_get(fib_index, prefix->fp_proto);
828 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
829
830 /*
831 * don't nobody go nowhere
832 */
833 fib_entry_lock(fib_entry_index);
834
835 src_flag = fib_entry_delete(fib_entry_index, source);
836
837 if (!(FIB_ENTRY_SRC_FLAG_ADDED & src_flag))
838 {
839 /*
840 * last source gone. remove from the table
841 */
842 fib_table_entry_remove(fib_table, prefix, fib_entry_index);
843
844 /*
845 * now the entry is no longer in the table, we can
846 * inform the entries that it covers to re-calculate their cover
847 */
848 fib_entry_cover_change_notify(fib_entry_index,
849 FIB_NODE_INDEX_INVALID);
850 }
851 /*
852 * else
853 * still has sources, leave it be.
854 */
855 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
856 {
857 fib_table->ft_src_route_counts[source]--;
858 }
859
860 fib_entry_unlock(fib_entry_index);
861}
862
863void
864fib_table_entry_delete (u32 fib_index,
865 const fib_prefix_t *prefix,
866 fib_source_t source)
867{
868 fib_node_index_t fib_entry_index;
869
870 fib_entry_index = fib_table_lookup_exact_match(fib_index, prefix);
871
872 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
873 {
874 /*
875 * removing an etry that does not exist.
876 * i'll allow it, but i won't like it.
877 */
Dave Barach59b25652017-09-10 15:04:27 -0400878 if (0)
879 clib_warning("%U not in FIB", format_fib_prefix, prefix);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100880 }
881 else
882 {
883 fib_table_entry_delete_i(fib_index, fib_entry_index, prefix, source);
884 }
885}
886
887void
888fib_table_entry_delete_index (fib_node_index_t fib_entry_index,
889 fib_source_t source)
890{
Neale Rannsc5d43172018-07-30 08:04:40 -0700891 const fib_prefix_t *prefix;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100892
Neale Rannsc5d43172018-07-30 08:04:40 -0700893 prefix = fib_entry_get_prefix(fib_entry_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100894
895 fib_table_entry_delete_i(fib_entry_get_fib_index(fib_entry_index),
Neale Rannsc5d43172018-07-30 08:04:40 -0700896 fib_entry_index, prefix, source);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100897}
898
Neale Ranns008dbe12018-09-07 09:32:36 -0700899u32
Neale Ranns28c142e2018-09-07 09:37:07 -0700900fib_table_entry_get_stats_index (u32 fib_index,
901 const fib_prefix_t *prefix)
Neale Ranns008dbe12018-09-07 09:32:36 -0700902{
903 return (fib_entry_get_stats_index(
904 fib_table_lookup_exact_match(fib_index, prefix)));
905}
906
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100907fib_node_index_t
908fib_table_entry_local_label_add (u32 fib_index,
909 const fib_prefix_t *prefix,
910 mpls_label_t label)
911{
912 fib_node_index_t fib_entry_index;
913
Neale Ranns1357f3b2016-10-16 12:01:42 -0700914 fib_entry_index = fib_table_lookup_exact_match(fib_index, prefix);
915
916 if (FIB_NODE_INDEX_INVALID == fib_entry_index ||
917 !fib_entry_is_sourced(fib_entry_index, FIB_SOURCE_MPLS))
918 {
919 /*
920 * only source the prefix once. this allows the label change
921 * operation to work
922 */
923 fib_entry_index = fib_table_entry_special_dpo_add(fib_index, prefix,
924 FIB_SOURCE_MPLS,
925 FIB_ENTRY_FLAG_NONE,
926 NULL);
927 }
928
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100929 fib_entry_set_source_data(fib_entry_index, FIB_SOURCE_MPLS, &label);
930
931 return (fib_entry_index);
932}
933
934void
935fib_table_entry_local_label_remove (u32 fib_index,
936 const fib_prefix_t *prefix,
937 mpls_label_t label)
938{
939 fib_node_index_t fib_entry_index;
940 const void *data;
941 mpls_label_t pl;
942
943 fib_entry_index = fib_table_lookup_exact_match(fib_index, prefix);
944
945 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
946 return;
947
948 data = fib_entry_get_source_data(fib_entry_index, FIB_SOURCE_MPLS);
949
950 if (NULL == data)
951 return;
952
953 pl = *(mpls_label_t*)data;
954
955 if (pl != label)
956 return;
957
958 pl = MPLS_LABEL_INVALID;
959
960 fib_entry_set_source_data(fib_entry_index, FIB_SOURCE_MPLS, &pl);
961 fib_table_entry_special_remove(fib_index,
962 prefix,
963 FIB_SOURCE_MPLS);
964}
965
966u32
967fib_table_get_index_for_sw_if_index (fib_protocol_t proto,
968 u32 sw_if_index)
969{
970 switch (proto)
971 {
972 case FIB_PROTOCOL_IP4:
973 return (ip4_fib_table_get_index_for_sw_if_index(sw_if_index));
974 case FIB_PROTOCOL_IP6:
975 return (ip6_fib_table_get_index_for_sw_if_index(sw_if_index));
976 case FIB_PROTOCOL_MPLS:
977 return (mpls_fib_table_get_index_for_sw_if_index(sw_if_index));
978 }
979 return (~0);
980}
981
982flow_hash_config_t
983fib_table_get_flow_hash_config (u32 fib_index,
984 fib_protocol_t proto)
985{
Neale Ranns227038a2017-04-21 01:07:59 -0700986 fib_table_t *fib;
987
988 fib = fib_table_get(fib_index, proto);
989
990 return (fib->ft_flow_hash_config);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100991}
Neale Rannsd792d9c2017-10-21 10:53:20 -0700992
Neale Ranns41da54f2017-05-02 10:15:19 -0700993flow_hash_config_t
994fib_table_get_default_flow_hash_config (fib_protocol_t proto)
995{
996 switch (proto)
997 {
998 case FIB_PROTOCOL_IP4:
999 case FIB_PROTOCOL_IP6:
1000 return (IP_FLOW_HASH_DEFAULT);
1001
1002 case FIB_PROTOCOL_MPLS:
1003 return (MPLS_FLOW_HASH_DEFAULT);
1004 }
1005
1006 ASSERT(0);
1007 return (IP_FLOW_HASH_DEFAULT);
1008}
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001009
Neale Ranns227038a2017-04-21 01:07:59 -07001010/**
1011 * @brief Table set flow hash config context.
1012 */
1013typedef struct fib_table_set_flow_hash_config_ctx_t_
1014{
1015 /**
1016 * the flow hash config to set
1017 */
1018 flow_hash_config_t hash_config;
1019} fib_table_set_flow_hash_config_ctx_t;
1020
Neale Ranns89541992017-04-06 04:41:02 -07001021static fib_table_walk_rc_t
Neale Ranns227038a2017-04-21 01:07:59 -07001022fib_table_set_flow_hash_config_cb (fib_node_index_t fib_entry_index,
1023 void *arg)
1024{
1025 fib_table_set_flow_hash_config_ctx_t *ctx = arg;
1026
1027 fib_entry_set_flow_hash_config(fib_entry_index, ctx->hash_config);
1028
Neale Ranns89541992017-04-06 04:41:02 -07001029 return (FIB_TABLE_WALK_CONTINUE);
Neale Ranns227038a2017-04-21 01:07:59 -07001030}
1031
1032void
1033fib_table_set_flow_hash_config (u32 fib_index,
1034 fib_protocol_t proto,
1035 flow_hash_config_t hash_config)
1036{
1037 fib_table_set_flow_hash_config_ctx_t ctx = {
1038 .hash_config = hash_config,
1039 };
1040 fib_table_t *fib;
1041
1042 fib = fib_table_get(fib_index, proto);
1043 fib->ft_flow_hash_config = hash_config;
1044
1045 fib_table_walk(fib_index, proto,
1046 fib_table_set_flow_hash_config_cb,
1047 &ctx);
1048}
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001049
1050u32
1051fib_table_get_table_id_for_sw_if_index (fib_protocol_t proto,
1052 u32 sw_if_index)
1053{
1054 fib_table_t *fib_table;
1055
1056 fib_table = fib_table_get(fib_table_get_index_for_sw_if_index(
1057 proto, sw_if_index),
1058 proto);
1059
1060 return ((NULL != fib_table ? fib_table->ft_table_id : ~0));
1061}
1062
1063u32
Neale Ranns25b04942018-04-04 09:34:50 -07001064fib_table_get_table_id (u32 fib_index,
1065 fib_protocol_t proto)
1066{
1067 fib_table_t *fib_table;
1068
1069 fib_table = fib_table_get(fib_index, proto);
1070
1071 return ((NULL != fib_table ? fib_table->ft_table_id : ~0));
1072}
1073
1074u32
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001075fib_table_find (fib_protocol_t proto,
1076 u32 table_id)
1077{
1078 switch (proto)
1079 {
1080 case FIB_PROTOCOL_IP4:
1081 return (ip4_fib_index_from_table_id(table_id));
1082 case FIB_PROTOCOL_IP6:
1083 return (ip6_fib_index_from_table_id(table_id));
1084 case FIB_PROTOCOL_MPLS:
1085 return (mpls_fib_index_from_table_id(table_id));
1086 }
1087 return (~0);
1088}
1089
Neale Ranns2297af02017-09-12 09:45:04 -07001090static u32
1091fib_table_find_or_create_and_lock_i (fib_protocol_t proto,
1092 u32 table_id,
1093 fib_source_t src,
1094 const u8 *name)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001095{
1096 fib_table_t *fib_table;
1097 fib_node_index_t fi;
1098
1099 switch (proto)
1100 {
1101 case FIB_PROTOCOL_IP4:
Neale Ranns15002542017-09-10 04:39:11 -07001102 fi = ip4_fib_table_find_or_create_and_lock(table_id, src);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001103 break;
1104 case FIB_PROTOCOL_IP6:
Neale Ranns15002542017-09-10 04:39:11 -07001105 fi = ip6_fib_table_find_or_create_and_lock(table_id, src);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001106 break;
1107 case FIB_PROTOCOL_MPLS:
Neale Ranns15002542017-09-10 04:39:11 -07001108 fi = mpls_fib_table_find_or_create_and_lock(table_id, src);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001109 break;
1110 default:
1111 return (~0);
1112 }
1113
1114 fib_table = fib_table_get(fi, proto);
1115
Neale Ranns2297af02017-09-12 09:45:04 -07001116 if (NULL == fib_table->ft_desc)
1117 {
1118 if (name && name[0])
1119 {
1120 fib_table->ft_desc = format(NULL, "%s", name);
1121 }
1122 else
1123 {
1124 fib_table->ft_desc = format(NULL, "%U-VRF:%d",
1125 format_fib_protocol, proto,
1126 table_id);
1127 }
1128 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001129
1130 return (fi);
1131}
1132
1133u32
Neale Ranns2297af02017-09-12 09:45:04 -07001134fib_table_find_or_create_and_lock (fib_protocol_t proto,
1135 u32 table_id,
1136 fib_source_t src)
1137{
1138 return (fib_table_find_or_create_and_lock_i(proto, table_id,
1139 src, NULL));
1140}
1141
1142u32
1143fib_table_find_or_create_and_lock_w_name (fib_protocol_t proto,
1144 u32 table_id,
1145 fib_source_t src,
1146 const u8 *name)
1147{
1148 return (fib_table_find_or_create_and_lock_i(proto, table_id,
1149 src, name));
1150}
1151
1152u32
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001153fib_table_create_and_lock (fib_protocol_t proto,
Neale Ranns15002542017-09-10 04:39:11 -07001154 fib_source_t src,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001155 const char *const fmt,
1156 ...)
1157{
1158 fib_table_t *fib_table;
1159 fib_node_index_t fi;
1160 va_list ap;
1161
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001162
1163 switch (proto)
1164 {
1165 case FIB_PROTOCOL_IP4:
Neale Ranns15002542017-09-10 04:39:11 -07001166 fi = ip4_fib_table_create_and_lock(src);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001167 break;
1168 case FIB_PROTOCOL_IP6:
Neale Ranns53da2212018-02-24 02:11:19 -08001169 fi = ip6_fib_table_create_and_lock(src, FIB_TABLE_FLAG_NONE, NULL);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001170 break;
1171 case FIB_PROTOCOL_MPLS:
Neale Ranns15002542017-09-10 04:39:11 -07001172 fi = mpls_fib_table_create_and_lock(src);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001173 break;
1174 default:
1175 return (~0);
1176 }
1177
1178 fib_table = fib_table_get(fi, proto);
1179
Paul Vinciguerra0c0383d2018-10-24 12:14:09 -07001180 va_start(ap, fmt);
1181
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001182 fib_table->ft_desc = va_format(fib_table->ft_desc, fmt, &ap);
1183
1184 va_end(ap);
1185 return (fi);
1186}
1187
1188static void
1189fib_table_destroy (fib_table_t *fib_table)
1190{
1191 vec_free(fib_table->ft_desc);
1192
1193 switch (fib_table->ft_proto)
1194 {
1195 case FIB_PROTOCOL_IP4:
Neale Rannsa3af3372017-03-28 03:49:52 -07001196 ip4_fib_table_destroy(fib_table->ft_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001197 break;
1198 case FIB_PROTOCOL_IP6:
1199 ip6_fib_table_destroy(fib_table->ft_index);
1200 break;
1201 case FIB_PROTOCOL_MPLS:
Neale Rannsa3af3372017-03-28 03:49:52 -07001202 mpls_fib_table_destroy(fib_table->ft_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001203 break;
1204 }
1205}
Neale Ranns5a8123b2017-01-26 01:18:23 -08001206
Neale Ranns32e1c012016-11-22 17:07:28 +00001207void
1208fib_table_walk (u32 fib_index,
1209 fib_protocol_t proto,
1210 fib_table_walk_fn_t fn,
1211 void *ctx)
1212{
1213 switch (proto)
1214 {
1215 case FIB_PROTOCOL_IP4:
1216 ip4_fib_table_walk(ip4_fib_get(fib_index), fn, ctx);
1217 break;
1218 case FIB_PROTOCOL_IP6:
1219 ip6_fib_table_walk(fib_index, fn, ctx);
1220 break;
1221 case FIB_PROTOCOL_MPLS:
1222 mpls_fib_table_walk(mpls_fib_get(fib_index), fn, ctx);
1223 break;
1224 }
1225}
1226
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001227void
Neale Ranns89541992017-04-06 04:41:02 -07001228fib_table_sub_tree_walk (u32 fib_index,
1229 fib_protocol_t proto,
1230 const fib_prefix_t *root,
1231 fib_table_walk_fn_t fn,
1232 void *ctx)
1233{
1234 switch (proto)
1235 {
1236 case FIB_PROTOCOL_IP4:
1237 ip4_fib_table_sub_tree_walk(ip4_fib_get(fib_index), root, fn, ctx);
1238 break;
1239 case FIB_PROTOCOL_IP6:
1240 ip6_fib_table_sub_tree_walk(fib_index, root, fn, ctx);
1241 break;
1242 case FIB_PROTOCOL_MPLS:
1243 break;
1244 }
1245}
1246
1247void
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001248fib_table_unlock (u32 fib_index,
Neale Ranns15002542017-09-10 04:39:11 -07001249 fib_protocol_t proto,
1250 fib_source_t source)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001251{
1252 fib_table_t *fib_table;
1253
1254 fib_table = fib_table_get(fib_index, proto);
Neale Ranns15002542017-09-10 04:39:11 -07001255 fib_table->ft_locks[source]--;
1256 fib_table->ft_locks[FIB_TABLE_TOTAL_LOCKS]--;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001257
Neale Ranns15002542017-09-10 04:39:11 -07001258 if (0 == fib_table->ft_locks[FIB_TABLE_TOTAL_LOCKS])
1259 {
1260 /*
1261 * no more locak from any source - kill it
1262 */
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001263 fib_table_destroy(fib_table);
1264 }
1265}
Neale Ranns15002542017-09-10 04:39:11 -07001266
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001267void
1268fib_table_lock (u32 fib_index,
Neale Ranns15002542017-09-10 04:39:11 -07001269 fib_protocol_t proto,
1270 fib_source_t source)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001271{
1272 fib_table_t *fib_table;
1273
1274 fib_table = fib_table_get(fib_index, proto);
Neale Ranns6fff24a2018-09-10 19:14:07 -07001275
1276 ASSERT(fib_table->ft_locks[source] < (0xffff - 1));
1277
Neale Ranns15002542017-09-10 04:39:11 -07001278 fib_table->ft_locks[source]++;
1279 fib_table->ft_locks[FIB_TABLE_TOTAL_LOCKS]++;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001280}
1281
1282u32
1283fib_table_get_num_entries (u32 fib_index,
1284 fib_protocol_t proto,
1285 fib_source_t source)
1286{
1287 fib_table_t *fib_table;
1288
1289 fib_table = fib_table_get(fib_index, proto);
1290
1291 return (fib_table->ft_src_route_counts[source]);
1292}
1293
1294u8*
Christophe Fontained3c008d2017-10-02 18:10:54 +02001295format_fib_table_name (u8* s, va_list* ap)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001296{
Christophe Fontained3c008d2017-10-02 18:10:54 +02001297 fib_node_index_t fib_index = va_arg(*ap, fib_node_index_t);
1298 fib_protocol_t proto = va_arg(*ap, int); // int promotion
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001299 fib_table_t *fib_table;
1300
1301 fib_table = fib_table_get(fib_index, proto);
1302
1303 s = format(s, "%v", fib_table->ft_desc);
1304
1305 return (s);
1306}
1307
Neale Ranns32e1c012016-11-22 17:07:28 +00001308/**
1309 * @brief Table flush context. Store the indicies of matching FIB entries
1310 * that need to be removed.
1311 */
1312typedef struct fib_table_flush_ctx_t_
1313{
1314 /**
1315 * The list of entries to flush
1316 */
1317 fib_node_index_t *ftf_entries;
1318
1319 /**
1320 * The source we are flushing
1321 */
1322 fib_source_t ftf_source;
1323} fib_table_flush_ctx_t;
1324
Neale Ranns89541992017-04-06 04:41:02 -07001325static fib_table_walk_rc_t
Neale Ranns32e1c012016-11-22 17:07:28 +00001326fib_table_flush_cb (fib_node_index_t fib_entry_index,
1327 void *arg)
1328{
1329 fib_table_flush_ctx_t *ctx = arg;
1330
1331 if (fib_entry_is_sourced(fib_entry_index, ctx->ftf_source))
1332 {
1333 vec_add1(ctx->ftf_entries, fib_entry_index);
1334 }
Neale Ranns89541992017-04-06 04:41:02 -07001335 return (FIB_TABLE_WALK_CONTINUE);
Neale Ranns32e1c012016-11-22 17:07:28 +00001336}
1337
1338
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001339void
1340fib_table_flush (u32 fib_index,
1341 fib_protocol_t proto,
1342 fib_source_t source)
1343{
Neale Ranns32e1c012016-11-22 17:07:28 +00001344 fib_node_index_t *fib_entry_index;
1345 fib_table_flush_ctx_t ctx = {
1346 .ftf_entries = NULL,
1347 .ftf_source = source,
1348 };
1349
1350 fib_table_walk(fib_index, proto,
1351 fib_table_flush_cb,
1352 &ctx);
1353
1354 vec_foreach(fib_entry_index, ctx.ftf_entries)
1355 {
Neale Rannsa8d9f302017-02-20 09:17:02 -08001356 fib_table_entry_delete_index(*fib_entry_index, source);
Neale Ranns32e1c012016-11-22 17:07:28 +00001357 }
1358
1359 vec_free(ctx.ftf_entries);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001360}
Neale Rannsc87aafa2017-11-29 00:59:31 -08001361
1362u8 *
1363format_fib_table_memory (u8 *s, va_list *args)
1364{
1365 s = format(s, "%U", format_ip4_fib_table_memory);
1366 s = format(s, "%U", format_ip6_fib_table_memory);
1367 s = format(s, "%U", format_mpls_fib_table_memory);
1368
1369 return (s);
1370}