2 * Copyright (C) 2013 Cumulus Networks, Inc.
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
30 #include "sockunion.h"
33 #include "workqueue.h"
40 #include "zebra/rib.h"
42 #include "zebra/zserv.h"
43 #include "zebra/redistribute.h"
44 #include "zebra/debug.h"
45 #include "zebra/zebra_memory.h"
46 #include "zebra/zebra_vrf.h"
47 #include "zebra/zebra_mpls.h"
49 DEFINE_MTYPE_STATIC(ZEBRA
, LSP
, "MPLS LSP object")
50 DEFINE_MTYPE_STATIC(ZEBRA
, SLSP
, "MPLS static LSP config")
51 DEFINE_MTYPE_STATIC(ZEBRA
, NHLFE
, "MPLS nexthop object")
52 DEFINE_MTYPE_STATIC(ZEBRA
, SNHLFE
, "MPLS static nexthop object")
53 DEFINE_MTYPE_STATIC(ZEBRA
, SNHLFE_IFNAME
, "MPLS static nexthop ifname")
57 /* Default rtm_table for all clients */
58 extern struct zebra_t zebrad
;
60 /* static function declarations */
64 label_cmp (const void *p1
, const void *p2
);
66 nhlfe_nexthop_active_ipv4 (zebra_nhlfe_t
*nhlfe
, struct nexthop
*nexthop
);
68 nhlfe_nexthop_active_ipv6 (zebra_nhlfe_t
*nhlfe
, struct nexthop
*nexthop
);
70 nhlfe_nexthop_active (zebra_nhlfe_t
*nhlfe
);
72 lsp_select_best_nhlfe (zebra_lsp_t
*lsp
);
74 lsp_uninstall_from_kernel (struct hash_backet
*backet
, void *ctxt
);
76 lsp_schedule (struct hash_backet
*backet
, void *ctxt
);
78 lsp_process (struct work_queue
*wq
, void *data
);
80 lsp_processq_del (struct work_queue
*wq
, void *data
);
82 lsp_processq_complete (struct work_queue
*wq
);
84 lsp_processq_add (zebra_lsp_t
*lsp
);
88 nhlfe2str (zebra_nhlfe_t
*nhlfe
, char *buf
, int size
);
90 nhlfe_nhop_match (zebra_nhlfe_t
*nhlfe
, enum nexthop_types_t gtype
,
91 union g_addr
*gate
, char *ifname
, ifindex_t ifindex
);
92 static zebra_nhlfe_t
*
93 nhlfe_find (zebra_lsp_t
*lsp
, enum lsp_types_t lsp_type
,
94 enum nexthop_types_t gtype
, union g_addr
*gate
,
95 char *ifname
, ifindex_t ifindex
);
96 static zebra_nhlfe_t
*
97 nhlfe_add (zebra_lsp_t
*lsp
, enum lsp_types_t lsp_type
,
98 enum nexthop_types_t gtype
, union g_addr
*gate
,
99 char *ifname
, ifindex_t ifindex
, mpls_label_t out_label
);
101 nhlfe_del (zebra_nhlfe_t
*snhlfe
);
103 mpls_lsp_uninstall_all (struct hash
*lsp_table
, zebra_lsp_t
*lsp
,
104 enum lsp_types_t type
);
106 mpls_static_lsp_uninstall_all (struct zebra_vrf
*zvrf
, mpls_label_t in_label
);
108 nhlfe_print (zebra_nhlfe_t
*nhlfe
, struct vty
*vty
);
110 lsp_print (zebra_lsp_t
*lsp
, void *ctxt
);
112 slsp_alloc (void *p
);
114 snhlfe_match (zebra_snhlfe_t
*snhlfe
, enum nexthop_types_t gtype
,
115 union g_addr
*gate
, char *ifname
, ifindex_t ifindex
);
116 static zebra_snhlfe_t
*
117 snhlfe_find (zebra_slsp_t
*slsp
, enum nexthop_types_t gtype
,
118 union g_addr
*gate
, char *ifname
, ifindex_t ifindex
);
119 static zebra_snhlfe_t
*
120 snhlfe_add (zebra_slsp_t
*slsp
, enum nexthop_types_t gtype
,
121 union g_addr
*gate
, char *ifname
, ifindex_t ifindex
,
122 mpls_label_t out_label
);
124 snhlfe_del (zebra_snhlfe_t
*snhlfe
);
126 snhlfe_del_all (zebra_slsp_t
*slsp
);
128 snhlfe2str (zebra_snhlfe_t
*snhlfe
, char *buf
, int size
);
130 mpls_processq_init (struct zebra_t
*zebra
);
135 /* Static functions */
138 * Hash function for label.
143 const zebra_ile_t
*ile
= p
;
145 return (jhash_1word(ile
->in_label
, 0));
149 * Compare 2 LSP hash entries based on in-label.
152 label_cmp (const void *p1
, const void *p2
)
154 const zebra_ile_t
*ile1
= p1
;
155 const zebra_ile_t
*ile2
= p2
;
157 return (ile1
->in_label
== ile2
->in_label
);
161 * Check if an IPv4 nexthop for a NHLFE is active. Update nexthop based on
163 * NOTE: Looking only for connected routes right now.
166 nhlfe_nexthop_active_ipv4 (zebra_nhlfe_t
*nhlfe
, struct nexthop
*nexthop
)
168 struct route_table
*table
;
169 struct prefix_ipv4 p
;
170 struct route_node
*rn
;
172 struct nexthop
*match_nh
;
174 table
= zebra_vrf_table (AFI_IP
, SAFI_UNICAST
, VRF_DEFAULT
);
178 /* Lookup nexthop in IPv4 routing table. */
179 memset (&p
, 0, sizeof (struct prefix_ipv4
));
181 p
.prefixlen
= IPV4_MAX_PREFIXLEN
;
182 p
.prefix
= nexthop
->gate
.ipv4
;
184 rn
= route_node_match (table
, (struct prefix
*) &p
);
188 route_unlock_node (rn
);
190 /* Locate a valid connected route. */
191 RNODE_FOREACH_RIB (rn
, match
)
193 if (CHECK_FLAG (match
->status
, RIB_ENTRY_REMOVED
) ||
194 !CHECK_FLAG (match
->flags
, ZEBRA_FLAG_SELECTED
))
197 for (match_nh
= match
->nexthop
; match_nh
; match_nh
= match_nh
->next
)
199 if (match
->type
== ZEBRA_ROUTE_CONNECT
||
200 nexthop
->ifindex
== match_nh
->ifindex
)
202 nexthop
->ifindex
= match_nh
->ifindex
;
213 * Check if an IPv6 nexthop for a NHLFE is active. Update nexthop based on
215 * NOTE: Looking only for connected routes right now.
218 nhlfe_nexthop_active_ipv6 (zebra_nhlfe_t
*nhlfe
, struct nexthop
*nexthop
)
220 struct route_table
*table
;
221 struct prefix_ipv6 p
;
222 struct route_node
*rn
;
225 table
= zebra_vrf_table (AFI_IP6
, SAFI_UNICAST
, VRF_DEFAULT
);
229 /* Lookup nexthop in IPv6 routing table. */
230 memset (&p
, 0, sizeof (struct prefix_ipv6
));
232 p
.prefixlen
= IPV6_MAX_PREFIXLEN
;
233 p
.prefix
= nexthop
->gate
.ipv6
;
235 rn
= route_node_match (table
, (struct prefix
*) &p
);
239 route_unlock_node (rn
);
241 /* Locate a valid connected route. */
242 RNODE_FOREACH_RIB (rn
, match
)
244 if ((match
->type
== ZEBRA_ROUTE_CONNECT
) &&
245 !CHECK_FLAG (match
->status
, RIB_ENTRY_REMOVED
) &&
246 CHECK_FLAG (match
->flags
, ZEBRA_FLAG_SELECTED
))
250 if (!match
|| !match
->nexthop
)
253 nexthop
->ifindex
= match
->nexthop
->ifindex
;
259 * Check the nexthop reachability for a NHLFE and return if valid (reachable)
261 * NOTE: Each NHLFE points to only 1 nexthop.
264 nhlfe_nexthop_active (zebra_nhlfe_t
*nhlfe
)
266 struct nexthop
*nexthop
;
267 struct interface
*ifp
;
269 nexthop
= nhlfe
->nexthop
;
270 if (!nexthop
) // unexpected
273 /* Check on nexthop based on type. */
274 switch (nexthop
->type
)
276 case NEXTHOP_TYPE_IPV4
:
277 case NEXTHOP_TYPE_IPV4_IFINDEX
:
278 if (nhlfe_nexthop_active_ipv4 (nhlfe
, nexthop
))
279 SET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
);
281 UNSET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
);
284 case NEXTHOP_TYPE_IPV6
:
285 if (nhlfe_nexthop_active_ipv6 (nhlfe
, nexthop
))
286 SET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
);
288 UNSET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
);
291 case NEXTHOP_TYPE_IPV6_IFINDEX
:
292 if (IN6_IS_ADDR_LINKLOCAL (&nexthop
->gate
.ipv6
))
294 ifp
= if_lookup_by_index (nexthop
->ifindex
);
295 if (ifp
&& if_is_operative(ifp
))
296 SET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
);
298 UNSET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
);
302 if (nhlfe_nexthop_active_ipv6 (nhlfe
, nexthop
))
303 SET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
);
305 UNSET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
);
313 return CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
);
317 * Walk through NHLFEs for a LSP forwarding entry, verify nexthop
318 * reachability and select the best. Multipath entries are also
319 * marked. This is invoked when an LSP scheduled for processing (due
320 * to some change) is examined.
323 lsp_select_best_nhlfe (zebra_lsp_t
*lsp
)
325 zebra_nhlfe_t
*nhlfe
;
327 struct nexthop
*nexthop
;
335 UNSET_FLAG (lsp
->flags
, LSP_FLAG_CHANGED
);
338 * First compute the best path, after checking nexthop status. We are only
339 * concerned with non-deleted NHLFEs.
341 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
)
343 /* Clear selection flags. */
344 UNSET_FLAG (nhlfe
->flags
,
345 (NHLFE_FLAG_SELECTED
| NHLFE_FLAG_MULTIPATH
));
347 if (!CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_DELETED
) &&
348 nhlfe_nexthop_active (nhlfe
))
350 if (!best
|| (nhlfe
->distance
< best
->distance
))
355 lsp
->best_nhlfe
= best
;
356 if (!lsp
->best_nhlfe
)
359 /* Mark best NHLFE as selected. */
360 SET_FLAG (lsp
->best_nhlfe
->flags
, NHLFE_FLAG_SELECTED
);
363 * If best path exists, see if there is ECMP. While doing this, note if a
364 * new (uninstalled) NHLFE has been selected, an installed entry that is
365 * still selected has a change or an installed entry is to be removed.
367 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
)
369 int nh_chg
, nh_sel
, nh_inst
;
371 nexthop
= nhlfe
->nexthop
;
372 if (!nexthop
) // unexpected
375 if (!CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_DELETED
) &&
376 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
) &&
377 (nhlfe
->distance
== lsp
->best_nhlfe
->distance
))
379 SET_FLAG (nhlfe
->flags
, NHLFE_FLAG_SELECTED
);
380 SET_FLAG (nhlfe
->flags
, NHLFE_FLAG_MULTIPATH
);
384 if (CHECK_FLAG (lsp
->flags
, LSP_FLAG_INSTALLED
) &&
387 nh_chg
= CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_CHANGED
);
388 nh_sel
= CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_SELECTED
);
389 nh_inst
= CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
);
391 if ((nh_sel
&& !nh_inst
) ||
392 (nh_sel
&& nh_inst
&& nh_chg
) ||
393 (nh_inst
&& !nh_sel
))
397 /* We have finished examining, clear changed flag. */
398 UNSET_FLAG (nhlfe
->flags
, NHLFE_FLAG_CHANGED
);
402 SET_FLAG (lsp
->flags
, LSP_FLAG_CHANGED
);
406 * Delete LSP forwarding entry from kernel, if installed. Called upon
410 lsp_uninstall_from_kernel (struct hash_backet
*backet
, void *ctxt
)
414 lsp
= (zebra_lsp_t
*) backet
->data
;
415 if (CHECK_FLAG(lsp
->flags
, LSP_FLAG_INSTALLED
))
416 kernel_del_lsp (lsp
);
420 * Schedule LSP forwarding entry for processing. Called upon changes
421 * that may impact LSPs such as nexthop / connected route changes.
424 lsp_schedule (struct hash_backet
*backet
, void *ctxt
)
428 lsp
= (zebra_lsp_t
*) backet
->data
;
429 lsp_processq_add (lsp
);
433 * Process a LSP entry that is in the queue. Recalculate best NHLFE and
434 * any multipaths and update or delete from the kernel, as needed.
436 static wq_item_status
437 lsp_process (struct work_queue
*wq
, void *data
)
440 zebra_nhlfe_t
*oldbest
, *newbest
;
441 char buf
[BUFSIZ
], buf2
[BUFSIZ
];
443 lsp
= (zebra_lsp_t
*)data
;
444 if (!lsp
) // unexpected
447 oldbest
= lsp
->best_nhlfe
;
449 /* Select best NHLFE(s) */
450 lsp_select_best_nhlfe (lsp
);
452 newbest
= lsp
->best_nhlfe
;
454 if (IS_ZEBRA_DEBUG_MPLS
)
457 nhlfe2str (oldbest
, buf
, BUFSIZ
);
459 nhlfe2str (newbest
, buf2
, BUFSIZ
);
460 zlog_debug ("Process LSP in-label %u oldbest %s newbest %s "
461 "flags 0x%x ecmp# %d",
462 lsp
->ile
.in_label
, oldbest
? buf
: "NULL",
463 newbest
? buf2
: "NULL", lsp
->flags
, lsp
->num_ecmp
);
466 if (!CHECK_FLAG (lsp
->flags
, LSP_FLAG_INSTALLED
))
468 /* Not already installed */
470 kernel_add_lsp (lsp
);
474 /* Installed, may need an update and/or delete. */
476 kernel_del_lsp (lsp
);
477 else if (CHECK_FLAG (lsp
->flags
, LSP_FLAG_CHANGED
))
478 kernel_upd_lsp (lsp
);
486 * Callback upon processing completion of a LSP forwarding entry.
489 lsp_processq_del (struct work_queue
*wq
, void *data
)
491 struct zebra_vrf
*zvrf
;
493 struct hash
*lsp_table
;
494 zebra_nhlfe_t
*nhlfe
, *nhlfe_next
;
496 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
499 lsp_table
= zvrf
->lsp_table
;
500 if (!lsp_table
) // unexpected
503 lsp
= (zebra_lsp_t
*)data
;
504 if (!lsp
) // unexpected
507 /* Clear flag, remove any NHLFEs marked for deletion. If no NHLFEs exist,
508 * delete LSP entry also.
510 UNSET_FLAG (lsp
->flags
, LSP_FLAG_SCHEDULED
);
512 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe_next
)
514 nhlfe_next
= nhlfe
->next
;
515 if (CHECK_FLAG(nhlfe
->flags
, NHLFE_FLAG_DELETED
))
519 if (!lsp
->nhlfe_list
)
521 if (IS_ZEBRA_DEBUG_MPLS
)
522 zlog_debug ("Free LSP in-label %u flags 0x%x",
523 lsp
->ile
.in_label
, lsp
->flags
);
525 lsp
= hash_release(lsp_table
, &lsp
->ile
);
527 XFREE(MTYPE_LSP
, lsp
);
532 * Callback upon finishing the processing of all scheduled
533 * LSP forwarding entries.
536 lsp_processq_complete (struct work_queue
*wq
)
538 /* Nothing to do for now. */
542 * Add LSP forwarding entry to queue for subsequent processing.
545 lsp_processq_add (zebra_lsp_t
*lsp
)
547 /* If already scheduled, exit. */
548 if (CHECK_FLAG (lsp
->flags
, LSP_FLAG_SCHEDULED
))
551 work_queue_add (zebrad
.lsp_process_q
, lsp
);
552 SET_FLAG (lsp
->flags
, LSP_FLAG_SCHEDULED
);
557 * Callback to allocate LSP forwarding table entry.
562 const zebra_ile_t
*ile
= p
;
565 lsp
= XCALLOC (MTYPE_LSP
, sizeof(zebra_lsp_t
));
568 if (IS_ZEBRA_DEBUG_MPLS
)
569 zlog_debug ("Alloc LSP in-label %u", lsp
->ile
.in_label
);
571 return ((void *)lsp
);
575 * Create printable string for NHLFE entry.
578 nhlfe2str (zebra_nhlfe_t
*nhlfe
, char *buf
, int size
)
580 struct nexthop
*nexthop
;
583 nexthop
= nhlfe
->nexthop
;
584 switch (nexthop
->type
)
586 case NEXTHOP_TYPE_IPV4
:
587 case NEXTHOP_TYPE_IPV4_IFINDEX
:
588 inet_ntop (AF_INET
, &nexthop
->gate
.ipv4
, buf
, size
);
590 case NEXTHOP_TYPE_IPV6
:
591 inet_ntop (AF_INET6
, &nexthop
->gate
.ipv6
, buf
, size
);
601 * Check if NHLFE matches with search info passed.
604 nhlfe_nhop_match (zebra_nhlfe_t
*nhlfe
, enum nexthop_types_t gtype
,
605 union g_addr
*gate
, char *ifname
, ifindex_t ifindex
)
607 struct nexthop
*nhop
;
610 nhop
= nhlfe
->nexthop
;
614 if (nhop
->type
!= gtype
)
619 case NEXTHOP_TYPE_IPV4
:
620 case NEXTHOP_TYPE_IPV4_IFINDEX
:
621 cmp
= memcmp(&(nhop
->gate
.ipv4
), &(gate
->ipv4
),
622 sizeof(struct in_addr
));
623 if (!cmp
&& nhop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
)
624 cmp
= !(nhop
->ifindex
== ifindex
);
626 case NEXTHOP_TYPE_IPV6
:
627 case NEXTHOP_TYPE_IPV6_IFINDEX
:
628 cmp
= memcmp(&(nhop
->gate
.ipv6
), &(gate
->ipv6
),
629 sizeof(struct in6_addr
));
630 if (!cmp
&& nhop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
)
631 cmp
= !(nhop
->ifindex
== ifindex
);
642 * Locate NHLFE that matches with passed info.
644 static zebra_nhlfe_t
*
645 nhlfe_find (zebra_lsp_t
*lsp
, enum lsp_types_t lsp_type
,
646 enum nexthop_types_t gtype
, union g_addr
*gate
,
647 char *ifname
, ifindex_t ifindex
)
649 zebra_nhlfe_t
*nhlfe
;
654 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
)
656 if (nhlfe
->type
!= lsp_type
)
658 if (!nhlfe_nhop_match (nhlfe
, gtype
, gate
, ifname
, ifindex
))
666 * Add NHLFE. Base entry must have been created and duplicate
669 static zebra_nhlfe_t
*
670 nhlfe_add (zebra_lsp_t
*lsp
, enum lsp_types_t lsp_type
,
671 enum nexthop_types_t gtype
, union g_addr
*gate
,
672 char *ifname
, ifindex_t ifindex
, mpls_label_t out_label
)
674 zebra_nhlfe_t
*nhlfe
;
675 struct nexthop
*nexthop
;
680 nhlfe
= XCALLOC(MTYPE_NHLFE
, sizeof(zebra_nhlfe_t
));
685 nhlfe
->type
= lsp_type
;
686 nhlfe
->distance
= lsp_distance (lsp_type
);
688 nexthop
= nexthop_new();
691 XFREE (MTYPE_NHLFE
, nhlfe
);
694 nexthop_add_labels (nexthop
, lsp_type
, 1, &out_label
);
696 nexthop
->type
= gtype
;
697 switch (nexthop
->type
)
699 case NEXTHOP_TYPE_IPV4
:
700 case NEXTHOP_TYPE_IPV4_IFINDEX
:
701 nexthop
->gate
.ipv4
= gate
->ipv4
;
703 nexthop
->ifindex
= ifindex
;
705 case NEXTHOP_TYPE_IPV6
:
706 case NEXTHOP_TYPE_IPV6_IFINDEX
:
707 nexthop
->gate
.ipv6
= gate
->ipv6
;
709 nexthop
->ifindex
= ifindex
;
712 nexthop_free(nexthop
);
713 XFREE (MTYPE_NHLFE
, nhlfe
);
718 nhlfe
->nexthop
= nexthop
;
720 lsp
->nhlfe_list
->prev
= nhlfe
;
721 nhlfe
->next
= lsp
->nhlfe_list
;
722 lsp
->nhlfe_list
= nhlfe
;
728 * Delete NHLFE. Entry must be present on list.
731 nhlfe_del (zebra_nhlfe_t
*nhlfe
)
744 nexthop_free(nhlfe
->nexthop
);
746 /* Unlink from LSP */
748 nhlfe
->next
->prev
= nhlfe
->prev
;
750 nhlfe
->prev
->next
= nhlfe
->next
;
752 lsp
->nhlfe_list
= nhlfe
->next
;
754 if (nhlfe
== lsp
->best_nhlfe
)
755 lsp
->best_nhlfe
= NULL
;
757 XFREE (MTYPE_NHLFE
, nhlfe
);
763 mpls_lsp_uninstall_all (struct hash
*lsp_table
, zebra_lsp_t
*lsp
,
764 enum lsp_types_t type
)
766 zebra_nhlfe_t
*nhlfe
, *nhlfe_next
;
767 int schedule_lsp
= 0;
770 /* Mark NHLFEs for delete or directly delete, as appropriate. */
771 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe_next
)
773 nhlfe_next
= nhlfe
->next
;
775 /* Skip non-static NHLFEs */
776 if (nhlfe
->type
!= type
)
779 if (IS_ZEBRA_DEBUG_MPLS
)
781 nhlfe2str (nhlfe
, buf
, BUFSIZ
);
782 zlog_debug ("Del LSP in-label %u type %d nexthop %s flags 0x%x",
783 lsp
->ile
.in_label
, type
, buf
, nhlfe
->flags
);
786 if (CHECK_FLAG(nhlfe
->flags
, NHLFE_FLAG_INSTALLED
))
788 UNSET_FLAG (nhlfe
->flags
, NHLFE_FLAG_CHANGED
);
789 SET_FLAG (nhlfe
->flags
, NHLFE_FLAG_DELETED
);
798 /* Queue LSP for processing, if needed, else delete. */
801 if (lsp_processq_add (lsp
))
804 else if (!lsp
->nhlfe_list
&&
805 !CHECK_FLAG (lsp
->flags
, LSP_FLAG_SCHEDULED
))
807 if (IS_ZEBRA_DEBUG_MPLS
)
808 zlog_debug ("Free LSP in-label %u flags 0x%x",
809 lsp
->ile
.in_label
, lsp
->flags
);
811 lsp
= hash_release(lsp_table
, &lsp
->ile
);
813 XFREE(MTYPE_LSP
, lsp
);
820 * Uninstall all static NHLFEs for a particular LSP forwarding entry.
821 * If no other NHLFEs exist, the entry would be deleted.
824 mpls_static_lsp_uninstall_all (struct zebra_vrf
*zvrf
, mpls_label_t in_label
)
826 struct hash
*lsp_table
;
831 lsp_table
= zvrf
->lsp_table
;
835 /* If entry is not present, exit. */
836 tmp_ile
.in_label
= in_label
;
837 lsp
= hash_lookup (lsp_table
, &tmp_ile
);
838 if (!lsp
|| !lsp
->nhlfe_list
)
841 return mpls_lsp_uninstall_all (lsp_table
, lsp
, ZEBRA_LSP_STATIC
);
845 nhlfe_json (zebra_nhlfe_t
*nhlfe
)
848 json_object
*json_nhlfe
= NULL
;
849 struct nexthop
*nexthop
= nhlfe
->nexthop
;
851 json_nhlfe
= json_object_new_object();
852 json_object_string_add(json_nhlfe
, "type", nhlfe_type2str(nhlfe
->type
));
853 json_object_int_add(json_nhlfe
, "outLabel", nexthop
->nh_label
->label
[0]);
854 json_object_int_add(json_nhlfe
, "distance", nhlfe
->distance
);
856 if (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
))
857 json_object_boolean_true_add(json_nhlfe
, "installed");
859 switch (nexthop
->type
)
861 case NEXTHOP_TYPE_IPV4
:
862 case NEXTHOP_TYPE_IPV4_IFINDEX
:
863 json_object_string_add(json_nhlfe
, "nexthop",
864 inet_ntoa (nexthop
->gate
.ipv4
));
866 case NEXTHOP_TYPE_IPV6
:
867 case NEXTHOP_TYPE_IPV6_IFINDEX
:
868 json_object_string_add(json_nhlfe
, "nexthop",
869 inet_ntop (AF_INET6
, &nexthop
->gate
.ipv6
, buf
, BUFSIZ
));
871 if (nexthop
->ifindex
)
872 json_object_string_add(json_nhlfe
, "interface", ifindex2ifname (nexthop
->ifindex
));
881 * Print the NHLFE for a LSP forwarding entry.
884 nhlfe_print (zebra_nhlfe_t
*nhlfe
, struct vty
*vty
)
886 struct nexthop
*nexthop
;
889 nexthop
= nhlfe
->nexthop
;
890 if (!nexthop
|| !nexthop
->nh_label
) // unexpected
893 vty_out(vty
, " type: %s remote label: %s distance: %d%s",
894 nhlfe_type2str(nhlfe
->type
),
895 label2str(nexthop
->nh_label
->label
[0], buf
, BUFSIZ
),
896 nhlfe
->distance
, VTY_NEWLINE
);
897 switch (nexthop
->type
)
899 case NEXTHOP_TYPE_IPV4
:
900 case NEXTHOP_TYPE_IPV4_IFINDEX
:
901 vty_out (vty
, " via %s", inet_ntoa (nexthop
->gate
.ipv4
));
902 if (nexthop
->ifindex
)
903 vty_out (vty
, " dev %s", ifindex2ifname (nexthop
->ifindex
));
905 case NEXTHOP_TYPE_IPV6
:
906 case NEXTHOP_TYPE_IPV6_IFINDEX
:
907 vty_out (vty
, " via %s",
908 inet_ntop (AF_INET6
, &nexthop
->gate
.ipv6
, buf
, BUFSIZ
));
909 if (nexthop
->ifindex
)
910 vty_out (vty
, " dev %s", ifindex2ifname (nexthop
->ifindex
));
915 vty_out(vty
, "%s", CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
) ?
916 " (installed)" : "");
917 vty_out(vty
, "%s", VTY_NEWLINE
);
921 * Print an LSP forwarding entry.
924 lsp_print (zebra_lsp_t
*lsp
, void *ctxt
)
926 zebra_nhlfe_t
*nhlfe
;
929 vty
= (struct vty
*) ctxt
;
931 vty_out(vty
, "Local label: %u%s%s",
933 CHECK_FLAG (lsp
->flags
, LSP_FLAG_INSTALLED
) ? " (installed)" : "",
936 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
)
937 nhlfe_print (nhlfe
, vty
);
941 * JSON objects for an LSP forwarding entry.
944 lsp_json (zebra_lsp_t
*lsp
)
946 zebra_nhlfe_t
*nhlfe
= NULL
;
947 json_object
*json
= json_object_new_object();
948 json_object
*json_nhlfe_list
= json_object_new_array();
950 json_object_int_add(json
, "inLabel", lsp
->ile
.in_label
);
952 if (CHECK_FLAG (lsp
->flags
, LSP_FLAG_INSTALLED
))
953 json_object_boolean_true_add(json
, "installed");
955 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
)
956 json_object_array_add(json_nhlfe_list
, nhlfe_json(nhlfe
));
958 json_object_object_add(json
, "nexthops", json_nhlfe_list
);
963 /* Return a sorted linked list of the hash contents */
965 hash_get_sorted_list (struct hash
*hash
, void *cmp
)
968 struct hash_backet
*hb
;
969 struct list
*sorted_list
= list_new();
971 sorted_list
->cmp
= (int (*)(void *, void *)) cmp
;
973 for (i
= 0; i
< hash
->size
; i
++)
974 for (hb
= hash
->index
[i
]; hb
; hb
= hb
->next
)
975 listnode_add_sort(sorted_list
, hb
->data
);
981 * Compare two LSPs based on their label values.
984 lsp_cmp (zebra_lsp_t
*lsp1
, zebra_lsp_t
*lsp2
)
986 if (lsp1
->ile
.in_label
< lsp2
->ile
.in_label
)
989 if (lsp1
->ile
.in_label
> lsp2
->ile
.in_label
)
996 * Callback to allocate static LSP.
1001 const zebra_ile_t
*ile
= p
;
1004 slsp
= XCALLOC (MTYPE_SLSP
, sizeof(zebra_slsp_t
));
1006 return ((void *)slsp
);
1010 * Compare two static LSPs based on their label values.
1013 slsp_cmp (zebra_slsp_t
*slsp1
, zebra_slsp_t
*slsp2
)
1015 if (slsp1
->ile
.in_label
< slsp2
->ile
.in_label
)
1018 if (slsp1
->ile
.in_label
> slsp2
->ile
.in_label
)
1025 * Check if static NHLFE matches with search info passed.
1028 snhlfe_match (zebra_snhlfe_t
*snhlfe
, enum nexthop_types_t gtype
,
1029 union g_addr
*gate
, char *ifname
, ifindex_t ifindex
)
1033 if (snhlfe
->gtype
!= gtype
)
1036 switch (snhlfe
->gtype
)
1038 case NEXTHOP_TYPE_IPV4
:
1039 cmp
= memcmp(&(snhlfe
->gate
.ipv4
), &(gate
->ipv4
),
1040 sizeof(struct in_addr
));
1042 case NEXTHOP_TYPE_IPV6
:
1043 case NEXTHOP_TYPE_IPV6_IFINDEX
:
1044 cmp
= memcmp(&(snhlfe
->gate
.ipv6
), &(gate
->ipv6
),
1045 sizeof(struct in6_addr
));
1046 if (!cmp
&& snhlfe
->gtype
== NEXTHOP_TYPE_IPV6_IFINDEX
)
1047 cmp
= !(snhlfe
->ifindex
== ifindex
);
1057 * Locate static NHLFE that matches with passed info.
1059 static zebra_snhlfe_t
*
1060 snhlfe_find (zebra_slsp_t
*slsp
, enum nexthop_types_t gtype
,
1061 union g_addr
*gate
, char *ifname
, ifindex_t ifindex
)
1063 zebra_snhlfe_t
*snhlfe
;
1068 for (snhlfe
= slsp
->snhlfe_list
; snhlfe
; snhlfe
= snhlfe
->next
)
1070 if (!snhlfe_match (snhlfe
, gtype
, gate
, ifname
, ifindex
))
1079 * Add static NHLFE. Base LSP config entry must have been created
1080 * and duplicate check done.
1082 static zebra_snhlfe_t
*
1083 snhlfe_add (zebra_slsp_t
*slsp
, enum nexthop_types_t gtype
,
1084 union g_addr
*gate
, char *ifname
, ifindex_t ifindex
,
1085 mpls_label_t out_label
)
1087 zebra_snhlfe_t
*snhlfe
;
1092 snhlfe
= XCALLOC(MTYPE_SNHLFE
, sizeof(zebra_snhlfe_t
));
1093 snhlfe
->slsp
= slsp
;
1094 snhlfe
->out_label
= out_label
;
1095 snhlfe
->gtype
= gtype
;
1098 case NEXTHOP_TYPE_IPV4
:
1099 snhlfe
->gate
.ipv4
= gate
->ipv4
;
1101 case NEXTHOP_TYPE_IPV6
:
1102 case NEXTHOP_TYPE_IPV6_IFINDEX
:
1103 snhlfe
->gate
.ipv6
= gate
->ipv6
;
1105 snhlfe
->ifindex
= ifindex
;
1108 XFREE (MTYPE_SNHLFE
, snhlfe
);
1112 if (slsp
->snhlfe_list
)
1113 slsp
->snhlfe_list
->prev
= snhlfe
;
1114 snhlfe
->next
= slsp
->snhlfe_list
;
1115 slsp
->snhlfe_list
= snhlfe
;
1121 * Delete static NHLFE. Entry must be present on list.
1124 snhlfe_del (zebra_snhlfe_t
*snhlfe
)
1131 slsp
= snhlfe
->slsp
;
1136 snhlfe
->next
->prev
= snhlfe
->prev
;
1138 snhlfe
->prev
->next
= snhlfe
->next
;
1140 slsp
->snhlfe_list
= snhlfe
->next
;
1142 snhlfe
->prev
= snhlfe
->next
= NULL
;
1144 XFREE (MTYPE_SNHLFE_IFNAME
, snhlfe
->ifname
);
1145 XFREE (MTYPE_SNHLFE
, snhlfe
);
1151 * Delete all static NHLFE entries for this LSP (in label).
1154 snhlfe_del_all (zebra_slsp_t
*slsp
)
1156 zebra_snhlfe_t
*snhlfe
, *snhlfe_next
;
1161 for (snhlfe
= slsp
->snhlfe_list
; snhlfe
; snhlfe
= snhlfe_next
)
1163 snhlfe_next
= snhlfe
->next
;
1164 snhlfe_del (snhlfe
);
1171 * Create printable string for NHLFE configuration.
1174 snhlfe2str (zebra_snhlfe_t
*snhlfe
, char *buf
, int size
)
1177 switch (snhlfe
->gtype
)
1179 case NEXTHOP_TYPE_IPV4
:
1180 inet_ntop (AF_INET
, &snhlfe
->gate
.ipv4
, buf
, size
);
1182 case NEXTHOP_TYPE_IPV6
:
1183 case NEXTHOP_TYPE_IPV6_IFINDEX
:
1184 inet_ntop (AF_INET6
, &snhlfe
->gate
.ipv6
, buf
, size
);
1185 if (snhlfe
->ifindex
)
1186 strcat (buf
, ifindex2ifname (snhlfe
->ifindex
));
1196 * Initialize work queue for processing changed LSPs.
1199 mpls_processq_init (struct zebra_t
*zebra
)
1201 zebra
->lsp_process_q
= work_queue_new (zebra
->master
, "LSP processing");
1202 if (!zebra
->lsp_process_q
)
1204 zlog_err ("%s: could not initialise work queue!", __func__
);
1208 zebra
->lsp_process_q
->spec
.workfunc
= &lsp_process
;
1209 zebra
->lsp_process_q
->spec
.del_item_data
= &lsp_processq_del
;
1210 zebra
->lsp_process_q
->spec
.errorfunc
= NULL
;
1211 zebra
->lsp_process_q
->spec
.completion_func
= &lsp_processq_complete
;
1212 zebra
->lsp_process_q
->spec
.max_retries
= 0;
1213 zebra
->lsp_process_q
->spec
.hold
= 10;
1218 /* Public functions */
1221 * String to label conversion, labels separated by '/'.
1224 mpls_str2label (const char *label_str
, u_int8_t
*num_labels
,
1225 mpls_label_t
*labels
)
1231 for (i
= 0; i
< MPLS_MAX_LABELS
; i
++)
1235 label
= strtoul(label_str
, &endp
, 0);
1237 /* validity checks */
1238 if (endp
== label_str
)
1241 if (!IS_MPLS_UNRESERVED_LABEL(label
))
1247 *num_labels
= i
+ 1;
1251 /* Check separator. */
1255 label_str
= endp
+ 1;
1258 /* Too many labels. */
1263 * Label to string conversion, labels in string separated by '/'.
1266 mpls_label2str (u_int8_t num_labels
, mpls_label_t
*labels
,
1270 if (num_labels
== 1)
1271 snprintf (buf
, len
, "%u", labels
[0]);
1272 else if (num_labels
== 2)
1273 snprintf (buf
, len
, "%u/%u", labels
[0], labels
[1]);
1278 * Install/uninstall a FEC-To-NHLFE (FTN) binding.
1281 mpls_ftn_update (int add
, struct zebra_vrf
*zvrf
, enum lsp_types_t type
,
1282 struct prefix
*prefix
, enum nexthop_types_t gtype
,
1283 union g_addr
*gate
, ifindex_t ifindex
, u_int8_t distance
,
1284 mpls_label_t out_label
)
1286 struct route_table
*table
;
1287 struct route_node
*rn
;
1289 struct nexthop
*nexthop
;
1292 table
= zebra_vrf_table (family2afi(prefix
->family
), SAFI_UNICAST
, zvrf_id (zvrf
));
1296 /* Lookup existing route */
1297 rn
= route_node_get (table
, prefix
);
1298 RNODE_FOREACH_RIB (rn
, rib
)
1300 if (CHECK_FLAG (rib
->status
, RIB_ENTRY_REMOVED
))
1302 if (rib
->distance
== distance
)
1309 for (nexthop
= rib
->nexthop
; nexthop
; nexthop
= nexthop
->next
)
1311 switch (nexthop
->type
)
1313 case NEXTHOP_TYPE_IPV4
:
1314 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1315 if (gtype
!= NEXTHOP_TYPE_IPV4
&& gtype
!= NEXTHOP_TYPE_IPV4_IFINDEX
)
1317 if (! IPV4_ADDR_SAME (&nexthop
->gate
.ipv4
, &gate
->ipv4
))
1319 if (nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
&&
1320 nexthop
->ifindex
!= ifindex
)
1323 case NEXTHOP_TYPE_IPV6
:
1324 case NEXTHOP_TYPE_IPV6_IFINDEX
:
1325 if (gtype
!= NEXTHOP_TYPE_IPV6
&& gtype
!= NEXTHOP_TYPE_IPV6_IFINDEX
)
1327 if (! IPV6_ADDR_SAME (&nexthop
->gate
.ipv6
, &gate
->ipv6
))
1329 if (nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
&&
1330 nexthop
->ifindex
!= ifindex
)
1337 /* nexthop not found */
1341 if (add
&& nexthop
->nh_label_type
== ZEBRA_LSP_NONE
)
1342 nexthop_add_labels (nexthop
, type
, 1, &out_label
);
1343 else if (!add
&& nexthop
->nh_label_type
== type
)
1344 nexthop_del_labels (nexthop
);
1348 SET_FLAG (rib
->status
, RIB_ENTRY_CHANGED
);
1349 SET_FLAG (rib
->status
, RIB_ENTRY_NEXTHOPS_CHANGED
);
1356 * Install/update a NHLFE for an LSP in the forwarding table. This may be
1357 * a new LSP entry or a new NHLFE for an existing in-label or an update of
1358 * the out-label for an existing NHLFE (update case).
1361 mpls_lsp_install (struct zebra_vrf
*zvrf
, enum lsp_types_t type
,
1362 mpls_label_t in_label
, mpls_label_t out_label
,
1363 enum nexthop_types_t gtype
, union g_addr
*gate
,
1364 char *ifname
, ifindex_t ifindex
)
1366 struct hash
*lsp_table
;
1367 zebra_ile_t tmp_ile
;
1369 zebra_nhlfe_t
*nhlfe
;
1373 lsp_table
= zvrf
->lsp_table
;
1377 /* If entry is present, exit. */
1378 tmp_ile
.in_label
= in_label
;
1379 lsp
= hash_get (lsp_table
, &tmp_ile
, lsp_alloc
);
1382 nhlfe
= nhlfe_find (lsp
, type
, gtype
, gate
, ifname
, ifindex
);
1385 struct nexthop
*nh
= nhlfe
->nexthop
;
1388 assert (nh
->nh_label
);
1390 /* Clear deleted flag (in case it was set) */
1391 UNSET_FLAG (nhlfe
->flags
, NHLFE_FLAG_DELETED
);
1392 if (nh
->nh_label
->label
[0] == out_label
)
1396 if (IS_ZEBRA_DEBUG_MPLS
)
1398 nhlfe2str (nhlfe
, buf
, BUFSIZ
);
1399 zlog_debug ("LSP in-label %u type %d nexthop %s "
1400 "out-label changed to %u (old %u)",
1401 in_label
, type
, buf
,
1402 out_label
, nh
->nh_label
->label
[0]);
1405 /* Update out label, trigger processing. */
1406 nh
->nh_label
->label
[0] = out_label
;
1410 /* Add LSP entry to this nexthop */
1411 nhlfe
= nhlfe_add (lsp
, type
, gtype
, gate
,
1412 ifname
, ifindex
, out_label
);
1416 if (IS_ZEBRA_DEBUG_MPLS
)
1418 nhlfe2str (nhlfe
, buf
, BUFSIZ
);
1419 zlog_debug ("Add LSP in-label %u type %d nexthop %s "
1420 "out-label %u", in_label
, type
, buf
, out_label
);
1423 lsp
->addr_family
= NHLFE_FAMILY (nhlfe
);
1426 /* Mark NHLFE, queue LSP for processing. */
1427 SET_FLAG(nhlfe
->flags
, NHLFE_FLAG_CHANGED
);
1428 if (lsp_processq_add (lsp
))
1435 * Uninstall a particular NHLFE in the forwarding table. If this is
1436 * the only NHLFE, the entire LSP forwarding entry has to be deleted.
1439 mpls_lsp_uninstall (struct zebra_vrf
*zvrf
, enum lsp_types_t type
,
1440 mpls_label_t in_label
, enum nexthop_types_t gtype
,
1441 union g_addr
*gate
, char *ifname
, ifindex_t ifindex
)
1443 struct hash
*lsp_table
;
1444 zebra_ile_t tmp_ile
;
1446 zebra_nhlfe_t
*nhlfe
;
1450 lsp_table
= zvrf
->lsp_table
;
1454 /* If entry is not present, exit. */
1455 tmp_ile
.in_label
= in_label
;
1456 lsp
= hash_lookup (lsp_table
, &tmp_ile
);
1459 nhlfe
= nhlfe_find (lsp
, type
, gtype
, gate
, ifname
, ifindex
);
1463 if (IS_ZEBRA_DEBUG_MPLS
)
1465 nhlfe2str (nhlfe
, buf
, BUFSIZ
);
1466 zlog_debug ("Del LSP in-label %u type %d nexthop %s flags 0x%x",
1467 in_label
, type
, buf
, nhlfe
->flags
);
1470 /* Mark NHLFE for delete or directly delete, as appropriate. */
1471 if (CHECK_FLAG(nhlfe
->flags
, NHLFE_FLAG_INSTALLED
))
1473 UNSET_FLAG (nhlfe
->flags
, NHLFE_FLAG_CHANGED
);
1474 SET_FLAG (nhlfe
->flags
, NHLFE_FLAG_DELETED
);
1475 if (lsp_processq_add (lsp
))
1482 /* Free LSP entry if no other NHLFEs and not scheduled. */
1483 if (!lsp
->nhlfe_list
&&
1484 !CHECK_FLAG (lsp
->flags
, LSP_FLAG_SCHEDULED
))
1486 if (IS_ZEBRA_DEBUG_MPLS
)
1487 zlog_debug ("Free LSP in-label %u flags 0x%x",
1488 lsp
->ile
.in_label
, lsp
->flags
);
1490 lsp
= hash_release(lsp_table
, &lsp
->ile
);
1492 XFREE(MTYPE_LSP
, lsp
);
1499 * Uninstall all LDP NHLFEs for a particular LSP forwarding entry.
1500 * If no other NHLFEs exist, the entry would be deleted.
1503 mpls_ldp_lsp_uninstall_all (struct hash_backet
*backet
, void *ctxt
)
1506 struct hash
*lsp_table
;
1508 lsp
= (zebra_lsp_t
*) backet
->data
;
1509 if (!lsp
|| !lsp
->nhlfe_list
)
1516 mpls_lsp_uninstall_all (lsp_table
, lsp
, ZEBRA_LSP_LDP
);
1520 * Uninstall all LDP FEC-To-NHLFE (FTN) bindings of the given address-family.
1523 mpls_ldp_ftn_uninstall_all (struct zebra_vrf
*zvrf
, int afi
)
1525 struct route_table
*table
;
1526 struct route_node
*rn
;
1528 struct nexthop
*nexthop
;
1531 /* Process routes of interested address-families. */
1532 table
= zebra_vrf_table (afi
, SAFI_UNICAST
, zvrf_id (zvrf
));
1536 for (rn
= route_top (table
); rn
; rn
= route_next (rn
))
1539 RNODE_FOREACH_RIB (rn
, rib
)
1540 for (nexthop
= rib
->nexthop
; nexthop
; nexthop
= nexthop
->next
)
1541 if (nexthop
->nh_label_type
== ZEBRA_LSP_LDP
)
1543 nexthop_del_labels (nexthop
);
1544 SET_FLAG (rib
->status
, RIB_ENTRY_CHANGED
);
1545 SET_FLAG (rib
->status
, RIB_ENTRY_NEXTHOPS_CHANGED
);
1554 #if defined(HAVE_CUMULUS)
1556 * Check that the label values used in LSP creation are consistent. The
1557 * main criteria is that if there is ECMP, the label operation must still
1558 * be consistent - i.e., all paths either do a swap or do PHP. This is due
1559 * to current HW restrictions.
1562 zebra_mpls_lsp_label_consistent (struct zebra_vrf
*zvrf
, mpls_label_t in_label
,
1563 mpls_label_t out_label
, enum nexthop_types_t gtype
,
1564 union g_addr
*gate
, char *ifname
, ifindex_t ifindex
)
1566 struct hash
*slsp_table
;
1567 zebra_ile_t tmp_ile
;
1569 zebra_snhlfe_t
*snhlfe
;
1572 slsp_table
= zvrf
->slsp_table
;
1576 /* If entry is not present, exit. */
1577 tmp_ile
.in_label
= in_label
;
1578 slsp
= hash_lookup (slsp_table
, &tmp_ile
);
1582 snhlfe
= snhlfe_find (slsp
, gtype
, gate
, ifname
, ifindex
);
1585 if (snhlfe
->out_label
== out_label
)
1588 /* If not only NHLFE, cannot allow label change. */
1589 if (snhlfe
!= slsp
->snhlfe_list
||
1595 /* If other NHLFEs exist, label operation must match. */
1596 if (slsp
->snhlfe_list
)
1600 cur_op
= (slsp
->snhlfe_list
->out_label
== MPLS_IMP_NULL_LABEL
);
1601 new_op
= (out_label
== MPLS_IMP_NULL_LABEL
);
1602 if (cur_op
!= new_op
)
1607 /* Label values are good. */
1610 #endif /* HAVE_CUMULUS */
1613 * Add static LSP entry. This may be the first entry for this incoming label
1614 * or an additional nexthop; an existing entry may also have outgoing label
1616 * Note: The label operation (swap or PHP) is common for the LSP entry (all
1620 zebra_mpls_static_lsp_add (struct zebra_vrf
*zvrf
, mpls_label_t in_label
,
1621 mpls_label_t out_label
, enum nexthop_types_t gtype
,
1622 union g_addr
*gate
, char *ifname
, ifindex_t ifindex
)
1624 struct hash
*slsp_table
;
1625 zebra_ile_t tmp_ile
;
1627 zebra_snhlfe_t
*snhlfe
;
1631 slsp_table
= zvrf
->slsp_table
;
1635 /* If entry is present, exit. */
1636 tmp_ile
.in_label
= in_label
;
1637 slsp
= hash_get (slsp_table
, &tmp_ile
, slsp_alloc
);
1640 snhlfe
= snhlfe_find (slsp
, gtype
, gate
, ifname
, ifindex
);
1643 if (snhlfe
->out_label
== out_label
)
1647 if (IS_ZEBRA_DEBUG_MPLS
)
1649 snhlfe2str (snhlfe
, buf
, BUFSIZ
);
1650 zlog_debug ("Upd static LSP in-label %u nexthop %s "
1651 "out-label %u (old %u)",
1652 in_label
, buf
, out_label
, snhlfe
->out_label
);
1654 snhlfe
->out_label
= out_label
;
1658 /* Add static LSP entry to this nexthop */
1659 snhlfe
= snhlfe_add (slsp
, gtype
, gate
, ifname
, ifindex
, out_label
);
1663 if (IS_ZEBRA_DEBUG_MPLS
)
1665 snhlfe2str (snhlfe
, buf
, BUFSIZ
);
1666 zlog_debug ("Add static LSP in-label %u nexthop %s out-label %u",
1667 in_label
, buf
, out_label
);
1671 /* (Re)Install LSP in the main table. */
1672 if (mpls_lsp_install (zvrf
, ZEBRA_LSP_STATIC
, in_label
, out_label
, gtype
,
1673 gate
, ifname
, ifindex
))
1680 * Delete static LSP entry. This may be the delete of one particular
1681 * NHLFE for this incoming label or the delete of the entire entry (i.e.,
1683 * NOTE: Delete of the only NHLFE will also end up deleting the entire
1684 * LSP configuration.
1687 zebra_mpls_static_lsp_del (struct zebra_vrf
*zvrf
, mpls_label_t in_label
,
1688 enum nexthop_types_t gtype
, union g_addr
*gate
,
1689 char *ifname
, ifindex_t ifindex
)
1691 struct hash
*slsp_table
;
1692 zebra_ile_t tmp_ile
;
1694 zebra_snhlfe_t
*snhlfe
;
1697 slsp_table
= zvrf
->slsp_table
;
1701 /* If entry is not present, exit. */
1702 tmp_ile
.in_label
= in_label
;
1703 slsp
= hash_lookup (slsp_table
, &tmp_ile
);
1707 /* Is it delete of entire LSP or a specific NHLFE? */
1708 if (gtype
== NEXTHOP_TYPE_BLACKHOLE
)
1710 if (IS_ZEBRA_DEBUG_MPLS
)
1711 zlog_debug ("Del static LSP in-label %u", in_label
);
1713 /* Uninstall entire LSP from the main table. */
1714 mpls_static_lsp_uninstall_all (zvrf
, in_label
);
1716 /* Delete all static NHLFEs */
1717 snhlfe_del_all (slsp
);
1721 /* Find specific NHLFE, exit if not found. */
1722 snhlfe
= snhlfe_find (slsp
, gtype
, gate
, ifname
, ifindex
);
1726 if (IS_ZEBRA_DEBUG_MPLS
)
1729 snhlfe2str (snhlfe
, buf
, BUFSIZ
);
1730 zlog_debug ("Del static LSP in-label %u nexthop %s",
1734 /* Uninstall LSP from the main table. */
1735 mpls_lsp_uninstall (zvrf
, ZEBRA_LSP_STATIC
, in_label
, gtype
, gate
,
1738 /* Delete static LSP NHLFE */
1739 snhlfe_del (snhlfe
);
1742 /* Remove entire static LSP entry if no NHLFE - valid in either case above. */
1743 if (!slsp
->snhlfe_list
)
1745 slsp
= hash_release(slsp_table
, &tmp_ile
);
1747 XFREE(MTYPE_SLSP
, slsp
);
1754 * Schedule all MPLS label forwarding entries for processing.
1755 * Called upon changes that may affect one or more of them such as
1756 * interface or nexthop state changes.
1759 zebra_mpls_lsp_schedule (struct zebra_vrf
*zvrf
)
1763 hash_iterate(zvrf
->lsp_table
, lsp_schedule
, NULL
);
1767 * Display MPLS label forwarding table for a specific LSP
1768 * (VTY command handler).
1771 zebra_mpls_print_lsp (struct vty
*vty
, struct zebra_vrf
*zvrf
, mpls_label_t label
,
1774 struct hash
*lsp_table
;
1776 zebra_ile_t tmp_ile
;
1777 json_object
*json
= NULL
;
1780 lsp_table
= zvrf
->lsp_table
;
1784 /* If entry is not present, exit. */
1785 tmp_ile
.in_label
= label
;
1786 lsp
= hash_lookup (lsp_table
, &tmp_ile
);
1792 json
= lsp_json(lsp
);
1793 vty_out (vty
, "%s%s", json_object_to_json_string_ext(json
, JSON_C_TO_STRING_PRETTY
), VTY_NEWLINE
);
1794 json_object_free(json
);
1797 lsp_print (lsp
, (void *)vty
);
1801 * Display MPLS label forwarding table (VTY command handler).
1804 zebra_mpls_print_lsp_table (struct vty
*vty
, struct zebra_vrf
*zvrf
,
1808 json_object
*json
= NULL
;
1809 zebra_lsp_t
*lsp
= NULL
;
1810 zebra_nhlfe_t
*nhlfe
= NULL
;
1811 struct nexthop
*nexthop
= NULL
;
1812 struct listnode
*node
= NULL
;
1813 struct list
*lsp_list
= hash_get_sorted_list(zvrf
->lsp_table
, lsp_cmp
);
1817 json
= json_object_new_object();
1819 for (ALL_LIST_ELEMENTS_RO(lsp_list
, node
, lsp
))
1820 json_object_object_add(json
, label2str(lsp
->ile
.in_label
, buf
, BUFSIZ
),
1823 vty_out (vty
, "%s%s", json_object_to_json_string_ext(json
, JSON_C_TO_STRING_PRETTY
), VTY_NEWLINE
);
1824 json_object_free(json
);
1828 vty_out (vty
, " Inbound Outbound%s", VTY_NEWLINE
);
1829 vty_out (vty
, " Label Type Nexthop Label%s", VTY_NEWLINE
);
1830 vty_out (vty
, "-------- ------- --------------- --------%s", VTY_NEWLINE
);
1832 for (ALL_LIST_ELEMENTS_RO(lsp_list
, node
, lsp
))
1834 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
)
1836 vty_out (vty
, "%8d %7s ", lsp
->ile
.in_label
, nhlfe_type2str(nhlfe
->type
));
1837 nexthop
= nhlfe
->nexthop
;
1839 switch (nexthop
->type
)
1841 case NEXTHOP_TYPE_IPV4
:
1842 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1843 vty_out (vty
, "%15s", inet_ntoa (nexthop
->gate
.ipv4
));
1845 case NEXTHOP_TYPE_IPV6
:
1846 case NEXTHOP_TYPE_IPV6_IFINDEX
:
1847 vty_out (vty
, "%15s", inet_ntop (AF_INET6
, &nexthop
->gate
.ipv6
, buf
, BUFSIZ
));
1853 vty_out (vty
, " %8d%s", nexthop
->nh_label
->label
[0], VTY_NEWLINE
);
1857 vty_out (vty
, "%s", VTY_NEWLINE
);
1860 list_delete (lsp_list
);
1864 * Display MPLS LSP configuration of all static LSPs (VTY command handler).
1867 zebra_mpls_write_lsp_config (struct vty
*vty
, struct zebra_vrf
*zvrf
)
1870 zebra_snhlfe_t
*snhlfe
;
1871 struct listnode
*node
;
1872 struct list
*slsp_list
= hash_get_sorted_list(zvrf
->slsp_table
, slsp_cmp
);
1874 for (ALL_LIST_ELEMENTS_RO(slsp_list
, node
, slsp
))
1876 for (snhlfe
= slsp
->snhlfe_list
; snhlfe
; snhlfe
= snhlfe
->next
)
1878 char buf
[INET6_ADDRSTRLEN
];
1881 snhlfe2str (snhlfe
, buf
, BUFSIZ
);
1882 switch (snhlfe
->out_label
) {
1883 case MPLS_V4_EXP_NULL_LABEL
:
1884 case MPLS_V6_EXP_NULL_LABEL
:
1885 strlcpy(lstr
, "explicit-null", sizeof(lstr
));
1887 case MPLS_IMP_NULL_LABEL
:
1888 strlcpy(lstr
, "implicit-null", sizeof(lstr
));
1891 sprintf(lstr
, "%u", snhlfe
->out_label
);
1895 vty_out (vty
, "mpls lsp %u %s %s%s",
1896 slsp
->ile
.in_label
, buf
, lstr
, VTY_NEWLINE
);
1900 list_delete (slsp_list
);
1901 return (zvrf
->slsp_table
->count
? 1 : 0);
1905 * Called upon process exiting, need to delete LSP forwarding
1906 * entries from the kernel.
1907 * NOTE: Currently supported only for default VRF.
1910 zebra_mpls_close_tables (struct zebra_vrf
*zvrf
)
1912 hash_iterate(zvrf
->lsp_table
, lsp_uninstall_from_kernel
, NULL
);
1913 hash_clean(zvrf
->lsp_table
, NULL
);
1914 hash_free(zvrf
->lsp_table
);
1915 hash_clean(zvrf
->slsp_table
, NULL
);
1916 hash_free(zvrf
->slsp_table
);
1920 * Allocate MPLS tables for this VRF and do other initialization.
1921 * NOTE: Currently supported only for default VRF.
1924 zebra_mpls_init_tables (struct zebra_vrf
*zvrf
)
1928 zvrf
->slsp_table
= hash_create(label_hash
, label_cmp
);
1929 zvrf
->lsp_table
= hash_create(label_hash
, label_cmp
);
1930 zvrf
->mpls_flags
= 0;
1934 * Global MPLS initialization.
1937 zebra_mpls_init (void)
1939 if (mpls_kernel_init () < 0)
1941 zlog_warn ("Disabling MPLS support (no kernel support)");
1946 mpls_processq_init (&zebrad
);