summaryrefslogtreecommitdiff
path: root/usr.sbin/eigrpd
diff options
context:
space:
mode:
authorRenato Westphal <renato@cvs.openbsd.org>2015-12-13 19:02:50 +0000
committerRenato Westphal <renato@cvs.openbsd.org>2015-12-13 19:02:50 +0000
commit0fd720b609afab6a845b6d1343a04c293232f21b (patch)
treeda794f0c8db6f4fed4707740d2bddcdd60078210 /usr.sbin/eigrpd
parent428b8be00a508fa73949a3a7df2d49df57321edb (diff)
Respect the k-values configuration when calculating the composite metric.
Diffstat (limited to 'usr.sbin/eigrpd')
-rw-r--r--usr.sbin/eigrpd/rde.h9
-rw-r--r--usr.sbin/eigrpd/rde_dual.c114
2 files changed, 88 insertions, 35 deletions
diff --git a/usr.sbin/eigrpd/rde.h b/usr.sbin/eigrpd/rde.h
index a08394f7076..dd65d87264c 100644
--- a/usr.sbin/eigrpd/rde.h
+++ b/usr.sbin/eigrpd/rde.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.h,v 1.5 2015/10/27 03:25:55 renato Exp $ */
+/* $OpenBSD: rde.h,v 1.6 2015/12/13 19:02:49 renato Exp $ */
/*
* Copyright (c) 2015 Renato Westphal <renato@openbsd.org>
@@ -155,12 +155,15 @@ struct eigrp_route *route_new(struct rt_node *, struct rde_nbr *,
struct rinfo *);
void route_del(struct rt_node *, struct eigrp_route *);
uint32_t safe_sum_uint32(uint32_t, uint32_t);
+uint32_t safe_mul_uint32(uint32_t, uint32_t);
uint32_t eigrp_composite_delay(uint32_t);
uint32_t eigrp_real_delay(uint32_t);
uint32_t eigrp_composite_bandwidth(uint32_t);
uint32_t eigrp_real_bandwidth(uint32_t);
-void route_update_metrics(struct eigrp_route *,
- struct rinfo *);
+uint32_t route_composite_metric(uint8_t *, uint32_t, uint32_t,
+ uint8_t, uint8_t);
+void route_update_metrics(struct eigrp *,
+ struct eigrp_route *, struct rinfo *);
void reply_outstanding_add(struct rt_node *,
struct rde_nbr *);
struct reply_node *reply_outstanding_find(struct rt_node *,
diff --git a/usr.sbin/eigrpd/rde_dual.c b/usr.sbin/eigrpd/rde_dual.c
index d79e9da50e1..6c83dceb378 100644
--- a/usr.sbin/eigrpd/rde_dual.c
+++ b/usr.sbin/eigrpd/rde_dual.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_dual.c,v 1.11 2015/12/13 19:00:42 renato Exp $ */
+/* $OpenBSD: rde_dual.c,v 1.12 2015/12/13 19:02:49 renato Exp $ */
/*
* Copyright (c) 2015 Renato Westphal <renato@openbsd.org>
@@ -273,7 +273,7 @@ route_new(struct rt_node *rn, struct rde_nbr *nbr, struct rinfo *ri)
route->nbr = nbr;
route->type = ri->type;
memcpy(&route->nexthop, &ri->nexthop, sizeof(route->nexthop));
- route_update_metrics(route, ri);
+ route_update_metrics(eigrp, route, ri);
TAILQ_INSERT_TAIL(&rn->routes, route, entry);
log_debug("%s: prefix %s via %s distance (%u/%u)", __func__,
@@ -312,6 +312,19 @@ safe_sum_uint32(uint32_t a, uint32_t b)
}
uint32_t
+safe_mul_uint32(uint32_t a, uint32_t b)
+{
+ uint64_t total;
+
+ total = (uint64_t) a * (uint64_t) b;
+
+ if (total >> 32)
+ return ((uint32_t )(~0));
+
+ return ((uint32_t) total);
+}
+
+uint32_t
eigrp_composite_delay(uint32_t delay)
{
/* cheap overflow protection */
@@ -343,46 +356,82 @@ eigrp_real_bandwidth(uint32_t bandwidth)
return ((EIGRP_SCALING_FACTOR * (uint32_t)10000000) / bandwidth);
}
+uint32_t
+route_composite_metric(uint8_t *kvalues, uint32_t delay, uint32_t bandwidth,
+ uint8_t load, uint8_t reliability)
+{
+ uint64_t distance;
+ uint32_t operand1, operand2, operand3;
+ double operand4;
+
+ /*
+ * Need to apply the scaling factor before any division to avoid
+ * losing information from truncation.
+ */
+ operand1 = safe_mul_uint32(kvalues[0] * EIGRP_SCALING_FACTOR,
+ 10000000 / bandwidth);
+ operand2 = safe_mul_uint32(kvalues[1] * EIGRP_SCALING_FACTOR,
+ 10000000 /bandwidth) / (256 - load);
+ operand3 = safe_mul_uint32(kvalues[2] * EIGRP_SCALING_FACTOR, delay);
+
+ distance = (uint64_t) operand1 + (uint64_t) operand2 +
+ (uint64_t) operand3;
+
+ /* if K5 is set to zero, the last term of the formula is not used */
+ if (kvalues[4] != 0) {
+ operand4 = (double) kvalues[4] / (reliability + kvalues[3]);
+ /* no risk of overflow (64 bits), operand4 can be at most 255 */
+ distance *= operand4;
+ }
+
+ /* overflow protection */
+ if (distance >> 32)
+ distance = ((uint32_t )(~0));
+
+ return ((uint32_t) distance);
+}
+
void
-route_update_metrics(struct eigrp_route *route, struct rinfo *ri)
+route_update_metrics(struct eigrp *eigrp, struct eigrp_route *route,
+ struct rinfo *ri)
{
- uint32_t bandwidth;
- int mtu;
+ struct eigrp_iface *ei = route->nbr->ei;
+ uint32_t delay, bandwidth;
+ int mtu;
- if (route->nbr->flags & F_RDE_NBR_SELF) {
- memcpy(&route->metric, &ri->metric, sizeof(route->metric));
- memcpy(&route->emetric, &ri->emetric, sizeof(route->emetric));
+ memcpy(&route->metric, &ri->metric, sizeof(route->metric));
+ memcpy(&route->emetric, &ri->emetric, sizeof(route->emetric));
+ route->flags |= F_EIGRP_ROUTE_M_CHANGED;
+
+ delay = eigrp_real_delay(route->metric.delay);
+ bandwidth = eigrp_real_bandwidth(route->metric.bandwidth);
+
+ if (route->nbr->flags & F_RDE_NBR_SELF)
route->rdistance = 0;
+ else {
+ route->rdistance = route_composite_metric(eigrp->kvalues,
+ delay, bandwidth, route->metric.load,
+ route->metric.reliability);
- /* no need to update the local metric */
- } else {
- memcpy(&route->metric, &ri->metric, sizeof(route->metric));
- memcpy(&route->emetric, &ri->emetric, sizeof(route->emetric));
- route->rdistance = safe_sum_uint32(ri->metric.delay,
- ri->metric.bandwidth);
-
- /* update delay. */
- route->metric.delay = safe_sum_uint32(route->metric.delay,
- eigrp_composite_delay(route->nbr->ei->delay));
-
- /* update bandwidth */
- bandwidth = min(route->nbr->ei->bandwidth,
- eigrp_real_bandwidth(route->metric.bandwidth));
+ /* update the delay */
+ delay = safe_sum_uint32(delay, ei->delay);
+ route->metric.delay = eigrp_composite_delay(delay);
+
+ /* update the bandwidth */
+ bandwidth = min(bandwidth, ei->bandwidth);
route->metric.bandwidth = eigrp_composite_bandwidth(bandwidth);
- /* update mtu */
- mtu = min(metric_decode_mtu(route->metric.mtu),
- route->nbr->ei->iface->mtu);
+ /* update the mtu */
+ mtu = min(metric_decode_mtu(route->metric.mtu), ei->iface->mtu);
metric_encode_mtu(route->metric.mtu, mtu);
- /* update hop count */
+ /* update the hop count */
if (route->metric.hop_count < UINT8_MAX)
route->metric.hop_count++;
}
- route->distance = safe_sum_uint32(route->metric.delay,
- route->metric.bandwidth);
- route->flags |= F_EIGRP_ROUTE_M_CHANGED;
+ route->distance = route_composite_metric(eigrp->kvalues, delay,
+ bandwidth, DEFAULT_LOAD, DEFAULT_RELIABILITY);
}
void
@@ -626,6 +675,7 @@ rt_set_successor(struct rt_node *rn, struct eigrp_route *successor)
rn->successor.rdistance = EIGRP_INFINITE_METRIC;
memset(&rn->successor.metric, 0,
sizeof(rn->successor.metric));
+ rn->successor.metric.delay = EIGRP_INFINITE_METRIC;
memset(&rn->successor.emetric, 0,
sizeof(rn->successor.emetric));
} else {
@@ -846,7 +896,7 @@ rde_check_update(struct rde_nbr *nbr, struct rinfo *ri)
if (route == NULL)
route = route_new(rn, nbr, ri);
else
- route_update_metrics(route, ri);
+ route_update_metrics(eigrp, route, ri);
}
}
@@ -927,7 +977,7 @@ rde_check_query(struct rde_nbr *nbr, struct rinfo *ri, int siaquery)
if (route == NULL)
route = route_new(rn, nbr, ri);
else
- route_update_metrics(route, ri);
+ route_update_metrics(eigrp, route, ri);
}
switch (rn->state) {
@@ -1115,7 +1165,7 @@ rde_check_reply(struct rde_nbr *nbr, struct rinfo *ri, int siareply)
if (route == NULL)
route = route_new(rn, nbr, ri);
else
- route_update_metrics(route, ri);
+ route_update_metrics(eigrp, route, ri);
}
reply_outstanding_remove(reply);