// SPDX-License-Identifier: GPL-2.0-or-later /* * EIGRP Metric Math Functions. * Copyright (C) 2013-2016 * Authors: * Donnie Savage */ #include #include "eigrpd/eigrp_structs.h" #include "eigrpd/eigrpd.h" #include "eigrpd/eigrp_types.h" #include "eigrpd/eigrp_metric.h" eigrp_scaled_t eigrp_bandwidth_to_scaled(eigrp_bandwidth_t bandwidth) { eigrp_bandwidth_t scaled = EIGRP_BANDWIDTH_MAX; if (bandwidth != EIGRP_BANDWIDTH_MAX) { scaled = (EIGRP_CLASSIC_SCALER * EIGRP_BANDWIDTH_SCALER); scaled = scaled / bandwidth; scaled = scaled ? scaled : EIGRP_BANDWIDTH_MIN; } scaled = (scaled < EIGRP_METRIC_MAX) ? scaled : EIGRP_METRIC_MAX; return (eigrp_scaled_t)scaled; } eigrp_bandwidth_t eigrp_scaled_to_bandwidth(eigrp_scaled_t scaled) { eigrp_bandwidth_t bandwidth = EIGRP_BANDWIDTH_MAX; if (scaled != EIGRP_CLASSIC_MAX) { bandwidth = (EIGRP_CLASSIC_SCALER * EIGRP_BANDWIDTH_SCALER); bandwidth = scaled * bandwidth; bandwidth = (bandwidth < EIGRP_METRIC_MAX) ? bandwidth : EIGRP_BANDWIDTH_MAX; } return bandwidth; } eigrp_scaled_t eigrp_delay_to_scaled(eigrp_delay_t delay) { delay = delay ? delay : EIGRP_DELAY_MIN; return delay * EIGRP_CLASSIC_SCALER; } eigrp_delay_t eigrp_scaled_to_delay(eigrp_scaled_t scaled) { scaled = scaled / EIGRP_CLASSIC_SCALER; scaled = scaled ? scaled : EIGRP_DELAY_MIN; return scaled; } eigrp_metric_t eigrp_calculate_metrics(struct eigrp *eigrp, struct eigrp_metrics metric) { eigrp_metric_t composite = 0; if (metric.delay == EIGRP_MAX_METRIC) return EIGRP_METRIC_MAX; /* * EIGRP Composite = * {K1*BW+[(K2*BW)/(256-load)]+(K3*delay)}*{K5/(reliability+K4)} */ if (eigrp->k_values[0]) composite += ((eigrp_metric_t)eigrp->k_values[0] * (eigrp_metric_t)metric.bandwidth); if (eigrp->k_values[1]) composite += (((eigrp_metric_t)eigrp->k_values[1] * (eigrp_metric_t)metric.bandwidth) / (256 - metric.load)); if (eigrp->k_values[2]) composite += ((eigrp_metric_t)eigrp->k_values[2] * (eigrp_metric_t)metric.delay); if (eigrp->k_values[3] && !eigrp->k_values[4]) composite *= (eigrp_metric_t)eigrp->k_values[3]; if (!eigrp->k_values[3] && eigrp->k_values[4]) composite *= ((eigrp_metric_t)eigrp->k_values[4] / (eigrp_metric_t)metric.reliability); if (eigrp->k_values[3] && eigrp->k_values[4]) composite *= (((eigrp_metric_t)eigrp->k_values[4] / (eigrp_metric_t)metric.reliability) + (eigrp_metric_t)eigrp->k_values[3]); composite = (composite <= EIGRP_METRIC_MAX) ? composite : EIGRP_METRIC_MAX; return composite; } eigrp_metric_t eigrp_calculate_total_metrics(struct eigrp *eigrp, struct eigrp_route_descriptor *entry) { struct eigrp_interface *ei = entry->ei; eigrp_delay_t temp_delay; eigrp_bandwidth_t bw; entry->total_metric = entry->reported_metric; temp_delay = entry->total_metric.delay + eigrp_delay_to_scaled(ei->params.delay); entry->total_metric.delay = temp_delay > EIGRP_METRIC_MAX_CLASSIC ? EIGRP_METRIC_MAX_CLASSIC : temp_delay; bw = eigrp_bandwidth_to_scaled(ei->params.bandwidth); entry->total_metric.bandwidth = entry->total_metric.bandwidth > bw ? bw : entry->total_metric.bandwidth; return eigrp_calculate_metrics(eigrp, entry->total_metric); } bool eigrp_metrics_is_same(struct eigrp_metrics metric1, struct eigrp_metrics metric2) { if ((metric1.bandwidth == metric2.bandwidth) && (metric1.delay == metric2.delay) && (metric1.hop_count == metric2.hop_count) && (metric1.load == metric2.load) && (metric1.reliability == metric2.reliability) && (metric1.mtu[0] == metric2.mtu[0]) && (metric1.mtu[1] == metric2.mtu[1]) && (metric1.mtu[2] == metric2.mtu[2])) { return true; } return false; /* if different */ }