summaryrefslogtreecommitdiffstats
path: root/ospf6d
diff options
context:
space:
mode:
authorAlexander Rose <alexander.rose@secunet.com>2024-04-11 13:07:33 +0200
committerAlexander Rose <alexander.rose@secunet.com>2024-05-06 08:51:27 +0200
commit84d1285fc2c9b8944313cc4e8f0c74a5bf76bcf1 (patch)
tree6dbeb9638894b9bc24887c65b25e17f26a961c17 /ospf6d
parentMerge pull request #15770 from idryzhov/fix-yang-exit (diff)
downloadfrr-84d1285fc2c9b8944313cc4e8f0c74a5bf76bcf1.tar.xz
frr-84d1285fc2c9b8944313cc4e8f0c74a5bf76bcf1.zip
ospf6d: Redistribute metric for AS-external route
When ospf6d originates an AS-external route that has been read from a kernel routing table, then the metric of that route was ignored until now. If a routemap is configured, then this metric will be redistributed from now on. Using metric increment and decrement in routemaps is supported by ospf6d now. Signed-off-by: Alexander Rose <alexander.rose@secunet.com>
Diffstat (limited to 'ospf6d')
-rw-r--r--ospf6d/ospf6_abr.h5
-rw-r--r--ospf6d/ospf6_asbr.c85
-rw-r--r--ospf6d/ospf6_asbr.h11
-rw-r--r--ospf6d/ospf6_route.h3
-rw-r--r--ospf6d/ospf6_zebra.c2
5 files changed, 85 insertions, 21 deletions
diff --git a/ospf6d/ospf6_abr.h b/ospf6d/ospf6_abr.h
index 7bb161913..52686ed49 100644
--- a/ospf6d/ospf6_abr.h
+++ b/ospf6d/ospf6_abr.h
@@ -33,11 +33,12 @@ struct ospf6_inter_router_lsa {
uint32_t router_id;
};
-#define OSPF6_ABR_SUMMARY_METRIC(E) (ntohl ((E)->metric & htonl (0x00ffffff)))
+#define OSPF6_ABR_SUMMARY_METRIC(E) \
+ (ntohl((E)->metric & htonl(OSPF6_EXT_PATH_METRIC_MAX)))
#define OSPF6_ABR_SUMMARY_METRIC_SET(E, C) \
{ \
(E)->metric &= htonl(0x00000000); \
- (E)->metric |= htonl(0x00ffffff) & htonl(C); \
+ (E)->metric |= htonl(OSPF6_EXT_PATH_METRIC_MAX) & htonl(C); \
}
#define OSPF6_ABR_RANGE_CLEAR_COST(range) (range->path.cost = OSPF_AREA_RANGE_COST_UNSPEC)
diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c
index d1c2b8bfc..701704cdc 100644
--- a/ospf6d/ospf6_asbr.c
+++ b/ospf6d/ospf6_asbr.c
@@ -14,6 +14,7 @@
#include "table.h"
#include "plist.h"
#include "frrevent.h"
+#include "frrstr.h"
#include "linklist.h"
#include "lib/northbound_cli.h"
@@ -1426,10 +1427,9 @@ static void ospf6_external_lsa_fwd_addr_set(struct ospf6 *ospf6,
}
void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex,
- struct prefix *prefix,
- unsigned int nexthop_num,
- const struct in6_addr *nexthop,
- route_tag_t tag, struct ospf6 *ospf6)
+ struct prefix *prefix, unsigned int nexthop_num,
+ const struct in6_addr *nexthop, route_tag_t tag,
+ struct ospf6 *ospf6, uint32_t metric)
{
route_map_result_t ret;
struct ospf6_route troute;
@@ -1472,6 +1472,7 @@ void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex,
if (ROUTEMAP(red)) {
troute.route_option = &tinfo;
troute.ospf6 = ospf6;
+ troute.path.redistribute_cost = metric;
tinfo.ifindex = ifindex;
tinfo.tag = tag;
@@ -1924,7 +1925,7 @@ static void ospf6_redistribute_default_set(struct ospf6 *ospf6, int originate)
case DEFAULT_ORIGINATE_ALWAYS:
ospf6_asbr_redistribute_add(DEFAULT_ROUTE, 0,
(struct prefix *)&p, 0, &nexthop, 0,
- ospf6);
+ ospf6, 0);
break;
}
}
@@ -2153,25 +2154,81 @@ static const struct route_map_rule_cmd
ospf6_routemap_rule_set_metric_type_free,
};
+struct ospf6_metric {
+ enum { metric_increment, metric_decrement, metric_absolute } type;
+ bool used;
+ uint32_t metric;
+};
+
static enum route_map_cmd_result_t
ospf6_routemap_rule_set_metric(void *rule, const struct prefix *prefix,
void *object)
{
- char *metric = rule;
- struct ospf6_route *route = object;
+ struct ospf6_metric *metric;
+ struct ospf6_route *route;
+
+ /* Fetch routemap's rule information. */
+ metric = rule;
+ route = object;
+
+ /* Set metric out value. */
+ if (!metric->used)
+ return RMAP_OKAY;
+
+ if (route->path.redistribute_cost > OSPF6_EXT_PATH_METRIC_MAX)
+ route->path.redistribute_cost = OSPF6_EXT_PATH_METRIC_MAX;
+
+ if (metric->type == metric_increment) {
+ route->path.cost = route->path.redistribute_cost +
+ metric->metric;
+
+ /* Check overflow */
+ if (route->path.cost > OSPF6_EXT_PATH_METRIC_MAX ||
+ route->path.cost < metric->metric)
+ route->path.cost = OSPF6_EXT_PATH_METRIC_MAX;
+ } else if (metric->type == metric_decrement) {
+ route->path.cost = route->path.redistribute_cost -
+ metric->metric;
+
+ /* Check overflow */
+ if (route->path.cost == 0 ||
+ route->path.cost > route->path.redistribute_cost)
+ route->path.cost = 1;
+ } else if (metric->type == metric_absolute)
+ route->path.cost = metric->metric;
- route->path.cost = atoi(metric);
return RMAP_OKAY;
}
static void *ospf6_routemap_rule_set_metric_compile(const char *arg)
{
- uint32_t metric;
- char *endp;
- metric = strtoul(arg, &endp, 0);
- if (metric > OSPF_LS_INFINITY || *endp != '\0')
- return NULL;
- return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
+ struct ospf6_metric *metric;
+
+ metric = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(*metric));
+ metric->used = false;
+
+ if (all_digit(arg))
+ metric->type = metric_absolute;
+
+ if ((arg[0] == '+') && all_digit(arg + 1)) {
+ metric->type = metric_increment;
+ arg++;
+ }
+
+ if ((arg[0] == '-') && all_digit(arg + 1)) {
+ metric->type = metric_decrement;
+ arg++;
+ }
+
+ metric->metric = strtoul(arg, NULL, 10);
+
+ if (metric->metric > OSPF6_EXT_PATH_METRIC_MAX)
+ metric->metric = OSPF6_EXT_PATH_METRIC_MAX;
+
+ if (metric->metric)
+ metric->used = true;
+
+ return metric;
}
static void ospf6_routemap_rule_set_metric_free(void *rule)
diff --git a/ospf6d/ospf6_asbr.h b/ospf6d/ospf6_asbr.h
index d63e46727..21e6d898e 100644
--- a/ospf6d/ospf6_asbr.h
+++ b/ospf6d/ospf6_asbr.h
@@ -94,11 +94,13 @@ struct ospf6_as_external_lsa {
#define OSPF6_ASBR_BIT_F ntohl (0x02000000)
#define OSPF6_ASBR_BIT_E ntohl (0x04000000)
-#define OSPF6_ASBR_METRIC(E) (ntohl ((E)->bits_metric & htonl (0x00ffffff)))
+#define OSPF6_ASBR_METRIC(E) \
+ (ntohl((E)->bits_metric & htonl(OSPF6_EXT_PATH_METRIC_MAX)))
#define OSPF6_ASBR_METRIC_SET(E, C) \
{ \
- (E)->bits_metric &= htonl(0xff000000); \
- (E)->bits_metric |= htonl(0x00ffffff) & htonl(C); \
+ (E)->bits_metric &= htonl(~OSPF6_EXT_PATH_METRIC_MAX); \
+ (E)->bits_metric |= htonl(OSPF6_EXT_PATH_METRIC_MAX) & \
+ htonl(C); \
}
extern void ospf6_asbr_lsa_add(struct ospf6_lsa *lsa);
@@ -115,7 +117,8 @@ extern void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex,
struct prefix *prefix,
unsigned int nexthop_num,
const struct in6_addr *nexthop,
- route_tag_t tag, struct ospf6 *ospf6);
+ route_tag_t tag, struct ospf6 *ospf6,
+ uint32_t metric);
extern void ospf6_asbr_redistribute_remove(int type, ifindex_t ifindex,
struct prefix *prefix,
struct ospf6 *ospf6);
diff --git a/ospf6d/ospf6_route.h b/ospf6d/ospf6_route.h
index 2c1d17efc..d3c180465 100644
--- a/ospf6d/ospf6_route.h
+++ b/ospf6d/ospf6_route.h
@@ -115,6 +115,7 @@ struct ospf6_path {
/* Cost */
uint8_t metric_type;
uint32_t cost;
+ uint32_t redistribute_cost;
struct prefix ls_prefix;
@@ -139,6 +140,8 @@ struct ospf6_path {
#define OSPF6_PATH_COST_IS_CONFIGURED(path) (path.u.cost_config != OSPF_AREA_RANGE_COST_UNSPEC)
+#define OSPF6_EXT_PATH_METRIC_MAX 0x00ffffff
+
#include "prefix.h"
#include "table.h"
#include "bitfield.h"
diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c
index 3245578b0..911f3567d 100644
--- a/ospf6d/ospf6_zebra.c
+++ b/ospf6d/ospf6_zebra.c
@@ -289,7 +289,7 @@ static int ospf6_zebra_read_route(ZAPI_CALLBACK_ARGS)
if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
ospf6_asbr_redistribute_add(api.type, ifindex, &api.prefix,
api.nexthop_num, nexthop, api.tag,
- ospf6);
+ ospf6, api.metric);
else
ospf6_asbr_redistribute_remove(api.type, ifindex, &api.prefix,
ospf6);