summaryrefslogtreecommitdiff
path: root/ospf6d/ospf6_abr.c
diff options
context:
space:
mode:
Diffstat (limited to 'ospf6d/ospf6_abr.c')
-rw-r--r--ospf6d/ospf6_abr.c373
1 files changed, 195 insertions, 178 deletions
diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c
index f289bf26b9..a9b4c7756c 100644
--- a/ospf6d/ospf6_abr.c
+++ b/ospf6d/ospf6_abr.c
@@ -53,6 +53,16 @@
unsigned char conf_debug_ospf6_abr;
+int ospf6_ls_origin_same(struct ospf6_path *o_path, struct ospf6_path *r_path)
+{
+ if (((o_path->origin.type == r_path->origin.type)
+ && (o_path->origin.id == r_path->origin.id)
+ && (o_path->origin.adv_router == r_path->origin.adv_router)))
+ return 1;
+ else
+ return 0;
+}
+
bool ospf6_check_and_set_router_abr(struct ospf6 *o)
{
struct listnode *node;
@@ -96,8 +106,7 @@ static int ospf6_abr_nexthops_belong_to_area(struct ospf6_route *route,
return 0;
}
-static void ospf6_abr_delete_route(struct ospf6_route *range,
- struct ospf6_route *summary,
+static void ospf6_abr_delete_route(struct ospf6_route *summary,
struct ospf6_route_table *summary_table,
struct ospf6_lsa *old)
{
@@ -172,9 +181,19 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
uint16_t type;
int is_debug = 0;
- if (IS_OSPF6_DEBUG_ABR)
- zlog_debug("%s : start area %s, route %pFX", __func__,
- area->name, &route->prefix);
+ if (IS_OSPF6_DEBUG_ABR) {
+ char buf[BUFSIZ];
+
+ if (route->type == OSPF6_DEST_TYPE_ROUTER)
+ inet_ntop(AF_INET,
+ &ADV_ROUTER_IN_PREFIX(&route->prefix), buf,
+ sizeof(buf));
+ else
+ prefix2str(&route->prefix, buf, sizeof(buf));
+
+ zlog_debug("%s : start area %s, route %s", __func__, area->name,
+ buf);
+ }
if (route->type == OSPF6_DEST_TYPE_ROUTER)
summary_table = area->summary_router;
@@ -221,6 +240,69 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
return 0;
}
+ if (route->type == OSPF6_DEST_TYPE_NETWORK) {
+ bool filter = false;
+
+ route_area =
+ ospf6_area_lookup(route->path.area_id, area->ospf6);
+ assert(route_area);
+
+ /* Check export-list */
+ if (EXPORT_LIST(route_area)
+ && access_list_apply(EXPORT_LIST(route_area),
+ &route->prefix)
+ == FILTER_DENY) {
+ if (IS_OSPF6_DEBUG_ABR)
+ zlog_debug(
+ "%s: prefix %pFX was denied by export-list",
+ __func__, &route->prefix);
+ filter = true;
+ }
+
+ /* Check output prefix-list */
+ if (PREFIX_LIST_OUT(route_area)
+ && prefix_list_apply(PREFIX_LIST_OUT(route_area),
+ &route->prefix)
+ != PREFIX_PERMIT) {
+ if (IS_OSPF6_DEBUG_ABR)
+ zlog_debug(
+ "%s: prefix %pFX was denied by prefix-list out",
+ __func__, &route->prefix);
+ filter = true;
+ }
+
+ /* Check import-list */
+ if (IMPORT_LIST(area)
+ && access_list_apply(IMPORT_LIST(area), &route->prefix)
+ == FILTER_DENY) {
+ if (IS_OSPF6_DEBUG_ABR)
+ zlog_debug(
+ "%s: prefix %pFX was denied by import-list",
+ __func__, &route->prefix);
+ filter = true;
+ }
+
+ /* Check input prefix-list */
+ if (PREFIX_LIST_IN(area)
+ && prefix_list_apply(PREFIX_LIST_IN(area), &route->prefix)
+ != PREFIX_PERMIT) {
+ if (IS_OSPF6_DEBUG_ABR)
+ zlog_debug(
+ "%s: prefix %pFX was denied by prefix-list in",
+ __func__, &route->prefix);
+ filter = true;
+ }
+
+ if (filter) {
+ if (summary) {
+ ospf6_route_remove(summary, summary_table);
+ if (old)
+ ospf6_lsa_purge(old);
+ }
+ return 0;
+ }
+ }
+
/* do not generate if the nexthops belongs to the target area */
if (ospf6_abr_nexthops_belong_to_area(route, area)) {
if (IS_OSPF6_DEBUG_ABR)
@@ -302,8 +384,8 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
zlog_debug(
"The range is not active. withdraw");
- ospf6_abr_delete_route(route, summary,
- summary_table, old);
+ ospf6_abr_delete_route(summary, summary_table,
+ old);
}
} else if (old) {
ospf6_route_remove(summary, summary_table);
@@ -317,7 +399,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
zlog_debug(
"Area has been stubbed, purge Inter-Router LSA");
- ospf6_abr_delete_route(route, summary, summary_table, old);
+ ospf6_abr_delete_route(summary, summary_table, old);
return 0;
}
@@ -326,7 +408,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
if (is_debug)
zlog_debug("Area has been stubbed, purge prefix LSA");
- ospf6_abr_delete_route(route, summary, summary_table, old);
+ ospf6_abr_delete_route(summary, summary_table, old);
return 0;
}
@@ -361,8 +443,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
if (is_debug)
zlog_debug(
"This is the secondary path to the ASBR, ignore");
- ospf6_abr_delete_route(route, summary, summary_table,
- old);
+ ospf6_abr_delete_route(summary, summary_table, old);
return 0;
}
@@ -392,8 +473,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
zlog_debug(
"Suppressed by range %pFX of area %s",
&range->prefix, route_area->name);
- ospf6_abr_delete_route(route, summary, summary_table,
- old);
+ ospf6_abr_delete_route(summary, summary_table, old);
return 0;
}
}
@@ -405,8 +485,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
if (is_debug)
zlog_debug(
"This is the range with DoNotAdvertise set. ignore");
- ospf6_abr_delete_route(route, summary, summary_table,
- old);
+ ospf6_abr_delete_route(summary, summary_table, old);
return 0;
}
@@ -414,45 +493,11 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
if (!CHECK_FLAG(route->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)) {
if (is_debug)
zlog_debug("The range is not active. withdraw");
- ospf6_abr_delete_route(route, summary, summary_table,
- old);
+ ospf6_abr_delete_route(summary, summary_table, old);
return 0;
}
}
- /* Check export list */
- if (EXPORT_NAME(area)) {
- if (EXPORT_LIST(area) == NULL)
- EXPORT_LIST(area) =
- access_list_lookup(AFI_IP6, EXPORT_NAME(area));
-
- if (EXPORT_LIST(area))
- if (access_list_apply(EXPORT_LIST(area), &route->prefix)
- == FILTER_DENY) {
- if (is_debug)
- zlog_debug(
- "prefix %pFX was denied by export list",
- &route->prefix);
- ospf6_abr_delete_route(route, summary,
- summary_table, old);
- return 0;
- }
- }
-
- /* Check filter-list */
- if (PREFIX_LIST_OUT(area))
- if (prefix_list_apply(PREFIX_LIST_OUT(area), &route->prefix)
- != PREFIX_PERMIT) {
- if (is_debug)
- zlog_debug(
- "prefix %pFX was denied by filter-list out",
- &route->prefix);
- ospf6_abr_delete_route(route, summary, summary_table,
- old);
-
- return 0;
- }
-
/* the route is going to be originated. store it in area's summary_table
*/
if (summary == NULL) {
@@ -477,11 +522,11 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
monotime(&summary->changed);
}
+ summary->prefix_options = route->prefix_options;
summary->path.router_bits = route->path.router_bits;
summary->path.options[0] = route->path.options[0];
summary->path.options[1] = route->path.options[1];
summary->path.options[2] = route->path.options[2];
- summary->path.prefix_options = route->path.prefix_options;
summary->path.area_id = area->area_id;
summary->path.type = OSPF6_PATH_TYPE_INTER;
summary->path.subtype = route->path.subtype;
@@ -514,7 +559,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
/* Fill Inter-Area-Prefix-LSA */
OSPF6_ABR_SUMMARY_METRIC_SET(prefix_lsa, route->path.cost);
prefix_lsa->prefix.prefix_length = route->prefix.prefixlen;
- prefix_lsa->prefix.prefix_options = route->path.prefix_options;
+ prefix_lsa->prefix.prefix_options = route->prefix_options;
/* set Prefix */
memcpy(p, &route->prefix.u.prefix6,
@@ -558,10 +603,14 @@ void ospf6_abr_range_reset_cost(struct ospf6 *ospf6)
struct ospf6_area *oa;
struct ospf6_route *range;
- for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa))
+ for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) {
for (range = ospf6_route_head(oa->range_table); range;
range = ospf6_route_next(range))
OSPF6_ABR_RANGE_CLEAR_COST(range);
+ for (range = ospf6_route_head(oa->nssa_range_table); range;
+ range = ospf6_route_next(range))
+ OSPF6_ABR_RANGE_CLEAR_COST(range);
+ }
}
static inline uint32_t ospf6_abr_range_compute_cost(struct ospf6_route *range,
@@ -572,10 +621,19 @@ static inline uint32_t ospf6_abr_range_compute_cost(struct ospf6_route *range,
for (ro = ospf6_route_match_head(&range->prefix, o->route_table); ro;
ro = ospf6_route_match_next(&range->prefix, ro)) {
- if (ro->path.area_id == range->path.area_id
- && (ro->path.type == OSPF6_PATH_TYPE_INTRA)
- && !CHECK_FLAG(ro->flag, OSPF6_ROUTE_REMOVE))
- cost = MAX(cost, ro->path.cost);
+ if (CHECK_FLAG(ro->flag, OSPF6_ROUTE_REMOVE))
+ continue;
+ if (ro->path.area_id != range->path.area_id)
+ continue;
+ if (CHECK_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE)
+ && ro->path.type != OSPF6_PATH_TYPE_EXTERNAL1
+ && ro->path.type != OSPF6_PATH_TYPE_EXTERNAL2)
+ continue;
+ if (!CHECK_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE)
+ && ro->path.type != OSPF6_PATH_TYPE_INTRA)
+ continue;
+
+ cost = MAX(cost, ro->path.cost);
}
return cost;
@@ -624,6 +682,8 @@ void ospf6_abr_range_update(struct ospf6_route *range, struct ospf6 *ospf6)
int summary_orig = 0;
assert(range->type == OSPF6_DEST_TYPE_RANGE);
+ oa = ospf6_area_lookup(range->path.area_id, ospf6);
+ assert(oa);
/* update range's cost and active flag */
cost = ospf6_abr_range_compute_cost(range, ospf6);
@@ -646,34 +706,49 @@ void ospf6_abr_range_update(struct ospf6_route *range, struct ospf6 *ospf6)
* if there
* were active ranges.
*/
+ if (!ospf6_abr_range_summary_needs_update(range, cost))
+ return;
- if (ospf6_abr_range_summary_needs_update(range, cost)) {
- if (IS_OSPF6_DEBUG_ABR)
- zlog_debug("%s: range %pFX update", __func__,
- &range->prefix);
- for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa))
+ if (IS_OSPF6_DEBUG_ABR)
+ zlog_debug("%s: range %pFX update", __func__, &range->prefix);
+
+ if (CHECK_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE)) {
+ if (CHECK_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)
+ && !CHECK_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE)) {
+ ospf6_nssa_lsa_originate(range, oa, true);
+ summary_orig = 1;
+ } else {
+ struct ospf6_lsa *lsa;
+
+ lsa = ospf6_lsdb_lookup(range->path.origin.type,
+ range->path.origin.id,
+ ospf6->router_id, oa->lsdb);
+ if (lsa)
+ ospf6_lsa_premature_aging(lsa);
+ }
+ } else {
+ for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) {
summary_orig +=
ospf6_abr_originate_summary_to_area(range, oa);
+ }
+ }
- if (CHECK_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)
- && summary_orig) {
- if (!CHECK_FLAG(range->flag,
- OSPF6_ROUTE_BLACKHOLE_ADDED)) {
- if (IS_OSPF6_DEBUG_ABR)
- zlog_debug("Add discard route");
+ if (CHECK_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)
+ && summary_orig) {
+ if (!CHECK_FLAG(range->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) {
+ if (IS_OSPF6_DEBUG_ABR)
+ zlog_debug("Add discard route");
- ospf6_zebra_add_discard(range, ospf6);
- }
- } else {
- /* Summary removed or no summary generated as no
- * specifics exist */
- if (CHECK_FLAG(range->flag,
- OSPF6_ROUTE_BLACKHOLE_ADDED)) {
- if (IS_OSPF6_DEBUG_ABR)
- zlog_debug("Delete discard route");
+ ospf6_zebra_add_discard(range, ospf6);
+ }
+ } else {
+ /* Summary removed or no summary generated as no
+ * specifics exist */
+ if (CHECK_FLAG(range->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) {
+ if (IS_OSPF6_DEBUG_ABR)
+ zlog_debug("Delete discard route");
- ospf6_zebra_delete_discard(range, ospf6);
- }
+ ospf6_zebra_delete_discard(range, ospf6);
}
}
}
@@ -684,8 +759,18 @@ void ospf6_abr_originate_summary(struct ospf6_route *route, struct ospf6 *ospf6)
struct ospf6_area *oa;
struct ospf6_route *range = NULL;
- if (IS_OSPF6_DEBUG_ABR)
- zlog_debug("%s: route %pFX", __func__, &route->prefix);
+ if (IS_OSPF6_DEBUG_ABR) {
+ char buf[BUFSIZ];
+
+ if (route->type == OSPF6_DEST_TYPE_ROUTER)
+ inet_ntop(AF_INET,
+ &ADV_ROUTER_IN_PREFIX(&route->prefix), buf,
+ sizeof(buf));
+ else
+ prefix2str(&route->prefix, buf, sizeof(buf));
+
+ zlog_debug("%s: route %s", __func__, buf);
+ }
if (route->type == OSPF6_DEST_TYPE_NETWORK) {
oa = ospf6_area_lookup(route->path.area_id, ospf6);
@@ -710,25 +795,12 @@ void ospf6_abr_defaults_to_stub(struct ospf6 *o)
struct listnode *node, *nnode;
struct ospf6_area *oa;
struct ospf6_route *def, *route;
- struct ospf6_redist *red;
int type = DEFAULT_ROUTE;
- struct prefix_ipv6 p = {};
if (!o->backbone)
return;
- red = ospf6_redist_lookup(o, type, 0);
- if (!red)
- return;
-
- p.family = AF_INET6;
- p.prefixlen = 0;
-
- route = ospf6_route_lookup((struct prefix *)&p, o->external_table);
- if (!route)
- return;
-
- def = ospf6_route_create();
+ def = ospf6_route_create(o);
def->type = OSPF6_DEST_TYPE_NETWORK;
def->prefix.family = AF_INET6;
def->prefix.prefixlen = 0;
@@ -741,7 +813,15 @@ void ospf6_abr_defaults_to_stub(struct ospf6 *o)
def->path.cost = metric_value(o, type, 0);
for (ALL_LIST_ELEMENTS(o->area_list, node, nnode, oa)) {
- if (!IS_AREA_STUB(oa)) {
+ if (IS_AREA_STUB(oa) || (IS_AREA_NSSA(oa) && oa->no_summary)) {
+ /* announce defaults to stubby areas */
+ if (IS_OSPF6_DEBUG_ABR)
+ zlog_debug(
+ "Announcing default route into stubby area %s",
+ oa->name);
+ UNSET_FLAG(def->flag, OSPF6_ROUTE_REMOVE);
+ ospf6_abr_originate_summary_to_area(def, oa);
+ } else {
/* withdraw defaults when an area switches from stub to
* non-stub */
route = ospf6_route_lookup(&def->prefix,
@@ -755,14 +835,6 @@ void ospf6_abr_defaults_to_stub(struct ospf6 *o)
SET_FLAG(def->flag, OSPF6_ROUTE_REMOVE);
ospf6_abr_originate_summary_to_area(def, oa);
}
- } else {
- /* announce defaults to stubby areas */
- if (IS_OSPF6_DEBUG_ABR)
- zlog_debug(
- "Announcing default route into stubby area %s",
- oa->name);
- UNSET_FLAG(def->flag, OSPF6_ROUTE_REMOVE);
- ospf6_abr_originate_summary_to_area(def, oa);
}
}
ospf6_route_delete(def);
@@ -778,9 +850,8 @@ void ospf6_abr_old_path_update(struct ospf6_route *old_route,
struct ospf6_nexthop *nh, *rnh;
for (ALL_LIST_ELEMENTS(old_route->paths, anode, anext, o_path)) {
- if (o_path->area_id != route->path.area_id ||
- (memcmp(&(o_path)->origin, &(route)->path.origin,
- sizeof(struct ospf6_ls_origin)) != 0))
+ if (o_path->area_id != route->path.area_id
+ || !ospf6_ls_origin_same(o_path, &route->path))
continue;
if ((o_path->cost == route->path.cost) &&
@@ -1127,46 +1198,14 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
return;
}
- /* Check import list */
- if (IMPORT_NAME(oa)) {
- if (IMPORT_LIST(oa) == NULL)
- IMPORT_LIST(oa) =
- access_list_lookup(AFI_IP6, IMPORT_NAME(oa));
-
- if (IMPORT_LIST(oa))
- if (access_list_apply(IMPORT_LIST(oa), &prefix)
- == FILTER_DENY) {
- if (is_debug)
- zlog_debug(
- "Prefix %pFX was denied by import-list",
- &prefix);
- if (old)
- ospf6_route_remove(old, table);
- return;
- }
- }
-
- /* Check input prefix-list */
- if (PREFIX_LIST_IN(oa)) {
- if (prefix_list_apply(PREFIX_LIST_IN(oa), &prefix)
- != PREFIX_PERMIT) {
- if (is_debug)
- zlog_debug(
- "Prefix %pFX was denied by prefix-list in",
- &prefix);
- if (old)
- ospf6_route_remove(old, table);
- return;
- }
- }
-
/* (5),(6): the path preference is handled by the sorting
in the routing table. Always install the path by substituting
old route (if any). */
- route = ospf6_route_create();
+ route = ospf6_route_create(oa->ospf6);
route->type = type;
route->prefix = prefix;
+ route->prefix_options = prefix_options;
route->path.origin.type = lsa->header->type;
route->path.origin.id = lsa->header->id;
route->path.origin.adv_router = lsa->header->adv_router;
@@ -1174,7 +1213,6 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
route->path.options[0] = options[0];
route->path.options[1] = options[1];
route->path.options[2] = options[2];
- route->path.prefix_options = prefix_options;
route->path.area_id = oa->area_id;
route->path.type = OSPF6_PATH_TYPE_INTER;
route->path.cost = abr_entry->path.cost + cost;
@@ -1194,9 +1232,16 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
__func__, &prefix, listcount(old->paths));
}
for (old_route = old; old_route; old_route = old_route->next) {
- if (!ospf6_route_is_same(old_route, route) ||
- (old_route->type != route->type) ||
- (old_route->path.type != route->path.type))
+
+ /* The route linked-list is grouped in batches of prefix.
+ * If the new prefix is not the same as the one of interest
+ * then we have walked over the end of the batch and so we
+ * should break rather than continuing unnecessarily.
+ */
+ if (!ospf6_route_is_same(old_route, route))
+ break;
+ if ((old_route->type != route->type)
+ || (old_route->path.type != route->path.type))
continue;
if ((ospf6_route_cmp(route, old_route) != 0)) {
@@ -1221,9 +1266,8 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
for (ALL_LIST_ELEMENTS_RO(old_route->paths, anode,
o_path)) {
- if (o_path->area_id == route->path.area_id &&
- (memcmp(&(o_path)->origin, &(route)->path.origin,
- sizeof(struct ospf6_ls_origin)) == 0))
+ if (o_path->area_id == route->path.area_id
+ && ospf6_ls_origin_same(o_path, &route->path))
break;
}
@@ -1250,7 +1294,9 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
listcount(old_route->nh_list));
}
} else {
- struct ospf6_route *tmp_route = ospf6_route_create();
+ struct ospf6_route *tmp_route;
+
+ tmp_route = ospf6_route_create(oa->ospf6);
ospf6_copy_nexthops(tmp_route->nh_list,
o_path->nh_list);
@@ -1339,35 +1385,6 @@ void ospf6_abr_examin_brouter(uint32_t router_id, struct ospf6_route *route,
ospf6_abr_examin_summary(lsa, oa);
}
-void ospf6_abr_reimport(struct ospf6_area *oa)
-{
- struct ospf6_lsa *lsa;
- uint16_t type;
-
- type = htons(OSPF6_LSTYPE_INTER_ROUTER);
- for (ALL_LSDB_TYPED(oa->lsdb, type, lsa))
- ospf6_abr_examin_summary(lsa, oa);
-
- type = htons(OSPF6_LSTYPE_INTER_PREFIX);
- for (ALL_LSDB_TYPED(oa->lsdb, type, lsa))
- ospf6_abr_examin_summary(lsa, oa);
-}
-
-/* export filter removed so determine if we should reoriginate summary LSAs */
-void ospf6_abr_reexport(struct ospf6_area *oa)
-{
- struct ospf6_route *route;
-
- /* if not a ABR return success */
- if (!ospf6_check_and_set_router_abr(oa->ospf6))
- return;
-
- /* Redo summaries if required */
- for (route = ospf6_route_head(oa->ospf6->route_table); route;
- route = ospf6_route_next(route))
- ospf6_abr_originate_summary_to_area(route, oa);
-}
-
void ospf6_abr_prefix_resummarize(struct ospf6 *o)
{
struct ospf6_route *route;