summaryrefslogtreecommitdiffstats
path: root/ospf6d/ospf6_asbr.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--ospf6d/ospf6_asbr.c112
1 files changed, 83 insertions, 29 deletions
diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c
index d1c2b8b..2065527 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"
@@ -101,9 +102,8 @@ struct ospf6_lsa *ospf6_as_external_lsa_originate(struct ospf6_route *route,
/* prepare buffer */
memset(buffer, 0, sizeof(buffer));
lsa_header = (struct ospf6_lsa_header *)buffer;
- as_external_lsa = (struct ospf6_as_external_lsa
- *)((caddr_t)lsa_header
- + sizeof(struct ospf6_lsa_header));
+ as_external_lsa = (struct ospf6_as_external_lsa *)ospf6_lsa_header_end(
+ lsa_header);
p = (caddr_t)((caddr_t)as_external_lsa
+ sizeof(struct ospf6_as_external_lsa));
@@ -216,7 +216,7 @@ static route_tag_t ospf6_as_external_lsa_get_tag(struct ospf6_lsa *lsa)
if (!lsa)
return 0;
- external = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
+ external = (struct ospf6_as_external_lsa *)ospf6_lsa_header_end(
lsa->header);
if (!CHECK_FLAG(external->bits_metric, OSPF6_ASBR_BIT_T))
@@ -520,7 +520,7 @@ void ospf6_asbr_lsa_add(struct ospf6_lsa *lsa)
type = ntohs(lsa->header->type);
oa = lsa->lsdb->data;
- external = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
+ external = (struct ospf6_as_external_lsa *)ospf6_lsa_header_end(
lsa->header);
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL))
@@ -725,7 +725,7 @@ void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa,
int type;
bool debug = false;
- external = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
+ external = (struct ospf6_as_external_lsa *)ospf6_lsa_header_end(
lsa->header);
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL) || (IS_OSPF6_DEBUG_NSSA))
@@ -1426,10 +1426,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 +1471,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 +1924,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 +2153,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)
@@ -2368,7 +2424,7 @@ static char *ospf6_as_external_lsa_get_prefix_str(struct ospf6_lsa *lsa,
char tbuf[16];
if (lsa) {
- external = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
+ external = (struct ospf6_as_external_lsa *)ospf6_lsa_header_end(
lsa->header);
if (pos == 0) {
@@ -2403,7 +2459,7 @@ static int ospf6_as_external_lsa_show(struct vty *vty, struct ospf6_lsa *lsa,
char buf[64];
assert(lsa->header);
- external = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
+ external = (struct ospf6_as_external_lsa *)ospf6_lsa_header_end(
lsa->header);
/* bits */
@@ -2971,8 +3027,8 @@ ospf6_originate_summary_lsa(struct ospf6 *ospf6,
return;
}
- external = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END
- (aggr_lsa->header);
+ external = (struct ospf6_as_external_lsa *)ospf6_lsa_header_end(
+ aggr_lsa->header);
metric = (unsigned long)OSPF6_ASBR_METRIC(external);
tag = ospf6_as_external_lsa_get_tag(aggr_lsa);
mtype = CHECK_FLAG(external->bits_metric,
@@ -3120,8 +3176,7 @@ ospf6_handle_external_aggr_modify(struct ospf6 *ospf6,
return OSPF6_FAILURE;
}
- asel = (struct ospf6_as_external_lsa *)
- OSPF6_LSA_HEADER_END(lsa->header);
+ asel = (struct ospf6_as_external_lsa *)ospf6_lsa_header_end(lsa->header);
metric = (unsigned long)OSPF6_ASBR_METRIC(asel);
tag = ospf6_as_external_lsa_get_tag(lsa);
mtype = CHECK_FLAG(asel->bits_metric,
@@ -3310,9 +3365,8 @@ static void ospf6_handle_aggregated_exnl_rt(struct ospf6 *ospf6,
lsa = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL),
htonl(info->id), ospf6->router_id, ospf6->lsdb);
if (lsa) {
- ext_lsa = (struct ospf6_as_external_lsa
- *)((char *)(lsa->header)
- + sizeof(struct ospf6_lsa_header));
+ ext_lsa = (struct ospf6_as_external_lsa *)ospf6_lsa_header_end(
+ lsa->header);
if (rt->prefix.prefixlen != ext_lsa->prefix.prefix_length)
return;