Merge pull request #9752 from opensourcerouting/ospf6d-nssa-ranges

ospf6d: add support for NSSA Type-7 address ranges
This commit is contained in:
Russ White 2021-10-19 19:15:40 -04:00 committed by GitHub
commit ed131d8b74
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 452 additions and 376 deletions

View File

@ -181,7 +181,7 @@ OSPF6 area
The `not-advertise` option, when present, prevents the summary route from
being advertised, effectively filtering the summarized routes.
.. clicmd:: area A.B.C.D nssa [no-summary]
.. clicmd:: area A.B.C.D nssa [no-summary] [default-information-originate [metric-type (1-2)] [metric (0-16777214)]]
.. clicmd:: area (0-4294967295) nssa [no-summary] [default-information-originate [metric-type (1-2)] [metric (0-16777214)]]
@ -209,6 +209,21 @@ OSPF6 area
existence of a default route in the RIB that wasn't learned via the OSPF
protocol.
.. clicmd:: area A.B.C.D nssa range X:X::X:X/M [<not-advertise|cost (0-16777215)>]
.. clicmd:: area (0-4294967295) nssa range X:X::X:X/M [<not-advertise|cost (0-16777215)>]
Summarize a group of external subnets into a single Type-7 LSA, which is
then translated to a Type-5 LSA and avertised to the backbone.
This command can only be used at the area boundary (NSSA ABR router).
By default, the metric of the summary route is calculated as the highest
metric among the summarized routes. The `cost` option, however, can be used
to set an explicit metric.
The `not-advertise` option, when present, prevents the summary route from
being advertised, effectively filtering the summarized routes.
.. clicmd:: area A.B.C.D export-list NAME
.. clicmd:: area (0-4294967295) export-list NAME

View File

@ -106,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)
{
@ -385,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);
@ -400,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;
}
@ -409,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;
}
@ -444,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;
}
@ -475,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;
}
}
@ -488,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;
}
@ -497,8 +493,7 @@ 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;
}
}
@ -608,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,
@ -622,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;
@ -674,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);
@ -696,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);
}
}
}

View File

@ -306,7 +306,8 @@ struct ospf6_area *ospf6_area_create(uint32_t area_id, struct ospf6 *o, int df)
oa->range_table = OSPF6_ROUTE_TABLE_CREATE(AREA, PREFIX_RANGES);
oa->range_table->scope = oa;
bf_init(oa->range_table->idspace, 32);
oa->nssa_range_table = OSPF6_ROUTE_TABLE_CREATE(AREA, PREFIX_RANGES);
oa->nssa_range_table->scope = oa;
oa->summary_prefix = OSPF6_ROUTE_TABLE_CREATE(AREA, SUMMARY_PREFIXES);
oa->summary_prefix->scope = oa;
oa->summary_router = OSPF6_ROUTE_TABLE_CREATE(AREA, SUMMARY_ROUTERS);
@ -361,6 +362,7 @@ void ospf6_area_delete(struct ospf6_area *oa)
ospf6_route_table_delete(oa->route_table);
ospf6_route_table_delete(oa->range_table);
ospf6_route_table_delete(oa->nssa_range_table);
ospf6_route_table_delete(oa->summary_prefix);
ospf6_route_table_delete(oa->summary_router);
@ -576,8 +578,6 @@ DEFUN (area_range,
range->path.u.cost_config = cost;
zlog_debug("%s: for prefix %s, flag = %x", __func__,
argv[idx_ipv6_prefixlen]->arg, range->flag);
if (range->rnode == NULL) {
ospf6_route_add(range, oa->range_table);
}
@ -694,6 +694,22 @@ void ospf6_area_config_write(struct vty *vty, struct ospf6 *ospf6)
vty_out(vty, " no-summary");
vty_out(vty, "\n");
}
for (range = ospf6_route_head(oa->nssa_range_table); range;
range = ospf6_route_next(range)) {
vty_out(vty, " area %s nssa range %pFX", oa->name,
&range->prefix);
if (CHECK_FLAG(range->flag,
OSPF6_ROUTE_DO_NOT_ADVERTISE)) {
vty_out(vty, " not-advertise");
} else {
if (range->path.u.cost_config
!= OSPF_AREA_RANGE_COST_UNSPEC)
vty_out(vty, " cost %u",
range->path.u.cost_config);
}
vty_out(vty, "\n");
}
if (PREFIX_NAME_IN(oa))
vty_out(vty, " area %s filter-list prefix %s in\n",
oa->name, PREFIX_NAME_IN(oa));

View File

@ -46,6 +46,7 @@ struct ospf6_area {
/* Summary routes to be originated (includes Configured Address Ranges)
*/
struct ospf6_route_table *range_table;
struct ospf6_route_table *nssa_range_table;
struct ospf6_route_table *summary_prefix;
struct ospf6_route_table *summary_router;

View File

@ -266,10 +266,14 @@ void ospf6_decrement_retrans_count(struct ospf6_lsa *lsa)
/* RFC2328 section 13.2 Installing LSAs in the database */
void ospf6_install_lsa(struct ospf6_lsa *lsa)
{
struct ospf6 *ospf6;
struct timeval now;
struct ospf6_lsa *old;
struct ospf6_area *area = NULL;
ospf6 = ospf6_get_by_lsdb(lsa);
assert(ospf6);
/* Remove the old instance from all neighbors' Link state
retransmission list (RFC2328 13.2 last paragraph) */
old = ospf6_lsdb_lookup(lsa->header->type, lsa->header->id,
@ -330,20 +334,14 @@ void ospf6_install_lsa(struct ospf6_lsa *lsa)
&& !CHECK_FLAG(lsa->flag, OSPF6_LSA_DUPLICATE)) {
/* check if it is new lsa ? or existing lsa got modified ?*/
if (!old || OSPF6_LSA_IS_CHANGED(old, lsa)) {
struct ospf6 *ospf6;
ospf6 = ospf6_get_by_lsdb(lsa);
assert(ospf6);
if (!old || OSPF6_LSA_IS_CHANGED(old, lsa))
ospf6_helper_handle_topo_chg(ospf6, lsa);
}
}
ospf6_lsdb_add(lsa, lsa->lsdb);
if (ntohs(lsa->header->type) == OSPF6_LSTYPE_TYPE_7) {
if (ntohs(lsa->header->type) == OSPF6_LSTYPE_TYPE_7
&& lsa->header->adv_router != ospf6->router_id) {
area = OSPF6_AREA(lsa->lsdb->data);
ospf6_translated_nssa_refresh(area, lsa, NULL);
ospf6_schedule_abr_task(area->ospf6);

View File

@ -1241,7 +1241,6 @@ struct in6_addr *ospf6_interface_get_global_address(struct interface *ifp)
{
struct listnode *n;
struct connected *c;
struct in6_addr *l = (struct in6_addr *)NULL;
/* for each connected address */
for (ALL_LIST_ELEMENTS_RO(ifp->connected, n, c)) {
@ -1250,9 +1249,10 @@ struct in6_addr *ospf6_interface_get_global_address(struct interface *ifp)
continue;
if (!IN6_IS_ADDR_LINKLOCAL(&c->address->u.prefix6))
l = &c->address->u.prefix6;
return &c->address->u.prefix6;
}
return l;
return NULL;
}

View File

@ -1070,7 +1070,7 @@ DEFPY (debug_ospf6_lsa_aggregation,
DEFUN (debug_ospf6_lsa_type,
debug_ospf6_lsa_hex_cmd,
"debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|link|intra-prefix|unknown> [<originate|examine|flooding>]",
"debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|nssa|link|intra-prefix|unknown> [<originate|examine|flooding>]",
DEBUG_STR
OSPF6_STR
"Debug Link State Advertisements (LSAs)\n"
@ -1079,6 +1079,7 @@ DEFUN (debug_ospf6_lsa_type,
"Display Inter-Area-Prefix LSAs\n"
"Display Inter-Router LSAs\n"
"Display As-External LSAs\n"
"Display NSSA LSAs\n"
"Display Link LSAs\n"
"Display Intra-Area-Prefix LSAs\n"
"Display LSAs of unknown origin\n"
@ -1122,7 +1123,7 @@ DEFUN (debug_ospf6_lsa_type,
DEFUN (no_debug_ospf6_lsa_type,
no_debug_ospf6_lsa_hex_cmd,
"no debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|link|intra-prefix|unknown> [<originate|examine|flooding>]",
"no debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|nssa|link|intra-prefix|unknown> [<originate|examine|flooding>]",
NO_STR
DEBUG_STR
OSPF6_STR
@ -1132,6 +1133,7 @@ DEFUN (no_debug_ospf6_lsa_type,
"Display Inter-Area-Prefix LSAs\n"
"Display Inter-Router LSAs\n"
"Display As-External LSAs\n"
"Display NSSA LSAs\n"
"Display Link LSAs\n"
"Display Intra-Area-Prefix LSAs\n"
"Display LSAs of unknown origin\n"

View File

@ -87,11 +87,6 @@
#define OSPF6_SCOPE_AS 0x4000
#define OSPF6_SCOPE_RESERVED 0x6000
/* AS-external-LSA refresh method. */
#define LSA_REFRESH_IF_CHANGED 0
#define LSA_REFRESH_FORCE 1
/* XXX U-bit handling should be treated here */
#define OSPF6_LSA_SCOPE(type) (ntohs(type) & OSPF6_LSTYPE_SCOPE_MASK)

View File

@ -48,7 +48,7 @@
#include "ospf6_gr.h"
#include "lib/json.h"
DEFINE_MTYPE(OSPF6D, OSPF6_NEIGHBOR, "OSPF6 neighbor");
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_NEIGHBOR, "OSPF6 neighbor");
DEFINE_HOOK(ospf6_neighbor_change,
(struct ospf6_neighbor * on, int state, int next_state),

View File

@ -49,6 +49,9 @@
#include "ospf6_asbr.h"
#include "ospf6d.h"
#include "ospf6_nssa.h"
#ifndef VTYSH_EXTRACT_PL
#include "ospf6d/ospf6_nssa_clippy.c"
#endif
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_LSA, "OSPF6 LSA");
unsigned char config_debug_ospf6_nssa = 0;
@ -262,22 +265,20 @@ static void ospf6_abr_announce_aggregates(struct ospf6 *ospf6)
{
struct ospf6_area *area;
struct ospf6_route *range;
struct listnode *node, *nnode;
struct listnode *node;
if (IS_OSPF6_DEBUG_ABR)
zlog_debug("ospf6_abr_announce_aggregates(): Start");
for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, area)) {
for (range = ospf6_route_head(area->range_table); range;
range = ospf6_route_next(range))
ospf6_abr_range_update(range, ospf6);
}
for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, area)) {
if (IS_OSPF6_DEBUG_ABR)
zlog_debug(
"ospf_abr_announce_aggregates(): looking at area %pI4",
&area->area_id);
for (range = ospf6_route_head(area->range_table); range;
range = ospf6_route_next(range))
ospf6_abr_range_update(range, ospf6);
}
if (IS_OSPF6_DEBUG_ABR)
@ -381,22 +382,18 @@ static void ospf6_abr_unapprove_translates(struct ospf6 *ospf6)
{
struct ospf6_lsa *lsa;
uint16_t type;
struct ospf6_area *oa;
struct listnode *node;
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug("ospf6_abr_unapprove_translates(): Start");
type = htons(OSPF6_LSTYPE_AS_EXTERNAL);
for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
for (ALL_LSDB_TYPED(oa->lsdb, type, lsa)) {
if (CHECK_FLAG(lsa->flag, OSPF6_LSA_LOCAL_XLT)) {
SET_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED);
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug(
"%s : approved unset on link id %pI4",
__func__, &lsa->header->id);
}
for (ALL_LSDB_TYPED(ospf6->lsdb, type, lsa)) {
if (CHECK_FLAG(lsa->flag, OSPF6_LSA_LOCAL_XLT)) {
SET_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED);
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug(
"%s : approved unset on link id %pI4",
__func__, &lsa->header->id);
}
}
@ -408,17 +405,17 @@ static void ospf6_abr_unapprove_translates(struct ospf6 *ospf6)
static struct ospf6_lsa *ospf6_lsa_translated_nssa_new(struct ospf6_area *area,
struct ospf6_lsa *type7)
{
char *buffer;
char buffer[OSPF6_MAX_LSASIZE];
struct ospf6_lsa *lsa;
struct ospf6_as_external_lsa *ext, *extnew;
struct ospf6_lsa_header *lsa_header;
caddr_t old_ptr, new_ptr;
struct ospf6_as_external_lsa *nssa;
struct prefix prefix;
struct ospf6_route *match;
struct ospf6 *ospf6 = area->ospf6;
ptrdiff_t tag_offset = 0;
route_tag_t network_order;
struct ospf6_route *range;
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug("%s : Start", __func__);
@ -430,7 +427,27 @@ static struct ospf6_lsa *ospf6_lsa_translated_nssa_new(struct ospf6_area *area,
return NULL;
}
buffer = XCALLOC(MTYPE_OSPF6_LSA, OSPF6_MAX_LSASIZE);
/* find the translated Type-5 for this Type-7 */
nssa = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
type7->header);
prefix.family = AF_INET6;
prefix.prefixlen = nssa->prefix.prefix_length;
ospf6_prefix_in6_addr(&prefix.u.prefix6, nssa, &nssa->prefix);
/* Check if the Type-7 LSA should be suppressed by aggregation. */
range = ospf6_route_lookup_bestmatch(&prefix, area->nssa_range_table);
if (range && !prefix_same(&prefix, &range->prefix)
&& !CHECK_FLAG(range->flag, OSPF6_ROUTE_REMOVE)) {
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug(
"%s: LSA %s suppressed by range %pFX of area %s",
__func__, type7->name, &range->prefix,
area->name);
return NULL;
}
/* prepare buffer */
memset(buffer, 0, sizeof(buffer));
lsa_header = (struct ospf6_lsa_header *)buffer;
extnew = (struct ospf6_as_external_lsa
*)((caddr_t)lsa_header
@ -445,23 +462,6 @@ static struct ospf6_lsa *ospf6_lsa_translated_nssa_new(struct ospf6_area *area,
memcpy(extnew, ext, sizeof(struct ospf6_as_external_lsa));
/* find the translated Type-5 for this Type-7 */
nssa = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
type7->header);
prefix.family = AF_INET6;
prefix.prefixlen = nssa->prefix.prefix_length;
ospf6_prefix_in6_addr(&prefix.u.prefix6, nssa, &nssa->prefix);
/* Find the LSA from the external route */
match = ospf6_route_lookup(&prefix, area->route_table);
if (match == NULL) {
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug("%s : no matching route %pFX", __func__,
&prefix);
return NULL;
}
/* set Prefix */
memcpy(new_ptr, old_ptr, OSPF6_PREFIX_SPACE(ext->prefix.prefix_length));
ospf6_prefix_apply_mask(&extnew->prefix);
@ -542,7 +542,6 @@ struct ospf6_lsa *ospf6_translated_nssa_refresh(struct ospf6_area *area,
struct ospf6_lsa *type5)
{
struct ospf6_lsa *new = NULL;
struct ospf6_as_external_lsa *ext_lsa;
struct prefix prefix;
struct ospf6 *ospf6 = area->ospf6;
@ -554,27 +553,27 @@ struct ospf6_lsa *ospf6_translated_nssa_refresh(struct ospf6_area *area,
/* Find the AS external LSA */
if (type5 == NULL) {
struct ospf6_as_external_lsa *ext_lsa;
struct ospf6_route *match;
/* Find the AS external LSA from Type-7 LSA */
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug(
"%s: No translated Type-5 found for Type-7 with Id %pI4",
__func__, &type7->header->id);
"%s: try to find translated Type-5 LSA for %s",
__func__, type7->name);
/* find the translated Type-5 for this Type-7 */
ext_lsa = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
type7->header);
prefix.family = AF_INET6;
prefix.prefixlen = ext_lsa->prefix.prefix_length;
ospf6_prefix_in6_addr(&prefix.u.prefix6, ext_lsa,
&ext_lsa->prefix);
/* Find the AS external LSA from Type-7 LSA */
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug("%s: try to find external LSA id %d",
__func__, type7->external_lsa_id);
type5 = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL),
type7->external_lsa_id,
ospf6->router_id, ospf6->lsdb);
match = ospf6_route_lookup(&prefix, ospf6->external_table);
if (match)
type5 = ospf6_lsdb_lookup(
OSPF6_LSTYPE_AS_EXTERNAL, match->path.origin.id,
ospf6->router_id, ospf6->lsdb);
}
if (type5) {
@ -602,6 +601,7 @@ struct ospf6_lsa *ospf6_translated_nssa_refresh(struct ospf6_area *area,
__func__, &type7->header->id);
return NULL;
}
UNSET_FLAG(new->flag, OSPF6_LSA_UNAPPROVED);
}
if (IS_OSPF6_DEBUG_NSSA)
@ -610,32 +610,11 @@ struct ospf6_lsa *ospf6_translated_nssa_refresh(struct ospf6_area *area,
return new;
}
/* Originate Translated Type-5 for supplied Type-7 NSSA LSA */
struct ospf6_lsa *ospf6_translated_nssa_originate(struct ospf6_area *oa,
struct ospf6_lsa *type7)
{
struct ospf6_lsa *new;
if (ntohs(type7->header->type) != OSPF6_LSTYPE_TYPE_7)
return NULL;
if ((new = ospf6_lsa_translated_nssa_new(oa, type7)) == NULL) {
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug(
"%s : Could not translate Type-7, Id %pI4, to Type-5",
__func__, &type7->header->id);
return NULL;
}
return new;
}
int ospf6_abr_translate_nssa(struct ospf6_area *area, struct ospf6_lsa *lsa)
static void ospf6_abr_translate_nssa(struct ospf6_area *area, struct ospf6_lsa *lsa)
{
/* Incoming Type-7 or later aggregated Type-7
*
* LSA is skipped if P-bit is off.
* LSA is aggregated if within range.
*
* The Type-7 is translated, Installed/Approved as a Type-5 into
* global LSDB, then Flooded through AS
@ -659,7 +638,7 @@ int ospf6_abr_translate_nssa(struct ospf6_area *area, struct ospf6_lsa *lsa)
zlog_debug(
"%s : LSA Id %pI4, P-bit off, NO Translation",
__func__, &lsa->header->id);
return 1;
return;
}
if (IS_OSPF6_DEBUG_NSSA)
@ -676,7 +655,7 @@ int ospf6_abr_translate_nssa(struct ospf6_area *area, struct ospf6_lsa *lsa)
zlog_debug(
"%s : LSA Id %pI4, Forward address is 0, NO Translation",
__func__, &lsa->header->id);
return 1;
return;
}
/* Find the existing AS-External LSA for this prefix */
@ -687,23 +666,13 @@ int ospf6_abr_translate_nssa(struct ospf6_area *area, struct ospf6_lsa *lsa)
ospf6->lsdb);
}
/* Check Type 5 LSA using the matching external ID */
if (old == NULL) {
old = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL),
lsa->external_lsa_id, ospf6->router_id,
ospf6->lsdb);
if (OSPF6_LSA_IS_MAXAGE(lsa)) {
if (old)
ospf6_lsa_premature_aging(old);
return;
}
if (old) {
/* Do not continue if type 5 LSA not approved */
if (CHECK_FLAG(old->flag, OSPF6_LSA_UNAPPROVED)) {
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug(
"%s : LSA Id %pI4 type 5 is not approved",
__func__, &old->header->id);
return 1;
}
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug(
"%s : found old translated LSA Id %pI4, refreshing",
@ -722,16 +691,14 @@ int ospf6_abr_translate_nssa(struct ospf6_area *area, struct ospf6_lsa *lsa)
* originate translated LSA
*/
if (ospf6_translated_nssa_originate(area, lsa) == NULL) {
if (ospf6_lsa_translated_nssa_new(area, lsa) == NULL) {
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug(
"%s : Could not translate Type-7 for %pI4 to Type-5",
__func__, &lsa->header->id);
return 1;
return;
}
}
return 0;
}
static void ospf6_abr_process_nssa_translates(struct ospf6 *ospf6)
@ -751,6 +718,8 @@ static void ospf6_abr_process_nssa_translates(struct ospf6 *ospf6)
zlog_debug("%s : Start", __func__);
for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
if (!IS_AREA_NSSA(oa))
continue;
/* skip if not translator */
if (oa->NSSATranslatorState == OSPF6_NSSA_TRANSLATE_DISABLED) {
@ -760,13 +729,6 @@ static void ospf6_abr_process_nssa_translates(struct ospf6 *ospf6)
continue;
}
/* skip if not Nssa Area */
if (!IS_AREA_NSSA(oa)) {
zlog_debug("%s area %pI4 Flag %x", __func__,
&oa->area_id, oa->flag);
continue;
}
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug("%s : looking at area %pI4", __func__,
&oa->area_id);
@ -784,71 +746,30 @@ static void ospf6_abr_process_nssa_translates(struct ospf6 *ospf6)
zlog_debug("%s : Stop", __func__);
}
/* Generate translated type-5 LSA from the configured area ranges*/
static void ospf6_abr_translate_nssa_range(struct ospf6 *ospf6)
{
struct listnode *node, *nnode;
struct ospf6_area *oa;
struct ospf6_route *range;
struct ospf6_lsa *lsa;
for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) {
for (range = ospf6_route_head(oa->range_table); range;
range = ospf6_route_next(range)) {
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug(
"Translating range %pFX of area %pI4",
&range->prefix, &oa->area_id);
if (CHECK_FLAG(range->flag,
OSPF6_ROUTE_DO_NOT_ADVERTISE))
continue;
/* Find the NSSA LSA from the route */
/* Generate and flood external LSA */
lsa = ospf6_lsdb_lookup(OSPF6_LSTYPE_TYPE_7,
range->path.origin.id,
ospf6->router_id, oa->lsdb);
if (lsa)
ospf6_abr_translate_nssa(oa, lsa);
}
}
}
static void ospf6_abr_send_nssa_aggregates(struct ospf6 *ospf6)
{
struct listnode *node;
struct ospf6_area *area;
struct ospf6_route *range;
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug("%s : Start", __func__);
zlog_debug("%s: Start", __func__);
for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, area)) {
if (area->NSSATranslatorState == OSPF6_NSSA_TRANSLATE_DISABLED)
continue;
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug("%s : looking at area %pI4", __func__,
zlog_debug("%s: looking at area %pI4", __func__,
&area->area_id);
ospf6_abr_translate_nssa_range(ospf6);
for (range = ospf6_route_head(area->nssa_range_table); range;
range = ospf6_route_next(range))
ospf6_abr_range_update(range, ospf6);
}
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug("%s : Stop", __func__);
}
/*Flood max age LSA's for the unapproved LSA's */
static int ospf6_abr_remove_unapproved_translates_apply(struct ospf6_lsa *lsa)
{
if (CHECK_FLAG(lsa->flag, OSPF6_LSA_LOCAL_XLT)
&& CHECK_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED)) {
zlog_debug("%s : removing unapproved translates, lsa : %s",
__func__, lsa->name);
/* FLUSH THROUGHOUT AS */
ospf6_lsa_premature_aging(lsa);
}
return 0;
zlog_debug("%s: Stop", __func__);
}
static void ospf6_abr_remove_unapproved_translates(struct ospf6 *ospf6)
@ -862,8 +783,16 @@ static void ospf6_abr_remove_unapproved_translates(struct ospf6 *ospf6)
zlog_debug("ospf6_abr_remove_unapproved_translates(): Start");
type = htons(OSPF6_LSTYPE_AS_EXTERNAL);
for (ALL_LSDB_TYPED(ospf6->lsdb, type, lsa))
ospf6_abr_remove_unapproved_translates_apply(lsa);
for (ALL_LSDB_TYPED(ospf6->lsdb, type, lsa)) {
if (CHECK_FLAG(lsa->flag, OSPF6_LSA_LOCAL_XLT)
&& CHECK_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED)) {
zlog_debug(
"%s : removing unapproved translates, lsa : %s",
__func__, lsa->name);
ospf6_lsa_premature_aging(lsa);
}
}
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug("ospf_abr_remove_unapproved_translates(): Stop");
@ -948,11 +877,6 @@ void ospf6_abr_nssa_type_7_defaults(struct ospf6 *ospf6)
static void ospf6_abr_nssa_task(struct ospf6 *ospf6)
{
/* called only if any_nssa */
struct ospf6_route *range;
struct ospf6_area *area;
struct listnode *node, *nnode;
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug("Check for NSSA-ABR Tasks():");
@ -978,10 +902,10 @@ static void ospf6_abr_nssa_task(struct ospf6 *ospf6)
ospf6_abr_unapprove_translates(ospf6);
/* RESET all Ranges in every Area, same as summaries */
/* Originate Type-7 aggregates */
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug("ospf6_abr_nssa_task(): NSSA initialize aggregates");
ospf6_abr_range_reset_cost(ospf6);
zlog_debug("ospf6_abr_nssa_task(): send NSSA aggregates");
ospf6_abr_send_nssa_aggregates(ospf6);
/* For all NSSAs, Type-7s, translate to 5's, INSTALL/FLOOD, or
* Aggregate as Type-7
@ -991,32 +915,12 @@ static void ospf6_abr_nssa_task(struct ospf6 *ospf6)
zlog_debug("ospf6_abr_nssa_task(): process translates");
ospf6_abr_process_nssa_translates(ospf6);
/* Translate/Send any "ranged" aggregates, and also 5-Install and
* Approve
* Scan Type-7's for aggregates, translate to Type-5's,
* Install/Flood/Approve
*/
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug("ospf6_abr_nssa_task(): send NSSA aggregates");
ospf6_abr_send_nssa_aggregates(ospf6); /*TURNED OFF FOR NOW */
/* Flush any unapproved previous translates from Global Data Base */
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug(
"ospf6_abr_nssa_task(): remove unapproved translates");
ospf6_abr_remove_unapproved_translates(ospf6);
for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, area)) {
for (range = ospf6_route_head(area->range_table); range;
range = ospf6_route_next(range)) {
if (CHECK_FLAG(range->flag,
OSPF6_ROUTE_DO_NOT_ADVERTISE))
ospf6_zebra_delete_discard(range, ospf6);
else
ospf6_zebra_add_discard(range, ospf6);
}
}
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug("ospf6_abr_nssa_task(): Stop");
}
@ -1063,106 +967,6 @@ int ospf6_redistribute_check(struct ospf6 *ospf6, struct ospf6_route *route,
return 1;
}
static void ospf6_external_lsa_refresh_type(struct ospf6 *ospf6, uint8_t type,
unsigned short instance, int force)
{
struct ospf6_route *route;
struct ospf6_external_info *info;
struct ospf6_lsa *lsa;
if (type == ZEBRA_ROUTE_MAX)
return;
for (route = ospf6_route_head(ospf6->external_table); route;
route = ospf6_route_next(route)) {
info = route->route_option;
/* Find the external LSA in the database */
if (!is_default_prefix(&route->prefix)) {
lsa = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL),
htonl(info->id),
ospf6->router_id, ospf6->lsdb);
if (lsa) {
THREAD_OFF(lsa->refresh);
/* LSA is maxage, immediate refresh */
if (OSPF6_LSA_IS_MAXAGE(lsa))
ospf6_flood(NULL, lsa);
else
thread_add_timer(master,
ospf6_lsa_refresh, lsa,
OSPF_LS_REFRESH_TIME,
&lsa->refresh);
} else {
/* LSA not found in the database
* Verify and originate external LSA
*/
if (ospf6_redistribute_check(ospf6, route,
type))
ospf6_as_external_lsa_originate(route,
ospf6);
}
}
}
}
/* Refresh default route */
static void ospf6_external_lsa_refresh_default(struct ospf6 *ospf6)
{
struct ospf6_route *route;
struct ospf6_external_info *info;
struct ospf6_lsa *lsa;
for (route = ospf6_route_head(ospf6->external_table); route;
route = ospf6_route_next(route)) {
if (is_default_prefix(&route->prefix)) {
info = route->route_option;
lsa = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL),
htonl(info->id),
ospf6->router_id, ospf6->lsdb);
if (lsa) {
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug(
"LSA[Type5:0.0.0.0]: Refresh AS-external-LSA %p",
(void *)lsa);
if (OSPF6_LSA_IS_MAXAGE(lsa))
ospf6_flood(NULL, lsa);
else
thread_add_timer(master,
ospf6_lsa_refresh, lsa,
OSPF_LS_REFRESH_TIME,
&lsa->refresh);
} else if (!lsa) {
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug(
"LSA[Type5:0.0.0.0]: Originate AS-external-LSA");
ospf6_as_external_lsa_originate(route, ospf6);
}
}
}
}
/* If there's redistribution configured, we need to refresh external
* LSAs in order to install Type-7 and flood to all NSSA Areas
*/
void ospf6_asbr_nssa_redist_task(struct ospf6 *ospf6)
{
int type;
struct ospf6_redist *red;
for (type = 0; type < ZEBRA_ROUTE_MAX; type++) {
red = ospf6_redist_lookup(ospf6, type, 0);
if (!red)
return;
ospf6_external_lsa_refresh_type(ospf6, type, red->instance,
LSA_REFRESH_IF_CHANGED);
}
ospf6_external_lsa_refresh_default(ospf6);
}
/* This function performs ABR related processing */
static int ospf6_abr_task_timer(struct thread *thread)
{
@ -1176,7 +980,6 @@ static int ospf6_abr_task_timer(struct thread *thread)
ospf6_abr_task(ospf6);
/* if nssa-abr, then scan Type-7 LSDB */
ospf6_abr_nssa_task(ospf6);
ospf6_asbr_nssa_redist_task(ospf6);
return 0;
}
@ -1337,6 +1140,13 @@ int ospf6_area_nssa_unset(struct ospf6 *ospf6, struct ospf6_area *area)
UNSET_FLAG(area->flag, OSPF6_AREA_NSSA);
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug("area %s nssa reset", area->name);
/* Clear the table of NSSA ranges. */
ospf6_route_table_delete(area->nssa_range_table);
area->nssa_range_table =
OSPF6_ROUTE_TABLE_CREATE(AREA, PREFIX_RANGES);
area->nssa_range_table->scope = area;
ospf6_area_nssa_update(area);
}
@ -1350,10 +1160,14 @@ static struct in6_addr *ospf6_get_nssa_fwd_addr(struct ospf6_area *oa)
struct ospf6_interface *oi;
for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi)) {
if (if_is_operative(oi->interface))
if (oi->area && IS_AREA_NSSA(oi->area))
return ospf6_interface_get_global_address(
oi->interface);
struct in6_addr *addr;
if (!if_is_operative(oi->interface))
continue;
addr = ospf6_interface_get_global_address(oi->interface);
if (addr)
return addr;
}
return NULL;
}
@ -1463,17 +1277,119 @@ void ospf6_abr_check_translate_nssa(struct ospf6_area *area,
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug("%s : start", __func__);
if (!ospf6_check_and_set_router_abr(ospf6))
return;
type5 = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL),
lsa->external_lsa_id, ospf6->router_id,
ospf6->lsdb);
if (ospf6_check_and_set_router_abr(ospf6) && (type5 == NULL)) {
if (!type5) {
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug("%s : Originating type5 LSA", __func__);
ospf6_lsa_translated_nssa_new(area, lsa);
}
}
DEFPY (area_nssa_range,
area_nssa_range_cmd,
"area <A.B.C.D|(0-4294967295)>$area nssa range X:X::X:X/M$prefix [<not-advertise$not_adv|cost (0-16777215)$cost>]",
"OSPF6 area parameters\n"
"OSPF6 area ID in IP address format\n"
"OSPF6 area ID as a decimal value\n"
"Configure OSPF6 area as nssa\n"
"Configured address range\n"
"Specify IPv6 prefix\n"
"Do not advertise\n"
"User specified metric for this range\n"
"Advertised metric for this range\n")
{
struct ospf6_area *oa;
struct ospf6_route *range;
VTY_DECLVAR_CONTEXT(ospf6, ospf6);
OSPF6_CMD_AREA_GET(area, oa, ospf6);
if (!IS_AREA_NSSA(oa)) {
vty_out(vty, "%% First configure %s as an NSSA area\n", area);
return CMD_WARNING;
}
range = ospf6_route_lookup((struct prefix *)prefix,
oa->nssa_range_table);
if (range == NULL) {
range = ospf6_route_create(ospf6);
range->type = OSPF6_DEST_TYPE_RANGE;
SET_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE);
prefix_copy(&range->prefix, prefix);
range->path.area_id = oa->area_id;
range->path.metric_type = 2;
range->path.cost = OSPF_AREA_RANGE_COST_UNSPEC;
range->path.origin.type = htons(OSPF6_LSTYPE_TYPE_7);
range->path.origin.id = htonl(ospf6->external_id++);
range->path.origin.adv_router = ospf6->router_id;
ospf6_route_add(range, oa->nssa_range_table);
}
/* process "not-advertise" */
if (not_adv)
SET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
else
UNSET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
/* process "cost" */
if (!cost_str)
cost = OSPF_AREA_RANGE_COST_UNSPEC;
range->path.u.cost_config = cost;
/* Redo summaries if required */
if (ospf6_check_and_set_router_abr(ospf6))
ospf6_schedule_abr_task(ospf6);
return CMD_SUCCESS;
}
DEFPY (no_area_nssa_range,
no_area_nssa_range_cmd,
"no area <A.B.C.D|(0-4294967295)>$area nssa range X:X::X:X/M$prefix [<not-advertise|cost (0-16777215)>]",
NO_STR
"OSPF6 area parameters\n"
"OSPF6 area ID in IP address format\n"
"OSPF6 area ID as a decimal value\n"
"Configure OSPF6 area as nssa\n"
"Configured address range\n"
"Specify IPv6 prefix\n"
"Do not advertise\n"
"User specified metric for this range\n"
"Advertised metric for this range\n")
{
struct ospf6_area *oa;
struct ospf6_route *range;
VTY_DECLVAR_CONTEXT(ospf6, ospf6);
OSPF6_CMD_AREA_GET(area, oa, ospf6);
range = ospf6_route_lookup((struct prefix *)prefix,
oa->nssa_range_table);
if (range == NULL) {
vty_out(vty, "%% range %s does not exists.\n", prefix_str);
return CMD_SUCCESS;
}
if (ospf6_check_and_set_router_abr(oa->ospf6)) {
/* Blow away the aggregated LSA and route */
SET_FLAG(range->flag, OSPF6_ROUTE_REMOVE);
/* Redo summaries if required */
thread_execute(master, ospf6_abr_task_timer, ospf6, 0);
}
ospf6_route_remove(range, oa->nssa_range_table);
return CMD_SUCCESS;
}
DEFUN(debug_ospf6_nssa, debug_ospf6_nssa_cmd,
"debug ospf6 nssa",
DEBUG_STR
@ -1503,6 +1419,9 @@ void config_write_ospf6_debug_nssa(struct vty *vty)
void install_element_ospf6_debug_nssa(void)
{
install_element(OSPF6_NODE, &area_nssa_range_cmd);
install_element(OSPF6_NODE, &no_area_nssa_range_cmd);
install_element(ENABLE_NODE, &debug_ospf6_nssa_cmd);
install_element(ENABLE_NODE, &no_debug_ospf6_nssa_cmd);
install_element(CONFIG_NODE, &debug_ospf6_nssa_cmd);

View File

@ -55,8 +55,6 @@ extern void ospf6_nssa_lsa_flush(struct ospf6 *ospf6, struct prefix_ipv6 *p);
extern struct ospf6_lsa *ospf6_translated_nssa_refresh(struct ospf6_area *oa,
struct ospf6_lsa *type7,
struct ospf6_lsa *type5);
extern struct ospf6_lsa *
ospf6_translated_nssa_originate(struct ospf6_area *oa, struct ospf6_lsa *type7);
extern void ospf6_asbr_nssa_redist_task(struct ospf6 *ospf6);
@ -69,8 +67,6 @@ extern void install_element_ospf6_debug_nssa(void);
extern void ospf6_abr_nssa_type_7_defaults(struct ospf6 *osof6);
int ospf6_redistribute_check(struct ospf6 *ospf6, struct ospf6_route *route,
int type);
extern int ospf6_abr_translate_nssa(struct ospf6_area *area,
struct ospf6_lsa *lsa);
extern void ospf6_abr_check_translate_nssa(struct ospf6_area *area,
struct ospf6_lsa *lsa);
extern void ospf6_abr_nssa_check_status(struct ospf6 *ospf6);

View File

@ -1098,7 +1098,6 @@ struct ospf6_route_table *ospf6_route_table_create(int s, int t)
void ospf6_route_table_delete(struct ospf6_route_table *table)
{
ospf6_route_remove_all(table);
bf_free(table->idspace);
route_table_finish(table->table);
XFREE(MTYPE_OSPF6_ROUTE_TABLE, table);
}

View File

@ -186,7 +186,7 @@ struct ospf6_route {
struct timeval changed;
/* flag */
uint8_t flag;
uint16_t flag;
/* Prefix Options */
uint8_t prefix_options;
@ -221,14 +221,15 @@ struct ospf6_route {
#define OSPF6_DEST_TYPE_RANGE 5
#define OSPF6_DEST_TYPE_MAX 6
#define OSPF6_ROUTE_CHANGE 0x01
#define OSPF6_ROUTE_ADD 0x02
#define OSPF6_ROUTE_REMOVE 0x04
#define OSPF6_ROUTE_BEST 0x08
#define OSPF6_ROUTE_ACTIVE_SUMMARY 0x10
#define OSPF6_ROUTE_DO_NOT_ADVERTISE 0x20
#define OSPF6_ROUTE_WAS_REMOVED 0x40
#define OSPF6_ROUTE_BLACKHOLE_ADDED 0x80
#define OSPF6_ROUTE_CHANGE 0x0001
#define OSPF6_ROUTE_ADD 0x0002
#define OSPF6_ROUTE_REMOVE 0x0004
#define OSPF6_ROUTE_BEST 0x0008
#define OSPF6_ROUTE_ACTIVE_SUMMARY 0x0010
#define OSPF6_ROUTE_DO_NOT_ADVERTISE 0x0020
#define OSPF6_ROUTE_WAS_REMOVED 0x0040
#define OSPF6_ROUTE_BLACKHOLE_ADDED 0x0080
#define OSPF6_ROUTE_NSSA_RANGE 0x0100
struct ospf6;
struct ospf6_route_table {
@ -241,8 +242,6 @@ struct ospf6_route_table {
uint32_t count;
bitfield_t idspace;
/* hooks */
void (*hook_add)(struct ospf6_route *);
void (*hook_change)(struct ospf6_route *);

View File

@ -99,6 +99,7 @@ clippy_scan += \
ospf6d/ospf6_lsa.c \
ospf6d/ospf6_gr_helper.c \
ospf6d/ospf6_gr.c \
ospf6d/ospf6_nssa.c \
ospf6d/ospf6_route.c \
# end

View File

@ -2,6 +2,10 @@ debug ospf6 lsa router
debug ospf6 lsa router originate
debug ospf6 lsa router examine
debug ospf6 lsa router flooding
debug ospf6 lsa nssa
debug ospf6 lsa nssa originate
debug ospf6 lsa nssa examine
debug ospf6 lsa nssa flooding
debug ospf6 lsa as-external
debug ospf6 lsa as-external originate
debug ospf6 lsa as-external examine
@ -15,7 +19,6 @@ debug ospf6 zebra
debug ospf6 interface
debug ospf6 neighbor
debug ospf6 flooding
debug ospf6 gr helper
debug ospf6 spf process
debug ospf6 route intra-area
debug ospf6 route inter-area
@ -24,11 +27,11 @@ debug ospf6 asbr
debug ospf6 nssa
!
interface r1-eth0
ipv6 ospf6 area 0.0.0.1
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 10
!
router ospf6
ospf6 router-id 10.254.254.1
area 0.0.0.1 stub
interface r1-eth0 area 0.0.0.1
!

View File

@ -2,6 +2,10 @@ debug ospf6 lsa router
debug ospf6 lsa router originate
debug ospf6 lsa router examine
debug ospf6 lsa router flooding
debug ospf6 lsa nssa
debug ospf6 lsa nssa originate
debug ospf6 lsa nssa examine
debug ospf6 lsa nssa flooding
debug ospf6 lsa as-external
debug ospf6 lsa as-external originate
debug ospf6 lsa as-external examine
@ -15,7 +19,6 @@ debug ospf6 zebra
debug ospf6 interface
debug ospf6 neighbor
debug ospf6 flooding
debug ospf6 gr helper
debug ospf6 spf process
debug ospf6 route intra-area
debug ospf6 route inter-area
@ -24,14 +27,17 @@ debug ospf6 asbr
debug ospf6 nssa
!
interface r2-eth0
ipv6 ospf6 area 0.0.0.1
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 10
!
interface r2-eth1
ipv6 ospf6 area 0.0.0.0
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 10
!
interface r2-eth2
ipv6 ospf6 area 0.0.0.2
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 10
!
@ -42,7 +48,4 @@ router ospf6
default-information originate always metric 123
area 0.0.0.1 stub
area 0.0.0.2 nssa
interface r2-eth0 area 0.0.0.1
interface r2-eth1 area 0.0.0.0
interface r2-eth2 area 0.0.0.2
!

View File

@ -2,6 +2,10 @@ debug ospf6 lsa router
debug ospf6 lsa router originate
debug ospf6 lsa router examine
debug ospf6 lsa router flooding
debug ospf6 lsa nssa
debug ospf6 lsa nssa originate
debug ospf6 lsa nssa examine
debug ospf6 lsa nssa flooding
debug ospf6 lsa as-external
debug ospf6 lsa as-external originate
debug ospf6 lsa as-external examine
@ -15,7 +19,6 @@ debug ospf6 zebra
debug ospf6 interface
debug ospf6 neighbor
debug ospf6 flooding
debug ospf6 gr helper
debug ospf6 spf process
debug ospf6 route intra-area
debug ospf6 route inter-area
@ -24,6 +27,7 @@ debug ospf6 asbr
debug ospf6 nssa
!
interface r3-eth0
ipv6 ospf6 area 0.0.0.0
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 10
!
@ -31,5 +35,4 @@ router ospf6
ospf6 router-id 10.254.254.3
redistribute connected
redistribute static
interface r3-eth0 area 0.0.0.0
!

View File

@ -2,6 +2,10 @@ debug ospf6 lsa router
debug ospf6 lsa router originate
debug ospf6 lsa router examine
debug ospf6 lsa router flooding
debug ospf6 lsa nssa
debug ospf6 lsa nssa originate
debug ospf6 lsa nssa examine
debug ospf6 lsa nssa flooding
debug ospf6 lsa as-external
debug ospf6 lsa as-external originate
debug ospf6 lsa as-external examine
@ -15,7 +19,6 @@ debug ospf6 zebra
debug ospf6 interface
debug ospf6 neighbor
debug ospf6 flooding
debug ospf6 gr helper
debug ospf6 spf process
debug ospf6 route intra-area
debug ospf6 route inter-area
@ -24,11 +27,11 @@ debug ospf6 asbr
debug ospf6 nssa
!
interface r4-eth0
ipv6 ospf6 area 0.0.0.2
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 10
!
router ospf6
ospf6 router-id 10.254.254.4
area 0.0.0.2 nssa
interface r4-eth0 area 0.0.0.2
!

View File

@ -131,6 +131,8 @@ def build_topo(tgen):
switch.add_link(tgen.gears["r2"])
switch.add_link(tgen.gears["r4"])
switch = tgen.add_switch("s4")
switch.add_link(tgen.gears["r4"], nodeif="r4-stubnet")
def setup_module(mod):
"Sets up the pytest environment"
@ -484,7 +486,7 @@ def test_area_filters():
pytest.skip(tgen.errors)
#
# Configure import/export filters on r2 (ABR for area 1).
# Configure import/export filters on r2 (ABR for area 2).
#
config = """
configure terminal
@ -544,6 +546,102 @@ def test_area_filters():
expect_ospfv3_routes("r1", routes, wait=30, type="inter-area")
def test_nssa_range():
"""
Test NSSA ABR ranges.
"""
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
# Configure new addresses on r4 and enable redistribution of connected
# routes.
config = """
configure terminal
interface r4-stubnet
ipv6 address 2001:db8:1000::1/128
ipv6 address 2001:db8:1000::2/128
router ospf6
redistribute connected
"""
tgen.gears["r4"].vtysh_cmd(config)
logger.info("Expecting NSSA-translated external routes to be added on r3")
routes = {"2001:db8:1000::1/128": {}, "2001:db8:1000::2/128": {}}
expect_ospfv3_routes("r3", routes, wait=30, type="external-2")
# Configure an NSSA range on r2 (ABR for area 2).
config = """
configure terminal
router ospf6
area 2 nssa range 2001:db8:1000::/64
"""
tgen.gears["r2"].vtysh_cmd(config)
logger.info("Expecting summarized routes to be removed from r3")
for route in ["2001:db8:1000::1/128", "2001:db8:1000::2/128"]:
test_func = partial(dont_expect_route, "r3", route, type="external-2")
_, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
assertmsg = "{}'s {} summarized route still exists".format("r3", route)
assert result is None, assertmsg
logger.info("Expecting NSSA range to be added on r3")
routes = {
"2001:db8:1000::/64": {
"metricType":2,
"metricCost":20,
"metricCostE2":10,
}}
expect_ospfv3_routes("r3", routes, wait=30, type="external-2", detail=True)
# Change the NSSA range cost.
config = """
configure terminal
router ospf6
area 2 nssa range 2001:db8:1000::/64 cost 1000
"""
tgen.gears["r2"].vtysh_cmd(config)
logger.info("Expecting NSSA range to be updated with new cost")
routes = {
"2001:db8:1000::/64": {
"metricType":2,
"metricCost":20,
"metricCostE2":1000,
}}
expect_ospfv3_routes("r3", routes, wait=30, type="external-2", detail=True)
# Configure the NSSA range to not be advertised.
config = """
configure terminal
router ospf6
area 2 nssa range 2001:db8:1000::/64 not-advertise
"""
tgen.gears["r2"].vtysh_cmd(config)
logger.info("Expecting NSSA summary route to be removed")
route = "2001:db8:1000::/64"
test_func = partial(dont_expect_route, "r3", route, type="external-2")
_, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
assertmsg = "{}'s {} NSSA summary route still exists".format("r3", route)
assert result is None, assertmsg
# Remove the NSSA range.
config = """
configure terminal
router ospf6
no area 2 nssa range 2001:db8:1000::/64
"""
tgen.gears["r2"].vtysh_cmd(config)
logger.info("Expecting previously summarized routes to be re-added")
routes = {
"2001:db8:1000::1/128": {
"metricType":2,
"metricCost":20,
},
"2001:db8:1000::2/128": {
"metricType":2,
"metricCost":20,
},
}
expect_ospfv3_routes("r3", routes, wait=30, type="external-2", detail=True)
def teardown_module(_mod):
"Teardown the pytest environment"
tgen = get_topogen()