Merge pull request #1075 from donaldsharp/rip_metric

lib, ospfd, ripd, ripngd:  Fix 'set metric'
This commit is contained in:
David Lamparter 2017-09-05 18:17:52 +02:00 committed by GitHub
commit c6fe740998
4 changed files with 73 additions and 41 deletions

View File

@ -194,7 +194,15 @@ extern int route_map_delete_set(struct route_map_index *index,
/* Install rule command to the match list. */
extern void route_map_install_match(struct route_map_rule_cmd *cmd);
/* Install rule command to the set list. */
/*
* Install rule command to the set list.
*
* When installing a particular item, Allow a difference of handling
* of bad cli inputted(return NULL) -vs- this particular daemon cannot use
* this form of the command(return a pointer and handle it appropriately
* in the apply command). See 'set metric' command
* as it is handled in ripd/ripngd and ospfd.
*/
extern void route_map_install_set(struct route_map_rule_cmd *cmd);
/* Lookup route map by name. */

View File

@ -336,6 +336,10 @@ static struct route_map_rule_cmd route_match_tag_cmd = {
route_map_rule_tag_free,
};
struct ospf_metric {
bool used;
u_int32_t metric;
};
/* `set metric METRIC' */
/* Set metric to attribute. */
@ -343,7 +347,7 @@ static route_map_result_t route_set_metric(void *rule, struct prefix *prefix,
route_map_object_t type,
void *object)
{
u_int32_t *metric;
struct ospf_metric *metric;
struct external_info *ei;
if (type == RMAP_OSPF) {
@ -352,7 +356,8 @@ static route_map_result_t route_set_metric(void *rule, struct prefix *prefix,
ei = object;
/* Set metric out value. */
ei->route_map_set.metric = *metric;
if (metric->used)
ei->route_map_set.metric = metric->metric;
}
return RMAP_OKAY;
}
@ -360,7 +365,10 @@ static route_map_result_t route_set_metric(void *rule, struct prefix *prefix,
/* set metric compilation. */
static void *route_set_metric_compile(const char *arg)
{
u_int32_t *metric;
struct ospf_metric *metric;
metric = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(u_int32_t));
metric->used = false;
/* OSPF doesn't support the +/- in
set metric <+/-metric> check
@ -373,11 +381,12 @@ static void *route_set_metric_compile(const char *arg)
if (strmatch(arg, "+rtt") || strmatch(arg, "-rtt"))
zlog_warn(
"OSPF does not support 'set metric +rtt / -rtt'");
return NULL;
return metric;
}
}
metric = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(u_int32_t));
*metric = strtoul(arg, NULL, 10);
metric->metric = strtoul(arg, NULL, 10);
metric->used = true;
return metric;
}

View File

@ -36,8 +36,8 @@
struct rip_metric_modifier {
enum { metric_increment, metric_decrement, metric_absolute } type;
u_char metric;
bool used;
u_int8_t metric;
};
/* Hook function for updating route_map assignment. */
@ -365,6 +365,9 @@ static route_map_result_t route_set_metric(void *rule, struct prefix *prefix,
mod = rule;
rinfo = object;
if (!mod->used)
return RMAP_OKAY;
if (mod->type == metric_increment)
rinfo->metric_out += mod->metric;
else if (mod->type == metric_decrement)
@ -387,43 +390,49 @@ static void *route_set_metric_compile(const char *arg)
{
int len;
const char *pnt;
int type;
long metric;
char *endptr = NULL;
struct rip_metric_modifier *mod;
mod = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
sizeof(struct rip_metric_modifier));
mod->used = false;
len = strlen(arg);
pnt = arg;
if (len == 0)
return NULL;
return mod;
/* Examine first character. */
if (arg[0] == '+') {
type = metric_increment;
mod->type = metric_increment;
pnt++;
} else if (arg[0] == '-') {
type = metric_decrement;
mod->type = metric_decrement;
pnt++;
} else
type = metric_absolute;
mod->type = metric_absolute;
/* Check beginning with digit string. */
if (*pnt < '0' || *pnt > '9')
return NULL;
return mod;
/* Convert string to integer. */
metric = strtol(pnt, &endptr, 10);
if (metric == LONG_MAX || *endptr != '\0')
return NULL;
if (metric < 0 || metric > RIP_METRIC_INFINITY)
return NULL;
if (*endptr != '\0' || mod->metric < 0) {
metric = 0;
return mod;
}
if (metric > RIP_METRIC_INFINITY) {
zlog_info("%s: Metric specified: %ld is greater than RIP_METRIC_INFINITY, using INFINITY instead",
__PRETTY_FUNCTION__, metric);
mod->metric = RIP_METRIC_INFINITY;
} else
mod->metric = metric;
mod = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
sizeof(struct rip_metric_modifier));
mod->type = type;
mod->metric = metric;
mod->used = true;
return mod;
}

View File

@ -32,8 +32,8 @@
struct rip_metric_modifier {
enum { metric_increment, metric_decrement, metric_absolute } type;
u_char metric;
bool used;
u_int8_t metric;
};
/* `match metric METRIC' */
@ -168,6 +168,9 @@ static route_map_result_t route_set_metric(void *rule, struct prefix *prefix,
mod = rule;
rinfo = object;
if (!mod->used)
return RMAP_OKAY;
if (mod->type == metric_increment)
rinfo->metric_out += mod->metric;
else if (mod->type == metric_decrement)
@ -190,7 +193,6 @@ static void *route_set_metric_compile(const char *arg)
{
int len;
const char *pnt;
int type;
long metric;
char *endptr = NULL;
struct rip_metric_modifier *mod;
@ -198,38 +200,42 @@ static void *route_set_metric_compile(const char *arg)
len = strlen(arg);
pnt = arg;
mod = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
sizeof(struct rip_metric_modifier));
mod->used = false;
if (len == 0)
return NULL;
return mod;
/* Examine first character. */
if (arg[0] == '+') {
type = metric_increment;
mod->type = metric_increment;
pnt++;
} else if (arg[0] == '-') {
type = metric_decrement;
mod->type = metric_decrement;
pnt++;
} else
type = metric_absolute;
mod->type = metric_absolute;
/* Check beginning with digit string. */
if (*pnt < '0' || *pnt > '9')
return NULL;
return mod;
/* Convert string to integer. */
metric = strtol(pnt, &endptr, 10);
if (metric == LONG_MAX || *endptr != '\0')
return NULL;
/* Commented out by Hasso Tepper, to avoid problems in vtysh. */
/* if (metric < 0 || metric > RIPNG_METRIC_INFINITY) */
if (metric < 0)
return NULL;
if (*endptr != '\0' || metric < 0)
return mod;
mod = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
sizeof(struct rip_metric_modifier));
mod->type = type;
mod->metric = metric;
if (metric > RIPNG_METRIC_INFINITY) {
zlog_info("%s: Metric specified: %ld is being converted into METRIC_INFINITY",
__PRETTY_FUNCTION__,
metric);
mod->metric = RIPNG_METRIC_INFINITY;
} else
mod->metric = metric;
mod->used = true;
return mod;
}