summaryrefslogtreecommitdiffstats
path: root/bgpd
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2015-04-29 09:43:02 +0300
committerDavid Lamparter <equinox@opensourcerouting.org>2015-05-20 18:50:21 +0200
commit38f22ab07c8e1f0f12e23c2e2d0a3e1f71bef695 (patch)
treefdb9d52bea1f2105885182aef92691a5bf01e47a /bgpd
parent5460baef7f0014f2d0c3459aa9c4180da19d6850 (diff)
downloadquagga-38f22ab07c8e1f0f12e23c2e2d0a3e1f71bef695.tar.bz2
quagga-38f22ab07c8e1f0f12e23c2e2d0a3e1f71bef695.tar.xz
bgpd: refactor route-map objects modifying integer values
Use common code to parse, validate and adjust the route-map objects that contain a simple integer value. This also allows compiling the add/sub format metric object. Signed-off-by: Timo Teräs <timo.teras@iki.fi> Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
Diffstat (limited to 'bgpd')
-rw-r--r--bgpd/bgp_routemap.c303
1 files changed, 111 insertions, 192 deletions
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index 416a3e51..4a0dac76 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -101,6 +101,86 @@ o Local extensions
*/
+ /* generic value manipulation to be shared in multiple rules */
+
+#define RMAP_VALUE_SET 0
+#define RMAP_VALUE_ADD 1
+#define RMAP_VALUE_SUB 2
+
+struct rmap_value
+{
+ u_int8_t action;
+ u_int32_t value;
+};
+
+static int
+route_value_match (struct rmap_value *rv, u_int32_t value)
+{
+ if (value == rv->value)
+ return RMAP_MATCH;
+
+ return RMAP_NOMATCH;
+}
+
+static u_int32_t
+route_value_adjust (struct rmap_value *rv, u_int32_t current)
+{
+ u_int32_t value = rv->value;
+
+ switch (rv->action)
+ {
+ case RMAP_VALUE_ADD:
+ if (current > UINT32_MAX-value)
+ return UINT32_MAX;
+ return current + value;
+ case RMAP_VALUE_SUB:
+ if (current <= value)
+ return 0;
+ return current - value;
+ default:
+ return value;
+ }
+}
+
+static void *
+route_value_compile (const char *arg)
+{
+ u_int8_t action = RMAP_VALUE_SET;
+ unsigned long larg;
+ char *endptr = NULL;
+ struct rmap_value *rv;
+
+ if (arg[0] == '+')
+ {
+ action = RMAP_VALUE_ADD;
+ arg++;
+ }
+ else if (arg[0] == '-')
+ {
+ action = RMAP_VALUE_SUB;
+ arg++;
+ }
+
+ errno = 0;
+ larg = strtoul (arg, &endptr, 10);
+ if (*arg == 0 || *endptr != 0 || errno || larg > UINT32_MAX)
+ return NULL;
+
+ rv = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_value));
+ if (!rv)
+ return NULL;
+
+ rv->action = action;
+ rv->value = larg;
+ return rv;
+}
+
+static void
+route_value_free (void *rule)
+{
+ XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
/* generic as path object to be shared in multiple rules */
static void *
@@ -518,62 +598,25 @@ static route_map_result_t
route_match_metric (void *rule, struct prefix *prefix,
route_map_object_t type, void *object)
{
- u_int32_t *med;
+ struct rmap_value *rv;
struct bgp_info *bgp_info;
if (type == RMAP_BGP)
{
- med = rule;
+ rv = rule;
bgp_info = object;
-
- if (bgp_info->attr->med == *med)
- return RMAP_MATCH;
- else
- return RMAP_NOMATCH;
+ return route_value_match(rv, bgp_info->attr->med);
}
return RMAP_NOMATCH;
}
-/* Route map `match metric' match statement. `arg' is MED value */
-static void *
-route_match_metric_compile (const char *arg)
-{
- u_int32_t *med;
- char *endptr = NULL;
- unsigned long tmpval;
-
- /* Metric value shoud be integer. */
- if (! all_digit (arg))
- return NULL;
-
- errno = 0;
- tmpval = strtoul (arg, &endptr, 10);
- if (*endptr != '\0' || errno || tmpval > UINT32_MAX)
- return NULL;
-
- med = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
-
- if (!med)
- return med;
-
- *med = tmpval;
- return med;
-}
-
-/* Free route map's compiled `match metric' value. */
-static void
-route_match_metric_free (void *rule)
-{
- XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
-}
-
/* Route map commands for metric matching. */
struct route_map_rule_cmd route_match_metric_cmd =
{
"metric",
route_match_metric,
- route_match_metric_compile,
- route_match_metric_free
+ route_value_compile,
+ route_value_free,
};
/* `match as-path ASPATH' */
@@ -992,64 +1035,34 @@ static route_map_result_t
route_set_local_pref (void *rule, struct prefix *prefix,
route_map_object_t type, void *object)
{
- u_int32_t *local_pref;
+ struct rmap_value *rv;
struct bgp_info *bgp_info;
+ u_int32_t locpref = 0;
if (type == RMAP_BGP)
{
/* Fetch routemap's rule information. */
- local_pref = rule;
+ rv = rule;
bgp_info = object;
/* Set local preference value. */
+ if (bgp_info->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
+ locpref = bgp_info->attr->local_pref;
+
bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF);
- bgp_info->attr->local_pref = *local_pref;
+ bgp_info->attr->local_pref = route_value_adjust(rv, locpref);
}
return RMAP_OKAY;
}
-/* set local preference compilation. */
-static void *
-route_set_local_pref_compile (const char *arg)
-{
- unsigned long tmp;
- u_int32_t *local_pref;
- char *endptr = NULL;
-
- /* Local preference value shoud be integer. */
- if (! all_digit (arg))
- return NULL;
-
- errno = 0;
- tmp = strtoul (arg, &endptr, 10);
- if (*endptr != '\0' || errno || tmp > UINT32_MAX)
- return NULL;
-
- local_pref = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
-
- if (!local_pref)
- return local_pref;
-
- *local_pref = tmp;
-
- return local_pref;
-}
-
-/* Free route map's local preference value. */
-static void
-route_set_local_pref_free (void *rule)
-{
- XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
-}
-
/* Set local preference rule structure. */
struct route_map_rule_cmd route_set_local_pref_cmd =
{
"local-preference",
route_set_local_pref,
- route_set_local_pref_compile,
- route_set_local_pref_free,
+ route_value_compile,
+ route_value_free,
};
/* `set weight WEIGHT' */
@@ -1059,18 +1072,20 @@ static route_map_result_t
route_set_weight (void *rule, struct prefix *prefix, route_map_object_t type,
void *object)
{
- u_int32_t *weight;
+ struct rmap_value *rv;
struct bgp_info *bgp_info;
+ u_int32_t weight;
if (type == RMAP_BGP)
{
/* Fetch routemap's rule information. */
- weight = rule;
+ rv = rule;
bgp_info = object;
/* Set weight value. */
- if (*weight)
- (bgp_attr_extra_get (bgp_info->attr))->weight = *weight;
+ weight = route_value_adjust(rv, 0);
+ if (weight)
+ (bgp_attr_extra_get (bgp_info->attr))->weight = weight;
else if (bgp_info->attr->extra)
bgp_info->attr->extra->weight = 0;
}
@@ -1078,47 +1093,13 @@ route_set_weight (void *rule, struct prefix *prefix, route_map_object_t type,
return RMAP_OKAY;
}
-/* set local preference compilation. */
-static void *
-route_set_weight_compile (const char *arg)
-{
- unsigned long tmp;
- u_int32_t *weight;
- char *endptr = NULL;
-
- /* Local preference value shoud be integer. */
- if (! all_digit (arg))
- return NULL;
-
- errno = 0;
- tmp = strtoul (arg, &endptr, 10);
- if (*endptr != '\0' || errno || tmp > UINT32_MAX)
- return NULL;
-
- weight = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
-
- if (weight == NULL)
- return weight;
-
- *weight = tmp;
-
- return weight;
-}
-
-/* Free route map's local preference value. */
-static void
-route_set_weight_free (void *rule)
-{
- XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
-}
-
/* Set local preference rule structure. */
struct route_map_rule_cmd route_set_weight_cmd =
{
"weight",
route_set_weight,
- route_set_weight_compile,
- route_set_weight_free,
+ route_value_compile,
+ route_value_free,
};
/* `set metric METRIC' */
@@ -1128,94 +1109,32 @@ static route_map_result_t
route_set_metric (void *rule, struct prefix *prefix,
route_map_object_t type, void *object)
{
- char *metric;
- u_int32_t metric_val;
+ struct rmap_value *rv;
struct bgp_info *bgp_info;
+ u_int32_t med = 0;
if (type == RMAP_BGP)
{
/* Fetch routemap's rule information. */
- metric = rule;
+ rv = rule;
bgp_info = object;
- if (! (bgp_info->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)))
- bgp_info->attr->med = 0;
- bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
+ if (bgp_info->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
+ med = bgp_info->attr->med;
- if (all_digit (metric))
- {
- metric_val = strtoul (metric, (char **)NULL, 10);
- bgp_info->attr->med = metric_val;
- }
- else
- {
- metric_val = strtoul (metric+1, (char **)NULL, 10);
-
- if (strncmp (metric, "+", 1) == 0)
- {
- if (bgp_info->attr->med/2 + metric_val/2 > BGP_MED_MAX/2)
- bgp_info->attr->med = BGP_MED_MAX - 1;
- else
- bgp_info->attr->med += metric_val;
- }
- else if (strncmp (metric, "-", 1) == 0)
- {
- if (bgp_info->attr->med <= metric_val)
- bgp_info->attr->med = 0;
- else
- bgp_info->attr->med -= metric_val;
- }
- }
+ bgp_info->attr->med = route_value_adjust(rv, med);
+ bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
}
return RMAP_OKAY;
}
-/* set metric compilation. */
-static void *
-route_set_metric_compile (const char *arg)
-{
- unsigned long larg;
- char *endptr = NULL;
-
- if (all_digit (arg))
- {
- /* set metric value check*/
- errno = 0;
- larg = strtoul (arg, &endptr, 10);
- if (*endptr != '\0' || errno || larg > UINT32_MAX)
- return NULL;
- }
- else
- {
- /* set metric +/-value check */
- if ((strncmp (arg, "+", 1) != 0
- && strncmp (arg, "-", 1) != 0)
- || (! all_digit (arg+1)))
- return NULL;
-
- errno = 0;
- larg = strtoul (arg+1, &endptr, 10);
- if (*endptr != '\0' || errno || larg > UINT32_MAX)
- return NULL;
- }
-
- return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
-}
-
-/* Free route map's compiled `set metric' value. */
-static void
-route_set_metric_free (void *rule)
-{
- XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
-}
-
/* Set metric rule structure. */
struct route_map_rule_cmd route_set_metric_cmd =
{
"metric",
route_set_metric,
- route_set_metric_compile,
- route_set_metric_free,
+ route_value_compile,
+ route_value_free,
};
/* `set as-path prepend ASPATH' */