Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F161213714
D57389.id179614.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D57389.id179614.diff
View Options
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,44 @@
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;
+
+ NHOPS_RLOCK_ASSERT(ctl);
+
+ 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/nhop_var.h b/sys/net/route/nhop_var.h
--- a/sys/net/route/nhop_var.h
+++ b/sys/net/route/nhop_var.h
@@ -66,6 +66,7 @@
#define NHOPS_RUNLOCK(ctl) rw_runlock(&(ctl)->ctl_lock)
#define NHOPS_LOCK_INIT(ctl) rw_init(&(ctl)->ctl_lock, "nhop_ctl")
#define NHOPS_LOCK_DESTROY(ctl) rw_destroy(&(ctl)->ctl_lock)
+#define NHOPS_RLOCK_ASSERT(ctl) rw_assert(&(ctl)->ctl_lock, RA_RLOCKED)
#define NHOPS_WLOCK_ASSERT(ctl) rw_assert(&(ctl)->ctl_lock, RA_WLOCKED)
/* Control plane-only nhop data */
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
Details
Attached
Mime Type
text/plain
Expires
Thu, Jul 2, 6:17 PM (6 h, 34 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34600331
Default Alt Text
D57389.id179614.diff (4 KB)
Attached To
Mode
D57389: routing: Replace unreachable nhops in nhgrp
Attached
Detach File
Event Timeline
Log In to Comment