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;
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:
continue;
if (!mpls_ftn_update_nexthop(add, nexthop, type,
out_label))
- return 0;
+ break;
found = true;
break;
case NEXTHOP_TYPE_IPV6:
continue;
if (!mpls_ftn_update_nexthop(add, nexthop, type,
out_label))
- return 0;
+ break;
found = true;
break;
default:
}
}
- 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,
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;
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)