Skip to content

Commit

Permalink
Respect the k-values configuration when calculating the composite met…
Browse files Browse the repository at this point in the history
…ric.
  • Loading branch information
rwestphal committed Dec 13, 2015
1 parent 1a3c9e8 commit 87d5934
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 33 deletions.
7 changes: 5 additions & 2 deletions rde.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 *,
Expand Down
112 changes: 81 additions & 31 deletions rde_dual.c
Original file line number Diff line number Diff line change
Expand Up @@ -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__,
Expand Down Expand Up @@ -311,6 +311,19 @@ safe_sum_uint32(uint32_t a, uint32_t b)
return ((uint32_t) total);
}

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)
{
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 87d5934

Please sign in to comment.