]> git.puffer.fish Git - mirror/frr.git/commitdiff
lib, ospfd, ripd, ripngd: Fix 'set metric' 1075/head
authorDonald Sharp <sharpd@cumulusnetworks.com>
Tue, 29 Aug 2017 18:47:35 +0000 (14:47 -0400)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Tue, 29 Aug 2017 19:08:13 +0000 (15:08 -0400)
There are a variety of cli's associated with the
'set metric ...' command.  The problem that we
are experiencing is that not all the daemons
support all the varieties of the set metric
and the returned of NULL during the XXX_compile
phase for these unsupported commands is causing
issues.  Modify the code base to only return
NULL if we encounter a true parsing issue.
Else we need to keep track if this metric
applies to us or not.

In the case of rip or ripngd if the metric
passed to us is greater than 16 just turn
it internally into a MAX_METRIC.

Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
lib/routemap.h
ospfd/ospf_routemap.c
ripd/rip_routemap.c
ripngd/ripng_routemap.c

index 43af8dbcfe347c07d9685f21c05f06a64790b653..1302df1fee156f6e4eb0448531a349877b31f744 100644 (file)
@@ -192,7 +192,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. */
index 547e1e8f53ee5250ea027125b872b3375663954f..f47e2b6f1ee303d51fbfcb54bd98a657a897d29d 100644 (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;
 }
index 7255df5e67848f1fb94f5ead512591df5ab8f2ee..7d39023b38df0ce410723619e5cd6244e9e781af 100644 (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;
 }
index 3080801fb3537db541946a05f757e08fed8c5908..e518585c743ec6ec84734a12bb028894f7c49570 100644 (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;
 }