blob: eaeee5bb92131c6f177835822db253b5194d29e7 [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
Neale Ranns9db6ada2019-11-08 12:42:31 +000026const static char * fib_table_flags_strings[] = FIB_TABLE_ATTRIBUTES;
27
Neale Ranns0bfe5d82016-08-25 15:29:12 +010028fib_table_t *
29fib_table_get (fib_node_index_t index,
30 fib_protocol_t proto)
31{
32 switch (proto)
33 {
34 case FIB_PROTOCOL_IP4:
35 return (pool_elt_at_index(ip4_main.fibs, index));
36 case FIB_PROTOCOL_IP6:
37 return (pool_elt_at_index(ip6_main.fibs, index));
38 case FIB_PROTOCOL_MPLS:
39 return (pool_elt_at_index(mpls_main.fibs, index));
40 }
41 ASSERT(0);
42 return (NULL);
43}
44
45static inline fib_node_index_t
46fib_table_lookup_i (fib_table_t *fib_table,
47 const fib_prefix_t *prefix)
48{
49 switch (prefix->fp_proto)
50 {
51 case FIB_PROTOCOL_IP4:
Neale Rannsa3af3372017-03-28 03:49:52 -070052 return (ip4_fib_table_lookup(ip4_fib_get(fib_table->ft_index),
Neale Ranns0bfe5d82016-08-25 15:29:12 +010053 &prefix->fp_addr.ip4,
54 prefix->fp_len));
55 case FIB_PROTOCOL_IP6:
56 return (ip6_fib_table_lookup(fib_table->ft_index,
57 &prefix->fp_addr.ip6,
58 prefix->fp_len));
59 case FIB_PROTOCOL_MPLS:
Neale Rannsa3af3372017-03-28 03:49:52 -070060 return (mpls_fib_table_lookup(mpls_fib_get(fib_table->ft_index),
Neale Ranns0bfe5d82016-08-25 15:29:12 +010061 prefix->fp_label,
62 prefix->fp_eos));
63 }
64 return (FIB_NODE_INDEX_INVALID);
65}
66
67fib_node_index_t
68fib_table_lookup (u32 fib_index,
69 const fib_prefix_t *prefix)
70{
71 return (fib_table_lookup_i(fib_table_get(fib_index, prefix->fp_proto), prefix));
72}
73
74static inline fib_node_index_t
75fib_table_lookup_exact_match_i (const fib_table_t *fib_table,
76 const fib_prefix_t *prefix)
77{
78 switch (prefix->fp_proto)
79 {
80 case FIB_PROTOCOL_IP4:
Neale Rannsa3af3372017-03-28 03:49:52 -070081 return (ip4_fib_table_lookup_exact_match(ip4_fib_get(fib_table->ft_index),
Neale Ranns0bfe5d82016-08-25 15:29:12 +010082 &prefix->fp_addr.ip4,
83 prefix->fp_len));
84 case FIB_PROTOCOL_IP6:
85 return (ip6_fib_table_lookup_exact_match(fib_table->ft_index,
86 &prefix->fp_addr.ip6,
87 prefix->fp_len));
88 case FIB_PROTOCOL_MPLS:
Neale Rannsa3af3372017-03-28 03:49:52 -070089 return (mpls_fib_table_lookup(mpls_fib_get(fib_table->ft_index),
Neale Ranns0bfe5d82016-08-25 15:29:12 +010090 prefix->fp_label,
91 prefix->fp_eos));
92 }
93 return (FIB_NODE_INDEX_INVALID);
94}
95
96fib_node_index_t
97fib_table_lookup_exact_match (u32 fib_index,
98 const fib_prefix_t *prefix)
99{
100 return (fib_table_lookup_exact_match_i(fib_table_get(fib_index,
101 prefix->fp_proto),
102 prefix));
103}
104
105static fib_node_index_t
106fib_table_get_less_specific_i (fib_table_t *fib_table,
107 const fib_prefix_t *prefix)
108{
109 fib_prefix_t pfx;
110
111 pfx = *prefix;
112
113 if (FIB_PROTOCOL_MPLS == pfx.fp_proto)
114 {
115 return (FIB_NODE_INDEX_INVALID);
116 }
117
118 /*
119 * in the absence of a tree structure for the table that allows for an O(1)
120 * parent get, a cheeky way to find the cover is to LPM for the prefix with
121 * mask-1.
122 * there should always be a cover, though it may be the default route. the
123 * default route's cover is the default route.
124 */
125 if (pfx.fp_len != 0) {
126 pfx.fp_len -= 1;
127 }
128
129 return (fib_table_lookup_i(fib_table, &pfx));
130}
131
132fib_node_index_t
133fib_table_get_less_specific (u32 fib_index,
134 const fib_prefix_t *prefix)
135{
136 return (fib_table_get_less_specific_i(fib_table_get(fib_index,
137 prefix->fp_proto),
138 prefix));
139}
140
141static void
142fib_table_entry_remove (fib_table_t *fib_table,
143 const fib_prefix_t *prefix,
144 fib_node_index_t fib_entry_index)
145{
146 vlib_smp_unsafe_warning();
147
148 fib_table->ft_total_route_counts--;
149
150 switch (prefix->fp_proto)
151 {
152 case FIB_PROTOCOL_IP4:
Neale Rannsa3af3372017-03-28 03:49:52 -0700153 ip4_fib_table_entry_remove(ip4_fib_get(fib_table->ft_index),
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100154 &prefix->fp_addr.ip4,
155 prefix->fp_len);
156 break;
157 case FIB_PROTOCOL_IP6:
158 ip6_fib_table_entry_remove(fib_table->ft_index,
159 &prefix->fp_addr.ip6,
160 prefix->fp_len);
161 break;
162 case FIB_PROTOCOL_MPLS:
Neale Rannsa3af3372017-03-28 03:49:52 -0700163 mpls_fib_table_entry_remove(mpls_fib_get(fib_table->ft_index),
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100164 prefix->fp_label,
165 prefix->fp_eos);
166 break;
167 }
168
169 fib_entry_unlock(fib_entry_index);
170}
171
172static void
173fib_table_post_insert_actions (fib_table_t *fib_table,
174 const fib_prefix_t *prefix,
175 fib_node_index_t fib_entry_index)
176{
177 fib_node_index_t fib_entry_cover_index;
178
179 /*
180 * no cover relationships in the MPLS FIB
181 */
182 if (FIB_PROTOCOL_MPLS == prefix->fp_proto)
183 return;
184
185 /*
Neale Ranns89541992017-04-06 04:41:02 -0700186 * find the covering entry
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100187 */
188 fib_entry_cover_index = fib_table_get_less_specific_i(fib_table, prefix);
189 /*
190 * the indicies are the same when the default route is first added
191 */
192 if (fib_entry_cover_index != fib_entry_index)
193 {
Neale Ranns89541992017-04-06 04:41:02 -0700194 /*
195 * push any inherting sources from the cover onto the covered
196 */
197 fib_entry_inherit(fib_entry_cover_index,
198 fib_entry_index);
199
200 /*
201 * inform the covering entry that a new more specific
Neale Ranns56f949b2018-04-25 01:41:24 -0700202 * has been inserted beneath it.
203 * If the prefix that has been inserted is a host route
204 * then it is not possible that it will be the cover for any
205 * other entry, so we can elide the walk. This is particularly
206 * beneficial since there are often many host entries sharing the
207 * same cover (i.e. ADJ or RR sourced entries).
Neale Ranns89541992017-04-06 04:41:02 -0700208 */
Neale Ranns56f949b2018-04-25 01:41:24 -0700209 if (!fib_entry_is_host(fib_entry_index))
210 {
211 fib_entry_cover_change_notify(fib_entry_cover_index,
212 fib_entry_index);
213 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100214 }
215}
216
217static void
218fib_table_entry_insert (fib_table_t *fib_table,
219 const fib_prefix_t *prefix,
220 fib_node_index_t fib_entry_index)
221{
222 vlib_smp_unsafe_warning();
223
224 fib_entry_lock(fib_entry_index);
225 fib_table->ft_total_route_counts++;
226
227 switch (prefix->fp_proto)
228 {
229 case FIB_PROTOCOL_IP4:
Neale Rannsa3af3372017-03-28 03:49:52 -0700230 ip4_fib_table_entry_insert(ip4_fib_get(fib_table->ft_index),
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100231 &prefix->fp_addr.ip4,
232 prefix->fp_len,
233 fib_entry_index);
234 break;
235 case FIB_PROTOCOL_IP6:
236 ip6_fib_table_entry_insert(fib_table->ft_index,
237 &prefix->fp_addr.ip6,
238 prefix->fp_len,
239 fib_entry_index);
240 break;
241 case FIB_PROTOCOL_MPLS:
Neale Rannsa3af3372017-03-28 03:49:52 -0700242 mpls_fib_table_entry_insert(mpls_fib_get(fib_table->ft_index),
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100243 prefix->fp_label,
244 prefix->fp_eos,
245 fib_entry_index);
246 break;
247 }
248
249 fib_table_post_insert_actions(fib_table, prefix, fib_entry_index);
250}
251
252void
253fib_table_fwding_dpo_update (u32 fib_index,
254 const fib_prefix_t *prefix,
255 const dpo_id_t *dpo)
256{
257 vlib_smp_unsafe_warning();
258
259 switch (prefix->fp_proto)
260 {
261 case FIB_PROTOCOL_IP4:
262 return (ip4_fib_table_fwding_dpo_update(ip4_fib_get(fib_index),
263 &prefix->fp_addr.ip4,
264 prefix->fp_len,
265 dpo));
266 case FIB_PROTOCOL_IP6:
267 return (ip6_fib_table_fwding_dpo_update(fib_index,
268 &prefix->fp_addr.ip6,
269 prefix->fp_len,
270 dpo));
271 case FIB_PROTOCOL_MPLS:
272 return (mpls_fib_forwarding_table_update(mpls_fib_get(fib_index),
273 prefix->fp_label,
274 prefix->fp_eos,
275 dpo));
276 }
277}
278
279void
280fib_table_fwding_dpo_remove (u32 fib_index,
281 const fib_prefix_t *prefix,
282 const dpo_id_t *dpo)
283{
284 vlib_smp_unsafe_warning();
285
286 switch (prefix->fp_proto)
287 {
288 case FIB_PROTOCOL_IP4:
289 return (ip4_fib_table_fwding_dpo_remove(ip4_fib_get(fib_index),
290 &prefix->fp_addr.ip4,
291 prefix->fp_len,
Neale Rannsa3af3372017-03-28 03:49:52 -0700292 dpo,
293 fib_table_get_less_specific(fib_index,
294 prefix)));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100295 case FIB_PROTOCOL_IP6:
296 return (ip6_fib_table_fwding_dpo_remove(fib_index,
297 &prefix->fp_addr.ip6,
298 prefix->fp_len,
299 dpo));
300 case FIB_PROTOCOL_MPLS:
301 return (mpls_fib_forwarding_table_reset(mpls_fib_get(fib_index),
302 prefix->fp_label,
303 prefix->fp_eos));
304 }
305}
306
Neale Ranns3bab8f92019-12-04 06:11:00 +0000307static void
308fib_table_source_count_inc (fib_table_t *fib_table,
309 fib_source_t source)
310{
311 vec_validate (fib_table->ft_src_route_counts, source);
312 fib_table->ft_src_route_counts[source]++;
313}
314
315static void
316fib_table_source_count_dec (fib_table_t *fib_table,
317 fib_source_t source)
318{
319 vec_validate (fib_table->ft_src_route_counts, source);
320 fib_table->ft_src_route_counts[source]--;
321}
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100322
323fib_node_index_t
324fib_table_entry_special_dpo_add (u32 fib_index,
325 const fib_prefix_t *prefix,
326 fib_source_t source,
327 fib_entry_flag_t flags,
328 const dpo_id_t *dpo)
329{
330 fib_node_index_t fib_entry_index;
331 fib_table_t *fib_table;
332
333 fib_table = fib_table_get(fib_index, prefix->fp_proto);
334 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
335
336 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
337 {
338 fib_entry_index = fib_entry_create_special(fib_index, prefix,
339 source, flags,
340 dpo);
341
342 fib_table_entry_insert(fib_table, prefix, fib_entry_index);
Neale Ranns3bab8f92019-12-04 06:11:00 +0000343 fib_table_source_count_inc(fib_table, source);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100344 }
345 else
346 {
347 int was_sourced;
348
349 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
350 fib_entry_special_add(fib_entry_index, source, flags, dpo);
351
352 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
353 {
Neale Ranns3bab8f92019-12-04 06:11:00 +0000354 fib_table_source_count_inc(fib_table, source);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100355 }
356 }
357
358
359 return (fib_entry_index);
360}
361
362fib_node_index_t
Neale Ranns948e00f2016-10-20 13:39:34 +0100363fib_table_entry_special_dpo_update (u32 fib_index,
364 const fib_prefix_t *prefix,
365 fib_source_t source,
366 fib_entry_flag_t flags,
367 const dpo_id_t *dpo)
368{
369 fib_node_index_t fib_entry_index;
370 fib_table_t *fib_table;
371
372 fib_table = fib_table_get(fib_index, prefix->fp_proto);
373 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
374
375 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
376 {
377 fib_entry_index = fib_entry_create_special(fib_index, prefix,
378 source, flags,
379 dpo);
380
381 fib_table_entry_insert(fib_table, prefix, fib_entry_index);
Neale Ranns3bab8f92019-12-04 06:11:00 +0000382 fib_table_source_count_inc(fib_table, source);
Neale Ranns948e00f2016-10-20 13:39:34 +0100383 }
384 else
385 {
386 int was_sourced;
387
388 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
389
390 if (was_sourced)
391 fib_entry_special_update(fib_entry_index, source, flags, dpo);
392 else
393 fib_entry_special_add(fib_entry_index, source, flags, dpo);
394
395 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
396 {
Neale Ranns3bab8f92019-12-04 06:11:00 +0000397 fib_table_source_count_inc(fib_table, source);
Neale Ranns948e00f2016-10-20 13:39:34 +0100398 }
399 }
400
401 return (fib_entry_index);
402}
403
404fib_node_index_t
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100405fib_table_entry_special_add (u32 fib_index,
406 const fib_prefix_t *prefix,
407 fib_source_t source,
Neale Rannsa0558302017-04-13 00:44:52 -0700408 fib_entry_flag_t flags)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100409{
410 fib_node_index_t fib_entry_index;
Neale Ranns948e00f2016-10-20 13:39:34 +0100411 dpo_id_t tmp_dpo = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100412
Neale Rannsa0558302017-04-13 00:44:52 -0700413 dpo_copy(&tmp_dpo, drop_dpo_get(fib_proto_to_dpo(prefix->fp_proto)));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100414
415 fib_entry_index = fib_table_entry_special_dpo_add(fib_index, prefix, source,
416 flags, &tmp_dpo);
417
418 dpo_unlock(&tmp_dpo);
419
420 return (fib_entry_index);
421}
422
423void
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100424fib_table_entry_special_remove (u32 fib_index,
425 const fib_prefix_t *prefix,
426 fib_source_t source)
427{
428 /*
429 * 1 is it present
430 * yes => remove source
431 * 2 - is it still sourced?
432 * no => cover walk
433 */
434 fib_node_index_t fib_entry_index;
435 fib_table_t *fib_table;
436
437 fib_table = fib_table_get(fib_index, prefix->fp_proto);
438 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
439
440 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
441 {
442 /*
443 * removing an etry that does not exist. i'll allow it.
444 */
445 }
446 else
447 {
448 fib_entry_src_flag_t src_flag;
449 int was_sourced;
450
451 /*
452 * don't nobody go nowhere
453 */
454 fib_entry_lock(fib_entry_index);
455 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
456
457 src_flag = fib_entry_special_remove(fib_entry_index, source);
458
459 if (!(FIB_ENTRY_SRC_FLAG_ADDED & src_flag))
460 {
461 /*
462 * last source gone. remove from the table
463 */
464 fib_table_entry_remove(fib_table, prefix, fib_entry_index);
465
466 /*
467 * now the entry is no longer in the table, we can
468 * inform the entries that it covers to re-calculate their cover
469 */
470 fib_entry_cover_change_notify(fib_entry_index,
471 FIB_NODE_INDEX_INVALID);
472 }
473 /*
474 * else
475 * still has sources, leave it be.
476 */
477 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
478 {
Neale Ranns3bab8f92019-12-04 06:11:00 +0000479 fib_table_source_count_dec(fib_table, source);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100480 }
481
482 fib_entry_unlock(fib_entry_index);
483 }
484}
485
486/**
487 * fib_table_route_path_fixup
488 *
489 * Convert attached hosts to attached next-hops.
490 *
491 * This special case is required because an attached path will link to a
492 * glean, and the FIB entry will have the interface or API/CLI source. When
493 * the ARP/ND process is completes then that source (which will provide a
494 * complete adjacency) will be lower priority and so the FIB entry will
495 * remain linked to a glean and traffic will never reach the hosts. For
496 * an ATTAHCED_HOST path we can link the path directly to the [incomplete]
497 * adjacency.
498 */
499static void
500fib_table_route_path_fixup (const fib_prefix_t *prefix,
Neale Ranns097fa662018-05-01 05:17:55 -0700501 fib_entry_flag_t *eflags,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100502 fib_route_path_t *path)
503{
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800504 /*
505 * not all zeros next hop &&
506 * is recursive path &&
507 * nexthop is same as the route's address
508 */
509 if ((!ip46_address_is_zero(&path->frp_addr)) &&
510 (~0 == path->frp_sw_if_index) &&
511 (0 == ip46_address_cmp(&path->frp_addr, &prefix->fp_addr)))
512 {
Neale Rannse2fe0972020-11-26 08:37:27 +0000513 /* Prefix recurses via itself */
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800514 path->frp_flags |= FIB_ROUTE_PATH_DROP;
515 }
Neale Ranns097fa662018-05-01 05:17:55 -0700516 if (!(path->frp_flags & FIB_ROUTE_PATH_LOCAL) &&
517 fib_prefix_is_host(prefix) &&
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100518 ip46_address_is_zero(&path->frp_addr) &&
Neale Ranns6f631152017-10-03 08:20:21 -0700519 path->frp_sw_if_index != ~0 &&
520 path->frp_proto != DPO_PROTO_ETHERNET)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100521 {
522 path->frp_addr = prefix->fp_addr;
Neale Ranns4b919a52017-03-11 05:55:21 -0800523 path->frp_flags |= FIB_ROUTE_PATH_ATTACHED;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100524 }
Neale Rannse2fe0972020-11-26 08:37:27 +0000525 else if ((*eflags & FIB_ENTRY_FLAG_CONNECTED) &&
526 !(*eflags & FIB_ENTRY_FLAG_LOCAL))
527 {
528 if (ip46_address_is_zero(&path->frp_addr))
529 {
530 path->frp_flags |= FIB_ROUTE_PATH_GLEAN;
531 fib_prefix_normalize(prefix, &path->frp_connected);
532 }
533 }
Neale Ranns097fa662018-05-01 05:17:55 -0700534 if (*eflags & FIB_ENTRY_FLAG_DROP)
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800535 {
536 path->frp_flags |= FIB_ROUTE_PATH_DROP;
537 }
Neale Ranns097fa662018-05-01 05:17:55 -0700538 if (*eflags & FIB_ENTRY_FLAG_LOCAL)
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800539 {
540 path->frp_flags |= FIB_ROUTE_PATH_LOCAL;
541 }
Neale Ranns097fa662018-05-01 05:17:55 -0700542 if (*eflags & FIB_ENTRY_FLAG_EXCLUSIVE)
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800543 {
544 path->frp_flags |= FIB_ROUTE_PATH_EXCLUSIVE;
545 }
Neale Ranns097fa662018-05-01 05:17:55 -0700546 if (path->frp_flags & FIB_ROUTE_PATH_LOCAL)
547 {
548 *eflags |= FIB_ENTRY_FLAG_LOCAL;
549
550 if (path->frp_sw_if_index != ~0)
551 {
552 *eflags |= FIB_ENTRY_FLAG_CONNECTED;
553 }
554 }
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800555}
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100556
557fib_node_index_t
558fib_table_entry_path_add (u32 fib_index,
559 const fib_prefix_t *prefix,
560 fib_source_t source,
561 fib_entry_flag_t flags,
Neale Rannsda78f952017-05-24 09:15:43 -0700562 dpo_proto_t next_hop_proto,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100563 const ip46_address_t *next_hop,
564 u32 next_hop_sw_if_index,
565 u32 next_hop_fib_index,
566 u32 next_hop_weight,
Neale Ranns31ed7442018-02-23 05:29:09 -0800567 fib_mpls_label_t *next_hop_labels,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100568 fib_route_path_flags_t path_flags)
569{
570 fib_route_path_t path = {
571 .frp_proto = next_hop_proto,
572 .frp_addr = (NULL == next_hop? zero_addr : *next_hop),
573 .frp_sw_if_index = next_hop_sw_if_index,
574 .frp_fib_index = next_hop_fib_index,
575 .frp_weight = next_hop_weight,
576 .frp_flags = path_flags,
Neale Ranns097fa662018-05-01 05:17:55 -0700577 .frp_rpf_id = INDEX_INVALID,
Neale Rannsad422ed2016-11-02 14:20:04 +0000578 .frp_label_stack = next_hop_labels,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100579 };
580 fib_node_index_t fib_entry_index;
581 fib_route_path_t *paths = NULL;
582
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100583 vec_add1(paths, path);
584
585 fib_entry_index = fib_table_entry_path_add2(fib_index, prefix,
586 source, flags, paths);
587
588 vec_free(paths);
589 return (fib_entry_index);
590}
591
Neale Rannsda5dedf2020-01-20 02:28:00 +0000592static int
593fib_route_path_cmp_for_sort (void * v1,
594 void * v2)
595{
596 return (fib_route_path_cmp(v1, v2));
597}
598
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100599fib_node_index_t
600fib_table_entry_path_add2 (u32 fib_index,
601 const fib_prefix_t *prefix,
602 fib_source_t source,
603 fib_entry_flag_t flags,
Neale Ranns097fa662018-05-01 05:17:55 -0700604 fib_route_path_t *rpaths)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100605{
606 fib_node_index_t fib_entry_index;
607 fib_table_t *fib_table;
Neale Rannsad422ed2016-11-02 14:20:04 +0000608 u32 ii;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100609
610 fib_table = fib_table_get(fib_index, prefix->fp_proto);
611 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
612
Neale Ranns097fa662018-05-01 05:17:55 -0700613 for (ii = 0; ii < vec_len(rpaths); ii++)
Neale Rannsad422ed2016-11-02 14:20:04 +0000614 {
Neale Ranns097fa662018-05-01 05:17:55 -0700615 fib_table_route_path_fixup(prefix, &flags, &rpaths[ii]);
Neale Rannsad422ed2016-11-02 14:20:04 +0000616 }
Neale Rannsda5dedf2020-01-20 02:28:00 +0000617 /*
618 * sort the paths provided by the control plane. this means
619 * the paths and the extension on the entry will be sorted.
620 */
621 vec_sort_with_function(rpaths, fib_route_path_cmp_for_sort);
Neale Rannsad422ed2016-11-02 14:20:04 +0000622
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100623 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
624 {
625 fib_entry_index = fib_entry_create(fib_index, prefix,
626 source, flags,
Neale Ranns097fa662018-05-01 05:17:55 -0700627 rpaths);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100628
629 fib_table_entry_insert(fib_table, prefix, fib_entry_index);
Neale Ranns3bab8f92019-12-04 06:11:00 +0000630 fib_table_source_count_inc(fib_table, source);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100631 }
632 else
633 {
634 int was_sourced;
635
636 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
Neale Ranns097fa662018-05-01 05:17:55 -0700637 fib_entry_path_add(fib_entry_index, source, flags, rpaths);;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100638
639 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
640 {
Neale Ranns3bab8f92019-12-04 06:11:00 +0000641 fib_table_source_count_inc(fib_table, source);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100642 }
643 }
644
645 return (fib_entry_index);
646}
647
648void
649fib_table_entry_path_remove2 (u32 fib_index,
Neale Rannsad422ed2016-11-02 14:20:04 +0000650 const fib_prefix_t *prefix,
651 fib_source_t source,
Neale Ranns097fa662018-05-01 05:17:55 -0700652 fib_route_path_t *rpaths)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100653{
654 /*
655 * 1 is it present
656 * yes => remove source
657 * 2 - is it still sourced?
658 * no => cover walk
659 */
660 fib_node_index_t fib_entry_index;
Neale Ranns097fa662018-05-01 05:17:55 -0700661 fib_route_path_t *rpath;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100662 fib_table_t *fib_table;
663
664 fib_table = fib_table_get(fib_index, prefix->fp_proto);
665 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
666
667 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
668 {
669 /*
670 * removing an etry that does not exist. i'll allow it.
671 */
672 }
673 else
674 {
675 fib_entry_src_flag_t src_flag;
676 int was_sourced;
677
Neale Rannsf12a83f2017-04-18 09:09:40 -0700678 /*
679 * if it's not sourced, then there's nowt to remove
680 */
681 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
682 if (!was_sourced)
683 {
684 return;
685 }
686
687 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100688 * don't nobody go nowhere
689 */
690 fib_entry_lock(fib_entry_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100691
Neale Ranns097fa662018-05-01 05:17:55 -0700692 vec_foreach(rpath, rpaths)
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800693 {
Neale Ranns097fa662018-05-01 05:17:55 -0700694 fib_entry_flag_t eflags;
695
696 eflags = fib_entry_get_flags_for_source(fib_entry_index,
697 source);
698 fib_table_route_path_fixup(prefix, &eflags, rpath);
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800699 }
700
Neale Ranns097fa662018-05-01 05:17:55 -0700701 src_flag = fib_entry_path_remove(fib_entry_index, source, rpaths);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100702
703 if (!(FIB_ENTRY_SRC_FLAG_ADDED & src_flag))
704 {
705 /*
706 * last source gone. remove from the table
707 */
708 fib_table_entry_remove(fib_table, prefix, fib_entry_index);
709
710 /*
711 * now the entry is no longer in the table, we can
712 * inform the entries that it covers to re-calculate their cover
713 */
714 fib_entry_cover_change_notify(fib_entry_index,
715 FIB_NODE_INDEX_INVALID);
716 }
717 /*
718 * else
719 * still has sources, leave it be.
720 */
721 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
722 {
Neale Ranns3bab8f92019-12-04 06:11:00 +0000723 fib_table_source_count_dec(fib_table, source);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100724 }
725
726 fib_entry_unlock(fib_entry_index);
727 }
728}
729
730void
731fib_table_entry_path_remove (u32 fib_index,
732 const fib_prefix_t *prefix,
733 fib_source_t source,
Neale Rannsda78f952017-05-24 09:15:43 -0700734 dpo_proto_t next_hop_proto,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100735 const ip46_address_t *next_hop,
736 u32 next_hop_sw_if_index,
737 u32 next_hop_fib_index,
738 u32 next_hop_weight,
739 fib_route_path_flags_t path_flags)
740{
741 /*
742 * 1 is it present
743 * yes => remove source
744 * 2 - is it still sourced?
745 * no => cover walk
746 */
747 fib_route_path_t path = {
748 .frp_proto = next_hop_proto,
749 .frp_addr = (NULL == next_hop? zero_addr : *next_hop),
750 .frp_sw_if_index = next_hop_sw_if_index,
751 .frp_fib_index = next_hop_fib_index,
752 .frp_weight = next_hop_weight,
753 .frp_flags = path_flags,
754 };
755 fib_route_path_t *paths = NULL;
756
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100757 vec_add1(paths, path);
758
759 fib_table_entry_path_remove2(fib_index, prefix, source, paths);
760
761 vec_free(paths);
762}
763
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100764fib_node_index_t
765fib_table_entry_update (u32 fib_index,
766 const fib_prefix_t *prefix,
767 fib_source_t source,
768 fib_entry_flag_t flags,
Neale Rannsad422ed2016-11-02 14:20:04 +0000769 fib_route_path_t *paths)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100770{
771 fib_node_index_t fib_entry_index;
772 fib_table_t *fib_table;
Neale Rannsad422ed2016-11-02 14:20:04 +0000773 u32 ii;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100774
775 fib_table = fib_table_get(fib_index, prefix->fp_proto);
776 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
777
Neale Rannsad422ed2016-11-02 14:20:04 +0000778 for (ii = 0; ii < vec_len(paths); ii++)
779 {
Neale Ranns097fa662018-05-01 05:17:55 -0700780 fib_table_route_path_fixup(prefix, &flags, &paths[ii]);
Neale Rannsad422ed2016-11-02 14:20:04 +0000781 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100782 /*
783 * sort the paths provided by the control plane. this means
784 * the paths and the extension on the entry will be sorted.
785 */
Neale Rannsad422ed2016-11-02 14:20:04 +0000786 vec_sort_with_function(paths, fib_route_path_cmp_for_sort);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100787
788 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
789 {
790 fib_entry_index = fib_entry_create(fib_index, prefix,
791 source, flags,
792 paths);
793
794 fib_table_entry_insert(fib_table, prefix, fib_entry_index);
Neale Ranns3bab8f92019-12-04 06:11:00 +0000795 fib_table_source_count_inc(fib_table, source);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100796 }
797 else
798 {
799 int was_sourced;
800
801 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
802 fib_entry_update(fib_entry_index, source, flags, paths);
803
804 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
805 {
Neale Ranns3bab8f92019-12-04 06:11:00 +0000806 fib_table_source_count_inc(fib_table, source);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100807 }
808 }
809
810 return (fib_entry_index);
811}
812
813fib_node_index_t
814fib_table_entry_update_one_path (u32 fib_index,
815 const fib_prefix_t *prefix,
816 fib_source_t source,
817 fib_entry_flag_t flags,
Neale Rannsda78f952017-05-24 09:15:43 -0700818 dpo_proto_t next_hop_proto,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100819 const ip46_address_t *next_hop,
820 u32 next_hop_sw_if_index,
821 u32 next_hop_fib_index,
822 u32 next_hop_weight,
Neale Ranns31ed7442018-02-23 05:29:09 -0800823 fib_mpls_label_t *next_hop_labels,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100824 fib_route_path_flags_t path_flags)
825{
826 fib_node_index_t fib_entry_index;
827 fib_route_path_t path = {
828 .frp_proto = next_hop_proto,
829 .frp_addr = (NULL == next_hop? zero_addr : *next_hop),
830 .frp_sw_if_index = next_hop_sw_if_index,
831 .frp_fib_index = next_hop_fib_index,
832 .frp_weight = next_hop_weight,
833 .frp_flags = path_flags,
Neale Rannsad422ed2016-11-02 14:20:04 +0000834 .frp_label_stack = next_hop_labels,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100835 };
836 fib_route_path_t *paths = NULL;
837
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100838 vec_add1(paths, path);
839
840 fib_entry_index =
841 fib_table_entry_update(fib_index, prefix, source, flags, paths);
842
843 vec_free(paths);
844
845 return (fib_entry_index);
846}
847
848static void
849fib_table_entry_delete_i (u32 fib_index,
850 fib_node_index_t fib_entry_index,
851 const fib_prefix_t *prefix,
852 fib_source_t source)
853{
854 fib_entry_src_flag_t src_flag;
855 fib_table_t *fib_table;
856 int was_sourced;
857
858 fib_table = fib_table_get(fib_index, prefix->fp_proto);
859 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
860
861 /*
862 * don't nobody go nowhere
863 */
864 fib_entry_lock(fib_entry_index);
865
866 src_flag = fib_entry_delete(fib_entry_index, source);
867
868 if (!(FIB_ENTRY_SRC_FLAG_ADDED & src_flag))
869 {
870 /*
871 * last source gone. remove from the table
872 */
873 fib_table_entry_remove(fib_table, prefix, fib_entry_index);
874
875 /*
876 * now the entry is no longer in the table, we can
877 * inform the entries that it covers to re-calculate their cover
878 */
879 fib_entry_cover_change_notify(fib_entry_index,
880 FIB_NODE_INDEX_INVALID);
881 }
882 /*
883 * else
884 * still has sources, leave it be.
885 */
886 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
887 {
Neale Ranns3bab8f92019-12-04 06:11:00 +0000888 fib_table_source_count_dec(fib_table, source);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100889 }
890
891 fib_entry_unlock(fib_entry_index);
892}
893
894void
895fib_table_entry_delete (u32 fib_index,
896 const fib_prefix_t *prefix,
897 fib_source_t source)
898{
899 fib_node_index_t fib_entry_index;
900
901 fib_entry_index = fib_table_lookup_exact_match(fib_index, prefix);
902
903 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
904 {
905 /*
906 * removing an etry that does not exist.
907 * i'll allow it, but i won't like it.
908 */
Dave Barach59b25652017-09-10 15:04:27 -0400909 if (0)
910 clib_warning("%U not in FIB", format_fib_prefix, prefix);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100911 }
912 else
913 {
914 fib_table_entry_delete_i(fib_index, fib_entry_index, prefix, source);
915 }
916}
917
918void
919fib_table_entry_delete_index (fib_node_index_t fib_entry_index,
920 fib_source_t source)
921{
Neale Rannsc5d43172018-07-30 08:04:40 -0700922 const fib_prefix_t *prefix;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100923
Neale Rannsc5d43172018-07-30 08:04:40 -0700924 prefix = fib_entry_get_prefix(fib_entry_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100925
926 fib_table_entry_delete_i(fib_entry_get_fib_index(fib_entry_index),
Neale Rannsc5d43172018-07-30 08:04:40 -0700927 fib_entry_index, prefix, source);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100928}
929
Neale Ranns008dbe12018-09-07 09:32:36 -0700930u32
Neale Ranns28c142e2018-09-07 09:37:07 -0700931fib_table_entry_get_stats_index (u32 fib_index,
932 const fib_prefix_t *prefix)
Neale Ranns008dbe12018-09-07 09:32:36 -0700933{
934 return (fib_entry_get_stats_index(
935 fib_table_lookup_exact_match(fib_index, prefix)));
936}
937
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100938fib_node_index_t
939fib_table_entry_local_label_add (u32 fib_index,
940 const fib_prefix_t *prefix,
941 mpls_label_t label)
942{
943 fib_node_index_t fib_entry_index;
944
Neale Ranns1357f3b2016-10-16 12:01:42 -0700945 fib_entry_index = fib_table_lookup_exact_match(fib_index, prefix);
946
947 if (FIB_NODE_INDEX_INVALID == fib_entry_index ||
948 !fib_entry_is_sourced(fib_entry_index, FIB_SOURCE_MPLS))
949 {
950 /*
951 * only source the prefix once. this allows the label change
952 * operation to work
953 */
954 fib_entry_index = fib_table_entry_special_dpo_add(fib_index, prefix,
955 FIB_SOURCE_MPLS,
956 FIB_ENTRY_FLAG_NONE,
957 NULL);
958 }
959
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100960 fib_entry_set_source_data(fib_entry_index, FIB_SOURCE_MPLS, &label);
961
962 return (fib_entry_index);
963}
964
965void
966fib_table_entry_local_label_remove (u32 fib_index,
967 const fib_prefix_t *prefix,
968 mpls_label_t label)
969{
970 fib_node_index_t fib_entry_index;
971 const void *data;
972 mpls_label_t pl;
973
974 fib_entry_index = fib_table_lookup_exact_match(fib_index, prefix);
975
976 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
977 return;
978
979 data = fib_entry_get_source_data(fib_entry_index, FIB_SOURCE_MPLS);
980
981 if (NULL == data)
982 return;
983
984 pl = *(mpls_label_t*)data;
985
986 if (pl != label)
987 return;
988
989 pl = MPLS_LABEL_INVALID;
990
991 fib_entry_set_source_data(fib_entry_index, FIB_SOURCE_MPLS, &pl);
992 fib_table_entry_special_remove(fib_index,
993 prefix,
994 FIB_SOURCE_MPLS);
995}
996
997u32
998fib_table_get_index_for_sw_if_index (fib_protocol_t proto,
999 u32 sw_if_index)
1000{
1001 switch (proto)
1002 {
1003 case FIB_PROTOCOL_IP4:
1004 return (ip4_fib_table_get_index_for_sw_if_index(sw_if_index));
1005 case FIB_PROTOCOL_IP6:
1006 return (ip6_fib_table_get_index_for_sw_if_index(sw_if_index));
1007 case FIB_PROTOCOL_MPLS:
1008 return (mpls_fib_table_get_index_for_sw_if_index(sw_if_index));
1009 }
1010 return (~0);
1011}
1012
1013flow_hash_config_t
1014fib_table_get_flow_hash_config (u32 fib_index,
1015 fib_protocol_t proto)
1016{
Neale Ranns227038a2017-04-21 01:07:59 -07001017 fib_table_t *fib;
1018
1019 fib = fib_table_get(fib_index, proto);
1020
1021 return (fib->ft_flow_hash_config);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001022}
Neale Rannsd792d9c2017-10-21 10:53:20 -07001023
Neale Ranns41da54f2017-05-02 10:15:19 -07001024flow_hash_config_t
1025fib_table_get_default_flow_hash_config (fib_protocol_t proto)
1026{
1027 switch (proto)
1028 {
1029 case FIB_PROTOCOL_IP4:
1030 case FIB_PROTOCOL_IP6:
1031 return (IP_FLOW_HASH_DEFAULT);
1032
1033 case FIB_PROTOCOL_MPLS:
1034 return (MPLS_FLOW_HASH_DEFAULT);
1035 }
1036
1037 ASSERT(0);
1038 return (IP_FLOW_HASH_DEFAULT);
1039}
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001040
Neale Ranns227038a2017-04-21 01:07:59 -07001041/**
1042 * @brief Table set flow hash config context.
1043 */
1044typedef struct fib_table_set_flow_hash_config_ctx_t_
1045{
1046 /**
1047 * the flow hash config to set
1048 */
1049 flow_hash_config_t hash_config;
1050} fib_table_set_flow_hash_config_ctx_t;
1051
Neale Ranns89541992017-04-06 04:41:02 -07001052static fib_table_walk_rc_t
Neale Ranns227038a2017-04-21 01:07:59 -07001053fib_table_set_flow_hash_config_cb (fib_node_index_t fib_entry_index,
1054 void *arg)
1055{
1056 fib_table_set_flow_hash_config_ctx_t *ctx = arg;
1057
1058 fib_entry_set_flow_hash_config(fib_entry_index, ctx->hash_config);
1059
Neale Ranns89541992017-04-06 04:41:02 -07001060 return (FIB_TABLE_WALK_CONTINUE);
Neale Ranns227038a2017-04-21 01:07:59 -07001061}
1062
1063void
1064fib_table_set_flow_hash_config (u32 fib_index,
1065 fib_protocol_t proto,
1066 flow_hash_config_t hash_config)
1067{
1068 fib_table_set_flow_hash_config_ctx_t ctx = {
1069 .hash_config = hash_config,
1070 };
1071 fib_table_t *fib;
1072
1073 fib = fib_table_get(fib_index, proto);
1074 fib->ft_flow_hash_config = hash_config;
1075
1076 fib_table_walk(fib_index, proto,
1077 fib_table_set_flow_hash_config_cb,
1078 &ctx);
1079}
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001080
1081u32
1082fib_table_get_table_id_for_sw_if_index (fib_protocol_t proto,
1083 u32 sw_if_index)
1084{
1085 fib_table_t *fib_table;
1086
1087 fib_table = fib_table_get(fib_table_get_index_for_sw_if_index(
1088 proto, sw_if_index),
1089 proto);
1090
1091 return ((NULL != fib_table ? fib_table->ft_table_id : ~0));
1092}
1093
1094u32
Neale Ranns25b04942018-04-04 09:34:50 -07001095fib_table_get_table_id (u32 fib_index,
1096 fib_protocol_t proto)
1097{
1098 fib_table_t *fib_table;
1099
1100 fib_table = fib_table_get(fib_index, proto);
1101
1102 return ((NULL != fib_table ? fib_table->ft_table_id : ~0));
1103}
1104
1105u32
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001106fib_table_find (fib_protocol_t proto,
1107 u32 table_id)
1108{
1109 switch (proto)
1110 {
1111 case FIB_PROTOCOL_IP4:
1112 return (ip4_fib_index_from_table_id(table_id));
1113 case FIB_PROTOCOL_IP6:
1114 return (ip6_fib_index_from_table_id(table_id));
1115 case FIB_PROTOCOL_MPLS:
1116 return (mpls_fib_index_from_table_id(table_id));
1117 }
1118 return (~0);
1119}
1120
Neale Ranns2297af02017-09-12 09:45:04 -07001121static u32
1122fib_table_find_or_create_and_lock_i (fib_protocol_t proto,
1123 u32 table_id,
1124 fib_source_t src,
1125 const u8 *name)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001126{
1127 fib_table_t *fib_table;
1128 fib_node_index_t fi;
1129
1130 switch (proto)
1131 {
1132 case FIB_PROTOCOL_IP4:
Neale Ranns15002542017-09-10 04:39:11 -07001133 fi = ip4_fib_table_find_or_create_and_lock(table_id, src);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001134 break;
1135 case FIB_PROTOCOL_IP6:
Neale Ranns15002542017-09-10 04:39:11 -07001136 fi = ip6_fib_table_find_or_create_and_lock(table_id, src);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001137 break;
1138 case FIB_PROTOCOL_MPLS:
Neale Ranns15002542017-09-10 04:39:11 -07001139 fi = mpls_fib_table_find_or_create_and_lock(table_id, src);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001140 break;
1141 default:
1142 return (~0);
1143 }
1144
1145 fib_table = fib_table_get(fi, proto);
1146
Neale Ranns2297af02017-09-12 09:45:04 -07001147 if (NULL == fib_table->ft_desc)
1148 {
1149 if (name && name[0])
1150 {
1151 fib_table->ft_desc = format(NULL, "%s", name);
1152 }
1153 else
1154 {
1155 fib_table->ft_desc = format(NULL, "%U-VRF:%d",
1156 format_fib_protocol, proto,
1157 table_id);
1158 }
1159 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001160
1161 return (fi);
1162}
1163
1164u32
Neale Ranns2297af02017-09-12 09:45:04 -07001165fib_table_find_or_create_and_lock (fib_protocol_t proto,
1166 u32 table_id,
1167 fib_source_t src)
1168{
1169 return (fib_table_find_or_create_and_lock_i(proto, table_id,
1170 src, NULL));
1171}
1172
1173u32
1174fib_table_find_or_create_and_lock_w_name (fib_protocol_t proto,
1175 u32 table_id,
1176 fib_source_t src,
1177 const u8 *name)
1178{
1179 return (fib_table_find_or_create_and_lock_i(proto, table_id,
1180 src, name));
1181}
1182
1183u32
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001184fib_table_create_and_lock (fib_protocol_t proto,
Neale Ranns15002542017-09-10 04:39:11 -07001185 fib_source_t src,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001186 const char *const fmt,
1187 ...)
1188{
1189 fib_table_t *fib_table;
1190 fib_node_index_t fi;
1191 va_list ap;
1192
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001193
1194 switch (proto)
1195 {
1196 case FIB_PROTOCOL_IP4:
Neale Ranns15002542017-09-10 04:39:11 -07001197 fi = ip4_fib_table_create_and_lock(src);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001198 break;
1199 case FIB_PROTOCOL_IP6:
Neale Ranns53da2212018-02-24 02:11:19 -08001200 fi = ip6_fib_table_create_and_lock(src, FIB_TABLE_FLAG_NONE, NULL);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001201 break;
1202 case FIB_PROTOCOL_MPLS:
Neale Ranns15002542017-09-10 04:39:11 -07001203 fi = mpls_fib_table_create_and_lock(src);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001204 break;
1205 default:
1206 return (~0);
1207 }
1208
1209 fib_table = fib_table_get(fi, proto);
1210
Paul Vinciguerra0c0383d2018-10-24 12:14:09 -07001211 va_start(ap, fmt);
1212
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001213 fib_table->ft_desc = va_format(fib_table->ft_desc, fmt, &ap);
1214
1215 va_end(ap);
1216 return (fi);
1217}
1218
1219static void
1220fib_table_destroy (fib_table_t *fib_table)
1221{
1222 vec_free(fib_table->ft_desc);
1223
1224 switch (fib_table->ft_proto)
1225 {
1226 case FIB_PROTOCOL_IP4:
Neale Rannsa3af3372017-03-28 03:49:52 -07001227 ip4_fib_table_destroy(fib_table->ft_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001228 break;
1229 case FIB_PROTOCOL_IP6:
1230 ip6_fib_table_destroy(fib_table->ft_index);
1231 break;
1232 case FIB_PROTOCOL_MPLS:
Neale Rannsa3af3372017-03-28 03:49:52 -07001233 mpls_fib_table_destroy(fib_table->ft_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001234 break;
1235 }
1236}
Neale Ranns5a8123b2017-01-26 01:18:23 -08001237
Neale Ranns32e1c012016-11-22 17:07:28 +00001238void
1239fib_table_walk (u32 fib_index,
1240 fib_protocol_t proto,
1241 fib_table_walk_fn_t fn,
1242 void *ctx)
1243{
1244 switch (proto)
1245 {
1246 case FIB_PROTOCOL_IP4:
1247 ip4_fib_table_walk(ip4_fib_get(fib_index), fn, ctx);
1248 break;
1249 case FIB_PROTOCOL_IP6:
1250 ip6_fib_table_walk(fib_index, fn, ctx);
1251 break;
1252 case FIB_PROTOCOL_MPLS:
1253 mpls_fib_table_walk(mpls_fib_get(fib_index), fn, ctx);
1254 break;
1255 }
1256}
1257
Neale Ranns976b2592019-12-04 06:11:00 +00001258typedef struct fib_table_walk_w_src_ctx_t_
1259{
1260 fib_table_walk_fn_t fn;
1261 void *data;
1262 fib_source_t src;
1263} fib_table_walk_w_src_cxt_t;
1264
1265static fib_table_walk_rc_t
1266fib_table_walk_w_src_cb (fib_node_index_t fei,
1267 void *arg)
1268{
1269 fib_table_walk_w_src_cxt_t *ctx = arg;
1270
1271 if (ctx->src == fib_entry_get_best_source(fei))
1272 {
1273 return (ctx->fn(fei, ctx->data));
1274 }
1275 return (FIB_TABLE_WALK_CONTINUE);
1276}
1277
1278void
1279fib_table_walk_w_src (u32 fib_index,
1280 fib_protocol_t proto,
1281 fib_source_t src,
1282 fib_table_walk_fn_t fn,
1283 void *data)
1284{
1285 fib_table_walk_w_src_cxt_t ctx = {
1286 .fn = fn,
1287 .src = src,
1288 .data = data,
1289 };
1290
1291 fib_table_walk(fib_index, proto, fib_table_walk_w_src_cb, &ctx);
1292}
1293
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001294void
Neale Ranns89541992017-04-06 04:41:02 -07001295fib_table_sub_tree_walk (u32 fib_index,
1296 fib_protocol_t proto,
1297 const fib_prefix_t *root,
1298 fib_table_walk_fn_t fn,
1299 void *ctx)
1300{
1301 switch (proto)
1302 {
1303 case FIB_PROTOCOL_IP4:
1304 ip4_fib_table_sub_tree_walk(ip4_fib_get(fib_index), root, fn, ctx);
1305 break;
1306 case FIB_PROTOCOL_IP6:
1307 ip6_fib_table_sub_tree_walk(fib_index, root, fn, ctx);
1308 break;
1309 case FIB_PROTOCOL_MPLS:
1310 break;
1311 }
1312}
1313
Neale Ranns3bab8f92019-12-04 06:11:00 +00001314static void
1315fib_table_lock_dec (fib_table_t *fib_table,
1316 fib_source_t source)
1317{
1318 vec_validate(fib_table->ft_locks, source);
1319
1320 fib_table->ft_locks[source]--;
1321 fib_table->ft_total_locks--;
1322}
1323
1324static void
1325fib_table_lock_inc (fib_table_t *fib_table,
1326 fib_source_t source)
1327{
1328 vec_validate(fib_table->ft_locks, source);
1329
Miklos Tirpak4a94cd22019-12-20 11:55:43 +01001330 ASSERT(fib_table->ft_total_locks < (0xffffffff - 1));
Neale Ranns3bab8f92019-12-04 06:11:00 +00001331 fib_table->ft_locks[source]++;
1332 fib_table->ft_total_locks++;
1333}
1334
Neale Ranns89541992017-04-06 04:41:02 -07001335void
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001336fib_table_unlock (u32 fib_index,
Neale Ranns15002542017-09-10 04:39:11 -07001337 fib_protocol_t proto,
1338 fib_source_t source)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001339{
1340 fib_table_t *fib_table;
1341
1342 fib_table = fib_table_get(fib_index, proto);
Neale Ranns3bab8f92019-12-04 06:11:00 +00001343 fib_table_lock_dec(fib_table, source);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001344
Neale Ranns3bab8f92019-12-04 06:11:00 +00001345 if (0 == fib_table->ft_total_locks)
Neale Ranns15002542017-09-10 04:39:11 -07001346 {
1347 /*
1348 * no more locak from any source - kill it
1349 */
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001350 fib_table_destroy(fib_table);
1351 }
1352}
Neale Ranns15002542017-09-10 04:39:11 -07001353
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001354void
1355fib_table_lock (u32 fib_index,
Neale Ranns15002542017-09-10 04:39:11 -07001356 fib_protocol_t proto,
1357 fib_source_t source)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001358{
1359 fib_table_t *fib_table;
1360
1361 fib_table = fib_table_get(fib_index, proto);
Neale Ranns6fff24a2018-09-10 19:14:07 -07001362
Neale Ranns3bab8f92019-12-04 06:11:00 +00001363 fib_table_lock_inc(fib_table, source);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001364}
1365
1366u32
1367fib_table_get_num_entries (u32 fib_index,
1368 fib_protocol_t proto,
1369 fib_source_t source)
1370{
1371 fib_table_t *fib_table;
1372
1373 fib_table = fib_table_get(fib_index, proto);
1374
1375 return (fib_table->ft_src_route_counts[source]);
1376}
1377
1378u8*
Christophe Fontained3c008d2017-10-02 18:10:54 +02001379format_fib_table_name (u8* s, va_list* ap)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001380{
Christophe Fontained3c008d2017-10-02 18:10:54 +02001381 fib_node_index_t fib_index = va_arg(*ap, fib_node_index_t);
1382 fib_protocol_t proto = va_arg(*ap, int); // int promotion
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001383 fib_table_t *fib_table;
1384
1385 fib_table = fib_table_get(fib_index, proto);
1386
1387 s = format(s, "%v", fib_table->ft_desc);
1388
1389 return (s);
1390}
1391
Neale Ranns9db6ada2019-11-08 12:42:31 +00001392u8*
1393format_fib_table_flags (u8 *s, va_list *args)
1394{
1395 fib_table_flags_t flags = va_arg(*args, int);
1396 fib_table_attribute_t attr;
1397
1398 if (!flags)
1399 {
1400 return format(s, "none");
1401 }
1402
1403 FOR_EACH_FIB_TABLE_ATTRIBUTE(attr) {
1404 if (1 << attr & flags) {
1405 s = format(s, "%s", fib_table_flags_strings[attr]);
1406 }
1407 }
1408
1409 return (s);
1410}
1411
Neale Ranns32e1c012016-11-22 17:07:28 +00001412/**
1413 * @brief Table flush context. Store the indicies of matching FIB entries
1414 * that need to be removed.
1415 */
1416typedef struct fib_table_flush_ctx_t_
1417{
1418 /**
1419 * The list of entries to flush
1420 */
1421 fib_node_index_t *ftf_entries;
1422
1423 /**
1424 * The source we are flushing
1425 */
1426 fib_source_t ftf_source;
1427} fib_table_flush_ctx_t;
1428
Neale Ranns89541992017-04-06 04:41:02 -07001429static fib_table_walk_rc_t
Neale Ranns32e1c012016-11-22 17:07:28 +00001430fib_table_flush_cb (fib_node_index_t fib_entry_index,
1431 void *arg)
1432{
1433 fib_table_flush_ctx_t *ctx = arg;
1434
1435 if (fib_entry_is_sourced(fib_entry_index, ctx->ftf_source))
1436 {
1437 vec_add1(ctx->ftf_entries, fib_entry_index);
1438 }
Neale Ranns89541992017-04-06 04:41:02 -07001439 return (FIB_TABLE_WALK_CONTINUE);
Neale Ranns32e1c012016-11-22 17:07:28 +00001440}
1441
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001442void
1443fib_table_flush (u32 fib_index,
1444 fib_protocol_t proto,
1445 fib_source_t source)
1446{
Neale Ranns32e1c012016-11-22 17:07:28 +00001447 fib_node_index_t *fib_entry_index;
1448 fib_table_flush_ctx_t ctx = {
1449 .ftf_entries = NULL,
1450 .ftf_source = source,
1451 };
1452
1453 fib_table_walk(fib_index, proto,
1454 fib_table_flush_cb,
1455 &ctx);
1456
1457 vec_foreach(fib_entry_index, ctx.ftf_entries)
1458 {
Neale Rannsa8d9f302017-02-20 09:17:02 -08001459 fib_table_entry_delete_index(*fib_entry_index, source);
Neale Ranns32e1c012016-11-22 17:07:28 +00001460 }
1461
1462 vec_free(ctx.ftf_entries);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001463}
Neale Rannsc87aafa2017-11-29 00:59:31 -08001464
Neale Ranns9db6ada2019-11-08 12:42:31 +00001465static fib_table_walk_rc_t
1466fib_table_mark_cb (fib_node_index_t fib_entry_index,
1467 void *arg)
1468{
1469 fib_table_flush_ctx_t *ctx = arg;
1470
1471 if (fib_entry_is_sourced(fib_entry_index, ctx->ftf_source))
1472 {
1473 fib_entry_mark(fib_entry_index, ctx->ftf_source);
1474 }
1475 return (FIB_TABLE_WALK_CONTINUE);
1476}
1477
1478void
1479fib_table_mark (u32 fib_index,
1480 fib_protocol_t proto,
1481 fib_source_t source)
1482{
1483 fib_table_flush_ctx_t ctx = {
1484 .ftf_source = source,
1485 };
1486 fib_table_t *fib_table;
1487
1488 fib_table = fib_table_get(fib_index, proto);
1489
1490 fib_table->ft_epoch++;
1491 fib_table->ft_flags |= FIB_TABLE_FLAG_RESYNC;
1492
1493 fib_table_walk(fib_index, proto,
1494 fib_table_mark_cb,
1495 &ctx);
1496}
1497
1498static fib_table_walk_rc_t
1499fib_table_sweep_cb (fib_node_index_t fib_entry_index,
1500 void *arg)
1501{
1502 fib_table_flush_ctx_t *ctx = arg;
1503
1504 if (fib_entry_is_marked(fib_entry_index, ctx->ftf_source))
1505 {
1506 vec_add1(ctx->ftf_entries, fib_entry_index);
1507 }
1508 return (FIB_TABLE_WALK_CONTINUE);
1509}
1510
1511void
1512fib_table_sweep (u32 fib_index,
1513 fib_protocol_t proto,
1514 fib_source_t source)
1515{
1516 fib_table_flush_ctx_t ctx = {
1517 .ftf_source = source,
1518 };
1519 fib_node_index_t *fib_entry_index;
1520 fib_table_t *fib_table;
1521
1522 fib_table = fib_table_get(fib_index, proto);
1523
1524 fib_table->ft_flags &= ~FIB_TABLE_FLAG_RESYNC;
1525
1526 fib_table_walk(fib_index, proto,
1527 fib_table_sweep_cb,
1528 &ctx);
1529
1530 vec_foreach(fib_entry_index, ctx.ftf_entries)
1531 {
1532 fib_table_entry_delete_index(*fib_entry_index, source);
1533 }
1534
1535 vec_free(ctx.ftf_entries);
1536}
1537
Neale Rannsc87aafa2017-11-29 00:59:31 -08001538u8 *
1539format_fib_table_memory (u8 *s, va_list *args)
1540{
1541 s = format(s, "%U", format_ip4_fib_table_memory);
1542 s = format(s, "%U", format_ip6_fib_table_memory);
1543 s = format(s, "%U", format_mpls_fib_table_memory);
1544
1545 return (s);
1546}