summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/user/bgp.rst6
-rw-r--r--doc/user/ospfd.rst21
-rw-r--r--ospfd/ospf_abr.c3
-rw-r--r--ospfd/ospf_lsa.c29
-rw-r--r--ospfd/ospf_lsa.h11
-rw-r--r--ospfd/ospf_vty.c58
-rw-r--r--ospfd/ospfd.c28
-rw-r--r--ospfd/ospfd.h6
-rwxr-xr-xtests/topotests/ospf_suppress_fa/__init__.py0
-rw-r--r--tests/topotests/ospf_suppress_fa/r1/ospfd.conf9
-rw-r--r--tests/topotests/ospf_suppress_fa/r1/zebra.conf4
-rw-r--r--tests/topotests/ospf_suppress_fa/r2/ospfd.conf16
-rw-r--r--tests/topotests/ospf_suppress_fa/r2/zebra.conf7
-rw-r--r--tests/topotests/ospf_suppress_fa/r3/ospfd.conf11
-rw-r--r--tests/topotests/ospf_suppress_fa/r3/zebra.conf8
-rw-r--r--tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.dot66
-rw-r--r--tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.dot.jpgbin0 -> 33501 bytes
-rw-r--r--tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.py181
18 files changed, 455 insertions, 9 deletions
diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst
index 4433dc9e21..61ed4d3e09 100644
--- a/doc/user/bgp.rst
+++ b/doc/user/bgp.rst
@@ -1420,6 +1420,12 @@ Configuring Peers
This command is deprecated and may be removed in a future release. Its use
should be avoided.
+.. clicmd:: neighbor PEER interface remote-as <internal|external|ASN>
+
+ Configure an unnumbered BGP peer. ``PEER`` should be an interface name. The
+ session will be established via IPv6 link locals. Use ``internal`` for iBGP
+ and ``external`` for eBGP sessions, or specify an ASN if you wish.
+
.. clicmd:: neighbor PEER next-hop-self [all]
This command specifies an announced route's nexthop as being equivalent to
diff --git a/doc/user/ospfd.rst b/doc/user/ospfd.rst
index 64ce85503e..af9a7844a2 100644
--- a/doc/user/ospfd.rst
+++ b/doc/user/ospfd.rst
@@ -390,6 +390,27 @@ Areas
Prevents an *ospfd* ABR from injecting inter-area
summaries into the specified stub area.
+.. clicmd:: area A.B.C.D nssa
+
+.. clicmd:: area (0-4294967295) nssa
+
+ Configure the area to be a NSSA (Not-So-Stubby Area). This is an area that
+ allows OSPF to import external routes into a stub area via a new LSA type
+ (type 7). An NSSA autonomous system boundary router (ASBR) will generate this
+ type of LSA. The area border router (ABR) translates the LSA type 7 into LSA
+ type 5, which is propagated into the OSPF domain. NSSA areas are defined in
+ RFC 3101.
+
+.. clicmd:: area A.B.C.D nssa suppress-fa
+
+.. clicmd:: area (0-4294967295) nssa suppress-fa
+
+ Configure the router to set the forwarding address to 0.0.0.0 in all LSA type 5
+ translated from LSA type 7. The router needs to be elected the translator of the
+ area for this command to take effect. This feature causes routers that are
+ configured not to advertise forwarding addresses into the backbone to direct
+ forwarded traffic to the NSSA ABR translator.
+
.. clicmd:: area A.B.C.D default-cost (0-16777215)
diff --git a/ospfd/ospf_abr.c b/ospfd/ospf_abr.c
index f3c4798906..b5c97eda3c 100644
--- a/ospfd/ospf_abr.c
+++ b/ospfd/ospf_abr.c
@@ -675,7 +675,8 @@ static int ospf_abr_translate_nssa(struct ospf_area *area, struct ospf_lsa *lsa)
* originate translated LSA
*/
- if (ospf_translated_nssa_originate(area->ospf, lsa) == NULL) {
+ if (ospf_translated_nssa_originate(area->ospf, lsa, old)
+ == NULL) {
if (IS_DEBUG_OSPF_NSSA)
zlog_debug(
"ospf_abr_translate_nssa(): Could not translate Type-7 for %pI4 to Type-5",
diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c
index 6bde5467b2..cb1c565d37 100644
--- a/ospfd/ospf_lsa.c
+++ b/ospfd/ospf_lsa.c
@@ -1765,7 +1765,14 @@ static struct ospf_lsa *ospf_lsa_translated_nssa_new(struct ospf *ospf,
/* copy over Type-7 data to new */
extnew->e[0].tos = ext->e[0].tos;
extnew->e[0].route_tag = ext->e[0].route_tag;
- extnew->e[0].fwd_addr.s_addr = ext->e[0].fwd_addr.s_addr;
+ if (type7->area->suppress_fa) {
+ extnew->e[0].fwd_addr.s_addr = 0;
+ if (IS_DEBUG_OSPF_NSSA)
+ zlog_debug(
+ "ospf_lsa_translated_nssa_new(): Suppress forwarding address for %pI4",
+ &ei.p.prefix);
+ } else
+ extnew->e[0].fwd_addr.s_addr = ext->e[0].fwd_addr.s_addr;
new->data->ls_seqnum = type7->data->ls_seqnum;
/* add translated flag, checksum and lock new lsa */
@@ -1777,7 +1784,8 @@ static struct ospf_lsa *ospf_lsa_translated_nssa_new(struct ospf *ospf,
/* Originate Translated Type-5 for supplied Type-7 NSSA LSA */
struct ospf_lsa *ospf_translated_nssa_originate(struct ospf *ospf,
- struct ospf_lsa *type7)
+ struct ospf_lsa *type7,
+ struct ospf_lsa *type5)
{
struct ospf_lsa *new;
struct as_external_lsa *extnew;
@@ -1796,6 +1804,10 @@ struct ospf_lsa *ospf_translated_nssa_originate(struct ospf *ospf,
extnew = (struct as_external_lsa *)new->data;
+ /* Update LSA sequence number from translated Type-5 LSA */
+ if (type5)
+ new->data->ls_seqnum = lsa_seqnum_increment(type5);
+
if ((new = ospf_lsa_install(ospf, NULL, new)) == NULL) {
flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
"%s: Could not install LSA id %pI4", __func__,
@@ -1823,6 +1835,8 @@ struct ospf_lsa *ospf_translated_nssa_refresh(struct ospf *ospf,
struct ospf_lsa *type5)
{
struct ospf_lsa *new = NULL;
+ struct as_external_lsa *extold = NULL;
+ uint32_t ls_seqnum = 0;
/* Sanity checks. */
assert(type7 || type5);
@@ -1887,6 +1901,12 @@ struct ospf_lsa *ospf_translated_nssa_refresh(struct ospf *ospf,
return NULL;
}
+ extold = (struct as_external_lsa *)type5->data;
+ if (type7->area->suppress_fa == 1) {
+ if (extold->e[0].fwd_addr.s_addr == 0)
+ ls_seqnum = ntohl(type5->data->ls_seqnum);
+ }
+
/* Delete LSA from neighbor retransmit-list. */
ospf_ls_retransmit_delete_nbr_as(ospf, type5);
@@ -1899,6 +1919,11 @@ struct ospf_lsa *ospf_translated_nssa_refresh(struct ospf *ospf,
return NULL;
}
+ if (type7->area->suppress_fa == 1) {
+ if (extold->e[0].fwd_addr.s_addr == 0)
+ new->data->ls_seqnum = htonl(ls_seqnum + 1);
+ }
+
if (!(new = ospf_lsa_install(ospf, NULL, new))) {
flog_warn(
EC_OSPF_LSA_INSTALL_FAILURE,
diff --git a/ospfd/ospf_lsa.h b/ospfd/ospf_lsa.h
index f2a0d36e7e..3c1f94e628 100644
--- a/ospfd/ospf_lsa.h
+++ b/ospfd/ospf_lsa.h
@@ -341,11 +341,12 @@ extern char link_info_set(struct stream **s, struct in_addr id,
extern struct in_addr ospf_get_nssa_ip(struct ospf_area *);
extern int ospf_translated_nssa_compare(struct ospf_lsa *, struct ospf_lsa *);
-extern struct ospf_lsa *ospf_translated_nssa_refresh(struct ospf *,
- struct ospf_lsa *,
- struct ospf_lsa *);
-extern struct ospf_lsa *ospf_translated_nssa_originate(struct ospf *,
- struct ospf_lsa *);
+extern struct ospf_lsa *ospf_translated_nssa_refresh(struct ospf *ospf,
+ struct ospf_lsa *type7,
+ struct ospf_lsa *type5);
+extern struct ospf_lsa *ospf_translated_nssa_originate(struct ospf *ospf,
+ struct ospf_lsa *type7,
+ struct ospf_lsa *type5);
extern void ospf_flush_lsa_from_area(struct ospf *ospf, struct in_addr area_id,
int type);
#endif /* _ZEBRA_OSPF_LSA_H */
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index e6835ffc72..d634853b3e 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -1574,6 +1574,58 @@ DEFUN (ospf_area_nssa,
return ospf_area_nssa_cmd_handler(vty, argc, argv, 0, 0);
}
+DEFUN(ospf_area_nssa_suppress_fa, ospf_area_nssa_suppress_fa_cmd,
+ "area <A.B.C.D|(0-4294967295)> nssa suppress-fa",
+ "OSPF area parameters\n"
+ "OSPF area ID in IP address format\n"
+ "OSPF area ID as a decimal value\n"
+ "Configure OSPF area as nssa\n"
+ "Suppress forwarding address\n")
+{
+ int idx_ipv4_number = 1;
+ struct in_addr area_id;
+ int format;
+
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
+ VTY_GET_OSPF_AREA_ID_NO_BB("NSSA", area_id, format,
+ argv[idx_ipv4_number]->arg);
+
+ ospf_area_display_format_set(ospf, ospf_area_get(ospf, area_id),
+ format);
+ ospf_area_nssa_suppress_fa_set(ospf, area_id);
+
+ ospf_schedule_abr_task(ospf);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(no_ospf_area_nssa_suppress_fa, no_ospf_area_nssa_suppress_fa_cmd,
+ "no area <A.B.C.D|(0-4294967295)> nssa suppress-fa",
+ NO_STR
+ "OSPF area parameters\n"
+ "OSPF area ID in IP address format\n"
+ "OSPF area ID as a decimal value\n"
+ "Configure OSPF area as nssa\n"
+ "Suppress forwarding address\n")
+{
+ int idx_ipv4_number = 2;
+ struct in_addr area_id;
+ int format;
+
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
+
+ VTY_GET_OSPF_AREA_ID_NO_BB("nssa", area_id, format,
+ argv[idx_ipv4_number]->arg);
+
+ ospf_area_display_format_set(ospf, ospf_area_get(ospf, area_id),
+ format);
+ ospf_area_nssa_suppress_fa_unset(ospf, area_id);
+
+ ospf_schedule_abr_task(ospf);
+
+ return CMD_SUCCESS;
+}
+
DEFUN (ospf_area_nssa_no_summary,
ospf_area_nssa_no_summary_cmd,
"area <A.B.C.D|(0-4294967295)> nssa no-summary",
@@ -11823,6 +11875,10 @@ static int config_write_ospf_area(struct vty *vty, struct ospf *ospf)
vty_out(vty,
" area %s nssa no-summary\n",
buf);
+ if (area->suppress_fa)
+ vty_out(vty,
+ " area %s nssa suppress-fa\n",
+ buf);
}
if (area->default_cost != 1)
@@ -12684,6 +12740,8 @@ void ospf_vty_init(void)
install_element(OSPF_NODE, &ospf_area_nssa_translate_cmd);
install_element(OSPF_NODE, &ospf_area_nssa_no_summary_cmd);
install_element(OSPF_NODE, &no_ospf_area_nssa_no_summary_cmd);
+ install_element(OSPF_NODE, &ospf_area_nssa_suppress_fa_cmd);
+ install_element(OSPF_NODE, &no_ospf_area_nssa_suppress_fa_cmd);
install_element(OSPF_NODE, &no_ospf_area_nssa_cmd);
install_element(OSPF_NODE, &ospf_area_default_cost_cmd);
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index 9856e60130..f126577aeb 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -1672,6 +1672,7 @@ int ospf_area_nssa_set(struct ospf *ospf, struct in_addr area_id)
/* set NSSA area defaults */
area->no_summary = 0;
+ area->suppress_fa = 0;
area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED;
area->NSSATranslatorStabilityInterval =
@@ -1693,6 +1694,7 @@ int ospf_area_nssa_unset(struct ospf *ospf, struct in_addr area_id, int argc)
ospf->anyNSSA--;
/* set NSSA area defaults */
area->no_summary = 0;
+ area->suppress_fa = 0;
area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED;
area->NSSATranslatorStabilityInterval =
@@ -1708,6 +1710,32 @@ int ospf_area_nssa_unset(struct ospf *ospf, struct in_addr area_id, int argc)
return 1;
}
+int ospf_area_nssa_suppress_fa_set(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 0;
+
+ area->suppress_fa = 1;
+
+ return 1;
+}
+
+int ospf_area_nssa_suppress_fa_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 0;
+
+ area->suppress_fa = 0;
+
+ return 1;
+}
+
int ospf_area_nssa_translator_role_set(struct ospf *ospf,
struct in_addr area_id, int role)
{
diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h
index 5d64ee9ba2..a3f78b074e 100644
--- a/ospfd/ospfd.h
+++ b/ospfd/ospfd.h
@@ -476,7 +476,7 @@ struct ospf_area {
int shortcut_capability; /* Other ABRs agree on S-bit */
uint32_t default_cost; /* StubDefaultCost. */
int auth_type; /* Authentication type. */
-
+ int suppress_fa; /* Suppress forwarding address in NSSA ABR */
uint8_t NSSATranslatorRole; /* NSSA configured role */
#define OSPF_NSSA_ROLE_NEVER 0
@@ -668,6 +668,10 @@ extern int ospf_area_no_summary_set(struct ospf *, struct in_addr);
extern int ospf_area_no_summary_unset(struct ospf *, struct in_addr);
extern int ospf_area_nssa_set(struct ospf *, struct in_addr);
extern int ospf_area_nssa_unset(struct ospf *, struct in_addr, int);
+extern int ospf_area_nssa_suppress_fa_set(struct ospf *ospf,
+ struct in_addr area_id);
+extern int ospf_area_nssa_suppress_fa_unset(struct ospf *ospf,
+ struct in_addr area_id);
extern int ospf_area_nssa_translator_role_set(struct ospf *, struct in_addr,
int);
extern int ospf_area_export_list_set(struct ospf *, struct ospf_area *,
diff --git a/tests/topotests/ospf_suppress_fa/__init__.py b/tests/topotests/ospf_suppress_fa/__init__.py
new file mode 100755
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/ospf_suppress_fa/__init__.py
diff --git a/tests/topotests/ospf_suppress_fa/r1/ospfd.conf b/tests/topotests/ospf_suppress_fa/r1/ospfd.conf
new file mode 100644
index 0000000000..c02be35b14
--- /dev/null
+++ b/tests/topotests/ospf_suppress_fa/r1/ospfd.conf
@@ -0,0 +1,9 @@
+!
+interface r1-eth0
+ ip ospf network point-to-point
+ ip ospf hello-interval 2
+ ip ospf dead-interval 10
+!
+router ospf
+ network 10.0.12.0/24 area 0
+!
diff --git a/tests/topotests/ospf_suppress_fa/r1/zebra.conf b/tests/topotests/ospf_suppress_fa/r1/zebra.conf
new file mode 100644
index 0000000000..c1e31fb474
--- /dev/null
+++ b/tests/topotests/ospf_suppress_fa/r1/zebra.conf
@@ -0,0 +1,4 @@
+!
+interface r1-eth0
+ ip address 10.0.12.1/24
+!
diff --git a/tests/topotests/ospf_suppress_fa/r2/ospfd.conf b/tests/topotests/ospf_suppress_fa/r2/ospfd.conf
new file mode 100644
index 0000000000..ebc7d252fd
--- /dev/null
+++ b/tests/topotests/ospf_suppress_fa/r2/ospfd.conf
@@ -0,0 +1,16 @@
+!
+interface r2-eth0
+ ip ospf network point-to-point
+ ip ospf hello-interval 2
+ ip ospf dead-interval 10
+!
+interface r2-eth1
+ ip ospf network point-to-point
+ ip ospf hello-interval 2
+ ip ospf dead-interval 10
+!
+router ospf
+ network 10.0.12.0/24 area 0
+ network 10.0.23.0/24 area 1
+ area 1 nssa
+!
diff --git a/tests/topotests/ospf_suppress_fa/r2/zebra.conf b/tests/topotests/ospf_suppress_fa/r2/zebra.conf
new file mode 100644
index 0000000000..9f1a26349e
--- /dev/null
+++ b/tests/topotests/ospf_suppress_fa/r2/zebra.conf
@@ -0,0 +1,7 @@
+!
+interface r2-eth0
+ ip address 10.0.12.2/24
+!
+interface r2-eth1
+ ip address 10.0.23.2/24
+!
diff --git a/tests/topotests/ospf_suppress_fa/r3/ospfd.conf b/tests/topotests/ospf_suppress_fa/r3/ospfd.conf
new file mode 100644
index 0000000000..08be11a7b7
--- /dev/null
+++ b/tests/topotests/ospf_suppress_fa/r3/ospfd.conf
@@ -0,0 +1,11 @@
+!
+interface r3-eth0
+ ip ospf network point-to-point
+ ip ospf hello-interval 2
+ ip ospf dead-interval 10
+!
+router ospf
+ redistribute static
+ network 10.0.23.0/24 area 1
+ area 1 nssa
+!
diff --git a/tests/topotests/ospf_suppress_fa/r3/zebra.conf b/tests/topotests/ospf_suppress_fa/r3/zebra.conf
new file mode 100644
index 0000000000..f76cbf74d2
--- /dev/null
+++ b/tests/topotests/ospf_suppress_fa/r3/zebra.conf
@@ -0,0 +1,8 @@
+!
+ip route 3.3.1.1/32 Null0
+ip route 3.3.2.2/32 Null0
+ip route 3.3.3.3/32 Null0
+!
+interface r3-eth0
+ ip address 10.0.23.3/24
+!
diff --git a/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.dot b/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.dot
new file mode 100644
index 0000000000..1036658f1a
--- /dev/null
+++ b/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.dot
@@ -0,0 +1,66 @@
+## Color coding:
+#########################
+## Main FRR: #f08080 red
+## Switches: #d0e0d0 gray
+## RIP: #19e3d9 Cyan
+## RIPng: #fcb314 dark yellow
+## OSPFv2: #32b835 Green
+## OSPFv3: #19e3d9 Cyan
+## ISIS IPv4 #fcb314 dark yellow
+## ISIS IPv6 #9a81ec purple
+## BGP IPv4 #eee3d3 beige
+## BGP IPv6 #fdff00 yellow
+##### Colors (see http://www.color-hex.com/)
+
+graph ospf_topo1 {
+ label="ospf suppress-fa";
+
+ # Routers
+ r1 [
+ label="r1\nrtr-id 10.0.12.1",
+ shape=doubleoctagon,
+ fillcolor="#f08080",
+ style=filled,
+ ];
+ r2 [
+ label="r2 (ABR)\nrtr-id 10.0.23.2",
+ shape=doubleoctagon,
+ fillcolor="#f08080",
+ style=filled,
+ ];
+ r3 [
+ label="r3 (ASBR)\nrtr-id 10.0.23.3",
+ shape=doubleoctagon,
+ fillcolor="#f08080",
+ style=filled,
+ ];
+
+ # Switches
+ s1 [
+ label="s1\n10.0.12.0/24",
+ shape=oval,
+ fillcolor="#d0e0d0",
+ style=filled,
+ ];
+ s2 [
+ label="s2\n10.0.23.0/24",
+ shape=oval,
+ fillcolor="#d0e0d0",
+ style=filled,
+ ];
+
+ # Connections
+ subgraph cluster0 {
+ label="area 0"
+ r1 -- s1 [label="eth1\n.1"];
+ r2 -- s1 [label="eth1\n.2"];
+ }
+
+ subgraph cluster1 {
+ label="area 1\nNSSA"
+ r2 -- s2 [label="eth2\n.2"];
+ r3 -- s2 [label="eth1\n.3"];
+ }
+
+ { rank=same; r1; r2; r3; }
+}
diff --git a/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.dot.jpg b/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.dot.jpg
new file mode 100644
index 0000000000..2907d799f5
--- /dev/null
+++ b/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.dot.jpg
Binary files differ
diff --git a/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.py b/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.py
new file mode 100644
index 0000000000..74d609c57e
--- /dev/null
+++ b/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.py
@@ -0,0 +1,181 @@
+#!/usr/bin/env python
+
+#
+# test_ospf_suppres_fa.py
+# Carles Kishimoto
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+test_ospf_suppres_fa.py: Test OSPF suppress-fa feature
+- Topology: r1 --- R2 (ABR) --- R3 (redistribute static)
+
+test_ospf_set_suppress_fa()
+ 1) R1: Get a dict[LSA_ID] = fwd_addr for all type 5 LSA
+ 2) R2: Configure: area 1 nssa suppress-fa
+ 3) R1: Get a dict[LSA_ID] and compare fwd_address with 0.0.0.0
+
+test_ospf_unset_suppress_fa()
+ 4) R2: Configure: no area 1 nssa suppress-fa
+ 5) R1: Get a dict[LSA_ID] = fwd_addr and compare it with the dict obtained in 1)
+"""
+
+import os
+import sys
+import re
+import pytest
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+
+# Required to instantiate the topology builder class.
+from mininet.topo import Topo
+
+
+class NetworkTopo(Topo):
+ "OSPF topology builder"
+
+ def build(self, *_args, **_opts):
+ "Build function"
+
+ tgen = get_topogen(self)
+
+ # Create routers
+ for router in range(1, 4):
+ tgen.add_router("r{}".format(router))
+
+ # R1-R2 backbone area
+ switch = tgen.add_switch("s1")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r2"])
+
+ # R2-R3 NSSA area
+ switch = tgen.add_switch("s2")
+ switch.add_link(tgen.gears["r2"])
+ switch.add_link(tgen.gears["r3"])
+
+
+def setup_module(mod):
+ "Sets up the pytest environment"
+
+ tgen = Topogen(NetworkTopo, mod.__name__)
+ tgen.start_topology()
+
+ # This is a sample of configuration loading.
+ router_list = tgen.routers()
+
+ # For all registred routers, load the zebra and ospf configuration file
+ for rname, router in router_list.items():
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_OSPF, os.path.join(CWD, "{}/ospfd.conf".format(rname))
+ )
+
+ tgen.start_router()
+
+def teardown_module(_mod):
+ "Teardown the pytest environment"
+
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+def test_converge_protocols():
+ "Wait for protocol convergence"
+
+ tgen = get_topogen()
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ topotest.sleep(10, "Waiting for OSPF convergence")
+
+def ospf_configure_suppress_fa(router_name, area):
+ "Configure OSPF suppress-fa in router_name"
+
+ tgen = get_topogen()
+ router = tgen.gears[router_name]
+ router.vtysh_cmd("conf t\nrouter ospf\narea {} nssa suppress-fa\nexit\n".format(area))
+
+def ospf_unconfigure_suppress_fa(router_name, area):
+ "Remove OSPF suppress-fa in router_name"
+
+ tgen = get_topogen()
+ router = tgen.gears[router_name]
+ router.vtysh_cmd("conf t\nrouter ospf\nno area {} nssa suppress-fa\nexit\n".format(area))
+
+def ospf_get_lsa_type5(router_name):
+ "Return a dict with link state id as key and forwarding addresses as value"
+
+ result = dict()
+ tgen = get_topogen()
+ router = tgen.gears[router_name]
+ cmd = "show ip ospf database external\n"
+ output = topotest.normalize_text(router.vtysh_cmd(cmd))
+ for line in output.splitlines():
+ re0 = re.match(r"\s+Link State ID: (\S+) \(External Network Number\)", line)
+ if re0:
+ lsa = re0.group(1)
+ re1 = re.match(r"\s+Forward Address: (\S+)", line)
+ if re1:
+ result[lsa] = re1.group(1)
+ return result
+
+@pytest.fixture(scope='module', name='original')
+def test_ospf_set_suppress_fa():
+ "Test OSPF area [x] nssa suppress-fa"
+
+ # Get current forwarding address for each LSA type-5 in r1
+ initial = ospf_get_lsa_type5("r1")
+
+ # Configure suppres-fa in r2 area 1
+ ospf_configure_suppress_fa("r2", "1")
+ topotest.sleep(10, "Waiting for OSPF convergence")
+
+ # Check forwarding address on r1 for all statics is 0.0.0.0
+ assertmsg = "Forwarding address is not 0.0.0.0 after enabling OSPF suppress-fa"
+ suppress = ospf_get_lsa_type5("r1")
+ for prefix in suppress:
+ assert suppress[prefix] == "0.0.0.0", assertmsg
+
+ # Return the original forwarding addresses so we can compare them
+ # in the test_ospf_unset_supress_fa
+ return initial
+
+def test_ospf_unset_supress_fa(original):
+ "Test OSPF no area [x] nssa suppress-fa"
+
+ # Remove suppress-fa in r2 area 1
+ ospf_unconfigure_suppress_fa("r2", "1")
+ topotest.sleep(10, "Waiting for OSPF convergence")
+
+ # Check forwarding address is the original value on r1 for all statics
+ assertmsg = "Forwarding address is not correct after removing OSPF suppress-fa"
+ restore = ospf_get_lsa_type5("r1")
+ for prefix in restore:
+ assert restore[prefix] == original[prefix], assertmsg
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))