]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_mpls.h
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / zebra / zebra_mpls.h
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Zebra MPLS Data structures and definitions
4 * Copyright (C) 2015 Cumulus Networks, Inc.
5 */
6
7 #ifndef _ZEBRA_MPLS_H
8 #define _ZEBRA_MPLS_H
9
10 #include "prefix.h"
11 #include "table.h"
12 #include "queue.h"
13 #include "hash.h"
14 #include "jhash.h"
15 #include "nexthop.h"
16 #include "vty.h"
17 #include "memory.h"
18 #include "mpls.h"
19 #include "zebra/zserv.h"
20 #include "zebra/zebra_vrf.h"
21 #include "hook.h"
22
23 #ifdef __cplusplus
24 extern "C" {
25 #endif
26
27 /* Definitions and macros. */
28
29 #define NHLFE_FAMILY(nhlfe) \
30 (((nhlfe)->nexthop->type == NEXTHOP_TYPE_IPV6 \
31 || (nhlfe)->nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) \
32 ? AF_INET6 \
33 : AF_INET)
34
35 /* Declare LSP nexthop list types */
36 PREDECL_DLIST(nhlfe_list);
37
38 /*
39 * (Outgoing) nexthop label forwarding entry
40 */
41 struct zebra_nhlfe {
42 /* Type of entry - static etc. */
43 enum lsp_types_t type;
44
45 /* Nexthop information (with outgoing label) */
46 struct nexthop *nexthop;
47
48 /* Backpointer to base entry. */
49 struct zebra_lsp *lsp;
50
51 /* Runtime info - flags, pointers etc. */
52 uint32_t flags;
53 #define NHLFE_FLAG_CHANGED (1 << 0)
54 #define NHLFE_FLAG_SELECTED (1 << 1)
55 #define NHLFE_FLAG_MULTIPATH (1 << 2)
56 #define NHLFE_FLAG_DELETED (1 << 3)
57 #define NHLFE_FLAG_INSTALLED (1 << 4)
58 #define NHLFE_FLAG_IS_BACKUP (1 << 5)
59
60 uint8_t distance;
61
62 /* Linkage for LSPs' lists */
63 struct nhlfe_list_item list;
64 };
65
66 /*
67 * Incoming label entry
68 */
69 struct zebra_ile {
70 mpls_label_t in_label;
71 };
72
73 /*
74 * Label swap entry (ile -> list of nhlfes)
75 */
76 struct zebra_lsp {
77 /* Incoming label */
78 struct zebra_ile ile;
79
80 /* List of NHLFEs, pointer to best, and num equal-cost. */
81 struct nhlfe_list_head nhlfe_list;
82
83 struct zebra_nhlfe *best_nhlfe;
84 uint32_t num_ecmp;
85
86 /* Backup nhlfes, if present. The nexthop in a primary/active nhlfe
87 * refers to its backup (if any) by index, so the order of this list
88 * is significant.
89 */
90 struct nhlfe_list_head backup_nhlfe_list;
91
92 /* Flags */
93 uint32_t flags;
94 #define LSP_FLAG_SCHEDULED (1 << 0)
95 #define LSP_FLAG_INSTALLED (1 << 1)
96 #define LSP_FLAG_CHANGED (1 << 2)
97 #define LSP_FLAG_FPM (1 << 3)
98
99 /* Address-family of NHLFE - saved here for delete. All NHLFEs */
100 /* have to be of the same AF */
101 uint8_t addr_family;
102 };
103
104 /*
105 * FEC to label binding.
106 */
107 struct zebra_fec {
108 /* FEC (prefix) */
109 struct route_node *rn;
110
111 /* In-label - either statically bound or derived from label block. */
112 mpls_label_t label;
113
114 /* Label index (into global label block), if valid */
115 uint32_t label_index;
116
117 /* Flags. */
118 uint32_t flags;
119 #define FEC_FLAG_CONFIGURED (1 << 0)
120
121 /* Clients interested in this FEC. */
122 struct list *client_list;
123 };
124
125 /* Declare typesafe list apis/macros */
126 DECLARE_DLIST(nhlfe_list, struct zebra_nhlfe, list);
127
128 /* Function declarations. */
129
130 /*
131 * Add/update global label block.
132 */
133 int zebra_mpls_label_block_add(struct zebra_vrf *zvrf, uint32_t start_label,
134 uint32_t end_label);
135
136 /*
137 * Delete global label block.
138 */
139 int zebra_mpls_label_block_del(struct zebra_vrf *vrf);
140
141 /*
142 * Display MPLS global label block configuration (VTY command handler).
143 */
144 int zebra_mpls_write_label_block_config(struct vty *vty, struct zebra_vrf *vrf);
145
146 /*
147 * Install dynamic LSP entry.
148 */
149 int zebra_mpls_lsp_install(struct zebra_vrf *zvrf, struct route_node *rn,
150 struct route_entry *re);
151
152 /*
153 * Uninstall dynamic LSP entry, if any.
154 */
155 int zebra_mpls_lsp_uninstall(struct zebra_vrf *zvrf, struct route_node *rn,
156 struct route_entry *re);
157
158 /* Add an NHLFE to an LSP, return the newly-added object */
159 struct zebra_nhlfe *
160 zebra_mpls_lsp_add_nhlfe(struct zebra_lsp *lsp, enum lsp_types_t lsp_type,
161 enum nexthop_types_t gtype, const union g_addr *gate,
162 ifindex_t ifindex, uint8_t num_labels,
163 const mpls_label_t *out_labels);
164
165 /* Add or update a backup NHLFE for an LSP; return the object */
166 struct zebra_nhlfe *zebra_mpls_lsp_add_backup_nhlfe(
167 struct zebra_lsp *lsp, enum lsp_types_t lsp_type,
168 enum nexthop_types_t gtype, const union g_addr *gate, ifindex_t ifindex,
169 uint8_t num_labels, const mpls_label_t *out_labels);
170
171 /*
172 * Add NHLFE or backup NHLFE to an LSP based on a nexthop. These just maintain
173 * the LSP and NHLFE objects; nothing is scheduled for processing.
174 * Return: the newly-added object
175 */
176 struct zebra_nhlfe *zebra_mpls_lsp_add_nh(struct zebra_lsp *lsp,
177 enum lsp_types_t lsp_type,
178 const struct nexthop *nh);
179 struct zebra_nhlfe *zebra_mpls_lsp_add_backup_nh(struct zebra_lsp *lsp,
180 enum lsp_types_t lsp_type,
181 const struct nexthop *nh);
182
183 /* Free an allocated NHLFE */
184 void zebra_mpls_nhlfe_free(struct zebra_nhlfe *nhlfe);
185
186 int zebra_mpls_fec_register(struct zebra_vrf *zvrf, struct prefix *p,
187 uint32_t label, uint32_t label_index,
188 struct zserv *client);
189
190 /*
191 * Deregistration from a client for the label binding for a FEC. The FEC
192 * itself is deleted if no other registered clients exist and there is no
193 * label bound to the FEC.
194 */
195 int zebra_mpls_fec_unregister(struct zebra_vrf *zvrf, struct prefix *p,
196 struct zserv *client);
197
198 /*
199 * Return FEC (if any) to which this label is bound.
200 * Note: Only works for per-prefix binding and when the label is not
201 * implicit-null.
202 * TODO: Currently walks entire table, can optimize later with another
203 * hash..
204 */
205 struct zebra_fec *zebra_mpls_fec_for_label(struct zebra_vrf *zvrf,
206 mpls_label_t label);
207
208 /*
209 * Inform if specified label is currently bound to a FEC or not.
210 */
211 int zebra_mpls_label_already_bound(struct zebra_vrf *zvrf, mpls_label_t label);
212
213 /*
214 * Add static FEC to label binding. If there are clients registered for this
215 * FEC, notify them. If there are labeled routes for this FEC, install the
216 * label forwarding entry.
217 */
218 int zebra_mpls_static_fec_add(struct zebra_vrf *zvrf, struct prefix *p,
219 mpls_label_t in_label);
220
221 /*
222 * Remove static FEC to label binding. If there are no clients registered
223 * for this FEC, delete the FEC; else notify clients.
224 * Note: Upon delete of static binding, if label index exists for this FEC,
225 * client may need to be updated with derived label.
226 */
227 int zebra_mpls_static_fec_del(struct zebra_vrf *zvrf, struct prefix *p);
228
229 /*
230 * Display MPLS FEC to label binding configuration (VTY command handler).
231 */
232 int zebra_mpls_write_fec_config(struct vty *vty, struct zebra_vrf *zvrf);
233
234 /*
235 * Display MPLS FEC to label binding (VTY command handler).
236 */
237 void zebra_mpls_print_fec_table(struct vty *vty, struct zebra_vrf *zvrf);
238
239 /*
240 * Display MPLS FEC to label binding for a specific FEC (VTY command handler).
241 */
242 void zebra_mpls_print_fec(struct vty *vty, struct zebra_vrf *zvrf,
243 struct prefix *p);
244
245 /*
246 * Handle zapi request to install/uninstall LSP and
247 * (optionally) FEC-To-NHLFE (FTN) bindings.
248 *
249 * mpls_zapi_labels_process -> Installs for future processing
250 * in the meta-q
251 * zebra_mpls_labels_process -> called by the meta-q
252 */
253 void mpls_zapi_labels_process(bool add_p, struct zebra_vrf *zvrf,
254 const struct zapi_labels *zl);
255 void zebra_mpls_zapi_labels_process(bool add_p, struct zebra_vrf *zvrf,
256 const struct zapi_labels *zl);
257
258 /*
259 * Uninstall all NHLFEs bound to a single FEC.
260 *
261 * mpls_ftn_uninstall -> Called to enqueue into early label processing
262 * via the metaq
263 * zebra_mpls_ftn_uninstall -> Called when we process the meta q
264 * for this item
265 */
266 void mpls_ftn_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type,
267 struct prefix *prefix, uint8_t route_type,
268 uint8_t route_instance);
269 void zebra_mpls_ftn_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type,
270 struct prefix *prefix, uint8_t route_type,
271 uint8_t route_instance);
272 /*
273 * Install/update a NHLFE for an LSP in the forwarding table. This may be
274 * a new LSP entry or a new NHLFE for an existing in-label or an update of
275 * the out-label(s) for an existing NHLFE (update case).
276 */
277 int mpls_lsp_install(struct zebra_vrf *zvrf, enum lsp_types_t type,
278 mpls_label_t in_label, uint8_t num_out_labels,
279 const mpls_label_t *out_labels, enum nexthop_types_t gtype,
280 const union g_addr *gate, ifindex_t ifindex);
281
282 /*
283 * Lookup LSP by its input label.
284 */
285 struct zebra_lsp *mpls_lsp_find(struct zebra_vrf *zvrf, mpls_label_t in_label);
286
287 /*
288 * Uninstall a particular NHLFE in the forwarding table. If this is
289 * the only NHLFE, the entire LSP forwarding entry has to be deleted.
290 */
291 int mpls_lsp_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type,
292 mpls_label_t in_label, enum nexthop_types_t gtype,
293 const union g_addr *gate, ifindex_t ifindex,
294 bool backup_p);
295
296 /*
297 * Uninstall all NHLFEs for a particular LSP forwarding entry.
298 */
299 int mpls_lsp_uninstall_all_vrf(struct zebra_vrf *zvrf, enum lsp_types_t type,
300 mpls_label_t in_label);
301
302 #if defined(HAVE_CUMULUS)
303 /*
304 * Check that the label values used in LSP creation are consistent. The
305 * main criteria is that if there is ECMP, the label operation must still
306 * be consistent - i.e., all paths either do a swap or do PHP. This is due
307 * to current HW restrictions.
308 */
309 int zebra_mpls_lsp_label_consistent(struct zebra_vrf *zvrf,
310 mpls_label_t in_label,
311 mpls_label_t out_label,
312 enum nexthop_types_t gtype,
313 union g_addr *gate, ifindex_t ifindex);
314 #endif /* HAVE_CUMULUS */
315
316 /*
317 * Add static LSP entry. This may be the first entry for this incoming label
318 * or an additional nexthop; an existing entry may also have outgoing label
319 * changed.
320 * Note: The label operation (swap or PHP) is common for the LSP entry (all
321 * NHLFEs).
322 */
323 int zebra_mpls_static_lsp_add(struct zebra_vrf *zvrf, mpls_label_t in_label,
324 mpls_label_t out_label,
325 enum nexthop_types_t gtype, union g_addr *gate,
326 ifindex_t ifindex);
327
328 /*
329 * Delete static LSP entry. This may be the delete of one particular
330 * NHLFE for this incoming label or the delete of the entire entry (i.e.,
331 * all NHLFEs).
332 * NOTE: Delete of the only NHLFE will also end up deleting the entire
333 * LSP configuration.
334 */
335 int zebra_mpls_static_lsp_del(struct zebra_vrf *zvrf, mpls_label_t in_label,
336 enum nexthop_types_t gtype, union g_addr *gate,
337 ifindex_t ifindex);
338
339 /*
340 * Process LSP update results from zebra dataplane.
341 */
342 /* Forward ref of dplane update context type */
343 struct zebra_dplane_ctx;
344
345 void zebra_mpls_lsp_dplane_result(struct zebra_dplane_ctx *ctx);
346
347 /* Process async dplane notifications. */
348 void zebra_mpls_process_dplane_notify(struct zebra_dplane_ctx *ctx);
349
350 /*
351 * Schedule all MPLS label forwarding entries for processing.
352 * Called upon changes that may affect one or more of them such as
353 * interface or nexthop state changes.
354 */
355 void zebra_mpls_lsp_schedule(struct zebra_vrf *zvrf);
356
357 /*
358 * Display MPLS label forwarding table for a specific LSP
359 * (VTY command handler).
360 */
361 void zebra_mpls_print_lsp(struct vty *vty, struct zebra_vrf *zvrf,
362 mpls_label_t label, bool use_json);
363
364 /*
365 * Display MPLS label forwarding table (VTY command handler).
366 */
367 void zebra_mpls_print_lsp_table(struct vty *vty, struct zebra_vrf *zvrf,
368 bool use_json);
369
370 /*
371 * Display MPLS LSP configuration of all static LSPs (VTY command handler).
372 */
373 int zebra_mpls_write_lsp_config(struct vty *vty, struct zebra_vrf *zvrf);
374
375 /*
376 * Called when VRF becomes inactive, cleans up information but keeps
377 * the table itself.
378 * NOTE: Currently supported only for default VRF.
379 */
380 void zebra_mpls_cleanup_tables(struct zebra_vrf *zvrf);
381
382 /*
383 * Called upon process exiting, need to delete LSP forwarding
384 * entries from the kernel.
385 * NOTE: Currently supported only for default VRF.
386 */
387 void zebra_mpls_close_tables(struct zebra_vrf *zvrf);
388
389 /*
390 * Allocate MPLS tables for this VRF.
391 * NOTE: Currently supported only for default VRF.
392 */
393 void zebra_mpls_init_tables(struct zebra_vrf *zvrf);
394
395 /*
396 * If mpls is turned on *after* FRR is brought
397 * up let's actually notice this and turn on
398 * the relevant bits to make it work.
399 */
400 void zebra_mpls_turned_on(void);
401
402 /*
403 * Global MPLS initialization.
404 */
405 void zebra_mpls_init(void);
406
407 /*
408 * MPLS VTY.
409 */
410 void zebra_mpls_vty_init(void);
411
412 /*
413 * When cleaning up a client connection ensure that there are no
414 * vrf labels that need cleaning up too
415 */
416 void zebra_mpls_client_cleanup_vrf_label(uint8_t proto);
417
418 /* Inline functions. */
419
420 /*
421 * Distance (priority) definition for LSP NHLFE.
422 */
423 static inline uint8_t lsp_distance(enum lsp_types_t type)
424 {
425 switch (type) {
426 case ZEBRA_LSP_STATIC:
427 return (route_distance(ZEBRA_ROUTE_STATIC));
428 case ZEBRA_LSP_LDP:
429 return (route_distance(ZEBRA_ROUTE_LDP));
430 case ZEBRA_LSP_BGP:
431 return (route_distance(ZEBRA_ROUTE_BGP));
432 case ZEBRA_LSP_NONE:
433 case ZEBRA_LSP_SHARP:
434 case ZEBRA_LSP_EVPN:
435 case ZEBRA_LSP_OSPF_SR:
436 case ZEBRA_LSP_ISIS_SR:
437 case ZEBRA_LSP_SRTE:
438 return 150;
439 }
440
441 /*
442 * For some reason certain compilers do not believe
443 * that all the cases have been handled. And
444 * WTF does this work differently than when I removed
445 * the default case????
446 */
447 return 150;
448 }
449
450 /*
451 * Map RIB type to LSP type. Used when labeled-routes from BGP
452 * are converted into LSPs.
453 */
454 static inline enum lsp_types_t lsp_type_from_re_type(int re_type)
455 {
456 switch (re_type) {
457 case ZEBRA_ROUTE_STATIC:
458 return ZEBRA_LSP_STATIC;
459 case ZEBRA_ROUTE_LDP:
460 return ZEBRA_LSP_LDP;
461 case ZEBRA_ROUTE_BGP:
462 return ZEBRA_LSP_BGP;
463 case ZEBRA_ROUTE_OSPF:
464 return ZEBRA_LSP_OSPF_SR;
465 case ZEBRA_ROUTE_ISIS:
466 return ZEBRA_LSP_ISIS_SR;
467 case ZEBRA_ROUTE_SHARP:
468 return ZEBRA_LSP_SHARP;
469 case ZEBRA_ROUTE_SRTE:
470 return ZEBRA_LSP_SRTE;
471 default:
472 return ZEBRA_LSP_NONE;
473 }
474 }
475
476 /*
477 * Map LSP type to RIB type.
478 */
479 static inline int re_type_from_lsp_type(enum lsp_types_t lsp_type)
480 {
481 switch (lsp_type) {
482 case ZEBRA_LSP_STATIC:
483 return ZEBRA_ROUTE_STATIC;
484 case ZEBRA_LSP_LDP:
485 return ZEBRA_ROUTE_LDP;
486 case ZEBRA_LSP_BGP:
487 case ZEBRA_LSP_EVPN:
488 return ZEBRA_ROUTE_BGP;
489 case ZEBRA_LSP_OSPF_SR:
490 return ZEBRA_ROUTE_OSPF;
491 case ZEBRA_LSP_ISIS_SR:
492 return ZEBRA_ROUTE_ISIS;
493 case ZEBRA_LSP_NONE:
494 return ZEBRA_ROUTE_KERNEL;
495 case ZEBRA_LSP_SHARP:
496 return ZEBRA_ROUTE_SHARP;
497 case ZEBRA_LSP_SRTE:
498 return ZEBRA_ROUTE_SRTE;
499 }
500
501 /*
502 * For some reason certain compilers do not believe
503 * that all the cases have been handled. And
504 * WTF does this work differently than when I removed
505 * the default case????
506 */
507 return ZEBRA_ROUTE_KERNEL;
508 }
509
510 /* NHLFE type as printable string. */
511 static inline const char *nhlfe_type2str(enum lsp_types_t lsp_type)
512 {
513 switch (lsp_type) {
514 case ZEBRA_LSP_STATIC:
515 return "Static";
516 case ZEBRA_LSP_LDP:
517 return "LDP";
518 case ZEBRA_LSP_BGP:
519 return "BGP";
520 case ZEBRA_LSP_OSPF_SR:
521 return "SR (OSPF)";
522 case ZEBRA_LSP_ISIS_SR:
523 return "SR (IS-IS)";
524 case ZEBRA_LSP_SHARP:
525 return "SHARP";
526 case ZEBRA_LSP_SRTE:
527 return "SR-TE";
528 case ZEBRA_LSP_EVPN:
529 return "EVPN";
530 case ZEBRA_LSP_NONE:
531 return "Unknown";
532 }
533
534 /*
535 * For some reason certain compilers do not believe
536 * that all the cases have been handled. And
537 * WTF does this work differently than when I removed
538 * the default case????
539 */
540 return "Unknown";
541 }
542
543 static inline void mpls_mark_lsps_for_processing(struct zebra_vrf *zvrf,
544 struct prefix *p)
545 {
546 struct route_table *table;
547 struct route_node *rn;
548 rib_dest_t *dest;
549
550 if (!zvrf)
551 return;
552
553 table = zvrf->table[family2afi(p->family)][SAFI_UNICAST];
554 if (!table)
555 return;
556
557 rn = route_node_match(table, p);
558 if (!rn)
559 return;
560
561
562 dest = rib_dest_from_rnode(rn);
563 SET_FLAG(dest->flags, RIB_DEST_UPDATE_LSPS);
564 }
565
566 static inline void mpls_unmark_lsps_for_processing(struct route_node *rn)
567 {
568 rib_dest_t *dest = rib_dest_from_rnode(rn);
569
570 UNSET_FLAG(dest->flags, RIB_DEST_UPDATE_LSPS);
571 }
572
573 static inline int mpls_should_lsps_be_processed(struct route_node *rn)
574 {
575 rib_dest_t *dest = rib_dest_from_rnode(rn);
576
577 return !!CHECK_FLAG(dest->flags, RIB_DEST_UPDATE_LSPS);
578 }
579
580 /* Global variables. */
581 extern bool mpls_enabled;
582 extern bool mpls_pw_reach_strict; /* Strict pseudowire reachability checking */
583
584 #ifdef __cplusplus
585 }
586 #endif
587
588 #endif /*_ZEBRA_MPLS_H */