blob: 6766028762da8003876c68d35dc0f49ad7277038 [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
583fib_node_index_t
584fib_table_entry_path_add2 (u32 fib_index,
585 const fib_prefix_t *prefix,
586 fib_source_t source,
587 fib_entry_flag_t flags,
Neale Ranns097fa662018-05-01 05:17:55 -0700588 fib_route_path_t *rpaths)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100589{
590 fib_node_index_t fib_entry_index;
591 fib_table_t *fib_table;
Neale Rannsad422ed2016-11-02 14:20:04 +0000592 u32 ii;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100593
594 fib_table = fib_table_get(fib_index, prefix->fp_proto);
595 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
596
Neale Ranns097fa662018-05-01 05:17:55 -0700597 for (ii = 0; ii < vec_len(rpaths); ii++)
Neale Rannsad422ed2016-11-02 14:20:04 +0000598 {
Neale Ranns097fa662018-05-01 05:17:55 -0700599 fib_table_route_path_fixup(prefix, &flags, &rpaths[ii]);
Neale Rannsad422ed2016-11-02 14:20:04 +0000600 }
601
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100602 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
603 {
604 fib_entry_index = fib_entry_create(fib_index, prefix,
605 source, flags,
Neale Ranns097fa662018-05-01 05:17:55 -0700606 rpaths);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100607
608 fib_table_entry_insert(fib_table, prefix, fib_entry_index);
Neale Ranns3bab8f92019-12-04 06:11:00 +0000609 fib_table_source_count_inc(fib_table, source);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100610 }
611 else
612 {
613 int was_sourced;
614
615 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
Neale Ranns097fa662018-05-01 05:17:55 -0700616 fib_entry_path_add(fib_entry_index, source, flags, rpaths);;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100617
618 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
619 {
Neale Ranns3bab8f92019-12-04 06:11:00 +0000620 fib_table_source_count_inc(fib_table, source);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100621 }
622 }
623
624 return (fib_entry_index);
625}
626
627void
628fib_table_entry_path_remove2 (u32 fib_index,
Neale Rannsad422ed2016-11-02 14:20:04 +0000629 const fib_prefix_t *prefix,
630 fib_source_t source,
Neale Ranns097fa662018-05-01 05:17:55 -0700631 fib_route_path_t *rpaths)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100632{
633 /*
634 * 1 is it present
635 * yes => remove source
636 * 2 - is it still sourced?
637 * no => cover walk
638 */
639 fib_node_index_t fib_entry_index;
Neale Ranns097fa662018-05-01 05:17:55 -0700640 fib_route_path_t *rpath;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100641 fib_table_t *fib_table;
642
643 fib_table = fib_table_get(fib_index, prefix->fp_proto);
644 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
645
646 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
647 {
648 /*
649 * removing an etry that does not exist. i'll allow it.
650 */
651 }
652 else
653 {
654 fib_entry_src_flag_t src_flag;
655 int was_sourced;
656
Neale Rannsf12a83f2017-04-18 09:09:40 -0700657 /*
658 * if it's not sourced, then there's nowt to remove
659 */
660 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
661 if (!was_sourced)
662 {
663 return;
664 }
665
666 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100667 * don't nobody go nowhere
668 */
669 fib_entry_lock(fib_entry_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100670
Neale Ranns097fa662018-05-01 05:17:55 -0700671 vec_foreach(rpath, rpaths)
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800672 {
Neale Ranns097fa662018-05-01 05:17:55 -0700673 fib_entry_flag_t eflags;
674
675 eflags = fib_entry_get_flags_for_source(fib_entry_index,
676 source);
677 fib_table_route_path_fixup(prefix, &eflags, rpath);
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800678 }
679
Neale Ranns097fa662018-05-01 05:17:55 -0700680 src_flag = fib_entry_path_remove(fib_entry_index, source, rpaths);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100681
682 if (!(FIB_ENTRY_SRC_FLAG_ADDED & src_flag))
683 {
684 /*
685 * last source gone. remove from the table
686 */
687 fib_table_entry_remove(fib_table, prefix, fib_entry_index);
688
689 /*
690 * now the entry is no longer in the table, we can
691 * inform the entries that it covers to re-calculate their cover
692 */
693 fib_entry_cover_change_notify(fib_entry_index,
694 FIB_NODE_INDEX_INVALID);
695 }
696 /*
697 * else
698 * still has sources, leave it be.
699 */
700 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
701 {
Neale Ranns3bab8f92019-12-04 06:11:00 +0000702 fib_table_source_count_dec(fib_table, source);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100703 }
704
705 fib_entry_unlock(fib_entry_index);
706 }
707}
708
709void
710fib_table_entry_path_remove (u32 fib_index,
711 const fib_prefix_t *prefix,
712 fib_source_t source,
Neale Rannsda78f952017-05-24 09:15:43 -0700713 dpo_proto_t next_hop_proto,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100714 const ip46_address_t *next_hop,
715 u32 next_hop_sw_if_index,
716 u32 next_hop_fib_index,
717 u32 next_hop_weight,
718 fib_route_path_flags_t path_flags)
719{
720 /*
721 * 1 is it present
722 * yes => remove source
723 * 2 - is it still sourced?
724 * no => cover walk
725 */
726 fib_route_path_t path = {
727 .frp_proto = next_hop_proto,
728 .frp_addr = (NULL == next_hop? zero_addr : *next_hop),
729 .frp_sw_if_index = next_hop_sw_if_index,
730 .frp_fib_index = next_hop_fib_index,
731 .frp_weight = next_hop_weight,
732 .frp_flags = path_flags,
733 };
734 fib_route_path_t *paths = NULL;
735
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100736 vec_add1(paths, path);
737
738 fib_table_entry_path_remove2(fib_index, prefix, source, paths);
739
740 vec_free(paths);
741}
742
743static int
744fib_route_path_cmp_for_sort (void * v1,
745 void * v2)
746{
747 return (fib_route_path_cmp(v1, v2));
748}
749
750fib_node_index_t
751fib_table_entry_update (u32 fib_index,
752 const fib_prefix_t *prefix,
753 fib_source_t source,
754 fib_entry_flag_t flags,
Neale Rannsad422ed2016-11-02 14:20:04 +0000755 fib_route_path_t *paths)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100756{
757 fib_node_index_t fib_entry_index;
758 fib_table_t *fib_table;
Neale Rannsad422ed2016-11-02 14:20:04 +0000759 u32 ii;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100760
761 fib_table = fib_table_get(fib_index, prefix->fp_proto);
762 fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
763
Neale Rannsad422ed2016-11-02 14:20:04 +0000764 for (ii = 0; ii < vec_len(paths); ii++)
765 {
Neale Ranns097fa662018-05-01 05:17:55 -0700766 fib_table_route_path_fixup(prefix, &flags, &paths[ii]);
Neale Rannsad422ed2016-11-02 14:20:04 +0000767 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100768 /*
769 * sort the paths provided by the control plane. this means
770 * the paths and the extension on the entry will be sorted.
771 */
Neale Rannsad422ed2016-11-02 14:20:04 +0000772 vec_sort_with_function(paths, fib_route_path_cmp_for_sort);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100773
774 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
775 {
776 fib_entry_index = fib_entry_create(fib_index, prefix,
777 source, flags,
778 paths);
779
780 fib_table_entry_insert(fib_table, prefix, fib_entry_index);
Neale Ranns3bab8f92019-12-04 06:11:00 +0000781 fib_table_source_count_inc(fib_table, source);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100782 }
783 else
784 {
785 int was_sourced;
786
787 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
788 fib_entry_update(fib_entry_index, source, flags, paths);
789
790 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
791 {
Neale Ranns3bab8f92019-12-04 06:11:00 +0000792 fib_table_source_count_inc(fib_table, source);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100793 }
794 }
795
796 return (fib_entry_index);
797}
798
799fib_node_index_t
800fib_table_entry_update_one_path (u32 fib_index,
801 const fib_prefix_t *prefix,
802 fib_source_t source,
803 fib_entry_flag_t flags,
Neale Rannsda78f952017-05-24 09:15:43 -0700804 dpo_proto_t next_hop_proto,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100805 const ip46_address_t *next_hop,
806 u32 next_hop_sw_if_index,
807 u32 next_hop_fib_index,
808 u32 next_hop_weight,
Neale Ranns31ed7442018-02-23 05:29:09 -0800809 fib_mpls_label_t *next_hop_labels,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100810 fib_route_path_flags_t path_flags)
811{
812 fib_node_index_t fib_entry_index;
813 fib_route_path_t path = {
814 .frp_proto = next_hop_proto,
815 .frp_addr = (NULL == next_hop? zero_addr : *next_hop),
816 .frp_sw_if_index = next_hop_sw_if_index,
817 .frp_fib_index = next_hop_fib_index,
818 .frp_weight = next_hop_weight,
819 .frp_flags = path_flags,
Neale Rannsad422ed2016-11-02 14:20:04 +0000820 .frp_label_stack = next_hop_labels,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100821 };
822 fib_route_path_t *paths = NULL;
823
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100824 vec_add1(paths, path);
825
826 fib_entry_index =
827 fib_table_entry_update(fib_index, prefix, source, flags, paths);
828
829 vec_free(paths);
830
831 return (fib_entry_index);
832}
833
834static void
835fib_table_entry_delete_i (u32 fib_index,
836 fib_node_index_t fib_entry_index,
837 const fib_prefix_t *prefix,
838 fib_source_t source)
839{
840 fib_entry_src_flag_t src_flag;
841 fib_table_t *fib_table;
842 int was_sourced;
843
844 fib_table = fib_table_get(fib_index, prefix->fp_proto);
845 was_sourced = fib_entry_is_sourced(fib_entry_index, source);
846
847 /*
848 * don't nobody go nowhere
849 */
850 fib_entry_lock(fib_entry_index);
851
852 src_flag = fib_entry_delete(fib_entry_index, source);
853
854 if (!(FIB_ENTRY_SRC_FLAG_ADDED & src_flag))
855 {
856 /*
857 * last source gone. remove from the table
858 */
859 fib_table_entry_remove(fib_table, prefix, fib_entry_index);
860
861 /*
862 * now the entry is no longer in the table, we can
863 * inform the entries that it covers to re-calculate their cover
864 */
865 fib_entry_cover_change_notify(fib_entry_index,
866 FIB_NODE_INDEX_INVALID);
867 }
868 /*
869 * else
870 * still has sources, leave it be.
871 */
872 if (was_sourced != fib_entry_is_sourced(fib_entry_index, source))
873 {
Neale Ranns3bab8f92019-12-04 06:11:00 +0000874 fib_table_source_count_dec(fib_table, source);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100875 }
876
877 fib_entry_unlock(fib_entry_index);
878}
879
880void
881fib_table_entry_delete (u32 fib_index,
882 const fib_prefix_t *prefix,
883 fib_source_t source)
884{
885 fib_node_index_t fib_entry_index;
886
887 fib_entry_index = fib_table_lookup_exact_match(fib_index, prefix);
888
889 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
890 {
891 /*
892 * removing an etry that does not exist.
893 * i'll allow it, but i won't like it.
894 */
Dave Barach59b25652017-09-10 15:04:27 -0400895 if (0)
896 clib_warning("%U not in FIB", format_fib_prefix, prefix);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100897 }
898 else
899 {
900 fib_table_entry_delete_i(fib_index, fib_entry_index, prefix, source);
901 }
902}
903
904void
905fib_table_entry_delete_index (fib_node_index_t fib_entry_index,
906 fib_source_t source)
907{
Neale Rannsc5d43172018-07-30 08:04:40 -0700908 const fib_prefix_t *prefix;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100909
Neale Rannsc5d43172018-07-30 08:04:40 -0700910 prefix = fib_entry_get_prefix(fib_entry_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100911
912 fib_table_entry_delete_i(fib_entry_get_fib_index(fib_entry_index),
Neale Rannsc5d43172018-07-30 08:04:40 -0700913 fib_entry_index, prefix, source);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100914}
915
Neale Ranns008dbe12018-09-07 09:32:36 -0700916u32
Neale Ranns28c142e2018-09-07 09:37:07 -0700917fib_table_entry_get_stats_index (u32 fib_index,
918 const fib_prefix_t *prefix)
Neale Ranns008dbe12018-09-07 09:32:36 -0700919{
920 return (fib_entry_get_stats_index(
921 fib_table_lookup_exact_match(fib_index, prefix)));
922}
923
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100924fib_node_index_t
925fib_table_entry_local_label_add (u32 fib_index,
926 const fib_prefix_t *prefix,
927 mpls_label_t label)
928{
929 fib_node_index_t fib_entry_index;
930
Neale Ranns1357f3b2016-10-16 12:01:42 -0700931 fib_entry_index = fib_table_lookup_exact_match(fib_index, prefix);
932
933 if (FIB_NODE_INDEX_INVALID == fib_entry_index ||
934 !fib_entry_is_sourced(fib_entry_index, FIB_SOURCE_MPLS))
935 {
936 /*
937 * only source the prefix once. this allows the label change
938 * operation to work
939 */
940 fib_entry_index = fib_table_entry_special_dpo_add(fib_index, prefix,
941 FIB_SOURCE_MPLS,
942 FIB_ENTRY_FLAG_NONE,
943 NULL);
944 }
945
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100946 fib_entry_set_source_data(fib_entry_index, FIB_SOURCE_MPLS, &label);
947
948 return (fib_entry_index);
949}
950
951void
952fib_table_entry_local_label_remove (u32 fib_index,
953 const fib_prefix_t *prefix,
954 mpls_label_t label)
955{
956 fib_node_index_t fib_entry_index;
957 const void *data;
958 mpls_label_t pl;
959
960 fib_entry_index = fib_table_lookup_exact_match(fib_index, prefix);
961
962 if (FIB_NODE_INDEX_INVALID == fib_entry_index)
963 return;
964
965 data = fib_entry_get_source_data(fib_entry_index, FIB_SOURCE_MPLS);
966
967 if (NULL == data)
968 return;
969
970 pl = *(mpls_label_t*)data;
971
972 if (pl != label)
973 return;
974
975 pl = MPLS_LABEL_INVALID;
976
977 fib_entry_set_source_data(fib_entry_index, FIB_SOURCE_MPLS, &pl);
978 fib_table_entry_special_remove(fib_index,
979 prefix,
980 FIB_SOURCE_MPLS);
981}
982
983u32
984fib_table_get_index_for_sw_if_index (fib_protocol_t proto,
985 u32 sw_if_index)
986{
987 switch (proto)
988 {
989 case FIB_PROTOCOL_IP4:
990 return (ip4_fib_table_get_index_for_sw_if_index(sw_if_index));
991 case FIB_PROTOCOL_IP6:
992 return (ip6_fib_table_get_index_for_sw_if_index(sw_if_index));
993 case FIB_PROTOCOL_MPLS:
994 return (mpls_fib_table_get_index_for_sw_if_index(sw_if_index));
995 }
996 return (~0);
997}
998
999flow_hash_config_t
1000fib_table_get_flow_hash_config (u32 fib_index,
1001 fib_protocol_t proto)
1002{
Neale Ranns227038a2017-04-21 01:07:59 -07001003 fib_table_t *fib;
1004
1005 fib = fib_table_get(fib_index, proto);
1006
1007 return (fib->ft_flow_hash_config);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001008}
Neale Rannsd792d9c2017-10-21 10:53:20 -07001009
Neale Ranns41da54f2017-05-02 10:15:19 -07001010flow_hash_config_t
1011fib_table_get_default_flow_hash_config (fib_protocol_t proto)
1012{
1013 switch (proto)
1014 {
1015 case FIB_PROTOCOL_IP4:
1016 case FIB_PROTOCOL_IP6:
1017 return (IP_FLOW_HASH_DEFAULT);
1018
1019 case FIB_PROTOCOL_MPLS:
1020 return (MPLS_FLOW_HASH_DEFAULT);
1021 }
1022
1023 ASSERT(0);
1024 return (IP_FLOW_HASH_DEFAULT);
1025}
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001026
Neale Ranns227038a2017-04-21 01:07:59 -07001027/**
1028 * @brief Table set flow hash config context.
1029 */
1030typedef struct fib_table_set_flow_hash_config_ctx_t_
1031{
1032 /**
1033 * the flow hash config to set
1034 */
1035 flow_hash_config_t hash_config;
1036} fib_table_set_flow_hash_config_ctx_t;
1037
Neale Ranns89541992017-04-06 04:41:02 -07001038static fib_table_walk_rc_t
Neale Ranns227038a2017-04-21 01:07:59 -07001039fib_table_set_flow_hash_config_cb (fib_node_index_t fib_entry_index,
1040 void *arg)
1041{
1042 fib_table_set_flow_hash_config_ctx_t *ctx = arg;
1043
1044 fib_entry_set_flow_hash_config(fib_entry_index, ctx->hash_config);
1045
Neale Ranns89541992017-04-06 04:41:02 -07001046 return (FIB_TABLE_WALK_CONTINUE);
Neale Ranns227038a2017-04-21 01:07:59 -07001047}
1048
1049void
1050fib_table_set_flow_hash_config (u32 fib_index,
1051 fib_protocol_t proto,
1052 flow_hash_config_t hash_config)
1053{
1054 fib_table_set_flow_hash_config_ctx_t ctx = {
1055 .hash_config = hash_config,
1056 };
1057 fib_table_t *fib;
1058
1059 fib = fib_table_get(fib_index, proto);
1060 fib->ft_flow_hash_config = hash_config;
1061
1062 fib_table_walk(fib_index, proto,
1063 fib_table_set_flow_hash_config_cb,
1064 &ctx);
1065}
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001066
1067u32
1068fib_table_get_table_id_for_sw_if_index (fib_protocol_t proto,
1069 u32 sw_if_index)
1070{
1071 fib_table_t *fib_table;
1072
1073 fib_table = fib_table_get(fib_table_get_index_for_sw_if_index(
1074 proto, sw_if_index),
1075 proto);
1076
1077 return ((NULL != fib_table ? fib_table->ft_table_id : ~0));
1078}
1079
1080u32
Neale Ranns25b04942018-04-04 09:34:50 -07001081fib_table_get_table_id (u32 fib_index,
1082 fib_protocol_t proto)
1083{
1084 fib_table_t *fib_table;
1085
1086 fib_table = fib_table_get(fib_index, proto);
1087
1088 return ((NULL != fib_table ? fib_table->ft_table_id : ~0));
1089}
1090
1091u32
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001092fib_table_find (fib_protocol_t proto,
1093 u32 table_id)
1094{
1095 switch (proto)
1096 {
1097 case FIB_PROTOCOL_IP4:
1098 return (ip4_fib_index_from_table_id(table_id));
1099 case FIB_PROTOCOL_IP6:
1100 return (ip6_fib_index_from_table_id(table_id));
1101 case FIB_PROTOCOL_MPLS:
1102 return (mpls_fib_index_from_table_id(table_id));
1103 }
1104 return (~0);
1105}
1106
Neale Ranns2297af02017-09-12 09:45:04 -07001107static u32
1108fib_table_find_or_create_and_lock_i (fib_protocol_t proto,
1109 u32 table_id,
1110 fib_source_t src,
1111 const u8 *name)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001112{
1113 fib_table_t *fib_table;
1114 fib_node_index_t fi;
1115
1116 switch (proto)
1117 {
1118 case FIB_PROTOCOL_IP4:
Neale Ranns15002542017-09-10 04:39:11 -07001119 fi = ip4_fib_table_find_or_create_and_lock(table_id, src);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001120 break;
1121 case FIB_PROTOCOL_IP6:
Neale Ranns15002542017-09-10 04:39:11 -07001122 fi = ip6_fib_table_find_or_create_and_lock(table_id, src);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001123 break;
1124 case FIB_PROTOCOL_MPLS:
Neale Ranns15002542017-09-10 04:39:11 -07001125 fi = mpls_fib_table_find_or_create_and_lock(table_id, src);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001126 break;
1127 default:
1128 return (~0);
1129 }
1130
1131 fib_table = fib_table_get(fi, proto);
1132
Neale Ranns2297af02017-09-12 09:45:04 -07001133 if (NULL == fib_table->ft_desc)
1134 {
1135 if (name && name[0])
1136 {
1137 fib_table->ft_desc = format(NULL, "%s", name);
1138 }
1139 else
1140 {
1141 fib_table->ft_desc = format(NULL, "%U-VRF:%d",
1142 format_fib_protocol, proto,
1143 table_id);
1144 }
1145 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001146
1147 return (fi);
1148}
1149
1150u32
Neale Ranns2297af02017-09-12 09:45:04 -07001151fib_table_find_or_create_and_lock (fib_protocol_t proto,
1152 u32 table_id,
1153 fib_source_t src)
1154{
1155 return (fib_table_find_or_create_and_lock_i(proto, table_id,
1156 src, NULL));
1157}
1158
1159u32
1160fib_table_find_or_create_and_lock_w_name (fib_protocol_t proto,
1161 u32 table_id,
1162 fib_source_t src,
1163 const u8 *name)
1164{
1165 return (fib_table_find_or_create_and_lock_i(proto, table_id,
1166 src, name));
1167}
1168
1169u32
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001170fib_table_create_and_lock (fib_protocol_t proto,
Neale Ranns15002542017-09-10 04:39:11 -07001171 fib_source_t src,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001172 const char *const fmt,
1173 ...)
1174{
1175 fib_table_t *fib_table;
1176 fib_node_index_t fi;
1177 va_list ap;
1178
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001179
1180 switch (proto)
1181 {
1182 case FIB_PROTOCOL_IP4:
Neale Ranns15002542017-09-10 04:39:11 -07001183 fi = ip4_fib_table_create_and_lock(src);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001184 break;
1185 case FIB_PROTOCOL_IP6:
Neale Ranns53da2212018-02-24 02:11:19 -08001186 fi = ip6_fib_table_create_and_lock(src, FIB_TABLE_FLAG_NONE, NULL);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001187 break;
1188 case FIB_PROTOCOL_MPLS:
Neale Ranns15002542017-09-10 04:39:11 -07001189 fi = mpls_fib_table_create_and_lock(src);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001190 break;
1191 default:
1192 return (~0);
1193 }
1194
1195 fib_table = fib_table_get(fi, proto);
1196
Paul Vinciguerra0c0383d2018-10-24 12:14:09 -07001197 va_start(ap, fmt);
1198
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001199 fib_table->ft_desc = va_format(fib_table->ft_desc, fmt, &ap);
1200
1201 va_end(ap);
1202 return (fi);
1203}
1204
1205static void
1206fib_table_destroy (fib_table_t *fib_table)
1207{
1208 vec_free(fib_table->ft_desc);
1209
1210 switch (fib_table->ft_proto)
1211 {
1212 case FIB_PROTOCOL_IP4:
Neale Rannsa3af3372017-03-28 03:49:52 -07001213 ip4_fib_table_destroy(fib_table->ft_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001214 break;
1215 case FIB_PROTOCOL_IP6:
1216 ip6_fib_table_destroy(fib_table->ft_index);
1217 break;
1218 case FIB_PROTOCOL_MPLS:
Neale Rannsa3af3372017-03-28 03:49:52 -07001219 mpls_fib_table_destroy(fib_table->ft_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001220 break;
1221 }
1222}
Neale Ranns5a8123b2017-01-26 01:18:23 -08001223
Neale Ranns32e1c012016-11-22 17:07:28 +00001224void
1225fib_table_walk (u32 fib_index,
1226 fib_protocol_t proto,
1227 fib_table_walk_fn_t fn,
1228 void *ctx)
1229{
1230 switch (proto)
1231 {
1232 case FIB_PROTOCOL_IP4:
1233 ip4_fib_table_walk(ip4_fib_get(fib_index), fn, ctx);
1234 break;
1235 case FIB_PROTOCOL_IP6:
1236 ip6_fib_table_walk(fib_index, fn, ctx);
1237 break;
1238 case FIB_PROTOCOL_MPLS:
1239 mpls_fib_table_walk(mpls_fib_get(fib_index), fn, ctx);
1240 break;
1241 }
1242}
1243
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001244void
Neale Ranns89541992017-04-06 04:41:02 -07001245fib_table_sub_tree_walk (u32 fib_index,
1246 fib_protocol_t proto,
1247 const fib_prefix_t *root,
1248 fib_table_walk_fn_t fn,
1249 void *ctx)
1250{
1251 switch (proto)
1252 {
1253 case FIB_PROTOCOL_IP4:
1254 ip4_fib_table_sub_tree_walk(ip4_fib_get(fib_index), root, fn, ctx);
1255 break;
1256 case FIB_PROTOCOL_IP6:
1257 ip6_fib_table_sub_tree_walk(fib_index, root, fn, ctx);
1258 break;
1259 case FIB_PROTOCOL_MPLS:
1260 break;
1261 }
1262}
1263
Neale Ranns3bab8f92019-12-04 06:11:00 +00001264static void
1265fib_table_lock_dec (fib_table_t *fib_table,
1266 fib_source_t source)
1267{
1268 vec_validate(fib_table->ft_locks, source);
1269
1270 fib_table->ft_locks[source]--;
1271 fib_table->ft_total_locks--;
1272}
1273
1274static void
1275fib_table_lock_inc (fib_table_t *fib_table,
1276 fib_source_t source)
1277{
1278 vec_validate(fib_table->ft_locks, source);
1279
1280 ASSERT(fib_table->ft_locks[source] < (0xffff - 1));
1281 fib_table->ft_locks[source]++;
1282 fib_table->ft_total_locks++;
1283}
1284
Neale Ranns89541992017-04-06 04:41:02 -07001285void
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001286fib_table_unlock (u32 fib_index,
Neale Ranns15002542017-09-10 04:39:11 -07001287 fib_protocol_t proto,
1288 fib_source_t source)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001289{
1290 fib_table_t *fib_table;
1291
1292 fib_table = fib_table_get(fib_index, proto);
Neale Ranns3bab8f92019-12-04 06:11:00 +00001293 fib_table_lock_dec(fib_table, source);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001294
Neale Ranns3bab8f92019-12-04 06:11:00 +00001295 if (0 == fib_table->ft_total_locks)
Neale Ranns15002542017-09-10 04:39:11 -07001296 {
1297 /*
1298 * no more locak from any source - kill it
1299 */
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001300 fib_table_destroy(fib_table);
1301 }
1302}
Neale Ranns15002542017-09-10 04:39:11 -07001303
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001304void
1305fib_table_lock (u32 fib_index,
Neale Ranns15002542017-09-10 04:39:11 -07001306 fib_protocol_t proto,
1307 fib_source_t source)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001308{
1309 fib_table_t *fib_table;
1310
1311 fib_table = fib_table_get(fib_index, proto);
Neale Ranns6fff24a2018-09-10 19:14:07 -07001312
Neale Ranns3bab8f92019-12-04 06:11:00 +00001313 fib_table_lock_inc(fib_table, source);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001314}
1315
1316u32
1317fib_table_get_num_entries (u32 fib_index,
1318 fib_protocol_t proto,
1319 fib_source_t source)
1320{
1321 fib_table_t *fib_table;
1322
1323 fib_table = fib_table_get(fib_index, proto);
1324
1325 return (fib_table->ft_src_route_counts[source]);
1326}
1327
1328u8*
Christophe Fontained3c008d2017-10-02 18:10:54 +02001329format_fib_table_name (u8* s, va_list* ap)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001330{
Christophe Fontained3c008d2017-10-02 18:10:54 +02001331 fib_node_index_t fib_index = va_arg(*ap, fib_node_index_t);
1332 fib_protocol_t proto = va_arg(*ap, int); // int promotion
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001333 fib_table_t *fib_table;
1334
1335 fib_table = fib_table_get(fib_index, proto);
1336
1337 s = format(s, "%v", fib_table->ft_desc);
1338
1339 return (s);
1340}
1341
Neale Ranns9db6ada2019-11-08 12:42:31 +00001342u8*
1343format_fib_table_flags (u8 *s, va_list *args)
1344{
1345 fib_table_flags_t flags = va_arg(*args, int);
1346 fib_table_attribute_t attr;
1347
1348 if (!flags)
1349 {
1350 return format(s, "none");
1351 }
1352
1353 FOR_EACH_FIB_TABLE_ATTRIBUTE(attr) {
1354 if (1 << attr & flags) {
1355 s = format(s, "%s", fib_table_flags_strings[attr]);
1356 }
1357 }
1358
1359 return (s);
1360}
1361
Neale Ranns32e1c012016-11-22 17:07:28 +00001362/**
1363 * @brief Table flush context. Store the indicies of matching FIB entries
1364 * that need to be removed.
1365 */
1366typedef struct fib_table_flush_ctx_t_
1367{
1368 /**
1369 * The list of entries to flush
1370 */
1371 fib_node_index_t *ftf_entries;
1372
1373 /**
1374 * The source we are flushing
1375 */
1376 fib_source_t ftf_source;
1377} fib_table_flush_ctx_t;
1378
Neale Ranns89541992017-04-06 04:41:02 -07001379static fib_table_walk_rc_t
Neale Ranns32e1c012016-11-22 17:07:28 +00001380fib_table_flush_cb (fib_node_index_t fib_entry_index,
1381 void *arg)
1382{
1383 fib_table_flush_ctx_t *ctx = arg;
1384
1385 if (fib_entry_is_sourced(fib_entry_index, ctx->ftf_source))
1386 {
1387 vec_add1(ctx->ftf_entries, fib_entry_index);
1388 }
Neale Ranns89541992017-04-06 04:41:02 -07001389 return (FIB_TABLE_WALK_CONTINUE);
Neale Ranns32e1c012016-11-22 17:07:28 +00001390}
1391
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001392void
1393fib_table_flush (u32 fib_index,
1394 fib_protocol_t proto,
1395 fib_source_t source)
1396{
Neale Ranns32e1c012016-11-22 17:07:28 +00001397 fib_node_index_t *fib_entry_index;
1398 fib_table_flush_ctx_t ctx = {
1399 .ftf_entries = NULL,
1400 .ftf_source = source,
1401 };
1402
1403 fib_table_walk(fib_index, proto,
1404 fib_table_flush_cb,
1405 &ctx);
1406
1407 vec_foreach(fib_entry_index, ctx.ftf_entries)
1408 {
Neale Rannsa8d9f302017-02-20 09:17:02 -08001409 fib_table_entry_delete_index(*fib_entry_index, source);
Neale Ranns32e1c012016-11-22 17:07:28 +00001410 }
1411
1412 vec_free(ctx.ftf_entries);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001413}
Neale Rannsc87aafa2017-11-29 00:59:31 -08001414
Neale Ranns9db6ada2019-11-08 12:42:31 +00001415static fib_table_walk_rc_t
1416fib_table_mark_cb (fib_node_index_t fib_entry_index,
1417 void *arg)
1418{
1419 fib_table_flush_ctx_t *ctx = arg;
1420
1421 if (fib_entry_is_sourced(fib_entry_index, ctx->ftf_source))
1422 {
1423 fib_entry_mark(fib_entry_index, ctx->ftf_source);
1424 }
1425 return (FIB_TABLE_WALK_CONTINUE);
1426}
1427
1428void
1429fib_table_mark (u32 fib_index,
1430 fib_protocol_t proto,
1431 fib_source_t source)
1432{
1433 fib_table_flush_ctx_t ctx = {
1434 .ftf_source = source,
1435 };
1436 fib_table_t *fib_table;
1437
1438 fib_table = fib_table_get(fib_index, proto);
1439
1440 fib_table->ft_epoch++;
1441 fib_table->ft_flags |= FIB_TABLE_FLAG_RESYNC;
1442
1443 fib_table_walk(fib_index, proto,
1444 fib_table_mark_cb,
1445 &ctx);
1446}
1447
1448static fib_table_walk_rc_t
1449fib_table_sweep_cb (fib_node_index_t fib_entry_index,
1450 void *arg)
1451{
1452 fib_table_flush_ctx_t *ctx = arg;
1453
1454 if (fib_entry_is_marked(fib_entry_index, ctx->ftf_source))
1455 {
1456 vec_add1(ctx->ftf_entries, fib_entry_index);
1457 }
1458 return (FIB_TABLE_WALK_CONTINUE);
1459}
1460
1461void
1462fib_table_sweep (u32 fib_index,
1463 fib_protocol_t proto,
1464 fib_source_t source)
1465{
1466 fib_table_flush_ctx_t ctx = {
1467 .ftf_source = source,
1468 };
1469 fib_node_index_t *fib_entry_index;
1470 fib_table_t *fib_table;
1471
1472 fib_table = fib_table_get(fib_index, proto);
1473
1474 fib_table->ft_flags &= ~FIB_TABLE_FLAG_RESYNC;
1475
1476 fib_table_walk(fib_index, proto,
1477 fib_table_sweep_cb,
1478 &ctx);
1479
1480 vec_foreach(fib_entry_index, ctx.ftf_entries)
1481 {
1482 fib_table_entry_delete_index(*fib_entry_index, source);
1483 }
1484
1485 vec_free(ctx.ftf_entries);
1486}
1487
Neale Rannsc87aafa2017-11-29 00:59:31 -08001488u8 *
1489format_fib_table_memory (u8 *s, va_list *args)
1490{
1491 s = format(s, "%U", format_ip4_fib_table_memory);
1492 s = format(s, "%U", format_ip6_fib_table_memory);
1493 s = format(s, "%U", format_mpls_fib_table_memory);
1494
1495 return (s);
1496}