diff options
Diffstat (limited to 'zebra/zebra_mpls.c')
| -rw-r--r-- | zebra/zebra_mpls.c | 2849 |
1 files changed, 1373 insertions, 1476 deletions
diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c index ba500cac27..7e74edf333 100644 --- a/zebra/zebra_mpls.c +++ b/zebra/zebra_mpls.c @@ -46,11 +46,11 @@ #include "zebra/zebra_vrf.h" #include "zebra/zebra_mpls.h" -DEFINE_MTYPE_STATIC(ZEBRA, LSP, "MPLS LSP object") -DEFINE_MTYPE_STATIC(ZEBRA, SLSP, "MPLS static LSP config") -DEFINE_MTYPE_STATIC(ZEBRA, NHLFE, "MPLS nexthop object") -DEFINE_MTYPE_STATIC(ZEBRA, SNHLFE, "MPLS static nexthop object") -DEFINE_MTYPE_STATIC(ZEBRA, SNHLFE_IFNAME, "MPLS static nexthop ifname") +DEFINE_MTYPE_STATIC(ZEBRA, LSP, "MPLS LSP object") +DEFINE_MTYPE_STATIC(ZEBRA, SLSP, "MPLS static LSP config") +DEFINE_MTYPE_STATIC(ZEBRA, NHLFE, "MPLS nexthop object") +DEFINE_MTYPE_STATIC(ZEBRA, SNHLFE, "MPLS static nexthop object") +DEFINE_MTYPE_STATIC(ZEBRA, SNHLFE_IFNAME, "MPLS static nexthop ifname") int mpls_enabled; @@ -58,78 +58,54 @@ int mpls_enabled; extern struct zebra_t zebrad; /* static function declarations */ -static unsigned int -label_hash (void *p); -static int -label_cmp (const void *p1, const void *p2); -static int -nhlfe_nexthop_active_ipv4 (zebra_nhlfe_t *nhlfe, struct nexthop *nexthop); -static int -nhlfe_nexthop_active_ipv6 (zebra_nhlfe_t *nhlfe, struct nexthop *nexthop); -static int -nhlfe_nexthop_active (zebra_nhlfe_t *nhlfe); -static void -lsp_select_best_nhlfe (zebra_lsp_t *lsp); -static void -lsp_uninstall_from_kernel (struct hash_backet *backet, void *ctxt); -static void -lsp_schedule (struct hash_backet *backet, void *ctxt); -static wq_item_status -lsp_process (struct work_queue *wq, void *data); -static void -lsp_processq_del (struct work_queue *wq, void *data); -static void -lsp_processq_complete (struct work_queue *wq); -static int -lsp_processq_add (zebra_lsp_t *lsp); -static void * -lsp_alloc (void *p); -static char * -nhlfe2str (zebra_nhlfe_t *nhlfe, char *buf, int size); -static int -nhlfe_nhop_match (zebra_nhlfe_t *nhlfe, enum nexthop_types_t gtype, - union g_addr *gate, char *ifname, ifindex_t ifindex); -static zebra_nhlfe_t * -nhlfe_find (zebra_lsp_t *lsp, enum lsp_types_t lsp_type, - enum nexthop_types_t gtype, union g_addr *gate, - char *ifname, ifindex_t ifindex); -static zebra_nhlfe_t * -nhlfe_add (zebra_lsp_t *lsp, enum lsp_types_t lsp_type, - enum nexthop_types_t gtype, union g_addr *gate, - char *ifname, ifindex_t ifindex, mpls_label_t out_label); -static int -nhlfe_del (zebra_nhlfe_t *snhlfe); -static int -mpls_lsp_uninstall_all (struct hash *lsp_table, zebra_lsp_t *lsp, - enum lsp_types_t type); -static int -mpls_static_lsp_uninstall_all (struct zebra_vrf *zvrf, mpls_label_t in_label); -static void -nhlfe_print (zebra_nhlfe_t *nhlfe, struct vty *vty); -static void -lsp_print (zebra_lsp_t *lsp, void *ctxt); -static void * -slsp_alloc (void *p); -static int -snhlfe_match (zebra_snhlfe_t *snhlfe, enum nexthop_types_t gtype, - union g_addr *gate, char *ifname, ifindex_t ifindex); -static zebra_snhlfe_t * -snhlfe_find (zebra_slsp_t *slsp, enum nexthop_types_t gtype, - union g_addr *gate, char *ifname, ifindex_t ifindex); -static zebra_snhlfe_t * -snhlfe_add (zebra_slsp_t *slsp, enum nexthop_types_t gtype, - union g_addr *gate, char *ifname, ifindex_t ifindex, - mpls_label_t out_label); -static int -snhlfe_del (zebra_snhlfe_t *snhlfe); -static int -snhlfe_del_all (zebra_slsp_t *slsp); -static char * -snhlfe2str (zebra_snhlfe_t *snhlfe, char *buf, int size); -static void -mpls_processq_init (struct zebra_t *zebra); - - +static unsigned int label_hash(void *p); +static int label_cmp(const void *p1, const void *p2); +static int nhlfe_nexthop_active_ipv4(zebra_nhlfe_t *nhlfe, + struct nexthop *nexthop); +static int nhlfe_nexthop_active_ipv6(zebra_nhlfe_t *nhlfe, + struct nexthop *nexthop); +static int nhlfe_nexthop_active(zebra_nhlfe_t *nhlfe); +static void lsp_select_best_nhlfe(zebra_lsp_t *lsp); +static void lsp_uninstall_from_kernel(struct hash_backet *backet, void *ctxt); +static void lsp_schedule(struct hash_backet *backet, void *ctxt); +static wq_item_status lsp_process(struct work_queue *wq, void *data); +static void lsp_processq_del(struct work_queue *wq, void *data); +static void lsp_processq_complete(struct work_queue *wq); +static int lsp_processq_add(zebra_lsp_t *lsp); +static void *lsp_alloc(void *p); +static char *nhlfe2str(zebra_nhlfe_t *nhlfe, char *buf, int size); +static int nhlfe_nhop_match(zebra_nhlfe_t *nhlfe, enum nexthop_types_t gtype, + union g_addr *gate, char *ifname, + ifindex_t ifindex); +static zebra_nhlfe_t *nhlfe_find(zebra_lsp_t *lsp, enum lsp_types_t lsp_type, + enum nexthop_types_t gtype, union g_addr *gate, + char *ifname, ifindex_t ifindex); +static zebra_nhlfe_t *nhlfe_add(zebra_lsp_t *lsp, enum lsp_types_t lsp_type, + enum nexthop_types_t gtype, union g_addr *gate, + char *ifname, ifindex_t ifindex, + mpls_label_t out_label); +static int nhlfe_del(zebra_nhlfe_t *snhlfe); +static int mpls_lsp_uninstall_all(struct hash *lsp_table, zebra_lsp_t *lsp, + enum lsp_types_t type); +static int mpls_static_lsp_uninstall_all(struct zebra_vrf *zvrf, + mpls_label_t in_label); +static void nhlfe_print(zebra_nhlfe_t *nhlfe, struct vty *vty); +static void lsp_print(zebra_lsp_t *lsp, void *ctxt); +static void *slsp_alloc(void *p); +static int snhlfe_match(zebra_snhlfe_t *snhlfe, enum nexthop_types_t gtype, + union g_addr *gate, char *ifname, ifindex_t ifindex); +static zebra_snhlfe_t *snhlfe_find(zebra_slsp_t *slsp, + enum nexthop_types_t gtype, + union g_addr *gate, char *ifname, + ifindex_t ifindex); +static zebra_snhlfe_t *snhlfe_add(zebra_slsp_t *slsp, + enum nexthop_types_t gtype, + union g_addr *gate, char *ifname, + ifindex_t ifindex, mpls_label_t out_label); +static int snhlfe_del(zebra_snhlfe_t *snhlfe); +static int snhlfe_del_all(zebra_slsp_t *slsp); +static char *snhlfe2str(zebra_snhlfe_t *snhlfe, char *buf, int size); +static void mpls_processq_init(struct zebra_t *zebra); /* Static functions */ @@ -137,24 +113,22 @@ mpls_processq_init (struct zebra_t *zebra); /* * Hash function for label. */ -static unsigned int -label_hash (void *p) +static unsigned int label_hash(void *p) { - const zebra_ile_t *ile = p; + const zebra_ile_t *ile = p; - return (jhash_1word(ile->in_label, 0)); + return (jhash_1word(ile->in_label, 0)); } /* * Compare 2 LSP hash entries based on in-label. */ -static int -label_cmp (const void *p1, const void *p2) +static int label_cmp(const void *p1, const void *p2) { - const zebra_ile_t *ile1 = p1; - const zebra_ile_t *ile2 = p2; + const zebra_ile_t *ile1 = p1; + const zebra_ile_t *ile2 = p2; - return (ile1->in_label == ile2->in_label); + return (ile1->in_label == ile2->in_label); } /* @@ -162,50 +136,49 @@ label_cmp (const void *p1, const void *p2) * the passed flag. * NOTE: Looking only for connected routes right now. */ -static int -nhlfe_nexthop_active_ipv4 (zebra_nhlfe_t *nhlfe, struct nexthop *nexthop) +static int nhlfe_nexthop_active_ipv4(zebra_nhlfe_t *nhlfe, + struct nexthop *nexthop) { - struct route_table *table; - struct prefix_ipv4 p; - struct route_node *rn; - struct rib *match; - struct nexthop *match_nh; - - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); - if (!table) - return 0; - - /* Lookup nexthop in IPv4 routing table. */ - memset (&p, 0, sizeof (struct prefix_ipv4)); - p.family = AF_INET; - p.prefixlen = IPV4_MAX_PREFIXLEN; - p.prefix = nexthop->gate.ipv4; - - rn = route_node_match (table, (struct prefix *) &p); - if (!rn) - return 0; - - route_unlock_node (rn); - - /* Locate a valid connected route. */ - RNODE_FOREACH_RIB (rn, match) - { - if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED) || - !CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED)) - continue; - - for (match_nh = match->nexthop; match_nh; match_nh = match_nh->next) + struct route_table *table; + struct prefix_ipv4 p; + struct route_node *rn; + struct rib *match; + struct nexthop *match_nh; + + table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, VRF_DEFAULT); + if (!table) + return 0; + + /* Lookup nexthop in IPv4 routing table. */ + memset(&p, 0, sizeof(struct prefix_ipv4)); + p.family = AF_INET; + p.prefixlen = IPV4_MAX_PREFIXLEN; + p.prefix = nexthop->gate.ipv4; + + rn = route_node_match(table, (struct prefix *)&p); + if (!rn) + return 0; + + route_unlock_node(rn); + + /* Locate a valid connected route. */ + RNODE_FOREACH_RIB(rn, match) { - if (match->type == ZEBRA_ROUTE_CONNECT || - nexthop->ifindex == match_nh->ifindex) - { - nexthop->ifindex = match_nh->ifindex; - return 1; - } + if (CHECK_FLAG(match->status, RIB_ENTRY_REMOVED) + || !CHECK_FLAG(match->flags, ZEBRA_FLAG_SELECTED)) + continue; + + for (match_nh = match->nexthop; match_nh; + match_nh = match_nh->next) { + if (match->type == ZEBRA_ROUTE_CONNECT + || nexthop->ifindex == match_nh->ifindex) { + nexthop->ifindex = match_nh->ifindex; + return 1; + } + } } - } - return 0; + return 0; } @@ -214,44 +187,44 @@ nhlfe_nexthop_active_ipv4 (zebra_nhlfe_t *nhlfe, struct nexthop *nexthop) * the passed flag. * NOTE: Looking only for connected routes right now. */ -static int -nhlfe_nexthop_active_ipv6 (zebra_nhlfe_t *nhlfe, struct nexthop *nexthop) +static int nhlfe_nexthop_active_ipv6(zebra_nhlfe_t *nhlfe, + struct nexthop *nexthop) { - struct route_table *table; - struct prefix_ipv6 p; - struct route_node *rn; - struct rib *match; - - table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); - if (!table) - return 0; - - /* Lookup nexthop in IPv6 routing table. */ - memset (&p, 0, sizeof (struct prefix_ipv6)); - p.family = AF_INET6; - p.prefixlen = IPV6_MAX_PREFIXLEN; - p.prefix = nexthop->gate.ipv6; - - rn = route_node_match (table, (struct prefix *) &p); - if (!rn) - return 0; - - route_unlock_node (rn); - - /* Locate a valid connected route. */ - RNODE_FOREACH_RIB (rn, match) - { - if ((match->type == ZEBRA_ROUTE_CONNECT) && - !CHECK_FLAG (match->status, RIB_ENTRY_REMOVED) && - CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED)) - break; - } - - if (!match || !match->nexthop) - return 0; - - nexthop->ifindex = match->nexthop->ifindex; - return 1; + struct route_table *table; + struct prefix_ipv6 p; + struct route_node *rn; + struct rib *match; + + table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); + if (!table) + return 0; + + /* Lookup nexthop in IPv6 routing table. */ + memset(&p, 0, sizeof(struct prefix_ipv6)); + p.family = AF_INET6; + p.prefixlen = IPV6_MAX_PREFIXLEN; + p.prefix = nexthop->gate.ipv6; + + rn = route_node_match(table, (struct prefix *)&p); + if (!rn) + return 0; + + route_unlock_node(rn); + + /* Locate a valid connected route. */ + RNODE_FOREACH_RIB(rn, match) + { + if ((match->type == ZEBRA_ROUTE_CONNECT) + && !CHECK_FLAG(match->status, RIB_ENTRY_REMOVED) + && CHECK_FLAG(match->flags, ZEBRA_FLAG_SELECTED)) + break; + } + + if (!match || !match->nexthop) + return 0; + + nexthop->ifindex = match->nexthop->ifindex; + return 1; } @@ -260,57 +233,52 @@ nhlfe_nexthop_active_ipv6 (zebra_nhlfe_t *nhlfe, struct nexthop *nexthop) * or not. * NOTE: Each NHLFE points to only 1 nexthop. */ -static int -nhlfe_nexthop_active (zebra_nhlfe_t *nhlfe) +static int nhlfe_nexthop_active(zebra_nhlfe_t *nhlfe) { - struct nexthop *nexthop; - struct interface *ifp; - - nexthop = nhlfe->nexthop; - if (!nexthop) // unexpected - return 0; - - /* Check on nexthop based on type. */ - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - if (nhlfe_nexthop_active_ipv4 (nhlfe, nexthop)) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - else - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - break; - - case NEXTHOP_TYPE_IPV6: - if (nhlfe_nexthop_active_ipv6 (nhlfe, nexthop)) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - else - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - break; - - case NEXTHOP_TYPE_IPV6_IFINDEX: - if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6)) - { - ifp = if_lookup_by_index (nexthop->ifindex, VRF_DEFAULT); - if (ifp && if_is_operative(ifp)) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - else - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - } - else - { - if (nhlfe_nexthop_active_ipv6 (nhlfe, nexthop)) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - else - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - } - break; - - default: - break; - } - - return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); + struct nexthop *nexthop; + struct interface *ifp; + + nexthop = nhlfe->nexthop; + if (!nexthop) // unexpected + return 0; + + /* Check on nexthop based on type. */ + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + if (nhlfe_nexthop_active_ipv4(nhlfe, nexthop)) + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + else + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + break; + + case NEXTHOP_TYPE_IPV6: + if (nhlfe_nexthop_active_ipv6(nhlfe, nexthop)) + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + else + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + break; + + case NEXTHOP_TYPE_IPV6_IFINDEX: + if (IN6_IS_ADDR_LINKLOCAL(&nexthop->gate.ipv6)) { + ifp = if_lookup_by_index(nexthop->ifindex, VRF_DEFAULT); + if (ifp && if_is_operative(ifp)) + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + else + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + } else { + if (nhlfe_nexthop_active_ipv6(nhlfe, nexthop)) + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + else + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + } + break; + + default: + break; + } + + return CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); } /* @@ -319,759 +287,722 @@ nhlfe_nexthop_active (zebra_nhlfe_t *nhlfe) * marked. This is invoked when an LSP scheduled for processing (due * to some change) is examined. */ -static void -lsp_select_best_nhlfe (zebra_lsp_t *lsp) +static void lsp_select_best_nhlfe(zebra_lsp_t *lsp) { - zebra_nhlfe_t *nhlfe; - zebra_nhlfe_t *best; - struct nexthop *nexthop; - int changed = 0; - - if (!lsp) - return; - - best = NULL; - lsp->num_ecmp = 0; - UNSET_FLAG (lsp->flags, LSP_FLAG_CHANGED); - - /* - * First compute the best path, after checking nexthop status. We are only - * concerned with non-deleted NHLFEs. - */ - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) - { - /* Clear selection flags. */ - UNSET_FLAG (nhlfe->flags, - (NHLFE_FLAG_SELECTED | NHLFE_FLAG_MULTIPATH)); - - if (!CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_DELETED) && - nhlfe_nexthop_active (nhlfe)) - { - if (!best || (nhlfe->distance < best->distance)) - best = nhlfe; - } - } - - lsp->best_nhlfe = best; - if (!lsp->best_nhlfe) - return; - - /* Mark best NHLFE as selected. */ - SET_FLAG (lsp->best_nhlfe->flags, NHLFE_FLAG_SELECTED); - - /* - * If best path exists, see if there is ECMP. While doing this, note if a - * new (uninstalled) NHLFE has been selected, an installed entry that is - * still selected has a change or an installed entry is to be removed. - */ - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) - { - int nh_chg, nh_sel, nh_inst; - - nexthop = nhlfe->nexthop; - if (!nexthop) // unexpected - continue; - - if (!CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_DELETED) && - CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE) && - (nhlfe->distance == lsp->best_nhlfe->distance)) - { - SET_FLAG (nhlfe->flags, NHLFE_FLAG_SELECTED); - SET_FLAG (nhlfe->flags, NHLFE_FLAG_MULTIPATH); - lsp->num_ecmp++; - } - - if (CHECK_FLAG (lsp->flags, LSP_FLAG_INSTALLED) && - !changed) - { - nh_chg = CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_CHANGED); - nh_sel = CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_SELECTED); - nh_inst = CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED); - - if ((nh_sel && !nh_inst) || - (nh_sel && nh_inst && nh_chg) || - (nh_inst && !nh_sel)) - changed = 1; - } - - /* We have finished examining, clear changed flag. */ - UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_CHANGED); - } - - if (changed) - SET_FLAG (lsp->flags, LSP_FLAG_CHANGED); + zebra_nhlfe_t *nhlfe; + zebra_nhlfe_t *best; + struct nexthop *nexthop; + int changed = 0; + + if (!lsp) + return; + + best = NULL; + lsp->num_ecmp = 0; + UNSET_FLAG(lsp->flags, LSP_FLAG_CHANGED); + + /* + * First compute the best path, after checking nexthop status. We are + * only + * concerned with non-deleted NHLFEs. + */ + for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) { + /* Clear selection flags. */ + UNSET_FLAG(nhlfe->flags, + (NHLFE_FLAG_SELECTED | NHLFE_FLAG_MULTIPATH)); + + if (!CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_DELETED) + && nhlfe_nexthop_active(nhlfe)) { + if (!best || (nhlfe->distance < best->distance)) + best = nhlfe; + } + } + + lsp->best_nhlfe = best; + if (!lsp->best_nhlfe) + return; + + /* Mark best NHLFE as selected. */ + SET_FLAG(lsp->best_nhlfe->flags, NHLFE_FLAG_SELECTED); + + /* + * If best path exists, see if there is ECMP. While doing this, note if + * a + * new (uninstalled) NHLFE has been selected, an installed entry that is + * still selected has a change or an installed entry is to be removed. + */ + for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) { + int nh_chg, nh_sel, nh_inst; + + nexthop = nhlfe->nexthop; + if (!nexthop) // unexpected + continue; + + if (!CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_DELETED) + && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE) + && (nhlfe->distance == lsp->best_nhlfe->distance)) { + SET_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED); + SET_FLAG(nhlfe->flags, NHLFE_FLAG_MULTIPATH); + lsp->num_ecmp++; + } + + if (CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED) && !changed) { + nh_chg = CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_CHANGED); + nh_sel = CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED); + nh_inst = + CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED); + + if ((nh_sel && !nh_inst) + || (nh_sel && nh_inst && nh_chg) + || (nh_inst && !nh_sel)) + changed = 1; + } + + /* We have finished examining, clear changed flag. */ + UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_CHANGED); + } + + if (changed) + SET_FLAG(lsp->flags, LSP_FLAG_CHANGED); } /* * Delete LSP forwarding entry from kernel, if installed. Called upon * process exit. */ -static void -lsp_uninstall_from_kernel (struct hash_backet *backet, void *ctxt) +static void lsp_uninstall_from_kernel(struct hash_backet *backet, void *ctxt) { - zebra_lsp_t *lsp; + zebra_lsp_t *lsp; - lsp = (zebra_lsp_t *) backet->data; - if (CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED)) - kernel_del_lsp (lsp); + lsp = (zebra_lsp_t *)backet->data; + if (CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED)) + kernel_del_lsp(lsp); } /* * Schedule LSP forwarding entry for processing. Called upon changes * that may impact LSPs such as nexthop / connected route changes. */ -static void -lsp_schedule (struct hash_backet *backet, void *ctxt) +static void lsp_schedule(struct hash_backet *backet, void *ctxt) { - zebra_lsp_t *lsp; + zebra_lsp_t *lsp; - lsp = (zebra_lsp_t *) backet->data; - lsp_processq_add (lsp); + lsp = (zebra_lsp_t *)backet->data; + lsp_processq_add(lsp); } /* * Process a LSP entry that is in the queue. Recalculate best NHLFE and * any multipaths and update or delete from the kernel, as needed. */ -static wq_item_status -lsp_process (struct work_queue *wq, void *data) +static wq_item_status lsp_process(struct work_queue *wq, void *data) { - zebra_lsp_t *lsp; - zebra_nhlfe_t *oldbest, *newbest; - char buf[BUFSIZ], buf2[BUFSIZ]; - - lsp = (zebra_lsp_t *)data; - if (!lsp) // unexpected - return WQ_SUCCESS; - - oldbest = lsp->best_nhlfe; - - /* Select best NHLFE(s) */ - lsp_select_best_nhlfe (lsp); - - newbest = lsp->best_nhlfe; - - if (IS_ZEBRA_DEBUG_MPLS) - { - if (oldbest) - nhlfe2str (oldbest, buf, BUFSIZ); - if (newbest) - nhlfe2str (newbest, buf2, BUFSIZ); - zlog_debug ("Process LSP in-label %u oldbest %s newbest %s " - "flags 0x%x ecmp# %d", - lsp->ile.in_label, oldbest ? buf : "NULL", - newbest ? buf2 : "NULL", lsp->flags, lsp->num_ecmp); - } - - if (!CHECK_FLAG (lsp->flags, LSP_FLAG_INSTALLED)) - { - /* Not already installed */ - if (newbest) - kernel_add_lsp (lsp); - } - else - { - /* Installed, may need an update and/or delete. */ - if (!newbest) - kernel_del_lsp (lsp); - else if (CHECK_FLAG (lsp->flags, LSP_FLAG_CHANGED)) - kernel_upd_lsp (lsp); - } - - return WQ_SUCCESS; + zebra_lsp_t *lsp; + zebra_nhlfe_t *oldbest, *newbest; + char buf[BUFSIZ], buf2[BUFSIZ]; + + lsp = (zebra_lsp_t *)data; + if (!lsp) // unexpected + return WQ_SUCCESS; + + oldbest = lsp->best_nhlfe; + + /* Select best NHLFE(s) */ + lsp_select_best_nhlfe(lsp); + + newbest = lsp->best_nhlfe; + + if (IS_ZEBRA_DEBUG_MPLS) { + if (oldbest) + nhlfe2str(oldbest, buf, BUFSIZ); + if (newbest) + nhlfe2str(newbest, buf2, BUFSIZ); + zlog_debug( + "Process LSP in-label %u oldbest %s newbest %s " + "flags 0x%x ecmp# %d", + lsp->ile.in_label, oldbest ? buf : "NULL", + newbest ? buf2 : "NULL", lsp->flags, lsp->num_ecmp); + } + + if (!CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED)) { + /* Not already installed */ + if (newbest) + kernel_add_lsp(lsp); + } else { + /* Installed, may need an update and/or delete. */ + if (!newbest) + kernel_del_lsp(lsp); + else if (CHECK_FLAG(lsp->flags, LSP_FLAG_CHANGED)) + kernel_upd_lsp(lsp); + } + + return WQ_SUCCESS; } /* * Callback upon processing completion of a LSP forwarding entry. */ -static void -lsp_processq_del (struct work_queue *wq, void *data) +static void lsp_processq_del(struct work_queue *wq, void *data) { - struct zebra_vrf *zvrf; - zebra_lsp_t *lsp; - struct hash *lsp_table; - zebra_nhlfe_t *nhlfe, *nhlfe_next; - - zvrf = vrf_info_lookup(VRF_DEFAULT); - assert (zvrf); - - lsp_table = zvrf->lsp_table; - if (!lsp_table) // unexpected - return; - - lsp = (zebra_lsp_t *)data; - if (!lsp) // unexpected - return; - - /* Clear flag, remove any NHLFEs marked for deletion. If no NHLFEs exist, - * delete LSP entry also. - */ - UNSET_FLAG (lsp->flags, LSP_FLAG_SCHEDULED); - - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe_next) - { - nhlfe_next = nhlfe->next; - if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_DELETED)) - nhlfe_del (nhlfe); - } - - if (!lsp->nhlfe_list) - { - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("Free LSP in-label %u flags 0x%x", - lsp->ile.in_label, lsp->flags); - - lsp = hash_release(lsp_table, &lsp->ile); - if (lsp) - XFREE(MTYPE_LSP, lsp); - } + struct zebra_vrf *zvrf; + zebra_lsp_t *lsp; + struct hash *lsp_table; + zebra_nhlfe_t *nhlfe, *nhlfe_next; + + zvrf = vrf_info_lookup(VRF_DEFAULT); + assert(zvrf); + + lsp_table = zvrf->lsp_table; + if (!lsp_table) // unexpected + return; + + lsp = (zebra_lsp_t *)data; + if (!lsp) // unexpected + return; + + /* Clear flag, remove any NHLFEs marked for deletion. If no NHLFEs + * exist, + * delete LSP entry also. + */ + UNSET_FLAG(lsp->flags, LSP_FLAG_SCHEDULED); + + for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe_next) { + nhlfe_next = nhlfe->next; + if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_DELETED)) + nhlfe_del(nhlfe); + } + + if (!lsp->nhlfe_list) { + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug("Free LSP in-label %u flags 0x%x", + lsp->ile.in_label, lsp->flags); + + lsp = hash_release(lsp_table, &lsp->ile); + if (lsp) + XFREE(MTYPE_LSP, lsp); + } } /* * Callback upon finishing the processing of all scheduled * LSP forwarding entries. */ -static void -lsp_processq_complete (struct work_queue *wq) +static void lsp_processq_complete(struct work_queue *wq) { - /* Nothing to do for now. */ + /* Nothing to do for now. */ } /* * Add LSP forwarding entry to queue for subsequent processing. */ -static int -lsp_processq_add (zebra_lsp_t *lsp) +static int lsp_processq_add(zebra_lsp_t *lsp) { - /* If already scheduled, exit. */ - if (CHECK_FLAG (lsp->flags, LSP_FLAG_SCHEDULED)) - return 0; + /* If already scheduled, exit. */ + if (CHECK_FLAG(lsp->flags, LSP_FLAG_SCHEDULED)) + return 0; - work_queue_add (zebrad.lsp_process_q, lsp); - SET_FLAG (lsp->flags, LSP_FLAG_SCHEDULED); - return 0; + work_queue_add(zebrad.lsp_process_q, lsp); + SET_FLAG(lsp->flags, LSP_FLAG_SCHEDULED); + return 0; } /* * Callback to allocate LSP forwarding table entry. */ -static void * -lsp_alloc (void *p) +static void *lsp_alloc(void *p) { - const zebra_ile_t *ile = p; - zebra_lsp_t *lsp; + const zebra_ile_t *ile = p; + zebra_lsp_t *lsp; - lsp = XCALLOC (MTYPE_LSP, sizeof(zebra_lsp_t)); - lsp->ile = *ile; + lsp = XCALLOC(MTYPE_LSP, sizeof(zebra_lsp_t)); + lsp->ile = *ile; - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("Alloc LSP in-label %u", lsp->ile.in_label); + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug("Alloc LSP in-label %u", lsp->ile.in_label); - return ((void *)lsp); + return ((void *)lsp); } /* * Create printable string for NHLFE entry. */ -static char * -nhlfe2str (zebra_nhlfe_t *nhlfe, char *buf, int size) +static char *nhlfe2str(zebra_nhlfe_t *nhlfe, char *buf, int size) { - struct nexthop *nexthop; - - buf[0] = '\0'; - nexthop = nhlfe->nexthop; - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - inet_ntop (AF_INET, &nexthop->gate.ipv4, buf, size); - break; - case NEXTHOP_TYPE_IPV6: - inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, size); - break; - default: - break; - } - - return buf; + struct nexthop *nexthop; + + buf[0] = '\0'; + nexthop = nhlfe->nexthop; + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + inet_ntop(AF_INET, &nexthop->gate.ipv4, buf, size); + break; + case NEXTHOP_TYPE_IPV6: + inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf, size); + break; + default: + break; + } + + return buf; } /* * Check if NHLFE matches with search info passed. */ -static int -nhlfe_nhop_match (zebra_nhlfe_t *nhlfe, enum nexthop_types_t gtype, - union g_addr *gate, char *ifname, ifindex_t ifindex) +static int nhlfe_nhop_match(zebra_nhlfe_t *nhlfe, enum nexthop_types_t gtype, + union g_addr *gate, char *ifname, ifindex_t ifindex) { - struct nexthop *nhop; - int cmp = 1; - - nhop = nhlfe->nexthop; - if (!nhop) - return 1; - - if (nhop->type != gtype) - return 1; - - switch (nhop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - cmp = memcmp(&(nhop->gate.ipv4), &(gate->ipv4), - sizeof(struct in_addr)); - if (!cmp && nhop->type == NEXTHOP_TYPE_IPV4_IFINDEX) - cmp = !(nhop->ifindex == ifindex); - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - cmp = memcmp(&(nhop->gate.ipv6), &(gate->ipv6), - sizeof(struct in6_addr)); - if (!cmp && nhop->type == NEXTHOP_TYPE_IPV6_IFINDEX) - cmp = !(nhop->ifindex == ifindex); - break; - default: - break; - } - - return cmp; + struct nexthop *nhop; + int cmp = 1; + + nhop = nhlfe->nexthop; + if (!nhop) + return 1; + + if (nhop->type != gtype) + return 1; + + switch (nhop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + cmp = memcmp(&(nhop->gate.ipv4), &(gate->ipv4), + sizeof(struct in_addr)); + if (!cmp && nhop->type == NEXTHOP_TYPE_IPV4_IFINDEX) + cmp = !(nhop->ifindex == ifindex); + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + cmp = memcmp(&(nhop->gate.ipv6), &(gate->ipv6), + sizeof(struct in6_addr)); + if (!cmp && nhop->type == NEXTHOP_TYPE_IPV6_IFINDEX) + cmp = !(nhop->ifindex == ifindex); + break; + default: + break; + } + + return cmp; } /* * Locate NHLFE that matches with passed info. */ -static zebra_nhlfe_t * -nhlfe_find (zebra_lsp_t *lsp, enum lsp_types_t lsp_type, - enum nexthop_types_t gtype, union g_addr *gate, - char *ifname, ifindex_t ifindex) +static zebra_nhlfe_t *nhlfe_find(zebra_lsp_t *lsp, enum lsp_types_t lsp_type, + enum nexthop_types_t gtype, union g_addr *gate, + char *ifname, ifindex_t ifindex) { - zebra_nhlfe_t *nhlfe; + zebra_nhlfe_t *nhlfe; - if (!lsp) - return NULL; + if (!lsp) + return NULL; - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) - { - if (nhlfe->type != lsp_type) - continue; - if (!nhlfe_nhop_match (nhlfe, gtype, gate, ifname, ifindex)) - break; - } + for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) { + if (nhlfe->type != lsp_type) + continue; + if (!nhlfe_nhop_match(nhlfe, gtype, gate, ifname, ifindex)) + break; + } - return nhlfe; + return nhlfe; } /* * Add NHLFE. Base entry must have been created and duplicate * check done. */ -static zebra_nhlfe_t * -nhlfe_add (zebra_lsp_t *lsp, enum lsp_types_t lsp_type, - enum nexthop_types_t gtype, union g_addr *gate, - char *ifname, ifindex_t ifindex, mpls_label_t out_label) +static zebra_nhlfe_t *nhlfe_add(zebra_lsp_t *lsp, enum lsp_types_t lsp_type, + enum nexthop_types_t gtype, union g_addr *gate, + char *ifname, ifindex_t ifindex, + mpls_label_t out_label) { - zebra_nhlfe_t *nhlfe; - struct nexthop *nexthop; - - if (!lsp) - return NULL; - - nhlfe = XCALLOC(MTYPE_NHLFE, sizeof(zebra_nhlfe_t)); - if (!nhlfe) - return NULL; - - nhlfe->lsp = lsp; - nhlfe->type = lsp_type; - nhlfe->distance = lsp_distance (lsp_type); - - nexthop = nexthop_new(); - if (!nexthop) - { - XFREE (MTYPE_NHLFE, nhlfe); - return NULL; - } - nexthop_add_labels (nexthop, lsp_type, 1, &out_label); - - nexthop->type = gtype; - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - nexthop->gate.ipv4 = gate->ipv4; - if (ifindex) - nexthop->ifindex = ifindex; - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - nexthop->gate.ipv6 = gate->ipv6; - if (ifindex) - nexthop->ifindex = ifindex; - break; - default: - nexthop_free(nexthop); - XFREE (MTYPE_NHLFE, nhlfe); - return NULL; - break; - } - - nhlfe->nexthop = nexthop; - if (lsp->nhlfe_list) - lsp->nhlfe_list->prev = nhlfe; - nhlfe->next = lsp->nhlfe_list; - lsp->nhlfe_list = nhlfe; - - return nhlfe; + zebra_nhlfe_t *nhlfe; + struct nexthop *nexthop; + + if (!lsp) + return NULL; + + nhlfe = XCALLOC(MTYPE_NHLFE, sizeof(zebra_nhlfe_t)); + if (!nhlfe) + return NULL; + + nhlfe->lsp = lsp; + nhlfe->type = lsp_type; + nhlfe->distance = lsp_distance(lsp_type); + + nexthop = nexthop_new(); + if (!nexthop) { + XFREE(MTYPE_NHLFE, nhlfe); + return NULL; + } + nexthop_add_labels(nexthop, lsp_type, 1, &out_label); + + nexthop->type = gtype; + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + nexthop->gate.ipv4 = gate->ipv4; + if (ifindex) + nexthop->ifindex = ifindex; + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + nexthop->gate.ipv6 = gate->ipv6; + if (ifindex) + nexthop->ifindex = ifindex; + break; + default: + nexthop_free(nexthop); + XFREE(MTYPE_NHLFE, nhlfe); + return NULL; + break; + } + + nhlfe->nexthop = nexthop; + if (lsp->nhlfe_list) + lsp->nhlfe_list->prev = nhlfe; + nhlfe->next = lsp->nhlfe_list; + lsp->nhlfe_list = nhlfe; + + return nhlfe; } /* * Delete NHLFE. Entry must be present on list. */ -static int -nhlfe_del (zebra_nhlfe_t *nhlfe) +static int nhlfe_del(zebra_nhlfe_t *nhlfe) { - zebra_lsp_t *lsp; + zebra_lsp_t *lsp; - if (!nhlfe) - return -1; + if (!nhlfe) + return -1; - lsp = nhlfe->lsp; - if (!lsp) - return -1; + lsp = nhlfe->lsp; + if (!lsp) + return -1; - /* Free nexthop. */ - if (nhlfe->nexthop) - nexthop_free(nhlfe->nexthop); + /* Free nexthop. */ + if (nhlfe->nexthop) + nexthop_free(nhlfe->nexthop); - /* Unlink from LSP */ - if (nhlfe->next) - nhlfe->next->prev = nhlfe->prev; - if (nhlfe->prev) - nhlfe->prev->next = nhlfe->next; - else - lsp->nhlfe_list = nhlfe->next; + /* Unlink from LSP */ + if (nhlfe->next) + nhlfe->next->prev = nhlfe->prev; + if (nhlfe->prev) + nhlfe->prev->next = nhlfe->next; + else + lsp->nhlfe_list = nhlfe->next; - if (nhlfe == lsp->best_nhlfe) - lsp->best_nhlfe = NULL; + if (nhlfe == lsp->best_nhlfe) + lsp->best_nhlfe = NULL; - XFREE (MTYPE_NHLFE, nhlfe); + XFREE(MTYPE_NHLFE, nhlfe); - return 0; + return 0; } -static int -mpls_lsp_uninstall_all (struct hash *lsp_table, zebra_lsp_t *lsp, - enum lsp_types_t type) +static int mpls_lsp_uninstall_all(struct hash *lsp_table, zebra_lsp_t *lsp, + enum lsp_types_t type) { - zebra_nhlfe_t *nhlfe, *nhlfe_next; - int schedule_lsp = 0; - char buf[BUFSIZ]; - - /* Mark NHLFEs for delete or directly delete, as appropriate. */ - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe_next) - { - nhlfe_next = nhlfe->next; - - /* Skip non-static NHLFEs */ - if (nhlfe->type != type) - continue; - - if (IS_ZEBRA_DEBUG_MPLS) - { - nhlfe2str (nhlfe, buf, BUFSIZ); - zlog_debug ("Del LSP in-label %u type %d nexthop %s flags 0x%x", - lsp->ile.in_label, type, buf, nhlfe->flags); - } - - if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED)) - { - UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_CHANGED); - SET_FLAG (nhlfe->flags, NHLFE_FLAG_DELETED); - schedule_lsp = 1; - } - else - { - nhlfe_del (nhlfe); - } - } - - /* Queue LSP for processing, if needed, else delete. */ - if (schedule_lsp) - { - if (lsp_processq_add (lsp)) - return -1; - } - else if (!lsp->nhlfe_list && - !CHECK_FLAG (lsp->flags, LSP_FLAG_SCHEDULED)) - { - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("Free LSP in-label %u flags 0x%x", - lsp->ile.in_label, lsp->flags); - - lsp = hash_release(lsp_table, &lsp->ile); - if (lsp) - XFREE(MTYPE_LSP, lsp); - } - - return 0; + zebra_nhlfe_t *nhlfe, *nhlfe_next; + int schedule_lsp = 0; + char buf[BUFSIZ]; + + /* Mark NHLFEs for delete or directly delete, as appropriate. */ + for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe_next) { + nhlfe_next = nhlfe->next; + + /* Skip non-static NHLFEs */ + if (nhlfe->type != type) + continue; + + if (IS_ZEBRA_DEBUG_MPLS) { + nhlfe2str(nhlfe, buf, BUFSIZ); + zlog_debug( + "Del LSP in-label %u type %d nexthop %s flags 0x%x", + lsp->ile.in_label, type, buf, nhlfe->flags); + } + + if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED)) { + UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_CHANGED); + SET_FLAG(nhlfe->flags, NHLFE_FLAG_DELETED); + schedule_lsp = 1; + } else { + nhlfe_del(nhlfe); + } + } + + /* Queue LSP for processing, if needed, else delete. */ + if (schedule_lsp) { + if (lsp_processq_add(lsp)) + return -1; + } else if (!lsp->nhlfe_list + && !CHECK_FLAG(lsp->flags, LSP_FLAG_SCHEDULED)) { + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug("Free LSP in-label %u flags 0x%x", + lsp->ile.in_label, lsp->flags); + + lsp = hash_release(lsp_table, &lsp->ile); + if (lsp) + XFREE(MTYPE_LSP, lsp); + } + + return 0; } /* * Uninstall all static NHLFEs for a particular LSP forwarding entry. * If no other NHLFEs exist, the entry would be deleted. */ -static int -mpls_static_lsp_uninstall_all (struct zebra_vrf *zvrf, mpls_label_t in_label) +static int mpls_static_lsp_uninstall_all(struct zebra_vrf *zvrf, + mpls_label_t in_label) { - struct hash *lsp_table; - zebra_ile_t tmp_ile; - zebra_lsp_t *lsp; - - /* Lookup table. */ - lsp_table = zvrf->lsp_table; - if (!lsp_table) - return -1; - - /* If entry is not present, exit. */ - tmp_ile.in_label = in_label; - lsp = hash_lookup (lsp_table, &tmp_ile); - if (!lsp || !lsp->nhlfe_list) - return 0; - - return mpls_lsp_uninstall_all (lsp_table, lsp, ZEBRA_LSP_STATIC); + struct hash *lsp_table; + zebra_ile_t tmp_ile; + zebra_lsp_t *lsp; + + /* Lookup table. */ + lsp_table = zvrf->lsp_table; + if (!lsp_table) + return -1; + + /* If entry is not present, exit. */ + tmp_ile.in_label = in_label; + lsp = hash_lookup(lsp_table, &tmp_ile); + if (!lsp || !lsp->nhlfe_list) + return 0; + + return mpls_lsp_uninstall_all(lsp_table, lsp, ZEBRA_LSP_STATIC); } -static json_object * -nhlfe_json (zebra_nhlfe_t *nhlfe) +static json_object *nhlfe_json(zebra_nhlfe_t *nhlfe) { - char buf[BUFSIZ]; - json_object *json_nhlfe = NULL; - struct nexthop *nexthop = nhlfe->nexthop; - - json_nhlfe = json_object_new_object(); - json_object_string_add(json_nhlfe, "type", nhlfe_type2str(nhlfe->type)); - json_object_int_add(json_nhlfe, "outLabel", nexthop->nh_label->label[0]); - json_object_int_add(json_nhlfe, "distance", nhlfe->distance); - - if (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED)) - json_object_boolean_true_add(json_nhlfe, "installed"); - - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - json_object_string_add(json_nhlfe, "nexthop", - inet_ntoa (nexthop->gate.ipv4)); - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - json_object_string_add(json_nhlfe, "nexthop", - inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ)); - - if (nexthop->ifindex) - json_object_string_add(json_nhlfe, "interface", ifindex2ifname (nexthop->ifindex, VRF_DEFAULT)); - break; - default: - break; - } - return json_nhlfe; + char buf[BUFSIZ]; + json_object *json_nhlfe = NULL; + struct nexthop *nexthop = nhlfe->nexthop; + + json_nhlfe = json_object_new_object(); + json_object_string_add(json_nhlfe, "type", nhlfe_type2str(nhlfe->type)); + json_object_int_add(json_nhlfe, "outLabel", + nexthop->nh_label->label[0]); + json_object_int_add(json_nhlfe, "distance", nhlfe->distance); + + if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED)) + json_object_boolean_true_add(json_nhlfe, "installed"); + + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + json_object_string_add(json_nhlfe, "nexthop", + inet_ntoa(nexthop->gate.ipv4)); + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + json_object_string_add( + json_nhlfe, "nexthop", + inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ)); + + if (nexthop->ifindex) + json_object_string_add( + json_nhlfe, "interface", + ifindex2ifname(nexthop->ifindex, VRF_DEFAULT)); + break; + default: + break; + } + return json_nhlfe; } /* * Print the NHLFE for a LSP forwarding entry. */ -static void -nhlfe_print (zebra_nhlfe_t *nhlfe, struct vty *vty) +static void nhlfe_print(zebra_nhlfe_t *nhlfe, struct vty *vty) { - struct nexthop *nexthop; - char buf[BUFSIZ]; - - nexthop = nhlfe->nexthop; - if (!nexthop || !nexthop->nh_label) // unexpected - return; - - vty_out(vty, " type: %s remote label: %s distance: %d%s", - nhlfe_type2str(nhlfe->type), - label2str(nexthop->nh_label->label[0], buf, BUFSIZ), - nhlfe->distance, VTY_NEWLINE); - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - vty_out (vty, " via %s", inet_ntoa (nexthop->gate.ipv4)); - if (nexthop->ifindex) - vty_out (vty, " dev %s", ifindex2ifname (nexthop->ifindex, VRF_DEFAULT)); - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - vty_out (vty, " via %s", - inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ)); - if (nexthop->ifindex) - vty_out (vty, " dev %s", ifindex2ifname (nexthop->ifindex, VRF_DEFAULT)); - break; - default: - break; - } - vty_out(vty, "%s", CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED) ? - " (installed)" : ""); - vty_out(vty, "%s", VTY_NEWLINE); + struct nexthop *nexthop; + char buf[BUFSIZ]; + + nexthop = nhlfe->nexthop; + if (!nexthop || !nexthop->nh_label) // unexpected + return; + + vty_out(vty, " type: %s remote label: %s distance: %d%s", + nhlfe_type2str(nhlfe->type), + label2str(nexthop->nh_label->label[0], buf, BUFSIZ), + nhlfe->distance, VTY_NEWLINE); + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + vty_out(vty, " via %s", inet_ntoa(nexthop->gate.ipv4)); + if (nexthop->ifindex) + vty_out(vty, " dev %s", + ifindex2ifname(nexthop->ifindex, VRF_DEFAULT)); + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + vty_out(vty, " via %s", + inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ)); + if (nexthop->ifindex) + vty_out(vty, " dev %s", + ifindex2ifname(nexthop->ifindex, VRF_DEFAULT)); + break; + default: + break; + } + vty_out(vty, "%s", + CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED) ? " (installed)" + : ""); + vty_out(vty, "%s", VTY_NEWLINE); } /* * Print an LSP forwarding entry. */ -static void -lsp_print (zebra_lsp_t *lsp, void *ctxt) +static void lsp_print(zebra_lsp_t *lsp, void *ctxt) { - zebra_nhlfe_t *nhlfe; - struct vty *vty; + zebra_nhlfe_t *nhlfe; + struct vty *vty; - vty = (struct vty *) ctxt; + vty = (struct vty *)ctxt; - vty_out(vty, "Local label: %u%s%s", - lsp->ile.in_label, - CHECK_FLAG (lsp->flags, LSP_FLAG_INSTALLED) ? " (installed)" : "", - VTY_NEWLINE); + vty_out(vty, "Local label: %u%s%s", lsp->ile.in_label, + CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED) ? " (installed)" + : "", + VTY_NEWLINE); - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) - nhlfe_print (nhlfe, vty); + for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) + nhlfe_print(nhlfe, vty); } /* * JSON objects for an LSP forwarding entry. */ -static json_object * -lsp_json (zebra_lsp_t *lsp) +static json_object *lsp_json(zebra_lsp_t *lsp) { - zebra_nhlfe_t *nhlfe = NULL; - json_object *json = json_object_new_object(); - json_object *json_nhlfe_list = json_object_new_array(); + zebra_nhlfe_t *nhlfe = NULL; + json_object *json = json_object_new_object(); + json_object *json_nhlfe_list = json_object_new_array(); - json_object_int_add(json, "inLabel", lsp->ile.in_label); + json_object_int_add(json, "inLabel", lsp->ile.in_label); - if (CHECK_FLAG (lsp->flags, LSP_FLAG_INSTALLED)) - json_object_boolean_true_add(json, "installed"); + if (CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED)) + json_object_boolean_true_add(json, "installed"); - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) - json_object_array_add(json_nhlfe_list, nhlfe_json(nhlfe)); + for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) + json_object_array_add(json_nhlfe_list, nhlfe_json(nhlfe)); - json_object_object_add(json, "nexthops", json_nhlfe_list); - return json; + json_object_object_add(json, "nexthops", json_nhlfe_list); + return json; } /* Return a sorted linked list of the hash contents */ -static struct list * -hash_get_sorted_list (struct hash *hash, void *cmp) +static struct list *hash_get_sorted_list(struct hash *hash, void *cmp) { - unsigned int i; - struct hash_backet *hb; - struct list *sorted_list = list_new(); + unsigned int i; + struct hash_backet *hb; + struct list *sorted_list = list_new(); - sorted_list->cmp = (int (*)(void *, void *)) cmp; + sorted_list->cmp = (int (*)(void *, void *))cmp; - for (i = 0; i < hash->size; i++) - for (hb = hash->index[i]; hb; hb = hb->next) - listnode_add_sort(sorted_list, hb->data); + for (i = 0; i < hash->size; i++) + for (hb = hash->index[i]; hb; hb = hb->next) + listnode_add_sort(sorted_list, hb->data); - return sorted_list; + return sorted_list; } /* * Compare two LSPs based on their label values. */ -static int -lsp_cmp (zebra_lsp_t *lsp1, zebra_lsp_t *lsp2) +static int lsp_cmp(zebra_lsp_t *lsp1, zebra_lsp_t *lsp2) { - if (lsp1->ile.in_label < lsp2->ile.in_label) - return -1; + if (lsp1->ile.in_label < lsp2->ile.in_label) + return -1; - if (lsp1->ile.in_label > lsp2->ile.in_label) - return 1; + if (lsp1->ile.in_label > lsp2->ile.in_label) + return 1; - return 0; + return 0; } /* * Callback to allocate static LSP. */ -static void * -slsp_alloc (void *p) +static void *slsp_alloc(void *p) { - const zebra_ile_t *ile = p; - zebra_slsp_t *slsp; + const zebra_ile_t *ile = p; + zebra_slsp_t *slsp; - slsp = XCALLOC (MTYPE_SLSP, sizeof(zebra_slsp_t)); - slsp->ile = *ile; - return ((void *)slsp); + slsp = XCALLOC(MTYPE_SLSP, sizeof(zebra_slsp_t)); + slsp->ile = *ile; + return ((void *)slsp); } /* * Compare two static LSPs based on their label values. */ -static int -slsp_cmp (zebra_slsp_t *slsp1, zebra_slsp_t *slsp2) +static int slsp_cmp(zebra_slsp_t *slsp1, zebra_slsp_t *slsp2) { - if (slsp1->ile.in_label < slsp2->ile.in_label) - return -1; + if (slsp1->ile.in_label < slsp2->ile.in_label) + return -1; - if (slsp1->ile.in_label > slsp2->ile.in_label) - return 1; + if (slsp1->ile.in_label > slsp2->ile.in_label) + return 1; - return 0; + return 0; } /* * Check if static NHLFE matches with search info passed. */ -static int -snhlfe_match (zebra_snhlfe_t *snhlfe, enum nexthop_types_t gtype, - union g_addr *gate, char *ifname, ifindex_t ifindex) +static int snhlfe_match(zebra_snhlfe_t *snhlfe, enum nexthop_types_t gtype, + union g_addr *gate, char *ifname, ifindex_t ifindex) { - int cmp = 1; - - if (snhlfe->gtype != gtype) - return 1; - - switch (snhlfe->gtype) - { - case NEXTHOP_TYPE_IPV4: - cmp = memcmp(&(snhlfe->gate.ipv4), &(gate->ipv4), - sizeof(struct in_addr)); - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - cmp = memcmp(&(snhlfe->gate.ipv6), &(gate->ipv6), - sizeof(struct in6_addr)); - if (!cmp && snhlfe->gtype == NEXTHOP_TYPE_IPV6_IFINDEX) - cmp = !(snhlfe->ifindex == ifindex); - break; - default: - break; - } - - return cmp; + int cmp = 1; + + if (snhlfe->gtype != gtype) + return 1; + + switch (snhlfe->gtype) { + case NEXTHOP_TYPE_IPV4: + cmp = memcmp(&(snhlfe->gate.ipv4), &(gate->ipv4), + sizeof(struct in_addr)); + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + cmp = memcmp(&(snhlfe->gate.ipv6), &(gate->ipv6), + sizeof(struct in6_addr)); + if (!cmp && snhlfe->gtype == NEXTHOP_TYPE_IPV6_IFINDEX) + cmp = !(snhlfe->ifindex == ifindex); + break; + default: + break; + } + + return cmp; } /* * Locate static NHLFE that matches with passed info. */ -static zebra_snhlfe_t * -snhlfe_find (zebra_slsp_t *slsp, enum nexthop_types_t gtype, - union g_addr *gate, char *ifname, ifindex_t ifindex) +static zebra_snhlfe_t *snhlfe_find(zebra_slsp_t *slsp, + enum nexthop_types_t gtype, + union g_addr *gate, char *ifname, + ifindex_t ifindex) { - zebra_snhlfe_t *snhlfe; + zebra_snhlfe_t *snhlfe; - if (!slsp) - return NULL; + if (!slsp) + return NULL; - for (snhlfe = slsp->snhlfe_list; snhlfe; snhlfe = snhlfe->next) - { - if (!snhlfe_match (snhlfe, gtype, gate, ifname, ifindex)) - break; - } + for (snhlfe = slsp->snhlfe_list; snhlfe; snhlfe = snhlfe->next) { + if (!snhlfe_match(snhlfe, gtype, gate, ifname, ifindex)) + break; + } - return snhlfe; + return snhlfe; } @@ -1079,140 +1010,132 @@ snhlfe_find (zebra_slsp_t *slsp, enum nexthop_types_t gtype, * Add static NHLFE. Base LSP config entry must have been created * and duplicate check done. */ -static zebra_snhlfe_t * -snhlfe_add (zebra_slsp_t *slsp, enum nexthop_types_t gtype, - union g_addr *gate, char *ifname, ifindex_t ifindex, - mpls_label_t out_label) +static zebra_snhlfe_t *snhlfe_add(zebra_slsp_t *slsp, + enum nexthop_types_t gtype, + union g_addr *gate, char *ifname, + ifindex_t ifindex, mpls_label_t out_label) { - zebra_snhlfe_t *snhlfe; - - if (!slsp) - return NULL; - - snhlfe = XCALLOC(MTYPE_SNHLFE, sizeof(zebra_snhlfe_t)); - snhlfe->slsp = slsp; - snhlfe->out_label = out_label; - snhlfe->gtype = gtype; - switch (gtype) - { - case NEXTHOP_TYPE_IPV4: - snhlfe->gate.ipv4 = gate->ipv4; - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - snhlfe->gate.ipv6 = gate->ipv6; - if (ifindex) - snhlfe->ifindex = ifindex; - break; - default: - XFREE (MTYPE_SNHLFE, snhlfe); - return NULL; - } - - if (slsp->snhlfe_list) - slsp->snhlfe_list->prev = snhlfe; - snhlfe->next = slsp->snhlfe_list; - slsp->snhlfe_list = snhlfe; - - return snhlfe; + zebra_snhlfe_t *snhlfe; + + if (!slsp) + return NULL; + + snhlfe = XCALLOC(MTYPE_SNHLFE, sizeof(zebra_snhlfe_t)); + snhlfe->slsp = slsp; + snhlfe->out_label = out_label; + snhlfe->gtype = gtype; + switch (gtype) { + case NEXTHOP_TYPE_IPV4: + snhlfe->gate.ipv4 = gate->ipv4; + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + snhlfe->gate.ipv6 = gate->ipv6; + if (ifindex) + snhlfe->ifindex = ifindex; + break; + default: + XFREE(MTYPE_SNHLFE, snhlfe); + return NULL; + } + + if (slsp->snhlfe_list) + slsp->snhlfe_list->prev = snhlfe; + snhlfe->next = slsp->snhlfe_list; + slsp->snhlfe_list = snhlfe; + + return snhlfe; } /* * Delete static NHLFE. Entry must be present on list. */ -static int -snhlfe_del (zebra_snhlfe_t *snhlfe) +static int snhlfe_del(zebra_snhlfe_t *snhlfe) { - zebra_slsp_t *slsp; + zebra_slsp_t *slsp; - if (!snhlfe) - return -1; + if (!snhlfe) + return -1; - slsp = snhlfe->slsp; - if (!slsp) - return -1; + slsp = snhlfe->slsp; + if (!slsp) + return -1; - if (snhlfe->next) - snhlfe->next->prev = snhlfe->prev; - if (snhlfe->prev) - snhlfe->prev->next = snhlfe->next; - else - slsp->snhlfe_list = snhlfe->next; + if (snhlfe->next) + snhlfe->next->prev = snhlfe->prev; + if (snhlfe->prev) + snhlfe->prev->next = snhlfe->next; + else + slsp->snhlfe_list = snhlfe->next; - snhlfe->prev = snhlfe->next = NULL; - if (snhlfe->ifname) - XFREE (MTYPE_SNHLFE_IFNAME, snhlfe->ifname); - XFREE (MTYPE_SNHLFE, snhlfe); + snhlfe->prev = snhlfe->next = NULL; + if (snhlfe->ifname) + XFREE(MTYPE_SNHLFE_IFNAME, snhlfe->ifname); + XFREE(MTYPE_SNHLFE, snhlfe); - return 0; + return 0; } /* * Delete all static NHLFE entries for this LSP (in label). */ -static int -snhlfe_del_all (zebra_slsp_t *slsp) +static int snhlfe_del_all(zebra_slsp_t *slsp) { - zebra_snhlfe_t *snhlfe, *snhlfe_next; + zebra_snhlfe_t *snhlfe, *snhlfe_next; - if (!slsp) - return -1; + if (!slsp) + return -1; - for (snhlfe = slsp->snhlfe_list; snhlfe; snhlfe = snhlfe_next) - { - snhlfe_next = snhlfe->next; - snhlfe_del (snhlfe); - } + for (snhlfe = slsp->snhlfe_list; snhlfe; snhlfe = snhlfe_next) { + snhlfe_next = snhlfe->next; + snhlfe_del(snhlfe); + } - return 0; + return 0; } /* * Create printable string for NHLFE configuration. */ -static char * -snhlfe2str (zebra_snhlfe_t *snhlfe, char *buf, int size) +static char *snhlfe2str(zebra_snhlfe_t *snhlfe, char *buf, int size) { - buf[0] = '\0'; - switch (snhlfe->gtype) - { - case NEXTHOP_TYPE_IPV4: - inet_ntop (AF_INET, &snhlfe->gate.ipv4, buf, size); - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - inet_ntop (AF_INET6, &snhlfe->gate.ipv6, buf, size); - if (snhlfe->ifindex) - strcat (buf, ifindex2ifname (snhlfe->ifindex, VRF_DEFAULT)); - break; - default: - break; - } - - return buf; + buf[0] = '\0'; + switch (snhlfe->gtype) { + case NEXTHOP_TYPE_IPV4: + inet_ntop(AF_INET, &snhlfe->gate.ipv4, buf, size); + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + inet_ntop(AF_INET6, &snhlfe->gate.ipv6, buf, size); + if (snhlfe->ifindex) + strcat(buf, + ifindex2ifname(snhlfe->ifindex, VRF_DEFAULT)); + break; + default: + break; + } + + return buf; } /* * Initialize work queue for processing changed LSPs. */ -static void -mpls_processq_init (struct zebra_t *zebra) +static void mpls_processq_init(struct zebra_t *zebra) { - zebra->lsp_process_q = work_queue_new (zebra->master, "LSP processing"); - if (!zebra->lsp_process_q) - { - zlog_err ("%s: could not initialise work queue!", __func__); - return; - } - - zebra->lsp_process_q->spec.workfunc = &lsp_process; - zebra->lsp_process_q->spec.del_item_data = &lsp_processq_del; - zebra->lsp_process_q->spec.errorfunc = NULL; - zebra->lsp_process_q->spec.completion_func = &lsp_processq_complete; - zebra->lsp_process_q->spec.max_retries = 0; - zebra->lsp_process_q->spec.hold = 10; -} + zebra->lsp_process_q = work_queue_new(zebra->master, "LSP processing"); + if (!zebra->lsp_process_q) { + zlog_err("%s: could not initialise work queue!", __func__); + return; + } + zebra->lsp_process_q->spec.workfunc = &lsp_process; + zebra->lsp_process_q->spec.del_item_data = &lsp_processq_del; + zebra->lsp_process_q->spec.errorfunc = NULL; + zebra->lsp_process_q->spec.completion_func = &lsp_processq_complete; + zebra->lsp_process_q->spec.max_retries = 0; + zebra->lsp_process_q->spec.hold = 10; +} /* Public functions */ @@ -1220,136 +1143,132 @@ mpls_processq_init (struct zebra_t *zebra) /* * String to label conversion, labels separated by '/'. */ -int -mpls_str2label (const char *label_str, u_int8_t *num_labels, - mpls_label_t *labels) +int mpls_str2label(const char *label_str, u_int8_t *num_labels, + mpls_label_t *labels) { - char *endp; - int i; + char *endp; + int i; - *num_labels = 0; - for (i = 0; i < MPLS_MAX_LABELS; i++) - { - u_int32_t label; + *num_labels = 0; + for (i = 0; i < MPLS_MAX_LABELS; i++) { + u_int32_t label; - label = strtoul(label_str, &endp, 0); + label = strtoul(label_str, &endp, 0); - /* validity checks */ - if (endp == label_str) - return -1; + /* validity checks */ + if (endp == label_str) + return -1; - if (!IS_MPLS_UNRESERVED_LABEL(label)) - return -1; + if (!IS_MPLS_UNRESERVED_LABEL(label)) + return -1; - labels[i] = label; - if (*endp == '\0') - { - *num_labels = i + 1; - return 0; - } + labels[i] = label; + if (*endp == '\0') { + *num_labels = i + 1; + return 0; + } - /* Check separator. */ - if (*endp != '/') - return -1; + /* Check separator. */ + if (*endp != '/') + return -1; - label_str = endp + 1; - } + label_str = endp + 1; + } - /* Too many labels. */ - return -1; + /* Too many labels. */ + return -1; } /* * Label to string conversion, labels in string separated by '/'. */ -char * -mpls_label2str (u_int8_t num_labels, mpls_label_t *labels, - char *buf, int len) +char *mpls_label2str(u_int8_t num_labels, mpls_label_t *labels, char *buf, + int len) { - buf[0] = '\0'; - if (num_labels == 1) - snprintf (buf, len, "%u", labels[0]); - else if (num_labels == 2) - snprintf (buf, len, "%u/%u", labels[0], labels[1]); - return buf; + buf[0] = '\0'; + if (num_labels == 1) + snprintf(buf, len, "%u", labels[0]); + else if (num_labels == 2) + snprintf(buf, len, "%u/%u", labels[0], labels[1]); + return buf; } /* * Install/uninstall a FEC-To-NHLFE (FTN) binding. */ -int -mpls_ftn_update (int add, struct zebra_vrf *zvrf, enum lsp_types_t type, - struct prefix *prefix, enum nexthop_types_t gtype, - union g_addr *gate, ifindex_t ifindex, u_int8_t distance, - mpls_label_t out_label) +int mpls_ftn_update(int add, struct zebra_vrf *zvrf, enum lsp_types_t type, + struct prefix *prefix, enum nexthop_types_t gtype, + union g_addr *gate, ifindex_t ifindex, u_int8_t distance, + mpls_label_t out_label) { - struct route_table *table; - struct route_node *rn; - struct rib *rib; - struct nexthop *nexthop; - - /* Lookup table. */ - table = zebra_vrf_table (family2afi(prefix->family), SAFI_UNICAST, zvrf_id (zvrf)); - if (! table) - return -1; - - /* Lookup existing route */ - rn = route_node_get (table, prefix); - RNODE_FOREACH_RIB (rn, rib) - { - if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) - continue; - if (rib->distance == distance) - break; - } - - if (rib == NULL) - return -1; - - for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) - { - switch (nexthop->type) + struct route_table *table; + struct route_node *rn; + struct rib *rib; + struct nexthop *nexthop; + + /* Lookup table. */ + table = zebra_vrf_table(family2afi(prefix->family), SAFI_UNICAST, + zvrf_id(zvrf)); + if (!table) + return -1; + + /* Lookup existing route */ + rn = route_node_get(table, prefix); + RNODE_FOREACH_RIB(rn, rib) { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - if (gtype != NEXTHOP_TYPE_IPV4 && gtype != NEXTHOP_TYPE_IPV4_IFINDEX) - continue; - if (! IPV4_ADDR_SAME (&nexthop->gate.ipv4, &gate->ipv4)) - continue; - if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX && - nexthop->ifindex != ifindex) - continue; - goto found; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - if (gtype != NEXTHOP_TYPE_IPV6 && gtype != NEXTHOP_TYPE_IPV6_IFINDEX) - continue; - if (! IPV6_ADDR_SAME (&nexthop->gate.ipv6, &gate->ipv6)) - continue; - if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX && - nexthop->ifindex != ifindex) - continue; - goto found; - default: - break; + if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED)) + continue; + if (rib->distance == distance) + break; } - } - /* nexthop not found */ - return -1; - - found: - if (add && nexthop->nh_label_type == ZEBRA_LSP_NONE) - nexthop_add_labels (nexthop, type, 1, &out_label); - else if (!add && nexthop->nh_label_type == type) - nexthop_del_labels (nexthop); - else - return 0; - - SET_FLAG (rib->status, RIB_ENTRY_CHANGED); - SET_FLAG (rib->status, RIB_ENTRY_LABELS_CHANGED); - rib_queue_add (rn); - - return 0; + + if (rib == NULL) + return -1; + + for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) { + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + if (gtype != NEXTHOP_TYPE_IPV4 + && gtype != NEXTHOP_TYPE_IPV4_IFINDEX) + continue; + if (!IPV4_ADDR_SAME(&nexthop->gate.ipv4, &gate->ipv4)) + continue; + if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX + && nexthop->ifindex != ifindex) + continue; + goto found; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + if (gtype != NEXTHOP_TYPE_IPV6 + && gtype != NEXTHOP_TYPE_IPV6_IFINDEX) + continue; + if (!IPV6_ADDR_SAME(&nexthop->gate.ipv6, &gate->ipv6)) + continue; + if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX + && nexthop->ifindex != ifindex) + continue; + goto found; + default: + break; + } + } + /* nexthop not found */ + return -1; + +found: + if (add && nexthop->nh_label_type == ZEBRA_LSP_NONE) + nexthop_add_labels(nexthop, type, 1, &out_label); + else if (!add && nexthop->nh_label_type == type) + nexthop_del_labels(nexthop); + else + return 0; + + SET_FLAG(rib->status, RIB_ENTRY_CHANGED); + SET_FLAG(rib->status, RIB_ENTRY_LABELS_CHANGED); + rib_queue_add(rn); + + return 0; } /* @@ -1357,198 +1276,185 @@ mpls_ftn_update (int add, struct zebra_vrf *zvrf, enum lsp_types_t type, * a new LSP entry or a new NHLFE for an existing in-label or an update of * the out-label for an existing NHLFE (update case). */ -int -mpls_lsp_install (struct zebra_vrf *zvrf, enum lsp_types_t type, - mpls_label_t in_label, mpls_label_t out_label, - enum nexthop_types_t gtype, union g_addr *gate, - char *ifname, ifindex_t ifindex) +int mpls_lsp_install(struct zebra_vrf *zvrf, enum lsp_types_t type, + mpls_label_t in_label, mpls_label_t out_label, + enum nexthop_types_t gtype, union g_addr *gate, + char *ifname, ifindex_t ifindex) { - struct hash *lsp_table; - zebra_ile_t tmp_ile; - zebra_lsp_t *lsp; - zebra_nhlfe_t *nhlfe; - char buf[BUFSIZ]; - - /* Lookup table. */ - lsp_table = zvrf->lsp_table; - if (!lsp_table) - return -1; - - /* If entry is present, exit. */ - tmp_ile.in_label = in_label; - lsp = hash_get (lsp_table, &tmp_ile, lsp_alloc); - if (!lsp) - return -1; - nhlfe = nhlfe_find (lsp, type, gtype, gate, ifname, ifindex); - if (nhlfe) - { - struct nexthop *nh = nhlfe->nexthop; - - assert (nh); - assert (nh->nh_label); - - /* Clear deleted flag (in case it was set) */ - UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_DELETED); - if (nh->nh_label->label[0] == out_label) - /* No change */ - return 0; - - if (IS_ZEBRA_DEBUG_MPLS) - { - nhlfe2str (nhlfe, buf, BUFSIZ); - zlog_debug ("LSP in-label %u type %d nexthop %s " - "out-label changed to %u (old %u)", - in_label, type, buf, - out_label, nh->nh_label->label[0]); - } - - /* Update out label, trigger processing. */ - nh->nh_label->label[0] = out_label; - } - else - { - /* Add LSP entry to this nexthop */ - nhlfe = nhlfe_add (lsp, type, gtype, gate, - ifname, ifindex, out_label); - if (!nhlfe) - return -1; - - if (IS_ZEBRA_DEBUG_MPLS) - { - nhlfe2str (nhlfe, buf, BUFSIZ); - zlog_debug ("Add LSP in-label %u type %d nexthop %s " - "out-label %u", in_label, type, buf, out_label); - } - - lsp->addr_family = NHLFE_FAMILY (nhlfe); - } - - /* Mark NHLFE, queue LSP for processing. */ - SET_FLAG(nhlfe->flags, NHLFE_FLAG_CHANGED); - if (lsp_processq_add (lsp)) - return -1; - - return 0; + struct hash *lsp_table; + zebra_ile_t tmp_ile; + zebra_lsp_t *lsp; + zebra_nhlfe_t *nhlfe; + char buf[BUFSIZ]; + + /* Lookup table. */ + lsp_table = zvrf->lsp_table; + if (!lsp_table) + return -1; + + /* If entry is present, exit. */ + tmp_ile.in_label = in_label; + lsp = hash_get(lsp_table, &tmp_ile, lsp_alloc); + if (!lsp) + return -1; + nhlfe = nhlfe_find(lsp, type, gtype, gate, ifname, ifindex); + if (nhlfe) { + struct nexthop *nh = nhlfe->nexthop; + + assert(nh); + assert(nh->nh_label); + + /* Clear deleted flag (in case it was set) */ + UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_DELETED); + if (nh->nh_label->label[0] == out_label) + /* No change */ + return 0; + + if (IS_ZEBRA_DEBUG_MPLS) { + nhlfe2str(nhlfe, buf, BUFSIZ); + zlog_debug( + "LSP in-label %u type %d nexthop %s " + "out-label changed to %u (old %u)", + in_label, type, buf, out_label, + nh->nh_label->label[0]); + } + + /* Update out label, trigger processing. */ + nh->nh_label->label[0] = out_label; + } else { + /* Add LSP entry to this nexthop */ + nhlfe = nhlfe_add(lsp, type, gtype, gate, ifname, ifindex, + out_label); + if (!nhlfe) + return -1; + + if (IS_ZEBRA_DEBUG_MPLS) { + nhlfe2str(nhlfe, buf, BUFSIZ); + zlog_debug( + "Add LSP in-label %u type %d nexthop %s " + "out-label %u", + in_label, type, buf, out_label); + } + + lsp->addr_family = NHLFE_FAMILY(nhlfe); + } + + /* Mark NHLFE, queue LSP for processing. */ + SET_FLAG(nhlfe->flags, NHLFE_FLAG_CHANGED); + if (lsp_processq_add(lsp)) + return -1; + + return 0; } /* * Uninstall a particular NHLFE in the forwarding table. If this is * the only NHLFE, the entire LSP forwarding entry has to be deleted. */ -int -mpls_lsp_uninstall (struct zebra_vrf *zvrf, enum lsp_types_t type, - mpls_label_t in_label, enum nexthop_types_t gtype, - union g_addr *gate, char *ifname, ifindex_t ifindex) +int mpls_lsp_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type, + mpls_label_t in_label, enum nexthop_types_t gtype, + union g_addr *gate, char *ifname, ifindex_t ifindex) { - struct hash *lsp_table; - zebra_ile_t tmp_ile; - zebra_lsp_t *lsp; - zebra_nhlfe_t *nhlfe; - char buf[BUFSIZ]; - - /* Lookup table. */ - lsp_table = zvrf->lsp_table; - if (!lsp_table) - return -1; - - /* If entry is not present, exit. */ - tmp_ile.in_label = in_label; - lsp = hash_lookup (lsp_table, &tmp_ile); - if (!lsp) - return 0; - nhlfe = nhlfe_find (lsp, type, gtype, gate, ifname, ifindex); - if (!nhlfe) - return 0; - - if (IS_ZEBRA_DEBUG_MPLS) - { - nhlfe2str (nhlfe, buf, BUFSIZ); - zlog_debug ("Del LSP in-label %u type %d nexthop %s flags 0x%x", - in_label, type, buf, nhlfe->flags); - } - - /* Mark NHLFE for delete or directly delete, as appropriate. */ - if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED)) - { - UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_CHANGED); - SET_FLAG (nhlfe->flags, NHLFE_FLAG_DELETED); - if (lsp_processq_add (lsp)) - return -1; - } - else - { - nhlfe_del (nhlfe); - - /* Free LSP entry if no other NHLFEs and not scheduled. */ - if (!lsp->nhlfe_list && - !CHECK_FLAG (lsp->flags, LSP_FLAG_SCHEDULED)) - { - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("Free LSP in-label %u flags 0x%x", - lsp->ile.in_label, lsp->flags); - - lsp = hash_release(lsp_table, &lsp->ile); - if (lsp) - XFREE(MTYPE_LSP, lsp); - } - } - return 0; + struct hash *lsp_table; + zebra_ile_t tmp_ile; + zebra_lsp_t *lsp; + zebra_nhlfe_t *nhlfe; + char buf[BUFSIZ]; + + /* Lookup table. */ + lsp_table = zvrf->lsp_table; + if (!lsp_table) + return -1; + + /* If entry is not present, exit. */ + tmp_ile.in_label = in_label; + lsp = hash_lookup(lsp_table, &tmp_ile); + if (!lsp) + return 0; + nhlfe = nhlfe_find(lsp, type, gtype, gate, ifname, ifindex); + if (!nhlfe) + return 0; + + if (IS_ZEBRA_DEBUG_MPLS) { + nhlfe2str(nhlfe, buf, BUFSIZ); + zlog_debug("Del LSP in-label %u type %d nexthop %s flags 0x%x", + in_label, type, buf, nhlfe->flags); + } + + /* Mark NHLFE for delete or directly delete, as appropriate. */ + if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED)) { + UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_CHANGED); + SET_FLAG(nhlfe->flags, NHLFE_FLAG_DELETED); + if (lsp_processq_add(lsp)) + return -1; + } else { + nhlfe_del(nhlfe); + + /* Free LSP entry if no other NHLFEs and not scheduled. */ + if (!lsp->nhlfe_list + && !CHECK_FLAG(lsp->flags, LSP_FLAG_SCHEDULED)) { + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug("Free LSP in-label %u flags 0x%x", + lsp->ile.in_label, lsp->flags); + + lsp = hash_release(lsp_table, &lsp->ile); + if (lsp) + XFREE(MTYPE_LSP, lsp); + } + } + return 0; } /* * Uninstall all LDP NHLFEs for a particular LSP forwarding entry. * If no other NHLFEs exist, the entry would be deleted. */ -void -mpls_ldp_lsp_uninstall_all (struct hash_backet *backet, void *ctxt) +void mpls_ldp_lsp_uninstall_all(struct hash_backet *backet, void *ctxt) { - zebra_lsp_t *lsp; - struct hash *lsp_table; + zebra_lsp_t *lsp; + struct hash *lsp_table; - lsp = (zebra_lsp_t *) backet->data; - if (!lsp || !lsp->nhlfe_list) - return; + lsp = (zebra_lsp_t *)backet->data; + if (!lsp || !lsp->nhlfe_list) + return; - lsp_table = ctxt; - if (!lsp_table) - return; + lsp_table = ctxt; + if (!lsp_table) + return; - mpls_lsp_uninstall_all (lsp_table, lsp, ZEBRA_LSP_LDP); + mpls_lsp_uninstall_all(lsp_table, lsp, ZEBRA_LSP_LDP); } /* * Uninstall all LDP FEC-To-NHLFE (FTN) bindings of the given address-family. */ -void -mpls_ldp_ftn_uninstall_all (struct zebra_vrf *zvrf, int afi) +void mpls_ldp_ftn_uninstall_all(struct zebra_vrf *zvrf, int afi) { - struct route_table *table; - struct route_node *rn; - struct rib *rib; - struct nexthop *nexthop; - int update; - - /* Process routes of interested address-families. */ - table = zebra_vrf_table (afi, SAFI_UNICAST, zvrf_id (zvrf)); - if (!table) - return; - - for (rn = route_top (table); rn; rn = route_next (rn)) - { - update = 0; - RNODE_FOREACH_RIB (rn, rib) - for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) - if (nexthop->nh_label_type == ZEBRA_LSP_LDP) - { - nexthop_del_labels (nexthop); - SET_FLAG (rib->status, RIB_ENTRY_CHANGED); - SET_FLAG (rib->status, RIB_ENTRY_LABELS_CHANGED); - update = 1; - } - - if (update) - rib_queue_add (rn); - } + struct route_table *table; + struct route_node *rn; + struct rib *rib; + struct nexthop *nexthop; + int update; + + /* Process routes of interested address-families. */ + table = zebra_vrf_table(afi, SAFI_UNICAST, zvrf_id(zvrf)); + if (!table) + return; + + for (rn = route_top(table); rn; rn = route_next(rn)) { + update = 0; + RNODE_FOREACH_RIB(rn, rib) + for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) + if (nexthop->nh_label_type == ZEBRA_LSP_LDP) { + nexthop_del_labels(nexthop); + SET_FLAG(rib->status, RIB_ENTRY_CHANGED); + SET_FLAG(rib->status, RIB_ENTRY_LABELS_CHANGED); + update = 1; + } + + if (update) + rib_queue_add(rn); + } } #if defined(HAVE_CUMULUS) @@ -1558,54 +1464,52 @@ mpls_ldp_ftn_uninstall_all (struct zebra_vrf *zvrf, int afi) * be consistent - i.e., all paths either do a swap or do PHP. This is due * to current HW restrictions. */ -int -zebra_mpls_lsp_label_consistent (struct zebra_vrf *zvrf, mpls_label_t in_label, - mpls_label_t out_label, enum nexthop_types_t gtype, - union g_addr *gate, char *ifname, ifindex_t ifindex) +int zebra_mpls_lsp_label_consistent(struct zebra_vrf *zvrf, + mpls_label_t in_label, + mpls_label_t out_label, + enum nexthop_types_t gtype, + union g_addr *gate, char *ifname, + ifindex_t ifindex) { - struct hash *slsp_table; - zebra_ile_t tmp_ile; - zebra_slsp_t *slsp; - zebra_snhlfe_t *snhlfe; - - /* Lookup table. */ - slsp_table = zvrf->slsp_table; - if (!slsp_table) - return 0; - - /* If entry is not present, exit. */ - tmp_ile.in_label = in_label; - slsp = hash_lookup (slsp_table, &tmp_ile); - if (!slsp) - return 1; - - snhlfe = snhlfe_find (slsp, gtype, gate, ifname, ifindex); - if (snhlfe) - { - if (snhlfe->out_label == out_label) - return 1; - - /* If not only NHLFE, cannot allow label change. */ - if (snhlfe != slsp->snhlfe_list || - snhlfe->next) - return 0; - } - else - { - /* If other NHLFEs exist, label operation must match. */ - if (slsp->snhlfe_list) - { - int cur_op, new_op; - - cur_op = (slsp->snhlfe_list->out_label == MPLS_IMP_NULL_LABEL); - new_op = (out_label == MPLS_IMP_NULL_LABEL); - if (cur_op != new_op) - return 0; - } - } - - /* Label values are good. */ - return 1; + struct hash *slsp_table; + zebra_ile_t tmp_ile; + zebra_slsp_t *slsp; + zebra_snhlfe_t *snhlfe; + + /* Lookup table. */ + slsp_table = zvrf->slsp_table; + if (!slsp_table) + return 0; + + /* If entry is not present, exit. */ + tmp_ile.in_label = in_label; + slsp = hash_lookup(slsp_table, &tmp_ile); + if (!slsp) + return 1; + + snhlfe = snhlfe_find(slsp, gtype, gate, ifname, ifindex); + if (snhlfe) { + if (snhlfe->out_label == out_label) + return 1; + + /* If not only NHLFE, cannot allow label change. */ + if (snhlfe != slsp->snhlfe_list || snhlfe->next) + return 0; + } else { + /* If other NHLFEs exist, label operation must match. */ + if (slsp->snhlfe_list) { + int cur_op, new_op; + + cur_op = (slsp->snhlfe_list->out_label + == MPLS_IMP_NULL_LABEL); + new_op = (out_label == MPLS_IMP_NULL_LABEL); + if (cur_op != new_op) + return 0; + } + } + + /* Label values are good. */ + return 1; } #endif /* HAVE_CUMULUS */ @@ -1616,64 +1520,62 @@ zebra_mpls_lsp_label_consistent (struct zebra_vrf *zvrf, mpls_label_t in_label, * Note: The label operation (swap or PHP) is common for the LSP entry (all * NHLFEs). */ -int -zebra_mpls_static_lsp_add (struct zebra_vrf *zvrf, mpls_label_t in_label, - mpls_label_t out_label, enum nexthop_types_t gtype, - union g_addr *gate, char *ifname, ifindex_t ifindex) +int zebra_mpls_static_lsp_add(struct zebra_vrf *zvrf, mpls_label_t in_label, + mpls_label_t out_label, + enum nexthop_types_t gtype, union g_addr *gate, + char *ifname, ifindex_t ifindex) { - struct hash *slsp_table; - zebra_ile_t tmp_ile; - zebra_slsp_t *slsp; - zebra_snhlfe_t *snhlfe; - char buf[BUFSIZ]; - - /* Lookup table. */ - slsp_table = zvrf->slsp_table; - if (!slsp_table) - return -1; - - /* If entry is present, exit. */ - tmp_ile.in_label = in_label; - slsp = hash_get (slsp_table, &tmp_ile, slsp_alloc); - if (!slsp) - return -1; - snhlfe = snhlfe_find (slsp, gtype, gate, ifname, ifindex); - if (snhlfe) - { - if (snhlfe->out_label == out_label) - /* No change */ - return 0; - - if (IS_ZEBRA_DEBUG_MPLS) - { - snhlfe2str (snhlfe, buf, BUFSIZ); - zlog_debug ("Upd static LSP in-label %u nexthop %s " - "out-label %u (old %u)", - in_label, buf, out_label, snhlfe->out_label); - } - snhlfe->out_label = out_label; - } - else - { - /* Add static LSP entry to this nexthop */ - snhlfe = snhlfe_add (slsp, gtype, gate, ifname, ifindex, out_label); - if (!snhlfe) - return -1; - - if (IS_ZEBRA_DEBUG_MPLS) - { - snhlfe2str (snhlfe, buf, BUFSIZ); - zlog_debug ("Add static LSP in-label %u nexthop %s out-label %u", - in_label, buf, out_label); - } - } - - /* (Re)Install LSP in the main table. */ - if (mpls_lsp_install (zvrf, ZEBRA_LSP_STATIC, in_label, out_label, gtype, - gate, ifname, ifindex)) - return -1; - - return 0; + struct hash *slsp_table; + zebra_ile_t tmp_ile; + zebra_slsp_t *slsp; + zebra_snhlfe_t *snhlfe; + char buf[BUFSIZ]; + + /* Lookup table. */ + slsp_table = zvrf->slsp_table; + if (!slsp_table) + return -1; + + /* If entry is present, exit. */ + tmp_ile.in_label = in_label; + slsp = hash_get(slsp_table, &tmp_ile, slsp_alloc); + if (!slsp) + return -1; + snhlfe = snhlfe_find(slsp, gtype, gate, ifname, ifindex); + if (snhlfe) { + if (snhlfe->out_label == out_label) + /* No change */ + return 0; + + if (IS_ZEBRA_DEBUG_MPLS) { + snhlfe2str(snhlfe, buf, BUFSIZ); + zlog_debug( + "Upd static LSP in-label %u nexthop %s " + "out-label %u (old %u)", + in_label, buf, out_label, snhlfe->out_label); + } + snhlfe->out_label = out_label; + } else { + /* Add static LSP entry to this nexthop */ + snhlfe = snhlfe_add(slsp, gtype, gate, ifname, ifindex, + out_label); + if (!snhlfe) + return -1; + + if (IS_ZEBRA_DEBUG_MPLS) { + snhlfe2str(snhlfe, buf, BUFSIZ); + zlog_debug( + "Add static LSP in-label %u nexthop %s out-label %u", + in_label, buf, out_label); + } + } + + /* (Re)Install LSP in the main table. */ + if (mpls_lsp_install(zvrf, ZEBRA_LSP_STATIC, in_label, out_label, gtype, + gate, ifname, ifindex)) + return -1; + + return 0; } /* @@ -1683,71 +1585,66 @@ zebra_mpls_static_lsp_add (struct zebra_vrf *zvrf, mpls_label_t in_label, * NOTE: Delete of the only NHLFE will also end up deleting the entire * LSP configuration. */ -int -zebra_mpls_static_lsp_del (struct zebra_vrf *zvrf, mpls_label_t in_label, - enum nexthop_types_t gtype, union g_addr *gate, - char *ifname, ifindex_t ifindex) +int zebra_mpls_static_lsp_del(struct zebra_vrf *zvrf, mpls_label_t in_label, + enum nexthop_types_t gtype, union g_addr *gate, + char *ifname, ifindex_t ifindex) { - struct hash *slsp_table; - zebra_ile_t tmp_ile; - zebra_slsp_t *slsp; - zebra_snhlfe_t *snhlfe; - - /* Lookup table. */ - slsp_table = zvrf->slsp_table; - if (!slsp_table) - return -1; - - /* If entry is not present, exit. */ - tmp_ile.in_label = in_label; - slsp = hash_lookup (slsp_table, &tmp_ile); - if (!slsp) - return 0; - - /* Is it delete of entire LSP or a specific NHLFE? */ - if (gtype == NEXTHOP_TYPE_BLACKHOLE) - { - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("Del static LSP in-label %u", in_label); - - /* Uninstall entire LSP from the main table. */ - mpls_static_lsp_uninstall_all (zvrf, in_label); - - /* Delete all static NHLFEs */ - snhlfe_del_all (slsp); - } - else - { - /* Find specific NHLFE, exit if not found. */ - snhlfe = snhlfe_find (slsp, gtype, gate, ifname, ifindex); - if (!snhlfe) - return 0; - - if (IS_ZEBRA_DEBUG_MPLS) - { - char buf[BUFSIZ]; - snhlfe2str (snhlfe, buf, BUFSIZ); - zlog_debug ("Del static LSP in-label %u nexthop %s", - in_label, buf); - } - - /* Uninstall LSP from the main table. */ - mpls_lsp_uninstall (zvrf, ZEBRA_LSP_STATIC, in_label, gtype, gate, - ifname, ifindex); - - /* Delete static LSP NHLFE */ - snhlfe_del (snhlfe); - } - - /* Remove entire static LSP entry if no NHLFE - valid in either case above. */ - if (!slsp->snhlfe_list) - { - slsp = hash_release(slsp_table, &tmp_ile); - if (slsp) - XFREE(MTYPE_SLSP, slsp); - } - - return 0; + struct hash *slsp_table; + zebra_ile_t tmp_ile; + zebra_slsp_t *slsp; + zebra_snhlfe_t *snhlfe; + + /* Lookup table. */ + slsp_table = zvrf->slsp_table; + if (!slsp_table) + return -1; + + /* If entry is not present, exit. */ + tmp_ile.in_label = in_label; + slsp = hash_lookup(slsp_table, &tmp_ile); + if (!slsp) + return 0; + + /* Is it delete of entire LSP or a specific NHLFE? */ + if (gtype == NEXTHOP_TYPE_BLACKHOLE) { + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug("Del static LSP in-label %u", in_label); + + /* Uninstall entire LSP from the main table. */ + mpls_static_lsp_uninstall_all(zvrf, in_label); + + /* Delete all static NHLFEs */ + snhlfe_del_all(slsp); + } else { + /* Find specific NHLFE, exit if not found. */ + snhlfe = snhlfe_find(slsp, gtype, gate, ifname, ifindex); + if (!snhlfe) + return 0; + + if (IS_ZEBRA_DEBUG_MPLS) { + char buf[BUFSIZ]; + snhlfe2str(snhlfe, buf, BUFSIZ); + zlog_debug("Del static LSP in-label %u nexthop %s", + in_label, buf); + } + + /* Uninstall LSP from the main table. */ + mpls_lsp_uninstall(zvrf, ZEBRA_LSP_STATIC, in_label, gtype, + gate, ifname, ifindex); + + /* Delete static LSP NHLFE */ + snhlfe_del(snhlfe); + } + + /* Remove entire static LSP entry if no NHLFE - valid in either case + * above. */ + if (!slsp->snhlfe_list) { + slsp = hash_release(slsp_table, &tmp_ile); + if (slsp) + XFREE(MTYPE_SLSP, slsp); + } + + return 0; } /* @@ -1755,150 +1652,154 @@ zebra_mpls_static_lsp_del (struct zebra_vrf *zvrf, mpls_label_t in_label, * Called upon changes that may affect one or more of them such as * interface or nexthop state changes. */ -void -zebra_mpls_lsp_schedule (struct zebra_vrf *zvrf) +void zebra_mpls_lsp_schedule(struct zebra_vrf *zvrf) { - if (!zvrf) - return; - hash_iterate(zvrf->lsp_table, lsp_schedule, NULL); + if (!zvrf) + return; + hash_iterate(zvrf->lsp_table, lsp_schedule, NULL); } /* * Display MPLS label forwarding table for a specific LSP * (VTY command handler). */ -void -zebra_mpls_print_lsp (struct vty *vty, struct zebra_vrf *zvrf, mpls_label_t label, - u_char use_json) +void zebra_mpls_print_lsp(struct vty *vty, struct zebra_vrf *zvrf, + mpls_label_t label, u_char use_json) { - struct hash *lsp_table; - zebra_lsp_t *lsp; - zebra_ile_t tmp_ile; - json_object *json = NULL; - - /* Lookup table. */ - lsp_table = zvrf->lsp_table; - if (!lsp_table) - return; - - /* If entry is not present, exit. */ - tmp_ile.in_label = label; - lsp = hash_lookup (lsp_table, &tmp_ile); - if (!lsp) - return; - - if (use_json) - { - json = lsp_json(lsp); - vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE); - json_object_free(json); - } - else - lsp_print (lsp, (void *)vty); + struct hash *lsp_table; + zebra_lsp_t *lsp; + zebra_ile_t tmp_ile; + json_object *json = NULL; + + /* Lookup table. */ + lsp_table = zvrf->lsp_table; + if (!lsp_table) + return; + + /* If entry is not present, exit. */ + tmp_ile.in_label = label; + lsp = hash_lookup(lsp_table, &tmp_ile); + if (!lsp) + return; + + if (use_json) { + json = lsp_json(lsp); + vty_out(vty, "%s%s", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY), + VTY_NEWLINE); + json_object_free(json); + } else + lsp_print(lsp, (void *)vty); } /* * Display MPLS label forwarding table (VTY command handler). */ -void -zebra_mpls_print_lsp_table (struct vty *vty, struct zebra_vrf *zvrf, - u_char use_json) +void zebra_mpls_print_lsp_table(struct vty *vty, struct zebra_vrf *zvrf, + u_char use_json) { - char buf[BUFSIZ]; - json_object *json = NULL; - zebra_lsp_t *lsp = NULL; - zebra_nhlfe_t *nhlfe = NULL; - struct nexthop *nexthop = NULL; - struct listnode *node = NULL; - struct list *lsp_list = hash_get_sorted_list(zvrf->lsp_table, lsp_cmp); - - if (use_json) - { - json = json_object_new_object(); - - for (ALL_LIST_ELEMENTS_RO(lsp_list, node, lsp)) - json_object_object_add(json, label2str(lsp->ile.in_label, buf, BUFSIZ), - lsp_json(lsp)); - - vty_out (vty, "%s%s", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY), VTY_NEWLINE); - json_object_free(json); - } - else - { - vty_out (vty, " Inbound Outbound%s", VTY_NEWLINE); - vty_out (vty, " Label Type Nexthop Label%s", VTY_NEWLINE); - vty_out (vty, "-------- ------- --------------- --------%s", VTY_NEWLINE); - - for (ALL_LIST_ELEMENTS_RO(lsp_list, node, lsp)) - { - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) - { - vty_out (vty, "%8d %7s ", lsp->ile.in_label, nhlfe_type2str(nhlfe->type)); - nexthop = nhlfe->nexthop; - - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - vty_out (vty, "%15s", inet_ntoa (nexthop->gate.ipv4)); - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - vty_out (vty, "%15s", inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ)); - break; - default: - break; - } - - vty_out (vty, " %8d%s", nexthop->nh_label->label[0], VTY_NEWLINE); - } - } - - vty_out (vty, "%s", VTY_NEWLINE); - } - - list_delete (lsp_list); + char buf[BUFSIZ]; + json_object *json = NULL; + zebra_lsp_t *lsp = NULL; + zebra_nhlfe_t *nhlfe = NULL; + struct nexthop *nexthop = NULL; + struct listnode *node = NULL; + struct list *lsp_list = hash_get_sorted_list(zvrf->lsp_table, lsp_cmp); + + if (use_json) { + json = json_object_new_object(); + + for (ALL_LIST_ELEMENTS_RO(lsp_list, node, lsp)) + json_object_object_add( + json, label2str(lsp->ile.in_label, buf, BUFSIZ), + lsp_json(lsp)); + + vty_out(vty, "%s%s", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY), + VTY_NEWLINE); + json_object_free(json); + } else { + vty_out(vty, " Inbound Outbound%s", + VTY_NEWLINE); + vty_out(vty, " Label Type Nexthop Label%s", + VTY_NEWLINE); + vty_out(vty, "-------- ------- --------------- --------%s", + VTY_NEWLINE); + + for (ALL_LIST_ELEMENTS_RO(lsp_list, node, lsp)) { + for (nhlfe = lsp->nhlfe_list; nhlfe; + nhlfe = nhlfe->next) { + vty_out(vty, "%8d %7s ", lsp->ile.in_label, + nhlfe_type2str(nhlfe->type)); + nexthop = nhlfe->nexthop; + + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + vty_out(vty, "%15s", + inet_ntoa(nexthop->gate.ipv4)); + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + vty_out(vty, "%15s", + inet_ntop(AF_INET6, + &nexthop->gate.ipv6, + buf, BUFSIZ)); + break; + default: + break; + } + + vty_out(vty, " %8d%s", + nexthop->nh_label->label[0], + VTY_NEWLINE); + } + } + + vty_out(vty, "%s", VTY_NEWLINE); + } + + list_delete(lsp_list); } /* * Display MPLS LSP configuration of all static LSPs (VTY command handler). */ -int -zebra_mpls_write_lsp_config (struct vty *vty, struct zebra_vrf *zvrf) +int zebra_mpls_write_lsp_config(struct vty *vty, struct zebra_vrf *zvrf) { - zebra_slsp_t *slsp; - zebra_snhlfe_t *snhlfe; - struct listnode *node; - struct list *slsp_list = hash_get_sorted_list(zvrf->slsp_table, slsp_cmp); - - for (ALL_LIST_ELEMENTS_RO(slsp_list, node, slsp)) - { - for (snhlfe = slsp->snhlfe_list; snhlfe; snhlfe = snhlfe->next) - { - char buf[INET6_ADDRSTRLEN]; - char lstr[30]; - - snhlfe2str (snhlfe, buf, BUFSIZ); - switch (snhlfe->out_label) { - case MPLS_V4_EXP_NULL_LABEL: - case MPLS_V6_EXP_NULL_LABEL: - strlcpy(lstr, "explicit-null", sizeof(lstr)); - break; - case MPLS_IMP_NULL_LABEL: - strlcpy(lstr, "implicit-null", sizeof(lstr)); - break; - default: - sprintf(lstr, "%u", snhlfe->out_label); - break; - } - - vty_out (vty, "mpls lsp %u %s %s%s", - slsp->ile.in_label, buf, lstr, VTY_NEWLINE); - } - } + zebra_slsp_t *slsp; + zebra_snhlfe_t *snhlfe; + struct listnode *node; + struct list *slsp_list = + hash_get_sorted_list(zvrf->slsp_table, slsp_cmp); + + for (ALL_LIST_ELEMENTS_RO(slsp_list, node, slsp)) { + for (snhlfe = slsp->snhlfe_list; snhlfe; + snhlfe = snhlfe->next) { + char buf[INET6_ADDRSTRLEN]; + char lstr[30]; + + snhlfe2str(snhlfe, buf, BUFSIZ); + switch (snhlfe->out_label) { + case MPLS_V4_EXP_NULL_LABEL: + case MPLS_V6_EXP_NULL_LABEL: + strlcpy(lstr, "explicit-null", sizeof(lstr)); + break; + case MPLS_IMP_NULL_LABEL: + strlcpy(lstr, "implicit-null", sizeof(lstr)); + break; + default: + sprintf(lstr, "%u", snhlfe->out_label); + break; + } + + vty_out(vty, "mpls lsp %u %s %s%s", slsp->ile.in_label, + buf, lstr, VTY_NEWLINE); + } + } - list_delete (slsp_list); - return (zvrf->slsp_table->count ? 1 : 0); + list_delete(slsp_list); + return (zvrf->slsp_table->count ? 1 : 0); } /* @@ -1906,42 +1807,38 @@ zebra_mpls_write_lsp_config (struct vty *vty, struct zebra_vrf *zvrf) * entries from the kernel. * NOTE: Currently supported only for default VRF. */ -void -zebra_mpls_close_tables (struct zebra_vrf *zvrf) +void zebra_mpls_close_tables(struct zebra_vrf *zvrf) { - hash_iterate(zvrf->lsp_table, lsp_uninstall_from_kernel, NULL); - hash_clean(zvrf->lsp_table, NULL); - hash_free(zvrf->lsp_table); - hash_clean(zvrf->slsp_table, NULL); - hash_free(zvrf->slsp_table); + hash_iterate(zvrf->lsp_table, lsp_uninstall_from_kernel, NULL); + hash_clean(zvrf->lsp_table, NULL); + hash_free(zvrf->lsp_table); + hash_clean(zvrf->slsp_table, NULL); + hash_free(zvrf->slsp_table); } /* * Allocate MPLS tables for this VRF and do other initialization. * NOTE: Currently supported only for default VRF. */ -void -zebra_mpls_init_tables (struct zebra_vrf *zvrf) +void zebra_mpls_init_tables(struct zebra_vrf *zvrf) { - if (!zvrf) - return; - zvrf->slsp_table = hash_create(label_hash, label_cmp); - zvrf->lsp_table = hash_create(label_hash, label_cmp); - zvrf->mpls_flags = 0; + if (!zvrf) + return; + zvrf->slsp_table = hash_create(label_hash, label_cmp); + zvrf->lsp_table = hash_create(label_hash, label_cmp); + zvrf->mpls_flags = 0; } /* * Global MPLS initialization. */ -void -zebra_mpls_init (void) +void zebra_mpls_init(void) { - if (mpls_kernel_init () < 0) - { - zlog_warn ("Disabling MPLS support (no kernel support)"); - return; - } - - mpls_enabled = 1; - mpls_processq_init (&zebrad); + if (mpls_kernel_init() < 0) { + zlog_warn("Disabling MPLS support (no kernel support)"); + return; + } + + mpls_enabled = 1; + mpls_processq_init(&zebrad); } |
