From: Mark Stapp Date: Thu, 7 May 2020 20:21:20 +0000 (-0400) Subject: zebra: backup LSP zapi processing X-Git-Tag: base_7.5~322^2 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=f2e7f4eba44ddb448e18e89c46f6318164bfa39a;p=matthieu%2Ffrr.git zebra: backup LSP zapi processing 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 --- diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 9f099d2819..9f0153dae2 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -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 */ diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c index af9dfb5bbb..1210430b06 100644 --- a/zebra/zebra_mpls.c +++ b/zebra/zebra_mpls.c @@ -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) diff --git a/zebra/zebra_mpls.h b/zebra/zebra_mpls.h index 11eb82eb41..9b5fb39573 100644 --- a/zebra/zebra_mpls.h +++ b/zebra/zebra_mpls.h @@ -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.