diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index da7f4cf64e..db2b9e002e 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -3684,7 +3684,7 @@ int dplane_show_helper(struct vty *vty, bool detailed) int dplane_show_provs_helper(struct vty *vty, bool detailed) { struct zebra_dplane_provider *prov; - uint64_t in, in_max, out, out_max; + uint64_t in, in_q, in_max, out, out_q, out_max; vty_out(vty, "Zebra dataplane providers:\n"); @@ -3697,17 +3697,20 @@ int dplane_show_provs_helper(struct vty *vty, bool detailed) in = atomic_load_explicit(&prov->dp_in_counter, memory_order_relaxed); + in_q = atomic_load_explicit(&prov->dp_in_queued, + memory_order_relaxed); in_max = atomic_load_explicit(&prov->dp_in_max, memory_order_relaxed); out = atomic_load_explicit(&prov->dp_out_counter, memory_order_relaxed); + out_q = atomic_load_explicit(&prov->dp_out_queued, + memory_order_relaxed); out_max = atomic_load_explicit(&prov->dp_out_max, memory_order_relaxed); - vty_out(vty, - "%s (%u): in: %" PRIu64 ", q_max: %" PRIu64 - ", out: %" PRIu64 ", q_max: %" PRIu64 "\n", - prov->dp_name, prov->dp_id, in, in_max, out, out_max); + vty_out(vty, "%s (%u): in: %"PRIu64", q: %"PRIu64", q_max: %"PRIu64", out: %"PRIu64", q: %"PRIu64", q_max: %"PRIu64"\n", + prov->dp_name, prov->dp_id, in, in_q, in_max, + out, out_q, out_max); DPLANE_LOCK(); prov = TAILQ_NEXT(prov, dp_prov_link); @@ -3912,11 +3915,24 @@ uint32_t dplane_provider_out_ctx_queue_len(struct zebra_dplane_provider *prov) void dplane_provider_enqueue_out_ctx(struct zebra_dplane_provider *prov, struct zebra_dplane_ctx *ctx) { + uint64_t curr, high; + dplane_provider_lock(prov); TAILQ_INSERT_TAIL(&(prov->dp_ctx_out_q), ctx, zd_q_entries); + /* Maintain out-queue counters */ + atomic_fetch_add_explicit(&(prov->dp_out_queued), 1, + memory_order_relaxed); + curr = atomic_load_explicit(&prov->dp_out_queued, + memory_order_relaxed); + high = atomic_load_explicit(&prov->dp_out_max, + memory_order_relaxed); + if (curr > high) + atomic_store_explicit(&prov->dp_out_max, curr, + memory_order_relaxed); + dplane_provider_unlock(prov); atomic_fetch_add_explicit(&(prov->dp_out_counter), 1, diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 1f92c43a69..07cf0604fa 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -2941,8 +2941,10 @@ int rib_add_multipath_nhe(afi_t afi, safi_t safi, struct prefix *p, struct nhg_hash_entry *nhe = NULL; struct route_table *table; struct route_node *rn; - struct route_entry *same = NULL; + struct route_entry *same = NULL, *first_same = NULL; int ret = 0; + int same_count = 0; + rib_dest_t *dest; if (!re || !re_nhe) return -1; @@ -3010,14 +3012,22 @@ int rib_add_multipath_nhe(afi_t afi, safi_t safi, struct prefix *p, * for the install don't do a route replace. */ RNODE_FOREACH_RE (rn, same) { - if (CHECK_FLAG(same->status, ROUTE_ENTRY_REMOVED)) + if (CHECK_FLAG(same->status, ROUTE_ENTRY_REMOVED)) { + same_count++; continue; + } /* Compare various route_entry properties */ - if (rib_compare_routes(re, same)) - break; + if (rib_compare_routes(re, same)) { + same_count++; + + if (first_same == NULL) + first_same = same; + } } + same = first_same; + /* If this route is kernel/connected route, notify the dataplane. */ if (RIB_SYSTEM_ROUTE(re)) { /* Notify dataplane */ @@ -3027,8 +3037,9 @@ int rib_add_multipath_nhe(afi_t afi, safi_t safi, struct prefix *p, /* Link new re to node.*/ if (IS_ZEBRA_DEBUG_RIB) { rnode_debug(rn, re->vrf_id, - "Inserting route rn %p, re %p (%s) existing %p", - rn, re, zebra_route_string(re->type), same); + "Inserting route rn %p, re %p (%s) existing %p, same_count %d", + rn, re, zebra_route_string(re->type), same, + same_count); if (IS_ZEBRA_DEBUG_RIB_DETAILED) route_entry_dump(p, src_p, re); @@ -3042,6 +3053,24 @@ int rib_add_multipath_nhe(afi_t afi, safi_t safi, struct prefix *p, if (same) rib_delnode(rn, same); + /* See if we can remove some RE entries that are queued for + * removal, but won't be considered in rib processing. + */ + dest = rib_dest_from_rnode(rn); + RNODE_FOREACH_RE_SAFE (rn, re, same) { + if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) { + /* If the route was used earlier, must retain it. */ + if (dest && re == dest->selected_fib) + continue; + + if (IS_ZEBRA_DEBUG_RIB) + rnode_debug(rn, re->vrf_id, "rn %p, removing unneeded re %p", + rn, re); + + rib_unlink(rn, re); + } + } + route_unlock_node(rn); return ret; }