blob: 9169dccff8a3067ff4581a5bf2f4ffba998ff84f [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/ip/format.h>
18#include <vnet/ip/lookup.h>
19#include <vnet/adj/adj.h>
20#include <vnet/dpo/load_balance.h>
21#include <vnet/dpo/drop_dpo.h>
22
23#include <vnet/fib/fib_entry.h>
24#include <vnet/fib/fib_walk.h>
25#include <vnet/fib/fib_entry_src.h>
26#include <vnet/fib/fib_entry_cover.h>
27#include <vnet/fib/fib_table.h>
28#include <vnet/fib/fib_internal.h>
29#include <vnet/fib/fib_attached_export.h>
30#include <vnet/fib/fib_path_ext.h>
Neale Ranns1f50bf82019-07-16 15:28:52 +000031#include <vnet/fib/fib_entry_delegate.h>
32#include <vnet/fib/fib_entry_track.h>
Neale Ranns0bfe5d82016-08-25 15:29:12 +010033
34/*
35 * Array of strings/names for the FIB sources
36 */
37static const char *fib_source_names[] = FIB_SOURCES;
38static const char *fib_attribute_names[] = FIB_ENTRY_ATTRIBUTES;
Neale Ranns89541992017-04-06 04:41:02 -070039static const char *fib_src_attribute_names[] = FIB_ENTRY_SRC_ATTRIBUTES;
Neale Ranns0bfe5d82016-08-25 15:29:12 +010040
41/*
42 * Pool for all fib_entries
43 */
44static fib_entry_t *fib_entry_pool;
45
Neale Ranns710071b2018-09-24 12:36:26 +000046/**
47 * the logger
48 */
49vlib_log_class_t fib_entry_logger;
50
Neale Ranns0bfe5d82016-08-25 15:29:12 +010051fib_entry_t *
52fib_entry_get (fib_node_index_t index)
53{
54 return (pool_elt_at_index(fib_entry_pool, index));
55}
56
57static fib_node_t *
58fib_entry_get_node (fib_node_index_t index)
59{
60 return ((fib_node_t*)fib_entry_get(index));
61}
62
63fib_node_index_t
64fib_entry_get_index (const fib_entry_t * fib_entry)
65{
66 return (fib_entry - fib_entry_pool);
67}
68
Neale Rannsda78f952017-05-24 09:15:43 -070069fib_protocol_t
Neale Ranns0bfe5d82016-08-25 15:29:12 +010070fib_entry_get_proto (const fib_entry_t * fib_entry)
71{
72 return (fib_entry->fe_prefix.fp_proto);
73}
74
Neale Rannsda78f952017-05-24 09:15:43 -070075dpo_proto_t
76fib_entry_get_dpo_proto (const fib_entry_t * fib_entry)
77{
78 return (fib_proto_to_dpo(fib_entry->fe_prefix.fp_proto));
79}
80
Neale Ranns0bfe5d82016-08-25 15:29:12 +010081fib_forward_chain_type_t
82fib_entry_get_default_chain_type (const fib_entry_t *fib_entry)
83{
84 switch (fib_entry->fe_prefix.fp_proto)
85 {
86 case FIB_PROTOCOL_IP4:
87 return (FIB_FORW_CHAIN_TYPE_UNICAST_IP4);
88 case FIB_PROTOCOL_IP6:
89 return (FIB_FORW_CHAIN_TYPE_UNICAST_IP6);
90 case FIB_PROTOCOL_MPLS:
91 if (MPLS_EOS == fib_entry->fe_prefix.fp_eos)
Neale Ranns0f26c5a2017-03-01 15:12:11 -080092 return (FIB_FORW_CHAIN_TYPE_MPLS_EOS);
Neale Ranns0bfe5d82016-08-25 15:29:12 +010093 else
94 return (FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS);
95 }
96
97 return (FIB_FORW_CHAIN_TYPE_UNICAST_IP4);
98}
99
100u8 *
Neale Ranns15002542017-09-10 04:39:11 -0700101format_fib_source (u8 * s, va_list * args)
102{
103 fib_source_t source = va_arg (*args, int);
104
Neale Ranns2297af02017-09-12 09:45:04 -0700105 s = format (s, "src:%s", fib_source_names[source]);
Neale Ranns15002542017-09-10 04:39:11 -0700106
107 return (s);
108}
109
110u8 *
Neale Ranns710071b2018-09-24 12:36:26 +0000111format_fib_entry_flags (u8 *s, va_list *args)
112{
113 fib_entry_attribute_t attr;
114 fib_entry_flag_t flag = va_arg(*args, int);
115
116 FOR_EACH_FIB_ATTRIBUTE(attr) {
117 if ((1<<attr) & flag) {
118 s = format (s, "%s,", fib_attribute_names[attr]);
119 }
120 }
121
122 return (s);
123}
124
125u8 *
126format_fib_entry_src_flags (u8 *s, va_list *args)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100127{
Neale Ranns89541992017-04-06 04:41:02 -0700128 fib_entry_src_attribute_t sattr;
Neale Ranns710071b2018-09-24 12:36:26 +0000129 fib_entry_src_flag_t flag = va_arg(*args, int);
130
131 FOR_EACH_FIB_SRC_ATTRIBUTE(sattr) {
132 if ((1<<sattr) & flag) {
133 s = format (s, "%s,", fib_src_attribute_names[sattr]);
134 }
135 }
136
137 return (s);
138}
139
140u8 *
141format_fib_entry (u8 * s, va_list * args)
142{
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100143 fib_forward_chain_type_t fct;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100144 fib_entry_t *fib_entry;
145 fib_entry_src_t *src;
146 fib_node_index_t fei;
147 fib_source_t source;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100148 int level;
149
150 fei = va_arg (*args, fib_node_index_t);
151 level = va_arg (*args, int);
152 fib_entry = fib_entry_get(fei);
153
154 s = format (s, "%U", format_fib_prefix, &fib_entry->fe_prefix);
155
Neale Rannsabcf3ea2018-03-26 09:10:41 -0700156 if (level >= FIB_ENTRY_FORMAT_DETAIL)
157 {
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100158 s = format (s, " fib:%d", fib_entry->fe_fib_index);
159 s = format (s, " index:%d", fib_entry_get_index(fib_entry));
160 s = format (s, " locks:%d", fib_entry->fe_node.fn_locks);
161
162 FOR_EACH_SRC_ADDED(fib_entry, src, source,
163 ({
Neale Ranns2297af02017-09-12 09:45:04 -0700164 s = format (s, "\n %U", format_fib_source, source);
Neale Ranns89541992017-04-06 04:41:02 -0700165 s = format (s, " refs:%d", src->fes_ref_count);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100166 if (FIB_ENTRY_FLAG_NONE != src->fes_entry_flags) {
Neale Ranns710071b2018-09-24 12:36:26 +0000167 s = format(s, " entry-flags:%U",
168 format_fib_entry_flags, src->fes_entry_flags);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100169 }
Neale Ranns89541992017-04-06 04:41:02 -0700170 if (FIB_ENTRY_SRC_FLAG_NONE != src->fes_flags) {
Neale Ranns710071b2018-09-24 12:36:26 +0000171 s = format(s, " src-flags:%U",
172 format_fib_entry_src_flags, src->fes_flags);
Neale Ranns89541992017-04-06 04:41:02 -0700173 }
Neale Ranns2303cb12018-02-21 04:57:17 -0800174 s = fib_entry_src_format(fib_entry, source, s);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100175 s = format (s, "\n");
176 if (FIB_NODE_INDEX_INVALID != src->fes_pl)
177 {
178 s = fib_path_list_format(src->fes_pl, s);
179 }
Neale Ranns81424992017-05-18 03:03:22 -0700180 s = format(s, "%U", format_fib_path_ext_list, &src->fes_path_exts);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100181 }));
182
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100183 s = format (s, "\n forwarding: ");
Neale Rannsabcf3ea2018-03-26 09:10:41 -0700184 }
185 else
186 {
187 s = format (s, "\n");
188 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100189
190 fct = fib_entry_get_default_chain_type(fib_entry);
191
Neale Rannsad422ed2016-11-02 14:20:04 +0000192 if (!dpo_id_is_valid(&fib_entry->fe_lb))
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100193 {
194 s = format (s, " UNRESOLVED\n");
195 return (s);
196 }
197 else
198 {
Neale Rannsad422ed2016-11-02 14:20:04 +0000199 s = format(s, " %U-chain\n %U",
200 format_fib_forw_chain_type, fct,
201 format_dpo_id,
202 &fib_entry->fe_lb,
203 2);
204 s = format(s, "\n");
205
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100206 if (level >= FIB_ENTRY_FORMAT_DETAIL2)
207 {
Neale Ranns1f50bf82019-07-16 15:28:52 +0000208 index_t *fedi;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100209
Neale Ranns88fc83e2017-04-05 08:11:14 -0700210 s = format (s, " Delegates:\n");
Neale Ranns1f50bf82019-07-16 15:28:52 +0000211 vec_foreach(fedi, fib_entry->fe_delegates)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100212 {
Neale Ranns1f50bf82019-07-16 15:28:52 +0000213 s = format(s, " %U\n", format_fib_entry_delegate, *fedi);
214 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100215 }
216 }
217
218 if (level >= FIB_ENTRY_FORMAT_DETAIL2)
219 {
Neale Ranns88fc83e2017-04-05 08:11:14 -0700220 s = format(s, " Children:");
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100221 s = fib_node_children_format(fib_entry->fe_node.fn_children, s);
222 }
223
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100224 return (s);
225}
226
227static fib_entry_t*
228fib_entry_from_fib_node (fib_node_t *node)
229{
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100230 ASSERT(FIB_NODE_TYPE_ENTRY == node->fn_type);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100231 return ((fib_entry_t*)node);
232}
233
234static void
235fib_entry_last_lock_gone (fib_node_t *node)
236{
Neale Rannsad422ed2016-11-02 14:20:04 +0000237 fib_entry_delegate_type_t fdt;
238 fib_entry_delegate_t *fed;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100239 fib_entry_t *fib_entry;
240
241 fib_entry = fib_entry_from_fib_node(node);
242
Neale Ranns2303cb12018-02-21 04:57:17 -0800243 ASSERT(!dpo_id_is_valid(&fib_entry->fe_lb));
244
Neale Rannsad422ed2016-11-02 14:20:04 +0000245 FOR_EACH_DELEGATE_CHAIN(fib_entry, fdt, fed,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100246 {
Neale Rannsad422ed2016-11-02 14:20:04 +0000247 dpo_reset(&fed->fd_dpo);
248 fib_entry_delegate_remove(fib_entry, fdt);
249 });
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100250
251 FIB_ENTRY_DBG(fib_entry, "last-lock");
252
253 fib_node_deinit(&fib_entry->fe_node);
Neale Rannsad422ed2016-11-02 14:20:04 +0000254
255 ASSERT(0 == vec_len(fib_entry->fe_delegates));
256 vec_free(fib_entry->fe_delegates);
Neale Rannsa4e77662017-12-04 20:00:30 +0000257 vec_free(fib_entry->fe_srcs);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100258 pool_put(fib_entry_pool, fib_entry);
259}
260
Neale Rannsa4e77662017-12-04 20:00:30 +0000261static fib_entry_src_t*
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100262fib_entry_get_best_src_i (const fib_entry_t *fib_entry)
263{
Neale Rannsa4e77662017-12-04 20:00:30 +0000264 fib_entry_src_t *bsrc;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100265
266 /*
267 * the enum of sources is deliberately arranged in priority order
268 */
Neale Rannsa4e77662017-12-04 20:00:30 +0000269 if (0 == vec_len(fib_entry->fe_srcs))
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100270 {
Neale Rannsa4e77662017-12-04 20:00:30 +0000271 bsrc = NULL;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100272 }
273 else
274 {
Neale Rannsa4e77662017-12-04 20:00:30 +0000275 bsrc = vec_elt_at_index(fib_entry->fe_srcs, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100276 }
277
278 return (bsrc);
279}
280
281static fib_source_t
282fib_entry_src_get_source (const fib_entry_src_t *esrc)
283{
284 if (NULL != esrc)
285 {
286 return (esrc->fes_src);
287 }
Neale Rannsa4e77662017-12-04 20:00:30 +0000288 return (FIB_SOURCE_MAX);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100289}
290
291static fib_entry_flag_t
292fib_entry_src_get_flags (const fib_entry_src_t *esrc)
293{
294 if (NULL != esrc)
295 {
296 return (esrc->fes_entry_flags);
297 }
298 return (FIB_ENTRY_FLAG_NONE);
299}
300
301fib_entry_flag_t
302fib_entry_get_flags (fib_node_index_t fib_entry_index)
303{
304 return (fib_entry_get_flags_i(fib_entry_get(fib_entry_index)));
305}
306
307/*
308 * fib_entry_back_walk_notify
309 *
310 * A back walk has reach this entry.
311 */
312static fib_node_back_walk_rc_t
313fib_entry_back_walk_notify (fib_node_t *node,
314 fib_node_back_walk_ctx_t *ctx)
315{
316 fib_entry_t *fib_entry;
317
318 fib_entry = fib_entry_from_fib_node(node);
319
320 if (FIB_NODE_BW_REASON_FLAG_EVALUATE & ctx->fnbw_reason ||
321 FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE & ctx->fnbw_reason ||
Neale Rannsad95b5d2016-11-10 20:35:14 +0000322 FIB_NODE_BW_REASON_FLAG_ADJ_DOWN & ctx->fnbw_reason ||
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100323 FIB_NODE_BW_REASON_FLAG_INTERFACE_UP & ctx->fnbw_reason ||
324 FIB_NODE_BW_REASON_FLAG_INTERFACE_DOWN & ctx->fnbw_reason ||
325 FIB_NODE_BW_REASON_FLAG_INTERFACE_DELETE & ctx->fnbw_reason)
326 {
327 fib_entry_src_action_reactivate(fib_entry,
328 fib_entry_get_best_source(
329 fib_entry_get_index(fib_entry)));
330 }
331
Neale Rannsb80c5362016-10-08 13:03:40 +0100332 /*
333 * all other walk types can be reclassifed to a re-evaluate to
334 * all recursive dependents.
335 * By reclassifying we ensure that should any of these walk types meet
336 * they can be merged.
337 */
338 ctx->fnbw_reason = FIB_NODE_BW_REASON_FLAG_EVALUATE;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100339
Neale Rannsb80c5362016-10-08 13:03:40 +0100340 /*
Neale Rannsad95b5d2016-11-10 20:35:14 +0000341 * ... and nothing is forced sync from now on.
342 */
343 ctx->fnbw_flags &= ~FIB_NODE_BW_FLAG_FORCE_SYNC;
344
Neale Ranns710071b2018-09-24 12:36:26 +0000345 FIB_ENTRY_DBG(fib_entry, "bw:%U",
346 format_fib_node_bw_reason, ctx->fnbw_reason);
347
Neale Rannsad95b5d2016-11-10 20:35:14 +0000348 /*
Neale Rannsb80c5362016-10-08 13:03:40 +0100349 * propagate the backwalk further if we haven't already reached the
350 * maximum depth.
351 */
352 fib_walk_sync(FIB_NODE_TYPE_ENTRY,
353 fib_entry_get_index(fib_entry),
354 ctx);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100355
356 return (FIB_NODE_BACK_WALK_CONTINUE);
357}
358
Neale Ranns6c3ebcc2016-10-02 21:20:15 +0100359static void
360fib_entry_show_memory (void)
361{
362 u32 n_srcs = 0, n_exts = 0;
363 fib_entry_src_t *esrc;
364 fib_entry_t *entry;
365
366 fib_show_memory_usage("Entry",
367 pool_elts(fib_entry_pool),
368 pool_len(fib_entry_pool),
369 sizeof(fib_entry_t));
370
371 pool_foreach(entry, fib_entry_pool,
372 ({
Neale Rannsa4e77662017-12-04 20:00:30 +0000373 n_srcs += vec_len(entry->fe_srcs);
374 vec_foreach(esrc, entry->fe_srcs)
375 {
376 n_exts += fib_path_ext_list_length(&esrc->fes_path_exts);
377 }
Neale Ranns6c3ebcc2016-10-02 21:20:15 +0100378 }));
379
380 fib_show_memory_usage("Entry Source",
381 n_srcs, n_srcs, sizeof(fib_entry_src_t));
382 fib_show_memory_usage("Entry Path-Extensions",
383 n_exts, n_exts,
384 sizeof(fib_path_ext_t));
385}
386
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100387/*
388 * The FIB path-list's graph node virtual function table
389 */
390static const fib_node_vft_t fib_entry_vft = {
391 .fnv_get = fib_entry_get_node,
392 .fnv_last_lock = fib_entry_last_lock_gone,
393 .fnv_back_walk = fib_entry_back_walk_notify,
Neale Ranns6c3ebcc2016-10-02 21:20:15 +0100394 .fnv_mem_show = fib_entry_show_memory,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100395};
396
Neale Ranns3ee44042016-10-03 13:05:48 +0100397/**
398 * @brief Contribute the set of Adjacencies that this entry forwards with
399 * to build the uRPF list of its children
400 */
401void
402fib_entry_contribute_urpf (fib_node_index_t entry_index,
403 index_t urpf)
404{
405 fib_entry_t *fib_entry;
406
407 fib_entry = fib_entry_get(entry_index);
408
409 return (fib_path_list_contribute_urpf(fib_entry->fe_parent, urpf));
410}
411
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100412/*
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800413 * If the client is request a chain for multicast forwarding then swap
414 * the chain type to one that can provide such transport.
415 */
416static fib_forward_chain_type_t
417fib_entry_chain_type_mcast_to_ucast (fib_forward_chain_type_t fct)
418{
419 switch (fct)
420 {
421 case FIB_FORW_CHAIN_TYPE_MCAST_IP4:
422 case FIB_FORW_CHAIN_TYPE_MCAST_IP6:
423 /*
424 * we can only transport IP multicast packets if there is an
425 * LSP.
426 */
427 fct = FIB_FORW_CHAIN_TYPE_MPLS_EOS;
428 break;
429 case FIB_FORW_CHAIN_TYPE_MPLS_EOS:
430 case FIB_FORW_CHAIN_TYPE_UNICAST_IP4:
431 case FIB_FORW_CHAIN_TYPE_UNICAST_IP6:
432 case FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS:
433 case FIB_FORW_CHAIN_TYPE_ETHERNET:
434 case FIB_FORW_CHAIN_TYPE_NSH:
Neale Rannsd792d9c2017-10-21 10:53:20 -0700435 case FIB_FORW_CHAIN_TYPE_BIER:
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800436 break;
437 }
438
439 return (fct);
440}
441
442/*
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100443 * fib_entry_contribute_forwarding
444 *
445 * Get an lock the forwarding information (DPO) contributed by the FIB entry.
446 */
447void
448fib_entry_contribute_forwarding (fib_node_index_t fib_entry_index,
Neale Rannsad422ed2016-11-02 14:20:04 +0000449 fib_forward_chain_type_t fct,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100450 dpo_id_t *dpo)
451{
Neale Rannsad422ed2016-11-02 14:20:04 +0000452 fib_entry_delegate_t *fed;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100453 fib_entry_t *fib_entry;
454
455 fib_entry = fib_entry_get(fib_entry_index);
456
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800457 /*
458 * mfib children ask for mcast chains. fix these to the appropriate ucast types.
459 */
460 fct = fib_entry_chain_type_mcast_to_ucast(fct);
461
Neale Rannsad422ed2016-11-02 14:20:04 +0000462 if (fct == fib_entry_get_default_chain_type(fib_entry))
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100463 {
Neale Rannsad422ed2016-11-02 14:20:04 +0000464 dpo_copy(dpo, &fib_entry->fe_lb);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100465 }
Neale Rannsad422ed2016-11-02 14:20:04 +0000466 else
467 {
Neale Ranns1f50bf82019-07-16 15:28:52 +0000468 fed = fib_entry_delegate_find(fib_entry,
469 fib_entry_chain_type_to_delegate_type(fct));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100470
Neale Rannsad422ed2016-11-02 14:20:04 +0000471 if (NULL == fed)
472 {
473 fed = fib_entry_delegate_find_or_add(
474 fib_entry,
475 fib_entry_chain_type_to_delegate_type(fct));
476 /*
477 * on-demand create eos/non-eos.
478 * There is no on-demand delete because:
479 * - memory versus complexity & reliability:
480 * leaving unrequired [n]eos LB arounds wastes memory, cleaning
481 * then up on the right trigger is more code. i favour the latter.
482 */
483 fib_entry_src_mk_lb(fib_entry,
484 fib_entry_get_best_src_i(fib_entry),
485 fct,
486 &fed->fd_dpo);
487 }
488
489 dpo_copy(dpo, &fed->fd_dpo);
490 }
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800491 /*
Neale Ranns2303cb12018-02-21 04:57:17 -0800492 * use the drop DPO is nothing else is present
493 */
494 if (!dpo_id_is_valid(dpo))
495 {
496 dpo_copy(dpo, drop_dpo_get(fib_forw_chain_type_to_dpo_proto(fct)));
497 }
498
499 /*
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800500 * don't allow the special index indicating replicate.vs.load-balance
501 * to escape to the clients
502 */
503 dpo->dpoi_index &= ~MPLS_IS_REPLICATE;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100504}
505
506const dpo_id_t *
507fib_entry_contribute_ip_forwarding (fib_node_index_t fib_entry_index)
508{
Neale Rannsad422ed2016-11-02 14:20:04 +0000509 fib_forward_chain_type_t fct;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100510 fib_entry_t *fib_entry;
511
512 fib_entry = fib_entry_get(fib_entry_index);
Neale Rannsad422ed2016-11-02 14:20:04 +0000513 fct = fib_entry_get_default_chain_type(fib_entry);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100514
Neale Rannsad422ed2016-11-02 14:20:04 +0000515 ASSERT((fct == FIB_FORW_CHAIN_TYPE_UNICAST_IP4 ||
516 fct == FIB_FORW_CHAIN_TYPE_UNICAST_IP6));
517
Neale Ranns2303cb12018-02-21 04:57:17 -0800518 if (dpo_id_is_valid(&fib_entry->fe_lb))
519 {
520 return (&fib_entry->fe_lb);
521 }
522
523 return (drop_dpo_get(fib_forw_chain_type_to_dpo_proto(fct)));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100524}
525
526adj_index_t
527fib_entry_get_adj (fib_node_index_t fib_entry_index)
528{
529 const dpo_id_t *dpo;
530
531 dpo = fib_entry_contribute_ip_forwarding(fib_entry_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100532
Neale Rannsca193612017-06-14 06:50:08 -0700533 if (dpo_id_is_valid(dpo))
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100534 {
Neale Rannsca193612017-06-14 06:50:08 -0700535 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
536
537 if (dpo_is_adj(dpo))
538 {
539 return (dpo->dpoi_index);
540 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100541 }
542 return (ADJ_INDEX_INVALID);
543}
544
545fib_node_index_t
546fib_entry_get_path_list (fib_node_index_t fib_entry_index)
547{
548 fib_entry_t *fib_entry;
549
550 fib_entry = fib_entry_get(fib_entry_index);
551
552 return (fib_entry->fe_parent);
553}
554
555u32
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100556fib_entry_child_add (fib_node_index_t fib_entry_index,
557 fib_node_type_t child_type,
558 fib_node_index_t child_index)
559{
560 return (fib_node_child_add(FIB_NODE_TYPE_ENTRY,
561 fib_entry_index,
562 child_type,
563 child_index));
564};
565
566void
567fib_entry_child_remove (fib_node_index_t fib_entry_index,
568 u32 sibling_index)
569{
570 fib_node_child_remove(FIB_NODE_TYPE_ENTRY,
571 fib_entry_index,
572 sibling_index);
Neale Rannsad422ed2016-11-02 14:20:04 +0000573
574 if (0 == fib_node_get_n_children(FIB_NODE_TYPE_ENTRY,
575 fib_entry_index))
576 {
577 /*
578 * if there are no children left then there is no reason to keep
579 * the non-default forwarding chains. those chains are built only
580 * because the children want them.
581 */
582 fib_entry_delegate_type_t fdt;
583 fib_entry_delegate_t *fed;
584 fib_entry_t *fib_entry;
585
586 fib_entry = fib_entry_get(fib_entry_index);
587
588 FOR_EACH_DELEGATE_CHAIN(fib_entry, fdt, fed,
589 {
590 dpo_reset(&fed->fd_dpo);
591 fib_entry_delegate_remove(fib_entry, fdt);
592 });
593 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100594}
595
596static fib_entry_t *
597fib_entry_alloc (u32 fib_index,
598 const fib_prefix_t *prefix,
599 fib_node_index_t *fib_entry_index)
600{
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100601 fib_entry_t *fib_entry;
Neale Rannsad422ed2016-11-02 14:20:04 +0000602 fib_prefix_t *fep;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100603
604 pool_get(fib_entry_pool, fib_entry);
Dave Barachb7b92992018-10-17 10:38:51 -0400605 clib_memset(fib_entry, 0, sizeof(*fib_entry));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100606
607 fib_node_init(&fib_entry->fe_node,
608 FIB_NODE_TYPE_ENTRY);
609
610 fib_entry->fe_fib_index = fib_index;
Neale Rannsad422ed2016-11-02 14:20:04 +0000611
612 /*
613 * the one time we need to update the const prefix is when
614 * the entry is first created
615 */
616 fep = (fib_prefix_t*)&(fib_entry->fe_prefix);
617 *fep = *prefix;
618
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100619 if (FIB_PROTOCOL_MPLS == fib_entry->fe_prefix.fp_proto)
620 {
Neale Rannsad422ed2016-11-02 14:20:04 +0000621 fep->fp_len = 21;
622 if (MPLS_NON_EOS == fep->fp_eos)
623 {
624 fep->fp_payload_proto = DPO_PROTO_MPLS;
625 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100626 ASSERT(DPO_PROTO_NONE != fib_entry->fe_prefix.fp_payload_proto);
627 }
628
Neale Rannsad422ed2016-11-02 14:20:04 +0000629 dpo_reset(&fib_entry->fe_lb);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100630
631 *fib_entry_index = fib_entry_get_index(fib_entry);
632
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100633 return (fib_entry);
634}
635
Neale Ranns08a70f12017-02-24 06:16:01 -0800636static fib_entry_t*
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100637fib_entry_post_flag_update_actions (fib_entry_t *fib_entry,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100638 fib_entry_flag_t old_flags)
639{
Neale Ranns08a70f12017-02-24 06:16:01 -0800640 fib_node_index_t fei;
641
642 /*
643 * save the index so we can recover from pool reallocs
644 */
645 fei = fib_entry_get_index(fib_entry);
646
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100647 /*
648 * handle changes to attached export for import entries
649 */
650 int is_import = (FIB_ENTRY_FLAG_IMPORT & fib_entry_get_flags_i(fib_entry));
651 int was_import = (FIB_ENTRY_FLAG_IMPORT & old_flags);
652
653 if (!was_import && is_import)
654 {
655 /*
656 * transition from not exported to exported
657 */
658
659 /*
660 * there is an assumption here that the entry resolves via only
661 * one interface and that it is the cross VRF interface.
662 */
663 u32 sw_if_index = fib_path_list_get_resolving_interface(fib_entry->fe_parent);
664
665 fib_attached_export_import(fib_entry,
666 fib_table_get_index_for_sw_if_index(
667 fib_entry_get_proto(fib_entry),
668 sw_if_index));
669 }
670 else if (was_import && !is_import)
671 {
672 /*
673 * transition from exported to not exported
674 */
675 fib_attached_export_purge(fib_entry);
676 }
677 /*
678 * else
679 * no change. nothing to do.
680 */
681
682 /*
Neale Ranns08a70f12017-02-24 06:16:01 -0800683 * reload the entry address post possible pool realloc
684 */
685 fib_entry = fib_entry_get(fei);
686
687 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100688 * handle changes to attached export for export entries
689 */
690 int is_attached = (FIB_ENTRY_FLAG_ATTACHED & fib_entry_get_flags_i(fib_entry));
691 int was_attached = (FIB_ENTRY_FLAG_ATTACHED & old_flags);
692
693 if (!was_attached && is_attached)
694 {
695 /*
696 * transition to attached. time to export
697 */
698 // FIXME
699 }
700 // else FIXME
Neale Ranns08a70f12017-02-24 06:16:01 -0800701
702 return (fib_entry);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100703}
704
705static void
706fib_entry_post_install_actions (fib_entry_t *fib_entry,
707 fib_source_t source,
708 fib_entry_flag_t old_flags)
709{
Neale Ranns08a70f12017-02-24 06:16:01 -0800710 fib_entry = fib_entry_post_flag_update_actions(fib_entry,
Neale Ranns08a70f12017-02-24 06:16:01 -0800711 old_flags);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100712 fib_entry_src_action_installed(fib_entry, source);
713}
714
715fib_node_index_t
716fib_entry_create (u32 fib_index,
717 const fib_prefix_t *prefix,
718 fib_source_t source,
719 fib_entry_flag_t flags,
720 const fib_route_path_t *paths)
721{
722 fib_node_index_t fib_entry_index;
723 fib_entry_t *fib_entry;
724
725 ASSERT(0 < vec_len(paths));
726
727 fib_entry = fib_entry_alloc(fib_index, prefix, &fib_entry_index);
728
729 /*
730 * since this is a new entry create, we don't need to check for winning
731 * sources - there is only one.
732 */
733 fib_entry = fib_entry_src_action_add(fib_entry, source, flags,
734 drop_dpo_get(
735 fib_proto_to_dpo(
736 fib_entry_get_proto(fib_entry))));
737 fib_entry_src_action_path_swap(fib_entry,
738 source,
739 flags,
740 paths);
741 /*
742 * handle possible realloc's by refetching the pointer
743 */
744 fib_entry = fib_entry_get(fib_entry_index);
745 fib_entry_src_action_activate(fib_entry, source);
746
747 fib_entry_post_install_actions(fib_entry, source, FIB_ENTRY_FLAG_NONE);
748
Neale Ranns710071b2018-09-24 12:36:26 +0000749 FIB_ENTRY_DBG(fib_entry, "create");
750
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100751 return (fib_entry_index);
752}
753
754fib_node_index_t
755fib_entry_create_special (u32 fib_index,
756 const fib_prefix_t *prefix,
757 fib_source_t source,
758 fib_entry_flag_t flags,
759 const dpo_id_t *dpo)
760{
761 fib_node_index_t fib_entry_index;
762 fib_entry_t *fib_entry;
763
764 /*
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700765 * create and initialize the new enty
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100766 */
767 fib_entry = fib_entry_alloc(fib_index, prefix, &fib_entry_index);
768
769 /*
770 * create the path-list
771 */
772 fib_entry = fib_entry_src_action_add(fib_entry, source, flags, dpo);
773 fib_entry_src_action_activate(fib_entry, source);
774
775 fib_entry_post_install_actions(fib_entry, source, FIB_ENTRY_FLAG_NONE);
776
Neale Ranns710071b2018-09-24 12:36:26 +0000777 FIB_ENTRY_DBG(fib_entry, "create-special");
778
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100779 return (fib_entry_index);
780}
781
782static void
783fib_entry_post_update_actions (fib_entry_t *fib_entry,
784 fib_source_t source,
785 fib_entry_flag_t old_flags)
786{
787 /*
788 * backwalk to children to inform then of the change to forwarding.
789 */
790 fib_node_back_walk_ctx_t bw_ctx = {
791 .fnbw_reason = FIB_NODE_BW_REASON_FLAG_EVALUATE,
792 };
793
794 fib_walk_sync(FIB_NODE_TYPE_ENTRY, fib_entry_get_index(fib_entry), &bw_ctx);
795
796 /*
797 * then inform any covered prefixes
798 */
799 fib_entry_cover_update_notify(fib_entry);
800
801 fib_entry_post_install_actions(fib_entry, source, old_flags);
802}
803
Neale Ranns89541992017-04-06 04:41:02 -0700804void
Neale Ranns2303cb12018-02-21 04:57:17 -0800805fib_entry_recalculate_forwarding (fib_node_index_t fib_entry_index)
Neale Ranns948e00f2016-10-20 13:39:34 +0100806{
Neale Ranns2303cb12018-02-21 04:57:17 -0800807 fib_source_t best_source;
808 fib_entry_t *fib_entry;
809 fib_entry_src_t *bsrc;
Neale Ranns89541992017-04-06 04:41:02 -0700810
Neale Ranns2303cb12018-02-21 04:57:17 -0800811 fib_entry = fib_entry_get(fib_entry_index);
Neale Ranns89541992017-04-06 04:41:02 -0700812
Neale Ranns2303cb12018-02-21 04:57:17 -0800813 bsrc = fib_entry_get_best_src_i(fib_entry);
814 best_source = fib_entry_src_get_source(bsrc);
815
816 fib_entry_src_action_reactivate(fib_entry, best_source);
817}
818
819static void
820fib_entry_source_change_w_flags (fib_entry_t *fib_entry,
821 fib_source_t old_source,
822 fib_entry_flag_t old_flags,
823 fib_source_t new_source)
824{
Neale Ranns89541992017-04-06 04:41:02 -0700825 if (new_source < old_source)
Neale Ranns948e00f2016-10-20 13:39:34 +0100826 {
827 /*
828 * we have a new winning source.
829 */
Neale Ranns89541992017-04-06 04:41:02 -0700830 fib_entry_src_action_deactivate(fib_entry, old_source);
Neale Ranns948e00f2016-10-20 13:39:34 +0100831 fib_entry_src_action_activate(fib_entry, new_source);
832 }
Neale Ranns89541992017-04-06 04:41:02 -0700833 else if (new_source > old_source)
Neale Ranns948e00f2016-10-20 13:39:34 +0100834 {
Neale Ranns2303cb12018-02-21 04:57:17 -0800835 /*
836 * the new source loses. Re-activate the winning sources
837 * in case it is an interposer and hence relied on the losing
838 * source's path-list.
839 */
840 fib_entry_src_action_reactivate(fib_entry, old_source);
841 return;
Neale Ranns948e00f2016-10-20 13:39:34 +0100842 }
843 else
844 {
845 /*
846 * the new source is one this entry already has.
847 * But the path-list was updated, which will contribute new forwarding,
848 * so install it.
849 */
Neale Ranns89541992017-04-06 04:41:02 -0700850 fib_entry_src_action_reactivate(fib_entry, new_source);
Neale Ranns948e00f2016-10-20 13:39:34 +0100851 }
852
853 fib_entry_post_update_actions(fib_entry, new_source, old_flags);
854}
855
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100856void
Neale Ranns2303cb12018-02-21 04:57:17 -0800857fib_entry_source_change (fib_entry_t *fib_entry,
858 fib_source_t old_source,
859 fib_source_t new_source)
860{
861 fib_entry_flag_t old_flags;
862
863 old_flags = fib_entry_get_flags_for_source(
864 fib_entry_get_index(fib_entry), old_source);
865
866 return (fib_entry_source_change_w_flags(fib_entry, old_source,
867 old_flags, new_source));
868}
869
870void
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100871fib_entry_special_add (fib_node_index_t fib_entry_index,
872 fib_source_t source,
873 fib_entry_flag_t flags,
874 const dpo_id_t *dpo)
875{
876 fib_source_t best_source;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100877 fib_entry_t *fib_entry;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100878
879 fib_entry = fib_entry_get(fib_entry_index);
Neale Ranns89541992017-04-06 04:41:02 -0700880 best_source = fib_entry_get_best_source(fib_entry_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100881
882 fib_entry = fib_entry_src_action_add(fib_entry, source, flags, dpo);
Neale Ranns89541992017-04-06 04:41:02 -0700883 fib_entry_source_change(fib_entry, best_source, source);
Neale Ranns710071b2018-09-24 12:36:26 +0000884 FIB_ENTRY_DBG(fib_entry, "special-add:%U", format_fib_source, source);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100885}
886
887void
Neale Ranns948e00f2016-10-20 13:39:34 +0100888fib_entry_special_update (fib_node_index_t fib_entry_index,
889 fib_source_t source,
890 fib_entry_flag_t flags,
891 const dpo_id_t *dpo)
892{
893 fib_source_t best_source;
Neale Ranns948e00f2016-10-20 13:39:34 +0100894 fib_entry_t *fib_entry;
Neale Ranns948e00f2016-10-20 13:39:34 +0100895
896 fib_entry = fib_entry_get(fib_entry_index);
Neale Ranns89541992017-04-06 04:41:02 -0700897 best_source = fib_entry_get_best_source(fib_entry_index);
Neale Ranns948e00f2016-10-20 13:39:34 +0100898
899 fib_entry = fib_entry_src_action_update(fib_entry, source, flags, dpo);
Neale Ranns89541992017-04-06 04:41:02 -0700900 fib_entry_source_change(fib_entry, best_source, source);
Neale Ranns710071b2018-09-24 12:36:26 +0000901
902 FIB_ENTRY_DBG(fib_entry, "special-updated:%U", format_fib_source, source);
Neale Ranns948e00f2016-10-20 13:39:34 +0100903}
904
905
906void
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100907fib_entry_path_add (fib_node_index_t fib_entry_index,
908 fib_source_t source,
909 fib_entry_flag_t flags,
Neale Ranns097fa662018-05-01 05:17:55 -0700910 const fib_route_path_t *rpaths)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100911{
912 fib_source_t best_source;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100913 fib_entry_t *fib_entry;
Neale Rannsa4e77662017-12-04 20:00:30 +0000914 fib_entry_src_t *bsrc;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100915
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100916 fib_entry = fib_entry_get(fib_entry_index);
917 ASSERT(NULL != fib_entry);
918
919 bsrc = fib_entry_get_best_src_i(fib_entry);
920 best_source = fib_entry_src_get_source(bsrc);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100921
Neale Ranns097fa662018-05-01 05:17:55 -0700922 fib_entry = fib_entry_src_action_path_add(fib_entry, source, flags, rpaths);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100923
Neale Ranns2303cb12018-02-21 04:57:17 -0800924 fib_entry_source_change(fib_entry, best_source, source);
Neale Ranns710071b2018-09-24 12:36:26 +0000925
926 FIB_ENTRY_DBG(fib_entry, "path add:%U", format_fib_source, source);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100927}
928
Neale Ranns89541992017-04-06 04:41:02 -0700929static fib_entry_src_flag_t
930fib_entry_src_burn_only_inherited (fib_entry_t *fib_entry)
931{
932 fib_entry_src_t *src;
933 fib_source_t source;
934 int has_only_inherited_sources = 1;
935
936 FOR_EACH_SRC_ADDED(fib_entry, src, source,
937 ({
938 if (!(src->fes_flags & FIB_ENTRY_SRC_FLAG_INHERITED))
939 {
940 has_only_inherited_sources = 0;
941 break;
942 }
943 }));
944 if (has_only_inherited_sources)
945 {
946 FOR_EACH_SRC_ADDED(fib_entry, src, source,
947 ({
948 fib_entry_src_action_remove(fib_entry, source);
949 }));
950 return (FIB_ENTRY_SRC_FLAG_NONE);
951 }
952 else
953 {
954 return (FIB_ENTRY_SRC_FLAG_ADDED);
955 }
956}
957
958static fib_entry_src_flag_t
959fib_entry_source_removed (fib_entry_t *fib_entry,
960 fib_entry_flag_t old_flags)
961{
962 const fib_entry_src_t *bsrc;
963 fib_source_t best_source;
964
965 /*
966 * if all that is left are inherited sources, then burn them
967 */
968 fib_entry_src_burn_only_inherited(fib_entry);
969
970 bsrc = fib_entry_get_best_src_i(fib_entry);
971 best_source = fib_entry_src_get_source(bsrc);
972
Neale Ranns2303cb12018-02-21 04:57:17 -0800973 if (FIB_SOURCE_MAX == best_source)
974 {
Neale Ranns89541992017-04-06 04:41:02 -0700975 /*
976 * no more sources left. this entry is toast.
977 */
978 fib_entry = fib_entry_post_flag_update_actions(fib_entry, old_flags);
979 fib_entry_src_action_uninstall(fib_entry);
980
981 return (FIB_ENTRY_SRC_FLAG_NONE);
982 }
983 else
984 {
985 fib_entry_src_action_activate(fib_entry, best_source);
986 }
987
988 fib_entry_post_update_actions(fib_entry, best_source, old_flags);
989
990 /*
991 * still have sources
992 */
993 return (FIB_ENTRY_SRC_FLAG_ADDED);
994}
995
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100996/*
997 * fib_entry_path_remove
998 *
999 * remove a path from the entry.
1000 * return the fib_entry's index if it is still present, INVALID otherwise.
1001 */
1002fib_entry_src_flag_t
1003fib_entry_path_remove (fib_node_index_t fib_entry_index,
1004 fib_source_t source,
Neale Ranns097fa662018-05-01 05:17:55 -07001005 const fib_route_path_t *rpaths)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001006{
1007 fib_entry_src_flag_t sflag;
1008 fib_source_t best_source;
1009 fib_entry_flag_t bflags;
1010 fib_entry_t *fib_entry;
Neale Rannsa4e77662017-12-04 20:00:30 +00001011 fib_entry_src_t *bsrc;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001012
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001013 fib_entry = fib_entry_get(fib_entry_index);
1014 ASSERT(NULL != fib_entry);
1015
1016 bsrc = fib_entry_get_best_src_i(fib_entry);
1017 best_source = fib_entry_src_get_source(bsrc);
1018 bflags = fib_entry_src_get_flags(bsrc);
1019
Neale Ranns097fa662018-05-01 05:17:55 -07001020 sflag = fib_entry_src_action_path_remove(fib_entry, source, rpaths);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001021
Neale Ranns710071b2018-09-24 12:36:26 +00001022 FIB_ENTRY_DBG(fib_entry, "path remove:%U", format_fib_source, source);
1023
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001024 /*
1025 * if the path list for the source passed is invalid,
1026 * then we need to create a new one. else we are updating
1027 * an existing.
1028 */
Neale Ranns89541992017-04-06 04:41:02 -07001029 if (source < best_source)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001030 {
1031 /*
1032 * Que! removing a path from a source that is better than the
1033 * one this entry is using.
1034 */
1035 ASSERT(0);
1036 }
1037 else if (source > best_source )
1038 {
1039 /*
Neale Ranns89541992017-04-06 04:41:02 -07001040 * the source is not the best. no need to update forwarding
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001041 */
Neale Ranns89541992017-04-06 04:41:02 -07001042 if (FIB_ENTRY_SRC_FLAG_ADDED & sflag)
1043 {
1044 /*
1045 * the source being removed still has paths
1046 */
1047 return (FIB_ENTRY_SRC_FLAG_ADDED);
1048 }
1049 else
1050 {
1051 /*
1052 * that was the last path from this source, check if those
1053 * that remain are non-inherited
1054 */
1055 return (fib_entry_src_burn_only_inherited(fib_entry));
1056 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001057 }
1058 else
1059 {
1060 /*
1061 * removing a path from the path-list we were using.
1062 */
1063 if (!(FIB_ENTRY_SRC_FLAG_ADDED & sflag))
1064 {
1065 /*
1066 * the last path from the source was removed.
1067 * fallback to lower source
1068 */
Neale Ranns89541992017-04-06 04:41:02 -07001069 return (fib_entry_source_removed(fib_entry, bflags));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001070 }
1071 else
1072 {
1073 /*
1074 * re-install the new forwarding information
1075 */
Neale Ranns89541992017-04-06 04:41:02 -07001076 fib_entry_src_action_reactivate(fib_entry, source);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001077 }
1078 }
1079
1080 fib_entry_post_update_actions(fib_entry, source, bflags);
1081
1082 /*
1083 * still have sources
1084 */
1085 return (FIB_ENTRY_SRC_FLAG_ADDED);
1086}
1087
1088/*
1089 * fib_entry_special_remove
1090 *
1091 * remove a special source from the entry.
1092 * return the fib_entry's index if it is still present, INVALID otherwise.
1093 */
1094fib_entry_src_flag_t
1095fib_entry_special_remove (fib_node_index_t fib_entry_index,
1096 fib_source_t source)
1097{
1098 fib_entry_src_flag_t sflag;
1099 fib_source_t best_source;
1100 fib_entry_flag_t bflags;
1101 fib_entry_t *fib_entry;
Neale Rannsa4e77662017-12-04 20:00:30 +00001102 fib_entry_src_t *bsrc;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001103
1104 fib_entry = fib_entry_get(fib_entry_index);
1105 ASSERT(NULL != fib_entry);
1106
1107 bsrc = fib_entry_get_best_src_i(fib_entry);
1108 best_source = fib_entry_src_get_source(bsrc);
1109 bflags = fib_entry_src_get_flags(bsrc);
1110
Neale Ranns710071b2018-09-24 12:36:26 +00001111 FIB_ENTRY_DBG(fib_entry, "special remove:%U", format_fib_source, source);
1112
Neale Ranns8164a032019-03-26 07:25:11 -07001113 sflag = fib_entry_src_action_remove_or_update_inherit(fib_entry, source);
1114
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001115 /*
1116 * if the path list for the source passed is invalid,
1117 * then we need to create a new one. else we are updating
1118 * an existing.
1119 */
1120 if (source < best_source )
1121 {
1122 /*
1123 * Que! removing a path from a source that is better than the
1124 * one this entry is using. This can only mean it is a source
1125 * this prefix does not have.
1126 */
1127 return (FIB_ENTRY_SRC_FLAG_ADDED);
1128 }
1129 else if (source > best_source ) {
1130 /*
Neale Ranns89541992017-04-06 04:41:02 -07001131 * the source is not the best. no need to update forwarding
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001132 */
Neale Ranns89541992017-04-06 04:41:02 -07001133 if (FIB_ENTRY_SRC_FLAG_ADDED & sflag)
1134 {
1135 /*
1136 * the source being removed still has paths
1137 */
1138 return (FIB_ENTRY_SRC_FLAG_ADDED);
1139 }
1140 else
1141 {
1142 /*
1143 * that was the last path from this source, check if those
1144 * that remain are non-inherited
1145 */
1146 if (FIB_ENTRY_SRC_FLAG_NONE == fib_entry_src_burn_only_inherited(fib_entry))
1147 {
1148 /*
1149 * no more sources left. this entry is toast.
1150 */
1151 fib_entry = fib_entry_post_flag_update_actions(fib_entry, bflags);
1152 fib_entry_src_action_uninstall(fib_entry);
1153 return (FIB_ENTRY_SRC_FLAG_NONE);
1154 }
Neale Ranns2303cb12018-02-21 04:57:17 -08001155
1156 /*
1157 * reactivate the best source so the interposer gets restacked
1158 */
1159 fib_entry_src_action_reactivate(fib_entry, best_source);
1160
Neale Ranns89541992017-04-06 04:41:02 -07001161 return (FIB_ENTRY_SRC_FLAG_ADDED);
1162 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001163 }
1164 else
1165 {
1166 if (!(FIB_ENTRY_SRC_FLAG_ADDED & sflag))
1167 {
1168 /*
1169 * the source was removed. use the next best.
1170 */
Neale Ranns89541992017-04-06 04:41:02 -07001171 return (fib_entry_source_removed(fib_entry, bflags));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001172 }
1173 else
1174 {
1175 /*
1176 * re-install the new forwarding information
1177 */
1178 fib_entry_src_action_reactivate(fib_entry, source);
1179 }
1180 }
1181
1182 fib_entry_post_update_actions(fib_entry, source, bflags);
1183
1184 /*
1185 * still have sources
1186 */
1187 return (FIB_ENTRY_SRC_FLAG_ADDED);
1188}
1189
1190/**
Neale Ranns89541992017-04-06 04:41:02 -07001191 * fib_entry_inherit
1192 *
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001193 * If the source on the cover is inheriting then push this source
Neale Ranns89541992017-04-06 04:41:02 -07001194 * down to the covered.
1195 */
1196void
1197fib_entry_inherit (fib_node_index_t cover,
1198 fib_node_index_t covered)
1199{
1200 fib_entry_src_inherit(fib_entry_get(cover),
1201 fib_entry_get(covered));
1202}
1203
1204/**
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001205 * fib_entry_delete
1206 *
1207 * The source is withdrawing all the paths it provided
1208 */
1209fib_entry_src_flag_t
1210fib_entry_delete (fib_node_index_t fib_entry_index,
1211 fib_source_t source)
1212{
1213 return (fib_entry_special_remove(fib_entry_index, source));
1214}
1215
1216/**
1217 * fib_entry_update
1218 *
1219 * The source has provided a new set of paths that will replace the old.
1220 */
1221void
1222fib_entry_update (fib_node_index_t fib_entry_index,
1223 fib_source_t source,
1224 fib_entry_flag_t flags,
1225 const fib_route_path_t *paths)
1226{
1227 fib_source_t best_source;
1228 fib_entry_flag_t bflags;
1229 fib_entry_t *fib_entry;
Neale Rannsa4e77662017-12-04 20:00:30 +00001230 fib_entry_src_t *bsrc;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001231
1232 fib_entry = fib_entry_get(fib_entry_index);
1233 ASSERT(NULL != fib_entry);
1234
1235 bsrc = fib_entry_get_best_src_i(fib_entry);
1236 best_source = fib_entry_src_get_source(bsrc);
Neale Ranns2303cb12018-02-21 04:57:17 -08001237 bflags = fib_entry_get_flags_i(fib_entry);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001238
Neale Ranns2303cb12018-02-21 04:57:17 -08001239 fib_entry = fib_entry_src_action_path_swap(fib_entry,
1240 source,
1241 flags,
1242 paths);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001243
Neale Ranns2303cb12018-02-21 04:57:17 -08001244 fib_entry_source_change_w_flags(fib_entry, best_source, bflags, source);
Neale Ranns710071b2018-09-24 12:36:26 +00001245 FIB_ENTRY_DBG(fib_entry, "update");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001246}
1247
1248
1249/*
1250 * fib_entry_cover_changed
1251 *
1252 * this entry is tracking its cover and that cover has changed.
1253 */
1254void
1255fib_entry_cover_changed (fib_node_index_t fib_entry_index)
1256{
1257 fib_entry_src_cover_res_t res = {
1258 .install = !0,
1259 .bw_reason = FIB_NODE_BW_REASON_FLAG_NONE,
1260 };
Neale Ranns2303cb12018-02-21 04:57:17 -08001261 CLIB_UNUSED(fib_source_t source);
1262 fib_source_t best_source;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001263 fib_entry_flag_t bflags;
1264 fib_entry_t *fib_entry;
1265 fib_entry_src_t *esrc;
1266 u32 index;
1267
1268 bflags = FIB_ENTRY_FLAG_NONE;
1269 best_source = FIB_SOURCE_FIRST;
1270 fib_entry = fib_entry_get(fib_entry_index);
1271
1272 fib_attached_export_cover_change(fib_entry);
1273
1274 /*
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001275 * propagate the notification to each of the added sources
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001276 */
1277 index = 0;
1278 FOR_EACH_SRC_ADDED(fib_entry, esrc, source,
1279 ({
1280 if (0 == index)
1281 {
1282 /*
1283 * only the best source gets to set the back walk flags
1284 */
Neale Ranns2303cb12018-02-21 04:57:17 -08001285 res = fib_entry_src_action_cover_change(fib_entry, esrc);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001286 bflags = fib_entry_src_get_flags(esrc);
1287 best_source = fib_entry_src_get_source(esrc);
1288 }
1289 else
1290 {
Neale Ranns2303cb12018-02-21 04:57:17 -08001291 fib_entry_src_action_cover_change(fib_entry, esrc);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001292 }
1293 index++;
1294 }));
1295
1296 if (res.install)
1297 {
1298 fib_entry_src_action_reactivate(fib_entry,
1299 fib_entry_src_get_source(
1300 fib_entry_get_best_src_i(fib_entry)));
1301 fib_entry_post_install_actions(fib_entry, best_source, bflags);
1302 }
1303 else
1304 {
1305 fib_entry_src_action_uninstall(fib_entry);
1306 }
1307
1308 if (FIB_NODE_BW_REASON_FLAG_NONE != res.bw_reason)
1309 {
1310 /*
1311 * time for walkies fido.
1312 */
1313 fib_node_back_walk_ctx_t bw_ctx = {
1314 .fnbw_reason = res.bw_reason,
1315 };
1316
1317 fib_walk_sync(FIB_NODE_TYPE_ENTRY, fib_entry_index, &bw_ctx);
1318 }
Neale Ranns710071b2018-09-24 12:36:26 +00001319 FIB_ENTRY_DBG(fib_entry, "cover-changed");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001320}
1321
1322/*
1323 * fib_entry_cover_updated
1324 *
1325 * this entry is tracking its cover and that cover has been updated
1326 * (i.e. its forwarding information has changed).
1327 */
1328void
1329fib_entry_cover_updated (fib_node_index_t fib_entry_index)
1330{
1331 fib_entry_src_cover_res_t res = {
1332 .install = !0,
1333 .bw_reason = FIB_NODE_BW_REASON_FLAG_NONE,
1334 };
Neale Ranns2303cb12018-02-21 04:57:17 -08001335 CLIB_UNUSED(fib_source_t source);
1336 fib_source_t best_source;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001337 fib_entry_flag_t bflags;
1338 fib_entry_t *fib_entry;
1339 fib_entry_src_t *esrc;
1340 u32 index;
1341
1342 bflags = FIB_ENTRY_FLAG_NONE;
1343 best_source = FIB_SOURCE_FIRST;
1344 fib_entry = fib_entry_get(fib_entry_index);
1345
1346 fib_attached_export_cover_update(fib_entry);
1347
1348 /*
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001349 * propagate the notification to each of the added sources
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001350 */
1351 index = 0;
1352 FOR_EACH_SRC_ADDED(fib_entry, esrc, source,
1353 ({
1354 if (0 == index)
1355 {
1356 /*
1357 * only the best source gets to set the back walk flags
1358 */
Neale Ranns2303cb12018-02-21 04:57:17 -08001359 res = fib_entry_src_action_cover_update(fib_entry, esrc);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001360 bflags = fib_entry_src_get_flags(esrc);
1361 best_source = fib_entry_src_get_source(esrc);
1362 }
1363 else
1364 {
Neale Ranns2303cb12018-02-21 04:57:17 -08001365 fib_entry_src_action_cover_update(fib_entry, esrc);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001366 }
1367 index++;
1368 }));
1369
1370 if (res.install)
1371 {
1372 fib_entry_src_action_reactivate(fib_entry,
1373 fib_entry_src_get_source(
1374 fib_entry_get_best_src_i(fib_entry)));
1375 fib_entry_post_install_actions(fib_entry, best_source, bflags);
1376 }
1377 else
1378 {
1379 fib_entry_src_action_uninstall(fib_entry);
1380 }
1381
1382 if (FIB_NODE_BW_REASON_FLAG_NONE != res.bw_reason)
1383 {
1384 /*
1385 * time for walkies fido.
1386 */
1387 fib_node_back_walk_ctx_t bw_ctx = {
1388 .fnbw_reason = res.bw_reason,
1389 };
1390
1391 fib_walk_sync(FIB_NODE_TYPE_ENTRY, fib_entry_index, &bw_ctx);
1392 }
Neale Ranns710071b2018-09-24 12:36:26 +00001393 FIB_ENTRY_DBG(fib_entry, "cover-updated");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001394}
1395
1396int
1397fib_entry_recursive_loop_detect (fib_node_index_t entry_index,
1398 fib_node_index_t **entry_indicies)
1399{
1400 fib_entry_t *fib_entry;
1401 int was_looped, is_looped;
1402
1403 fib_entry = fib_entry_get(entry_index);
1404
1405 if (FIB_NODE_INDEX_INVALID != fib_entry->fe_parent)
1406 {
1407 fib_node_index_t *entries = *entry_indicies;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001408
1409 vec_add1(entries, entry_index);
1410 was_looped = fib_path_list_is_looped(fib_entry->fe_parent);
1411 is_looped = fib_path_list_recursive_loop_detect(fib_entry->fe_parent,
1412 &entries);
1413
1414 *entry_indicies = entries;
1415
1416 if (!!was_looped != !!is_looped)
1417 {
1418 /*
1419 * re-evaluate all the entry's forwarding
1420 * NOTE: this is an inplace modify
1421 */
Neale Rannsad422ed2016-11-02 14:20:04 +00001422 fib_entry_delegate_type_t fdt;
1423 fib_entry_delegate_t *fed;
1424
1425 FOR_EACH_DELEGATE_CHAIN(fib_entry, fdt, fed,
1426 {
1427 fib_entry_src_mk_lb(fib_entry,
1428 fib_entry_get_best_src_i(fib_entry),
1429 fib_entry_delegate_type_to_chain_type(fdt),
1430 &fed->fd_dpo);
1431 });
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001432 }
1433 }
1434 else
1435 {
1436 /*
1437 * the entry is currently not linked to a path-list. this happens
1438 * when it is this entry that is re-linking path-lists and has thus
1439 * broken the loop
1440 */
1441 is_looped = 0;
1442 }
1443
1444 return (is_looped);
1445}
1446
1447u32
1448fib_entry_get_resolving_interface (fib_node_index_t entry_index)
1449{
Neale Rannsdf089a82016-10-02 16:39:06 +01001450 fib_entry_t *fib_entry;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001451
1452 fib_entry = fib_entry_get(entry_index);
1453
1454 return (fib_path_list_get_resolving_interface(fib_entry->fe_parent));
1455}
1456
1457fib_source_t
1458fib_entry_get_best_source (fib_node_index_t entry_index)
1459{
1460 fib_entry_t *fib_entry;
Neale Rannsa4e77662017-12-04 20:00:30 +00001461 fib_entry_src_t *bsrc;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001462
1463 fib_entry = fib_entry_get(entry_index);
1464
1465 bsrc = fib_entry_get_best_src_i(fib_entry);
1466 return (fib_entry_src_get_source(bsrc));
1467}
1468
Neale Ranns88fc83e2017-04-05 08:11:14 -07001469/**
Neale Ranns56f949b2018-04-25 01:41:24 -07001470 * Return !0 is the entry represents a host prefix
1471 */
1472int
1473fib_entry_is_host (fib_node_index_t fib_entry_index)
1474{
Neale Rannsc5d43172018-07-30 08:04:40 -07001475 return (fib_prefix_is_host(fib_entry_get_prefix(fib_entry_index)));
Neale Ranns56f949b2018-04-25 01:41:24 -07001476}
1477
1478/**
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001479 * Return !0 is the entry is resolved, i.e. will return a valid forwarding
Neale Ranns88fc83e2017-04-05 08:11:14 -07001480 * chain
1481 */
1482int
1483fib_entry_is_resolved (fib_node_index_t fib_entry_index)
1484{
1485 fib_entry_delegate_t *fed;
1486 fib_entry_t *fib_entry;
1487
1488 fib_entry = fib_entry_get(fib_entry_index);
1489
Neale Ranns1f50bf82019-07-16 15:28:52 +00001490 fed = fib_entry_delegate_find(fib_entry, FIB_ENTRY_DELEGATE_BFD);
Neale Ranns88fc83e2017-04-05 08:11:14 -07001491
1492 if (NULL == fed)
1493 {
1494 /*
Neale Ranns57b58602017-07-15 07:37:25 -07001495 * no BFD tracking - consider it resolved.
Neale Ranns88fc83e2017-04-05 08:11:14 -07001496 */
1497 return (!0);
1498 }
1499 else
1500 {
1501 /*
1502 * defer to the state of the BFD tracking
1503 */
1504 return (FIB_BFD_STATE_UP == fed->fd_bfd_state);
1505 }
1506}
1507
Neale Ranns227038a2017-04-21 01:07:59 -07001508void
1509fib_entry_set_flow_hash_config (fib_node_index_t fib_entry_index,
1510 flow_hash_config_t hash_config)
1511{
1512 fib_entry_t *fib_entry;
1513
1514 fib_entry = fib_entry_get(fib_entry_index);
1515
1516 /*
1517 * pass the hash-config on to the load-balance object where it is cached.
1518 * we can ignore LBs in the delegate chains, since they will not be of the
1519 * correct protocol type (i.e. they are not IP)
1520 * There's no way, nor need, to change the hash config for MPLS.
1521 */
1522 if (dpo_id_is_valid(&fib_entry->fe_lb))
1523 {
1524 load_balance_t *lb;
1525
1526 ASSERT(DPO_LOAD_BALANCE == fib_entry->fe_lb.dpoi_type);
1527
1528 lb = load_balance_get(fib_entry->fe_lb.dpoi_index);
1529
1530 /*
1531 * atomic update for packets in flight
1532 */
1533 lb->lb_hash_config = hash_config;
1534 }
1535}
1536
Neale Ranns008dbe12018-09-07 09:32:36 -07001537u32
1538fib_entry_get_stats_index (fib_node_index_t fib_entry_index)
1539{
1540 fib_entry_t *fib_entry;
1541
1542 fib_entry = fib_entry_get(fib_entry_index);
1543
1544 return (fib_entry->fe_lb.dpoi_index);
1545}
1546
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001547static int
Neale Rannsad422ed2016-11-02 14:20:04 +00001548fib_ip4_address_compare (const ip4_address_t * a1,
1549 const ip4_address_t * a2)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001550{
1551 /*
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001552 * IP addresses are unsigned ints. the return value here needs to be signed
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001553 * a simple subtraction won't cut it.
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001554 * If the addresses are the same, the sort order is undefined, so phoey.
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001555 */
1556 return ((clib_net_to_host_u32(a1->data_u32) >
1557 clib_net_to_host_u32(a2->data_u32) ) ?
1558 1 : -1);
1559}
1560
1561static int
Neale Rannsad422ed2016-11-02 14:20:04 +00001562fib_ip6_address_compare (const ip6_address_t * a1,
1563 const ip6_address_t * a2)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001564{
1565 int i;
1566 for (i = 0; i < ARRAY_LEN (a1->as_u16); i++)
1567 {
1568 int cmp = (clib_net_to_host_u16 (a1->as_u16[i]) -
1569 clib_net_to_host_u16 (a2->as_u16[i]));
1570 if (cmp != 0)
1571 return cmp;
1572 }
1573 return 0;
1574}
1575
1576static int
1577fib_entry_cmp (fib_node_index_t fib_entry_index1,
1578 fib_node_index_t fib_entry_index2)
1579{
1580 fib_entry_t *fib_entry1, *fib_entry2;
1581 int cmp = 0;
1582
1583 fib_entry1 = fib_entry_get(fib_entry_index1);
1584 fib_entry2 = fib_entry_get(fib_entry_index2);
1585
1586 switch (fib_entry1->fe_prefix.fp_proto)
1587 {
1588 case FIB_PROTOCOL_IP4:
1589 cmp = fib_ip4_address_compare(&fib_entry1->fe_prefix.fp_addr.ip4,
1590 &fib_entry2->fe_prefix.fp_addr.ip4);
1591 break;
1592 case FIB_PROTOCOL_IP6:
1593 cmp = fib_ip6_address_compare(&fib_entry1->fe_prefix.fp_addr.ip6,
1594 &fib_entry2->fe_prefix.fp_addr.ip6);
1595 break;
1596 case FIB_PROTOCOL_MPLS:
1597 cmp = (fib_entry1->fe_prefix.fp_label - fib_entry2->fe_prefix.fp_label);
1598
1599 if (0 == cmp)
1600 {
1601 cmp = (fib_entry1->fe_prefix.fp_eos - fib_entry2->fe_prefix.fp_eos);
1602 }
1603 break;
1604 }
1605
1606 if (0 == cmp) {
1607 cmp = (fib_entry1->fe_prefix.fp_len - fib_entry2->fe_prefix.fp_len);
1608 }
1609 return (cmp);
1610}
1611
1612int
1613fib_entry_cmp_for_sort (void *i1, void *i2)
1614{
1615 fib_node_index_t *fib_entry_index1 = i1, *fib_entry_index2 = i2;
1616
1617 return (fib_entry_cmp(*fib_entry_index1,
1618 *fib_entry_index2));
1619}
1620
1621void
1622fib_entry_lock (fib_node_index_t fib_entry_index)
1623{
1624 fib_entry_t *fib_entry;
1625
1626 fib_entry = fib_entry_get(fib_entry_index);
1627
1628 fib_node_lock(&fib_entry->fe_node);
1629}
1630
1631void
1632fib_entry_unlock (fib_node_index_t fib_entry_index)
1633{
1634 fib_entry_t *fib_entry;
1635
1636 fib_entry = fib_entry_get(fib_entry_index);
1637
1638 fib_node_unlock(&fib_entry->fe_node);
1639}
1640
1641void
1642fib_entry_module_init (void)
1643{
Neale Ranns710071b2018-09-24 12:36:26 +00001644 fib_node_register_type(FIB_NODE_TYPE_ENTRY, &fib_entry_vft);
1645 fib_entry_logger = vlib_log_register_class("fib", "entry");
Neale Ranns1f50bf82019-07-16 15:28:52 +00001646
1647 fib_entry_track_module_init();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001648}
1649
Neale Ranns097fa662018-05-01 05:17:55 -07001650fib_route_path_t *
1651fib_entry_encode (fib_node_index_t fib_entry_index)
Steven01b07122016-11-02 10:40:09 -07001652{
Neale Ranns775f73c2018-12-20 03:01:49 -08001653 fib_path_ext_list_t *ext_list;
Neale Ranns097fa662018-05-01 05:17:55 -07001654 fib_path_encode_ctx_t ctx = {
1655 .rpaths = NULL,
1656 };
Steven01b07122016-11-02 10:40:09 -07001657 fib_entry_t *fib_entry;
Neale Ranns775f73c2018-12-20 03:01:49 -08001658 fib_entry_src_t *bsrc;
Steven01b07122016-11-02 10:40:09 -07001659
Neale Ranns775f73c2018-12-20 03:01:49 -08001660 ext_list = NULL;
Steven01b07122016-11-02 10:40:09 -07001661 fib_entry = fib_entry_get(fib_entry_index);
Neale Ranns775f73c2018-12-20 03:01:49 -08001662 bsrc = fib_entry_get_best_src_i(fib_entry);
1663
1664 if (bsrc)
1665 {
1666 ext_list = &bsrc->fes_path_exts;
1667 }
1668
Neale Rannsa8d9f302017-02-20 09:17:02 -08001669 if (FIB_NODE_INDEX_INVALID != fib_entry->fe_parent)
1670 {
Neale Ranns775f73c2018-12-20 03:01:49 -08001671 fib_path_list_walk_w_ext(fib_entry->fe_parent,
1672 ext_list,
1673 fib_path_encode,
Neale Ranns097fa662018-05-01 05:17:55 -07001674 &ctx);
Neale Rannsa8d9f302017-02-20 09:17:02 -08001675 }
Neale Ranns097fa662018-05-01 05:17:55 -07001676
1677 return (ctx.rpaths);
Steven01b07122016-11-02 10:40:09 -07001678}
1679
Neale Rannsc5d43172018-07-30 08:04:40 -07001680const fib_prefix_t *
1681fib_entry_get_prefix (fib_node_index_t fib_entry_index)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001682{
1683 fib_entry_t *fib_entry;
1684
1685 fib_entry = fib_entry_get(fib_entry_index);
Neale Rannsc5d43172018-07-30 08:04:40 -07001686
1687 return (&fib_entry->fe_prefix);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001688}
1689
1690u32
1691fib_entry_get_fib_index (fib_node_index_t fib_entry_index)
1692{
1693 fib_entry_t *fib_entry;
1694
1695 fib_entry = fib_entry_get(fib_entry_index);
1696
1697 return (fib_entry->fe_fib_index);
1698}
1699
1700u32
1701fib_entry_pool_size (void)
1702{
1703 return (pool_elts(fib_entry_pool));
1704}
1705
1706static clib_error_t *
1707show_fib_entry_command (vlib_main_t * vm,
1708 unformat_input_t * input,
1709 vlib_cli_command_t * cmd)
1710{
1711 fib_node_index_t fei;
1712
1713 if (unformat (input, "%d", &fei))
1714 {
1715 /*
1716 * show one in detail
1717 */
1718 if (!pool_is_free_index(fib_entry_pool, fei))
1719 {
1720 vlib_cli_output (vm, "%d@%U",
1721 fei,
1722 format_fib_entry, fei,
1723 FIB_ENTRY_FORMAT_DETAIL2);
1724 }
1725 else
1726 {
1727 vlib_cli_output (vm, "entry %d invalid", fei);
1728 }
1729 }
1730 else
1731 {
1732 /*
1733 * show all
1734 */
1735 vlib_cli_output (vm, "FIB Entries:");
1736 pool_foreach_index(fei, fib_entry_pool,
1737 ({
1738 vlib_cli_output (vm, "%d@%U",
1739 fei,
1740 format_fib_entry, fei,
1741 FIB_ENTRY_FORMAT_BRIEF);
1742 }));
1743 }
1744
1745 return (NULL);
1746}
1747
1748VLIB_CLI_COMMAND (show_fib_entry, static) = {
1749 .path = "show fib entry",
1750 .function = show_fib_entry_command,
1751 .short_help = "show fib entry",
1752};