Skip to content

Commit

Permalink
Merge pull request FRRouting#9585 from opensourcerouting/ospf6d-nssa-…
Browse files Browse the repository at this point in the history
…dflt-originate

ospf6d: add a knob to generate Type-7 default routes
  • Loading branch information
riw777 authored Sep 24, 2021
2 parents d2e4107 + 6735622 commit b8beb67
Show file tree
Hide file tree
Showing 11 changed files with 313 additions and 21 deletions.
8 changes: 7 additions & 1 deletion doc/user/ospf6d.rst
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ OSPF6 area

.. clicmd:: area A.B.C.D nssa [no-summary]

.. clicmd:: area (0-4294967295) nssa [no-summary]
.. clicmd:: area (0-4294967295) nssa [no-summary] [default-information-originate [metric-type (1-2)] [metric (0-16777214)]]

Configure the area to be a NSSA (Not-So-Stubby Area).

Expand All @@ -198,6 +198,12 @@ OSPF6 area
advertisement of summaries into the area. In that case, a single Type-3 LSA
containing a default route is originated into the NSSA.

NSSA ABRs and ASBRs can be configured with `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 export-list NAME

.. clicmd:: area (0-4294967295) export-list NAME
Expand Down
79 changes: 76 additions & 3 deletions ospf6d/ospf6_area.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include "ospf6_intra.h"
#include "ospf6_abr.h"
#include "ospf6_asbr.h"
#include "ospf6_zebra.h"
#include "ospf6d.h"
#include "lib/json.h"
#include "ospf6_nssa.h"
Expand Down Expand Up @@ -234,6 +235,36 @@ static void ospf6_area_no_summary_unset(struct ospf6 *ospf6,
}
}

static void ospf6_nssa_default_originate_set(struct ospf6 *ospf6,
struct ospf6_area *area,
int metric, int metric_type)
{
if (!area->nssa_default_originate.enabled) {
area->nssa_default_originate.enabled = true;
if (++ospf6->nssa_default_import_check.refcnt == 1) {
ospf6->nssa_default_import_check.status = false;
ospf6_zebra_import_default_route(ospf6, false);
}
}

area->nssa_default_originate.metric_value = metric;
area->nssa_default_originate.metric_type = metric_type;
}

static void ospf6_nssa_default_originate_unset(struct ospf6 *ospf6,
struct ospf6_area *area)
{
if (area->nssa_default_originate.enabled) {
area->nssa_default_originate.enabled = false;
if (--ospf6->nssa_default_import_check.refcnt == 0) {
ospf6->nssa_default_import_check.status = false;
ospf6_zebra_import_default_route(ospf6, true);
}
area->nssa_default_originate.metric_value = -1;
area->nssa_default_originate.metric_type = -1;
}
}

/**
* Make new area structure.
*
Expand Down Expand Up @@ -648,6 +679,17 @@ void ospf6_area_config_write(struct vty *vty, struct ospf6 *ospf6)
}
if (IS_AREA_NSSA(oa)) {
vty_out(vty, " area %s nssa", oa->name);
if (oa->nssa_default_originate.enabled) {
vty_out(vty, " default-information-originate");
if (oa->nssa_default_originate.metric_value
!= -1)
vty_out(vty, " metric %d",
oa->nssa_default_originate
.metric_value);
if (oa->nssa_default_originate.metric_type
!= DEFAULT_METRIC_TYPE)
vty_out(vty, " metric-type 1");
}
if (oa->no_summary)
vty_out(vty, " no-summary");
vty_out(vty, "\n");
Expand Down Expand Up @@ -1278,11 +1320,20 @@ DEFUN (no_ospf6_area_stub_no_summary,
}

DEFPY(ospf6_area_nssa, ospf6_area_nssa_cmd,
"area <A.B.C.D|(0-4294967295)>$area_str nssa [no-summary$no_summary]",
"area <A.B.C.D|(0-4294967295)>$area_str nssa\
[{\
default-information-originate$dflt_originate [{metric (0-16777214)$mval|metric-type (1-2)$mtype}]\
|no-summary$no_summary\
}]",
"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"
"Originate Type 7 default into NSSA area\n"
"OSPFv3 default metric\n"
"OSPFv3 metric\n"
"OSPFv3 metric type for default routes\n"
"Set OSPFv3 External Type 1/2 metrics\n"
"Do not inject inter-area routes into area\n")
{
struct ospf6_area *area;
Expand All @@ -1296,23 +1347,44 @@ DEFPY(ospf6_area_nssa, ospf6_area_nssa_cmd,
return CMD_WARNING_CONFIG_FAILED;
}

if (dflt_originate) {
if (mval_str == NULL)
mval = -1;
if (mtype_str == NULL)
mtype = DEFAULT_METRIC_TYPE;
ospf6_nssa_default_originate_set(ospf6, area, mval, mtype);
} else
ospf6_nssa_default_originate_unset(ospf6, area);

if (no_summary)
ospf6_area_no_summary_set(ospf6, area);
else
ospf6_area_no_summary_unset(ospf6, area);
if (ospf6_check_and_set_router_abr(ospf6))

if (ospf6_check_and_set_router_abr(ospf6)) {
ospf6_abr_defaults_to_stub(ospf6);
ospf6_abr_nssa_type_7_defaults(ospf6);
}

return CMD_SUCCESS;
}

DEFPY(no_ospf6_area_nssa, no_ospf6_area_nssa_cmd,
"no area <A.B.C.D|(0-4294967295)>$area_str nssa [no-summary$no_summary]",
"no area <A.B.C.D|(0-4294967295)>$area_str nssa\
[{\
default-information-originate [{metric (0-16777214)|metric-type (1-2)}]\
|no-summary\
}]",
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"
"Originate Type 7 default into NSSA area\n"
"OSPFv3 default metric\n"
"OSPFv3 metric\n"
"OSPFv3 metric type for default routes\n"
"Set OSPFv3 External Type 1/2 metrics\n"
"Do not inject inter-area routes into area\n")
{
struct ospf6_area *area;
Expand All @@ -1322,6 +1394,7 @@ DEFPY(no_ospf6_area_nssa, no_ospf6_area_nssa_cmd,

ospf6_area_nssa_unset(ospf6, area);
ospf6_area_no_summary_unset(ospf6, area);
ospf6_nssa_default_originate_unset(ospf6, area);

return CMD_SUCCESS;
}
Expand Down
7 changes: 7 additions & 0 deletions ospf6d/ospf6_area.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,13 @@ struct ospf6_area {
/* Area type */
int no_summary;

/* NSSA default-information-originate */
struct {
bool enabled;
int metric_type;
int metric_value;
} nssa_default_originate;

/* Brouter traversal protection */
bool intra_brouter_calc;

Expand Down
10 changes: 7 additions & 3 deletions ospf6d/ospf6_asbr.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
#include "ospf6_abr.h"
#include "ospf6_intra.h"
#include "ospf6_flood.h"
#include "ospf6_nssa.h"
#include "ospf6d.h"
#include "ospf6_spf.h"
#include "ospf6_nssa.h"
Expand Down Expand Up @@ -85,7 +86,7 @@ static struct ospf6_lsa *ospf6_originate_type5_type7_lsas(

for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, lnode, oa)) {
if (IS_AREA_NSSA(oa))
ospf6_nssa_lsa_originate(route, oa);
ospf6_nssa_lsa_originate(route, oa, true);
}

return lsa;
Expand Down Expand Up @@ -1433,7 +1434,10 @@ void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex,
memset(&tinfo, 0, sizeof(tinfo));

if (IS_OSPF6_DEBUG_ASBR)
zlog_debug("Redistribute %pFX (%s)", prefix, ZROUTE_NAME(type));
zlog_debug("Redistribute %pFX (%s)", prefix,
type == DEFAULT_ROUTE
? "default-information-originate"
: ZROUTE_NAME(type));

/* if route-map was specified but not found, do not advertise */
if (ROUTEMAP_NAME(red)) {
Expand Down Expand Up @@ -1787,7 +1791,7 @@ int ospf6_redistribute_config_write(struct vty *vty, struct ospf6 *ospf6)
vty_out(vty, " redistribute %s", ZROUTE_NAME(type));
if (red->dmetric.value >= 0)
vty_out(vty, " metric %d", red->dmetric.value);
if (red->dmetric.type != DEFAULT_METRIC_TYPE)
if (red->dmetric.type == 1)
vty_out(vty, " metric-type 1");
if (ROUTEMAP_NAME(red))
vty_out(vty, " route-map %s", ROUTEMAP_NAME(red));
Expand Down
103 changes: 94 additions & 9 deletions ospf6d/ospf6_nssa.c
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,11 @@ static void ospf6_abr_task(struct ospf6 *ospf6)
if (IS_OSPF6_DEBUG_ABR)
zlog_debug("%s : announce stub defaults", __func__);
ospf6_abr_defaults_to_stub(ospf6);

if (IS_OSPF6_DEBUG_ABR)
zlog_debug("%s : announce NSSA Type-7 defaults",
__func__);
ospf6_abr_nssa_type_7_defaults(ospf6);
}

if (IS_OSPF6_DEBUG_ABR)
Expand Down Expand Up @@ -872,6 +877,83 @@ static void ospf6_abr_remove_unapproved_translates(struct ospf6 *ospf6)
zlog_debug("ospf_abr_remove_unapproved_translates(): Stop");
}

static void ospf6_abr_nssa_type_7_default_create(struct ospf6 *ospf6,
struct ospf6_area *oa)
{
struct ospf6_route *def;
int metric;
int metric_type;

if (IS_OSPF6_DEBUG_NSSA)
zlog_debug("Announcing Type-7 default route into NSSA area %s",
oa->name);

def = ospf6_route_create(ospf6);
def->type = OSPF6_DEST_TYPE_NETWORK;
def->prefix.family = AF_INET6;
def->prefix.prefixlen = 0;
memset(&def->prefix.u.prefix6, 0, sizeof(struct in6_addr));
def->type = OSPF6_DEST_TYPE_NETWORK;
def->path.subtype = OSPF6_PATH_SUBTYPE_DEFAULT_RT;
if (CHECK_FLAG(ospf6->flag, OSPF6_FLAG_ABR))
def->path.area_id = ospf6->backbone->area_id;
else
def->path.area_id = oa->area_id;

/* Compute default route type and metric. */
if (oa->nssa_default_originate.metric_value != -1)
metric = oa->nssa_default_originate.metric_value;
else
metric = DEFAULT_DEFAULT_ALWAYS_METRIC;
if (oa->nssa_default_originate.metric_type != -1)
metric_type = oa->nssa_default_originate.metric_type;
else
metric_type = DEFAULT_METRIC_TYPE;
def->path.metric_type = metric_type;
def->path.cost = metric;
if (metric_type == 1)
def->path.type = OSPF6_PATH_TYPE_EXTERNAL1;
else
def->path.type = OSPF6_PATH_TYPE_EXTERNAL2;

ospf6_nssa_lsa_originate(def, oa, false);
ospf6_route_delete(def);
}

static void ospf6_abr_nssa_type_7_default_delete(struct ospf6 *ospf6,
struct ospf6_area *oa)
{
struct ospf6_lsa *lsa;

lsa = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_TYPE_7), 0,
oa->ospf6->router_id, oa->lsdb);
if (lsa && !OSPF6_LSA_IS_MAXAGE(lsa)) {
if (IS_OSPF6_DEBUG_NSSA)
zlog_debug(
"Withdrawing Type-7 default route from area %s",
oa->name);

ospf6_lsa_purge(lsa);
}
}

/* NSSA Type-7 default route. */
void ospf6_abr_nssa_type_7_defaults(struct ospf6 *ospf6)
{
struct listnode *node;
struct ospf6_area *oa;

for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
if (IS_AREA_NSSA(oa) && oa->nssa_default_originate.enabled
&& (IS_OSPF6_ABR(ospf6)
|| (IS_OSPF6_ASBR(ospf6)
&& ospf6->nssa_default_import_check.status)))
ospf6_abr_nssa_type_7_default_create(ospf6, oa);
else
ospf6_abr_nssa_type_7_default_delete(ospf6, oa);
}
}

static void ospf6_abr_nssa_task(struct ospf6 *ospf6)
{
/* called only if any_nssa */
Expand Down Expand Up @@ -1169,10 +1251,11 @@ static void ospf6_check_and_originate_type7_lsa(struct ospf6_area *area)
for (route = ospf6_route_head(
area->ospf6->external_table);
route; route = ospf6_route_next(route)) {
/* This means the Type-5 LSA was originated for this route */
if (route->path.origin.id != 0)
ospf6_nssa_lsa_originate(route, area);
struct ospf6_external_info *info = route->route_option;

/* This means the Type-5 LSA was originated for this route */
if (route->path.origin.id != 0 && info->type != DEFAULT_ROUTE)
ospf6_nssa_lsa_originate(route, area, true);
}

/* Loop through the aggregation table to originate type-7 LSAs
Expand All @@ -1192,7 +1275,7 @@ static void ospf6_check_and_originate_type7_lsa(struct ospf6_area *area)
"Originating Type-7 LSAs for area %s",
area->name);

ospf6_nssa_lsa_originate(aggr->route, area);
ospf6_nssa_lsa_originate(aggr->route, area, true);
}
}

Expand Down Expand Up @@ -1286,7 +1369,7 @@ static struct in6_addr *ospf6_get_nssa_fwd_addr(struct ospf6_area *oa)
}

void ospf6_nssa_lsa_originate(struct ospf6_route *route,
struct ospf6_area *area)
struct ospf6_area *area, bool p_bit)
{
char buffer[OSPF6_MAX_LSASIZE];
struct ospf6_lsa_header *lsa_header;
Expand All @@ -1311,13 +1394,13 @@ void ospf6_nssa_lsa_originate(struct ospf6_route *route,

/* Fill AS-External-LSA */
/* Metric type */
if (route->path.metric_type == OSPF6_PATH_TYPE_EXTERNAL2)
if (route->path.metric_type == 2)
SET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_E);
else
UNSET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_E);

/* external route tag */
if (info->tag)
if (info && info->tag)
SET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T);
else
UNSET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T);
Expand All @@ -1332,7 +1415,8 @@ void ospf6_nssa_lsa_originate(struct ospf6_route *route,
as_external_lsa->prefix.prefix_options = route->prefix_options;

/* Set the P bit */
as_external_lsa->prefix.prefix_options |= OSPF6_PREFIX_OPTION_P;
if (p_bit)
as_external_lsa->prefix.prefix_options |= OSPF6_PREFIX_OPTION_P;

/* don't use refer LS-type */
as_external_lsa->prefix.prefix_refer_lstype = htons(0);
Expand All @@ -1353,7 +1437,8 @@ void ospf6_nssa_lsa_originate(struct ospf6_route *route,
UNSET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F);

/* External Route Tag */
if (CHECK_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T)) {
if (info
&& CHECK_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T)) {
route_tag_t network_order = htonl(info->tag);

memcpy(p, &network_order, sizeof(network_order));
Expand Down
3 changes: 2 additions & 1 deletion ospf6d/ospf6_nssa.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,9 @@ extern void ospf6_schedule_abr_task(struct ospf6 *ospf6);
extern void ospf6_area_nssa_update(struct ospf6_area *area);
void ospf6_asbr_prefix_readvertise(struct ospf6 *ospf6);
extern void ospf6_nssa_lsa_originate(struct ospf6_route *route,
struct ospf6_area *area);
struct ospf6_area *area, bool p_bit);
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,
Expand Down
Loading

0 comments on commit b8beb67

Please sign in to comment.