Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F160008079
D56322.id178124.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D56322.id178124.diff
View Options
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,8 @@
/* default route weight */
#define RT_DEFAULT_WEIGHT 1
-#define RT_MAX_WEIGHT 16777215 /* 3 bytes */
+#define RT_DEFAULT_METRIC 1
+#define RT_WILDCARD_METRIC 0
/*
* Keep a generation count of routing table, incremented on route addition,
@@ -300,6 +302,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.
+ * Only calculate for nexthops with specified metric and ignore the rest.
*
* Some examples:
* note: (i, X) pair means (nhop=i, weight=X):
@@ -144,17 +145,26 @@
*/
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 = 0;
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++) {
+ 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 +186,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 +195,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))
@@ -224,6 +236,9 @@
/*
* Compile actual list of nexthops to be used by datapath from
* the nexthop group @dst.
+ * Since we only need nexthops with lowest metric, only process
+ * nexthops with specified metric. The metric argument is taken
+ * from input and is expected to be the lowest metric in weightened_nhop.
*
* For example, compiling control plane list of 2 nexthops
* [(200, A), (100, B)] would result in the datapath array
@@ -231,7 +246,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 +254,20 @@
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++) {
+ 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 +296,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 +335,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);
}
@@ -464,6 +485,8 @@
struct nhgrp_priv *nhg_priv;
struct nh_control *ctl;
+ MPASS((num_nhops != 0));
+
if (rh == NULL) {
*perror = E2BIG;
return (NULL);
@@ -487,6 +510,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 +521,12 @@
return (NULL);
}
last_id = wn[i].nh->nh_priv->nh_idx;
+
+ 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
@@ -171,6 +171,19 @@
nhop_set_mtu(nh, info->rti_rmx->rmx_mtu, true);
}
+static void
+set_nhop_metric_from_info(struct nhop_object *nh, const struct rt_addrinfo *info)
+{
+ uint32_t metric;
+
+ if (info->rti_mflags & RTV_METRIC)
+ metric = info->rti_rmx->rmx_metric;
+ else
+ metric = RT_DEFAULT_METRIC;
+
+ nhop_set_metric(nh, metric);
+}
+
/*
* Fills in shorted link-level sockadd version suitable to be stored inside the
* nexthop gateway buffer.
@@ -288,6 +301,7 @@
nhop_set_rtflags(nh, info->rti_flags);
set_nhop_mtu_from_info(nh, info);
+ set_nhop_metric_from_info(nh, info);
nhop_set_src(nh, info->rti_ifa);
/*
@@ -1044,6 +1058,21 @@
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)
+{
+ if (metric != RT_WILDCARD_METRIC)
+ nh->nh_metric = metric;
+ else
+ nh->nh_metric = RT_DEFAULT_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
@@ -1328,6 +1328,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
Details
Attached
Mime Type
text/plain
Expires
Sun, Jun 21, 12:20 PM (33 m, 54 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34148976
Default Alt Text
D56322.id178124.diff (8 KB)
Attached To
Mode
D56322: routing: Add support for route metric
Attached
Detach File
Event Timeline
Log In to Comment