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