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 <mjs@voltanet.io>
This commit is contained in:
Mark Stapp 2020-05-07 16:21:20 -04:00
parent 1323491d7a
commit f2e7f4eba4
3 changed files with 421 additions and 256 deletions

View File

@ -1998,9 +1998,7 @@ static void zread_mpls_labels_add(ZAPI_HANDLER_ARGS)
{ {
struct stream *s; struct stream *s;
struct zapi_labels zl; struct zapi_labels zl;
int ret, i; int ret;
struct zapi_nexthop *znh;
char buf[NEXTHOP_STRLEN];
/* Get input stream. */ /* Get input stream. */
s = msg; s = msg;
@ -2014,55 +2012,11 @@ static void zread_mpls_labels_add(ZAPI_HANDLER_ARGS)
if (!mpls_enabled) if (!mpls_enabled)
return; return;
for (i = 0; i < zl.nexthop_num; i++) { ret = mpls_zapi_labels_process(true, zvrf, &zl);
if (ret < 0) {
znh = &zl.nexthops[i]; if (IS_ZEBRA_DEBUG_RECV)
zlog_debug("%s: Error processing zapi request",
ret = mpls_lsp_znh_install(zvrf, zl.type, zl.local_label, znh); __func__);
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;
}
}
} }
} }
@ -2080,6 +2034,7 @@ static void zread_mpls_labels_delete(ZAPI_HANDLER_ARGS)
{ {
struct stream *s; struct stream *s;
struct zapi_labels zl; struct zapi_labels zl;
int ret;
/* Get input stream. */ /* Get input stream. */
s = msg; s = msg;
@ -2094,21 +2049,11 @@ static void zread_mpls_labels_delete(ZAPI_HANDLER_ARGS)
return; return;
if (zl.nexthop_num > 0) { if (zl.nexthop_num > 0) {
for (int i = 0; i < zl.nexthop_num; i++) { ret = mpls_zapi_labels_process(false /*delete*/, zvrf, &zl);
struct zapi_nexthop *znh; if (ret < 0) {
if (IS_ZEBRA_DEBUG_RECV)
znh = &zl.nexthops[i]; zlog_debug("%s: Error processing zapi request",
mpls_lsp_uninstall(zvrf, zl.type, zl.local_label, __func__);
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]);
} }
} else { } else {
mpls_lsp_uninstall_all_vrf(zvrf, zl.type, zl.local_label); 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) if (!mpls_enabled)
return; 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); mpls_lsp_uninstall_all_vrf(zvrf, zl.type, zl.local_label);
if (CHECK_FLAG(zl.message, ZAPI_LABELS_FTN)) if (CHECK_FLAG(zl.message, ZAPI_LABELS_FTN))
mpls_ftn_uninstall(zvrf, zl.type, &zl.route.prefix, mpls_ftn_uninstall(zvrf, zl.type, &zl.route.prefix,
zl.route.type, zl.route.instance); zl.route.type, zl.route.instance);
for (int i = 0; i < zl.nexthop_num; i++) { mpls_zapi_labels_process(true, zvrf, &zl);
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]);
}
}
} }
/* Send response to a table manager connect request to client */ /* Send response to a table manager connect request to client */

View File

@ -117,6 +117,10 @@ static void nhlfe_out_label_update(zebra_nhlfe_t *nhlfe,
struct mpls_label_stack *nh_label); struct mpls_label_stack *nh_label);
static int mpls_lsp_uninstall_all(struct hash *lsp_table, zebra_lsp_t *lsp, static int mpls_lsp_uninstall_all(struct hash *lsp_table, zebra_lsp_t *lsp,
enum lsp_types_t type); 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, static int mpls_static_lsp_uninstall_all(struct zebra_vrf *zvrf,
mpls_label_t in_label); mpls_label_t in_label);
static void nhlfe_print(zebra_nhlfe_t *nhlfe, struct vty *vty); 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_lsp_uninstall_all_type(struct hash_bucket *bucket, void *ctxt);
static void mpls_ftn_uninstall_all(struct zebra_vrf *zvrf, static void mpls_ftn_uninstall_all(struct zebra_vrf *zvrf,
int afi, enum lsp_types_t lsp_type); 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 */ /* List implementations - declare internal linkage */
DECLARE_DLIST(snhlfe_list, struct zebra_snhlfe_t_, list); 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. */ /* Queue LSP for processing, if needed, else delete. */
if (schedule_lsp) { if (schedule_lsp) {
if (lsp_processq_add(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); fec_print(rn->info, vty);
} }
static void mpls_zebra_nhg_update(struct route_entry *re, afi_t afi, static void mpls_zebra_nhe_update(struct route_entry *re, afi_t afi,
struct nexthop_group *new_grp) struct nhg_hash_entry *new_nhe)
{ {
struct nhg_hash_entry *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); route_entry_update_nhe(re, nhe);
} }
static bool mpls_ftn_update_nexthop(int add, struct nexthop *nexthop, static bool ftn_update_nexthop(bool add_p, struct nexthop *nexthop,
enum lsp_types_t type, mpls_label_t label) enum lsp_types_t type,
const struct zapi_nexthop *znh)
{ {
if (add && nexthop->nh_label_type == ZEBRA_LSP_NONE) if (add_p && nexthop->nh_label_type == ZEBRA_LSP_NONE)
nexthop_add_labels(nexthop, type, 1, &label); nexthop_add_labels(nexthop, type, znh->label_num, znh->labels);
else if (!add && nexthop->nh_label_type == type) else if (!add_p && nexthop->nh_label_type == type)
nexthop_del_labels(nexthop); nexthop_del_labels(nexthop);
else else
return false; return false;
@ -2758,98 +2788,6 @@ static bool mpls_ftn_update_nexthop(int add, struct nexthop *nexthop,
return true; 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)
{
struct route_table *table;
struct route_node *rn;
struct route_entry *re;
struct nexthop *nexthop;
struct nexthop_group new_grp = {};
bool found;
afi_t afi = family2afi(prefix->family);
/* Lookup table. */
table = zebra_vrf_table(afi, SAFI_UNICAST, zvrf_id(zvrf));
if (!table)
return -1;
/* 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 == 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
*/
nexthop_group_copy(&new_grp, &(re->nhe->nhg));
found = false;
for (nexthop = new_grp.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;
if (!mpls_ftn_update_nexthop(add, nexthop, type,
out_label))
break;
found = true;
break;
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;
if (!mpls_ftn_update_nexthop(add, nexthop, type,
out_label))
break;
found = true;
break;
default:
break;
}
}
if (found) {
SET_FLAG(re->status, ROUTE_ENTRY_CHANGED);
SET_FLAG(re->status, ROUTE_ENTRY_LABELS_CHANGED);
mpls_zebra_nhg_update(re, afi, &new_grp);
rib_queue_add(rn);
}
nexthops_free(new_grp.nexthop);
return found ? 0 : -1;
}
int mpls_ftn_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type, int mpls_ftn_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type,
struct prefix *prefix, uint8_t route_type, struct prefix *prefix, uint8_t route_type,
unsigned short route_instance) unsigned short route_instance)
@ -2858,7 +2796,7 @@ int mpls_ftn_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type,
struct route_node *rn; struct route_node *rn;
struct route_entry *re; struct route_entry *re;
struct nexthop *nexthop; struct nexthop *nexthop;
struct nexthop_group new_grp = {}; struct nhg_hash_entry *new_nhe;
afi_t afi = family2afi(prefix->family); afi_t afi = family2afi(prefix->family);
/* Lookup table. */ /* Lookup table. */
@ -2877,23 +2815,293 @@ int mpls_ftn_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type,
if (re == NULL) if (re == NULL)
return -1; return -1;
nexthop_group_copy(&new_grp, &(re->nhe->nhg)); /*
* Nexthops are now shared by multiple routes, so we have to make
* a local copy, modify the copy, then update the route.
*/
new_nhe = zebra_nhe_copy(re->nhe, 0);
for (nexthop = new_grp.nexthop; nexthop; nexthop = nexthop->next) for (nexthop = new_nhe->nhg.nexthop; nexthop; nexthop = nexthop->next)
nexthop_del_labels(nexthop); 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_CHANGED);
SET_FLAG(re->status, ROUTE_ENTRY_LABELS_CHANGED); SET_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);
rib_queue_add(rn); rib_queue_add(rn);
return 0; 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 (znh->type != NEXTHOP_TYPE_IPV4
&& znh->type != NEXTHOP_TYPE_IPV4_IFINDEX)
continue;
if (!IPV4_ADDR_SAME(&nexthop->gate.ipv4,
&znh->gate.ipv4))
continue;
if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
&& nexthop->ifindex != znh->ifindex)
continue;
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 (znh->type != NEXTHOP_TYPE_IPV6
&& znh->type != NEXTHOP_TYPE_IPV6_IFINDEX)
continue;
if (!IPV6_ADDR_SAME(&nexthop->gate.ipv6,
&znh->gate.ipv6))
continue;
if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX
&& nexthop->ifindex != znh->ifindex)
continue;
found = true;
if (!ftn_update_nexthop(add_p, nexthop, type, znh))
break;
success = true;
break;
default:
break;
}
if (found)
break;
}
return success;
}
/*
* 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;
/* 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;
}
/* Prep for route/FEC update if requested */
if (CHECK_FLAG(zl->message, ZAPI_LABELS_FTN)) {
prefix = &zl->route.prefix;
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;
}
}
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);
} 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;
}
/* 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);
}
}
/*
* 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 (i = 0; i < zl->backup_nexthop_num; i++) {
znh = &zl->backup_nexthops[i];
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;
}
/* Attempt backup nexthop/FEC update if requested */
if (re == NULL || zebra_nhg_get_backup_nhg(new_nhe) == NULL)
continue;
/* 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);
}
}
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;
}
/* /*
* Install/update a NHLFE for an LSP in the forwarding table. This may be * Install/update a NHLFE for an LSP in the forwarding table. This may be
* a new LSP entry or a new NHLFE for an existing in-label or an update of * a new LSP entry or a new NHLFE for an existing in-label or an update of
@ -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 * Install or replace NHLFE, using info from zapi nexthop
*/ */
int mpls_lsp_znh_install(struct zebra_vrf *zvrf, enum lsp_types_t type, static int lsp_znh_install(zebra_lsp_t *lsp, enum lsp_types_t type,
mpls_label_t in_label, const struct zapi_nexthop *znh)
const struct zapi_nexthop *znh)
{ {
struct hash *lsp_table;
zebra_ile_t tmp_ile;
zebra_lsp_t *lsp;
zebra_nhlfe_t *nhlfe; 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, nhlfe = lsp_add_nhlfe(lsp, type, znh->label_num, znh->labels,
znh->type, &znh->gate, znh->ifindex); znh->type, &znh->gate, znh->ifindex);
if (nhlfe == NULL) 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. * 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, static int lsp_backup_znh_install(zebra_lsp_t *lsp, enum lsp_types_t type,
mpls_label_t in_label, const struct zapi_nexthop *znh)
const struct zapi_nexthop *znh)
{ {
struct hash *lsp_table;
zebra_ile_t tmp_ile;
zebra_lsp_t *lsp;
zebra_nhlfe_t *nhlfe; zebra_nhlfe_t *nhlfe;
/* Lookup table. */ nhlfe = lsp_add_backup_nhlfe(lsp, type, znh->label_num,
lsp_table = zvrf->lsp_table; znh->labels, znh->type, &znh->gate,
if (!lsp_table) znh->ifindex);
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);
if (nhlfe == NULL) { if (nhlfe == NULL) {
if (IS_ZEBRA_DEBUG_MPLS) if (IS_ZEBRA_DEBUG_MPLS)
zlog_debug("%s: unable to add backup nhlfe, label: %u", zlog_debug("%s: unable to add backup nhlfe, label: %u",
__func__, in_label); __func__, lsp->ile.in_label);
return -1; return -1;
} }
@ -3219,14 +3394,62 @@ int mpls_lsp_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type,
nhlfe_del(nhlfe); nhlfe_del(nhlfe);
/* Free LSP entry if no other NHLFEs and not scheduled. */ /* Free LSP entry if no other NHLFEs and not scheduled. */
if ((nhlfe_list_first(&lsp->nhlfe_list) == NULL) lsp_check_free(lsp_table, &lsp);
&& !CHECK_FLAG(lsp->flags, LSP_FLAG_SCHEDULED))
lsp_free(lsp_table, &lsp);
} }
return 0; 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;
}
int mpls_lsp_uninstall_all_vrf(struct zebra_vrf *zvrf, enum lsp_types_t type, int mpls_lsp_uninstall_all_vrf(struct zebra_vrf *zvrf, enum lsp_types_t type,
mpls_label_t in_label) mpls_label_t in_label)
{ {
@ -3280,7 +3503,8 @@ static void mpls_ftn_uninstall_all(struct zebra_vrf *zvrf,
struct route_node *rn; struct route_node *rn;
struct route_entry *re; struct route_entry *re;
struct nexthop *nexthop; struct nexthop *nexthop;
int update; struct nexthop_group *nhg;
bool update;
/* Process routes of interested address-families. */ /* Process routes of interested address-families. */
table = zebra_vrf_table(afi, SAFI_UNICAST, zvrf_id(zvrf)); 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; return;
for (rn = route_top(table); rn; rn = route_next(rn)) { for (rn = route_top(table); rn; rn = route_next(rn)) {
update = 0; update = false;
RNODE_FOREACH_RE (rn, re) { 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) { nexthop = nexthop->next) {
if (nexthop->nh_label_type != lsp_type) if (nexthop->nh_label_type != lsp_type)
continue; 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_CHANGED);
SET_FLAG(re->status, SET_FLAG(re->status,
ROUTE_ENTRY_LABELS_CHANGED); 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)) 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) if (update)

View File

@ -302,12 +302,11 @@ void zebra_mpls_print_fec(struct vty *vty, struct zebra_vrf *zvrf,
struct prefix *p); 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, int mpls_zapi_labels_process(bool add_p, struct zebra_vrf *zvrf,
struct prefix *prefix, enum nexthop_types_t gtype, const struct zapi_labels *zl);
union g_addr *gate, ifindex_t ifindex, uint8_t route_type,
unsigned short route_instance, mpls_label_t out_label);
/* /*
* Uninstall all NHLFEs bound to a single FEC. * 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 mpls_label_t *out_labels, enum nexthop_types_t gtype,
const union g_addr *gate, ifindex_t ifindex); 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 * Uninstall a particular NHLFE in the forwarding table. If this is
* the only NHLFE, the entire LSP forwarding entry has to be deleted. * the only NHLFE, the entire LSP forwarding entry has to be deleted.