void rib_unlink(struct route_node *rn, struct route_entry *re)
{
rib_dest_t *dest;
- rib_table_info_t *info;
+ struct nhg_hash_entry *nhe = NULL;
assert(rn && re);
if (dest->selected_fib == re)
dest->selected_fib = NULL;
- zebra_nhg_decrement_ref(re->nhe);
+ nhe = zebra_nhg_lookup_id(re->nhe_id);
+ if (nhe)
+ zebra_nhg_decrement_ref(nhe);
- // TODO: We need to hold on nh's until refcnt is 0 right?
- nexthops_free(re->ng->nexthop);
- nexthop_group_delete(&re->ng);
nexthops_free(re->fib_ng.nexthop);
XFREE(MTYPE_RE, re);
struct route_table *table;
struct route_node *rn;
struct route_entry *same = NULL;
+ struct nhg_hash_entry *nhe = NULL;
+ struct list *nhg_depends = NULL;
+ /* Default to route afi */
+ afi_t nhg_afi = afi;
int ret = 0;
if (!re)
/* Lookup table. */
table = zebra_vrf_table_with_table_id(afi, safi, re->vrf_id, re->table);
if (!table) {
- nexthops_free(re->ng->nexthop);
- nexthop_group_delete(&re->ng);
+ zebra_nhg_free_group_depends(re->ng, nhg_depends);
XFREE(MTYPE_RE, re);
return 0;
}
if (src_p)
apply_mask_ipv6(src_p);
- re->nhe = zebra_nhg_find(re->ng, re->vrf_id, 0);
- re->nhe->refcnt++;
+ /* If its a group, create a dependency list */
+ if (re->ng && re->ng->nexthop->next) {
+ struct nexthop *nh = NULL;
+ struct nexthop lookup = {0};
+ struct nhg_hash_entry *depend = NULL;
+
+ nhg_depends = nhg_depend_new_list();
+
+ for (ALL_NEXTHOPS_PTR(re->ng, nh)) {
+ lookup = *nh;
+ /* Clear it, since its a group */
+ lookup.next = NULL;
+ /* Use the route afi here, since a single nh */
+ depend = zebra_nhg_find_nexthop(&lookup, afi);
+ nhg_depend_add(nhg_depends, depend);
+ }
+
+ /* change the afi for group */
+ if (listcount(nhg_depends))
+ nhg_afi = AFI_UNSPEC;
+ }
+
+ nhe = zebra_nhg_find(re->ng, re->vrf_id, nhg_afi, re->nhe_id,
+ nhg_depends, false);
+
+ if (nhe) {
+ // TODO: Add interface pointer
+ zebra_nhg_free_group_depends(re->ng, nhg_depends);
+ re->ng = nhe->nhg;
+ re->nhe_id = nhe->id;
+ zebra_nhg_increment_ref(nhe);
+ } else {
+ flog_err(
+ EC_ZEBRA_TABLE_LOOKUP_FAILED,
+ "Zebra failed to find or create a nexthop hash entry for id=%u in a route entry",
+ re->nhe_id);
+ }
+
+
/* Set default distance by route type. */
if (re->distance == 0)
re->distance = route_distance(re->type);
int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
unsigned short instance, int flags, struct prefix *p,
struct prefix_ipv6 *src_p, const struct nexthop *nh,
- uint32_t table_id, uint32_t metric, uint32_t mtu, uint8_t distance,
- route_tag_t tag)
+ uint32_t nhe_id, uint32_t table_id, uint32_t metric, uint32_t mtu,
+ uint8_t distance, route_tag_t tag)
{
- struct route_entry *re;
- struct nexthop *nexthop;
+ struct route_entry *re = NULL;
+ struct nexthop *nexthop = NULL;
/* Allocate new route_entry structure. */
re = XCALLOC(MTYPE_RE, sizeof(struct route_entry));
re->vrf_id = vrf_id;
re->uptime = monotime(NULL);
re->tag = tag;
+ re->nhe_id = nhe_id;
+
re->ng = nexthop_group_new();
/* Add nexthop. */
rib_process_dplane_notify(ctx);
break;
+ case DPLANE_OP_NH_INSTALL:
+ case DPLANE_OP_NH_UPDATE:
+ case DPLANE_OP_NH_DELETE:
+ zebra_nhg_dplane_result(ctx);
+ break;
+
case DPLANE_OP_LSP_INSTALL:
case DPLANE_OP_LSP_UPDATE:
case DPLANE_OP_LSP_DELETE: