summaryrefslogtreecommitdiff
path: root/zebra/zebra_mpls.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/zebra_mpls.c')
-rw-r--r--zebra/zebra_mpls.c108
1 files changed, 74 insertions, 34 deletions
diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c
index ef1bd02608..5146311c6a 100644
--- a/zebra/zebra_mpls.c
+++ b/zebra/zebra_mpls.c
@@ -102,7 +102,8 @@ static zebra_nhlfe_t *nhlfe_find(zebra_lsp_t *lsp, enum lsp_types_t lsp_type,
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,
- ifindex_t ifindex, mpls_label_t out_label);
+ ifindex_t ifindex, uint8_t num_labels,
+ mpls_label_t *labels);
static int nhlfe_del(zebra_nhlfe_t *snhlfe);
static void nhlfe_out_label_update(zebra_nhlfe_t *nhlfe,
struct mpls_label_stack *nh_label);
@@ -218,7 +219,8 @@ static int lsp_install(struct zebra_vrf *zvrf, mpls_label_t label,
/* Add LSP entry to this nexthop */
nhlfe = nhlfe_add(lsp, lsp_type, nexthop->type,
&nexthop->gate, nexthop->ifindex,
- nexthop->nh_label->label[0]);
+ nexthop->nh_label->num_labels,
+ nexthop->nh_label->label);
if (!nhlfe)
return -1;
@@ -1197,7 +1199,8 @@ static zebra_nhlfe_t *nhlfe_find(zebra_lsp_t *lsp, enum lsp_types_t lsp_type,
*/
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,
- ifindex_t ifindex, mpls_label_t out_label)
+ ifindex_t ifindex, uint8_t num_labels,
+ mpls_label_t labels[])
{
zebra_nhlfe_t *nhlfe;
struct nexthop *nexthop;
@@ -1216,7 +1219,7 @@ static zebra_nhlfe_t *nhlfe_add(zebra_lsp_t *lsp, enum lsp_types_t lsp_type,
XFREE(MTYPE_NHLFE, nhlfe);
return NULL;
}
- nexthop_add_labels(nexthop, lsp_type, 1, &out_label);
+ nexthop_add_labels(nexthop, lsp_type, num_labels, labels);
nexthop->vrf_id = VRF_DEFAULT;
nexthop->type = gtype;
@@ -2083,10 +2086,12 @@ zebra_nhlfe_t *zebra_mpls_lsp_add_nhlfe(zebra_lsp_t *lsp,
enum nexthop_types_t gtype,
union g_addr *gate,
ifindex_t ifindex,
- mpls_label_t out_label)
+ uint8_t num_labels,
+ mpls_label_t out_labels[])
{
/* Just a public pass-through to the internal implementation */
- return nhlfe_add(lsp, lsp_type, gtype, gate, ifindex, out_label);
+ return nhlfe_add(lsp, lsp_type, gtype, gate, ifindex, num_labels,
+ out_labels);
}
/*
@@ -2565,6 +2570,16 @@ 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)
+{
+ struct nhg_hash_entry *nhe;
+
+ nhe = zebra_nhg_rib_find(0, new_grp, afi);
+
+ zebra_nhg_re_update_ref(re, nhe);
+}
+
static bool mpls_ftn_update_nexthop(int add, struct nexthop *nexthop,
enum lsp_types_t type, mpls_label_t label)
{
@@ -2591,7 +2606,6 @@ int mpls_ftn_update(int add, struct zebra_vrf *zvrf, enum lsp_types_t type,
struct route_entry *re;
struct nexthop *nexthop;
struct nexthop_group new_grp = {};
- struct nhg_hash_entry *nhe = NULL;
bool found;
afi_t afi = family2afi(prefix->family);
@@ -2658,12 +2672,11 @@ int mpls_ftn_update(int add, struct zebra_vrf *zvrf, enum lsp_types_t type,
}
if (found) {
- nhe = zebra_nhg_rib_find(0, &new_grp, afi);
-
- zebra_nhg_re_update_ref(re, nhe);
-
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);
}
@@ -2680,10 +2693,11 @@ int mpls_ftn_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type,
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(family2afi(prefix->family), SAFI_UNICAST,
- zvrf_id(zvrf));
+ table = zebra_vrf_table(afi, SAFI_UNICAST, zvrf_id(zvrf));
if (!table)
return -1;
@@ -2698,11 +2712,18 @@ int mpls_ftn_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type,
if (re == NULL)
return -1;
- for (nexthop = re->ng->nexthop; nexthop; nexthop = nexthop->next)
+ nexthop_group_copy(&new_grp, re->ng);
+
+ for (nexthop = new_grp.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_nhg_update(re, afi, &new_grp);
+
+ nexthops_free(new_grp.nexthop);
+
rib_queue_add(rn);
return 0;
@@ -2714,9 +2735,9 @@ int mpls_ftn_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type,
* 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,
- ifindex_t ifindex)
+ mpls_label_t in_label, uint8_t num_out_labels,
+ mpls_label_t out_labels[], enum nexthop_types_t gtype,
+ union g_addr *gate, ifindex_t ifindex)
{
struct hash *lsp_table;
zebra_ile_t tmp_ile;
@@ -2743,33 +2764,56 @@ int mpls_lsp_install(struct zebra_vrf *zvrf, enum lsp_types_t type,
/* Clear deleted flag (in case it was set) */
UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_DELETED);
- if (nh->nh_label->label[0] == out_label)
+ if (nh->nh_label->num_labels == num_out_labels
+ && !memcmp(nh->nh_label->label, out_labels,
+ sizeof(mpls_label_t) * num_out_labels))
/* No change */
return 0;
if (IS_ZEBRA_DEBUG_MPLS) {
+ char buf2[BUFSIZ];
+ char buf3[BUFSIZ];
+
nhlfe2str(nhlfe, buf, BUFSIZ);
+ mpls_label2str(num_out_labels, out_labels, buf2,
+ sizeof(buf2), 0);
+ mpls_label2str(nh->nh_label->num_labels,
+ nh->nh_label->label, buf3, sizeof(buf3),
+ 0);
+
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]);
+ "out-label(s) changed to %s (old %s)",
+ in_label, type, buf, buf2, buf3);
}
- /* Update out label, trigger processing. */
- nh->nh_label->label[0] = out_label;
+ /* Update out label(s), trigger processing. */
+ if (nh->nh_label->num_labels == num_out_labels)
+ memcpy(nh->nh_label->label, out_labels,
+ sizeof(mpls_label_t) * num_out_labels);
+ else {
+ nexthop_del_labels(nh);
+ nexthop_add_labels(nh, type, num_out_labels,
+ out_labels);
+ }
} else {
/* Add LSP entry to this nexthop */
- nhlfe = nhlfe_add(lsp, type, gtype, gate, ifindex, out_label);
+ nhlfe = nhlfe_add(lsp, type, gtype, gate, ifindex,
+ num_out_labels, out_labels);
if (!nhlfe)
return -1;
if (IS_ZEBRA_DEBUG_MPLS) {
+ char buf2[BUFSIZ];
+
nhlfe2str(nhlfe, buf, BUFSIZ);
+ mpls_label2str(num_out_labels, out_labels, buf2,
+ sizeof(buf2), 0);
+
zlog_debug(
"Add LSP in-label %u type %d nexthop %s "
- "out-label %u",
- in_label, type, buf, out_label);
+ "out-label(s) %s",
+ in_label, type, buf, buf2);
}
lsp->addr_family = NHLFE_FAMILY(nhlfe);
@@ -2904,7 +2948,6 @@ static void mpls_ftn_uninstall_all(struct zebra_vrf *zvrf,
update = 0;
RNODE_FOREACH_RE (rn, re) {
struct nexthop_group new_grp = {};
- struct nhg_hash_entry *nhe = NULL;
nexthop_group_copy(&new_grp, re->ng);
@@ -2920,11 +2963,8 @@ static void mpls_ftn_uninstall_all(struct zebra_vrf *zvrf,
update = 1;
}
- if (CHECK_FLAG(re->status,
- ROUTE_ENTRY_LABELS_CHANGED)) {
- nhe = zebra_nhg_rib_find(0, &new_grp, afi);
- zebra_nhg_re_update_ref(re, nhe);
- }
+ if (CHECK_FLAG(re->status, ROUTE_ENTRY_LABELS_CHANGED))
+ mpls_zebra_nhg_update(re, afi, &new_grp);
nexthops_free(new_grp.nexthop);
}
@@ -3046,8 +3086,8 @@ int zebra_mpls_static_lsp_add(struct zebra_vrf *zvrf, mpls_label_t in_label,
}
/* (Re)Install LSP in the main table. */
- if (mpls_lsp_install(zvrf, ZEBRA_LSP_STATIC, in_label, out_label, gtype,
- gate, ifindex))
+ if (mpls_lsp_install(zvrf, ZEBRA_LSP_STATIC, in_label, 1, &out_label,
+ gtype, gate, ifindex))
return -1;
return 0;