Page MenuHomeFreeBSD

D56322.id177153.diff
No OneTemporary

D56322.id177153.diff

diff --git a/sys/net/route.h b/sys/net/route.h
--- a/sys/net/route.h
+++ b/sys/net/route.h
@@ -90,7 +90,8 @@
u_long rmx_pksent; /* packets sent using this route */
u_long rmx_weight; /* route weight */
u_long rmx_nhidx; /* route nexhop index */
- u_long rmx_filler[2]; /* will be used for T/TCP later */
+ u_long rmx_metric; /* route metric */
+ u_long rmx_filler[1];
};
/*
@@ -103,7 +104,6 @@
/* default route weight */
#define RT_DEFAULT_WEIGHT 1
-#define RT_MAX_WEIGHT 16777215 /* 3 bytes */
/*
* Keep a generation count of routing table, incremented on route addition,
@@ -300,6 +300,7 @@
#define RTV_RTT 0x40 /* init or lock _rtt */
#define RTV_RTTVAR 0x80 /* init or lock _rttvar */
#define RTV_WEIGHT 0x100 /* init or lock _weight */
+#define RTV_METRIC 0x200 /* init or lock _metric */
#ifndef NETLINK_COMPAT
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
@@ -135,6 +135,7 @@
* comparable.
* Assumes @wn is sorted by weight ascending and each weight is > 0.
* Returns number of slots or 0 if precise calculation failed.
+ * We filter out nexthops with higher metrics.
*
* Some examples:
* note: (i, X) pair means (nhop=i, weight=X):
@@ -144,17 +145,27 @@
*/
static uint32_t
calc_min_mpath_slots_fast(struct weightened_nhop *wn, size_t num_items,
- uint64_t *ptotal)
+ uint32_t metric, uint64_t *ptotal)
{
- uint32_t i, last, xmin;
+ uint32_t i, x, last, xmin;
uint64_t total = 0;
// Get sorted array of weights in .storage field
sort_weightened_nhops_weights(wn, num_items);
+ /* start with lowest metric */
+ for (x = 0; x < num_items; x++) {
+ if (nhop_get_metric(wn[x].nh) == metric) {
+ xmin = wn[x].storage;
+ break;
+ }
+ }
last = 0;
- xmin = wn[0].storage;
- for (i = 0; i < num_items; i++) {
+ for (i = x; i < num_items; i++) {
+ /* skip over higher metrics */
+ if (nhop_get_metric(wn[i].nh) != metric)
+ continue;
+
total += wn[i].storage;
if ((wn[i].storage != last) &&
((wn[i].storage - last < xmin) || xmin == 0)) {
@@ -176,7 +187,8 @@
/*
* Calculate minimum number of slots required to fit the existing
- * set of weights while maintaining weight coefficients.
+ * set of weights while maintaining weight coefficients
+ * after filtering by metric.
*
* Assume @wn is sorted by weight ascending and each weight is > 0.
*
@@ -184,12 +196,13 @@
* RIB_MAX_MPATH_WIDTH in case of any failure.
*/
static uint32_t
-calc_min_mpath_slots(struct weightened_nhop *wn, size_t num_items)
+calc_min_mpath_slots(struct weightened_nhop *wn, size_t num_items,
+ uint32_t metric)
{
uint32_t v;
uint64_t total;
- v = calc_min_mpath_slots_fast(wn, num_items, &total);
+ v = calc_min_mpath_slots_fast(wn, num_items, metric, &total);
if (total == 0)
return (0);
if ((v == 0) || (v > RIB_MAX_MPATH_WIDTH))
@@ -231,7 +244,7 @@
*/
static void
compile_nhgrp(struct nhgrp_priv *dst_priv, const struct weightened_nhop *x,
- uint32_t num_slots)
+ uint32_t num_slots, uint32_t metric)
{
struct nhgrp_object *dst;
int i, slot_idx, remaining_slots;
@@ -239,14 +252,21 @@
slot_idx = 0;
dst = dst_priv->nhg;
- /* Calculate sum of all weights */
+ /* Calculate sum of all weights with lowest metric */
remaining_sum = 0;
- for (i = 0; i < dst_priv->nhg_nh_count; i++)
- remaining_sum += x[i].weight;
+ for (i = 0; i < dst_priv->nhg_nh_count; i++) {
+ if (nhop_get_metric(x[i].nh) == metric)
+ remaining_sum += x[i].weight;
+ }
+
remaining_slots = num_slots;
- FIB_NH_LOG(LOG_DEBUG3, x[0].nh, "sum: %lu, slots: %d",
- remaining_sum, remaining_slots);
+ FIB_NH_LOG(LOG_DEBUG3, x[0].nh, "sum: %lu, slots: %d, lowest_metric: %lu",
+ remaining_sum, remaining_slots, metric);
for (i = 0; i < dst_priv->nhg_nh_count; i++) {
+ /* Skip over lower metrics */
+ if (nhop_get_metric(x[i].nh) != metric)
+ continue;
+
/* Calculate number of slots for the current nexthop */
if (remaining_sum > 0) {
nh_weight = (uint64_t)x[i].weight;
@@ -275,13 +295,13 @@
* Returns group with refcount=1 or NULL.
*/
static struct nhgrp_priv *
-alloc_nhgrp(struct weightened_nhop *wn, int num_nhops)
+alloc_nhgrp(struct weightened_nhop *wn, int num_nhops, uint32_t min_metric)
{
uint32_t nhgrp_size;
struct nhgrp_object *nhg;
struct nhgrp_priv *nhg_priv;
- nhgrp_size = calc_min_mpath_slots(wn, num_nhops);
+ nhgrp_size = calc_min_mpath_slots(wn, num_nhops, min_metric);
if (nhgrp_size == 0) {
/* Zero weights, abort */
return (NULL);
@@ -314,7 +334,7 @@
FIB_NH_LOG(LOG_DEBUG, wn[0].nh, "num_nhops: %d, compiled_nhop: %u",
num_nhops, nhgrp_size);
- compile_nhgrp(nhg_priv, wn, nhg->nhg_size);
+ compile_nhgrp(nhg_priv, wn, nhg->nhg_size, min_metric);
return (nhg_priv);
}
@@ -487,6 +507,7 @@
/* Sort nexthops & check there are no duplicates */
sort_weightened_nhops(wn, num_nhops);
uint32_t last_id = 0;
+ uint32_t min_metric = nhop_get_metric(wn[0].nh);
for (int i = 0; i < num_nhops; i++) {
if (wn[i].nh->nh_priv->nh_control != ctl) {
*perror = EINVAL;
@@ -497,9 +518,13 @@
return (NULL);
}
last_id = wn[i].nh->nh_priv->nh_idx;
+
+ /* Find the lowest metric */
+ if (nhop_get_metric(wn[i].nh) < min_metric)
+ min_metric = nhop_get_metric(wn[i].nh);
}
- if ((nhg_priv = alloc_nhgrp(wn, num_nhops)) == NULL) {
+ if ((nhg_priv = alloc_nhgrp(wn, num_nhops, min_metric)) == NULL) {
*perror = ENOMEM;
return (NULL);
}
diff --git a/sys/net/route/nhop.h b/sys/net/route/nhop.h
--- a/sys/net/route/nhop.h
+++ b/sys/net/route/nhop.h
@@ -137,7 +137,7 @@
/* 32 bytes + 4xPTR == 64(amd64) / 48(i386) */
uint8_t nh_prepend_len; /* length of prepend data */
uint8_t spare[3];
- uint32_t spare1; /* alignment */
+ uint32_t nh_metric; /* nexthop metric */
char nh_prepend[48]; /* L2 prepend */
struct nhop_priv *nh_priv; /* control plane data */
/* -- 128 bytes -- */
@@ -219,6 +219,8 @@
void nhop_set_fibnum(struct nhop_object *nh, uint32_t fibnum);
uint32_t nhop_get_expire(const struct nhop_object *nh);
void nhop_set_expire(struct nhop_object *nh, uint32_t expire);
+uint32_t nhop_get_metric(const struct nhop_object *nh);
+void nhop_set_metric(struct nhop_object *nh, uint32_t metric);
struct rib_head *nhop_get_rh(const struct nhop_object *nh);
struct nhgrp_object;
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
@@ -1044,6 +1044,18 @@
nh->nh_priv->nh_origin = origin;
}
+uint32_t
+nhop_get_metric(const struct nhop_object *nh)
+{
+ return (nh->nh_metric);
+}
+
+void
+nhop_set_metric(struct nhop_object *nh, uint32_t metric)
+{
+ nh->nh_metric = metric;
+}
+
void
nhops_update_ifmtu(struct rib_head *rh, struct ifnet *ifp, uint32_t mtu)
{
diff --git a/sys/net/route/route_ctl.c b/sys/net/route/route_ctl.c
--- a/sys/net/route/route_ctl.c
+++ b/sys/net/route/route_ctl.c
@@ -196,10 +196,7 @@
weight = info->rti_rmx->rmx_weight;
else
weight = default_weight;
- /* Keep upper 1 byte for adm distance purposes */
- if (weight > RT_MAX_WEIGHT)
- weight = RT_MAX_WEIGHT;
- else if (weight == 0)
+ if (weight == 0)
weight = default_weight;
return (weight);
diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c
--- a/sys/net/rtsock.c
+++ b/sys/net/rtsock.c
@@ -1024,6 +1024,7 @@
(rtm->rtm_flags & ~RTF_GWFLAG_COMPAT);
rt_getmetrics(rc->rc_rt, nh, &rtm->rtm_rmx);
rtm->rtm_rmx.rmx_weight = rc->rc_nh_weight;
+ rtm->rtm_rmx.rmx_metric = nhop_get_metric(nh);
return (0);
}
@@ -1328,6 +1329,7 @@
bzero(out, sizeof(*out));
out->rmx_mtu = nh->nh_mtu;
out->rmx_weight = rt->rt_weight;
+ out->rmx_metric = nhop_get_metric(nh);
out->rmx_nhidx = nhop_get_idx(nh);
/* Kernel -> userland timebase conversion. */
out->rmx_expire = nhop_get_expire(nh) ?

File Metadata

Mime Type
text/plain
Expires
Sun, Jun 21, 4:46 PM (4 h, 59 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34148409
Default Alt Text
D56322.id177153.diff (7 KB)

Event Timeline