Page MenuHomeFreeBSD

D57389.id179080.diff
No OneTemporary

D57389.id179080.diff

diff --git a/sys/net/route/nhgrp_ctl.c b/sys/net/route/nhgrp_ctl.c
--- a/sys/net/route/nhgrp_ctl.c
+++ b/sys/net/route/nhgrp_ctl.c
@@ -251,14 +251,29 @@
struct nhgrp_object *dst;
int i, slot_idx, remaining_slots;
uint64_t remaining_sum, nh_weight, nh_slots;
+ bool one_reachable = true;
slot_idx = 0;
dst = dst_priv->nhg;
/* Calculate sum of all weights with lowest metric */
- remaining_sum = 0;
+ remaining_sum = nh_weight = 0;
for (i = 0; i < dst_priv->nhg_nh_count; i++) {
- if (nhop_get_metric(x[i].nh) == metric)
- remaining_sum += x[i].weight;
+ if (nhop_get_metric(x[i].nh) == metric) {
+ /*
+ * Temporary store weight of unreachable nhops in nh_weight
+ * to ensure we have at least one reachable nexthop.
+ */
+ if (NH_IS_VALID(x[i].nh))
+ remaining_sum += x[i].weight;
+ else
+ nh_weight += x[i].weight;
+ }
+ }
+
+ /* If no reachable nhops exist, include all */
+ if (remaining_sum == 0) {
+ remaining_sum = nh_weight;
+ one_reachable = false;
}
remaining_slots = num_slots;
@@ -268,14 +283,18 @@
if (nhop_get_metric(x[i].nh) != metric)
continue;
- /* Calculate number of slots for the current nexthop */
- if (remaining_sum > 0) {
+ /*
+ * Calculate number of slots for the current nexthop.
+ * Exclude unreachable nexthops if there is one reachable.
+ */
+ if (remaining_sum > 0 &&
+ (NH_IS_VALID(x[i].nh) || !one_reachable)) {
nh_weight = (uint64_t)x[i].weight;
nh_slots = (nh_weight * remaining_slots / remaining_sum);
+ remaining_sum -= x[i].weight;
} else
nh_slots = 0;
- remaining_sum -= x[i].weight;
remaining_slots -= nh_slots;
FIB_NH_LOG(LOG_DEBUG3, x[0].nh,
@@ -1060,6 +1079,42 @@
return (count);
}
+/*
+ * Recompile nexthop group without changing the slots.
+ * Since a nexthop might become reachable again soon,
+ * this avoids unnecessary memory allocation.
+ */
+static void
+nhgrp_recompile_one(struct nhgrp_priv *nhg_priv)
+{
+ struct nhgrp_object *nhg = nhg_priv->nhg;
+ const struct weightened_nhop *wn;
+ uint32_t num_nhops, min_metric;
+
+ wn = nhgrp_get_nhops(nhg, &num_nhops);
+
+ /* dataplane only has the lowest metric nhops, just pick one */
+ min_metric = nhop_get_metric(nhg->nhops[0]);
+ compile_nhgrp(nhg_priv, wn, nhg->nhg_size, min_metric);
+}
+
+void
+nhgrp_recompile_locked(struct rib_head *rh)
+{
+ struct nh_control *ctl = rh->nh_control;
+ struct epoch_tracker et;
+ struct nhgrp_priv *nhg_priv;
+
+ if (ctl->gr_head.items_count == 0)
+ return;
+
+ NET_EPOCH_ENTER(et);
+ CHT_SLIST_FOREACH(&ctl->gr_head, mpath, nhg_priv) {
+ nhgrp_recompile_one(nhg_priv);
+ } CHT_SLIST_FOREACH_END;
+ NET_EPOCH_EXIT(et);
+}
+
int
nhgrp_dump_sysctl(struct rib_head *rh, struct sysctl_req *w)
{
diff --git a/sys/net/route/nhop_ctl.c b/sys/net/route/nhop_ctl.c
--- a/sys/net/route/nhop_ctl.c
+++ b/sys/net/route/nhop_ctl.c
@@ -1329,18 +1329,34 @@
{
struct nhop_object *nh;
struct nhop_iter iter = { .fibnum = ifp->if_fib };
+ bool nhops_changed;
for (iter.family = 1; iter.family <= AF_MAX; iter.family++) {
+ /*
+ * By tracking nhop changes, we avoid redundant nhgrp
+ * recompilation triggered by multiple events.
+ */
+ nhops_changed = false;
iter.rh = rt_tables_get_rnh_safe(iter.fibnum, iter.family);
- for (nh = nhops_iter_start(&iter); nh != NULL; nh = nhops_iter_next(&iter)) {
+ for (nh = nhops_iter_start(&iter); nh != NULL;
+ nh = nhops_iter_next(&iter)) {
if (nh->nh_ifp != ifp)
continue;
- if (status)
- nh->nh_flags &= ~NHF_INVALID;
- else
- nh->nh_flags |= NHF_INVALID;
+ if (status) {
+ if (!NH_IS_VALID(nh)) {
+ nh->nh_flags &= ~NHF_INVALID;
+ nhops_changed = true;
+ }
+ } else {
+ if (NH_IS_VALID(nh)) {
+ nh->nh_flags |= NHF_INVALID;
+ nhops_changed = true;
+ }
+ }
}
+ if (iter.rh != NULL && nhops_changed)
+ nhgrp_recompile_locked(iter.rh);
nhops_iter_stop(&iter);
}
}
diff --git a/sys/net/route/route_var.h b/sys/net/route/route_var.h
--- a/sys/net/route/route_var.h
+++ b/sys/net/route/route_var.h
@@ -312,6 +312,7 @@
int nhgrp_get_merge_group(struct rib_head *rnh,
struct route_nhop_data *rnd_orig, struct route_nhop_data *rnd_add,
struct route_nhop_data *rnd_new);
+void nhgrp_recompile_locked(struct rib_head *rh);
void nhgrp_ref_object(struct nhgrp_object *nhg);
uint32_t nhgrp_get_idx(const struct nhgrp_object *nhg);

File Metadata

Mime Type
text/plain
Expires
Thu, Jul 2, 6:59 PM (7 h, 15 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34600827
Default Alt Text
D57389.id179080.diff (4 KB)

Event Timeline