From 8a60820f70cb9b218fdb87100caaca45c42f1a36 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Tue, 24 Aug 2021 17:35:21 -0300 Subject: [PATCH] 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 --- doc/user/ospf6d.rst | 8 ++++++-- ospf6d/ospf6_abr.c | 18 +++++++++--------- ospf6d/ospf6_area.c | 39 ++++++++++++++++++++++++++------------- ospf6d/ospf6_asbr.c | 26 ++++++++++++++++++++++++++ ospf6d/subdir.am | 1 + 5 files changed, 68 insertions(+), 24 deletions(-) diff --git a/doc/user/ospf6d.rst b/doc/user/ospf6d.rst index 499788ae87..4fd86ffb13 100644 --- a/doc/user/ospf6d.rst +++ b/doc/user/ospf6d.rst @@ -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 diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c index 650262f1ae..aa85475678 100644 --- a/ospf6d/ospf6_abr.c +++ b/ospf6d/ospf6_abr.c @@ -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); diff --git a/ospf6d/ospf6_area.c b/ospf6d/ospf6_area.c index 098132b1f6..71d32b409c 100644 --- a/ospf6d/ospf6_area.c +++ b/ospf6d/ospf6_area.c @@ -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 nssa", +DEFPY(ospf6_area_nssa, ospf6_area_nssa_cmd, + "area $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; } - ospf6_area_no_summary_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)) + ospf6_abr_defaults_to_stub(ospf6); return CMD_SUCCESS; } -DEFUN(no_ospf6_area_nssa, no_ospf6_area_nssa_cmd, - "no area nssa", +DEFPY(no_ospf6_area_nssa, no_ospf6_area_nssa_cmd, + "no area $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; } diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c index f16a1975a8..b5bf81c213 100644 --- a/ospf6d/ospf6_asbr.c +++ b/ospf6d/ospf6_asbr.c @@ -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) diff --git a/ospf6d/subdir.am b/ospf6d/subdir.am index ac99e90b26..5a4e4db69b 100644 --- a/ospf6d/subdir.am +++ b/ospf6d/subdir.am @@ -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 \ -- 2.39.5