summaryrefslogtreecommitdiff
path: root/zebra/zebra_mpls.c
diff options
context:
space:
mode:
authorStephen Worley <sworley@cumulusnetworks.com>2019-05-14 16:35:13 -0700
committerStephen Worley <sworley@cumulusnetworks.com>2019-10-25 11:13:40 -0400
commitda1371420204efbdaef17138392b146708cfbf4c (patch)
tree27b8671b8f61998ab88e307acee95533d6bf4dd8 /zebra/zebra_mpls.c
parent2f65aee06ad31d720a316f9d7dee90dcdaebcd41 (diff)
zebra: Create a new NHE if the mpls labels change
We should create a new NHE if the mpls labels change since we hash on them. This adds the functonality to do that and decrement the refcnt on the old one. Signed-off-by: Stephen Worley <sworley@cumulusnetworks.com>
Diffstat (limited to 'zebra/zebra_mpls.c')
-rw-r--r--zebra/zebra_mpls.c52
1 files changed, 40 insertions, 12 deletions
diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c
index 6e0c0b8d88..cbbb02be35 100644
--- a/zebra/zebra_mpls.c
+++ b/zebra/zebra_mpls.c
@@ -2590,11 +2590,13 @@ int mpls_ftn_update(int add, 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 = {};
+ struct nhg_hash_entry *nhe = NULL;
bool found;
+ 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;
@@ -2610,8 +2612,15 @@ int mpls_ftn_update(int add, struct zebra_vrf *zvrf, enum lsp_types_t type,
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->ng);
+
found = false;
- for (nexthop = re->ng->nexthop; nexthop; nexthop = nexthop->next) {
+ for (nexthop = new_grp.nexthop; nexthop; nexthop = nexthop->next) {
switch (nexthop->type) {
case NEXTHOP_TYPE_IPV4:
case NEXTHOP_TYPE_IPV4_IFINDEX:
@@ -2625,7 +2634,7 @@ int mpls_ftn_update(int add, struct zebra_vrf *zvrf, enum lsp_types_t type,
continue;
if (!mpls_ftn_update_nexthop(add, nexthop, type,
out_label))
- return 0;
+ break;
found = true;
break;
case NEXTHOP_TYPE_IPV6:
@@ -2640,7 +2649,7 @@ int mpls_ftn_update(int add, struct zebra_vrf *zvrf, enum lsp_types_t type,
continue;
if (!mpls_ftn_update_nexthop(add, nexthop, type,
out_label))
- return 0;
+ break;
found = true;
break;
default:
@@ -2648,14 +2657,19 @@ int mpls_ftn_update(int add, struct zebra_vrf *zvrf, enum lsp_types_t type,
}
}
- if (!found)
- return -1;
+ if (found) {
+ nhe = zebra_nhg_rib_find(0, &new_grp, re->vrf_id, afi);
- SET_FLAG(re->status, ROUTE_ENTRY_CHANGED);
- SET_FLAG(re->status, ROUTE_ENTRY_LABELS_CHANGED);
- rib_queue_add(rn);
+ zebra_nhg_re_update_ref(re, nhe);
- return 0;
+ SET_FLAG(re->status, ROUTE_ENTRY_CHANGED);
+ SET_FLAG(re->status, ROUTE_ENTRY_LABELS_CHANGED);
+ 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,
@@ -2889,7 +2903,12 @@ static void mpls_ftn_uninstall_all(struct zebra_vrf *zvrf,
for (rn = route_top(table); rn; rn = route_next(rn)) {
update = 0;
RNODE_FOREACH_RE (rn, re) {
- for (nexthop = re->ng->nexthop; nexthop;
+ struct nexthop_group new_grp = {};
+ struct nhg_hash_entry *nhe = NULL;
+
+ nexthop_group_copy(&new_grp, re->ng);
+
+ for (nexthop = new_grp.nexthop; nexthop;
nexthop = nexthop->next) {
if (nexthop->nh_label_type != lsp_type)
continue;
@@ -2900,6 +2919,15 @@ static void mpls_ftn_uninstall_all(struct zebra_vrf *zvrf,
ROUTE_ENTRY_LABELS_CHANGED);
update = 1;
}
+
+ if (CHECK_FLAG(re->status,
+ ROUTE_ENTRY_LABELS_CHANGED)) {
+ nhe = zebra_nhg_rib_find(0, &new_grp,
+ re->vrf_id, afi);
+ zebra_nhg_re_update_ref(re, nhe);
+ }
+
+ nexthops_free(new_grp.nexthop);
}
if (update)