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. */ /* Install rule command to the match list. */
extern void route_map_install_match(struct route_map_rule_cmd *cmd); 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); extern void route_map_install_set(struct route_map_rule_cmd *cmd);
/* Lookup route map by name. */ /* 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, route_map_rule_tag_free,
}; };
struct ospf_metric {
bool used;
u_int32_t metric;
};
/* `set metric METRIC' */ /* `set metric METRIC' */
/* Set metric to attribute. */ /* 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, route_map_object_t type,
void *object) void *object)
{ {
u_int32_t *metric; struct ospf_metric *metric;
struct external_info *ei; struct external_info *ei;
if (type == RMAP_OSPF) { if (type == RMAP_OSPF) {
@ -352,7 +356,8 @@ static route_map_result_t route_set_metric(void *rule, struct prefix *prefix,
ei = object; ei = object;
/* Set metric out value. */ /* Set metric out value. */
ei->route_map_set.metric = *metric; if (metric->used)
ei->route_map_set.metric = metric->metric;
} }
return RMAP_OKAY; return RMAP_OKAY;
} }
@ -360,7 +365,10 @@ static route_map_result_t route_set_metric(void *rule, struct prefix *prefix,
/* set metric compilation. */ /* set metric compilation. */
static void *route_set_metric_compile(const char *arg) 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 /* OSPF doesn't support the +/- in
set metric <+/-metric> check set metric <+/-metric> check
@ -373,11 +381,12 @@ static void *route_set_metric_compile(const char *arg)
if (strmatch(arg, "+rtt") || strmatch(arg, "-rtt")) if (strmatch(arg, "+rtt") || strmatch(arg, "-rtt"))
zlog_warn( zlog_warn(
"OSPF does not support 'set metric +rtt / -rtt'"); "OSPF does not support 'set metric +rtt / -rtt'");
return NULL;
return metric;
} }
} }
metric = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(u_int32_t)); metric->metric = strtoul(arg, NULL, 10);
*metric = strtoul(arg, NULL, 10); metric->used = true;
return metric; return metric;
} }

View File

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

View File

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