ospf6d: add support for NSSA totally stub areas

Add a knob to turn a NSSA area into a totally stub area. In this
configuration a Type-3 default summary route is generated by default.

Syntax: `area A.B.C.D nssa no-summary`.

Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
This commit is contained in:
Renato Westphal 2021-08-24 17:35:21 -03:00
parent b44f7c3f6d
commit 8a60820f70
5 changed files with 68 additions and 24 deletions

View file

@ -176,9 +176,9 @@ 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
.. clicmd:: area A.B.C.D nssa [no-summary]
.. clicmd:: area (0-4294967295) nssa
.. clicmd:: area (0-4294967295) nssa [no-summary]
Configure the area to be a NSSA (Not-So-Stubby Area).
@ -194,6 +194,10 @@ OSPF6 area
4. Support for NSSA Translator functionality when there are multiple NSSA
ABR in an area.
An NSSA ABR can be configured with the `no-summary` option to prevent the
advertisement of summaries into the area. In that case, a single Type-3 LSA
containing a default route is originated into the NSSA.
.. _ospf6-interface:
OSPF6 interface

View file

@ -748,7 +748,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,
@ -762,14 +770,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);

View file

@ -46,6 +46,9 @@
#include "ospf6d.h"
#include "lib/json.h"
#include "ospf6_nssa.h"
#ifndef VTYSH_EXTRACT_PL
#include "ospf6d/ospf6_area_clippy.c"
#endif
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_AREA, "OSPF6 area");
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_PLISTNAME, "Prefix list name");
@ -643,8 +646,12 @@ void ospf6_area_config_write(struct vty *vty, struct ospf6 *ospf6)
else
vty_out(vty, " area %s stub\n", oa->name);
}
if (IS_AREA_NSSA(oa))
vty_out(vty, " area %s nssa\n", oa->name);
if (IS_AREA_NSSA(oa)) {
vty_out(vty, " area %s nssa", oa->name);
if (oa->no_summary)
vty_out(vty, " no-summary");
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));
@ -1250,18 +1257,18 @@ DEFUN (no_ospf6_area_stub_no_summary,
return CMD_SUCCESS;
}
DEFUN(ospf6_area_nssa, ospf6_area_nssa_cmd,
"area <A.B.C.D|(0-4294967295)> nssa",
DEFPY(ospf6_area_nssa, ospf6_area_nssa_cmd,
"area <A.B.C.D|(0-4294967295)>$area_str nssa [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")
"Configure OSPF6 area as nssa\n"
"Do not inject inter-area routes into area\n")
{
int idx_ipv4_number = 1;
struct ospf6_area *area;
VTY_DECLVAR_CONTEXT(ospf6, ospf6);
OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area, ospf6);
OSPF6_CMD_AREA_GET(area_str, area, ospf6);
if (!ospf6_area_nssa_set(ospf6, area)) {
vty_out(vty,
@ -1269,26 +1276,32 @@ DEFUN(ospf6_area_nssa, ospf6_area_nssa_cmd,
return CMD_WARNING_CONFIG_FAILED;
}
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))
ospf6_abr_defaults_to_stub(ospf6);
return CMD_SUCCESS;
}
DEFUN(no_ospf6_area_nssa, no_ospf6_area_nssa_cmd,
"no area <A.B.C.D|(0-4294967295)> nssa",
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_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")
"Configure OSPF6 area as nssa\n"
"Do not inject inter-area routes into area\n")
{
int idx_ipv4_number = 2;
struct ospf6_area *area;
VTY_DECLVAR_CONTEXT(ospf6, ospf6);
OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area, ospf6);
OSPF6_CMD_AREA_GET(area_str, area, ospf6);
ospf6_area_nssa_unset(ospf6, area);
ospf6_area_no_summary_unset(ospf6, area);
return CMD_SUCCESS;
}

View file

@ -588,6 +588,32 @@ void ospf6_asbr_lsa_add(struct ospf6_lsa *lsa)
}
}
/*
* RFC 3101 - Section 2.5:
* "If the destination is a Type-7 default route (destination ID =
* DefaultDestination) and one of the following is true, then do
* nothing with this LSA and consider the next in the list:
*
* o The calculating router is a border router and the LSA has
* its P-bit clear. Appendix E describes a technique
* whereby an NSSA border router installs a Type-7 default
* LSA without propagating it.
*
* o The calculating router is a border router and is
* suppressing the import of summary routes as Type-3
* summary-LSAs".
*/
if (ntohs(lsa->header->type) == OSPF6_LSTYPE_TYPE_7
&& external->prefix.prefix_length == 0
&& CHECK_FLAG(ospf6->flag, OSPF6_FLAG_ABR)
&& (CHECK_FLAG(external->prefix.prefix_options,
OSPF6_PREFIX_OPTION_P)
|| oa->no_summary)) {
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL))
zlog_debug("Skipping Type-7 default route");
return;
}
/* Check the forwarding address */
if (CHECK_FLAG(external->bits_metric, OSPF6_ASBR_BIT_F)) {
offset = sizeof(*external)

View file

@ -92,6 +92,7 @@ ospf6d_ospf6d_snmp_la_LIBADD = lib/libfrrsnmp.la
clippy_scan += \
ospf6d/ospf6_top.c \
ospf6d/ospf6_area.c \
ospf6d/ospf6_asbr.c \
ospf6d/ospf6_lsa.c \
ospf6d/ospf6_gr_helper.c \