diff options
| author | Stephen Worley <sworley@cumulusnetworks.com> | 2019-05-14 16:35:13 -0700 |
|---|---|---|
| committer | Stephen Worley <sworley@cumulusnetworks.com> | 2019-10-25 11:13:40 -0400 |
| commit | da1371420204efbdaef17138392b146708cfbf4c (patch) | |
| tree | 27b8671b8f61998ab88e307acee95533d6bf4dd8 /zebra/zebra_mpls.c | |
| parent | 2f65aee06ad31d720a316f9d7dee90dcdaebcd41 (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.c | 52 |
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) |
