]> git.puffer.fish Git - matthieu/frr.git/commitdiff
zebra: backup LSP zapi processing
authorMark Stapp <mjs@voltanet.io>
Thu, 7 May 2020 20:21:20 +0000 (16:21 -0400)
committerMark Stapp <mjs@voltanet.io>
Mon, 1 Jun 2020 18:46:32 +0000 (14:46 -0400)
Move some processing of zapi label messages so they can be
handled more efficiently. Handle zapi delete and replace
messages.

Signed-off-by: Mark Stapp <mjs@voltanet.io>
zebra/zapi_msg.c
zebra/zebra_mpls.c
zebra/zebra_mpls.h

index 9f099d281911bc73a56c6e4272a6b21357e3a71f..9f0153dae2347eb923b62e0880ee358cbc502fd4 100644 (file)
@@ -1998,9 +1998,7 @@ static void zread_mpls_labels_add(ZAPI_HANDLER_ARGS)
 {
        struct stream *s;
        struct zapi_labels zl;
-       int ret, i;
-       struct zapi_nexthop *znh;
-       char buf[NEXTHOP_STRLEN];
+       int ret;
 
        /* Get input stream.  */
        s = msg;
@@ -2014,55 +2012,11 @@ static void zread_mpls_labels_add(ZAPI_HANDLER_ARGS)
        if (!mpls_enabled)
                return;
 
-       for (i = 0; i < zl.nexthop_num; i++) {
-
-               znh = &zl.nexthops[i];
-
-               ret = mpls_lsp_znh_install(zvrf, zl.type, zl.local_label, znh);
-               if (ret < 0) {
-                       if (IS_ZEBRA_DEBUG_RECV) {
-                               zapi_nexthop2str(znh, buf, sizeof(buf));
-                               zlog_debug("%s: Unable to install LSP: label %u, znh %s",
-                                          __func__, zl.local_label, buf);
-                       }
-                       continue;
-               }
-
-               if (CHECK_FLAG(zl.message, ZAPI_LABELS_FTN)) {
-                       ret = mpls_ftn_update(1 /*add*/, zvrf, zl.type,
-                                             &zl.route.prefix, znh->type,
-                                             &znh->gate, znh->ifindex,
-                                             zl.route.type, zl.route.instance,
-                                             znh->labels[0]);
-                       if (ret < 0) {
-                               if (IS_ZEBRA_DEBUG_RECV) {
-                                       zapi_nexthop2str(znh, buf, sizeof(buf));
-                                       zlog_debug("%s: Unable to update FEC: label %u, znh %s",
-                                                  __func__, zl.local_label,
-                                                  buf);
-                               }
-                       }
-               }
-       }
-
-       /* Process backup LSPs/nexthop entries also. */
-       if (CHECK_FLAG(zl.message, ZAPI_LABELS_HAS_BACKUPS)) {
-               for (i = 0; i < zl.backup_nexthop_num; i++) {
-
-                       znh = &zl.backup_nexthops[i];
-
-                       ret = mpls_lsp_backup_znh_install(zvrf, zl.type,
-                                                         zl.local_label, znh);
-                       if (ret < 0) {
-                               if (IS_ZEBRA_DEBUG_RECV) {
-                                       zapi_nexthop2str(znh, buf, sizeof(buf));
-                                       zlog_debug("%s: Unable to install backup LSP: label %u, znh %s",
-                                                  __func__, zl.local_label,
-                                                  buf);
-                               }
-                               continue;
-                       }
-               }
+       ret = mpls_zapi_labels_process(true, zvrf, &zl);
+       if (ret < 0) {
+               if (IS_ZEBRA_DEBUG_RECV)
+                       zlog_debug("%s: Error processing zapi request",
+                                  __func__);
        }
 }
 
@@ -2080,6 +2034,7 @@ static void zread_mpls_labels_delete(ZAPI_HANDLER_ARGS)
 {
        struct stream *s;
        struct zapi_labels zl;
+       int ret;
 
        /* Get input stream.  */
        s = msg;
@@ -2094,21 +2049,11 @@ static void zread_mpls_labels_delete(ZAPI_HANDLER_ARGS)
                return;
 
        if (zl.nexthop_num > 0) {
-               for (int i = 0; i < zl.nexthop_num; i++) {
-                       struct zapi_nexthop *znh;
-
-                       znh = &zl.nexthops[i];
-                       mpls_lsp_uninstall(zvrf, zl.type, zl.local_label,
-                                          znh->type, &znh->gate,
-                                          znh->ifindex);
-
-                       if (CHECK_FLAG(zl.message, ZAPI_LABELS_FTN))
-                               mpls_ftn_update(0, zvrf, zl.type,
-                                               &zl.route.prefix, znh->type,
-                                               &znh->gate, znh->ifindex,
-                                               zl.route.type,
-                                               zl.route.instance,
-                                               znh->labels[0]);
+               ret = mpls_zapi_labels_process(false /*delete*/, zvrf, &zl);
+               if (ret < 0) {
+                       if (IS_ZEBRA_DEBUG_RECV)
+                               zlog_debug("%s: Error processing zapi request",
+                                          __func__);
                }
        } else {
                mpls_lsp_uninstall_all_vrf(zvrf, zl.type, zl.local_label);
@@ -2148,26 +2093,16 @@ static void zread_mpls_labels_replace(ZAPI_HANDLER_ARGS)
        if (!mpls_enabled)
                return;
 
+       /* This removes everything, then re-adds from the client's
+        * zapi message. Since the LSP will be processed later, on this
+        * this same pthread, all of the changes will 'appear' at once.
+        */
        mpls_lsp_uninstall_all_vrf(zvrf, zl.type, zl.local_label);
        if (CHECK_FLAG(zl.message, ZAPI_LABELS_FTN))
                mpls_ftn_uninstall(zvrf, zl.type, &zl.route.prefix,
                                   zl.route.type, zl.route.instance);
 
-       for (int i = 0; i < zl.nexthop_num; i++) {
-               struct zapi_nexthop *znh;
-
-               znh = &zl.nexthops[i];
-               mpls_lsp_install(zvrf, zl.type, zl.local_label,
-                                znh->label_num, znh->labels, znh->type,
-                                &znh->gate, znh->ifindex);
-
-               if (CHECK_FLAG(zl.message, ZAPI_LABELS_FTN)) {
-                       mpls_ftn_update(1, zvrf, zl.type, &zl.route.prefix,
-                                       znh->type, &znh->gate, znh->ifindex,
-                                       zl.route.type, zl.route.instance,
-                                       znh->labels[0]);
-               }
-       }
+       mpls_zapi_labels_process(true, zvrf, &zl);
 }
 
 /* Send response to a table manager connect request to client */
index af9dfb5bbb8b549778c665eb8c4d6be9b84453f8..1210430b06e525cb07e11c1ec9fcf7a11bb1c533 100644 (file)
@@ -117,6 +117,10 @@ static void nhlfe_out_label_update(zebra_nhlfe_t *nhlfe,
                                   struct mpls_label_stack *nh_label);
 static int mpls_lsp_uninstall_all(struct hash *lsp_table, zebra_lsp_t *lsp,
                                  enum lsp_types_t type);
+static int lsp_backup_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type,
+                               mpls_label_t in_label,
+                               enum nexthop_types_t gtype,
+                               const union g_addr *gate, ifindex_t ifindex);
 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);
@@ -137,6 +141,10 @@ static char *snhlfe2str(zebra_snhlfe_t *snhlfe, char *buf, int size);
 static void mpls_lsp_uninstall_all_type(struct hash_bucket *bucket, void *ctxt);
 static void mpls_ftn_uninstall_all(struct zebra_vrf *zvrf,
                                   int afi, enum lsp_types_t lsp_type);
+static int lsp_znh_install(zebra_lsp_t *lsp, enum lsp_types_t type,
+                          const struct zapi_nexthop *znh);
+static int lsp_backup_znh_install(zebra_lsp_t *lsp, enum lsp_types_t type,
+                                 const struct zapi_nexthop *znh);
 
 /* List implementations - declare internal linkage */
 DECLARE_DLIST(snhlfe_list, struct zebra_snhlfe_t_, list);
@@ -1435,6 +1443,27 @@ static int mpls_lsp_uninstall_all(struct hash *lsp_table, zebra_lsp_t *lsp,
                }
        }
 
+       frr_each_safe(nhlfe_list, &lsp->backup_nhlfe_list, nhlfe) {
+               /* Skip non-static NHLFEs */
+               if (nhlfe->type != type)
+                       continue;
+
+               if (IS_ZEBRA_DEBUG_MPLS) {
+                       nhlfe2str(nhlfe, buf, BUFSIZ);
+                       zlog_debug(
+                               "Del backup 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))
@@ -2735,22 +2764,23 @@ void zebra_mpls_print_fec(struct vty *vty, struct zebra_vrf *zvrf,
        fec_print(rn->info, vty);
 }
 
-static void mpls_zebra_nhg_update(struct route_entry *re, afi_t afi,
-                                 struct nexthop_group *new_grp)
+static void mpls_zebra_nhe_update(struct route_entry *re, afi_t afi,
+                                 struct nhg_hash_entry *new_nhe)
 {
        struct nhg_hash_entry *nhe;
 
-       nhe = zebra_nhg_rib_find(0, new_grp, afi);
+       nhe = zebra_nhg_rib_find_nhe(new_nhe, afi);
 
        route_entry_update_nhe(re, nhe);
 }
 
-static bool mpls_ftn_update_nexthop(int add, struct nexthop *nexthop,
-                                   enum lsp_types_t type, mpls_label_t label)
+static bool ftn_update_nexthop(bool add_p, struct nexthop *nexthop,
+                              enum lsp_types_t type,
+                              const struct zapi_nexthop *znh)
 {
-       if (add && nexthop->nh_label_type == ZEBRA_LSP_NONE)
-               nexthop_add_labels(nexthop, type, 1, &label);
-       else if (!add && nexthop->nh_label_type == type)
+       if (add_p && nexthop->nh_label_type == ZEBRA_LSP_NONE)
+               nexthop_add_labels(nexthop, type, znh->label_num, znh->labels);
+       else if (!add_p && nexthop->nh_label_type == type)
                nexthop_del_labels(nexthop);
        else
                return false;
@@ -2758,20 +2788,15 @@ static bool mpls_ftn_update_nexthop(int add, struct nexthop *nexthop,
        return true;
 }
 
-/*
- * 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, uint8_t route_type,
-                   unsigned short route_instance, mpls_label_t out_label)
+int mpls_ftn_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type,
+                      struct prefix *prefix, uint8_t route_type,
+                      unsigned short route_instance)
 {
        struct route_table *table;
        struct route_node *rn;
        struct route_entry *re;
        struct nexthop *nexthop;
-       struct nexthop_group new_grp = {};
-       bool found;
+       struct nhg_hash_entry *new_nhe;
        afi_t afi = family2afi(prefix->family);
 
        /* Lookup table.  */
@@ -2787,111 +2812,294 @@ int mpls_ftn_update(int add, struct zebra_vrf *zvrf, enum lsp_types_t type,
                if (re->type == route_type && re->instance == route_instance)
                        break;
        }
-
        if (re == NULL)
                return -1;
 
        /*
-        * Copy over current nexthops into a temporary group.
-        * We can't just change the values here since we are hashing
-        * on labels. We need to create a whole new group
+        * Nexthops are now shared by multiple routes, so we have to make
+        * a local copy, modify the copy, then update the route.
         */
-       nexthop_group_copy(&new_grp, &(re->nhe->nhg));
+       new_nhe = zebra_nhe_copy(re->nhe, 0);
 
-       found = false;
-       for (nexthop = new_grp.nexthop; nexthop; nexthop = nexthop->next) {
+       for (nexthop = new_nhe->nhg.nexthop; nexthop; nexthop = nexthop->next)
+               nexthop_del_labels(nexthop);
+
+       /* Update backup routes/nexthops also, if present. */
+       if (zebra_nhg_get_backup_nhg(new_nhe) != NULL) {
+               for (nexthop = new_nhe->backup_info->nhe->nhg.nexthop; nexthop;
+                    nexthop = nexthop->next)
+                       nexthop_del_labels(nexthop);
+       }
+
+       SET_FLAG(re->status, ROUTE_ENTRY_CHANGED);
+       SET_FLAG(re->status, ROUTE_ENTRY_LABELS_CHANGED);
+
+       mpls_zebra_nhe_update(re, afi, new_nhe);
+
+       zebra_nhg_free(new_nhe);
+
+       rib_queue_add(rn);
+
+       return 0;
+}
+
+/*
+ * Iterate through a list of nexthops, for a match for 'znh'. If found,
+ * update its labels according to 'add_p', and return 'true' if successful.
+ */
+static bool ftn_update_znh(bool add_p, enum lsp_types_t type,
+                          struct nexthop *head, const struct zapi_nexthop *znh)
+{
+       bool found = false, success = false;
+       struct nexthop *nexthop;
+
+       for (nexthop = head; 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)
+                       if (znh->type != NEXTHOP_TYPE_IPV4
+                           && znh->type != NEXTHOP_TYPE_IPV4_IFINDEX)
                                continue;
-                       if (!IPV4_ADDR_SAME(&nexthop->gate.ipv4, &gate->ipv4))
+                       if (!IPV4_ADDR_SAME(&nexthop->gate.ipv4,
+                                           &znh->gate.ipv4))
                                continue;
                        if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
-                           && nexthop->ifindex != ifindex)
+                           && nexthop->ifindex != znh->ifindex)
                                continue;
-                       if (!mpls_ftn_update_nexthop(add, nexthop, type,
-                                                    out_label))
-                               break;
+
                        found = true;
+
+                       if (!ftn_update_nexthop(add_p, nexthop, type, znh))
+                               break;
+
+                       success = true;
                        break;
                case NEXTHOP_TYPE_IPV6:
                case NEXTHOP_TYPE_IPV6_IFINDEX:
-                       if (gtype != NEXTHOP_TYPE_IPV6
-                           && gtype != NEXTHOP_TYPE_IPV6_IFINDEX)
+                       if (znh->type != NEXTHOP_TYPE_IPV6
+                           && znh->type != NEXTHOP_TYPE_IPV6_IFINDEX)
                                continue;
-                       if (!IPV6_ADDR_SAME(&nexthop->gate.ipv6, &gate->ipv6))
+                       if (!IPV6_ADDR_SAME(&nexthop->gate.ipv6,
+                                           &znh->gate.ipv6))
                                continue;
                        if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX
-                           && nexthop->ifindex != ifindex)
+                           && nexthop->ifindex != znh->ifindex)
                                continue;
-                       if (!mpls_ftn_update_nexthop(add, nexthop, type,
-                                                    out_label))
-                               break;
+
                        found = true;
+
+                       if (!ftn_update_nexthop(add_p, nexthop, type, znh))
+                               break;
+                       success = true;
                        break;
                default:
                        break;
                }
+
+               if (found)
+                       break;
        }
 
-       if (found) {
-               SET_FLAG(re->status, ROUTE_ENTRY_CHANGED);
-               SET_FLAG(re->status, ROUTE_ENTRY_LABELS_CHANGED);
+       return success;
+}
 
-               mpls_zebra_nhg_update(re, afi, &new_grp);
+/*
+ * Install/uninstall LSP and (optionally) FEC-To-NHLFE (FTN) bindings,
+ * using zapi message info.
+ * There are several changes that need to be made, in several zebra
+ * data structures, so we want to do all the work required at once.
+ */
+int mpls_zapi_labels_process(bool add_p, struct zebra_vrf *zvrf,
+                            const struct zapi_labels *zl)
+{
+       int i, counter, ret = 0;
+       char buf[NEXTHOP_STRLEN], prefix_buf[PREFIX_STRLEN];
+       const struct zapi_nexthop *znh;
+       struct route_table *table;
+       struct route_node *rn = NULL;
+       struct route_entry *re = NULL;
+       struct nhg_hash_entry *new_nhe = NULL;
+       bool found;
+       afi_t afi = AFI_IP;
+       const struct prefix *prefix = NULL;
+       struct hash *lsp_table;
+       zebra_ile_t tmp_ile;
+       zebra_lsp_t *lsp = NULL;
 
-               rib_queue_add(rn);
+       /* Prep LSP for add case */
+       if (add_p) {
+               /* Lookup table. */
+               lsp_table = zvrf->lsp_table;
+               if (!lsp_table)
+                       return -1;
+
+               /* Find or create LSP object */
+               tmp_ile.in_label = zl->local_label;
+               lsp = hash_get(lsp_table, &tmp_ile, lsp_alloc);
+               if (!lsp)
+                       return -1;
        }
 
-       nexthops_free(new_grp.nexthop);
+       /* Prep for route/FEC update if requested */
+       if (CHECK_FLAG(zl->message, ZAPI_LABELS_FTN)) {
+               prefix = &zl->route.prefix;
 
-       return found ? 0 : -1;
-}
+               afi = family2afi(prefix->family);
 
-int mpls_ftn_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type,
-                      struct prefix *prefix, uint8_t route_type,
-                      unsigned short route_instance)
-{
-       struct route_table *table;
-       struct route_node *rn;
-       struct route_entry *re;
-       struct nexthop *nexthop;
-       struct nexthop_group new_grp = {};
-       afi_t afi = family2afi(prefix->family);
+               /* Lookup table.  */
+               table = zebra_vrf_table(afi, SAFI_UNICAST, zvrf_id(zvrf));
+               if (table) {
+                       /* Lookup existing route */
+                       rn = route_node_get(table, prefix);
+                       RNODE_FOREACH_RE(rn, re) {
+                               if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
+                                       continue;
+                               if (re->type == zl->route.type &&
+                                   re->instance == zl->route.instance)
+                                       break;
+                       }
+               }
 
-       /* Lookup table.  */
-       table = zebra_vrf_table(afi, SAFI_UNICAST, zvrf_id(zvrf));
-       if (!table)
-               return -1;
+               if (re) {
+                       /*
+                        * Copy over current nexthops into a temporary group.
+                        * We can't just change the values here since the nhgs
+                        * are shared and if the labels change, we'll need
+                        * to find or create a new nhg. We need to create
+                        * a whole temporary group, make changes to it,
+                        * then attach that to the route.
+                        */
+                       new_nhe = zebra_nhe_copy(re->nhe, 0);
 
-       /* Lookup existing route */
-       rn = route_node_get(table, prefix);
-       RNODE_FOREACH_RE (rn, re) {
-               if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
+               } else {
+                       /*
+                        * The old version of the zapi code
+                        * attempted to manage LSPs before trying to
+                        * find a route/FEC, so we'll continue that way.
+                        */
+                       if (IS_ZEBRA_DEBUG_RECV || IS_ZEBRA_DEBUG_MPLS) {
+                               prefix2str(prefix, prefix_buf,
+                                          sizeof(prefix_buf));
+                               zlog_debug("%s: FTN update requested: no route for prefix %s",
+                                          __func__, prefix_buf);
+                       }
+               }
+       }
+
+       /*
+        * Use info from the zapi nexthops to add/replace/remove LSP/FECs
+        */
+
+       counter = 0;
+       for (i = 0; i < zl->nexthop_num; i++) {
+
+               znh = &zl->nexthops[i];
+
+               /* Attempt LSP update */
+               if (add_p)
+                       ret = lsp_znh_install(lsp, zl->type, znh);
+               else
+                       ret = mpls_lsp_uninstall(zvrf, zl->type,
+                                                zl->local_label, znh->type,
+                                                &znh->gate, znh->ifindex);
+               if (ret < 0) {
+                       if (IS_ZEBRA_DEBUG_RECV || IS_ZEBRA_DEBUG_MPLS) {
+                               zapi_nexthop2str(znh, buf, sizeof(buf));
+                               zlog_debug("%s: Unable to %sinstall LSP: label %u, znh %s",
+                                          __func__, (add_p ? "" : "un"),
+                                          zl->local_label, buf);
+                       }
                        continue;
-               if (re->type == route_type && re->instance == route_instance)
-                       break;
+               }
+
+               /* Attempt route/FEC update if requested */
+               if (re == NULL)
+                       continue;
+
+               /* Search the route's nexthops for a match, and update it. */
+               found = ftn_update_znh(add_p, zl->type, new_nhe->nhg.nexthop,
+                                      znh);
+               if (found) {
+                       counter++;
+               } else if (IS_ZEBRA_DEBUG_RECV | IS_ZEBRA_DEBUG_MPLS) {
+                       zapi_nexthop2str(znh, buf, sizeof(buf));
+                       prefix2str(prefix, prefix_buf, sizeof(prefix_buf));
+                       zlog_debug("%s: Unable to update FEC: prefix %s, label %u, znh %s",
+                                  __func__, prefix_buf, zl->local_label, buf);
+               }
        }
-       if (re == NULL)
-               return -1;
 
-       nexthop_group_copy(&new_grp, &(re->nhe->nhg));
+       /*
+        * Process backup LSPs/nexthop entries also. We associate backup
+        * LSP info with backup nexthops.
+        */
+       if (!CHECK_FLAG(zl->message, ZAPI_LABELS_HAS_BACKUPS))
+               goto znh_done;
 
-       for (nexthop = new_grp.nexthop; nexthop; nexthop = nexthop->next)
-               nexthop_del_labels(nexthop);
+       for (i = 0; i < zl->backup_nexthop_num; i++) {
 
-       SET_FLAG(re->status, ROUTE_ENTRY_CHANGED);
-       SET_FLAG(re->status, ROUTE_ENTRY_LABELS_CHANGED);
+               znh = &zl->backup_nexthops[i];
 
-       mpls_zebra_nhg_update(re, afi, &new_grp);
+               if (add_p)
+                       ret = lsp_backup_znh_install(lsp, zl->type, znh);
+               else
+                       ret = lsp_backup_uninstall(zvrf, zl->type,
+                                                  zl->local_label,
+                                                  znh->type, &znh->gate,
+                                                  znh->ifindex);
+
+               if (ret < 0) {
+                       if (IS_ZEBRA_DEBUG_RECV ||
+                           IS_ZEBRA_DEBUG_MPLS) {
+                               zapi_nexthop2str(znh, buf, sizeof(buf));
+                               zlog_debug("%s: Unable to %sinstall backup LSP: label %u, znh %s",
+                                          __func__, (add_p ? "" : "un"),
+                                          zl->local_label, buf);
+                       }
+                       continue;
+               }
 
-       nexthops_free(new_grp.nexthop);
+               /* Attempt backup nexthop/FEC update if requested */
+               if (re == NULL || zebra_nhg_get_backup_nhg(new_nhe) == NULL)
+                       continue;
 
-       rib_queue_add(rn);
+               /* Search the route's backup nexthops for a match
+                * and update it.
+                */
+               found = ftn_update_znh(add_p, zl->type,
+                                      new_nhe->backup_info->nhe->nhg.nexthop,
+                                      znh);
+               if (found) {
+                       counter++;
+               } else if (IS_ZEBRA_DEBUG_RECV | IS_ZEBRA_DEBUG_MPLS) {
+                       zapi_nexthop2str(znh, buf, sizeof(buf));
+                       prefix2str(prefix, prefix_buf, sizeof(prefix_buf));
+                       zlog_debug("%s: Unable to update backup FEC: prefix %s, label %u, znh %s",
+                                  __func__, prefix_buf, zl->local_label, buf);
+               }
+       }
 
-       return 0;
+znh_done:
+
+       /*
+        * If we made changes, update the route, and schedule it
+        * for rib processing
+        */
+       if (re != NULL && counter > 0) {
+               assert(rn != NULL);
+
+               SET_FLAG(re->status, ROUTE_ENTRY_CHANGED);
+               SET_FLAG(re->status, ROUTE_ENTRY_LABELS_CHANGED);
+
+               mpls_zebra_nhe_update(re, afi, new_nhe);
+
+               rib_queue_add(rn);
+       }
+
+       if (new_nhe)
+               zebra_nhg_free(new_nhe);
+
+       return ret;
 }
 
 /*
@@ -3094,26 +3302,11 @@ int mpls_lsp_install(struct zebra_vrf *zvrf, enum lsp_types_t type,
 /*
  * Install or replace NHLFE, using info from zapi nexthop
  */
-int mpls_lsp_znh_install(struct zebra_vrf *zvrf, enum lsp_types_t type,
-                        mpls_label_t in_label,
-                        const struct zapi_nexthop *znh)
+static int lsp_znh_install(zebra_lsp_t *lsp, enum lsp_types_t type,
+                          const struct zapi_nexthop *znh)
 {
-       struct hash *lsp_table;
-       zebra_ile_t tmp_ile;
-       zebra_lsp_t *lsp;
        zebra_nhlfe_t *nhlfe;
 
-       /* Lookup table. */
-       lsp_table = zvrf->lsp_table;
-       if (!lsp_table)
-               return -1;
-
-       /* Find or create LSP object */
-       tmp_ile.in_label = in_label;
-       lsp = hash_get(lsp_table, &tmp_ile, lsp_alloc);
-       if (!lsp)
-               return -1;
-
        nhlfe = lsp_add_nhlfe(lsp, type, znh->label_num, znh->labels,
                              znh->type, &znh->gate, znh->ifindex);
        if (nhlfe == NULL)
@@ -3135,36 +3328,18 @@ int mpls_lsp_znh_install(struct zebra_vrf *zvrf, enum lsp_types_t type,
 /*
  * Install/update backup NHLFE for an LSP, using info from a zapi message.
  */
-int mpls_lsp_backup_znh_install(struct zebra_vrf *zvrf, enum lsp_types_t type,
-                               mpls_label_t in_label,
-                               const struct zapi_nexthop *znh)
+static int lsp_backup_znh_install(zebra_lsp_t *lsp, enum lsp_types_t type,
+                                 const struct zapi_nexthop *znh)
 {
-       struct hash *lsp_table;
-       zebra_ile_t tmp_ile;
-       zebra_lsp_t *lsp;
        zebra_nhlfe_t *nhlfe;
 
-       /* Lookup table. */
-       lsp_table = zvrf->lsp_table;
-       if (!lsp_table)
-               return -1;
-
-       /* Find or create LSP object */
-       tmp_ile.in_label = in_label;
-       lsp = hash_get(lsp_table, &tmp_ile, lsp_alloc);
-       if (!lsp) {
-               if (IS_ZEBRA_DEBUG_MPLS)
-                       zlog_debug("%s: unable to get LSP for label: %u",
-                                  __func__, in_label);
-               return -1;
-       }
-
-       nhlfe = lsp_add_backup_nhlfe(lsp, type, znh->label_num, znh->labels,
-                                    znh->type, &znh->gate, znh->ifindex);
+       nhlfe = lsp_add_backup_nhlfe(lsp, type, znh->label_num,
+                                    znh->labels, znh->type, &znh->gate,
+                                    znh->ifindex);
        if (nhlfe == NULL) {
                if (IS_ZEBRA_DEBUG_MPLS)
                        zlog_debug("%s: unable to add backup nhlfe, label: %u",
-                                  __func__, in_label);
+                                  __func__, lsp->ile.in_label);
                return -1;
        }
 
@@ -3219,10 +3394,58 @@ int mpls_lsp_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type,
                nhlfe_del(nhlfe);
 
                /* Free LSP entry if no other NHLFEs and not scheduled. */
-               if ((nhlfe_list_first(&lsp->nhlfe_list) == NULL)
-                   && !CHECK_FLAG(lsp->flags, LSP_FLAG_SCHEDULED))
-                       lsp_free(lsp_table, &lsp);
+               lsp_check_free(lsp_table, &lsp);
+
+       }
+       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.
+ */
+static int lsp_backup_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type,
+                               mpls_label_t in_label,
+                               enum nexthop_types_t gtype,
+                               const union g_addr *gate, 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->backup_nhlfe_list, type, gtype, gate, ifindex);
+       if (!nhlfe)
+               return 0;
+
+       if (IS_ZEBRA_DEBUG_MPLS) {
+               nhlfe2str(nhlfe, buf, BUFSIZ);
+               zlog_debug("Del backup 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. */
+               lsp_check_free(lsp_table, &lsp);
        }
        return 0;
 }
@@ -3280,7 +3503,8 @@ static void mpls_ftn_uninstall_all(struct zebra_vrf *zvrf,
        struct route_node *rn;
        struct route_entry *re;
        struct nexthop *nexthop;
-       int update;
+       struct nexthop_group *nhg;
+       bool update;
 
        /* Process routes of interested address-families. */
        table = zebra_vrf_table(afi, SAFI_UNICAST, zvrf_id(zvrf));
@@ -3288,13 +3512,15 @@ static void mpls_ftn_uninstall_all(struct zebra_vrf *zvrf,
                return;
 
        for (rn = route_top(table); rn; rn = route_next(rn)) {
-               update = 0;
+               update = false;
+
                RNODE_FOREACH_RE (rn, re) {
-                       struct nexthop_group new_grp = {};
+                       struct nhg_hash_entry *new_nhe;
 
-                       nexthop_group_copy(&new_grp, &(re->nhe->nhg));
+                       new_nhe = zebra_nhe_copy(re->nhe, 0);
 
-                       for (nexthop = new_grp.nexthop; nexthop;
+                       nhg = &new_nhe->nhg;
+                       for (nexthop = nhg->nexthop; nexthop;
                             nexthop = nexthop->next) {
                                if (nexthop->nh_label_type != lsp_type)
                                        continue;
@@ -3303,13 +3529,30 @@ static void mpls_ftn_uninstall_all(struct zebra_vrf *zvrf,
                                SET_FLAG(re->status, ROUTE_ENTRY_CHANGED);
                                SET_FLAG(re->status,
                                         ROUTE_ENTRY_LABELS_CHANGED);
-                               update = 1;
+                               update = true;
+                       }
+
+                       /* Check for backup info and update that also */
+                       nhg = zebra_nhg_get_backup_nhg(new_nhe);
+                       if (nhg != NULL) {
+                               for (nexthop = nhg->nexthop; nexthop;
+                                    nexthop = nexthop->next) {
+                                       if (nexthop->nh_label_type != lsp_type)
+                                               continue;
+
+                                       nexthop_del_labels(nexthop);
+                                       SET_FLAG(re->status,
+                                                ROUTE_ENTRY_CHANGED);
+                                       SET_FLAG(re->status,
+                                                ROUTE_ENTRY_LABELS_CHANGED);
+                                       update = true;
+                               }
                        }
 
                        if (CHECK_FLAG(re->status, ROUTE_ENTRY_LABELS_CHANGED))
-                               mpls_zebra_nhg_update(re, afi, &new_grp);
+                               mpls_zebra_nhe_update(re, afi, new_nhe);
 
-                       nexthops_free(new_grp.nexthop);
+                       zebra_nhg_free(new_nhe);
                }
 
                if (update)
index 11eb82eb41f0ef889d5dc02f90cf8add9f380747..9b5fb39573842bd2e96272a585789ccd10837eec 100644 (file)
@@ -302,12 +302,11 @@ void zebra_mpls_print_fec(struct vty *vty, struct zebra_vrf *zvrf,
                          struct prefix *p);
 
 /*
- * Install/uninstall a FEC-To-NHLFE (FTN) binding.
+ * Handle zapi request to install/uninstall LSP and
+ * (optionally) FEC-To-NHLFE (FTN) bindings.
  */
-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, uint8_t route_type,
-                   unsigned short route_instance, mpls_label_t out_label);
+int mpls_zapi_labels_process(bool add_p, struct zebra_vrf *zvrf,
+                            const struct zapi_labels *zl);
 
 /*
  * Uninstall all NHLFEs bound to a single FEC.
@@ -326,18 +325,6 @@ int mpls_lsp_install(struct zebra_vrf *zvrf, enum lsp_types_t type,
                     const mpls_label_t *out_labels, enum nexthop_types_t gtype,
                     const union g_addr *gate, ifindex_t ifindex);
 
-/* Version using a zapi nexthop directly */
-int mpls_lsp_znh_install(struct zebra_vrf *zvrf, enum lsp_types_t type,
-                        mpls_label_t in_label,
-                        const struct zapi_nexthop *znh);
-
-/*
- * Install/update backup NHLFE for an LSP, using zapi nexthop info.
- */
-int mpls_lsp_backup_znh_install(struct zebra_vrf *zvrf, enum lsp_types_t type,
-                               mpls_label_t in_label,
-                               const struct zapi_nexthop *znh);
-
 /*
  * Uninstall a particular NHLFE in the forwarding table. If this is
  * the only NHLFE, the entire LSP forwarding entry has to be deleted.