blob: ec2acc59c52f6ebd0283b05377f5a747eff763d6 [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 {
513 /* Prefix recurses via itse;f */
514 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 Ranns097fa662018-05-01 05:17:55 -0700525 if (*eflags & FIB_ENTRY_FLAG_DROP)
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800526 {
527 path->frp_flags |= FIB_ROUTE_PATH_DROP;
528 }
Neale Ranns097fa662018-05-01 05:17:55 -0700529 if (*eflags & FIB_ENTRY_FLAG_LOCAL)
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800530 {
531 path->frp_flags |= FIB_ROUTE_PATH_LOCAL;
532 }
Neale Ranns097fa662018-05-01 05:17:55 -0700533 if (*eflags & FIB_ENTRY_FLAG_EXCLUSIVE)
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800534 {
535 path->frp_flags |= FIB_ROUTE_PATH_EXCLUSIVE;
536 }
Neale Ranns097fa662018-05-01 05:17:55 -0700537 if (path->frp_flags & FIB_ROUTE_PATH_LOCAL)
538 {
539 *eflags |= FIB_ENTRY_FLAG_LOCAL;
540
541 if (path->frp_sw_if_index != ~0)
542 {
543 *eflags |= FIB_ENTRY_FLAG_CONNECTED;
544 }
545 }
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800546}
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100547
548fib_node_index_t
549fib_table_entry_path_add (u32 fib_index,
550 const fib_prefix_t *prefix,
551 fib_source_t source,
552 fib_entry_flag_t flags,
Neale Rannsda78f952017-05-24 09:15:43 -0700553 dpo_proto_t next_hop_proto,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100554 const ip46_address_t *next_hop,
555 u32 next_hop_sw_if_index,
556 u32 next_hop_fib_index,
557 u32 next_hop_weight,
Neale Ranns31ed7442018-02-23 05:29:09 -0800558 fib_mpls_label_t *next_hop_labels,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100559 fib_route_path_flags_t path_flags)
560{
561 fib_route_path_t path = {
562 .frp_proto = next_hop_proto,
563 .frp_addr = (NULL == next_hop? zero_addr : *next_hop),
564 .frp_sw_if_index = next_hop_sw_if_index,
565 .frp_fib_index = next_hop_fib_index,
566 .frp_weight = next_hop_weight,
567 .frp_flags = path_flags,
Neale Ranns097fa662018-05-01 05:17:55 -0700568 .frp_rpf_id = INDEX_INVALID,
Neale Rannsad422ed2016-11-02 14:20:04 +0000569 .frp_label_stack = next_hop_labels,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100570 };
571 fib_node_index_t fib_entry_index;
572 fib_route_path_t *paths = NULL;
573
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100574 vec_add1(paths, path);
575
576 fib_entry_index = fib_table_entry_path_add2(fib_index, prefix,
577 source, flags, paths);
578
579 vec_free(paths);
580 return (fib_entry_index);
581}
582
Neale Rannsda5dedf2020-01-20 02:28:00 +0000583static int
584fib_route_path_cmp_for_sort (void * v1,
585 void * v2)
586{
587 return (fib_route_path_cmp(v1, v2));
588}
589
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100590fib_node_index_t
591fib_table_entry_path_add2 (u32 fib_index,
592 const fib_prefix_t *prefix,
593 fib_source_t source,
594 fib_entry_flag_t flags,
Neale Ranns097fa662018-05-01 05:17:55 -0700595 fib_route_path_t *rpaths)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100596{
597 fib_node_index_t fib_entry_index;
598 fib_table_t *fib_table;
Neale Rannsad422ed2016-11-02 14:20:04 +0000599 u32 ii;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100600
601 fib_table = fib_table_get(fib_index, prefix->fp_proto);
602 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
603
Neale Ranns097fa662018-05-01 05:17:55 -0700604 for (ii = 0; ii < vec_len(rpaths); ii++)
Neale Rannsad422ed2016-11-02 14:20:04 +0000605 {
Neale Ranns097fa662018-05-01 05:17:55 -0700606 fib_table_route_path_fixup(prefix, &flags, &rpaths[ii]);
Neale Rannsad422ed2016-11-02 14:20:04 +0000607 }
Neale Rannsda5dedf2020-01-20 02:28:00 +0000608 /*
609 * sort the paths provided by the control plane. this means
610 * the paths and the extension on the entry will be sorted.
611 */
612 vec_sort_with_function(rpaths, fib_route_path_cmp_for_sort);
Neale Rannsad422ed2016-11-02 14:20:04 +0000613
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100614 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
615 {
616 fib_entry_index = fib_entry_create(fib_index, prefix,
617 source, flags,
Neale Ranns097fa662018-05-01 05:17:55 -0700618 rpaths);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100619
620 fib_table_entry_insert(fib_table, prefix, fib_entry_index);
Neale Ranns3bab8f92019-12-04 06:11:00 +0000621 fib_table_source_count_inc(fib_table, source);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100622 }
623 else
624 {
625 int was_sourced;
626
627 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
Neale Ranns097fa662018-05-01 05:17:55 -0700628 fib_entry_path_add(fib_entry_index, source, flags, rpaths);;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100629
630 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
631 {
Neale Ranns3bab8f92019-12-04 06:11:00 +0000632 fib_table_source_count_inc(fib_table, source);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100633 }
634 }
635
636 return (fib_entry_index);
637}
638
639void
640fib_table_entry_path_remove2 (u32 fib_index,
Neale Rannsad422ed2016-11-02 14:20:04 +0000641 const fib_prefix_t *prefix,
642 fib_source_t source,
Neale Ranns097fa662018-05-01 05:17:55 -0700643 fib_route_path_t *rpaths)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100644{
645 /*
646 * 1 is it present
647 * yes => remove source
648 * 2 - is it still sourced?
649 * no => cover walk
650 */
651 fib_node_index_t fib_entry_index;
Neale Ranns097fa662018-05-01 05:17:55 -0700652 fib_route_path_t *rpath;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100653 fib_table_t *fib_table;
654
655 fib_table = fib_table_get(fib_index, prefix->fp_proto);
656 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
657
658 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
659 {
660 /*
661 * removing an etry that does not exist. i'll allow it.
662 */
663 }
664 else
665 {
666 fib_entry_src_flag_t src_flag;
667 int was_sourced;
668
Neale Rannsf12a83f2017-04-18 09:09:40 -0700669 /*
670 * if it's not sourced, then there's nowt to remove
671 */
672 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
673 if (!was_sourced)
674 {
675 return;
676 }
677
678 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100679 * don't nobody go nowhere
680 */
681 fib_entry_lock(fib_entry_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100682
Neale Ranns097fa662018-05-01 05:17:55 -0700683 vec_foreach(rpath, rpaths)
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800684 {
Neale Ranns097fa662018-05-01 05:17:55 -0700685 fib_entry_flag_t eflags;
686
687 eflags = fib_entry_get_flags_for_source(fib_entry_index,
688 source);
689 fib_table_route_path_fixup(prefix, &eflags, rpath);
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800690 }
691
Neale Ranns097fa662018-05-01 05:17:55 -0700692 src_flag = fib_entry_path_remove(fib_entry_index, source, rpaths);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100693
694 if (!(FIB_ENTRY_SRC_FLAG_ADDED & src_flag))
695 {
696 /*
697 * last source gone. remove from the table
698 */
699 fib_table_entry_remove(fib_table, prefix, fib_entry_index);
700
701 /*
702 * now the entry is no longer in the table, we can
703 * inform the entries that it covers to re-calculate their cover
704 */
705 fib_entry_cover_change_notify(fib_entry_index,
706 FIB_NODE_INDEX_INVALID);
707 }
708 /*
709 * else
710 * still has sources, leave it be.
711 */
712 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
713 {
Neale Ranns3bab8f92019-12-04 06:11:00 +0000714 fib_table_source_count_dec(fib_table, source);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100715 }
716
717 fib_entry_unlock(fib_entry_index);
718 }
719}
720
721void
722fib_table_entry_path_remove (u32 fib_index,
723 const fib_prefix_t *prefix,
724 fib_source_t source,
Neale Rannsda78f952017-05-24 09:15:43 -0700725 dpo_proto_t next_hop_proto,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100726 const ip46_address_t *next_hop,
727 u32 next_hop_sw_if_index,
728 u32 next_hop_fib_index,
729 u32 next_hop_weight,
730 fib_route_path_flags_t path_flags)
731{
732 /*
733 * 1 is it present
734 * yes => remove source
735 * 2 - is it still sourced?
736 * no => cover walk
737 */
738 fib_route_path_t path = {
739 .frp_proto = next_hop_proto,
740 .frp_addr = (NULL == next_hop? zero_addr : *next_hop),
741 .frp_sw_if_index = next_hop_sw_if_index,
742 .frp_fib_index = next_hop_fib_index,
743 .frp_weight = next_hop_weight,
744 .frp_flags = path_flags,
745 };
746 fib_route_path_t *paths = NULL;
747
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100748 vec_add1(paths, path);
749
750 fib_table_entry_path_remove2(fib_index, prefix, source, paths);
751
752 vec_free(paths);
753}
754
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100755fib_node_index_t
756fib_table_entry_update (u32 fib_index,
757 const fib_prefix_t *prefix,
758 fib_source_t source,
759 fib_entry_flag_t flags,
Neale Rannsad422ed2016-11-02 14:20:04 +0000760 fib_route_path_t *paths)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100761{
762 fib_node_index_t fib_entry_index;
763 fib_table_t *fib_table;
Neale Rannsad422ed2016-11-02 14:20:04 +0000764 u32 ii;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100765
766 fib_table = fib_table_get(fib_index, prefix->fp_proto);
767 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
768
Neale Rannsad422ed2016-11-02 14:20:04 +0000769 for (ii = 0; ii < vec_len(paths); ii++)
770 {
Neale Ranns097fa662018-05-01 05:17:55 -0700771 fib_table_route_path_fixup(prefix, &flags, &paths[ii]);
Neale Rannsad422ed2016-11-02 14:20:04 +0000772 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100773 /*
774 * sort the paths provided by the control plane. this means
775 * the paths and the extension on the entry will be sorted.
776 */
Neale Rannsad422ed2016-11-02 14:20:04 +0000777 vec_sort_with_function(paths, fib_route_path_cmp_for_sort);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100778
779 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
780 {
781 fib_entry_index = fib_entry_create(fib_index, prefix,
782 source, flags,
783 paths);
784
785 fib_table_entry_insert(fib_table, prefix, fib_entry_index);
Neale Ranns3bab8f92019-12-04 06:11:00 +0000786 fib_table_source_count_inc(fib_table, source);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100787 }
788 else
789 {
790 int was_sourced;
791
792 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
793 fib_entry_update(fib_entry_index, source, flags, paths);
794
795 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
796 {
Neale Ranns3bab8f92019-12-04 06:11:00 +0000797 fib_table_source_count_inc(fib_table, source);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100798 }
799 }
800
801 return (fib_entry_index);
802}
803
804fib_node_index_t
805fib_table_entry_update_one_path (u32 fib_index,
806 const fib_prefix_t *prefix,
807 fib_source_t source,
808 fib_entry_flag_t flags,
Neale Rannsda78f952017-05-24 09:15:43 -0700809 dpo_proto_t next_hop_proto,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100810 const ip46_address_t *next_hop,
811 u32 next_hop_sw_if_index,
812 u32 next_hop_fib_index,
813 u32 next_hop_weight,
Neale Ranns31ed7442018-02-23 05:29:09 -0800814 fib_mpls_label_t *next_hop_labels,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100815 fib_route_path_flags_t path_flags)
816{
817 fib_node_index_t fib_entry_index;
818 fib_route_path_t path = {
819 .frp_proto = next_hop_proto,
820 .frp_addr = (NULL == next_hop? zero_addr : *next_hop),
821 .frp_sw_if_index = next_hop_sw_if_index,
822 .frp_fib_index = next_hop_fib_index,
823 .frp_weight = next_hop_weight,
824 .frp_flags = path_flags,
Neale Rannsad422ed2016-11-02 14:20:04 +0000825 .frp_label_stack = next_hop_labels,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100826 };
827 fib_route_path_t *paths = NULL;
828
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100829 vec_add1(paths, path);
830
831 fib_entry_index =
832 fib_table_entry_update(fib_index, prefix, source, flags, paths);
833
834 vec_free(paths);
835
836 return (fib_entry_index);
837}
838
839static void
840fib_table_entry_delete_i (u32 fib_index,
841 fib_node_index_t fib_entry_index,
842 const fib_prefix_t *prefix,
843 fib_source_t source)
844{
845 fib_entry_src_flag_t src_flag;
846 fib_table_t *fib_table;
847 int was_sourced;
848
849 fib_table = fib_table_get(fib_index, prefix->fp_proto);
850 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
851
852 /*
853 * don't nobody go nowhere
854 */
855 fib_entry_lock(fib_entry_index);
856
857 src_flag = fib_entry_delete(fib_entry_index, source);
858
859 if (!(FIB_ENTRY_SRC_FLAG_ADDED & src_flag))
860 {
861 /*
862 * last source gone. remove from the table
863 */
864 fib_table_entry_remove(fib_table, prefix, fib_entry_index);
865
866 /*
867 * now the entry is no longer in the table, we can
868 * inform the entries that it covers to re-calculate their cover
869 */
870 fib_entry_cover_change_notify(fib_entry_index,
871 FIB_NODE_INDEX_INVALID);
872 }
873 /*
874 * else
875 * still has sources, leave it be.
876 */
877 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
878 {
Neale Ranns3bab8f92019-12-04 06:11:00 +0000879 fib_table_source_count_dec(fib_table, source);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100880 }
881
882 fib_entry_unlock(fib_entry_index);
883}
884
885void
886fib_table_entry_delete (u32 fib_index,
887 const fib_prefix_t *prefix,
888 fib_source_t source)
889{
890 fib_node_index_t fib_entry_index;
891
892 fib_entry_index = fib_table_lookup_exact_match(fib_index, prefix);
893
894 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
895 {
896 /*
897 * removing an etry that does not exist.
898 * i'll allow it, but i won't like it.
899 */
Dave Barach59b25652017-09-10 15:04:27 -0400900 if (0)
901 clib_warning("%U not in FIB", format_fib_prefix, prefix);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100902 }
903 else
904 {
905 fib_table_entry_delete_i(fib_index, fib_entry_index, prefix, source);
906 }
907}
908
909void
910fib_table_entry_delete_index (fib_node_index_t fib_entry_index,
911 fib_source_t source)
912{
Neale Rannsc5d43172018-07-30 08:04:40 -0700913 const fib_prefix_t *prefix;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100914
Neale Rannsc5d43172018-07-30 08:04:40 -0700915 prefix = fib_entry_get_prefix(fib_entry_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100916
917 fib_table_entry_delete_i(fib_entry_get_fib_index(fib_entry_index),
Neale Rannsc5d43172018-07-30 08:04:40 -0700918 fib_entry_index, prefix, source);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100919}
920
Neale Ranns008dbe12018-09-07 09:32:36 -0700921u32
Neale Ranns28c142e2018-09-07 09:37:07 -0700922fib_table_entry_get_stats_index (u32 fib_index,
923 const fib_prefix_t *prefix)
Neale Ranns008dbe12018-09-07 09:32:36 -0700924{
925 return (fib_entry_get_stats_index(
926 fib_table_lookup_exact_match(fib_index, prefix)));
927}
928
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100929fib_node_index_t
930fib_table_entry_local_label_add (u32 fib_index,
931 const fib_prefix_t *prefix,
932 mpls_label_t label)
933{
934 fib_node_index_t fib_entry_index;
935
Neale Ranns1357f3b2016-10-16 12:01:42 -0700936 fib_entry_index = fib_table_lookup_exact_match(fib_index, prefix);
937
938 if (FIB_NODE_INDEX_INVALID == fib_entry_index ||
939 !fib_entry_is_sourced(fib_entry_index, FIB_SOURCE_MPLS))
940 {
941 /*
942 * only source the prefix once. this allows the label change
943 * operation to work
944 */
945 fib_entry_index = fib_table_entry_special_dpo_add(fib_index, prefix,
946 FIB_SOURCE_MPLS,
947 FIB_ENTRY_FLAG_NONE,
948 NULL);
949 }
950
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100951 fib_entry_set_source_data(fib_entry_index, FIB_SOURCE_MPLS, &label);
952
953 return (fib_entry_index);
954}
955
956void
957fib_table_entry_local_label_remove (u32 fib_index,
958 const fib_prefix_t *prefix,
959 mpls_label_t label)
960{
961 fib_node_index_t fib_entry_index;
962 const void *data;
963 mpls_label_t pl;
964
965 fib_entry_index = fib_table_lookup_exact_match(fib_index, prefix);
966
967 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
968 return;
969
970 data = fib_entry_get_source_data(fib_entry_index, FIB_SOURCE_MPLS);
971
972 if (NULL == data)
973 return;
974
975 pl = *(mpls_label_t*)data;
976
977 if (pl != label)
978 return;
979
980 pl = MPLS_LABEL_INVALID;
981
982 fib_entry_set_source_data(fib_entry_index, FIB_SOURCE_MPLS, &pl);
983 fib_table_entry_special_remove(fib_index,
984 prefix,
985 FIB_SOURCE_MPLS);
986}
987
988u32
989fib_table_get_index_for_sw_if_index (fib_protocol_t proto,
990 u32 sw_if_index)
991{
992 switch (proto)
993 {
994 case FIB_PROTOCOL_IP4:
995 return (ip4_fib_table_get_index_for_sw_if_index(sw_if_index));
996 case FIB_PROTOCOL_IP6:
997 return (ip6_fib_table_get_index_for_sw_if_index(sw_if_index));
998 case FIB_PROTOCOL_MPLS:
999 return (mpls_fib_table_get_index_for_sw_if_index(sw_if_index));
1000 }
1001 return (~0);
1002}
1003
1004flow_hash_config_t
1005fib_table_get_flow_hash_config (u32 fib_index,
1006 fib_protocol_t proto)
1007{
Neale Ranns227038a2017-04-21 01:07:59 -07001008 fib_table_t *fib;
1009
1010 fib = fib_table_get(fib_index, proto);
1011
1012 return (fib->ft_flow_hash_config);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001013}
Neale Rannsd792d9c2017-10-21 10:53:20 -07001014
Neale Ranns41da54f2017-05-02 10:15:19 -07001015flow_hash_config_t
1016fib_table_get_default_flow_hash_config (fib_protocol_t proto)
1017{
1018 switch (proto)
1019 {
1020 case FIB_PROTOCOL_IP4:
1021 case FIB_PROTOCOL_IP6:
1022 return (IP_FLOW_HASH_DEFAULT);
1023
1024 case FIB_PROTOCOL_MPLS:
1025 return (MPLS_FLOW_HASH_DEFAULT);
1026 }
1027
1028 ASSERT(0);
1029 return (IP_FLOW_HASH_DEFAULT);
1030}
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001031
Neale Ranns227038a2017-04-21 01:07:59 -07001032/**
1033 * @brief Table set flow hash config context.
1034 */
1035typedef struct fib_table_set_flow_hash_config_ctx_t_
1036{
1037 /**
1038 * the flow hash config to set
1039 */
1040 flow_hash_config_t hash_config;
1041} fib_table_set_flow_hash_config_ctx_t;
1042
Neale Ranns89541992017-04-06 04:41:02 -07001043static fib_table_walk_rc_t
Neale Ranns227038a2017-04-21 01:07:59 -07001044fib_table_set_flow_hash_config_cb (fib_node_index_t fib_entry_index,
1045 void *arg)
1046{
1047 fib_table_set_flow_hash_config_ctx_t *ctx = arg;
1048
1049 fib_entry_set_flow_hash_config(fib_entry_index, ctx->hash_config);
1050
Neale Ranns89541992017-04-06 04:41:02 -07001051 return (FIB_TABLE_WALK_CONTINUE);
Neale Ranns227038a2017-04-21 01:07:59 -07001052}
1053
1054void
1055fib_table_set_flow_hash_config (u32 fib_index,
1056 fib_protocol_t proto,
1057 flow_hash_config_t hash_config)
1058{
1059 fib_table_set_flow_hash_config_ctx_t ctx = {
1060 .hash_config = hash_config,
1061 };
1062 fib_table_t *fib;
1063
1064 fib = fib_table_get(fib_index, proto);
1065 fib->ft_flow_hash_config = hash_config;
1066
1067 fib_table_walk(fib_index, proto,
1068 fib_table_set_flow_hash_config_cb,
1069 &ctx);
1070}
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001071
1072u32
1073fib_table_get_table_id_for_sw_if_index (fib_protocol_t proto,
1074 u32 sw_if_index)
1075{
1076 fib_table_t *fib_table;
1077
1078 fib_table = fib_table_get(fib_table_get_index_for_sw_if_index(
1079 proto, sw_if_index),
1080 proto);
1081
1082 return ((NULL != fib_table ? fib_table->ft_table_id : ~0));
1083}
1084
1085u32
Neale Ranns25b04942018-04-04 09:34:50 -07001086fib_table_get_table_id (u32 fib_index,
1087 fib_protocol_t proto)
1088{
1089 fib_table_t *fib_table;
1090
1091 fib_table = fib_table_get(fib_index, proto);
1092
1093 return ((NULL != fib_table ? fib_table->ft_table_id : ~0));
1094}
1095
1096u32
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001097fib_table_find (fib_protocol_t proto,
1098 u32 table_id)
1099{
1100 switch (proto)
1101 {
1102 case FIB_PROTOCOL_IP4:
1103 return (ip4_fib_index_from_table_id(table_id));
1104 case FIB_PROTOCOL_IP6:
1105 return (ip6_fib_index_from_table_id(table_id));
1106 case FIB_PROTOCOL_MPLS:
1107 return (mpls_fib_index_from_table_id(table_id));
1108 }
1109 return (~0);
1110}
1111
Neale Ranns2297af02017-09-12 09:45:04 -07001112static u32
1113fib_table_find_or_create_and_lock_i (fib_protocol_t proto,
1114 u32 table_id,
1115 fib_source_t src,
1116 const u8 *name)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001117{
1118 fib_table_t *fib_table;
1119 fib_node_index_t fi;
1120
1121 switch (proto)
1122 {
1123 case FIB_PROTOCOL_IP4:
Neale Ranns15002542017-09-10 04:39:11 -07001124 fi = ip4_fib_table_find_or_create_and_lock(table_id, src);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001125 break;
1126 case FIB_PROTOCOL_IP6:
Neale Ranns15002542017-09-10 04:39:11 -07001127 fi = ip6_fib_table_find_or_create_and_lock(table_id, src);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001128 break;
1129 case FIB_PROTOCOL_MPLS:
Neale Ranns15002542017-09-10 04:39:11 -07001130 fi = mpls_fib_table_find_or_create_and_lock(table_id, src);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001131 break;
1132 default:
1133 return (~0);
1134 }
1135
1136 fib_table = fib_table_get(fi, proto);
1137
Neale Ranns2297af02017-09-12 09:45:04 -07001138 if (NULL == fib_table->ft_desc)
1139 {
1140 if (name && name[0])
1141 {
1142 fib_table->ft_desc = format(NULL, "%s", name);
1143 }
1144 else
1145 {
1146 fib_table->ft_desc = format(NULL, "%U-VRF:%d",
1147 format_fib_protocol, proto,
1148 table_id);
1149 }
1150 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001151
1152 return (fi);
1153}
1154
1155u32
Neale Ranns2297af02017-09-12 09:45:04 -07001156fib_table_find_or_create_and_lock (fib_protocol_t proto,
1157 u32 table_id,
1158 fib_source_t src)
1159{
1160 return (fib_table_find_or_create_and_lock_i(proto, table_id,
1161 src, NULL));
1162}
1163
1164u32
1165fib_table_find_or_create_and_lock_w_name (fib_protocol_t proto,
1166 u32 table_id,
1167 fib_source_t src,
1168 const u8 *name)
1169{
1170 return (fib_table_find_or_create_and_lock_i(proto, table_id,
1171 src, name));
1172}
1173
1174u32
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001175fib_table_create_and_lock (fib_protocol_t proto,
Neale Ranns15002542017-09-10 04:39:11 -07001176 fib_source_t src,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001177 const char *const fmt,
1178 ...)
1179{
1180 fib_table_t *fib_table;
1181 fib_node_index_t fi;
1182 va_list ap;
1183
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001184
1185 switch (proto)
1186 {
1187 case FIB_PROTOCOL_IP4:
Neale Ranns15002542017-09-10 04:39:11 -07001188 fi = ip4_fib_table_create_and_lock(src);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001189 break;
1190 case FIB_PROTOCOL_IP6:
Neale Ranns53da2212018-02-24 02:11:19 -08001191 fi = ip6_fib_table_create_and_lock(src, FIB_TABLE_FLAG_NONE, NULL);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001192 break;
1193 case FIB_PROTOCOL_MPLS:
Neale Ranns15002542017-09-10 04:39:11 -07001194 fi = mpls_fib_table_create_and_lock(src);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001195 break;
1196 default:
1197 return (~0);
1198 }
1199
1200 fib_table = fib_table_get(fi, proto);
1201
Paul Vinciguerra0c0383d2018-10-24 12:14:09 -07001202 va_start(ap, fmt);
1203
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001204 fib_table->ft_desc = va_format(fib_table->ft_desc, fmt, &ap);
1205
1206 va_end(ap);
1207 return (fi);
1208}
1209
1210static void
1211fib_table_destroy (fib_table_t *fib_table)
1212{
1213 vec_free(fib_table->ft_desc);
1214
1215 switch (fib_table->ft_proto)
1216 {
1217 case FIB_PROTOCOL_IP4:
Neale Rannsa3af3372017-03-28 03:49:52 -07001218 ip4_fib_table_destroy(fib_table->ft_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001219 break;
1220 case FIB_PROTOCOL_IP6:
1221 ip6_fib_table_destroy(fib_table->ft_index);
1222 break;
1223 case FIB_PROTOCOL_MPLS:
Neale Rannsa3af3372017-03-28 03:49:52 -07001224 mpls_fib_table_destroy(fib_table->ft_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001225 break;
1226 }
1227}
Neale Ranns5a8123b2017-01-26 01:18:23 -08001228
Neale Ranns32e1c012016-11-22 17:07:28 +00001229void
1230fib_table_walk (u32 fib_index,
1231 fib_protocol_t proto,
1232 fib_table_walk_fn_t fn,
1233 void *ctx)
1234{
1235 switch (proto)
1236 {
1237 case FIB_PROTOCOL_IP4:
1238 ip4_fib_table_walk(ip4_fib_get(fib_index), fn, ctx);
1239 break;
1240 case FIB_PROTOCOL_IP6:
1241 ip6_fib_table_walk(fib_index, fn, ctx);
1242 break;
1243 case FIB_PROTOCOL_MPLS:
1244 mpls_fib_table_walk(mpls_fib_get(fib_index), fn, ctx);
1245 break;
1246 }
1247}
1248
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001249void
Neale Ranns89541992017-04-06 04:41:02 -07001250fib_table_sub_tree_walk (u32 fib_index,
1251 fib_protocol_t proto,
1252 const fib_prefix_t *root,
1253 fib_table_walk_fn_t fn,
1254 void *ctx)
1255{
1256 switch (proto)
1257 {
1258 case FIB_PROTOCOL_IP4:
1259 ip4_fib_table_sub_tree_walk(ip4_fib_get(fib_index), root, fn, ctx);
1260 break;
1261 case FIB_PROTOCOL_IP6:
1262 ip6_fib_table_sub_tree_walk(fib_index, root, fn, ctx);
1263 break;
1264 case FIB_PROTOCOL_MPLS:
1265 break;
1266 }
1267}
1268
Neale Ranns3bab8f92019-12-04 06:11:00 +00001269static void
1270fib_table_lock_dec (fib_table_t *fib_table,
1271 fib_source_t source)
1272{
1273 vec_validate(fib_table->ft_locks, source);
1274
1275 fib_table->ft_locks[source]--;
1276 fib_table->ft_total_locks--;
1277}
1278
1279static void
1280fib_table_lock_inc (fib_table_t *fib_table,
1281 fib_source_t source)
1282{
1283 vec_validate(fib_table->ft_locks, source);
1284
Miklos Tirpak4a94cd22019-12-20 11:55:43 +01001285 ASSERT(fib_table->ft_total_locks < (0xffffffff - 1));
Neale Ranns3bab8f92019-12-04 06:11:00 +00001286 fib_table->ft_locks[source]++;
1287 fib_table->ft_total_locks++;
1288}
1289
Neale Ranns89541992017-04-06 04:41:02 -07001290void
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001291fib_table_unlock (u32 fib_index,
Neale Ranns15002542017-09-10 04:39:11 -07001292 fib_protocol_t proto,
1293 fib_source_t source)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001294{
1295 fib_table_t *fib_table;
1296
1297 fib_table = fib_table_get(fib_index, proto);
Neale Ranns3bab8f92019-12-04 06:11:00 +00001298 fib_table_lock_dec(fib_table, source);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001299
Neale Ranns3bab8f92019-12-04 06:11:00 +00001300 if (0 == fib_table->ft_total_locks)
Neale Ranns15002542017-09-10 04:39:11 -07001301 {
1302 /*
1303 * no more locak from any source - kill it
1304 */
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001305 fib_table_destroy(fib_table);
1306 }
1307}
Neale Ranns15002542017-09-10 04:39:11 -07001308
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001309void
1310fib_table_lock (u32 fib_index,
Neale Ranns15002542017-09-10 04:39:11 -07001311 fib_protocol_t proto,
1312 fib_source_t source)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001313{
1314 fib_table_t *fib_table;
1315
1316 fib_table = fib_table_get(fib_index, proto);
Neale Ranns6fff24a2018-09-10 19:14:07 -07001317
Neale Ranns3bab8f92019-12-04 06:11:00 +00001318 fib_table_lock_inc(fib_table, source);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001319}
1320
1321u32
1322fib_table_get_num_entries (u32 fib_index,
1323 fib_protocol_t proto,
1324 fib_source_t source)
1325{
1326 fib_table_t *fib_table;
1327
1328 fib_table = fib_table_get(fib_index, proto);
1329
1330 return (fib_table->ft_src_route_counts[source]);
1331}
1332
1333u8*
Christophe Fontained3c008d2017-10-02 18:10:54 +02001334format_fib_table_name (u8* s, va_list* ap)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001335{
Christophe Fontained3c008d2017-10-02 18:10:54 +02001336 fib_node_index_t fib_index = va_arg(*ap, fib_node_index_t);
1337 fib_protocol_t proto = va_arg(*ap, int); // int promotion
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001338 fib_table_t *fib_table;
1339
1340 fib_table = fib_table_get(fib_index, proto);
1341
1342 s = format(s, "%v", fib_table->ft_desc);
1343
1344 return (s);
1345}
1346
Neale Ranns9db6ada2019-11-08 12:42:31 +00001347u8*
1348format_fib_table_flags (u8 *s, va_list *args)
1349{
1350 fib_table_flags_t flags = va_arg(*args, int);
1351 fib_table_attribute_t attr;
1352
1353 if (!flags)
1354 {
1355 return format(s, "none");
1356 }
1357
1358 FOR_EACH_FIB_TABLE_ATTRIBUTE(attr) {
1359 if (1 << attr & flags) {
1360 s = format(s, "%s", fib_table_flags_strings[attr]);
1361 }
1362 }
1363
1364 return (s);
1365}
1366
Neale Ranns32e1c012016-11-22 17:07:28 +00001367/**
1368 * @brief Table flush context. Store the indicies of matching FIB entries
1369 * that need to be removed.
1370 */
1371typedef struct fib_table_flush_ctx_t_
1372{
1373 /**
1374 * The list of entries to flush
1375 */
1376 fib_node_index_t *ftf_entries;
1377
1378 /**
1379 * The source we are flushing
1380 */
1381 fib_source_t ftf_source;
1382} fib_table_flush_ctx_t;
1383
Neale Ranns89541992017-04-06 04:41:02 -07001384static fib_table_walk_rc_t
Neale Ranns32e1c012016-11-22 17:07:28 +00001385fib_table_flush_cb (fib_node_index_t fib_entry_index,
1386 void *arg)
1387{
1388 fib_table_flush_ctx_t *ctx = arg;
1389
1390 if (fib_entry_is_sourced(fib_entry_index, ctx->ftf_source))
1391 {
1392 vec_add1(ctx->ftf_entries, fib_entry_index);
1393 }
Neale Ranns89541992017-04-06 04:41:02 -07001394 return (FIB_TABLE_WALK_CONTINUE);
Neale Ranns32e1c012016-11-22 17:07:28 +00001395}
1396
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001397void
1398fib_table_flush (u32 fib_index,
1399 fib_protocol_t proto,
1400 fib_source_t source)
1401{
Neale Ranns32e1c012016-11-22 17:07:28 +00001402 fib_node_index_t *fib_entry_index;
1403 fib_table_flush_ctx_t ctx = {
1404 .ftf_entries = NULL,
1405 .ftf_source = source,
1406 };
1407
1408 fib_table_walk(fib_index, proto,
1409 fib_table_flush_cb,
1410 &ctx);
1411
1412 vec_foreach(fib_entry_index, ctx.ftf_entries)
1413 {
Neale Rannsa8d9f302017-02-20 09:17:02 -08001414 fib_table_entry_delete_index(*fib_entry_index, source);
Neale Ranns32e1c012016-11-22 17:07:28 +00001415 }
1416
1417 vec_free(ctx.ftf_entries);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001418}
Neale Rannsc87aafa2017-11-29 00:59:31 -08001419
Neale Ranns9db6ada2019-11-08 12:42:31 +00001420static fib_table_walk_rc_t
1421fib_table_mark_cb (fib_node_index_t fib_entry_index,
1422 void *arg)
1423{
1424 fib_table_flush_ctx_t *ctx = arg;
1425
1426 if (fib_entry_is_sourced(fib_entry_index, ctx->ftf_source))
1427 {
1428 fib_entry_mark(fib_entry_index, ctx->ftf_source);
1429 }
1430 return (FIB_TABLE_WALK_CONTINUE);
1431}
1432
1433void
1434fib_table_mark (u32 fib_index,
1435 fib_protocol_t proto,
1436 fib_source_t source)
1437{
1438 fib_table_flush_ctx_t ctx = {
1439 .ftf_source = source,
1440 };
1441 fib_table_t *fib_table;
1442
1443 fib_table = fib_table_get(fib_index, proto);
1444
1445 fib_table->ft_epoch++;
1446 fib_table->ft_flags |= FIB_TABLE_FLAG_RESYNC;
1447
1448 fib_table_walk(fib_index, proto,
1449 fib_table_mark_cb,
1450 &ctx);
1451}
1452
1453static fib_table_walk_rc_t
1454fib_table_sweep_cb (fib_node_index_t fib_entry_index,
1455 void *arg)
1456{
1457 fib_table_flush_ctx_t *ctx = arg;
1458
1459 if (fib_entry_is_marked(fib_entry_index, ctx->ftf_source))
1460 {
1461 vec_add1(ctx->ftf_entries, fib_entry_index);
1462 }
1463 return (FIB_TABLE_WALK_CONTINUE);
1464}
1465
1466void
1467fib_table_sweep (u32 fib_index,
1468 fib_protocol_t proto,
1469 fib_source_t source)
1470{
1471 fib_table_flush_ctx_t ctx = {
1472 .ftf_source = source,
1473 };
1474 fib_node_index_t *fib_entry_index;
1475 fib_table_t *fib_table;
1476
1477 fib_table = fib_table_get(fib_index, proto);
1478
1479 fib_table->ft_flags &= ~FIB_TABLE_FLAG_RESYNC;
1480
1481 fib_table_walk(fib_index, proto,
1482 fib_table_sweep_cb,
1483 &ctx);
1484
1485 vec_foreach(fib_entry_index, ctx.ftf_entries)
1486 {
1487 fib_table_entry_delete_index(*fib_entry_index, source);
1488 }
1489
1490 vec_free(ctx.ftf_entries);
1491}
1492
Neale Rannsc87aafa2017-11-29 00:59:31 -08001493u8 *
1494format_fib_table_memory (u8 *s, va_list *args)
1495{
1496 s = format(s, "%U", format_ip4_fib_table_memory);
1497 s = format(s, "%U", format_ip6_fib_table_memory);
1498 s = format(s, "%U", format_mpls_fib_table_memory);
1499
1500 return (s);
1501}