blob: baf8275d1816fe42c0ca70a324b9b1e3688441ef [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/vnet.h>
18#include <vnet/ip/format.h>
19#include <vnet/ip/ip.h>
20#include <vnet/dpo/drop_dpo.h>
21#include <vnet/dpo/receive_dpo.h>
22#include <vnet/dpo/load_balance_map.h>
23#include <vnet/dpo/lookup_dpo.h>
Neale Ranns43161a82017-08-12 02:12:00 -070024#include <vnet/dpo/interface_rx_dpo.h>
Neale Ranns0f26c5a2017-03-01 15:12:11 -080025#include <vnet/dpo/mpls_disposition.h>
Neale Rannsf068c3e2018-01-03 04:18:48 -080026#include <vnet/dpo/dvr_dpo.h>
Neale Rannsd792d9c2017-10-21 10:53:20 -070027#include <vnet/dpo/drop_dpo.h>
Neale Ranns0bfe5d82016-08-25 15:29:12 +010028
29#include <vnet/adj/adj.h>
Neale Ranns32e1c012016-11-22 17:07:28 +000030#include <vnet/adj/adj_mcast.h>
Neale Ranns0bfe5d82016-08-25 15:29:12 +010031
Neale Ranns3ee44042016-10-03 13:05:48 +010032#include <vnet/fib/fib_path.h>
33#include <vnet/fib/fib_node.h>
34#include <vnet/fib/fib_table.h>
35#include <vnet/fib/fib_entry.h>
36#include <vnet/fib/fib_path_list.h>
37#include <vnet/fib/fib_internal.h>
38#include <vnet/fib/fib_urpf_list.h>
Neale Rannsa3af3372017-03-28 03:49:52 -070039#include <vnet/fib/mpls_fib.h>
Neale Ranns810086d2017-11-05 16:26:46 -080040#include <vnet/udp/udp_encap.h>
Neale Rannsd792d9c2017-10-21 10:53:20 -070041#include <vnet/bier/bier_fmask.h>
42#include <vnet/bier/bier_table.h>
43#include <vnet/bier/bier_imp.h>
Neale Ranns91286372017-12-05 13:24:04 -080044#include <vnet/bier/bier_disp_table.h>
Neale Ranns0bfe5d82016-08-25 15:29:12 +010045
46/**
47 * Enurmeration of path types
48 */
49typedef enum fib_path_type_t_ {
50 /**
51 * Marker. Add new types after this one.
52 */
53 FIB_PATH_TYPE_FIRST = 0,
54 /**
55 * Attached-nexthop. An interface and a nexthop are known.
56 */
57 FIB_PATH_TYPE_ATTACHED_NEXT_HOP = FIB_PATH_TYPE_FIRST,
58 /**
59 * attached. Only the interface is known.
60 */
61 FIB_PATH_TYPE_ATTACHED,
62 /**
63 * recursive. Only the next-hop is known.
64 */
65 FIB_PATH_TYPE_RECURSIVE,
66 /**
67 * special. nothing is known. so we drop.
68 */
69 FIB_PATH_TYPE_SPECIAL,
70 /**
71 * exclusive. user provided adj.
72 */
73 FIB_PATH_TYPE_EXCLUSIVE,
74 /**
75 * deag. Link to a lookup adj in the next table
76 */
77 FIB_PATH_TYPE_DEAG,
78 /**
Neale Ranns0f26c5a2017-03-01 15:12:11 -080079 * interface receive.
80 */
81 FIB_PATH_TYPE_INTF_RX,
82 /**
Neale Ranns81458422018-03-12 06:59:36 -070083 * Path resolves via a UDP encap object.
Neale Ranns810086d2017-11-05 16:26:46 -080084 */
85 FIB_PATH_TYPE_UDP_ENCAP,
86 /**
Neale Ranns0bfe5d82016-08-25 15:29:12 +010087 * receive. it's for-us.
88 */
89 FIB_PATH_TYPE_RECEIVE,
90 /**
Neale Rannsd792d9c2017-10-21 10:53:20 -070091 * bier-imp. it's via a BIER imposition.
92 */
93 FIB_PATH_TYPE_BIER_IMP,
94 /**
95 * bier-fmask. it's via a BIER ECMP-table.
96 */
97 FIB_PATH_TYPE_BIER_TABLE,
98 /**
99 * bier-fmask. it's via a BIER f-mask.
100 */
101 FIB_PATH_TYPE_BIER_FMASK,
102 /**
Neale Rannsf068c3e2018-01-03 04:18:48 -0800103 * via a DVR.
104 */
105 FIB_PATH_TYPE_DVR,
106 /**
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100107 * Marker. Add new types before this one, then update it.
108 */
Neale Rannsd792d9c2017-10-21 10:53:20 -0700109 FIB_PATH_TYPE_LAST = FIB_PATH_TYPE_BIER_FMASK,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100110} __attribute__ ((packed)) fib_path_type_t;
111
112/**
113 * The maximum number of path_types
114 */
115#define FIB_PATH_TYPE_MAX (FIB_PATH_TYPE_LAST + 1)
116
117#define FIB_PATH_TYPES { \
118 [FIB_PATH_TYPE_ATTACHED_NEXT_HOP] = "attached-nexthop", \
119 [FIB_PATH_TYPE_ATTACHED] = "attached", \
120 [FIB_PATH_TYPE_RECURSIVE] = "recursive", \
121 [FIB_PATH_TYPE_SPECIAL] = "special", \
122 [FIB_PATH_TYPE_EXCLUSIVE] = "exclusive", \
123 [FIB_PATH_TYPE_DEAG] = "deag", \
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800124 [FIB_PATH_TYPE_INTF_RX] = "intf-rx", \
Neale Ranns810086d2017-11-05 16:26:46 -0800125 [FIB_PATH_TYPE_UDP_ENCAP] = "udp-encap", \
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100126 [FIB_PATH_TYPE_RECEIVE] = "receive", \
Neale Rannsd792d9c2017-10-21 10:53:20 -0700127 [FIB_PATH_TYPE_BIER_IMP] = "bier-imp", \
128 [FIB_PATH_TYPE_BIER_TABLE] = "bier-table", \
129 [FIB_PATH_TYPE_BIER_FMASK] = "bier-fmask", \
Neale Rannsf068c3e2018-01-03 04:18:48 -0800130 [FIB_PATH_TYPE_DVR] = "dvr", \
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100131}
132
Neale Rannsd792d9c2017-10-21 10:53:20 -0700133#define FOR_EACH_FIB_PATH_TYPE(_item) \
134 for (_item = FIB_PATH_TYPE_FIRST; \
135 _item <= FIB_PATH_TYPE_LAST; \
136 _item++)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100137
138/**
139 * Enurmeration of path operational (i.e. derived) attributes
140 */
141typedef enum fib_path_oper_attribute_t_ {
142 /**
143 * Marker. Add new types after this one.
144 */
145 FIB_PATH_OPER_ATTRIBUTE_FIRST = 0,
146 /**
147 * The path forms part of a recursive loop.
148 */
149 FIB_PATH_OPER_ATTRIBUTE_RECURSIVE_LOOP = FIB_PATH_OPER_ATTRIBUTE_FIRST,
150 /**
151 * The path is resolved
152 */
153 FIB_PATH_OPER_ATTRIBUTE_RESOLVED,
154 /**
Neale Ranns4b919a52017-03-11 05:55:21 -0800155 * The path is attached, despite what the next-hop may say.
156 */
157 FIB_PATH_OPER_ATTRIBUTE_ATTACHED,
158 /**
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100159 * The path has become a permanent drop.
160 */
161 FIB_PATH_OPER_ATTRIBUTE_DROP,
162 /**
163 * Marker. Add new types before this one, then update it.
164 */
165 FIB_PATH_OPER_ATTRIBUTE_LAST = FIB_PATH_OPER_ATTRIBUTE_DROP,
166} __attribute__ ((packed)) fib_path_oper_attribute_t;
167
168/**
169 * The maximum number of path operational attributes
170 */
171#define FIB_PATH_OPER_ATTRIBUTE_MAX (FIB_PATH_OPER_ATTRIBUTE_LAST + 1)
172
173#define FIB_PATH_OPER_ATTRIBUTES { \
174 [FIB_PATH_OPER_ATTRIBUTE_RECURSIVE_LOOP] = "recursive-loop", \
175 [FIB_PATH_OPER_ATTRIBUTE_RESOLVED] = "resolved", \
176 [FIB_PATH_OPER_ATTRIBUTE_DROP] = "drop", \
177}
178
179#define FOR_EACH_FIB_PATH_OPER_ATTRIBUTE(_item) \
180 for (_item = FIB_PATH_OPER_ATTRIBUTE_FIRST; \
181 _item <= FIB_PATH_OPER_ATTRIBUTE_LAST; \
182 _item++)
183
184/**
185 * Path flags from the attributes
186 */
187typedef enum fib_path_oper_flags_t_ {
188 FIB_PATH_OPER_FLAG_NONE = 0,
189 FIB_PATH_OPER_FLAG_RECURSIVE_LOOP = (1 << FIB_PATH_OPER_ATTRIBUTE_RECURSIVE_LOOP),
190 FIB_PATH_OPER_FLAG_DROP = (1 << FIB_PATH_OPER_ATTRIBUTE_DROP),
191 FIB_PATH_OPER_FLAG_RESOLVED = (1 << FIB_PATH_OPER_ATTRIBUTE_RESOLVED),
Neale Ranns4b919a52017-03-11 05:55:21 -0800192 FIB_PATH_OPER_FLAG_ATTACHED = (1 << FIB_PATH_OPER_ATTRIBUTE_ATTACHED),
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100193} __attribute__ ((packed)) fib_path_oper_flags_t;
194
195/**
196 * A FIB path
197 */
198typedef struct fib_path_t_ {
199 /**
200 * A path is a node in the FIB graph.
201 */
202 fib_node_t fp_node;
203
204 /**
205 * The index of the path-list to which this path belongs
206 */
207 u32 fp_pl_index;
208
209 /**
210 * This marks the start of the memory area used to hash
211 * the path
212 */
213 STRUCT_MARK(path_hash_start);
214
215 /**
216 * Configuration Flags
217 */
218 fib_path_cfg_flags_t fp_cfg_flags;
219
220 /**
221 * The type of the path. This is the selector for the union
222 */
223 fib_path_type_t fp_type;
224
225 /**
226 * The protocol of the next-hop, i.e. the address family of the
227 * next-hop's address. We can't derive this from the address itself
228 * since the address can be all zeros
229 */
Neale Rannsda78f952017-05-24 09:15:43 -0700230 dpo_proto_t fp_nh_proto;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100231
232 /**
Neale Ranns57b58602017-07-15 07:37:25 -0700233 * UCMP [unnormalised] weigth
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100234 */
Neale Rannsa0a908f2017-08-01 11:40:03 -0700235 u8 fp_weight;
236
Neale Ranns57b58602017-07-15 07:37:25 -0700237 /**
238 * A path preference. 0 is the best.
239 * Only paths of the best preference, that are 'up', are considered
240 * for forwarding.
241 */
Neale Rannsa0a908f2017-08-01 11:40:03 -0700242 u8 fp_preference;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100243
244 /**
245 * per-type union of the data required to resolve the path
246 */
247 union {
248 struct {
249 /**
250 * The next-hop
251 */
252 ip46_address_t fp_nh;
253 /**
254 * The interface
255 */
256 u32 fp_interface;
257 } attached_next_hop;
258 struct {
259 /**
260 * The interface
261 */
262 u32 fp_interface;
263 } attached;
264 struct {
Neale Rannsad422ed2016-11-02 14:20:04 +0000265 union
266 {
267 /**
268 * The next-hop
269 */
270 ip46_address_t fp_ip;
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800271 struct {
272 /**
273 * The local label to resolve through.
274 */
275 mpls_label_t fp_local_label;
276 /**
277 * The EOS bit of the resolving label
278 */
279 mpls_eos_bit_t fp_eos;
280 };
Neale Rannsad422ed2016-11-02 14:20:04 +0000281 } fp_nh;
Neale Rannsd792d9c2017-10-21 10:53:20 -0700282 union {
283 /**
284 * The FIB table index in which to find the next-hop.
285 */
286 fib_node_index_t fp_tbl_id;
287 /**
288 * The BIER FIB the fmask is in
289 */
290 index_t fp_bier_fib;
291 };
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100292 } recursive;
293 struct {
Neale Rannsd792d9c2017-10-21 10:53:20 -0700294 /**
Neale Ranns91286372017-12-05 13:24:04 -0800295 * BIER FMask ID
Neale Rannsd792d9c2017-10-21 10:53:20 -0700296 */
Neale Ranns91286372017-12-05 13:24:04 -0800297 index_t fp_bier_fmask;
Neale Rannsd792d9c2017-10-21 10:53:20 -0700298 } bier_fmask;
299 struct {
300 /**
301 * The BIER table's ID
302 */
303 bier_table_id_t fp_bier_tbl;
304 } bier_table;
305 struct {
306 /**
307 * The BIER imposition object
308 * this is part of the path's key, since the index_t
309 * of an imposition object is the object's key.
310 */
311 index_t fp_bier_imp;
312 } bier_imp;
313 struct {
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100314 /**
Neale Rannsad422ed2016-11-02 14:20:04 +0000315 * The FIB index in which to perfom the next lookup
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100316 */
317 fib_node_index_t fp_tbl_id;
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800318 /**
319 * The RPF-ID to tag the packets with
320 */
321 fib_rpf_id_t fp_rpf_id;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100322 } deag;
323 struct {
324 } special;
325 struct {
326 /**
327 * The user provided 'exclusive' DPO
328 */
329 dpo_id_t fp_ex_dpo;
330 } exclusive;
331 struct {
332 /**
333 * The interface on which the local address is configured
334 */
335 u32 fp_interface;
336 /**
337 * The next-hop
338 */
339 ip46_address_t fp_addr;
340 } receive;
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800341 struct {
342 /**
343 * The interface on which the packets will be input.
344 */
345 u32 fp_interface;
346 } intf_rx;
Neale Ranns810086d2017-11-05 16:26:46 -0800347 struct {
348 /**
349 * The UDP Encap object this path resolves through
350 */
351 u32 fp_udp_encap_id;
352 } udp_encap;
Neale Rannsf068c3e2018-01-03 04:18:48 -0800353 struct {
354 /**
355 * The interface
356 */
357 u32 fp_interface;
358 } dvr;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100359 };
360 STRUCT_MARK(path_hash_end);
361
362 /**
363 * Memebers in this last section represent information that is
364 * dervied during resolution. It should not be copied to new paths
365 * nor compared.
366 */
367
368 /**
369 * Operational Flags
370 */
371 fib_path_oper_flags_t fp_oper_flags;
372
Neale Rannsd792d9c2017-10-21 10:53:20 -0700373 union {
374 /**
375 * the resolving via fib. not part of the union, since it it not part
376 * of the path's hash.
377 */
378 fib_node_index_t fp_via_fib;
379 /**
Neale Rannsd792d9c2017-10-21 10:53:20 -0700380 * the resolving bier-table
381 */
382 index_t fp_via_bier_tbl;
Neale Ranns91286372017-12-05 13:24:04 -0800383 /**
384 * the resolving bier-fmask
385 */
386 index_t fp_via_bier_fmask;
Neale Rannsd792d9c2017-10-21 10:53:20 -0700387 };
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100388
389 /**
390 * The Data-path objects through which this path resolves for IP.
391 */
392 dpo_id_t fp_dpo;
393
394 /**
395 * the index of this path in the parent's child list.
396 */
397 u32 fp_sibling;
398} fib_path_t;
399
400/*
401 * Array of strings/names for the path types and attributes
402 */
403static const char *fib_path_type_names[] = FIB_PATH_TYPES;
404static const char *fib_path_oper_attribute_names[] = FIB_PATH_OPER_ATTRIBUTES;
405static const char *fib_path_cfg_attribute_names[] = FIB_PATH_CFG_ATTRIBUTES;
406
407/*
408 * The memory pool from which we allocate all the paths
409 */
410static fib_path_t *fib_path_pool;
411
Neale Ranns710071b2018-09-24 12:36:26 +0000412/**
413 * the logger
414 */
415vlib_log_class_t fib_path_logger;
416
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100417/*
418 * Debug macro
419 */
Neale Ranns710071b2018-09-24 12:36:26 +0000420#define FIB_PATH_DBG(_p, _fmt, _args...) \
421{ \
422 vlib_log_debug (fib_path_logger, \
423 "[%U]: " _fmt, \
424 format_fib_path, fib_path_get_index(_p), 0, \
425 FIB_PATH_FORMAT_FLAGS_ONE_LINE, \
426 ##_args); \
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100427}
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100428
429static fib_path_t *
430fib_path_get (fib_node_index_t index)
431{
432 return (pool_elt_at_index(fib_path_pool, index));
433}
434
435static fib_node_index_t
436fib_path_get_index (fib_path_t *path)
437{
438 return (path - fib_path_pool);
439}
440
441static fib_node_t *
442fib_path_get_node (fib_node_index_t index)
443{
444 return ((fib_node_t*)fib_path_get(index));
445}
446
447static fib_path_t*
448fib_path_from_fib_node (fib_node_t *node)
449{
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100450 ASSERT(FIB_NODE_TYPE_PATH == node->fn_type);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100451 return ((fib_path_t*)node);
452}
453
454u8 *
455format_fib_path (u8 * s, va_list * args)
456{
Neale Ranns91286372017-12-05 13:24:04 -0800457 fib_node_index_t path_index = va_arg (*args, fib_node_index_t);
458 u32 indent = va_arg (*args, u32);
Neale Ranns710071b2018-09-24 12:36:26 +0000459 fib_format_path_flags_t flags = va_arg (*args, fib_format_path_flags_t);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100460 vnet_main_t * vnm = vnet_get_main();
461 fib_path_oper_attribute_t oattr;
462 fib_path_cfg_attribute_t cattr;
Neale Ranns91286372017-12-05 13:24:04 -0800463 fib_path_t *path;
Neale Ranns710071b2018-09-24 12:36:26 +0000464 const char *eol;
465
466 if (flags & FIB_PATH_FORMAT_FLAGS_ONE_LINE)
467 {
468 eol = "";
469 }
470 else
471 {
472 eol = "\n";
473 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100474
Neale Ranns91286372017-12-05 13:24:04 -0800475 path = fib_path_get(path_index);
476
477 s = format (s, "%Upath:[%d] ", format_white_space, indent,
478 fib_path_get_index(path));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100479 s = format (s, "pl-index:%d ", path->fp_pl_index);
Neale Rannsda78f952017-05-24 09:15:43 -0700480 s = format (s, "%U ", format_dpo_proto, path->fp_nh_proto);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100481 s = format (s, "weight=%d ", path->fp_weight);
Neale Ranns57b58602017-07-15 07:37:25 -0700482 s = format (s, "pref=%d ", path->fp_preference);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100483 s = format (s, "%s: ", fib_path_type_names[path->fp_type]);
484 if (FIB_PATH_OPER_FLAG_NONE != path->fp_oper_flags) {
485 s = format(s, " oper-flags:");
486 FOR_EACH_FIB_PATH_OPER_ATTRIBUTE(oattr) {
487 if ((1<<oattr) & path->fp_oper_flags) {
488 s = format (s, "%s,", fib_path_oper_attribute_names[oattr]);
489 }
490 }
491 }
492 if (FIB_PATH_CFG_FLAG_NONE != path->fp_cfg_flags) {
493 s = format(s, " cfg-flags:");
494 FOR_EACH_FIB_PATH_CFG_ATTRIBUTE(cattr) {
495 if ((1<<cattr) & path->fp_cfg_flags) {
496 s = format (s, "%s,", fib_path_cfg_attribute_names[cattr]);
497 }
498 }
499 }
Neale Ranns710071b2018-09-24 12:36:26 +0000500 if (!(flags & FIB_PATH_FORMAT_FLAGS_ONE_LINE))
501 s = format(s, "\n%U", format_white_space, indent+2);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100502
503 switch (path->fp_type)
504 {
505 case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
506 s = format (s, "%U", format_ip46_address,
507 &path->attached_next_hop.fp_nh,
508 IP46_TYPE_ANY);
509 if (path->fp_oper_flags & FIB_PATH_OPER_FLAG_DROP)
510 {
511 s = format (s, " if_index:%d", path->attached_next_hop.fp_interface);
512 }
513 else
514 {
515 s = format (s, " %U",
516 format_vnet_sw_interface_name,
517 vnm,
518 vnet_get_sw_interface(
519 vnm,
520 path->attached_next_hop.fp_interface));
521 if (vnet_sw_interface_is_p2p(vnet_get_main(),
522 path->attached_next_hop.fp_interface))
523 {
524 s = format (s, " (p2p)");
525 }
526 }
527 if (!dpo_id_is_valid(&path->fp_dpo))
528 {
Neale Ranns710071b2018-09-24 12:36:26 +0000529 s = format(s, "%s%Uunresolved", eol, format_white_space, indent+2);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100530 }
531 else
532 {
Neale Ranns710071b2018-09-24 12:36:26 +0000533 s = format(s, "%s%U%U", eol,
Neale Ranns91286372017-12-05 13:24:04 -0800534 format_white_space, indent,
535 format_dpo_id,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100536 &path->fp_dpo, 13);
537 }
538 break;
539 case FIB_PATH_TYPE_ATTACHED:
540 if (path->fp_oper_flags & FIB_PATH_OPER_FLAG_DROP)
541 {
Neale Ranns91286372017-12-05 13:24:04 -0800542 s = format (s, "if_index:%d", path->attached_next_hop.fp_interface);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100543 }
544 else
545 {
546 s = format (s, " %U",
547 format_vnet_sw_interface_name,
548 vnm,
549 vnet_get_sw_interface(
550 vnm,
551 path->attached.fp_interface));
552 }
553 break;
554 case FIB_PATH_TYPE_RECURSIVE:
Neale Rannsda78f952017-05-24 09:15:43 -0700555 if (DPO_PROTO_MPLS == path->fp_nh_proto)
Neale Rannsad422ed2016-11-02 14:20:04 +0000556 {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800557 s = format (s, "via %U %U",
Neale Rannsad422ed2016-11-02 14:20:04 +0000558 format_mpls_unicast_label,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800559 path->recursive.fp_nh.fp_local_label,
560 format_mpls_eos_bit,
561 path->recursive.fp_nh.fp_eos);
Neale Rannsad422ed2016-11-02 14:20:04 +0000562 }
563 else
564 {
565 s = format (s, "via %U",
566 format_ip46_address,
567 &path->recursive.fp_nh.fp_ip,
568 IP46_TYPE_ANY);
569 }
570 s = format (s, " in fib:%d",
571 path->recursive.fp_tbl_id,
572 path->fp_via_fib);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100573 s = format (s, " via-fib:%d", path->fp_via_fib);
574 s = format (s, " via-dpo:[%U:%d]",
575 format_dpo_type, path->fp_dpo.dpoi_type,
576 path->fp_dpo.dpoi_index);
577
578 break;
Neale Ranns810086d2017-11-05 16:26:46 -0800579 case FIB_PATH_TYPE_UDP_ENCAP:
Neale Ranns91286372017-12-05 13:24:04 -0800580 s = format (s, "UDP-encap ID:%d", path->udp_encap.fp_udp_encap_id);
Neale Ranns810086d2017-11-05 16:26:46 -0800581 break;
Neale Rannsd792d9c2017-10-21 10:53:20 -0700582 case FIB_PATH_TYPE_BIER_TABLE:
583 s = format (s, "via bier-table:[%U}",
584 format_bier_table_id,
585 &path->bier_table.fp_bier_tbl);
586 s = format (s, " via-dpo:[%U:%d]",
587 format_dpo_type, path->fp_dpo.dpoi_type,
588 path->fp_dpo.dpoi_index);
589 break;
590 case FIB_PATH_TYPE_BIER_FMASK:
Neale Ranns91286372017-12-05 13:24:04 -0800591 s = format (s, "via-fmask:%d", path->bier_fmask.fp_bier_fmask);
Neale Rannsd792d9c2017-10-21 10:53:20 -0700592 s = format (s, " via-dpo:[%U:%d]",
593 format_dpo_type, path->fp_dpo.dpoi_type,
594 path->fp_dpo.dpoi_index);
595 break;
596 case FIB_PATH_TYPE_BIER_IMP:
597 s = format (s, "via %U", format_bier_imp,
598 path->bier_imp.fp_bier_imp, 0, BIER_SHOW_BRIEF);
599 break;
Neale Rannsf068c3e2018-01-03 04:18:48 -0800600 case FIB_PATH_TYPE_DVR:
601 s = format (s, " %U",
602 format_vnet_sw_interface_name,
603 vnm,
604 vnet_get_sw_interface(
605 vnm,
606 path->dvr.fp_interface));
607 break;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100608 case FIB_PATH_TYPE_RECEIVE:
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800609 case FIB_PATH_TYPE_INTF_RX:
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100610 case FIB_PATH_TYPE_SPECIAL:
611 case FIB_PATH_TYPE_DEAG:
612 case FIB_PATH_TYPE_EXCLUSIVE:
613 if (dpo_id_is_valid(&path->fp_dpo))
614 {
615 s = format(s, "%U", format_dpo_id,
Neale Ranns91286372017-12-05 13:24:04 -0800616 &path->fp_dpo, indent+2);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100617 }
618 break;
619 }
620 return (s);
621}
622
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100623/*
624 * fib_path_last_lock_gone
625 *
626 * We don't share paths, we share path lists, so the [un]lock functions
627 * are no-ops
628 */
629static void
630fib_path_last_lock_gone (fib_node_t *node)
631{
632 ASSERT(0);
633}
634
635static const adj_index_t
636fib_path_attached_next_hop_get_adj (fib_path_t *path,
Neale Ranns924d03a2016-10-19 08:25:46 +0100637 vnet_link_t link)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100638{
639 if (vnet_sw_interface_is_p2p(vnet_get_main(),
640 path->attached_next_hop.fp_interface))
641 {
642 /*
643 * if the interface is p2p then the adj for the specific
644 * neighbour on that link will never exist. on p2p links
645 * the subnet address (the attached route) links to the
646 * auto-adj (see below), we want that adj here too.
647 */
Neale Rannsda78f952017-05-24 09:15:43 -0700648 return (adj_nbr_add_or_lock(dpo_proto_to_fib(path->fp_nh_proto),
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100649 link,
650 &zero_addr,
651 path->attached_next_hop.fp_interface));
652 }
653 else
654 {
Neale Rannsda78f952017-05-24 09:15:43 -0700655 return (adj_nbr_add_or_lock(dpo_proto_to_fib(path->fp_nh_proto),
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100656 link,
657 &path->attached_next_hop.fp_nh,
658 path->attached_next_hop.fp_interface));
659 }
660}
661
662static void
663fib_path_attached_next_hop_set (fib_path_t *path)
664{
665 /*
666 * resolve directly via the adjacnecy discribed by the
667 * interface and next-hop
668 */
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100669 dpo_set(&path->fp_dpo,
670 DPO_ADJACENCY,
Neale Rannsda78f952017-05-24 09:15:43 -0700671 path->fp_nh_proto,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100672 fib_path_attached_next_hop_get_adj(
673 path,
Neale Rannsda78f952017-05-24 09:15:43 -0700674 dpo_proto_to_link(path->fp_nh_proto)));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100675
676 /*
677 * become a child of the adjacency so we receive updates
678 * when its rewrite changes
679 */
680 path->fp_sibling = adj_child_add(path->fp_dpo.dpoi_index,
681 FIB_NODE_TYPE_PATH,
682 fib_path_get_index(path));
Neale Ranns88fc83e2017-04-05 08:11:14 -0700683
684 if (!vnet_sw_interface_is_admin_up(vnet_get_main(),
685 path->attached_next_hop.fp_interface) ||
686 !adj_is_up(path->fp_dpo.dpoi_index))
687 {
688 path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
689 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100690}
691
Neale Ranns8c4611b2017-05-23 03:43:47 -0700692static const adj_index_t
693fib_path_attached_get_adj (fib_path_t *path,
694 vnet_link_t link)
695{
696 if (vnet_sw_interface_is_p2p(vnet_get_main(),
697 path->attached.fp_interface))
698 {
699 /*
700 * point-2-point interfaces do not require a glean, since
701 * there is nothing to ARP. Install a rewrite/nbr adj instead
702 */
Neale Rannsda78f952017-05-24 09:15:43 -0700703 return (adj_nbr_add_or_lock(dpo_proto_to_fib(path->fp_nh_proto),
Neale Ranns8c4611b2017-05-23 03:43:47 -0700704 link,
705 &zero_addr,
706 path->attached.fp_interface));
707 }
708 else
709 {
Neale Rannsda78f952017-05-24 09:15:43 -0700710 return (adj_glean_add_or_lock(dpo_proto_to_fib(path->fp_nh_proto),
Ole Troan6ee40512018-02-12 18:14:39 +0100711 link,
Neale Ranns8c4611b2017-05-23 03:43:47 -0700712 path->attached.fp_interface,
713 NULL));
714 }
715}
716
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100717/*
718 * create of update the paths recursive adj
719 */
720static void
721fib_path_recursive_adj_update (fib_path_t *path,
722 fib_forward_chain_type_t fct,
723 dpo_id_t *dpo)
724{
Neale Ranns948e00f2016-10-20 13:39:34 +0100725 dpo_id_t via_dpo = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100726
727 /*
728 * get the DPO to resolve through from the via-entry
729 */
730 fib_entry_contribute_forwarding(path->fp_via_fib,
731 fct,
732 &via_dpo);
733
734
735 /*
736 * hope for the best - clear if restrictions apply.
737 */
738 path->fp_oper_flags |= FIB_PATH_OPER_FLAG_RESOLVED;
739
740 /*
741 * Validate any recursion constraints and over-ride the via
742 * adj if not met
743 */
744 if (path->fp_oper_flags & FIB_PATH_OPER_FLAG_RECURSIVE_LOOP)
745 {
746 path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
Neale Rannsda78f952017-05-24 09:15:43 -0700747 dpo_copy(&via_dpo, drop_dpo_get(path->fp_nh_proto));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100748 }
749 else if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_RESOLVE_HOST)
750 {
751 /*
752 * the via FIB must be a host route.
753 * note the via FIB just added will always be a host route
754 * since it is an RR source added host route. So what we need to
755 * check is whether the route has other sources. If it does then
756 * some other source has added it as a host route. If it doesn't
757 * then it was added only here and inherits forwarding from a cover.
758 * the cover is not a host route.
759 * The RR source is the lowest priority source, so we check if it
760 * is the best. if it is there are no other sources.
761 */
762 if (fib_entry_get_best_source(path->fp_via_fib) >= FIB_SOURCE_RR)
763 {
764 path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
Neale Rannsda78f952017-05-24 09:15:43 -0700765 dpo_copy(&via_dpo, drop_dpo_get(path->fp_nh_proto));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100766
767 /*
768 * PIC edge trigger. let the load-balance maps know
769 */
770 load_balance_map_path_state_change(fib_path_get_index(path));
771 }
772 }
773 else if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_RESOLVE_ATTACHED)
774 {
775 /*
776 * RR source entries inherit the flags from the cover, so
777 * we can check the via directly
778 */
779 if (!(FIB_ENTRY_FLAG_ATTACHED & fib_entry_get_flags(path->fp_via_fib)))
780 {
781 path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
Neale Rannsda78f952017-05-24 09:15:43 -0700782 dpo_copy(&via_dpo, drop_dpo_get(path->fp_nh_proto));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100783
784 /*
785 * PIC edge trigger. let the load-balance maps know
786 */
787 load_balance_map_path_state_change(fib_path_get_index(path));
788 }
789 }
Neale Ranns88fc83e2017-04-05 08:11:14 -0700790 /*
791 * check for over-riding factors on the FIB entry itself
792 */
793 if (!fib_entry_is_resolved(path->fp_via_fib))
794 {
795 path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
Neale Rannsda78f952017-05-24 09:15:43 -0700796 dpo_copy(&via_dpo, drop_dpo_get(path->fp_nh_proto));
Neale Ranns88fc83e2017-04-05 08:11:14 -0700797
798 /*
799 * PIC edge trigger. let the load-balance maps know
800 */
801 load_balance_map_path_state_change(fib_path_get_index(path));
802 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100803
804 /*
Neale Ranns57b58602017-07-15 07:37:25 -0700805 * If this path is contributing a drop, then it's not resolved
806 */
807 if (dpo_is_drop(&via_dpo) || load_balance_is_drop(&via_dpo))
808 {
809 path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
810 }
811
812 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100813 * update the path's contributed DPO
814 */
815 dpo_copy(dpo, &via_dpo);
816
Neale Rannsda78f952017-05-24 09:15:43 -0700817 FIB_PATH_DBG(path, "recursive update:");
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100818
819 dpo_reset(&via_dpo);
820}
821
822/*
Neale Rannsd792d9c2017-10-21 10:53:20 -0700823 * re-evaulate the forwarding state for a via fmask path
824 */
825static void
826fib_path_bier_fmask_update (fib_path_t *path,
827 dpo_id_t *dpo)
828{
Neale Ranns91286372017-12-05 13:24:04 -0800829 bier_fmask_contribute_forwarding(path->bier_fmask.fp_bier_fmask, dpo);
Neale Rannsd792d9c2017-10-21 10:53:20 -0700830
831 /*
832 * if we are stakcing on the drop, then the path is not resolved
833 */
834 if (dpo_is_drop(dpo))
835 {
836 path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
837 }
838 else
839 {
840 path->fp_oper_flags |= FIB_PATH_OPER_FLAG_RESOLVED;
841 }
842}
843
844/*
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100845 * fib_path_is_permanent_drop
846 *
847 * Return !0 if the path is configured to permanently drop,
848 * despite other attributes.
849 */
850static int
851fib_path_is_permanent_drop (fib_path_t *path)
852{
853 return ((path->fp_cfg_flags & FIB_PATH_CFG_FLAG_DROP) ||
854 (path->fp_oper_flags & FIB_PATH_OPER_FLAG_DROP));
855}
856
857/*
858 * fib_path_unresolve
859 *
860 * Remove our dependency on the resolution target
861 */
862static void
863fib_path_unresolve (fib_path_t *path)
864{
865 /*
866 * the forced drop path does not need unresolving
867 */
868 if (fib_path_is_permanent_drop(path))
869 {
870 return;
871 }
872
873 switch (path->fp_type)
874 {
875 case FIB_PATH_TYPE_RECURSIVE:
876 if (FIB_NODE_INDEX_INVALID != path->fp_via_fib)
877 {
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100878 fib_entry_child_remove(path->fp_via_fib,
879 path->fp_sibling);
880 fib_table_entry_special_remove(path->recursive.fp_tbl_id,
Neale Rannsc5d43172018-07-30 08:04:40 -0700881 fib_entry_get_prefix(path->fp_via_fib),
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100882 FIB_SOURCE_RR);
Neale Ranns6fff24a2018-09-10 19:14:07 -0700883 fib_table_unlock(path->recursive.fp_tbl_id,
884 dpo_proto_to_fib(path->fp_nh_proto),
885 FIB_SOURCE_RR);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100886 path->fp_via_fib = FIB_NODE_INDEX_INVALID;
887 }
888 break;
Neale Rannsd792d9c2017-10-21 10:53:20 -0700889 case FIB_PATH_TYPE_BIER_FMASK:
Neale Ranns91286372017-12-05 13:24:04 -0800890 bier_fmask_child_remove(path->fp_via_bier_fmask,
891 path->fp_sibling);
Neale Rannsd792d9c2017-10-21 10:53:20 -0700892 break;
893 case FIB_PATH_TYPE_BIER_IMP:
894 bier_imp_unlock(path->fp_dpo.dpoi_index);
895 break;
896 case FIB_PATH_TYPE_BIER_TABLE:
897 bier_table_ecmp_unlock(path->fp_via_bier_tbl);
898 break;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100899 case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100900 adj_child_remove(path->fp_dpo.dpoi_index,
901 path->fp_sibling);
902 adj_unlock(path->fp_dpo.dpoi_index);
903 break;
Neale Ranns6f631152017-10-03 08:20:21 -0700904 case FIB_PATH_TYPE_ATTACHED:
Neale Rannsf068c3e2018-01-03 04:18:48 -0800905 adj_child_remove(path->fp_dpo.dpoi_index,
906 path->fp_sibling);
907 adj_unlock(path->fp_dpo.dpoi_index);
Neale Ranns6f631152017-10-03 08:20:21 -0700908 break;
Neale Ranns810086d2017-11-05 16:26:46 -0800909 case FIB_PATH_TYPE_UDP_ENCAP:
Neale Ranns9c0a3c42018-09-07 08:57:41 -0700910 udp_encap_unlock(path->fp_dpo.dpoi_index);
Neale Ranns810086d2017-11-05 16:26:46 -0800911 break;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100912 case FIB_PATH_TYPE_EXCLUSIVE:
913 dpo_reset(&path->exclusive.fp_ex_dpo);
914 break;
915 case FIB_PATH_TYPE_SPECIAL:
916 case FIB_PATH_TYPE_RECEIVE:
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800917 case FIB_PATH_TYPE_INTF_RX:
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100918 case FIB_PATH_TYPE_DEAG:
Neale Rannsf068c3e2018-01-03 04:18:48 -0800919 case FIB_PATH_TYPE_DVR:
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100920 /*
921 * these hold only the path's DPO, which is reset below.
922 */
923 break;
924 }
925
926 /*
927 * release the adj we were holding and pick up the
928 * drop just in case.
929 */
930 dpo_reset(&path->fp_dpo);
931 path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
932
933 return;
934}
935
936static fib_forward_chain_type_t
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800937fib_path_to_chain_type (const fib_path_t *path)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100938{
Neale Rannsda78f952017-05-24 09:15:43 -0700939 if (DPO_PROTO_MPLS == path->fp_nh_proto)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100940 {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800941 if (FIB_PATH_TYPE_RECURSIVE == path->fp_type &&
942 MPLS_EOS == path->recursive.fp_nh.fp_eos)
943 {
944 return (FIB_FORW_CHAIN_TYPE_MPLS_EOS);
945 }
946 else
947 {
Neale Ranns9f171f52017-04-11 08:56:53 -0700948 return (FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS);
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800949 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100950 }
Neale Rannsda78f952017-05-24 09:15:43 -0700951 else
952 {
953 return (fib_forw_chain_type_from_dpo_proto(path->fp_nh_proto));
954 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100955}
956
957/*
958 * fib_path_back_walk_notify
959 *
960 * A back walk has reach this path.
961 */
962static fib_node_back_walk_rc_t
963fib_path_back_walk_notify (fib_node_t *node,
964 fib_node_back_walk_ctx_t *ctx)
965{
966 fib_path_t *path;
967
968 path = fib_path_from_fib_node(node);
969
Neale Ranns710071b2018-09-24 12:36:26 +0000970 FIB_PATH_DBG(path, "bw:%U",
971 format_fib_node_bw_reason, ctx->fnbw_reason);
972
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100973 switch (path->fp_type)
974 {
975 case FIB_PATH_TYPE_RECURSIVE:
976 if (FIB_NODE_BW_REASON_FLAG_EVALUATE & ctx->fnbw_reason)
977 {
978 /*
979 * modify the recursive adjacency to use the new forwarding
980 * of the via-fib.
981 * this update is visible to packets in flight in the DP.
982 */
983 fib_path_recursive_adj_update(
984 path,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800985 fib_path_to_chain_type(path),
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100986 &path->fp_dpo);
987 }
Neale Rannsad95b5d2016-11-10 20:35:14 +0000988 if ((FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE & ctx->fnbw_reason) ||
989 (FIB_NODE_BW_REASON_FLAG_ADJ_DOWN & ctx->fnbw_reason))
Neale Rannsb80c5362016-10-08 13:03:40 +0100990 {
991 /*
992 * ADJ updates (complete<->incomplete) do not need to propagate to
993 * recursive entries.
994 * The only reason its needed as far back as here, is that the adj
995 * and the incomplete adj are a different DPO type, so the LBs need
996 * to re-stack.
997 * If this walk was quashed in the fib_entry, then any non-fib_path
998 * children (like tunnels that collapse out the LB when they stack)
999 * would not see the update.
1000 */
1001 return (FIB_NODE_BACK_WALK_CONTINUE);
1002 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001003 break;
Neale Rannsd792d9c2017-10-21 10:53:20 -07001004 case FIB_PATH_TYPE_BIER_FMASK:
1005 if (FIB_NODE_BW_REASON_FLAG_EVALUATE & ctx->fnbw_reason)
1006 {
1007 /*
1008 * update to use the BIER fmask's new forwading
1009 */
1010 fib_path_bier_fmask_update(path, &path->fp_dpo);
1011 }
1012 if ((FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE & ctx->fnbw_reason) ||
1013 (FIB_NODE_BW_REASON_FLAG_ADJ_DOWN & ctx->fnbw_reason))
1014 {
1015 /*
1016 * ADJ updates (complete<->incomplete) do not need to propagate to
1017 * recursive entries.
1018 * The only reason its needed as far back as here, is that the adj
1019 * and the incomplete adj are a different DPO type, so the LBs need
1020 * to re-stack.
1021 * If this walk was quashed in the fib_entry, then any non-fib_path
1022 * children (like tunnels that collapse out the LB when they stack)
1023 * would not see the update.
1024 */
1025 return (FIB_NODE_BACK_WALK_CONTINUE);
1026 }
1027 break;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001028 case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
1029 /*
1030FIXME comment
1031 * ADJ_UPDATE backwalk pass silently through here and up to
1032 * the path-list when the multipath adj collapse occurs.
1033 * The reason we do this is that the assumtption is that VPP
1034 * runs in an environment where the Control-Plane is remote
1035 * and hence reacts slowly to link up down. In order to remove
1036 * this down link from the ECMP set quickly, we back-walk.
1037 * VPP also has dedicated CPUs, so we are not stealing resources
1038 * from the CP to do so.
1039 */
1040 if (FIB_NODE_BW_REASON_FLAG_INTERFACE_UP & ctx->fnbw_reason)
1041 {
Neale Ranns8b37b872016-11-21 12:25:22 +00001042 if (path->fp_oper_flags & FIB_PATH_OPER_FLAG_RESOLVED)
1043 {
1044 /*
1045 * alreday resolved. no need to walk back again
1046 */
1047 return (FIB_NODE_BACK_WALK_CONTINUE);
1048 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001049 path->fp_oper_flags |= FIB_PATH_OPER_FLAG_RESOLVED;
1050 }
1051 if (FIB_NODE_BW_REASON_FLAG_INTERFACE_DOWN & ctx->fnbw_reason)
1052 {
Neale Ranns8b37b872016-11-21 12:25:22 +00001053 if (!(path->fp_oper_flags & FIB_PATH_OPER_FLAG_RESOLVED))
1054 {
1055 /*
1056 * alreday unresolved. no need to walk back again
1057 */
1058 return (FIB_NODE_BACK_WALK_CONTINUE);
1059 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001060 path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
1061 }
1062 if (FIB_NODE_BW_REASON_FLAG_INTERFACE_DELETE & ctx->fnbw_reason)
1063 {
1064 /*
1065 * The interface this path resolves through has been deleted.
1066 * This will leave the path in a permanent drop state. The route
1067 * needs to be removed and readded (and hence the path-list deleted)
1068 * before it can forward again.
1069 */
1070 fib_path_unresolve(path);
1071 path->fp_oper_flags |= FIB_PATH_OPER_FLAG_DROP;
1072 }
1073 if (FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE & ctx->fnbw_reason)
1074 {
1075 /*
1076 * restack the DPO to pick up the correct DPO sub-type
1077 */
Neale Ranns8b37b872016-11-21 12:25:22 +00001078 uword if_is_up;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001079 adj_index_t ai;
1080
Neale Ranns8b37b872016-11-21 12:25:22 +00001081 if_is_up = vnet_sw_interface_is_admin_up(
1082 vnet_get_main(),
1083 path->attached_next_hop.fp_interface);
1084
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001085 ai = fib_path_attached_next_hop_get_adj(
1086 path,
Neale Rannsda78f952017-05-24 09:15:43 -07001087 dpo_proto_to_link(path->fp_nh_proto));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001088
Neale Ranns88fc83e2017-04-05 08:11:14 -07001089 path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
1090 if (if_is_up && adj_is_up(ai))
1091 {
1092 path->fp_oper_flags |= FIB_PATH_OPER_FLAG_RESOLVED;
1093 }
1094
Neale Rannsda78f952017-05-24 09:15:43 -07001095 dpo_set(&path->fp_dpo, DPO_ADJACENCY, path->fp_nh_proto, ai);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001096 adj_unlock(ai);
Neale Ranns8b37b872016-11-21 12:25:22 +00001097
1098 if (!if_is_up)
1099 {
1100 /*
1101 * If the interface is not up there is no reason to walk
1102 * back to children. if we did they would only evalute
1103 * that this path is unresolved and hence it would
1104 * not contribute the adjacency - so it would be wasted
1105 * CPU time.
1106 */
1107 return (FIB_NODE_BACK_WALK_CONTINUE);
1108 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001109 }
Neale Rannsad95b5d2016-11-10 20:35:14 +00001110 if (FIB_NODE_BW_REASON_FLAG_ADJ_DOWN & ctx->fnbw_reason)
1111 {
Neale Ranns8b37b872016-11-21 12:25:22 +00001112 if (!(path->fp_oper_flags & FIB_PATH_OPER_FLAG_RESOLVED))
1113 {
1114 /*
1115 * alreday unresolved. no need to walk back again
1116 */
1117 return (FIB_NODE_BACK_WALK_CONTINUE);
1118 }
Neale Rannsad95b5d2016-11-10 20:35:14 +00001119 /*
1120 * the adj has gone down. the path is no longer resolved.
1121 */
1122 path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
1123 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001124 break;
1125 case FIB_PATH_TYPE_ATTACHED:
Neale Rannsf068c3e2018-01-03 04:18:48 -08001126 case FIB_PATH_TYPE_DVR:
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001127 /*
1128 * FIXME; this could schedule a lower priority walk, since attached
1129 * routes are not usually in ECMP configurations so the backwalk to
1130 * the FIB entry does not need to be high priority
1131 */
1132 if (FIB_NODE_BW_REASON_FLAG_INTERFACE_UP & ctx->fnbw_reason)
1133 {
1134 path->fp_oper_flags |= FIB_PATH_OPER_FLAG_RESOLVED;
1135 }
1136 if (FIB_NODE_BW_REASON_FLAG_INTERFACE_DOWN & ctx->fnbw_reason)
1137 {
1138 path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
1139 }
1140 if (FIB_NODE_BW_REASON_FLAG_INTERFACE_DELETE & ctx->fnbw_reason)
1141 {
1142 fib_path_unresolve(path);
1143 path->fp_oper_flags |= FIB_PATH_OPER_FLAG_DROP;
1144 }
1145 break;
Neale Ranns810086d2017-11-05 16:26:46 -08001146 case FIB_PATH_TYPE_UDP_ENCAP:
1147 {
1148 dpo_id_t via_dpo = DPO_INVALID;
1149
1150 /*
1151 * hope for the best - clear if restrictions apply.
1152 */
1153 path->fp_oper_flags |= FIB_PATH_OPER_FLAG_RESOLVED;
1154
1155 udp_encap_contribute_forwarding(path->udp_encap.fp_udp_encap_id,
1156 path->fp_nh_proto,
1157 &via_dpo);
1158 /*
1159 * If this path is contributing a drop, then it's not resolved
1160 */
1161 if (dpo_is_drop(&via_dpo) || load_balance_is_drop(&via_dpo))
1162 {
1163 path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
1164 }
1165
1166 /*
1167 * update the path's contributed DPO
1168 */
1169 dpo_copy(&path->fp_dpo, &via_dpo);
1170 dpo_reset(&via_dpo);
1171 break;
1172 }
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001173 case FIB_PATH_TYPE_INTF_RX:
1174 ASSERT(0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001175 case FIB_PATH_TYPE_DEAG:
1176 /*
1177 * FIXME When VRF delete is allowed this will need a poke.
1178 */
1179 case FIB_PATH_TYPE_SPECIAL:
1180 case FIB_PATH_TYPE_RECEIVE:
1181 case FIB_PATH_TYPE_EXCLUSIVE:
Neale Rannsd792d9c2017-10-21 10:53:20 -07001182 case FIB_PATH_TYPE_BIER_TABLE:
1183 case FIB_PATH_TYPE_BIER_IMP:
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001184 /*
1185 * these path types have no parents. so to be
1186 * walked from one is unexpected.
1187 */
1188 ASSERT(0);
1189 break;
1190 }
1191
1192 /*
1193 * propagate the backwalk further to the path-list
1194 */
1195 fib_path_list_back_walk(path->fp_pl_index, ctx);
1196
1197 return (FIB_NODE_BACK_WALK_CONTINUE);
1198}
1199
Neale Ranns6c3ebcc2016-10-02 21:20:15 +01001200static void
1201fib_path_memory_show (void)
1202{
1203 fib_show_memory_usage("Path",
1204 pool_elts(fib_path_pool),
1205 pool_len(fib_path_pool),
1206 sizeof(fib_path_t));
1207}
1208
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001209/*
1210 * The FIB path's graph node virtual function table
1211 */
1212static const fib_node_vft_t fib_path_vft = {
1213 .fnv_get = fib_path_get_node,
1214 .fnv_last_lock = fib_path_last_lock_gone,
1215 .fnv_back_walk = fib_path_back_walk_notify,
Neale Ranns6c3ebcc2016-10-02 21:20:15 +01001216 .fnv_mem_show = fib_path_memory_show,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001217};
1218
1219static fib_path_cfg_flags_t
1220fib_path_route_flags_to_cfg_flags (const fib_route_path_t *rpath)
1221{
Neale Ranns450cd302016-11-09 17:49:42 +00001222 fib_path_cfg_flags_t cfg_flags = FIB_PATH_CFG_FLAG_NONE;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001223
1224 if (rpath->frp_flags & FIB_ROUTE_PATH_RESOLVE_VIA_HOST)
1225 cfg_flags |= FIB_PATH_CFG_FLAG_RESOLVE_HOST;
1226 if (rpath->frp_flags & FIB_ROUTE_PATH_RESOLVE_VIA_ATTACHED)
1227 cfg_flags |= FIB_PATH_CFG_FLAG_RESOLVE_ATTACHED;
Neale Ranns32e1c012016-11-22 17:07:28 +00001228 if (rpath->frp_flags & FIB_ROUTE_PATH_LOCAL)
1229 cfg_flags |= FIB_PATH_CFG_FLAG_LOCAL;
Neale Ranns4b919a52017-03-11 05:55:21 -08001230 if (rpath->frp_flags & FIB_ROUTE_PATH_ATTACHED)
1231 cfg_flags |= FIB_PATH_CFG_FLAG_ATTACHED;
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001232 if (rpath->frp_flags & FIB_ROUTE_PATH_INTF_RX)
1233 cfg_flags |= FIB_PATH_CFG_FLAG_INTF_RX;
1234 if (rpath->frp_flags & FIB_ROUTE_PATH_RPF_ID)
1235 cfg_flags |= FIB_PATH_CFG_FLAG_RPF_ID;
1236 if (rpath->frp_flags & FIB_ROUTE_PATH_EXCLUSIVE)
1237 cfg_flags |= FIB_PATH_CFG_FLAG_EXCLUSIVE;
1238 if (rpath->frp_flags & FIB_ROUTE_PATH_DROP)
1239 cfg_flags |= FIB_PATH_CFG_FLAG_DROP;
Neale Ranns054c03a2017-10-13 05:15:07 -07001240 if (rpath->frp_flags & FIB_ROUTE_PATH_SOURCE_LOOKUP)
1241 cfg_flags |= FIB_PATH_CFG_FLAG_DEAG_SRC;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001242
1243 return (cfg_flags);
1244}
1245
1246/*
1247 * fib_path_create
1248 *
1249 * Create and initialise a new path object.
1250 * return the index of the path.
1251 */
1252fib_node_index_t
1253fib_path_create (fib_node_index_t pl_index,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001254 const fib_route_path_t *rpath)
1255{
1256 fib_path_t *path;
1257
1258 pool_get(fib_path_pool, path);
Dave Barachb7b92992018-10-17 10:38:51 -04001259 clib_memset(path, 0, sizeof(*path));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001260
1261 fib_node_init(&path->fp_node,
1262 FIB_NODE_TYPE_PATH);
1263
1264 dpo_reset(&path->fp_dpo);
1265 path->fp_pl_index = pl_index;
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001266 path->fp_nh_proto = rpath->frp_proto;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001267 path->fp_via_fib = FIB_NODE_INDEX_INVALID;
1268 path->fp_weight = rpath->frp_weight;
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001269 if (0 == path->fp_weight)
1270 {
1271 /*
1272 * a weight of 0 is a meaningless value. We could either reject it, and thus force
1273 * clients to always use 1, or we can accept it and fixup approrpiately.
1274 */
1275 path->fp_weight = 1;
1276 }
Neale Ranns57b58602017-07-15 07:37:25 -07001277 path->fp_preference = rpath->frp_preference;
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001278 path->fp_cfg_flags = fib_path_route_flags_to_cfg_flags(rpath);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001279
1280 /*
1281 * deduce the path's tpye from the parementers and save what is needed.
1282 */
Neale Ranns32e1c012016-11-22 17:07:28 +00001283 if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_LOCAL)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001284 {
Neale Ranns32e1c012016-11-22 17:07:28 +00001285 path->fp_type = FIB_PATH_TYPE_RECEIVE;
1286 path->receive.fp_interface = rpath->frp_sw_if_index;
1287 path->receive.fp_addr = rpath->frp_addr;
1288 }
Neale Ranns810086d2017-11-05 16:26:46 -08001289 else if (rpath->frp_flags & FIB_ROUTE_PATH_UDP_ENCAP)
1290 {
1291 path->fp_type = FIB_PATH_TYPE_UDP_ENCAP;
1292 path->udp_encap.fp_udp_encap_id = rpath->frp_udp_encap_id;
1293 }
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001294 else if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_INTF_RX)
1295 {
1296 path->fp_type = FIB_PATH_TYPE_INTF_RX;
1297 path->intf_rx.fp_interface = rpath->frp_sw_if_index;
1298 }
1299 else if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_RPF_ID)
1300 {
1301 path->fp_type = FIB_PATH_TYPE_DEAG;
1302 path->deag.fp_tbl_id = rpath->frp_fib_index;
1303 path->deag.fp_rpf_id = rpath->frp_rpf_id;
1304 }
Neale Rannsd792d9c2017-10-21 10:53:20 -07001305 else if (rpath->frp_flags & FIB_ROUTE_PATH_BIER_FMASK)
1306 {
1307 path->fp_type = FIB_PATH_TYPE_BIER_FMASK;
Neale Ranns91286372017-12-05 13:24:04 -08001308 path->bier_fmask.fp_bier_fmask = rpath->frp_bier_fmask;
Neale Rannsd792d9c2017-10-21 10:53:20 -07001309 }
1310 else if (rpath->frp_flags & FIB_ROUTE_PATH_BIER_IMP)
1311 {
1312 path->fp_type = FIB_PATH_TYPE_BIER_IMP;
1313 path->bier_imp.fp_bier_imp = rpath->frp_bier_imp;
1314 }
1315 else if (rpath->frp_flags & FIB_ROUTE_PATH_BIER_TABLE)
1316 {
1317 path->fp_type = FIB_PATH_TYPE_BIER_TABLE;
1318 path->bier_table.fp_bier_tbl = rpath->frp_bier_tbl;
1319 }
Florin Coras79ae2d32017-12-16 08:31:06 -08001320 else if (rpath->frp_flags & FIB_ROUTE_PATH_DEAG)
1321 {
1322 path->fp_type = FIB_PATH_TYPE_DEAG;
1323 path->deag.fp_tbl_id = rpath->frp_fib_index;
1324 }
Neale Rannsf068c3e2018-01-03 04:18:48 -08001325 else if (rpath->frp_flags & FIB_ROUTE_PATH_DVR)
1326 {
1327 path->fp_type = FIB_PATH_TYPE_DVR;
1328 path->dvr.fp_interface = rpath->frp_sw_if_index;
1329 }
Vijayabhaskar Katamreddycef5db02018-10-05 11:24:56 -07001330 else if (rpath->frp_flags & FIB_ROUTE_PATH_EXCLUSIVE)
1331 {
1332 path->fp_type = FIB_PATH_TYPE_EXCLUSIVE;
1333 dpo_copy(&path->exclusive.fp_ex_dpo, &rpath->dpo);
1334 }
Neale Ranns32e1c012016-11-22 17:07:28 +00001335 else if (~0 != rpath->frp_sw_if_index)
1336 {
1337 if (ip46_address_is_zero(&rpath->frp_addr))
1338 {
1339 path->fp_type = FIB_PATH_TYPE_ATTACHED;
1340 path->attached.fp_interface = rpath->frp_sw_if_index;
1341 }
1342 else
1343 {
1344 path->fp_type = FIB_PATH_TYPE_ATTACHED_NEXT_HOP;
1345 path->attached_next_hop.fp_interface = rpath->frp_sw_if_index;
1346 path->attached_next_hop.fp_nh = rpath->frp_addr;
1347 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001348 }
1349 else
1350 {
1351 if (ip46_address_is_zero(&rpath->frp_addr))
1352 {
1353 if (~0 == rpath->frp_fib_index)
1354 {
1355 path->fp_type = FIB_PATH_TYPE_SPECIAL;
1356 }
1357 else
1358 {
1359 path->fp_type = FIB_PATH_TYPE_DEAG;
1360 path->deag.fp_tbl_id = rpath->frp_fib_index;
Neale Ranns31ed7442018-02-23 05:29:09 -08001361 path->deag.fp_rpf_id = ~0;
1362 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001363 }
1364 else
1365 {
1366 path->fp_type = FIB_PATH_TYPE_RECURSIVE;
Neale Rannsda78f952017-05-24 09:15:43 -07001367 if (DPO_PROTO_MPLS == path->fp_nh_proto)
Neale Rannsad422ed2016-11-02 14:20:04 +00001368 {
1369 path->recursive.fp_nh.fp_local_label = rpath->frp_local_label;
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001370 path->recursive.fp_nh.fp_eos = rpath->frp_eos;
Neale Rannsad422ed2016-11-02 14:20:04 +00001371 }
1372 else
1373 {
1374 path->recursive.fp_nh.fp_ip = rpath->frp_addr;
1375 }
Neale Rannsd792d9c2017-10-21 10:53:20 -07001376 path->recursive.fp_tbl_id = rpath->frp_fib_index;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001377 }
1378 }
1379
1380 FIB_PATH_DBG(path, "create");
1381
1382 return (fib_path_get_index(path));
1383}
1384
1385/*
1386 * fib_path_create_special
1387 *
1388 * Create and initialise a new path object.
1389 * return the index of the path.
1390 */
1391fib_node_index_t
1392fib_path_create_special (fib_node_index_t pl_index,
Neale Rannsda78f952017-05-24 09:15:43 -07001393 dpo_proto_t nh_proto,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001394 fib_path_cfg_flags_t flags,
1395 const dpo_id_t *dpo)
1396{
1397 fib_path_t *path;
1398
1399 pool_get(fib_path_pool, path);
Dave Barachb7b92992018-10-17 10:38:51 -04001400 clib_memset(path, 0, sizeof(*path));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001401
1402 fib_node_init(&path->fp_node,
1403 FIB_NODE_TYPE_PATH);
1404 dpo_reset(&path->fp_dpo);
1405
1406 path->fp_pl_index = pl_index;
1407 path->fp_weight = 1;
Neale Ranns57b58602017-07-15 07:37:25 -07001408 path->fp_preference = 0;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001409 path->fp_nh_proto = nh_proto;
1410 path->fp_via_fib = FIB_NODE_INDEX_INVALID;
1411 path->fp_cfg_flags = flags;
1412
1413 if (FIB_PATH_CFG_FLAG_DROP & flags)
1414 {
1415 path->fp_type = FIB_PATH_TYPE_SPECIAL;
1416 }
1417 else if (FIB_PATH_CFG_FLAG_LOCAL & flags)
1418 {
1419 path->fp_type = FIB_PATH_TYPE_RECEIVE;
1420 path->attached.fp_interface = FIB_NODE_INDEX_INVALID;
1421 }
1422 else
1423 {
1424 path->fp_type = FIB_PATH_TYPE_EXCLUSIVE;
1425 ASSERT(NULL != dpo);
1426 dpo_copy(&path->exclusive.fp_ex_dpo, dpo);
1427 }
1428
1429 return (fib_path_get_index(path));
1430}
1431
1432/*
1433 * fib_path_copy
1434 *
1435 * Copy a path. return index of new path.
1436 */
1437fib_node_index_t
1438fib_path_copy (fib_node_index_t path_index,
1439 fib_node_index_t path_list_index)
1440{
1441 fib_path_t *path, *orig_path;
1442
1443 pool_get(fib_path_pool, path);
1444
1445 orig_path = fib_path_get(path_index);
1446 ASSERT(NULL != orig_path);
1447
1448 memcpy(path, orig_path, sizeof(*path));
1449
1450 FIB_PATH_DBG(path, "create-copy:%d", path_index);
1451
1452 /*
1453 * reset the dynamic section
1454 */
1455 fib_node_init(&path->fp_node, FIB_NODE_TYPE_PATH);
1456 path->fp_oper_flags = FIB_PATH_OPER_FLAG_NONE;
1457 path->fp_pl_index = path_list_index;
1458 path->fp_via_fib = FIB_NODE_INDEX_INVALID;
Dave Barachb7b92992018-10-17 10:38:51 -04001459 clib_memset(&path->fp_dpo, 0, sizeof(path->fp_dpo));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001460 dpo_reset(&path->fp_dpo);
1461
1462 return (fib_path_get_index(path));
1463}
1464
1465/*
1466 * fib_path_destroy
1467 *
1468 * destroy a path that is no longer required
1469 */
1470void
1471fib_path_destroy (fib_node_index_t path_index)
1472{
1473 fib_path_t *path;
1474
1475 path = fib_path_get(path_index);
1476
1477 ASSERT(NULL != path);
1478 FIB_PATH_DBG(path, "destroy");
1479
1480 fib_path_unresolve(path);
1481
1482 fib_node_deinit(&path->fp_node);
1483 pool_put(fib_path_pool, path);
1484}
1485
1486/*
1487 * fib_path_destroy
1488 *
1489 * destroy a path that is no longer required
1490 */
1491uword
1492fib_path_hash (fib_node_index_t path_index)
1493{
1494 fib_path_t *path;
1495
1496 path = fib_path_get(path_index);
1497
1498 return (hash_memory(STRUCT_MARK_PTR(path, path_hash_start),
1499 (STRUCT_OFFSET_OF(fib_path_t, path_hash_end) -
1500 STRUCT_OFFSET_OF(fib_path_t, path_hash_start)),
1501 0));
1502}
1503
1504/*
1505 * fib_path_cmp_i
1506 *
1507 * Compare two paths for equivalence.
1508 */
1509static int
1510fib_path_cmp_i (const fib_path_t *path1,
1511 const fib_path_t *path2)
1512{
1513 int res;
1514
1515 res = 1;
1516
1517 /*
1518 * paths of different types and protocol are not equal.
Neale Ranns57b58602017-07-15 07:37:25 -07001519 * different weights and/or preference only are the same path.
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001520 */
1521 if (path1->fp_type != path2->fp_type)
1522 {
1523 res = (path1->fp_type - path2->fp_type);
1524 }
Neale Ranns32e1c012016-11-22 17:07:28 +00001525 else if (path1->fp_nh_proto != path2->fp_nh_proto)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001526 {
1527 res = (path1->fp_nh_proto - path2->fp_nh_proto);
1528 }
1529 else
1530 {
1531 /*
1532 * both paths are of the same type.
1533 * consider each type and its attributes in turn.
1534 */
1535 switch (path1->fp_type)
1536 {
1537 case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
1538 res = ip46_address_cmp(&path1->attached_next_hop.fp_nh,
1539 &path2->attached_next_hop.fp_nh);
1540 if (0 == res) {
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001541 res = (path1->attached_next_hop.fp_interface -
1542 path2->attached_next_hop.fp_interface);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001543 }
1544 break;
1545 case FIB_PATH_TYPE_ATTACHED:
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001546 res = (path1->attached.fp_interface -
1547 path2->attached.fp_interface);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001548 break;
1549 case FIB_PATH_TYPE_RECURSIVE:
1550 res = ip46_address_cmp(&path1->recursive.fp_nh,
1551 &path2->recursive.fp_nh);
1552
1553 if (0 == res)
1554 {
1555 res = (path1->recursive.fp_tbl_id - path2->recursive.fp_tbl_id);
1556 }
1557 break;
Neale Rannsd792d9c2017-10-21 10:53:20 -07001558 case FIB_PATH_TYPE_BIER_FMASK:
Neale Ranns91286372017-12-05 13:24:04 -08001559 res = (path1->bier_fmask.fp_bier_fmask -
1560 path2->bier_fmask.fp_bier_fmask);
Neale Rannsd792d9c2017-10-21 10:53:20 -07001561 break;
1562 case FIB_PATH_TYPE_BIER_IMP:
1563 res = (path1->bier_imp.fp_bier_imp -
1564 path2->bier_imp.fp_bier_imp);
1565 break;
1566 case FIB_PATH_TYPE_BIER_TABLE:
1567 res = bier_table_id_cmp(&path1->bier_table.fp_bier_tbl,
1568 &path2->bier_table.fp_bier_tbl);
1569 break;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001570 case FIB_PATH_TYPE_DEAG:
1571 res = (path1->deag.fp_tbl_id - path2->deag.fp_tbl_id);
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001572 if (0 == res)
1573 {
1574 res = (path1->deag.fp_rpf_id - path2->deag.fp_rpf_id);
1575 }
1576 break;
1577 case FIB_PATH_TYPE_INTF_RX:
1578 res = (path1->intf_rx.fp_interface - path2->intf_rx.fp_interface);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001579 break;
Neale Ranns810086d2017-11-05 16:26:46 -08001580 case FIB_PATH_TYPE_UDP_ENCAP:
1581 res = (path1->udp_encap.fp_udp_encap_id - path2->udp_encap.fp_udp_encap_id);
1582 break;
Neale Rannsf068c3e2018-01-03 04:18:48 -08001583 case FIB_PATH_TYPE_DVR:
1584 res = (path1->dvr.fp_interface - path2->dvr.fp_interface);
1585 break;
Vijayabhaskar Katamreddycef5db02018-10-05 11:24:56 -07001586 case FIB_PATH_TYPE_EXCLUSIVE:
1587 res = dpo_cmp(&path1->exclusive.fp_ex_dpo, &path2->exclusive.fp_ex_dpo);
1588 break;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001589 case FIB_PATH_TYPE_SPECIAL:
1590 case FIB_PATH_TYPE_RECEIVE:
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001591 res = 0;
1592 break;
1593 }
1594 }
1595 return (res);
1596}
1597
1598/*
1599 * fib_path_cmp_for_sort
1600 *
1601 * Compare two paths for equivalence. Used during path sorting.
1602 * As usual 0 means equal.
1603 */
1604int
1605fib_path_cmp_for_sort (void * v1,
1606 void * v2)
1607{
1608 fib_node_index_t *pi1 = v1, *pi2 = v2;
1609 fib_path_t *path1, *path2;
1610
1611 path1 = fib_path_get(*pi1);
1612 path2 = fib_path_get(*pi2);
1613
Neale Ranns57b58602017-07-15 07:37:25 -07001614 /*
1615 * when sorting paths we want the highest preference paths
1616 * first, so that the choices set built is in prefernce order
1617 */
1618 if (path1->fp_preference != path2->fp_preference)
1619 {
1620 return (path1->fp_preference - path2->fp_preference);
1621 }
1622
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001623 return (fib_path_cmp_i(path1, path2));
1624}
1625
1626/*
1627 * fib_path_cmp
1628 *
1629 * Compare two paths for equivalence.
1630 */
1631int
1632fib_path_cmp (fib_node_index_t pi1,
1633 fib_node_index_t pi2)
1634{
1635 fib_path_t *path1, *path2;
1636
1637 path1 = fib_path_get(pi1);
1638 path2 = fib_path_get(pi2);
1639
1640 return (fib_path_cmp_i(path1, path2));
1641}
1642
1643int
1644fib_path_cmp_w_route_path (fib_node_index_t path_index,
1645 const fib_route_path_t *rpath)
1646{
1647 fib_path_t *path;
1648 int res;
1649
1650 path = fib_path_get(path_index);
1651
1652 res = 1;
1653
1654 if (path->fp_weight != rpath->frp_weight)
1655 {
1656 res = (path->fp_weight - rpath->frp_weight);
1657 }
1658 else
1659 {
1660 /*
1661 * both paths are of the same type.
1662 * consider each type and its attributes in turn.
1663 */
1664 switch (path->fp_type)
1665 {
1666 case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
1667 res = ip46_address_cmp(&path->attached_next_hop.fp_nh,
1668 &rpath->frp_addr);
1669 if (0 == res)
1670 {
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001671 res = (path->attached_next_hop.fp_interface -
1672 rpath->frp_sw_if_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001673 }
1674 break;
1675 case FIB_PATH_TYPE_ATTACHED:
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001676 res = (path->attached.fp_interface - rpath->frp_sw_if_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001677 break;
1678 case FIB_PATH_TYPE_RECURSIVE:
Neale Rannsda78f952017-05-24 09:15:43 -07001679 if (DPO_PROTO_MPLS == path->fp_nh_proto)
Neale Rannsad422ed2016-11-02 14:20:04 +00001680 {
1681 res = path->recursive.fp_nh.fp_local_label - rpath->frp_local_label;
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001682
1683 if (res == 0)
1684 {
1685 res = path->recursive.fp_nh.fp_eos - rpath->frp_eos;
1686 }
Neale Rannsad422ed2016-11-02 14:20:04 +00001687 }
1688 else
1689 {
1690 res = ip46_address_cmp(&path->recursive.fp_nh.fp_ip,
1691 &rpath->frp_addr);
1692 }
1693
1694 if (0 == res)
1695 {
1696 res = (path->recursive.fp_tbl_id - rpath->frp_fib_index);
1697 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001698 break;
Neale Rannsd792d9c2017-10-21 10:53:20 -07001699 case FIB_PATH_TYPE_BIER_FMASK:
Neale Ranns91286372017-12-05 13:24:04 -08001700 res = (path->bier_fmask.fp_bier_fmask - rpath->frp_bier_fmask);
Neale Rannsd792d9c2017-10-21 10:53:20 -07001701 break;
1702 case FIB_PATH_TYPE_BIER_IMP:
1703 res = (path->bier_imp.fp_bier_imp - rpath->frp_bier_imp);
1704 break;
1705 case FIB_PATH_TYPE_BIER_TABLE:
1706 res = bier_table_id_cmp(&path->bier_table.fp_bier_tbl,
1707 &rpath->frp_bier_tbl);
1708 break;
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001709 case FIB_PATH_TYPE_INTF_RX:
1710 res = (path->intf_rx.fp_interface - rpath->frp_sw_if_index);
1711 break;
Neale Ranns810086d2017-11-05 16:26:46 -08001712 case FIB_PATH_TYPE_UDP_ENCAP:
1713 res = (path->udp_encap.fp_udp_encap_id - rpath->frp_udp_encap_id);
1714 break;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001715 case FIB_PATH_TYPE_DEAG:
1716 res = (path->deag.fp_tbl_id - rpath->frp_fib_index);
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001717 if (0 == res)
1718 {
1719 res = (path->deag.fp_rpf_id - rpath->frp_rpf_id);
1720 }
1721 break;
Neale Rannsf068c3e2018-01-03 04:18:48 -08001722 case FIB_PATH_TYPE_DVR:
1723 res = (path->dvr.fp_interface - rpath->frp_sw_if_index);
1724 break;
Vijayabhaskar Katamreddycef5db02018-10-05 11:24:56 -07001725 case FIB_PATH_TYPE_EXCLUSIVE:
1726 res = dpo_cmp(&path->exclusive.fp_ex_dpo, &rpath->dpo);
1727 break;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001728 case FIB_PATH_TYPE_SPECIAL:
1729 case FIB_PATH_TYPE_RECEIVE:
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001730 res = 0;
1731 break;
1732 }
1733 }
1734 return (res);
1735}
1736
1737/*
1738 * fib_path_recursive_loop_detect
1739 *
1740 * A forward walk of the FIB object graph to detect for a cycle/loop. This
1741 * walk is initiated when an entry is linking to a new path list or from an old.
1742 * The entry vector passed contains all the FIB entrys that are children of this
1743 * path (it is all the entries encountered on the walk so far). If this vector
1744 * contains the entry this path resolve via, then a loop is about to form.
1745 * The loop must be allowed to form, since we need the dependencies in place
1746 * so that we can track when the loop breaks.
1747 * However, we MUST not produce a loop in the forwarding graph (else packets
1748 * would loop around the switch path until the loop breaks), so we mark recursive
1749 * paths as looped so that they do not contribute forwarding information.
1750 * By marking the path as looped, an etry such as;
1751 * X/Y
1752 * via a.a.a.a (looped)
1753 * via b.b.b.b (not looped)
1754 * can still forward using the info provided by b.b.b.b only
1755 */
1756int
1757fib_path_recursive_loop_detect (fib_node_index_t path_index,
1758 fib_node_index_t **entry_indicies)
1759{
1760 fib_path_t *path;
1761
1762 path = fib_path_get(path_index);
1763
1764 /*
1765 * the forced drop path is never looped, cos it is never resolved.
1766 */
1767 if (fib_path_is_permanent_drop(path))
1768 {
1769 return (0);
1770 }
1771
1772 switch (path->fp_type)
1773 {
1774 case FIB_PATH_TYPE_RECURSIVE:
1775 {
1776 fib_node_index_t *entry_index, *entries;
1777 int looped = 0;
1778 entries = *entry_indicies;
1779
1780 vec_foreach(entry_index, entries) {
1781 if (*entry_index == path->fp_via_fib)
1782 {
1783 /*
1784 * the entry that is about to link to this path-list (or
1785 * one of this path-list's children) is the same entry that
1786 * this recursive path resolves through. this is a cycle.
1787 * abort the walk.
1788 */
1789 looped = 1;
1790 break;
1791 }
1792 }
1793
1794 if (looped)
1795 {
1796 FIB_PATH_DBG(path, "recursive loop formed");
1797 path->fp_oper_flags |= FIB_PATH_OPER_FLAG_RECURSIVE_LOOP;
1798
Neale Rannsda78f952017-05-24 09:15:43 -07001799 dpo_copy(&path->fp_dpo, drop_dpo_get(path->fp_nh_proto));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001800 }
1801 else
1802 {
1803 /*
1804 * no loop here yet. keep forward walking the graph.
1805 */
1806 if (fib_entry_recursive_loop_detect(path->fp_via_fib, entry_indicies))
1807 {
1808 FIB_PATH_DBG(path, "recursive loop formed");
1809 path->fp_oper_flags |= FIB_PATH_OPER_FLAG_RECURSIVE_LOOP;
1810 }
1811 else
1812 {
1813 FIB_PATH_DBG(path, "recursive loop cleared");
1814 path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RECURSIVE_LOOP;
1815 }
1816 }
1817 break;
1818 }
1819 case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
1820 case FIB_PATH_TYPE_ATTACHED:
1821 case FIB_PATH_TYPE_SPECIAL:
1822 case FIB_PATH_TYPE_DEAG:
Neale Rannsf068c3e2018-01-03 04:18:48 -08001823 case FIB_PATH_TYPE_DVR:
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001824 case FIB_PATH_TYPE_RECEIVE:
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001825 case FIB_PATH_TYPE_INTF_RX:
Neale Ranns810086d2017-11-05 16:26:46 -08001826 case FIB_PATH_TYPE_UDP_ENCAP:
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001827 case FIB_PATH_TYPE_EXCLUSIVE:
Neale Rannsd792d9c2017-10-21 10:53:20 -07001828 case FIB_PATH_TYPE_BIER_FMASK:
1829 case FIB_PATH_TYPE_BIER_TABLE:
1830 case FIB_PATH_TYPE_BIER_IMP:
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001831 /*
1832 * these path types cannot be part of a loop, since they are the leaves
1833 * of the graph.
1834 */
1835 break;
1836 }
1837
1838 return (fib_path_is_looped(path_index));
1839}
1840
1841int
1842fib_path_resolve (fib_node_index_t path_index)
1843{
1844 fib_path_t *path;
1845
1846 path = fib_path_get(path_index);
1847
1848 /*
1849 * hope for the best.
1850 */
1851 path->fp_oper_flags |= FIB_PATH_OPER_FLAG_RESOLVED;
1852
1853 /*
1854 * the forced drop path resolves via the drop adj
1855 */
1856 if (fib_path_is_permanent_drop(path))
1857 {
Neale Rannsda78f952017-05-24 09:15:43 -07001858 dpo_copy(&path->fp_dpo, drop_dpo_get(path->fp_nh_proto));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001859 path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
1860 return (fib_path_is_resolved(path_index));
1861 }
1862
1863 switch (path->fp_type)
1864 {
1865 case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
1866 fib_path_attached_next_hop_set(path);
1867 break;
1868 case FIB_PATH_TYPE_ATTACHED:
Neale Rannsf068c3e2018-01-03 04:18:48 -08001869 /*
1870 * path->attached.fp_interface
1871 */
1872 if (!vnet_sw_interface_is_admin_up(vnet_get_main(),
1873 path->attached.fp_interface))
Neale Ranns6f631152017-10-03 08:20:21 -07001874 {
Neale Rannsf068c3e2018-01-03 04:18:48 -08001875 path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
Neale Ranns6f631152017-10-03 08:20:21 -07001876 }
Neale Rannsf068c3e2018-01-03 04:18:48 -08001877 dpo_set(&path->fp_dpo,
1878 DPO_ADJACENCY,
1879 path->fp_nh_proto,
1880 fib_path_attached_get_adj(path,
1881 dpo_proto_to_link(path->fp_nh_proto)));
Neale Ranns8c4611b2017-05-23 03:43:47 -07001882
Neale Rannsf068c3e2018-01-03 04:18:48 -08001883 /*
1884 * become a child of the adjacency so we receive updates
1885 * when the interface state changes
1886 */
1887 path->fp_sibling = adj_child_add(path->fp_dpo.dpoi_index,
1888 FIB_NODE_TYPE_PATH,
1889 fib_path_get_index(path));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001890 break;
1891 case FIB_PATH_TYPE_RECURSIVE:
1892 {
1893 /*
1894 * Create a RR source entry in the table for the address
1895 * that this path recurses through.
1896 * This resolve action is recursive, hence we may create
1897 * more paths in the process. more creates mean maybe realloc
1898 * of this path.
1899 */
1900 fib_node_index_t fei;
1901 fib_prefix_t pfx;
1902
1903 ASSERT(FIB_NODE_INDEX_INVALID == path->fp_via_fib);
1904
Neale Rannsda78f952017-05-24 09:15:43 -07001905 if (DPO_PROTO_MPLS == path->fp_nh_proto)
Neale Rannsad422ed2016-11-02 14:20:04 +00001906 {
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001907 fib_prefix_from_mpls_label(path->recursive.fp_nh.fp_local_label,
1908 path->recursive.fp_nh.fp_eos,
1909 &pfx);
Neale Rannsad422ed2016-11-02 14:20:04 +00001910 }
1911 else
1912 {
1913 fib_prefix_from_ip46_addr(&path->recursive.fp_nh.fp_ip, &pfx);
1914 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001915
Neale Ranns6fff24a2018-09-10 19:14:07 -07001916 fib_table_lock(path->recursive.fp_tbl_id,
1917 dpo_proto_to_fib(path->fp_nh_proto),
1918 FIB_SOURCE_RR);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001919 fei = fib_table_entry_special_add(path->recursive.fp_tbl_id,
1920 &pfx,
1921 FIB_SOURCE_RR,
Neale Rannsa0558302017-04-13 00:44:52 -07001922 FIB_ENTRY_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001923
1924 path = fib_path_get(path_index);
1925 path->fp_via_fib = fei;
1926
1927 /*
1928 * become a dependent child of the entry so the path is
1929 * informed when the forwarding for the entry changes.
1930 */
1931 path->fp_sibling = fib_entry_child_add(path->fp_via_fib,
1932 FIB_NODE_TYPE_PATH,
1933 fib_path_get_index(path));
1934
1935 /*
1936 * create and configure the IP DPO
1937 */
1938 fib_path_recursive_adj_update(
1939 path,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001940 fib_path_to_chain_type(path),
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001941 &path->fp_dpo);
1942
1943 break;
1944 }
Neale Rannsd792d9c2017-10-21 10:53:20 -07001945 case FIB_PATH_TYPE_BIER_FMASK:
1946 {
1947 /*
Neale Rannsd792d9c2017-10-21 10:53:20 -07001948 * become a dependent child of the entry so the path is
1949 * informed when the forwarding for the entry changes.
1950 */
Neale Ranns91286372017-12-05 13:24:04 -08001951 path->fp_sibling = bier_fmask_child_add(path->bier_fmask.fp_bier_fmask,
Neale Rannsd792d9c2017-10-21 10:53:20 -07001952 FIB_NODE_TYPE_PATH,
1953 fib_path_get_index(path));
1954
Neale Ranns91286372017-12-05 13:24:04 -08001955 path->fp_via_bier_fmask = path->bier_fmask.fp_bier_fmask;
Neale Rannsd792d9c2017-10-21 10:53:20 -07001956 fib_path_bier_fmask_update(path, &path->fp_dpo);
1957
1958 break;
1959 }
1960 case FIB_PATH_TYPE_BIER_IMP:
1961 bier_imp_lock(path->bier_imp.fp_bier_imp);
1962 bier_imp_contribute_forwarding(path->bier_imp.fp_bier_imp,
1963 DPO_PROTO_IP4,
1964 &path->fp_dpo);
1965 break;
1966 case FIB_PATH_TYPE_BIER_TABLE:
1967 {
1968 /*
1969 * Find/create the BIER table to link to
1970 */
1971 ASSERT(FIB_NODE_INDEX_INVALID == path->fp_via_bier_tbl);
1972
1973 path->fp_via_bier_tbl =
1974 bier_table_ecmp_create_and_lock(&path->bier_table.fp_bier_tbl);
1975
1976 bier_table_contribute_forwarding(path->fp_via_bier_tbl,
1977 &path->fp_dpo);
1978 break;
1979 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001980 case FIB_PATH_TYPE_SPECIAL:
1981 /*
1982 * Resolve via the drop
1983 */
Neale Rannsda78f952017-05-24 09:15:43 -07001984 dpo_copy(&path->fp_dpo, drop_dpo_get(path->fp_nh_proto));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001985 break;
1986 case FIB_PATH_TYPE_DEAG:
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001987 {
Neale Ranns91286372017-12-05 13:24:04 -08001988 if (DPO_PROTO_BIER == path->fp_nh_proto)
1989 {
1990 bier_disp_table_contribute_forwarding(path->deag.fp_tbl_id,
1991 &path->fp_dpo);
1992 }
1993 else
1994 {
1995 /*
1996 * Resolve via a lookup DPO.
1997 * FIXME. control plane should add routes with a table ID
1998 */
1999 lookup_input_t input;
2000 lookup_cast_t cast;
Neale Ranns054c03a2017-10-13 05:15:07 -07002001
Neale Ranns91286372017-12-05 13:24:04 -08002002 cast = (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_RPF_ID ?
2003 LOOKUP_MULTICAST :
2004 LOOKUP_UNICAST);
2005 input = (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_DEAG_SRC ?
2006 LOOKUP_INPUT_SRC_ADDR :
2007 LOOKUP_INPUT_DST_ADDR);
Neale Ranns0f26c5a2017-03-01 15:12:11 -08002008
Neale Ranns91286372017-12-05 13:24:04 -08002009 lookup_dpo_add_or_lock_w_fib_index(path->deag.fp_tbl_id,
2010 path->fp_nh_proto,
2011 cast,
2012 input,
2013 LOOKUP_TABLE_FROM_CONFIG,
2014 &path->fp_dpo);
2015 }
2016 break;
Neale Ranns0f26c5a2017-03-01 15:12:11 -08002017 }
Neale Rannsf068c3e2018-01-03 04:18:48 -08002018 case FIB_PATH_TYPE_DVR:
2019 dvr_dpo_add_or_lock(path->attached.fp_interface,
2020 path->fp_nh_proto,
2021 &path->fp_dpo);
2022 break;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002023 case FIB_PATH_TYPE_RECEIVE:
2024 /*
2025 * Resolve via a receive DPO.
2026 */
Neale Rannsda78f952017-05-24 09:15:43 -07002027 receive_dpo_add_or_lock(path->fp_nh_proto,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002028 path->receive.fp_interface,
2029 &path->receive.fp_addr,
2030 &path->fp_dpo);
2031 break;
Neale Ranns810086d2017-11-05 16:26:46 -08002032 case FIB_PATH_TYPE_UDP_ENCAP:
2033 udp_encap_lock(path->udp_encap.fp_udp_encap_id);
2034 udp_encap_contribute_forwarding(path->udp_encap.fp_udp_encap_id,
2035 path->fp_nh_proto,
2036 &path->fp_dpo);
2037 break;
Neale Ranns0f26c5a2017-03-01 15:12:11 -08002038 case FIB_PATH_TYPE_INTF_RX: {
2039 /*
2040 * Resolve via a receive DPO.
2041 */
Neale Ranns43161a82017-08-12 02:12:00 -07002042 interface_rx_dpo_add_or_lock(path->fp_nh_proto,
2043 path->intf_rx.fp_interface,
2044 &path->fp_dpo);
Neale Ranns0f26c5a2017-03-01 15:12:11 -08002045 break;
2046 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002047 case FIB_PATH_TYPE_EXCLUSIVE:
2048 /*
2049 * Resolve via the user provided DPO
2050 */
2051 dpo_copy(&path->fp_dpo, &path->exclusive.fp_ex_dpo);
2052 break;
2053 }
2054
2055 return (fib_path_is_resolved(path_index));
2056}
2057
2058u32
2059fib_path_get_resolving_interface (fib_node_index_t path_index)
2060{
2061 fib_path_t *path;
2062
2063 path = fib_path_get(path_index);
2064
2065 switch (path->fp_type)
2066 {
2067 case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
2068 return (path->attached_next_hop.fp_interface);
2069 case FIB_PATH_TYPE_ATTACHED:
2070 return (path->attached.fp_interface);
2071 case FIB_PATH_TYPE_RECEIVE:
2072 return (path->receive.fp_interface);
2073 case FIB_PATH_TYPE_RECURSIVE:
Neale Ranns08b16482017-05-13 05:52:58 -07002074 if (fib_path_is_resolved(path_index))
2075 {
2076 return (fib_entry_get_resolving_interface(path->fp_via_fib));
2077 }
2078 break;
Neale Rannsf068c3e2018-01-03 04:18:48 -08002079 case FIB_PATH_TYPE_DVR:
2080 return (path->dvr.fp_interface);
Neale Ranns0f26c5a2017-03-01 15:12:11 -08002081 case FIB_PATH_TYPE_INTF_RX:
Neale Ranns810086d2017-11-05 16:26:46 -08002082 case FIB_PATH_TYPE_UDP_ENCAP:
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002083 case FIB_PATH_TYPE_SPECIAL:
2084 case FIB_PATH_TYPE_DEAG:
2085 case FIB_PATH_TYPE_EXCLUSIVE:
Neale Rannsd792d9c2017-10-21 10:53:20 -07002086 case FIB_PATH_TYPE_BIER_FMASK:
2087 case FIB_PATH_TYPE_BIER_TABLE:
2088 case FIB_PATH_TYPE_BIER_IMP:
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002089 break;
2090 }
Neale Ranns4a6d0232018-04-24 07:45:33 -07002091 return (dpo_get_urpf(&path->fp_dpo));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002092}
2093
Neale Rannsd792d9c2017-10-21 10:53:20 -07002094index_t
2095fib_path_get_resolving_index (fib_node_index_t path_index)
2096{
2097 fib_path_t *path;
2098
2099 path = fib_path_get(path_index);
2100
2101 switch (path->fp_type)
2102 {
2103 case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
2104 case FIB_PATH_TYPE_ATTACHED:
2105 case FIB_PATH_TYPE_RECEIVE:
2106 case FIB_PATH_TYPE_INTF_RX:
2107 case FIB_PATH_TYPE_SPECIAL:
2108 case FIB_PATH_TYPE_DEAG:
Neale Rannsf068c3e2018-01-03 04:18:48 -08002109 case FIB_PATH_TYPE_DVR:
Neale Rannsd792d9c2017-10-21 10:53:20 -07002110 case FIB_PATH_TYPE_EXCLUSIVE:
2111 break;
2112 case FIB_PATH_TYPE_UDP_ENCAP:
2113 return (path->udp_encap.fp_udp_encap_id);
2114 case FIB_PATH_TYPE_RECURSIVE:
2115 return (path->fp_via_fib);
2116 case FIB_PATH_TYPE_BIER_FMASK:
Neale Ranns91286372017-12-05 13:24:04 -08002117 return (path->bier_fmask.fp_bier_fmask);
Neale Rannsd792d9c2017-10-21 10:53:20 -07002118 case FIB_PATH_TYPE_BIER_TABLE:
2119 return (path->fp_via_bier_tbl);
2120 case FIB_PATH_TYPE_BIER_IMP:
2121 return (path->bier_imp.fp_bier_imp);
2122 }
2123 return (~0);
2124}
2125
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002126adj_index_t
2127fib_path_get_adj (fib_node_index_t path_index)
2128{
2129 fib_path_t *path;
2130
2131 path = fib_path_get(path_index);
2132
2133 ASSERT(dpo_is_adj(&path->fp_dpo));
2134 if (dpo_is_adj(&path->fp_dpo))
2135 {
2136 return (path->fp_dpo.dpoi_index);
2137 }
2138 return (ADJ_INDEX_INVALID);
2139}
2140
Neale Ranns57b58602017-07-15 07:37:25 -07002141u16
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002142fib_path_get_weight (fib_node_index_t path_index)
2143{
2144 fib_path_t *path;
2145
2146 path = fib_path_get(path_index);
2147
2148 ASSERT(path);
2149
2150 return (path->fp_weight);
2151}
2152
Neale Ranns57b58602017-07-15 07:37:25 -07002153u16
2154fib_path_get_preference (fib_node_index_t path_index)
2155{
2156 fib_path_t *path;
2157
2158 path = fib_path_get(path_index);
2159
2160 ASSERT(path);
2161
2162 return (path->fp_preference);
2163}
2164
Neale Rannsd792d9c2017-10-21 10:53:20 -07002165u32
2166fib_path_get_rpf_id (fib_node_index_t path_index)
2167{
2168 fib_path_t *path;
2169
2170 path = fib_path_get(path_index);
2171
2172 ASSERT(path);
2173
2174 if (FIB_PATH_CFG_FLAG_RPF_ID & path->fp_cfg_flags)
2175 {
2176 return (path->deag.fp_rpf_id);
2177 }
2178
2179 return (~0);
2180}
2181
Neale Ranns3ee44042016-10-03 13:05:48 +01002182/**
2183 * @brief Contribute the path's adjacency to the list passed.
2184 * By calling this function over all paths, recursively, a child
2185 * can construct its full set of forwarding adjacencies, and hence its
2186 * uRPF list.
2187 */
2188void
2189fib_path_contribute_urpf (fib_node_index_t path_index,
2190 index_t urpf)
2191{
2192 fib_path_t *path;
2193
Neale Ranns3ee44042016-10-03 13:05:48 +01002194 path = fib_path_get(path_index);
2195
Neale Ranns88fc83e2017-04-05 08:11:14 -07002196 /*
2197 * resolved and unresolved paths contribute to the RPF list.
2198 */
Neale Ranns3ee44042016-10-03 13:05:48 +01002199 switch (path->fp_type)
2200 {
2201 case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
2202 fib_urpf_list_append(urpf, path->attached_next_hop.fp_interface);
2203 break;
2204
2205 case FIB_PATH_TYPE_ATTACHED:
2206 fib_urpf_list_append(urpf, path->attached.fp_interface);
2207 break;
2208
2209 case FIB_PATH_TYPE_RECURSIVE:
Neale Ranns08b16482017-05-13 05:52:58 -07002210 if (FIB_NODE_INDEX_INVALID != path->fp_via_fib &&
2211 !fib_path_is_looped(path_index))
Neale Ranns88fc83e2017-04-05 08:11:14 -07002212 {
2213 /*
2214 * there's unresolved due to constraints, and there's unresolved
Neale Ranns08b16482017-05-13 05:52:58 -07002215 * due to ain't got no via. can't do nowt w'out via.
Neale Ranns88fc83e2017-04-05 08:11:14 -07002216 */
2217 fib_entry_contribute_urpf(path->fp_via_fib, urpf);
2218 }
Neale Ranns3ee44042016-10-03 13:05:48 +01002219 break;
2220
2221 case FIB_PATH_TYPE_EXCLUSIVE:
2222 case FIB_PATH_TYPE_SPECIAL:
Andrew Yourtchenko5f3fcb92017-10-25 05:50:37 -07002223 {
2224 /*
Neale Ranns3ee44042016-10-03 13:05:48 +01002225 * these path types may link to an adj, if that's what
2226 * the clinet gave
2227 */
Andrew Yourtchenko5f3fcb92017-10-25 05:50:37 -07002228 u32 rpf_sw_if_index;
2229
2230 rpf_sw_if_index = dpo_get_urpf(&path->fp_dpo);
2231
2232 if (~0 != rpf_sw_if_index)
Neale Ranns3ee44042016-10-03 13:05:48 +01002233 {
Andrew Yourtchenko5f3fcb92017-10-25 05:50:37 -07002234 fib_urpf_list_append(urpf, rpf_sw_if_index);
Neale Ranns3ee44042016-10-03 13:05:48 +01002235 }
2236 break;
Andrew Yourtchenko5f3fcb92017-10-25 05:50:37 -07002237 }
Neale Rannsf068c3e2018-01-03 04:18:48 -08002238 case FIB_PATH_TYPE_DVR:
2239 fib_urpf_list_append(urpf, path->dvr.fp_interface);
2240 break;
Neale Ranns3ee44042016-10-03 13:05:48 +01002241 case FIB_PATH_TYPE_DEAG:
2242 case FIB_PATH_TYPE_RECEIVE:
Neale Ranns0f26c5a2017-03-01 15:12:11 -08002243 case FIB_PATH_TYPE_INTF_RX:
Neale Ranns810086d2017-11-05 16:26:46 -08002244 case FIB_PATH_TYPE_UDP_ENCAP:
Neale Rannsd792d9c2017-10-21 10:53:20 -07002245 case FIB_PATH_TYPE_BIER_FMASK:
2246 case FIB_PATH_TYPE_BIER_TABLE:
2247 case FIB_PATH_TYPE_BIER_IMP:
Neale Ranns3ee44042016-10-03 13:05:48 +01002248 /*
2249 * these path types don't link to an adj
2250 */
2251 break;
2252 }
2253}
2254
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002255void
Neale Ranns0f26c5a2017-03-01 15:12:11 -08002256fib_path_stack_mpls_disp (fib_node_index_t path_index,
2257 dpo_proto_t payload_proto,
Neale Ranns31ed7442018-02-23 05:29:09 -08002258 fib_mpls_lsp_mode_t mode,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08002259 dpo_id_t *dpo)
2260{
2261 fib_path_t *path;
2262
2263 path = fib_path_get(path_index);
2264
2265 ASSERT(path);
2266
2267 switch (path->fp_type)
2268 {
Neale Ranns62fe07c2017-10-31 12:28:22 -07002269 case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
2270 {
2271 dpo_id_t tmp = DPO_INVALID;
2272
2273 dpo_copy(&tmp, dpo);
Neale Ranns31ed7442018-02-23 05:29:09 -08002274
2275 mpls_disp_dpo_create(payload_proto, ~0, mode, &tmp, dpo);
Neale Ranns62fe07c2017-10-31 12:28:22 -07002276 dpo_reset(&tmp);
2277 break;
2278 }
Neale Ranns0f26c5a2017-03-01 15:12:11 -08002279 case FIB_PATH_TYPE_DEAG:
2280 {
2281 dpo_id_t tmp = DPO_INVALID;
2282
2283 dpo_copy(&tmp, dpo);
Neale Ranns31ed7442018-02-23 05:29:09 -08002284
2285 mpls_disp_dpo_create(payload_proto,
2286 path->deag.fp_rpf_id,
2287 mode, &tmp, dpo);
Neale Ranns0f26c5a2017-03-01 15:12:11 -08002288 dpo_reset(&tmp);
2289 break;
Neale Ranns810086d2017-11-05 16:26:46 -08002290 }
Neale Ranns0f26c5a2017-03-01 15:12:11 -08002291 case FIB_PATH_TYPE_RECEIVE:
2292 case FIB_PATH_TYPE_ATTACHED:
Neale Ranns0f26c5a2017-03-01 15:12:11 -08002293 case FIB_PATH_TYPE_RECURSIVE:
2294 case FIB_PATH_TYPE_INTF_RX:
Neale Ranns810086d2017-11-05 16:26:46 -08002295 case FIB_PATH_TYPE_UDP_ENCAP:
Neale Ranns0f26c5a2017-03-01 15:12:11 -08002296 case FIB_PATH_TYPE_EXCLUSIVE:
2297 case FIB_PATH_TYPE_SPECIAL:
Neale Rannsd792d9c2017-10-21 10:53:20 -07002298 case FIB_PATH_TYPE_BIER_FMASK:
2299 case FIB_PATH_TYPE_BIER_TABLE:
2300 case FIB_PATH_TYPE_BIER_IMP:
Neale Rannsf068c3e2018-01-03 04:18:48 -08002301 case FIB_PATH_TYPE_DVR:
Neale Ranns0f26c5a2017-03-01 15:12:11 -08002302 break;
2303 }
2304}
2305
2306void
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002307fib_path_contribute_forwarding (fib_node_index_t path_index,
2308 fib_forward_chain_type_t fct,
2309 dpo_id_t *dpo)
2310{
2311 fib_path_t *path;
2312
2313 path = fib_path_get(path_index);
2314
2315 ASSERT(path);
2316 ASSERT(FIB_FORW_CHAIN_TYPE_MPLS_EOS != fct);
2317
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002318 /*
2319 * The DPO stored in the path was created when the path was resolved.
2320 * This then represents the path's 'native' protocol; IP.
2321 * For all others will need to go find something else.
2322 */
Neale Ranns0f26c5a2017-03-01 15:12:11 -08002323 if (fib_path_to_chain_type(path) == fct)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002324 {
2325 dpo_copy(dpo, &path->fp_dpo);
2326 }
Neale Ranns5e575b12016-10-03 09:40:25 +01002327 else
2328 {
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002329 switch (path->fp_type)
2330 {
2331 case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
2332 switch (fct)
2333 {
2334 case FIB_FORW_CHAIN_TYPE_UNICAST_IP4:
2335 case FIB_FORW_CHAIN_TYPE_UNICAST_IP6:
2336 case FIB_FORW_CHAIN_TYPE_MPLS_EOS:
2337 case FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS:
Neale Ranns5e575b12016-10-03 09:40:25 +01002338 case FIB_FORW_CHAIN_TYPE_ETHERNET:
Florin Corasce1b4c72017-01-26 14:25:34 -08002339 case FIB_FORW_CHAIN_TYPE_NSH:
Neale Rannse821ab12017-06-01 07:45:05 -07002340 case FIB_FORW_CHAIN_TYPE_MCAST_IP4:
2341 case FIB_FORW_CHAIN_TYPE_MCAST_IP6:
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002342 {
2343 adj_index_t ai;
2344
2345 /*
Neale Rannsad422ed2016-11-02 14:20:04 +00002346 * get a appropriate link type adj.
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002347 */
2348 ai = fib_path_attached_next_hop_get_adj(
2349 path,
2350 fib_forw_chain_type_to_link_type(fct));
2351 dpo_set(dpo, DPO_ADJACENCY,
2352 fib_forw_chain_type_to_dpo_proto(fct), ai);
2353 adj_unlock(ai);
2354
2355 break;
2356 }
Neale Rannsd792d9c2017-10-21 10:53:20 -07002357 case FIB_FORW_CHAIN_TYPE_BIER:
2358 break;
2359 }
Neale Ranns32e1c012016-11-22 17:07:28 +00002360 break;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002361 case FIB_PATH_TYPE_RECURSIVE:
2362 switch (fct)
2363 {
2364 case FIB_FORW_CHAIN_TYPE_MPLS_EOS:
2365 case FIB_FORW_CHAIN_TYPE_UNICAST_IP4:
2366 case FIB_FORW_CHAIN_TYPE_UNICAST_IP6:
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002367 case FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS:
Neale Ranns32e1c012016-11-22 17:07:28 +00002368 case FIB_FORW_CHAIN_TYPE_MCAST_IP4:
2369 case FIB_FORW_CHAIN_TYPE_MCAST_IP6:
Neale Rannsd792d9c2017-10-21 10:53:20 -07002370 case FIB_FORW_CHAIN_TYPE_BIER:
Neale Ranns0f26c5a2017-03-01 15:12:11 -08002371 fib_path_recursive_adj_update(path, fct, dpo);
2372 break;
Neale Ranns5e575b12016-10-03 09:40:25 +01002373 case FIB_FORW_CHAIN_TYPE_ETHERNET:
Florin Corasce1b4c72017-01-26 14:25:34 -08002374 case FIB_FORW_CHAIN_TYPE_NSH:
Neale Ranns5e575b12016-10-03 09:40:25 +01002375 ASSERT(0);
2376 break;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002377 }
2378 break;
Neale Rannsd792d9c2017-10-21 10:53:20 -07002379 case FIB_PATH_TYPE_BIER_TABLE:
2380 switch (fct)
2381 {
2382 case FIB_FORW_CHAIN_TYPE_BIER:
2383 bier_table_contribute_forwarding(path->fp_via_bier_tbl, dpo);
2384 break;
2385 case FIB_FORW_CHAIN_TYPE_MPLS_EOS:
2386 case FIB_FORW_CHAIN_TYPE_UNICAST_IP4:
2387 case FIB_FORW_CHAIN_TYPE_UNICAST_IP6:
2388 case FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS:
2389 case FIB_FORW_CHAIN_TYPE_MCAST_IP4:
2390 case FIB_FORW_CHAIN_TYPE_MCAST_IP6:
2391 case FIB_FORW_CHAIN_TYPE_ETHERNET:
2392 case FIB_FORW_CHAIN_TYPE_NSH:
2393 ASSERT(0);
2394 break;
2395 }
2396 break;
2397 case FIB_PATH_TYPE_BIER_FMASK:
2398 switch (fct)
2399 {
2400 case FIB_FORW_CHAIN_TYPE_BIER:
2401 fib_path_bier_fmask_update(path, dpo);
2402 break;
2403 case FIB_FORW_CHAIN_TYPE_MPLS_EOS:
2404 case FIB_FORW_CHAIN_TYPE_UNICAST_IP4:
2405 case FIB_FORW_CHAIN_TYPE_UNICAST_IP6:
2406 case FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS:
2407 case FIB_FORW_CHAIN_TYPE_MCAST_IP4:
2408 case FIB_FORW_CHAIN_TYPE_MCAST_IP6:
2409 case FIB_FORW_CHAIN_TYPE_ETHERNET:
2410 case FIB_FORW_CHAIN_TYPE_NSH:
2411 ASSERT(0);
2412 break;
2413 }
2414 break;
2415 case FIB_PATH_TYPE_BIER_IMP:
2416 bier_imp_contribute_forwarding(path->bier_imp.fp_bier_imp,
2417 fib_forw_chain_type_to_dpo_proto(fct),
2418 dpo);
2419 break;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002420 case FIB_PATH_TYPE_DEAG:
Neale Ranns32e1c012016-11-22 17:07:28 +00002421 switch (fct)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002422 {
2423 case FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS:
2424 lookup_dpo_add_or_lock_w_table_id(MPLS_FIB_DEFAULT_TABLE_ID,
2425 DPO_PROTO_MPLS,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08002426 LOOKUP_UNICAST,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002427 LOOKUP_INPUT_DST_ADDR,
2428 LOOKUP_TABLE_FROM_CONFIG,
2429 dpo);
2430 break;
Neale Ranns0f26c5a2017-03-01 15:12:11 -08002431 case FIB_FORW_CHAIN_TYPE_MPLS_EOS:
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002432 case FIB_FORW_CHAIN_TYPE_UNICAST_IP4:
2433 case FIB_FORW_CHAIN_TYPE_UNICAST_IP6:
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002434 dpo_copy(dpo, &path->fp_dpo);
Neale Ranns32e1c012016-11-22 17:07:28 +00002435 break;
2436 case FIB_FORW_CHAIN_TYPE_MCAST_IP4:
2437 case FIB_FORW_CHAIN_TYPE_MCAST_IP6:
Neale Rannsd792d9c2017-10-21 10:53:20 -07002438 case FIB_FORW_CHAIN_TYPE_BIER:
2439 break;
Neale Ranns5e575b12016-10-03 09:40:25 +01002440 case FIB_FORW_CHAIN_TYPE_ETHERNET:
Florin Corasce1b4c72017-01-26 14:25:34 -08002441 case FIB_FORW_CHAIN_TYPE_NSH:
Neale Ranns5e575b12016-10-03 09:40:25 +01002442 ASSERT(0);
2443 break;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002444 }
2445 break;
2446 case FIB_PATH_TYPE_EXCLUSIVE:
2447 dpo_copy(dpo, &path->exclusive.fp_ex_dpo);
2448 break;
2449 case FIB_PATH_TYPE_ATTACHED:
Neale Ranns32e1c012016-11-22 17:07:28 +00002450 switch (fct)
2451 {
2452 case FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS:
2453 case FIB_FORW_CHAIN_TYPE_UNICAST_IP4:
2454 case FIB_FORW_CHAIN_TYPE_UNICAST_IP6:
2455 case FIB_FORW_CHAIN_TYPE_MPLS_EOS:
2456 case FIB_FORW_CHAIN_TYPE_ETHERNET:
Florin Corasce1b4c72017-01-26 14:25:34 -08002457 case FIB_FORW_CHAIN_TYPE_NSH:
Neale Rannsd792d9c2017-10-21 10:53:20 -07002458 case FIB_FORW_CHAIN_TYPE_BIER:
Neale Ranns8c4611b2017-05-23 03:43:47 -07002459 {
2460 adj_index_t ai;
2461
2462 /*
2463 * get a appropriate link type adj.
2464 */
2465 ai = fib_path_attached_get_adj(
2466 path,
2467 fib_forw_chain_type_to_link_type(fct));
2468 dpo_set(dpo, DPO_ADJACENCY,
2469 fib_forw_chain_type_to_dpo_proto(fct), ai);
2470 adj_unlock(ai);
2471 break;
2472 }
Neale Ranns32e1c012016-11-22 17:07:28 +00002473 case FIB_FORW_CHAIN_TYPE_MCAST_IP4:
2474 case FIB_FORW_CHAIN_TYPE_MCAST_IP6:
2475 {
2476 adj_index_t ai;
2477
2478 /*
2479 * Create the adj needed for sending IP multicast traffic
2480 */
Neale Rannsda78f952017-05-24 09:15:43 -07002481 ai = adj_mcast_add_or_lock(dpo_proto_to_fib(path->fp_nh_proto),
Neale Ranns32e1c012016-11-22 17:07:28 +00002482 fib_forw_chain_type_to_link_type(fct),
2483 path->attached.fp_interface);
Neale Ranns0f26c5a2017-03-01 15:12:11 -08002484 dpo_set(dpo, DPO_ADJACENCY,
Neale Ranns32e1c012016-11-22 17:07:28 +00002485 fib_forw_chain_type_to_dpo_proto(fct),
2486 ai);
2487 adj_unlock(ai);
2488 }
2489 break;
2490 }
2491 break;
Neale Ranns0f26c5a2017-03-01 15:12:11 -08002492 case FIB_PATH_TYPE_INTF_RX:
2493 /*
2494 * Create the adj needed for sending IP multicast traffic
2495 */
Neale Ranns43161a82017-08-12 02:12:00 -07002496 interface_rx_dpo_add_or_lock(fib_forw_chain_type_to_dpo_proto(fct),
2497 path->attached.fp_interface,
2498 dpo);
Neale Ranns0f26c5a2017-03-01 15:12:11 -08002499 break;
Neale Ranns810086d2017-11-05 16:26:46 -08002500 case FIB_PATH_TYPE_UDP_ENCAP:
2501 udp_encap_contribute_forwarding(path->udp_encap.fp_udp_encap_id,
2502 path->fp_nh_proto,
2503 dpo);
2504 break;
Neale Ranns32e1c012016-11-22 17:07:28 +00002505 case FIB_PATH_TYPE_RECEIVE:
2506 case FIB_PATH_TYPE_SPECIAL:
Neale Rannsf068c3e2018-01-03 04:18:48 -08002507 case FIB_PATH_TYPE_DVR:
Neale Ranns32e1c012016-11-22 17:07:28 +00002508 dpo_copy(dpo, &path->fp_dpo);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002509 break;
2510 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002511 }
2512}
2513
2514load_balance_path_t *
2515fib_path_append_nh_for_multipath_hash (fib_node_index_t path_index,
2516 fib_forward_chain_type_t fct,
2517 load_balance_path_t *hash_key)
2518{
2519 load_balance_path_t *mnh;
2520 fib_path_t *path;
2521
2522 path = fib_path_get(path_index);
2523
2524 ASSERT(path);
2525
Neale Rannsac64b712018-10-08 14:51:11 +00002526 vec_add2(hash_key, mnh, 1);
2527
2528 mnh->path_weight = path->fp_weight;
2529 mnh->path_index = path_index;
2530
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002531 if (fib_path_is_resolved(path_index))
2532 {
Neale Rannsac64b712018-10-08 14:51:11 +00002533 fib_path_contribute_forwarding(path_index, fct, &mnh->path_dpo);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002534 }
Neale Rannsac64b712018-10-08 14:51:11 +00002535 else
2536 {
2537 dpo_copy(&mnh->path_dpo,
2538 drop_dpo_get(fib_forw_chain_type_to_dpo_proto(fct)));
2539 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002540 return (hash_key);
2541}
2542
2543int
Neale Rannsf12a83f2017-04-18 09:09:40 -07002544fib_path_is_recursive_constrained (fib_node_index_t path_index)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002545{
2546 fib_path_t *path;
2547
2548 path = fib_path_get(path_index);
2549
Neale Rannsf12a83f2017-04-18 09:09:40 -07002550 return ((FIB_PATH_TYPE_RECURSIVE == path->fp_type) &&
2551 ((path->fp_cfg_flags & FIB_PATH_CFG_FLAG_RESOLVE_ATTACHED) ||
2552 (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_RESOLVE_HOST)));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002553}
2554
2555int
2556fib_path_is_exclusive (fib_node_index_t path_index)
2557{
2558 fib_path_t *path;
2559
2560 path = fib_path_get(path_index);
2561
2562 return (FIB_PATH_TYPE_EXCLUSIVE == path->fp_type);
2563}
2564
2565int
2566fib_path_is_deag (fib_node_index_t path_index)
2567{
2568 fib_path_t *path;
2569
2570 path = fib_path_get(path_index);
2571
2572 return (FIB_PATH_TYPE_DEAG == path->fp_type);
2573}
2574
2575int
2576fib_path_is_resolved (fib_node_index_t path_index)
2577{
2578 fib_path_t *path;
2579
2580 path = fib_path_get(path_index);
2581
2582 return (dpo_id_is_valid(&path->fp_dpo) &&
2583 (path->fp_oper_flags & FIB_PATH_OPER_FLAG_RESOLVED) &&
2584 !fib_path_is_looped(path_index) &&
2585 !fib_path_is_permanent_drop(path));
2586}
2587
2588int
2589fib_path_is_looped (fib_node_index_t path_index)
2590{
2591 fib_path_t *path;
2592
2593 path = fib_path_get(path_index);
2594
2595 return (path->fp_oper_flags & FIB_PATH_OPER_FLAG_RECURSIVE_LOOP);
2596}
2597
Neale Ranns81424992017-05-18 03:03:22 -07002598fib_path_list_walk_rc_t
Steven01b07122016-11-02 10:40:09 -07002599fib_path_encode (fib_node_index_t path_list_index,
2600 fib_node_index_t path_index,
2601 void *ctx)
2602{
2603 fib_route_path_encode_t **api_rpaths = ctx;
2604 fib_route_path_encode_t *api_rpath;
2605 fib_path_t *path;
2606
2607 path = fib_path_get(path_index);
2608 if (!path)
Neale Ranns81424992017-05-18 03:03:22 -07002609 return (FIB_PATH_LIST_WALK_CONTINUE);
Steven01b07122016-11-02 10:40:09 -07002610 vec_add2(*api_rpaths, api_rpath, 1);
2611 api_rpath->rpath.frp_weight = path->fp_weight;
Neale Ranns57b58602017-07-15 07:37:25 -07002612 api_rpath->rpath.frp_preference = path->fp_preference;
Steven01b07122016-11-02 10:40:09 -07002613 api_rpath->rpath.frp_proto = path->fp_nh_proto;
2614 api_rpath->rpath.frp_sw_if_index = ~0;
Neale Rannsde450cb2018-07-10 03:00:07 -07002615 api_rpath->rpath.frp_fib_index = 0;
Neale Rannsa161a6d2017-11-14 08:10:41 -08002616 api_rpath->dpo = path->fp_dpo;
2617
Steven01b07122016-11-02 10:40:09 -07002618 switch (path->fp_type)
2619 {
2620 case FIB_PATH_TYPE_RECEIVE:
2621 api_rpath->rpath.frp_addr = path->receive.fp_addr;
2622 api_rpath->rpath.frp_sw_if_index = path->receive.fp_interface;
2623 break;
2624 case FIB_PATH_TYPE_ATTACHED:
2625 api_rpath->rpath.frp_sw_if_index = path->attached.fp_interface;
2626 break;
2627 case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
2628 api_rpath->rpath.frp_sw_if_index = path->attached_next_hop.fp_interface;
2629 api_rpath->rpath.frp_addr = path->attached_next_hop.fp_nh;
2630 break;
Neale Rannsd792d9c2017-10-21 10:53:20 -07002631 case FIB_PATH_TYPE_BIER_FMASK:
Neale Ranns91286372017-12-05 13:24:04 -08002632 api_rpath->rpath.frp_bier_fmask = path->bier_fmask.fp_bier_fmask;
Neale Rannsd792d9c2017-10-21 10:53:20 -07002633 break;
Steven01b07122016-11-02 10:40:09 -07002634 case FIB_PATH_TYPE_SPECIAL:
2635 break;
2636 case FIB_PATH_TYPE_DEAG:
Neale Ranns7b7ba572017-10-01 12:08:10 -07002637 api_rpath->rpath.frp_fib_index = path->deag.fp_tbl_id;
Steven01b07122016-11-02 10:40:09 -07002638 break;
2639 case FIB_PATH_TYPE_RECURSIVE:
Neale Rannsad422ed2016-11-02 14:20:04 +00002640 api_rpath->rpath.frp_addr = path->recursive.fp_nh.fp_ip;
Neale Rannsde450cb2018-07-10 03:00:07 -07002641 api_rpath->rpath.frp_fib_index = path->recursive.fp_tbl_id;
Steven01b07122016-11-02 10:40:09 -07002642 break;
Neale Ranns81458422018-03-12 06:59:36 -07002643 case FIB_PATH_TYPE_DVR:
2644 api_rpath->rpath.frp_sw_if_index = path->dvr.fp_interface;
2645 api_rpath->rpath.frp_flags |= FIB_ROUTE_PATH_DVR;
2646 break;
2647 case FIB_PATH_TYPE_UDP_ENCAP:
2648 api_rpath->rpath.frp_udp_encap_id = path->udp_encap.fp_udp_encap_id;
2649 api_rpath->rpath.frp_flags |= FIB_ROUTE_PATH_UDP_ENCAP;
2650 break;
Steven01b07122016-11-02 10:40:09 -07002651 default:
2652 break;
2653 }
Neale Rannsa161a6d2017-11-14 08:10:41 -08002654
Neale Ranns81424992017-05-18 03:03:22 -07002655 return (FIB_PATH_LIST_WALK_CONTINUE);
Steven01b07122016-11-02 10:40:09 -07002656}
2657
Neale Rannsda78f952017-05-24 09:15:43 -07002658dpo_proto_t
Neale Rannsad422ed2016-11-02 14:20:04 +00002659fib_path_get_proto (fib_node_index_t path_index)
2660{
2661 fib_path_t *path;
2662
2663 path = fib_path_get(path_index);
2664
2665 return (path->fp_nh_proto);
2666}
2667
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002668void
2669fib_path_module_init (void)
2670{
2671 fib_node_register_type (FIB_NODE_TYPE_PATH, &fib_path_vft);
Neale Ranns710071b2018-09-24 12:36:26 +00002672 fib_path_logger = vlib_log_register_class ("fib", "path");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002673}
2674
2675static clib_error_t *
2676show_fib_path_command (vlib_main_t * vm,
2677 unformat_input_t * input,
2678 vlib_cli_command_t * cmd)
2679{
Neale Ranns33a7dd52016-10-07 15:14:33 +01002680 fib_node_index_t pi;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002681 fib_path_t *path;
2682
Neale Ranns33a7dd52016-10-07 15:14:33 +01002683 if (unformat (input, "%d", &pi))
2684 {
2685 /*
2686 * show one in detail
2687 */
2688 if (!pool_is_free_index(fib_path_pool, pi))
2689 {
2690 path = fib_path_get(pi);
Neale Ranns710071b2018-09-24 12:36:26 +00002691 u8 *s = format(NULL, "%U", format_fib_path, pi, 1,
2692 FIB_PATH_FORMAT_FLAGS_NONE);
Neale Ranns33a7dd52016-10-07 15:14:33 +01002693 s = format(s, "children:");
2694 s = fib_node_children_format(path->fp_node.fn_children, s);
2695 vlib_cli_output (vm, "%s", s);
2696 vec_free(s);
2697 }
2698 else
2699 {
2700 vlib_cli_output (vm, "path %d invalid", pi);
2701 }
2702 }
2703 else
2704 {
2705 vlib_cli_output (vm, "FIB Paths");
Florin Coras119dd3a2017-12-14 11:34:37 -08002706 pool_foreach_index (pi, fib_path_pool,
Neale Ranns33a7dd52016-10-07 15:14:33 +01002707 ({
Neale Ranns710071b2018-09-24 12:36:26 +00002708 vlib_cli_output (vm, "%U", format_fib_path, pi, 0,
2709 FIB_PATH_FORMAT_FLAGS_NONE);
Neale Ranns33a7dd52016-10-07 15:14:33 +01002710 }));
2711 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002712
2713 return (NULL);
2714}
2715
2716VLIB_CLI_COMMAND (show_fib_path, static) = {
2717 .path = "show fib paths",
2718 .function = show_fib_path_command,
2719 .short_help = "show fib paths",
2720};