ospfd: implement Type-7 default routes for NSSA areas

Add the "default-information-originate" option to the "area X nssa"
command. That option allows the origination of Type-7 default routes
on NSSA ABRs and ASBRs.

Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
This commit is contained in:
Renato Westphal 2023-03-07 21:13:53 -03:00
parent e85194f572
commit 017714e3ad
10 changed files with 370 additions and 18 deletions

View File

@ -431,6 +431,16 @@ Areas
configured not to advertise forwarding addresses into the backbone to direct configured not to advertise forwarding addresses into the backbone to direct
forwarded traffic to the NSSA ABR translator. forwarded traffic to the NSSA ABR translator.
.. clicmd:: area A.B.C.D nssa default-information-originate [metric-type (1-2)] [metric (0-16777214)]
.. clicmd:: area (0-4294967295) nssa default-information-originate [metric-type (1-2)] [metric (0-16777214)]
NSSA ABRs and ASBRs can be configured with the `default-information-originate`
option to originate a Type-7 default route into the NSSA area. In the case
of NSSA ASBRs, the origination of the default route is conditioned to the
existence of a default route in the RIB that wasn't learned via the OSPF
protocol.
.. clicmd:: area A.B.C.D default-cost (0-16777215) .. clicmd:: area A.B.C.D default-cost (0-16777215)

View File

@ -1807,6 +1807,82 @@ static void ospf_abr_announce_non_dna_routers(struct event *thread)
OSPF_LOG_DEBUG(IS_DEBUG_OSPF_EVENT, "%s(): Stop", __func__); OSPF_LOG_DEBUG(IS_DEBUG_OSPF_EVENT, "%s(): Stop", __func__);
} }
static void ospf_abr_nssa_type7_default_create(struct ospf *ospf,
struct ospf_area *area,
struct ospf_lsa *lsa)
{
struct external_info ei;
if (IS_DEBUG_OSPF_NSSA)
zlog_debug(
"Announcing Type-7 default route into NSSA area %pI4",
&area->area_id);
/* Prepare the extrenal_info for aggregator */
memset(&ei, 0, sizeof(struct external_info));
ei.p.family = AF_INET;
ei.p.prefixlen = 0;
ei.tag = 0;
ei.type = 0;
ei.instance = ospf->instance;
/* Compute default route type and metric. */
if (area->nssa_default_originate.metric_value != -1)
ei.route_map_set.metric =
area->nssa_default_originate.metric_value;
else
ei.route_map_set.metric = DEFAULT_DEFAULT_ALWAYS_METRIC;
if (area->nssa_default_originate.metric_type != -1)
ei.route_map_set.metric_type =
area->nssa_default_originate.metric_type;
else
ei.route_map_set.metric_type = DEFAULT_METRIC_TYPE;
if (!lsa)
ospf_nssa_lsa_originate(area, &ei);
else
ospf_nssa_lsa_refresh(area, lsa, &ei);
}
static void ospf_abr_nssa_type7_default_delete(struct ospf *ospf,
struct ospf_area *area,
struct ospf_lsa *lsa)
{
if (lsa && !CHECK_FLAG(lsa->flags, OSPF_LSA_IN_MAXAGE)) {
if (IS_DEBUG_OSPF_NSSA)
zlog_debug(
"Withdrawing Type-7 default route from area %pI4",
&area->area_id);
ospf_ls_retransmit_delete_nbr_area(area, lsa);
ospf_refresher_unregister_lsa(ospf, lsa);
ospf_lsa_flush_area(lsa, area);
}
}
/* NSSA Type-7 default route. */
void ospf_abr_nssa_type7_defaults(struct ospf *ospf)
{
struct ospf_area *area;
struct listnode *node;
for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) {
struct in_addr id = {};
struct ospf_lsa *lsa;
lsa = ospf_lsdb_lookup_by_id(area->lsdb, OSPF_AS_NSSA_LSA, id,
area->ospf->router_id);
if (area->external_routing == OSPF_AREA_NSSA
&& area->nssa_default_originate.enabled
&& (IS_OSPF_ABR(ospf)
|| (IS_OSPF_ASBR(ospf)
&& ospf->nssa_default_import_check.status)))
ospf_abr_nssa_type7_default_create(ospf, area, lsa);
else
ospf_abr_nssa_type7_default_delete(ospf, area, lsa);
}
}
static int ospf_abr_remove_unapproved_translates_apply(struct ospf *ospf, static int ospf_abr_remove_unapproved_translates_apply(struct ospf *ospf,
struct ospf_lsa *lsa) struct ospf_lsa *lsa)
{ {
@ -2031,6 +2107,11 @@ void ospf_abr_task(struct ospf *ospf)
zlog_debug("%s: announce stub defaults", __func__); zlog_debug("%s: announce stub defaults", __func__);
ospf_abr_announce_stub_defaults(ospf); ospf_abr_announce_stub_defaults(ospf);
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("%s: announce NSSA Type-7 defaults",
__func__);
ospf_abr_nssa_type7_defaults(ospf);
if (ospf->fr_configured) { if (ospf->fr_configured) {
OSPF_LOG_DEBUG(IS_DEBUG_OSPF_EVENT, OSPF_LOG_DEBUG(IS_DEBUG_OSPF_EVENT,
"%s(): announce non-DNArouters", "%s(): announce non-DNArouters",

View File

@ -73,6 +73,7 @@ extern void ospf_schedule_abr_task(struct ospf *);
extern void ospf_abr_announce_network_to_area(struct prefix_ipv4 *, uint32_t, extern void ospf_abr_announce_network_to_area(struct prefix_ipv4 *, uint32_t,
struct ospf_area *); struct ospf_area *);
extern void ospf_abr_nssa_type7_defaults(struct ospf *ospf);
extern void ospf_abr_nssa_check_status(struct ospf *ospf); extern void ospf_abr_nssa_check_status(struct ospf *ospf);
extern void ospf_abr_generate_indication_lsa(struct ospf *ospf, extern void ospf_abr_generate_indication_lsa(struct ospf *ospf,
const struct ospf_area *area); const struct ospf_area *area);

View File

@ -1868,8 +1868,7 @@ static struct ospf_lsa *ospf_external_lsa_new(struct ospf *ospf,
} }
/* As Type-7 */ /* As Type-7 */
static void ospf_install_flood_nssa(struct ospf *ospf, struct ospf_lsa *lsa, static void ospf_install_flood_nssa(struct ospf *ospf, struct ospf_lsa *lsa)
struct external_info *ei)
{ {
struct ospf_lsa *new; struct ospf_lsa *new;
struct as_external_lsa *extlsa; struct as_external_lsa *extlsa;
@ -2253,7 +2252,7 @@ struct ospf_lsa *ospf_external_lsa_originate(struct ospf *ospf,
/* stay away from translated LSAs! */ /* stay away from translated LSAs! */
!(CHECK_FLAG(new->flags, OSPF_LSA_LOCAL_XLT))) !(CHECK_FLAG(new->flags, OSPF_LSA_LOCAL_XLT)))
ospf_install_flood_nssa( ospf_install_flood_nssa(
ospf, new, ei); /* Install/Flood Type-7 to all NSSAs */ ospf, new); /* Install/Flood Type-7 to all NSSAs */
/* Debug logging. */ /* Debug logging. */
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
@ -2266,6 +2265,100 @@ struct ospf_lsa *ospf_external_lsa_originate(struct ospf *ospf,
return new; return new;
} }
/* Originate an NSSA-LSA, install and flood. */
struct ospf_lsa *ospf_nssa_lsa_originate(struct ospf_area *area,
struct external_info *ei)
{
struct ospf *ospf = area->ospf;
struct ospf_lsa *new;
if (ospf->gr_info.restart_in_progress) {
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
zlog_debug(
"LSA[Type7]: Graceful Restart in progress, don't originate");
return NULL;
}
if (ospf->router_id.s_addr == INADDR_ANY) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
"LSA[Type7:%pI4]: deferring NSSA-LSA origination, router ID is zero",
&ei->p.prefix);
return NULL;
}
/* Create new NSSA-LSA instance. */
if ((new = ospf_external_lsa_new(ospf, ei, NULL)) == NULL) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
"LSA[Type7:%pI4]: Could not originate NSSA-LSA",
&ei->p.prefix);
return NULL;
}
new->data->type = OSPF_AS_NSSA_LSA;
new->area = area;
/* Install newly created LSA into Type-7 LSDB. */
ospf_lsa_install(ospf, NULL, new);
/* Update LSA origination count. */
ospf->lsa_originate_count++;
/* Flooding new LSA */
ospf_flood_through_area(area, NULL, new);
/* Debug logging. */
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
zlog_debug("LSA[Type%d:%pI4]: Originate NSSA-LSA %p",
new->data->type, &new->data->id, (void *)new);
ospf_lsa_header_dump(new->data);
}
return new;
}
/* Refresh NSSA-LSA. */
struct ospf_lsa *ospf_nssa_lsa_refresh(struct ospf_area *area,
struct ospf_lsa *lsa,
struct external_info *ei)
{
struct ospf *ospf = area->ospf;
struct ospf_lsa *new;
/* Delete LSA from neighbor retransmit-list. */
ospf_ls_retransmit_delete_nbr_as(ospf, lsa);
/* Unregister AS-external-LSA from refresh-list. */
ospf_refresher_unregister_lsa(ospf, lsa);
/* Create new NSSA-LSA instance. */
if ((new = ospf_external_lsa_new(ospf, ei, NULL)) == NULL) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
"LSA[Type7:%pI4]: Could not originate NSSA-LSA",
&ei->p.prefix);
return NULL;
}
new->data->type = OSPF_AS_NSSA_LSA;
new->data->ls_seqnum = lsa_seqnum_increment(lsa);
new->area = area;
/* Install newly created LSA into Type-7 LSDB. */
ospf_lsa_install(ospf, NULL, new);
/* Flooding new LSA */
ospf_flood_through_area(area, NULL, new);
/* Debug logging. */
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
zlog_debug("LSA[Type%d:%pI4]: NSSA-LSA refresh",
new->data->type, &new->data->id);
ospf_lsa_header_dump(new->data);
}
return new;
}
static struct external_info *ospf_default_external_info(struct ospf *ospf) static struct external_info *ospf_default_external_info(struct ospf *ospf)
{ {
int type; int type;
@ -2611,8 +2704,8 @@ struct ospf_lsa *ospf_external_lsa_refresh(struct ospf *ospf,
/* If any attached NSSA, install as Type-7, flood to all NSSA Areas */ /* If any attached NSSA, install as Type-7, flood to all NSSA Areas */
if (ospf->anyNSSA && !(CHECK_FLAG(new->flags, OSPF_LSA_LOCAL_XLT))) if (ospf->anyNSSA && !(CHECK_FLAG(new->flags, OSPF_LSA_LOCAL_XLT)))
ospf_install_flood_nssa(ospf, new, ospf_install_flood_nssa(ospf,
ei); /* Install/Flood per new rules */ new); /* Install/Flood per new rules */
/* Register self-originated LSA to refresh queue. /* Register self-originated LSA to refresh queue.
* Translated LSAs should not be registered, but refreshed upon * Translated LSAs should not be registered, but refreshed upon

View File

@ -278,6 +278,11 @@ extern struct in_addr ospf_get_ip_from_ifp(struct ospf_interface *);
extern struct ospf_lsa *ospf_external_lsa_originate(struct ospf *, extern struct ospf_lsa *ospf_external_lsa_originate(struct ospf *,
struct external_info *); struct external_info *);
extern struct ospf_lsa *ospf_nssa_lsa_originate(struct ospf_area *area,
struct external_info *ei);
extern struct ospf_lsa *ospf_nssa_lsa_refresh(struct ospf_area *area,
struct ospf_lsa *lsa,
struct external_info *ei);
extern void ospf_external_lsa_rid_change(struct ospf *ospf); extern void ospf_external_lsa_rid_change(struct ospf *ospf);
extern struct ospf_lsa *ospf_lsa_lookup(struct ospf *ospf, struct ospf_area *, extern struct ospf_lsa *ospf_lsa_lookup(struct ospf *ospf, struct ospf_area *,
uint32_t, struct in_addr, uint32_t, struct in_addr,

View File

@ -1438,6 +1438,7 @@ DEFPY (ospf_area_nssa,
"area <A.B.C.D|(0-4294967295)>$area_str nssa\ "area <A.B.C.D|(0-4294967295)>$area_str nssa\
[{\ [{\
<translate-candidate|translate-never|translate-always>$translator_role\ <translate-candidate|translate-never|translate-always>$translator_role\
|default-information-originate$dflt_originate [{metric (0-16777214)$mval|metric-type (1-2)$mtype}]\
|no-summary$no_summary\ |no-summary$no_summary\
|suppress-fa$suppress_fa\ |suppress-fa$suppress_fa\
}]", }]",
@ -1448,6 +1449,11 @@ DEFPY (ospf_area_nssa,
"Configure NSSA-ABR for translate election (default)\n" "Configure NSSA-ABR for translate election (default)\n"
"Configure NSSA-ABR to never translate\n" "Configure NSSA-ABR to never translate\n"
"Configure NSSA-ABR to always translate\n" "Configure NSSA-ABR to always translate\n"
"Originate Type 7 default into NSSA area\n"
"OSPF default metric\n"
"OSPF metric\n"
"OSPF metric type for default routes\n"
"Set OSPF External Type 1/2 metrics\n"
"Do not inject inter-area routes into nssa\n" "Do not inject inter-area routes into nssa\n"
"Suppress forwarding address\n") "Suppress forwarding address\n")
{ {
@ -1481,6 +1487,18 @@ DEFPY (ospf_area_nssa,
OSPF_NSSA_ROLE_CANDIDATE); OSPF_NSSA_ROLE_CANDIDATE);
} }
if (dflt_originate) {
int metric_type = DEFAULT_METRIC_TYPE;
if (mval_str == NULL)
mval = -1;
if (mtype_str)
(void)str2metric_type(mtype_str, &metric_type);
ospf_area_nssa_default_originate_set(ospf, area_id, mval,
metric_type);
} else
ospf_area_nssa_default_originate_unset(ospf, area_id);
if (no_summary) if (no_summary)
ospf_area_nssa_no_summary_set(ospf, area_id); ospf_area_nssa_no_summary_set(ospf, area_id);
else else
@ -1504,6 +1522,7 @@ DEFPY (no_ospf_area_nssa,
"no area <A.B.C.D|(0-4294967295)>$area_str nssa\ "no area <A.B.C.D|(0-4294967295)>$area_str nssa\
[{\ [{\
<translate-candidate|translate-never|translate-always>\ <translate-candidate|translate-never|translate-always>\
|default-information-originate [{metric (0-16777214)|metric-type (1-2)}]\
|no-summary\ |no-summary\
|suppress-fa\ |suppress-fa\
}]", }]",
@ -1515,6 +1534,11 @@ DEFPY (no_ospf_area_nssa,
"Configure NSSA-ABR for translate election (default)\n" "Configure NSSA-ABR for translate election (default)\n"
"Configure NSSA-ABR to never translate\n" "Configure NSSA-ABR to never translate\n"
"Configure NSSA-ABR to always translate\n" "Configure NSSA-ABR to always translate\n"
"Originate Type 7 default into NSSA area\n"
"OSPF default metric\n"
"OSPF metric\n"
"OSPF metric type for default routes\n"
"Set OSPF External Type 1/2 metrics\n"
"Do not inject inter-area routes into nssa\n" "Do not inject inter-area routes into nssa\n"
"Suppress forwarding address\n") "Suppress forwarding address\n")
{ {
@ -1527,6 +1551,7 @@ DEFPY (no_ospf_area_nssa,
/* Flush the NSSA LSA for the specified area */ /* Flush the NSSA LSA for the specified area */
ospf_flush_lsa_from_area(ospf, area_id, OSPF_AS_NSSA_LSA); ospf_flush_lsa_from_area(ospf, area_id, OSPF_AS_NSSA_LSA);
ospf_area_no_summary_unset(ospf, area_id); ospf_area_no_summary_unset(ospf, area_id);
ospf_area_nssa_default_originate_unset(ospf, area_id);
ospf_area_nssa_suppress_fa_unset(ospf, area_id); ospf_area_nssa_suppress_fa_unset(ospf, area_id);
ospf_area_nssa_unset(ospf, area_id); ospf_area_nssa_unset(ospf, area_id);
@ -11872,29 +11897,39 @@ static int config_write_ospf_area(struct vty *vty, struct ospf *ospf)
vty_out(vty, " no-summary\n"); vty_out(vty, " no-summary\n");
vty_out(vty, "\n"); vty_out(vty, "\n");
} else if (area->external_routing == OSPF_AREA_NSSA) { } else if (area->external_routing == OSPF_AREA_NSSA) {
vty_out(vty, " area %s nssa", buf);
switch (area->NSSATranslatorRole) { switch (area->NSSATranslatorRole) {
case OSPF_NSSA_ROLE_NEVER: case OSPF_NSSA_ROLE_NEVER:
vty_out(vty, vty_out(vty, " translate-never");
" area %s nssa translate-never\n",
buf);
break; break;
case OSPF_NSSA_ROLE_ALWAYS: case OSPF_NSSA_ROLE_ALWAYS:
vty_out(vty, vty_out(vty, " translate-always");
" area %s nssa translate-always\n",
buf);
break; break;
case OSPF_NSSA_ROLE_CANDIDATE: case OSPF_NSSA_ROLE_CANDIDATE:
vty_out(vty, " area %s nssa \n", buf);
break; break;
} }
if (area->nssa_default_originate.enabled) {
vty_out(vty,
" default-information-originate");
if (area->nssa_default_originate
.metric_value
!= -1)
vty_out(vty, " metric %d",
area->nssa_default_originate
.metric_value);
if (area->nssa_default_originate
.metric_type
!= DEFAULT_METRIC_TYPE)
vty_out(vty, " metric-type 1");
}
if (area->no_summary) if (area->no_summary)
vty_out(vty, vty_out(vty, " no-summary");
" area %s nssa no-summary\n",
buf);
if (area->suppress_fa) if (area->suppress_fa)
vty_out(vty, vty_out(vty, " suppress-fa");
" area %s nssa suppress-fa\n", vty_out(vty, "\n");
buf);
} }
if (area->default_cost != 1) if (area->default_cost != 1)

View File

@ -20,6 +20,7 @@
#include "log.h" #include "log.h"
#include "route_opaque.h" #include "route_opaque.h"
#include "lib/bfd.h" #include "lib/bfd.h"
#include "lib/lib_errors.h"
#include "nexthop.h" #include "nexthop.h"
#include "ospfd/ospfd.h" #include "ospfd/ospfd.h"
@ -1470,6 +1471,61 @@ static int ospf_zebra_read_route(ZAPI_CALLBACK_ARGS)
return 0; return 0;
} }
void ospf_zebra_import_default_route(struct ospf *ospf, bool unreg)
{
struct prefix prefix = {};
int command;
if (zclient->sock < 0) {
if (IS_DEBUG_OSPF(zebra, ZEBRA))
zlog_debug(" Not connected to Zebra");
return;
}
prefix.family = AF_INET;
prefix.prefixlen = 0;
if (unreg)
command = ZEBRA_NEXTHOP_UNREGISTER;
else
command = ZEBRA_NEXTHOP_REGISTER;
if (IS_DEBUG_OSPF(zebra, ZEBRA))
zlog_debug("%s: sending cmd %s for %pFX (vrf %u)", __func__,
zserv_command_string(command), &prefix,
ospf->vrf_id);
if (zclient_send_rnh(zclient, command, &prefix, SAFI_UNICAST, false,
true, ospf->vrf_id) == ZCLIENT_SEND_FAILURE)
flog_err(EC_LIB_ZAPI_SOCKET, "%s: zclient_send_rnh() failed",
__func__);
}
static int ospf_zebra_import_check_update(ZAPI_CALLBACK_ARGS)
{
struct ospf *ospf;
struct zapi_route nhr;
struct prefix matched;
ospf = ospf_lookup_by_vrf_id(vrf_id);
if (ospf == NULL || !IS_OSPF_ASBR(ospf))
return 0;
if (!zapi_nexthop_update_decode(zclient->ibuf, &matched, &nhr)) {
zlog_err("%s[%u]: Failure to decode route", __func__,
ospf->vrf_id);
return -1;
}
if (matched.family != AF_INET || matched.prefixlen != 0 ||
nhr.type == ZEBRA_ROUTE_OSPF)
return 0;
ospf->nssa_default_import_check.status = !!nhr.nexthop_num;
ospf_abr_nssa_type7_defaults(ospf);
return 0;
}
int ospf_distribute_list_out_set(struct ospf *ospf, int type, const char *name) int ospf_distribute_list_out_set(struct ospf *ospf, int type, const char *name)
{ {
@ -2132,6 +2188,7 @@ static zclient_handler *const ospf_handlers[] = {
[ZEBRA_REDISTRIBUTE_ROUTE_ADD] = ospf_zebra_read_route, [ZEBRA_REDISTRIBUTE_ROUTE_ADD] = ospf_zebra_read_route,
[ZEBRA_REDISTRIBUTE_ROUTE_DEL] = ospf_zebra_read_route, [ZEBRA_REDISTRIBUTE_ROUTE_DEL] = ospf_zebra_read_route,
[ZEBRA_NEXTHOP_UPDATE] = ospf_zebra_import_check_update,
[ZEBRA_OPAQUE_MESSAGE] = ospf_opaque_msg_handler, [ZEBRA_OPAQUE_MESSAGE] = ospf_opaque_msg_handler,

View File

@ -69,6 +69,7 @@ extern int ospf_redistribute_set(struct ospf *, struct ospf_redist *, int,
unsigned short, int, int); unsigned short, int, int);
extern int ospf_redistribute_unset(struct ospf *, int, unsigned short); extern int ospf_redistribute_unset(struct ospf *, int, unsigned short);
extern int ospf_redistribute_default_set(struct ospf *, int, int, int); extern int ospf_redistribute_default_set(struct ospf *, int, int, int);
extern void ospf_zebra_import_default_route(struct ospf *ospf, bool unreg);
extern int ospf_distribute_list_out_set(struct ospf *, int, const char *); extern int ospf_distribute_list_out_set(struct ospf *, int, const char *);
extern int ospf_distribute_list_out_unset(struct ospf *, int, const char *); extern int ospf_distribute_list_out_unset(struct ospf *, int, const char *);
extern void ospf_routemap_set(struct ospf_redist *, const char *); extern void ospf_routemap_set(struct ospf_redist *, const char *);

View File

@ -1774,6 +1774,51 @@ int ospf_area_nssa_translator_role_set(struct ospf *ospf,
return 1; return 1;
} }
void ospf_area_nssa_default_originate_set(struct ospf *ospf,
struct in_addr area_id, int metric,
int metric_type)
{
struct ospf_area *area;
area = ospf_area_lookup_by_area_id(ospf, area_id);
if (area == NULL)
return;
if (!area->nssa_default_originate.enabled) {
area->nssa_default_originate.enabled = true;
if (++ospf->nssa_default_import_check.refcnt == 1) {
ospf->nssa_default_import_check.status = false;
ospf_zebra_import_default_route(ospf, false);
}
}
area->nssa_default_originate.metric_value = metric;
area->nssa_default_originate.metric_type = metric_type;
}
void ospf_area_nssa_default_originate_unset(struct ospf *ospf,
struct in_addr area_id)
{
struct ospf_area *area;
area = ospf_area_lookup_by_area_id(ospf, area_id);
if (area == NULL)
return;
if (area->nssa_default_originate.enabled) {
area->nssa_default_originate.enabled = false;
if (--ospf->nssa_default_import_check.refcnt == 0) {
ospf->nssa_default_import_check.status = false;
ospf_zebra_import_default_route(ospf, true);
}
area->nssa_default_originate.metric_value = -1;
area->nssa_default_originate.metric_type = -1;
if (!IS_OSPF_ABR(ospf))
ospf_abr_nssa_type7_defaults(ospf);
}
}
int ospf_area_export_list_set(struct ospf *ospf, struct ospf_area *area, int ospf_area_export_list_set(struct ospf *ospf, struct ospf_area *area,
const char *list_name) const char *list_name)
{ {

View File

@ -302,6 +302,18 @@ struct ospf {
int default_metric; /* Default metric for redistribute. */ int default_metric; /* Default metric for redistribute. */
/* NSSA default-information-originate */
struct {
/* # of NSSA areas requesting default information */
uint16_t refcnt;
/*
* Whether a default route known through non-OSPF protocol is
* present in the RIB.
*/
bool status;
} nssa_default_import_check;
#define OSPF_LSA_REFRESHER_GRANULARITY 10 #define OSPF_LSA_REFRESHER_GRANULARITY 10
#define OSPF_LSA_REFRESHER_SLOTS \ #define OSPF_LSA_REFRESHER_SLOTS \
((OSPF_LS_REFRESH_TIME + OSPF_LS_REFRESH_SHIFT) \ ((OSPF_LS_REFRESH_TIME + OSPF_LS_REFRESH_SHIFT) \
@ -561,6 +573,13 @@ struct ospf_area {
#define PREFIX_LIST_OUT(A) (A)->plist_out.list #define PREFIX_LIST_OUT(A) (A)->plist_out.list
#define PREFIX_NAME_OUT(A) (A)->plist_out.name #define PREFIX_NAME_OUT(A) (A)->plist_out.name
/* NSSA default-information-originate */
struct {
bool enabled;
int metric_type;
int metric_value;
} nssa_default_originate;
/* Shortest Path Tree. */ /* Shortest Path Tree. */
struct vertex *spf; struct vertex *spf;
struct list *spf_vertex_list; struct list *spf_vertex_list;
@ -704,6 +723,11 @@ extern int ospf_area_nssa_suppress_fa_unset(struct ospf *ospf,
struct in_addr area_id); struct in_addr area_id);
extern int ospf_area_nssa_translator_role_set(struct ospf *ospf, extern int ospf_area_nssa_translator_role_set(struct ospf *ospf,
struct in_addr area_id, int role); struct in_addr area_id, int role);
extern void ospf_area_nssa_default_originate_set(struct ospf *ospf,
struct in_addr area_id,
int metric, int metric_type);
extern void ospf_area_nssa_default_originate_unset(struct ospf *ospf,
struct in_addr area_id);
extern int ospf_area_export_list_set(struct ospf *ospf, extern int ospf_area_export_list_set(struct ospf *ospf,
struct ospf_area *area_id, struct ospf_area *area_id,
const char *list_name); const char *list_name);