summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--alpine/APKBUILD.in6
-rw-r--r--babeld/babeld.c62
-rw-r--r--babeld/babeld.h4
-rw-r--r--babeld/util.h9
-rw-r--r--bgpd/bgp_attr.c79
-rw-r--r--bgpd/bgp_bfd.c2
-rw-r--r--bgpd/bgp_bmp.c8
-rw-r--r--bgpd/bgp_dump.c3
-rw-r--r--bgpd/bgp_ecommunity.c29
-rw-r--r--bgpd/bgp_evpn.c17
-rw-r--r--bgpd/bgp_evpn.h2
-rw-r--r--bgpd/bgp_evpn_mh.c3
-rw-r--r--bgpd/bgp_flowspec.c9
-rw-r--r--bgpd/bgp_flowspec.h2
-rw-r--r--bgpd/bgp_mplsvpn.c4
-rw-r--r--bgpd/bgp_packet.c2
-rw-r--r--bgpd/bgp_packet.h26
-rw-r--r--bgpd/bgp_route.c79
-rw-r--r--bgpd/bgp_route.h1
-rw-r--r--bgpd/bgp_routemap.c30
-rw-r--r--bgpd/bgp_vty.c65
-rw-r--r--bgpd/bgp_zebra.c7
-rw-r--r--bgpd/bgpd.c17
-rw-r--r--configure.ac16
-rw-r--r--doc/developer/logging.rst45
-rw-r--r--doc/user/basic.rst4
-rw-r--r--doc/user/ospfd.rst31
-rw-r--r--doc/user/overview.rst2
-rw-r--r--isisd/fabricd.c13
-rw-r--r--isisd/isis_adjacency.c48
-rw-r--r--isisd/isis_adjacency.h2
-rw-r--r--isisd/isis_circuit.c17
-rw-r--r--isisd/isis_common.h8
-rw-r--r--isisd/isis_dynhn.c6
-rw-r--r--isisd/isis_events.c4
-rw-r--r--isisd/isis_lfa.c4
-rw-r--r--isisd/isis_lsp.c127
-rw-r--r--isisd/isis_misc.c102
-rw-r--r--isisd/isis_misc.h5
-rw-r--r--isisd/isis_mt.c15
-rw-r--r--isisd/isis_nb_config.c11
-rw-r--r--isisd/isis_nb_notifications.c36
-rw-r--r--isisd/isis_nb_state.c10
-rw-r--r--isisd/isis_pdu.c121
-rw-r--r--isisd/isis_snmp.c113
-rw-r--r--isisd/isis_spf.c18
-rw-r--r--isisd/isis_sr.c16
-rw-r--r--isisd/isis_te.c37
-rw-r--r--isisd/isis_tlvs.c102
-rw-r--r--isisd/isis_tx_queue.c17
-rw-r--r--isisd/isisd.c58
-rw-r--r--isisd/isisd.h3
-rw-r--r--lib/compiler.h8
-rw-r--r--lib/cspf.c2
-rw-r--r--lib/cspf.h2
-rw-r--r--lib/if_rmap.c15
-rw-r--r--lib/iso.c144
-rw-r--r--lib/iso.h49
-rw-r--r--lib/link_state.c24
-rw-r--r--lib/link_state.h4
-rw-r--r--lib/prefix.c2
-rw-r--r--lib/prefix.h5
-rw-r--r--lib/routemap.c74
-rw-r--r--lib/subdir.am2
-rw-r--r--lib/vty.c2
-rw-r--r--lib/vty.h1
-rw-r--r--lib/zclient.c2
-rw-r--r--mgmtd/mgmt.h2
-rw-r--r--mgmtd/mgmt_ds.c24
-rw-r--r--mgmtd/mgmt_ds.h2
-rw-r--r--mgmtd/mgmt_main.c7
-rw-r--r--mgmtd/mgmt_vty.c63
-rw-r--r--mgmtd/mgmt_vty.c.safe506
-rw-r--r--nhrpd/debug.h8
-rw-r--r--ospfd/ospf_abr.c324
-rw-r--r--ospfd/ospf_abr.h25
-rw-r--r--ospfd/ospf_lsa.c106
-rw-r--r--ospfd/ospf_lsa.h5
-rw-r--r--ospfd/ospf_network.c26
-rw-r--r--ospfd/ospf_network.h10
-rw-r--r--ospfd/ospf_route.c14
-rw-r--r--ospfd/ospf_route.h5
-rw-r--r--ospfd/ospf_routemap.c8
-rw-r--r--ospfd/ospf_snmp.c2
-rw-r--r--ospfd/ospf_te.c20
-rw-r--r--ospfd/ospf_vty.c468
-rw-r--r--ospfd/ospf_zebra.c57
-rw-r--r--ospfd/ospf_zebra.h1
-rw-r--r--ospfd/ospfd.c117
-rw-r--r--ospfd/ospfd.h38
-rw-r--r--pathd/path_ted.c4
-rw-r--r--pimd/pim_iface.c6
-rw-r--r--ripd/rip_nb.c60
-rw-r--r--ripd/rip_nb.h31
-rw-r--r--ripd/rip_nb_state.c161
-rw-r--r--ripd/ripd.c13
-rw-r--r--sharpd/sharp_vty.c5
-rw-r--r--sharpd/sharp_zebra.c2
-rw-r--r--staticd/static_main.c16
-rw-r--r--tests/bgpd/test_mp_attr.c4
-rw-r--r--tests/lib/subdir.am2
-rw-r--r--tests/topotests/all_protocol_startup/r1/ospf6d.conf-pre-v48
-rw-r--r--tests/topotests/all_protocol_startup/test_all_protocol_startup.py11
-rw-r--r--tests/topotests/bfd_topo3/r5/bfdd.conf6
-rw-r--r--tests/topotests/bfd_topo3/r6/bfdd.conf6
-rw-r--r--tests/topotests/bgp_accept_own/ce1/bgpd.conf2
-rw-r--r--tests/topotests/bgp_accept_own/ce2/bgpd.conf2
-rw-r--r--tests/topotests/bgp_accept_own/pe1/bgpd.conf8
-rw-r--r--tests/topotests/bgp_accept_own/rr1/bgpd.conf2
-rw-r--r--tests/topotests/bgp_comm_list_match/r2/bgpd.conf2
-rw-r--r--tests/topotests/bgp_confed1/r1/bgpd.conf8
-rw-r--r--tests/topotests/bgp_confed1/r2/bgpd.conf8
-rw-r--r--tests/topotests/bgp_confed1/r3/bgpd.conf8
-rw-r--r--tests/topotests/bgp_confed1/r4/bgpd.conf8
-rw-r--r--tests/topotests/bgp_dont_capability_negotiate/r1/bgpd.conf2
-rwxr-xr-xtests/topotests/bgp_evpn_vxlan_svd_topo1/test_bgp_evpn_vxlan_svd.py8
-rwxr-xr-xtests/topotests/bgp_evpn_vxlan_topo1/test_bgp_evpn_vxlan.py8
-rw-r--r--tests/topotests/bgp_labeled_unicast_addpath/test_bgp_labeled_unicast_addpath.py56
-rw-r--r--tests/topotests/bgp_prefix_list_any/r2/bgpd.conf2
-rw-r--r--tests/topotests/bgp_route_map_delay_timer/r1/bgpd.conf4
-rw-r--r--tests/topotests/bgp_route_map_vpn_import/r1/bgpd.conf10
-rw-r--r--tests/topotests/bgp_route_origin_parser/pe1/bgpd.conf2
-rw-r--r--tests/topotests/bgp_route_origin_parser/test_bgp_route_origin_parser.py129
-rw-r--r--tests/topotests/bgp_snmp_bgp4v2mib/r2/bgpd.conf2
-rw-r--r--tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r1/zebra.conf6
-rw-r--r--tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r2/zebra.conf6
-rw-r--r--tests/topotests/bgp_srv6l3vpn_to_bgp_vrf3/r1/zebra.conf6
-rw-r--r--tests/topotests/bgp_srv6l3vpn_to_bgp_vrf3/r2/bgpd.conf2
-rw-r--r--tests/topotests/bgp_srv6l3vpn_to_bgp_vrf3/r2/zebra.conf6
-rw-r--r--tests/topotests/bgp_suppress_fib/r2/bgpd.allowas_in.conf12
-rw-r--r--tests/topotests/bgp_suppress_fib/r2/bgpd.conf8
-rw-r--r--tests/topotests/bgp_vrf_md5_peering/r1/bgpd.conf2
-rw-r--r--tests/topotests/config_timing/test_config_timing.py4
-rw-r--r--tests/topotests/isis_snmp/r5/ldpdconf8
-rw-r--r--tests/topotests/lib/common_config.py119
-rw-r--r--tests/topotests/lib/micronet_compat.py4
-rw-r--r--tests/topotests/lib/topogen.py23
-rw-r--r--tests/topotests/lib/topotest.py42
-rw-r--r--tests/topotests/mgmt_tests/test_yang_mgmt.py18
-rw-r--r--tests/topotests/multicast_pim6_sm_topo1/test_multicast_pim6_sm1.py8
-rw-r--r--tests/topotests/multicast_pim6_sm_topo1/test_multicast_pim6_sm2.py8
-rwxr-xr-xtests/topotests/multicast_pim6_static_rp_topo1/test_multicast_pim6_static_rp1.py3
-rwxr-xr-xtests/topotests/multicast_pim6_static_rp_topo1/test_multicast_pim6_static_rp2.py3
-rw-r--r--tests/topotests/ospf6_ecmp_inter_area/r1/ospf6d.conf64
-rw-r--r--tests/topotests/ospf_nssa_topo1/__init__.py0
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt1/ospfd.conf22
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt1/staticd.conf6
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt1/step1/show_ip_ospf_route.ref115
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt1/step10/show_ip_ospf_route.ref115
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt1/step2/show_ip_ospf_route.ref115
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt1/step3/show_ip_ospf_route.ref115
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt1/step4/show_ip_ospf_route.ref103
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt1/step5/show_ip_ospf_route.ref103
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt1/step6/show_ip_ospf_route.ref91
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt1/step7/show_ip_ospf_route.ref103
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt1/step8/show_ip_ospf_route.ref103
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt1/step9/show_ip_ospf_route.ref91
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt1/zebra.conf18
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt2/ospfd.conf35
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt2/staticd.conf6
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt2/step1/show_ip_ospf_route.ref127
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt2/step10/show_ip_ospf_route.ref127
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt2/step2/show_ip_ospf_route.ref139
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt2/step3/show_ip_ospf_route.ref127
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt2/step4/show_ip_ospf_route.ref129
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt2/step5/show_ip_ospf_route.ref117
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt2/step6/show_ip_ospf_route.ref103
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt2/step7/show_ip_ospf_route.ref129
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt2/step8/show_ip_ospf_route.ref129
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt2/step9/show_ip_ospf_route.ref127
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt2/zebra.conf24
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt3/ospfd.conf24
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt3/staticd.conf8
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt3/step1/show_ip_ospf_route.ref138
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt3/step10/show_ip_ospf_route.ref150
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt3/step2/show_ip_ospf_route.ref138
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt3/step3/show_ip_ospf_route.ref138
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt3/step4/show_ip_ospf_route.ref150
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt3/step5/show_ip_ospf_route.ref138
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt3/step6/show_ip_ospf_route.ref126
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt3/step7/show_ip_ospf_route.ref150
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt3/step8/show_ip_ospf_route.ref150
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt3/step9/show_ip_ospf_route.ref150
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt3/zebra.conf18
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt4/ospfd.conf24
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt4/staticd.conf9
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt4/step1/show_ip_ospf_route.ref114
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt4/step10/show_ip_ospf_route.ref126
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt4/step2/show_ip_ospf_route.ref114
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt4/step3/show_ip_ospf_route.ref114
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt4/step4/show_ip_ospf_route.ref126
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt4/step5/show_ip_ospf_route.ref126
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt4/step6/show_ip_ospf_route.ref126
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt4/step7/show_ip_ospf_route.ref126
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt4/step8/show_ip_ospf_route.ref126
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt4/step9/show_ip_ospf_route.ref126
-rw-r--r--tests/topotests/ospf_nssa_topo1/rt4/zebra.conf18
-rw-r--r--tests/topotests/ospf_nssa_topo1/test_ospf_nssa_topo1.py416
-rw-r--r--tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.py4
-rw-r--r--tests/topotests/ospfv3_basic_functionality/test_ospfv3_single_area.py47
-rw-r--r--tests/topotests/rip_allow_ecmp/__init__.py0
-rw-r--r--tests/topotests/rip_allow_ecmp/r1/frr.conf9
-rw-r--r--tests/topotests/rip_allow_ecmp/r2/frr.conf13
-rw-r--r--tests/topotests/rip_allow_ecmp/r3/frr.conf13
-rw-r--r--tests/topotests/rip_allow_ecmp/test_rip_allow_ecmp.py124
-rw-r--r--tests/topotests/zebra_rib/test_zebra_rib.py3
-rw-r--r--yang/frr-ripd.yang127
-rw-r--r--zebra/dpdk/zebra_dplane_dpdk.c2
-rw-r--r--zebra/main.c12
-rw-r--r--zebra/rib.h9
-rw-r--r--zebra/zebra_gr.c383
-rw-r--r--zebra/zebra_rib.c91
-rw-r--r--zebra/zebra_routemap.c8
-rw-r--r--zebra/zebra_vxlan.c214
-rw-r--r--zebra/zserv.c4
-rw-r--r--zebra/zserv.h8
216 files changed, 8922 insertions, 2326 deletions
diff --git a/alpine/APKBUILD.in b/alpine/APKBUILD.in
index fef7a61ccc..fd3c02f47e 100644
--- a/alpine/APKBUILD.in
+++ b/alpine/APKBUILD.in
@@ -18,7 +18,8 @@ makedepends="ncurses-dev net-snmp-dev gawk texinfo perl
ncurses-libs ncurses-terminfo ncurses-terminfo-base patch pax-utils pcre2
perl pkgconf python3 python3-dev readline readline-dev sqlite-libs pcre2-dev
squashfs-tools sudo tar texinfo xorriso xz-libs py-pip rtrlib rtrlib-dev
- py3-sphinx elfutils elfutils-dev libyang-dev"
+ py3-sphinx elfutils elfutils-dev libyang-dev protobuf-c-compiler protobuf-c-dev
+ lua5.3-dev lua5.3"
checkdepends="pytest py-setuptools"
install="$pkgname.pre-install $pkgname.pre-deinstall $pkgname.post-deinstall"
subpackages="$pkgname-dev $pkgname-doc $pkgname-dbg"
@@ -47,7 +48,8 @@ build() {
--enable-vty-group=frrvty \
--enable-user=$_user \
--enable-group=$_user \
- --enable-pcre2posix
+ --enable-pcre2posix \
+ --enable-scripting
make -j $(nproc)
}
diff --git a/babeld/babeld.c b/babeld/babeld.c
index 4ce92c5204..f4c932971e 100644
--- a/babeld/babeld.c
+++ b/babeld/babeld.c
@@ -444,37 +444,39 @@ babel_fill_with_next_timeout(struct timeval *tv)
#if (defined NO_DEBUG)
#define printIfMin(a,b,c,d)
#else
-#define printIfMin(a,b,c,d) \
- if (UNLIKELY(debug & BABEL_DEBUG_TIMEOUT)) {printIfMin(a,b,c,d);}
-
- struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
- struct interface *ifp = NULL;
+#define printIfMin(a, b, c, d) \
+ if (unlikely(debug & BABEL_DEBUG_TIMEOUT)) { \
+ printIfMin(a, b, c, d); \
+ }
- *tv = check_neighbours_timeout;
- printIfMin(tv, 0, "check_neighbours_timeout", NULL);
- timeval_min_sec(tv, expiry_time);
- printIfMin(tv, 1, "expiry_time", NULL);
- timeval_min_sec(tv, source_expiry_time);
- printIfMin(tv, 1, "source_expiry_time", NULL);
- timeval_min(tv, &resend_time);
- printIfMin(tv, 1, "resend_time", NULL);
- FOR_ALL_INTERFACES(vrf, ifp) {
- babel_interface_nfo *babel_ifp = NULL;
- if(!if_up(ifp))
- continue;
- babel_ifp = babel_get_if_nfo(ifp);
- timeval_min(tv, &babel_ifp->flush_timeout);
- printIfMin(tv, 1, "flush_timeout", ifp->name);
- timeval_min(tv, &babel_ifp->hello_timeout);
- printIfMin(tv, 1, "hello_timeout", ifp->name);
- timeval_min(tv, &babel_ifp->update_timeout);
- printIfMin(tv, 1, "update_timeout", ifp->name);
- timeval_min(tv, &babel_ifp->update_flush_timeout);
- printIfMin(tv, 1, "update_flush_timeout",ifp->name);
- }
- timeval_min(tv, &unicast_flush_timeout);
- printIfMin(tv, 1, "unicast_flush_timeout", NULL);
- printIfMin(tv, 2, NULL, NULL);
+ struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
+ struct interface *ifp = NULL;
+
+ *tv = check_neighbours_timeout;
+ printIfMin(tv, 0, "check_neighbours_timeout", NULL);
+ timeval_min_sec(tv, expiry_time);
+ printIfMin(tv, 1, "expiry_time", NULL);
+ timeval_min_sec(tv, source_expiry_time);
+ printIfMin(tv, 1, "source_expiry_time", NULL);
+ timeval_min(tv, &resend_time);
+ printIfMin(tv, 1, "resend_time", NULL);
+ FOR_ALL_INTERFACES (vrf, ifp) {
+ babel_interface_nfo *babel_ifp = NULL;
+ if (!if_up(ifp))
+ continue;
+ babel_ifp = babel_get_if_nfo(ifp);
+ timeval_min(tv, &babel_ifp->flush_timeout);
+ printIfMin(tv, 1, "flush_timeout", ifp->name);
+ timeval_min(tv, &babel_ifp->hello_timeout);
+ printIfMin(tv, 1, "hello_timeout", ifp->name);
+ timeval_min(tv, &babel_ifp->update_timeout);
+ printIfMin(tv, 1, "update_timeout", ifp->name);
+ timeval_min(tv, &babel_ifp->update_flush_timeout);
+ printIfMin(tv, 1, "update_flush_timeout", ifp->name);
+ }
+ timeval_min(tv, &unicast_flush_timeout);
+ printIfMin(tv, 1, "unicast_flush_timeout", NULL);
+ printIfMin(tv, 2, NULL, NULL);
#undef printIfMin
#endif
}
diff --git a/babeld/babeld.h b/babeld/babeld.h
index 6c51af48a8..619550f651 100644
--- a/babeld/babeld.h
+++ b/babeld/babeld.h
@@ -26,12 +26,8 @@ Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
#if defined(__GNUC__) && (__GNUC__ >= 3)
#define ATTRIBUTE(x) __attribute__ (x)
-#define LIKELY(_x) __builtin_expect(!!(_x), 1)
-#define UNLIKELY(_x) __builtin_expect(!!(_x), 0)
#else
#define ATTRIBUTE(x) /**/
-#define LIKELY(_x) !!(_x)
-#define UNLIKELY(_x) !!(_x)
#endif
#if defined(__GNUC__) && (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 3)
diff --git a/babeld/util.h b/babeld/util.h
index 5e5843543a..8535d4dd6a 100644
--- a/babeld/util.h
+++ b/babeld/util.h
@@ -122,10 +122,11 @@ extern const unsigned char v4prefix[16];
#define BABEL_DEBUG_ROUTE (1 << 5)
#define BABEL_DEBUG_ALL (0xFFFF)
-#define debugf(level, ...) \
-do { \
-if(UNLIKELY(debug & level)) zlog_debug(__VA_ARGS__); \
-} while(0)
+#define debugf(level, ...) \
+ do { \
+ if (unlikely(debug & level)) \
+ zlog_debug(__VA_ARGS__); \
+ } while (0)
#endif /* NO_DEBUG */
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index c35e45275c..5b06bc3913 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -2927,9 +2927,21 @@ bgp_attr_psid_sub(uint8_t type, uint16_t length,
int srgb_count;
uint8_t sid_type, sid_flags;
+ /*
+ * Check that we actually have at least as much data as
+ * specified by the length field
+ */
+ if (STREAM_READABLE(peer->curr) < length) {
+ flog_err(
+ EC_BGP_ATTR_LEN,
+ "Prefix SID specifies length %hu, but only %zu bytes remain",
+ length, STREAM_READABLE(peer->curr));
+ return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+ args->total);
+ }
+
if (type == BGP_PREFIX_SID_LABEL_INDEX) {
- if (STREAM_READABLE(peer->curr) < length
- || length != BGP_PREFIX_SID_LABEL_INDEX_LENGTH) {
+ if (length != BGP_PREFIX_SID_LABEL_INDEX_LENGTH) {
flog_err(EC_BGP_ATTR_LEN,
"Prefix SID label index length is %hu instead of %u",
length, BGP_PREFIX_SID_LABEL_INDEX_LENGTH);
@@ -2951,12 +2963,8 @@ bgp_attr_psid_sub(uint8_t type, uint16_t length,
/* Store label index; subsequently, we'll check on
* address-family */
attr->label_index = label_index;
- }
-
- /* Placeholder code for the IPv6 SID type */
- else if (type == BGP_PREFIX_SID_IPV6) {
- if (STREAM_READABLE(peer->curr) < length
- || length != BGP_PREFIX_SID_IPV6_LENGTH) {
+ } else if (type == BGP_PREFIX_SID_IPV6) {
+ if (length != BGP_PREFIX_SID_IPV6_LENGTH) {
flog_err(EC_BGP_ATTR_LEN,
"Prefix SID IPv6 length is %hu instead of %u",
length, BGP_PREFIX_SID_IPV6_LENGTH);
@@ -2970,10 +2978,7 @@ bgp_attr_psid_sub(uint8_t type, uint16_t length,
stream_getw(peer->curr);
stream_get(&ipv6_sid, peer->curr, 16);
- }
-
- /* Placeholder code for the Originator SRGB type */
- else if (type == BGP_PREFIX_SID_ORIGINATOR_SRGB) {
+ } else if (type == BGP_PREFIX_SID_ORIGINATOR_SRGB) {
/*
* ietf-idr-bgp-prefix-sid-05:
* Length is the total length of the value portion of the
@@ -2999,19 +3004,6 @@ bgp_attr_psid_sub(uint8_t type, uint16_t length,
}
/*
- * Check that we actually have at least as much data as
- * specified by the length field
- */
- if (STREAM_READABLE(peer->curr) < length) {
- flog_err(EC_BGP_ATTR_LEN,
- "Prefix SID Originator SRGB specifies length %hu, but only %zu bytes remain",
- length, STREAM_READABLE(peer->curr));
- return bgp_attr_malformed(
- args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
- args->total);
- }
-
- /*
* Check that the portion of the TLV containing the sequence of
* SRGBs corresponds to a multiple of the SRGB size; to get
* that length, we skip the 16 bit flags field
@@ -3034,12 +3026,8 @@ bgp_attr_psid_sub(uint8_t type, uint16_t length,
stream_get(&srgb_base, peer->curr, 3);
stream_get(&srgb_range, peer->curr, 3);
}
- }
-
- /* Placeholder code for the VPN-SID Service type */
- else if (type == BGP_PREFIX_SID_VPN_SID) {
- if (STREAM_READABLE(peer->curr) < length
- || length != BGP_PREFIX_SID_VPN_SID_LENGTH) {
+ } else if (type == BGP_PREFIX_SID_VPN_SID) {
+ if (length != BGP_PREFIX_SID_VPN_SID_LENGTH) {
flog_err(EC_BGP_ATTR_LEN,
"Prefix SID VPN SID length is %hu instead of %u",
length, BGP_PREFIX_SID_VPN_SID_LENGTH);
@@ -3073,39 +3061,22 @@ bgp_attr_psid_sub(uint8_t type, uint16_t length,
attr->srv6_vpn->sid_flags = sid_flags;
sid_copy(&attr->srv6_vpn->sid, &ipv6_sid);
attr->srv6_vpn = srv6_vpn_intern(attr->srv6_vpn);
- }
-
- /* Placeholder code for the SRv6 L3 Service type */
- else if (type == BGP_PREFIX_SID_SRV6_L3_SERVICE) {
- if (STREAM_READABLE(peer->curr) < length) {
+ } else if (type == BGP_PREFIX_SID_SRV6_L3_SERVICE) {
+ if (STREAM_READABLE(peer->curr) < 1) {
flog_err(
EC_BGP_ATTR_LEN,
- "Prefix SID SRv6 L3-Service length is %hu, but only %zu bytes remain",
- length, STREAM_READABLE(peer->curr));
- return bgp_attr_malformed(args,
- BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
- args->total);
+ "Prefix SID SRV6 L3 Service not enough data left, it must be at least 1 byte");
+ return bgp_attr_malformed(
+ args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+ args->total);
}
-
/* ignore reserved */
stream_getc(peer->curr);
return bgp_attr_srv6_service(args);
}
-
/* Placeholder code for Unsupported TLV */
else {
-
- if (STREAM_READABLE(peer->curr) < length) {
- flog_err(
- EC_BGP_ATTR_LEN,
- "Prefix SID SRv6 length is %hu - too long, only %zu remaining in this UPDATE",
- length, STREAM_READABLE(peer->curr));
- return bgp_attr_malformed(
- args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
- args->total);
- }
-
if (bgp_debug_update(peer, NULL, NULL, 1))
zlog_debug(
"%s attr Prefix-SID sub-type=%u is not supported, skipped",
diff --git a/bgpd/bgp_bfd.c b/bgpd/bgp_bfd.c
index a51bcb1a1a..d1ddfd0460 100644
--- a/bgpd/bgp_bfd.c
+++ b/bgpd/bgp_bfd.c
@@ -55,7 +55,7 @@ static void bfd_session_status_update(struct bfd_session_params *bsp,
}
peer->last_reset = PEER_DOWN_BFD_DOWN;
- /* draft-ietf-idr-bfd-subcode */
+ /* rfc9384 */
if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_BFD_DOWN);
diff --git a/bgpd/bgp_bmp.c b/bgpd/bgp_bmp.c
index 73dbf4ab2b..baf164679c 100644
--- a/bgpd/bgp_bmp.c
+++ b/bgpd/bgp_bmp.c
@@ -389,13 +389,13 @@ static struct stream *bmp_peerstate(struct peer *peer, bool down)
/* Local Port, Remote Port */
if (peer->su_local->sa.sa_family == AF_INET6)
- stream_putw(s, peer->su_local->sin6.sin6_port);
+ stream_putw(s, htons(peer->su_local->sin6.sin6_port));
else if (peer->su_local->sa.sa_family == AF_INET)
- stream_putw(s, peer->su_local->sin.sin_port);
+ stream_putw(s, htons(peer->su_local->sin.sin_port));
if (peer->su_remote->sa.sa_family == AF_INET6)
- stream_putw(s, peer->su_remote->sin6.sin6_port);
+ stream_putw(s, htons(peer->su_remote->sin6.sin6_port));
else if (peer->su_remote->sa.sa_family == AF_INET)
- stream_putw(s, peer->su_remote->sin.sin_port);
+ stream_putw(s, htons(peer->su_remote->sin.sin_port));
static const uint8_t dummy_open[] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
diff --git a/bgpd/bgp_dump.c b/bgpd/bgp_dump.c
index c78e740ec9..fe77e7e250 100644
--- a/bgpd/bgp_dump.c
+++ b/bgpd/bgp_dump.c
@@ -845,8 +845,7 @@ void bgp_dump_init(void)
memset(&bgp_dump_routes, 0, sizeof(bgp_dump_routes));
bgp_dump_obuf =
- stream_new((BGP_STANDARD_MESSAGE_MAX_PACKET_SIZE * 2)
- + BGP_DUMP_MSG_HEADER + BGP_DUMP_HEADER_SIZE);
+ stream_new(BGP_MAX_PACKET_SIZE + BGP_MAX_PACKET_SIZE_OVERFLOW);
install_node(&bgp_dump_node);
diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c
index 541da9ecd6..dc1905868b 100644
--- a/bgpd/bgp_ecommunity.c
+++ b/bgpd/bgp_ecommunity.c
@@ -503,6 +503,8 @@ static const char *ecommunity_gettoken(const char *str,
uint8_t ecomm_type;
char buf[INET_ADDRSTRLEN + 1];
struct ecommunity_val *eval = (struct ecommunity_val *)eval_ptr;
+ uint64_t tmp_as = 0;
+
/* Skip white space. */
while (isspace((unsigned char)*p)) {
p++;
@@ -581,9 +583,18 @@ static const char *ecommunity_gettoken(const char *str,
goto error;
endptr++;
- as = strtoul(endptr, &endptr, 10);
- if (*endptr != '\0' || as == BGP_AS4_MAX)
+ errno = 0;
+ tmp_as = strtoul(endptr, &endptr, 10);
+ /* 'unsigned long' is a uint64 on 64-bit
+ * systems, and uint32 on 32-bit systems. So for
+ * 64-bit we can just directly check the value
+ * against BGP_AS4_MAX/UINT32_MAX, and for
+ * 32-bit we can check for errno (set to ERANGE
+ * upon overflow).
+ */
+ if (*endptr != '\0' || tmp_as == BGP_AS4_MAX || errno)
goto error;
+ as = (as_t)tmp_as;
memcpy(buf, p, (limit - p));
buf[limit - p] = '\0';
@@ -625,9 +636,19 @@ static const char *ecommunity_gettoken(const char *str,
goto error;
} else {
/* ASN */
- as = strtoul(buf, &endptr, 10);
- if (*endptr != '\0' || as == BGP_AS4_MAX)
+ errno = 0;
+ tmp_as = strtoul(buf, &endptr, 10);
+ /* 'unsigned long' is a uint64 on 64-bit
+ * systems, and uint32 on 32-bit systems. So for
+ * 64-bit we can just directly check the value
+ * against BGP_AS4_MAX/UINT32_MAX, and for
+ * 32-bit we can check for errno (set to ERANGE
+ * upon overflow).
+ */
+ if (*endptr != '\0' || tmp_as > BGP_AS4_MAX ||
+ errno)
goto error;
+ as = (as_t)tmp_as;
}
} else if (*p == '.') {
if (separator)
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index 78e96d130c..81117e94ef 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -5679,7 +5679,7 @@ void bgp_evpn_encode_prefix(struct stream *s, const struct prefix *p,
}
int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr,
- struct bgp_nlri *packet, int withdraw)
+ struct bgp_nlri *packet, bool withdraw)
{
uint8_t *pnt;
uint8_t *lim;
@@ -6235,6 +6235,14 @@ int bgp_evpn_local_l3vni_add(vni_t l3vni, vrf_id_t vrf_id,
l3vni);
return -1;
}
+
+ if (CHECK_FLAG(bgp_evpn->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
+ flog_err(EC_BGP_NO_DFLT,
+ "Cannot process L3VNI %u ADD - EVPN BGP instance is shutting down",
+ l3vni);
+ return -1;
+ }
+
as = bgp_evpn->as;
/* if the BGP vrf instance doesn't exist - create one */
@@ -6377,6 +6385,13 @@ int bgp_evpn_local_l3vni_del(vni_t l3vni, vrf_id_t vrf_id)
return -1;
}
+ if (CHECK_FLAG(bgp_evpn->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
+ flog_err(EC_BGP_NO_DFLT,
+ "Cannot process L3VNI %u ADD - EVPN BGP instance is shutting down",
+ l3vni);
+ return -1;
+ }
+
/* Remove remote routes from BGT VRF even if BGP_VRF_AUTO is configured,
* bgp_delete would not remove/decrement bgp_path_info of the ip_prefix
* routes. This will uninstalling the routes from zebra and decremnt the
diff --git a/bgpd/bgp_evpn.h b/bgpd/bgp_evpn.h
index 1dce4820d6..a034bfbd7e 100644
--- a/bgpd/bgp_evpn.h
+++ b/bgpd/bgp_evpn.h
@@ -150,7 +150,7 @@ extern void bgp_evpn_encode_prefix(struct stream *s, const struct prefix *p,
struct attr *attr, bool addpath_capable,
uint32_t addpath_tx_id);
extern int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr,
- struct bgp_nlri *packet, int withdraw);
+ struct bgp_nlri *packet, bool withdraw);
extern int bgp_evpn_import_route(struct bgp *bgp, afi_t afi, safi_t safi,
const struct prefix *p,
struct bgp_path_info *ri);
diff --git a/bgpd/bgp_evpn_mh.c b/bgpd/bgp_evpn_mh.c
index d821d4d582..200bcea70b 100644
--- a/bgpd/bgp_evpn_mh.c
+++ b/bgpd/bgp_evpn_mh.c
@@ -1071,7 +1071,8 @@ void update_type1_routes_for_evi(struct bgp *bgp, struct bgpevpn *vpn)
continue;
/* Update EAD-ES */
- bgp_evpn_ead_es_route_update(bgp, es);
+ if (bgp_evpn_local_es_is_active(es))
+ bgp_evpn_ead_es_route_update(bgp, es);
/* Update EAD-EVI */
if (CHECK_FLAG(es->flags, BGP_EVPNES_ADV_EVI)) {
diff --git a/bgpd/bgp_flowspec.c b/bgpd/bgp_flowspec.c
index f9debe43cd..70bdbaf035 100644
--- a/bgpd/bgp_flowspec.c
+++ b/bgpd/bgp_flowspec.c
@@ -82,7 +82,7 @@ static int bgp_fs_nlri_validate(uint8_t *nlri_content, uint32_t len,
}
int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr,
- struct bgp_nlri *packet, int withdraw)
+ struct bgp_nlri *packet, bool withdraw)
{
uint8_t *pnt;
uint8_t *lim;
@@ -98,6 +98,13 @@ int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr,
afi = packet->afi;
safi = packet->safi;
+ /*
+ * All other AFI/SAFI's treat no attribute as a implicit
+ * withdraw. Flowspec should as well.
+ */
+ if (!attr)
+ withdraw = true;
+
if (packet->length >= FLOWSPEC_NLRI_SIZELIMIT_EXTENDED) {
flog_err(EC_BGP_FLOWSPEC_PACKET,
"BGP flowspec nlri length maximum reached (%u)",
diff --git a/bgpd/bgp_flowspec.h b/bgpd/bgp_flowspec.h
index 58fc1775ab..bc2f00511e 100644
--- a/bgpd/bgp_flowspec.h
+++ b/bgpd/bgp_flowspec.h
@@ -15,7 +15,7 @@
#define BGP_FLOWSPEC_NLRI_STRING_MAX 512
extern int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr,
- struct bgp_nlri *packet, int withdraw);
+ struct bgp_nlri *packet, bool withdraw);
extern void bgp_flowspec_vty_init(void);
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index c08f95cdf4..63168f1e7a 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -1103,7 +1103,7 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
struct bgp_path_info *new;
struct bgp_path_info_extra *extra;
uint32_t num_sids = 0;
- void *parent = source_bpi;
+ struct bgp_path_info *parent = source_bpi;
if (new_attr->srv6_l3vpn || new_attr->srv6_vpn)
num_sids = 1;
@@ -1311,7 +1311,7 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
new->extra->parent = bgp_path_info_lock(parent);
bgp_dest_lock_node(
- (struct bgp_dest *)((struct bgp_path_info *)parent)->net);
+ (struct bgp_dest *)parent->net);
if (bgp_orig)
new->extra->bgp_orig = bgp_lock(bgp_orig);
if (nexthop_orig)
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index 1c76828a2f..9469a0778f 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -331,7 +331,7 @@ static void bgp_update_explicit_eors(struct peer *peer)
* calling safi function and for evpn, passed as parameter
*/
int bgp_nlri_parse(struct peer *peer, struct attr *attr,
- struct bgp_nlri *packet, int mp_withdraw)
+ struct bgp_nlri *packet, bool mp_withdraw)
{
switch (packet->safi) {
case SAFI_UNICAST:
diff --git a/bgpd/bgp_packet.h b/bgpd/bgp_packet.h
index c072bbc235..04bdb81849 100644
--- a/bgpd/bgp_packet.h
+++ b/bgpd/bgp_packet.h
@@ -42,26 +42,28 @@ DECLARE_HOOK(bgp_packet_send,
} while (0)
/* Packet send and receive function prototypes. */
-extern void bgp_keepalive_send(struct peer *);
-extern void bgp_open_send(struct peer *);
-extern void bgp_notify_send(struct peer *, uint8_t, uint8_t);
-extern void bgp_notify_send_with_data(struct peer *, uint8_t, uint8_t,
- uint8_t *, size_t);
+extern void bgp_keepalive_send(struct peer *peer);
+extern void bgp_open_send(struct peer *peer);
+extern void bgp_notify_send(struct peer *peer, uint8_t code, uint8_t sub_code);
+extern void bgp_notify_send_with_data(struct peer *peer, uint8_t code,
+ uint8_t sub_code, uint8_t *data,
+ size_t datalen);
void bgp_notify_io_invalid(struct peer *peer, uint8_t code, uint8_t sub_code,
uint8_t *data, size_t datalen);
extern void bgp_route_refresh_send(struct peer *peer, afi_t afi, safi_t safi,
uint8_t orf_type, uint8_t when_to_refresh,
int remove, uint8_t subtype);
-extern void bgp_capability_send(struct peer *, afi_t, safi_t, int, int);
+extern void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi,
+ int capabilty_code, int action);
-extern int bgp_capability_receive(struct peer *, bgp_size_t);
+extern int bgp_capability_receive(struct peer *peer, bgp_size_t length);
-extern int bgp_nlri_parse(struct peer *, struct attr *, struct bgp_nlri *,
- int mp_withdraw);
+extern int bgp_nlri_parse(struct peer *peer, struct attr *attr,
+ struct bgp_nlri *nlri, bool mp_withdraw);
-extern void bgp_update_restarted_peers(struct peer *);
-extern void bgp_update_implicit_eors(struct peer *);
-extern void bgp_check_update_delay(struct bgp *);
+extern void bgp_update_restarted_peers(struct peer *peer);
+extern void bgp_update_implicit_eors(struct peer *peer);
+extern void bgp_check_update_delay(struct bgp *peer);
extern int bgp_packet_set_marker(struct stream *s, uint8_t type);
extern void bgp_packet_set_size(struct stream *s);
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 4441e86fbb..a23bffd4ae 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -3838,6 +3838,12 @@ bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
(type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
: false;
+ /* If `bgp allow-martian-nexthop` is turned on, return next-hop
+ * as good.
+ */
+ if (bgp->allow_martian)
+ return false;
+
/*
* Only validated for unicast and multicast currently.
* Also valid for EVPN where the nexthop is an IP address.
@@ -8338,30 +8344,7 @@ static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
/* Unlock aggregate address configuration. */
bgp_dest_set_bgp_aggregate_info(dest, NULL);
- if (aggregate->community)
- community_free(&aggregate->community);
-
- hash_clean_and_free(&aggregate->community_hash,
- bgp_aggr_community_remove);
-
- if (aggregate->ecommunity)
- ecommunity_free(&aggregate->ecommunity);
-
- hash_clean_and_free(&aggregate->ecommunity_hash,
- bgp_aggr_ecommunity_remove);
-
- if (aggregate->lcommunity)
- lcommunity_free(&aggregate->lcommunity);
-
- hash_clean_and_free(&aggregate->lcommunity_hash,
- bgp_aggr_lcommunity_remove);
-
- if (aggregate->aspath)
- aspath_free(aggregate->aspath);
-
- hash_clean_and_free(&aggregate->aspath_hash, bgp_aggr_aspath_remove);
-
- bgp_aggregate_free(aggregate);
+ bgp_free_aggregate_info(aggregate);
bgp_dest_unlock_node(dest);
bgp_dest_unlock_node(dest);
@@ -8545,6 +8528,34 @@ DEFPY(aggregate_addressv4, aggregate_addressv4_cmd,
match_med != NULL, suppress_map);
}
+void bgp_free_aggregate_info(struct bgp_aggregate *aggregate)
+{
+ if (aggregate->community)
+ community_free(&aggregate->community);
+
+ hash_clean_and_free(&aggregate->community_hash,
+ bgp_aggr_community_remove);
+
+ if (aggregate->ecommunity)
+ ecommunity_free(&aggregate->ecommunity);
+
+ hash_clean_and_free(&aggregate->ecommunity_hash,
+ bgp_aggr_ecommunity_remove);
+
+ if (aggregate->lcommunity)
+ lcommunity_free(&aggregate->lcommunity);
+
+ hash_clean_and_free(&aggregate->lcommunity_hash,
+ bgp_aggr_lcommunity_remove);
+
+ if (aggregate->aspath)
+ aspath_free(aggregate->aspath);
+
+ hash_clean_and_free(&aggregate->aspath_hash, bgp_aggr_aspath_remove);
+
+ bgp_aggregate_free(aggregate);
+}
+
DEFPY(aggregate_addressv6, aggregate_addressv6_cmd,
"[no] aggregate-address X:X::X:X/M$prefix [{"
"as-set$as_set_s"
@@ -11592,9 +11603,28 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
vty_out(vty, ",\"%pFX\": ", dest_p);
}
+ /* This is used for 'json detail' vty keywords.
+ *
+ * In plain 'json' the per-prefix header is encoded
+ * as a standalone dictionary in the first json_paths
+ * array element:
+ * "<prefix>": [{header}, {path-1}, {path-N}]
+ * (which is confusing and borderline broken)
+ *
+ * For 'json detail' this changes the value
+ * of each prefix-key to be a dictionary where each
+ * header item has its own key, and json_paths is
+ * tucked under the "paths" key:
+ * "<prefix>": {
+ * "<header-key-1>": <header-val-1>,
+ * "<header-key-N>": <header-val-N>,
+ * "paths": [{path-1}, {path-N}]
+ * }
+ */
if (json_detail_header && json_paths != NULL) {
const struct prefix_rd *prd;
+ /* Start per-prefix dictionary */
vty_out(vty, "{\n");
prd = bgp_rd_from_dest(dest, safi);
@@ -11619,6 +11649,7 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
*/
vty_json_no_pretty(vty, json_paths);
+ /* End per-prefix dictionary */
if (json_detail_header_used)
vty_out(vty, "} ");
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index b48e8eda11..a64144b625 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -661,6 +661,7 @@ extern void bgp_process_queue_init(struct bgp *bgp);
extern void bgp_route_init(void);
extern void bgp_route_finish(void);
extern void bgp_cleanup_routes(struct bgp *);
+extern void bgp_free_aggregate_info(struct bgp_aggregate *aggregate);
extern void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi,
bool force);
extern void bgp_stop_announce_route_timer(struct peer_af *paf);
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index 4faf4a9f15..32ecb083be 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -461,7 +461,8 @@ route_match_ip_address(void *rule, const struct prefix *prefix, void *object)
if (prefix->family == AF_INET) {
alist = access_list_lookup(AFI_IP, (char *)rule);
if (alist == NULL) {
- if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))
+ if (unlikely(CHECK_FLAG(rmap_debug,
+ DEBUG_ROUTEMAP_DETAIL)))
zlog_debug(
"%s: Access-List Specified: %s does not exist defaulting to NO_MATCH",
__func__, (char *)rule);
@@ -521,7 +522,8 @@ route_match_ip_next_hop(void *rule, const struct prefix *prefix, void *object)
alist = access_list_lookup(AFI_IP, (char *)rule);
if (alist == NULL) {
- if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))
+ if (unlikely(CHECK_FLAG(rmap_debug,
+ DEBUG_ROUTEMAP_DETAIL)))
zlog_debug(
"%s: Access-List Specified: %s does not exist defaulting to NO_MATCH",
__func__, (char *)rule);
@@ -581,7 +583,8 @@ route_match_ip_route_source(void *rule, const struct prefix *pfx, void *object)
alist = access_list_lookup(AFI_IP, (char *)rule);
if (alist == NULL) {
- if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))
+ if (unlikely(CHECK_FLAG(rmap_debug,
+ DEBUG_ROUTEMAP_DETAIL)))
zlog_debug(
"%s: Access-List Specified: %s does not exist defaulting to NO_MATCH",
__func__, (char *)rule);
@@ -676,7 +679,7 @@ route_match_address_prefix_list(void *rule, afi_t afi,
plist = prefix_list_lookup(afi, (char *)rule);
if (plist == NULL) {
- if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))
+ if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)))
zlog_debug(
"%s: Prefix List %s specified does not exist defaulting to NO_MATCH",
__func__, (char *)rule);
@@ -737,7 +740,8 @@ route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix,
plist = prefix_list_lookup(AFI_IP, (char *)rule);
if (plist == NULL) {
- if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))
+ if (unlikely(CHECK_FLAG(rmap_debug,
+ DEBUG_ROUTEMAP_DETAIL)))
zlog_debug(
"%s: Prefix List %s specified does not exist defaulting to NO_MATCH",
__func__, (char *)rule);
@@ -786,7 +790,8 @@ route_match_ipv6_next_hop_prefix_list(void *rule, const struct prefix *prefix,
plist = prefix_list_lookup(AFI_IP6, (char *)rule);
if (!plist) {
- if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))
+ if (unlikely(CHECK_FLAG(rmap_debug,
+ DEBUG_ROUTEMAP_DETAIL)))
zlog_debug(
"%s: Prefix List %s specified does not exist defaulting to NO_MATCH",
__func__, (char *)rule);
@@ -891,7 +896,8 @@ route_match_ip_route_source_prefix_list(void *rule, const struct prefix *prefix,
plist = prefix_list_lookup(AFI_IP, (char *)rule);
if (plist == NULL) {
- if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))
+ if (unlikely(CHECK_FLAG(rmap_debug,
+ DEBUG_ROUTEMAP_DETAIL)))
zlog_debug(
"%s: Prefix List %s specified does not exist defaulting to NO_MATCH",
__func__, (char *)rule);
@@ -956,7 +962,7 @@ route_match_mac_address(void *rule, const struct prefix *prefix, void *object)
alist = access_list_lookup(AFI_L2VPN, (char *)rule);
if (alist == NULL) {
- if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))
+ if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)))
zlog_debug(
"%s: Access-List Specified: %s does not exist defaulting to NO_MATCH",
__func__, (char *)rule);
@@ -964,7 +970,7 @@ route_match_mac_address(void *rule, const struct prefix *prefix, void *object)
return RMAP_NOMATCH;
}
if (prefix->u.prefix_evpn.route_type != BGP_EVPN_MAC_IP_ROUTE) {
- if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))
+ if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)))
zlog_debug(
"%s: Prefix %pFX is not a EVPN MAC IP ROUTE defaulting to NO_MATCH",
__func__, prefix);
@@ -3242,7 +3248,8 @@ route_match_ipv6_address(void *rule, const struct prefix *prefix, void *object)
if (prefix->family == AF_INET6) {
alist = access_list_lookup(AFI_IP6, (char *)rule);
if (alist == NULL) {
- if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))
+ if (unlikely(CHECK_FLAG(rmap_debug,
+ DEBUG_ROUTEMAP_DETAIL)))
zlog_debug(
"%s: Access-List Specified: %s does not exist defaulting to NO_MATCH",
__func__, (char *)rule);
@@ -3299,7 +3306,8 @@ route_match_ipv6_next_hop(void *rule, const struct prefix *prefix, void *object)
alist = access_list_lookup(AFI_IP6, (char *)rule);
if (!alist) {
- if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))
+ if (unlikely(CHECK_FLAG(rmap_debug,
+ DEBUG_ROUTEMAP_DETAIL)))
zlog_debug(
"%s: Access-List Specified: %s does not exist defaulting to NO_MATCH",
__func__, (char *)rule);
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 4bbbced806..f7b0caf493 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -1675,28 +1675,46 @@ DEFUN (no_router_bgp,
for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, tmp_bgp)) {
if (tmp_bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
continue;
- if (CHECK_FLAG(tmp_bgp->af_flags[AFI_IP][SAFI_UNICAST],
- BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT) ||
- CHECK_FLAG(tmp_bgp->af_flags[AFI_IP6][SAFI_UNICAST],
- BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT) ||
- CHECK_FLAG(tmp_bgp->af_flags[AFI_IP][SAFI_UNICAST],
- BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT) ||
- CHECK_FLAG(tmp_bgp->af_flags[AFI_IP6][SAFI_UNICAST],
- BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT) ||
- CHECK_FLAG(tmp_bgp->af_flags[AFI_IP][SAFI_UNICAST],
+ if (CHECK_FLAG(
+ tmp_bgp->af_flags[AFI_IP]
+ [SAFI_UNICAST],
+ BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT) ||
+ CHECK_FLAG(
+ tmp_bgp->af_flags[AFI_IP6]
+ [SAFI_UNICAST],
+ BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT) ||
+ CHECK_FLAG(
+ tmp_bgp->af_flags[AFI_IP]
+ [SAFI_UNICAST],
+ BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT) ||
+ CHECK_FLAG(
+ tmp_bgp->af_flags[AFI_IP6]
+ [SAFI_UNICAST],
+ BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT) ||
+ CHECK_FLAG(tmp_bgp->af_flags[AFI_IP]
+ [SAFI_UNICAST],
BGP_CONFIG_VRF_TO_VRF_EXPORT) ||
- CHECK_FLAG(tmp_bgp->af_flags[AFI_IP6][SAFI_UNICAST],
+ CHECK_FLAG(tmp_bgp->af_flags[AFI_IP6]
+ [SAFI_UNICAST],
BGP_CONFIG_VRF_TO_VRF_EXPORT) ||
(bgp == bgp_get_evpn() &&
- (CHECK_FLAG(tmp_bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
- BGP_L2VPN_EVPN_ADV_IPV4_UNICAST) ||
- CHECK_FLAG(tmp_bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
- BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP) ||
- CHECK_FLAG(tmp_bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
- BGP_L2VPN_EVPN_ADV_IPV6_UNICAST) ||
- CHECK_FLAG(tmp_bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
- BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP))) ||
- (hashcount(tmp_bgp->vnihash))) {
+ (CHECK_FLAG(
+ tmp_bgp->af_flags[AFI_L2VPN]
+ [SAFI_EVPN],
+ BGP_L2VPN_EVPN_ADV_IPV4_UNICAST) ||
+ CHECK_FLAG(
+ tmp_bgp->af_flags[AFI_L2VPN]
+ [SAFI_EVPN],
+ BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP) ||
+ CHECK_FLAG(
+ tmp_bgp->af_flags[AFI_L2VPN]
+ [SAFI_EVPN],
+ BGP_L2VPN_EVPN_ADV_IPV6_UNICAST) ||
+ CHECK_FLAG(
+ tmp_bgp->af_flags[AFI_L2VPN]
+ [SAFI_EVPN],
+ BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP))) ||
+ (tmp_bgp->l3vni)) {
vty_out(vty,
"%% Cannot delete default BGP instance. Dependent VRF instances exist\n");
return CMD_WARNING_CONFIG_FAILED;
@@ -11036,10 +11054,10 @@ static char *bgp_peer_description_stripped(char *desc, uint32_t size)
{
static char stripped[BUFSIZ];
uint32_t i = 0;
- uint32_t last_space = 0;
+ uint32_t last_space = size;
while (i < size) {
- if (*(desc + i) == 0) {
+ if (*(desc + i) == '\0') {
stripped[i] = '\0';
return stripped;
}
@@ -11049,10 +11067,7 @@ static char *bgp_peer_description_stripped(char *desc, uint32_t size)
i++;
}
- if (last_space > size)
- stripped[size + 1] = '\0';
- else
- stripped[last_space] = '\0';
+ stripped[last_space] = '\0';
return stripped;
}
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 3d659d48d4..96b1f3e00f 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -834,6 +834,13 @@ bool bgp_zebra_nexthop_set(union sockunion *local, union sockunion *remote,
peer->bgp->vrf_id);
}
+ /* Handle peerings via loopbacks. For instance, peer between
+ * 127.0.0.1 and 127.0.0.2. In short, allow peering with self
+ * via 127.0.0.0/8.
+ */
+ if (!ifp && cmd_allow_reserved_ranges_get())
+ ifp = if_get_vrf_loopback(peer->bgp->vrf_id);
+
if (!ifp) {
/*
* BGP views do not currently get proper data
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 97238bc38b..9d7a1f967e 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -3844,6 +3844,23 @@ int bgp_delete(struct bgp *bgp)
#ifdef ENABLE_BGP_VNC
rfapi_delete(bgp);
#endif
+
+ /* Free memory allocated with aggregate address configuration. */
+ FOREACH_AFI_SAFI (afi, safi) {
+ struct bgp_aggregate *aggregate = NULL;
+
+ for (struct bgp_dest *dest =
+ bgp_table_top(bgp->aggregate[afi][safi]);
+ dest; dest = bgp_route_next(dest)) {
+ aggregate = bgp_dest_get_bgp_aggregate_info(dest);
+ if (aggregate == NULL)
+ continue;
+
+ bgp_dest_set_bgp_aggregate_info(dest, NULL);
+ bgp_free_aggregate_info(aggregate);
+ }
+ }
+
bgp_cleanup_routes(bgp);
for (afi = 0; afi < AFI_MAX; ++afi) {
diff --git a/configure.ac b/configure.ac
index f3968df2aa..79288c67e9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -299,14 +299,20 @@ if test "$enable_scripting" = "yes"; then
AX_LUA_HEADERS([], [
AC_MSG_ERROR([Lua 5.3 headers are required to build with Lua support. No other version is supported.])
])
- AX_LUA_LIBS([
+ PKG_CHECK_MODULES([LUA], [lua5.3], [
AC_DEFINE([HAVE_SCRIPTING], [1], [Have support for scripting])
- LIBS="$LIBS $LUA_LIB"
+ LIBS="$LIBS $LUA_LIBS"
SCRIPTING=true
], [
- SCRIPTING=false
- AC_MSG_ERROR([Lua 5.3 libraries are required to build with Lua support. No other version is supported.])
- ])
+ AX_LUA_LIBS([
+ AC_DEFINE([HAVE_SCRIPTING], [1], [Have support for scripting])
+ LIBS="$LIBS $LUA_LIB"
+ SCRIPTING=true
+ ], [
+ SCRIPTING=false
+ AC_MSG_ERROR([Lua 5.3 libraries are required to build with Lua support. No other version is supported.])
+ ])
+ ])
fi
dnl the following flags go in CFLAGS rather than AC_CFLAGS since they make
diff --git a/doc/developer/logging.rst b/doc/developer/logging.rst
index b7021b69a1..2fe0a5989b 100644
--- a/doc/developer/logging.rst
+++ b/doc/developer/logging.rst
@@ -502,6 +502,51 @@ General utility formats
representation for a hexdump. Non-printable characters are replaced with
a dot.
+.. frrfmt:: %pIS (struct iso_address *)
+
+ ([IS]o Network address) - Format ISO Network Address
+
+ ``%pIS``: :frrfmtout:`01.0203.04O5`
+ ISO Network address is printed as separated byte. The number of byte of the
+ address is embeded in the `iso_net` structure.
+
+ ``%pISl``: :frrfmtout:`01.0203.04O5.0607.0809.1011.1213.14` - long format to
+ print the long version of the ISO Network address which include the System
+ ID and the PSEUDO-ID of the IS-IS system
+
+ Note that the `ISO_ADDR_STRLEN` define gives the total size of the string
+ that could be used in conjunction to snprintfrr. Use like::
+
+ char buf[ISO_ADDR_STRLEN];
+ struct iso_net addr = {.len = 4, .addr = {1, 2, 3, 4}};
+ snprintfrr(buf, ISO_ADDR_STRLEN, "%pIS", &addr);
+
+.. frrfmt:: %pSY (uint8_t *)
+
+ (IS-IS [SY]stem ID) - Format IS-IS System ID
+
+ ``%pSY``: :frrfmtout:`0102.0304.0506`
+
+.. frrfmt:: %pPN (uint8_t *)
+
+ (IS-IS [P]seudo [N]ode System ID) - Format IS-IS Pseudo Node System ID
+
+ ``%pPN``: :frrfmtout:`0102.0304.0506.07`
+
+.. frrfmt:: %pLS (uint8_t *)
+
+ (IS-IS [L]sp fragment [S]ystem ID) - Format IS-IS Pseudo System ID
+
+ ``%pLS``: :frrfmtout:`0102.0304.0506.07-08`
+
+ Note that the `ISO_SYSID_STRLEN` define gives the total size of the string
+ that could be used in conjunction to snprintfrr. Use like::
+
+ char buf[ISO_SYSID_STRLEN];
+ uint8_t id[8] = {1, 2, 3, 4 , 5 , 6 , 7, 8};
+ snprintfrr(buf, SYS_ID_SIZE, "%pSY", id);
+
+
Integer formats
^^^^^^^^^^^^^^^
diff --git a/doc/user/basic.rst b/doc/user/basic.rst
index 254dad8303..337cfff937 100644
--- a/doc/user/basic.rst
+++ b/doc/user/basic.rst
@@ -349,6 +349,10 @@ Basic Config Commands
Allow using IPv4 reserved (Class E) IP ranges for daemons. E.g.: setting
IPv4 addresses for interfaces or allowing reserved ranges in BGP next-hops.
+ If you need multiple FRR instances (or FRR + any other daemon) running in a
+ single router and peering via 127.0.0.0/8, it's also possible to use this
+ knob if turned on.
+
Default: off.
.. _sample-config-file:
diff --git a/doc/user/ospfd.rst b/doc/user/ospfd.rst
index 30d55f34a7..a99785204b 100644
--- a/doc/user/ospfd.rst
+++ b/doc/user/ospfd.rst
@@ -310,6 +310,11 @@ To start OSPF process you have to specify the OSPF router.
of packets to process before returning. The defult value of this parameter
is 20.
+.. clicmd:: socket buffer <send | recv | all> (1-4000000000)
+
+ This command controls the ospf instance's socket buffer sizes. The
+ 'no' form resets one or both values to the default.
+
.. _ospf-area:
Areas
@@ -325,7 +330,6 @@ Areas
announced to other areas. This command can be used only in ABR and ONLY
router-LSAs (Type-1) and network-LSAs (Type-2) (i.e. LSAs with scope area) can
be summarized. Type-5 AS-external-LSAs can't be summarized - their scope is AS.
- Summarizing Type-7 AS-external-LSAs isn't supported yet by FRR.
.. code-block:: frr
@@ -431,6 +435,31 @@ Areas
configured not to advertise forwarding addresses into the backbone to direct
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 nssa range A.B.C.D/M [<not-advertise|cost (0-16777215)>]
+
+.. clicmd:: area (0-4294967295) nssa range A.B.C.D/M [<not-advertise|cost (0-16777215)>]
+
+ Summarize a group of external subnets into a single Type-7 LSA, which is
+ then translated to a Type-5 LSA and avertised to the backbone.
+ This command can only be used at the area boundary (NSSA ABR router).
+
+ By default, the metric of the summary route is calculated as the highest
+ metric among the summarized routes. The `cost` option, however, can be used
+ to set an explicit metric.
+
+ The `not-advertise` option, when present, prevents the summary route from
+ being advertised, effectively filtering the summarized routes.
+
.. clicmd:: area A.B.C.D default-cost (0-16777215)
diff --git a/doc/user/overview.rst b/doc/user/overview.rst
index 4a24fa52be..5ea33d62c9 100644
--- a/doc/user/overview.rst
+++ b/doc/user/overview.rst
@@ -424,6 +424,8 @@ BGP
:t:`Extended Optional Parameters Length for BGP OPEN Message. E. Chen, J. Scudder. July 2021.`
- :rfc:`9234`
:t:`Route Leak Prevention and Detection Using Roles in UPDATE and OPEN Messages. A. Azimov, E. Bogomazov, R. Bush, K. Patel, K. Sriram. May 2022.`
+- :rfc:`9384`
+ :t:`A BGP Cease NOTIFICATION Subcode for Bidirectional Forwarding Detection (BFD). J. Haas. March 2023.`
OSPF
----
diff --git a/isisd/fabricd.c b/isisd/fabricd.c
index 4fd39498a0..0be36e175a 100644
--- a/isisd/fabricd.c
+++ b/isisd/fabricd.c
@@ -273,8 +273,8 @@ void fabricd_initial_sync_hello(struct isis_circuit *circuit)
if (IS_DEBUG_ADJ_PACKETS)
zlog_debug(
- "OpenFabric: Started initial synchronization with %s on %s",
- sysid_print(circuit->u.p2p.neighbor->sysid),
+ "OpenFabric: Started initial synchronization with %pSY on %s",
+ circuit->u.p2p.neighbor->sysid,
circuit->interface->name);
}
@@ -359,7 +359,9 @@ static uint8_t fabricd_calculate_fabric_tier(struct isis_area *area)
return ISIS_TIER_UNDEFINED;
}
- zlog_info("OpenFabric: Found %s as furthest t0 from local system, dist == %u", rawlspid_print(furthest_t0->N.id), furthest_t0->d_N);
+ zlog_info(
+ "OpenFabric: Found %pLS as furthest t0 from local system, dist == %u",
+ furthest_t0->N.id, furthest_t0->d_N);
struct isis_spftree *remote_tree =
isis_run_hopcount_spf(area, furthest_t0->N.id, NULL);
@@ -372,8 +374,9 @@ static uint8_t fabricd_calculate_fabric_tier(struct isis_area *area)
isis_spftree_del(remote_tree);
return ISIS_TIER_UNDEFINED;
} else {
- zlog_info("OpenFabric: Found %s as furthest from remote dist == %u", rawlspid_print(furthest_from_remote->N.id),
- furthest_from_remote->d_N);
+ zlog_info(
+ "OpenFabric: Found %pLS as furthest from remote dist == %u",
+ furthest_from_remote->N.id, furthest_from_remote->d_N);
}
int64_t tier = furthest_from_remote->d_N - furthest_t0->d_N;
diff --git a/isisd/isis_adjacency.c b/isisd/isis_adjacency.c
index 1871078cc1..30b71537e0 100644
--- a/isisd/isis_adjacency.c
+++ b/isisd/isis_adjacency.c
@@ -283,6 +283,8 @@ void isis_adj_process_threeway(struct isis_adjacency *adj,
}
const char *isis_adj_name(const struct isis_adjacency *adj)
{
+ static char buf[ISO_SYSID_STRLEN];
+
if (!adj)
return "NONE";
@@ -291,8 +293,9 @@ const char *isis_adj_name(const struct isis_adjacency *adj)
dyn = dynhn_find_by_id(adj->circuit->isis, adj->sysid);
if (dyn)
return dyn->hostname;
- else
- return sysid_print(adj->sysid);
+
+ snprintfrr(buf, sizeof(buf), "%pSY", adj->sysid);
+ return buf;
}
void isis_log_adj_change(struct isis_adjacency *adj,
enum isis_adj_state old_state,
@@ -439,9 +442,8 @@ void isis_adj_print(struct isis_adjacency *adj)
if (dyn)
zlog_debug("%s", dyn->hostname);
- zlog_debug("SystemId %20s SNPA %s, level %d; Holding Time %d",
- sysid_print(adj->sysid), snpa_print(adj->snpa), adj->level,
- adj->hold_time);
+ zlog_debug("SystemId %20pSY SNPA %pSY, level %d; Holding Time %d",
+ adj->sysid, adj->snpa, adj->level, adj->hold_time);
if (adj->ipv4_address_count) {
zlog_debug("IPv4 Address(es):");
for (unsigned int i = 0; i < adj->ipv4_address_count; i++)
@@ -530,7 +532,7 @@ void isis_adj_print_json(struct isis_adjacency *adj, struct json_object *json,
time2string(adj->last_upd +
adj->hold_time - now));
}
- json_object_string_add(json, "snpa", snpa_print(adj->snpa));
+ json_object_string_addf(json, "snpa", "%pSY", adj->snpa);
}
if (detail == ISIS_UI_LEVEL_DETAIL) {
@@ -581,8 +583,7 @@ void isis_adj_print_json(struct isis_adjacency *adj, struct json_object *json,
isis_mtid2str(adj->mt_set[i]));
}
}
- json_object_string_add(iface_json, "snpa",
- snpa_print(adj->snpa));
+ json_object_string_addf(iface_json, "snpa", "%pSY", adj->snpa);
if (adj->circuit &&
(adj->circuit->circ_type == CIRCUIT_T_BROADCAST)) {
dyn = dynhn_find_by_id(adj->circuit->isis, adj->lanid);
@@ -593,11 +594,8 @@ void isis_adj_print_json(struct isis_adjacency *adj, struct json_object *json,
json_object_string_add(iface_json, "lan-id",
buf);
} else {
- snprintfrr(buf, sizeof(buf), "%s-%02x",
- sysid_print(adj->lanid),
- adj->lanid[ISIS_SYS_ID_LEN]);
- json_object_string_add(iface_json, "lan-id",
- buf);
+ json_object_string_addf(iface_json, "lan-id",
+ "%pSY", adj->lanid);
}
json_object_int_add(iface_json, "lan-prio",
@@ -626,12 +624,9 @@ void isis_adj_print_json(struct isis_adjacency *adj, struct json_object *json,
area_addr_json);
for (unsigned int i = 0; i < adj->area_address_count;
i++) {
- json_object_string_add(
- area_addr_json, "isonet",
- isonet_print(adj->area_addresses[i]
- .area_addr,
- adj->area_addresses[i]
- .addr_len));
+ json_object_string_addf(
+ area_addr_json, "isonet", "%pIS",
+ &adj->area_addresses[i]);
}
}
if (adj->ipv4_address_count) {
@@ -736,7 +731,7 @@ void isis_adj_print_vty(struct isis_adjacency *adj, struct vty *vty,
+ adj->hold_time - now);
} else
vty_out(vty, "- ");
- vty_out(vty, "%-10s", snpa_print(adj->snpa));
+ vty_out(vty, "%-10pSY", adj->snpa);
vty_out(vty, "\n");
}
@@ -780,7 +775,7 @@ void isis_adj_print_vty(struct isis_adjacency *adj, struct vty *vty,
vty_out(vty, " %s\n",
isis_mtid2str(adj->mt_set[i]));
}
- vty_out(vty, " SNPA: %s", snpa_print(adj->snpa));
+ vty_out(vty, " SNPA: %pSY", adj->snpa);
if (adj->circuit
&& (adj->circuit->circ_type == CIRCUIT_T_BROADCAST)) {
dyn = dynhn_find_by_id(adj->circuit->isis, adj->lanid);
@@ -788,9 +783,7 @@ void isis_adj_print_vty(struct isis_adjacency *adj, struct vty *vty,
vty_out(vty, ", LAN id: %s.%02x", dyn->hostname,
adj->lanid[ISIS_SYS_ID_LEN]);
else
- vty_out(vty, ", LAN id: %s.%02x",
- sysid_print(adj->lanid),
- adj->lanid[ISIS_SYS_ID_LEN]);
+ vty_out(vty, ", LAN id: %pPN", adj->lanid);
vty_out(vty, "\n");
vty_out(vty, " LAN Priority: %u",
@@ -811,11 +804,8 @@ void isis_adj_print_vty(struct isis_adjacency *adj, struct vty *vty,
vty_out(vty, " Area Address(es):\n");
for (unsigned int i = 0; i < adj->area_address_count;
i++) {
- vty_out(vty, " %s\n",
- isonet_print(adj->area_addresses[i]
- .area_addr,
- adj->area_addresses[i]
- .addr_len));
+ vty_out(vty, " %pIS\n",
+ &adj->area_addresses[i]);
}
}
if (adj->ipv4_address_count) {
diff --git a/isisd/isis_adjacency.h b/isisd/isis_adjacency.h
index f02f7a68ea..c0c8e68145 100644
--- a/isisd/isis_adjacency.h
+++ b/isisd/isis_adjacency.h
@@ -69,7 +69,7 @@ struct isis_adjacency {
struct isis_dis_record dis_record[DIS_RECORDS * ISIS_LEVELS];
enum isis_adj_state adj_state; /* adjacencyState */
enum isis_adj_usage adj_usage; /* adjacencyUsage */
- struct area_addr *area_addresses; /* areaAdressesOfNeighbour */
+ struct iso_address *area_addresses; /* areaAdressesOfNeighbour */
unsigned int area_address_count;
struct nlpids nlpids; /* protocols spoken ... */
struct in_addr *ipv4_addresses;
diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c
index 124dcdd86d..feab451233 100644
--- a/isisd/isis_circuit.c
+++ b/isisd/isis_circuit.c
@@ -286,8 +286,7 @@ void isis_circuit_add_addr(struct isis_circuit *circuit,
if (connected->address->family == AF_INET) {
uint32_t addr = connected->address->u.prefix4.s_addr;
addr = ntohl(addr);
- if (IPV4_NET0(addr) || IPV4_NET127(addr) || IN_CLASSD(addr)
- || IPV4_LINKLOCAL(addr))
+ if (IPV4_NET0(addr) || IPV4_NET127(addr) || IN_CLASSD(addr))
return;
for (ALL_LIST_ELEMENTS_RO(circuit->ip_addrs, node, ipv4))
@@ -696,10 +695,9 @@ int isis_circuit_up(struct isis_circuit *circuit)
}
#ifdef EXTREME_DEGUG
if (IS_DEBUG_EVENTS)
- zlog_debug("%s: if_id %d, isomtu %d snpa %s", __func__,
- circuit->interface->ifindex,
- ISO_MTU(circuit),
- snpa_print(circuit->u.bc.snpa));
+ zlog_debug("%s: if_id %d, isomtu %d snpa %pSY",
+ __func__, circuit->interface->ifindex,
+ ISO_MTU(circuit), circuit->u.bc.snpa);
#endif /* EXTREME_DEBUG */
circuit->u.bc.adjdb[0] = list_new();
@@ -996,8 +994,8 @@ void isis_circuit_print_json(struct isis_circuit *circuit,
json_object_string_add(iface_json, "level",
circuit_t2string(circuit->is_type));
if (circuit->circ_type == CIRCUIT_T_BROADCAST)
- json_object_string_add(iface_json, "snpa",
- snpa_print(circuit->u.bc.snpa));
+ json_object_string_addf(iface_json, "snpa", "%pSY",
+ circuit->u.bc.snpa);
levels_json = json_object_new_array();
@@ -1123,8 +1121,7 @@ void isis_circuit_print_vty(struct isis_circuit *circuit, struct vty *vty,
circuit_type2string(circuit->circ_type));
vty_out(vty, ", Level: %s", circuit_t2string(circuit->is_type));
if (circuit->circ_type == CIRCUIT_T_BROADCAST)
- vty_out(vty, ", SNPA: %-10s",
- snpa_print(circuit->u.bc.snpa));
+ vty_out(vty, ", SNPA: %-10pSY", circuit->u.bc.snpa);
vty_out(vty, "\n");
if (circuit->is_type & IS_LEVEL_1) {
vty_out(vty, " Level-1 Information:\n");
diff --git a/isisd/isis_common.h b/isisd/isis_common.h
index c908dc2e24..2ded68f84d 100644
--- a/isisd/isis_common.h
+++ b/isisd/isis_common.h
@@ -11,14 +11,6 @@
#ifndef ISIS_COMMON_H
#define ISIS_COMMON_H
-/*
- * Area Address
- */
-struct area_addr {
- uint8_t addr_len;
- uint8_t area_addr[20];
-};
-
struct isis_passwd {
uint8_t len;
#define ISIS_PASSWD_TYPE_UNUSED 0
diff --git a/isisd/isis_dynhn.c b/isisd/isis_dynhn.c
index 446e522019..61c49d08a7 100644
--- a/isisd/isis_dynhn.c
+++ b/isisd/isis_dynhn.c
@@ -145,12 +145,10 @@ void dynhn_print_all(struct vty *vty, struct isis *isis)
vty_out(vty, "Level System ID Dynamic Hostname\n");
for (ALL_LIST_ELEMENTS_RO(isis->dyn_cache, node, dyn)) {
vty_out(vty, "%-7d", dyn->level);
- vty_out(vty, "%-15s%-15s\n", sysid_print(dyn->id),
- dyn->hostname);
+ vty_out(vty, "%pSY %-15s\n", dyn->id, dyn->hostname);
}
- vty_out(vty, " * %s %s\n", sysid_print(isis->sysid),
- cmd_hostname_get());
+ vty_out(vty, " * %pSY %s\n", isis->sysid, cmd_hostname_get());
return;
}
diff --git a/isisd/isis_events.c b/isisd/isis_events.c
index 8a2a2ab971..32231a079f 100644
--- a/isisd/isis_events.c
+++ b/isisd/isis_events.c
@@ -217,8 +217,8 @@ void isis_event_auth_failure(char *area_tag, const char *error_string,
uint8_t *sysid)
{
if (IS_DEBUG_EVENTS)
- zlog_debug("ISIS-Evt (%s) Authentication failure %s from %s",
- area_tag, error_string, sysid_print(sysid));
+ zlog_debug("ISIS-Evt (%s) Authentication failure %s from %pSY",
+ area_tag, error_string, sysid);
return;
}
diff --git a/isisd/isis_lfa.c b/isisd/isis_lfa.c
index 7a25a92535..abb6168393 100644
--- a/isisd/isis_lfa.c
+++ b/isisd/isis_lfa.c
@@ -1466,8 +1466,8 @@ int isis_rlfa_activate(struct isis_spftree *spftree, struct rlfa *rlfa,
if (ldp_label == MPLS_INVALID_LABEL) {
if (IS_DEBUG_LFA)
zlog_debug(
- "ISIS-LFA: failed to activate RLFA: missing LDP label to reach PQ node through %s",
- sysid_print(vadj->sadj->id));
+ "ISIS-LFA: failed to activate RLFA: missing LDP label to reach PQ node through %pSY",
+ vadj->sadj->id);
return -1;
}
diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c
index d569f6bd5b..fb69448d04 100644
--- a/isisd/isis_lsp.c
+++ b/isisd/isis_lsp.c
@@ -193,10 +193,9 @@ int lsp_compare(char *areatag, struct isis_lsp *lsp, uint32_t seqno,
|| (lsp->hdr.rem_lifetime != 0 && rem_lifetime != 0))) {
if (IS_DEBUG_SNP_PACKETS) {
zlog_debug(
- "ISIS-Snp (%s): Compare LSP %s seq 0x%08x, cksum 0x%04hx, lifetime %hus",
- areatag, rawlspid_print(lsp->hdr.lsp_id),
- lsp->hdr.seqno, lsp->hdr.checksum,
- lsp->hdr.rem_lifetime);
+ "ISIS-Snp (%s): Compare LSP %pLS seq 0x%08x, cksum 0x%04hx, lifetime %hus",
+ areatag, lsp->hdr.lsp_id, lsp->hdr.seqno,
+ lsp->hdr.checksum, lsp->hdr.rem_lifetime);
zlog_debug(
"ISIS-Snp (%s): is equal to ours seq 0x%08x, cksum 0x%04hx, lifetime %hus",
areatag, seqno, checksum, rem_lifetime);
@@ -223,9 +222,9 @@ int lsp_compare(char *areatag, struct isis_lsp *lsp, uint32_t seqno,
&& lsp->hdr.rem_lifetime)))) {
if (IS_DEBUG_SNP_PACKETS) {
zlog_debug(
- "ISIS-Snp (%s): Compare LSP %s seq 0x%08x, cksum 0x%04hx, lifetime %hus",
- areatag, rawlspid_print(lsp->hdr.lsp_id), seqno,
- checksum, rem_lifetime);
+ "ISIS-Snp (%s): Compare LSP %pLS seq 0x%08x, cksum 0x%04hx, lifetime %hus",
+ areatag, lsp->hdr.lsp_id, seqno, checksum,
+ rem_lifetime);
zlog_debug(
"ISIS-Snp (%s): is newer than ours seq 0x%08x, cksum 0x%04hx, lifetime %hus",
areatag, lsp->hdr.seqno, lsp->hdr.checksum,
@@ -234,9 +233,10 @@ int lsp_compare(char *areatag, struct isis_lsp *lsp, uint32_t seqno,
return LSP_NEWER;
}
if (IS_DEBUG_SNP_PACKETS) {
- zlog_debug("ISIS-Snp (%s): Compare LSP %s seq 0x%08x, cksum 0x%04hx, lifetime %hus",
- areatag, rawlspid_print(lsp->hdr.lsp_id), seqno,
- checksum, rem_lifetime);
+ zlog_debug(
+ "ISIS-Snp (%s): Compare LSP %pLS seq 0x%08x, cksum 0x%04hx, lifetime %hus",
+ areatag, lsp->hdr.lsp_id, seqno, checksum,
+ rem_lifetime);
zlog_debug(
"ISIS-Snp (%s): is older than ours seq 0x%08x, cksum 0x%04hx, lifetime %hus",
areatag, lsp->hdr.seqno, lsp->hdr.checksum,
@@ -554,8 +554,8 @@ void lsp_update(struct isis_lsp *lsp, struct isis_lsp_hdr *hdr,
if (lsp->own_lsp) {
flog_err(
EC_LIB_DEVELOPMENT,
- "ISIS-Upd (%s): BUG updating LSP %s still marked as own LSP",
- area->area_tag, rawlspid_print(lsp->hdr.lsp_id));
+ "ISIS-Upd (%s): BUG updating LSP %pLS still marked as own LSP",
+ area->area_tag, lsp->hdr.lsp_id);
lsp_clear_data(lsp);
lsp->own_lsp = 0;
}
@@ -634,10 +634,8 @@ struct isis_lsp *lsp_new(struct isis_area *area, uint8_t *lsp_id,
put_lsp_hdr(lsp, NULL, false);
if (IS_DEBUG_EVENTS)
- zlog_debug("New LSP with ID %s-%02x-%02x len %d seqnum %08x",
- sysid_print(lsp_id), LSP_PSEUDO_ID(lsp->hdr.lsp_id),
- LSP_FRAGMENT(lsp->hdr.lsp_id), lsp->hdr.pdu_len,
- lsp->hdr.seqno);
+ zlog_debug("New LSP with ID %pLS len %d seqnum %08x", lsp_id,
+ lsp->hdr.pdu_len, lsp->hdr.seqno);
return lsp;
}
@@ -704,7 +702,7 @@ void lspid_print(uint8_t *lsp_id, char *dest, size_t dest_len, char dynhost,
else if (!memcmp(isis->sysid, lsp_id, ISIS_SYS_ID_LEN) && dynhost)
snprintf(id, sizeof(id), "%.14s", cmd_hostname_get());
else
- memcpy(id, sysid_print(lsp_id), 15);
+ snprintf(id, sizeof(id), "%pSY", lsp_id);
if (frag)
snprintf(dest, dest_len, "%s.%02x-%02x", id,
@@ -1250,10 +1248,8 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area)
if (LSP_PSEUDO_ID(ne_id)) {
if (area->oldmetric) {
lsp_debug(
- "ISIS (%s): Adding DIS %s.%02x as old-style neighbor",
- area->area_tag,
- sysid_print(ne_id),
- LSP_PSEUDO_ID(ne_id));
+ "ISIS (%s): Adding DIS %pPN as old-style neighbor",
+ area->area_tag, ne_id);
isis_tlvs_add_oldstyle_reach(
lsp->tlvs, ne_id,
metric);
@@ -1279,9 +1275,8 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area)
if (area->oldmetric) {
lsp_debug(
- "ISIS (%s): Adding old-style is reach for %s",
- area->area_tag,
- sysid_print(ne_id));
+ "ISIS (%s): Adding old-style is reach for %pSY",
+ area->area_tag, ne_id);
isis_tlvs_add_oldstyle_reach(
lsp->tlvs, ne_id, metric);
}
@@ -1424,12 +1419,12 @@ int lsp_generate(struct isis_area *area, int level)
refresh_time, &area->t_lsp_refresh[level - 1]);
if (IS_DEBUG_UPDATE_PACKETS) {
- zlog_debug("ISIS-Upd (%s): Building L%d LSP %s, len %hu, seq 0x%08x, cksum 0x%04hx, lifetime %hus refresh %hus",
- area->area_tag, level,
- rawlspid_print(newlsp->hdr.lsp_id),
- newlsp->hdr.pdu_len, newlsp->hdr.seqno,
- newlsp->hdr.checksum, newlsp->hdr.rem_lifetime,
- refresh_time);
+ zlog_debug(
+ "ISIS-Upd (%s): Building L%d LSP %pLS, len %hu, seq 0x%08x, cksum 0x%04hx, lifetime %hus refresh %hus",
+ area->area_tag, level, newlsp->hdr.lsp_id,
+ newlsp->hdr.pdu_len, newlsp->hdr.seqno,
+ newlsp->hdr.checksum, newlsp->hdr.rem_lifetime,
+ refresh_time);
}
sched_debug(
"ISIS (%s): Built L%d LSP. Set triggered regenerate to non-pending.",
@@ -1506,8 +1501,8 @@ static int lsp_regenerate(struct isis_area *area, int level)
if (IS_DEBUG_UPDATE_PACKETS) {
zlog_debug(
- "ISIS-Upd (%s): Refreshed our L%d LSP %s, len %hu, seq 0x%08x, cksum 0x%04hx, lifetime %hus refresh %hus",
- area->area_tag, level, rawlspid_print(lsp->hdr.lsp_id),
+ "ISIS-Upd (%s): Refreshed our L%d LSP %pLS, len %hu, seq 0x%08x, cksum 0x%04hx, lifetime %hus refresh %hus",
+ area->area_tag, level, lsp->hdr.lsp_id,
lsp->hdr.pdu_len, lsp->hdr.seqno, lsp->hdr.checksum,
lsp->hdr.rem_lifetime, refresh_time);
}
@@ -1698,9 +1693,9 @@ static void lsp_build_pseudo(struct isis_lsp *lsp, struct isis_circuit *circuit,
lsp_clear_data(lsp);
lsp->tlvs = isis_alloc_tlvs();
lsp_debug(
- "ISIS (%s): Constructing pseudo LSP %s for interface %s level %d",
- area->area_tag, rawlspid_print(lsp->hdr.lsp_id),
- circuit->interface->name, level);
+ "ISIS (%s): Constructing pseudo LSP %pLS for interface %s level %d",
+ area->area_tag, lsp->hdr.lsp_id, circuit->interface->name,
+ level);
lsp->level = level;
/* RFC3787 section 4 SHOULD not set overload bit in pseudo LSPs */
@@ -1717,10 +1712,8 @@ static void lsp_build_pseudo(struct isis_lsp *lsp, struct isis_circuit *circuit,
if (circuit->area->oldmetric) {
isis_tlvs_add_oldstyle_reach(lsp->tlvs, ne_id, 0);
- lsp_debug(
- "ISIS (%s): Adding %s.%02x as old-style neighbor (self)",
- area->area_tag, sysid_print(ne_id),
- LSP_PSEUDO_ID(ne_id));
+ lsp_debug("ISIS (%s): Adding %pPN as old-style neighbor (self)",
+ area->area_tag, ne_id);
}
if (circuit->area->newmetric) {
if (area_is_mt(circuit->area))
@@ -1728,10 +1721,8 @@ static void lsp_build_pseudo(struct isis_lsp *lsp, struct isis_circuit *circuit,
else
mtid = ISIS_MT_DISABLE;
isis_tlvs_add_extended_reach(lsp->tlvs, mtid, ne_id, 0, NULL);
- lsp_debug(
- "ISIS (%s): Adding %s.%02x as te-style neighbor (self)",
- area->area_tag, sysid_print(ne_id),
- LSP_PSEUDO_ID(ne_id));
+ lsp_debug("ISIS (%s): Adding %pPN as te-style neighbor (self)",
+ area->area_tag, ne_id);
}
adj_list = list_new();
@@ -1740,8 +1731,8 @@ static void lsp_build_pseudo(struct isis_lsp *lsp, struct isis_circuit *circuit,
for (ALL_LIST_ELEMENTS_RO(adj_list, node, adj)) {
if (!(adj->level & level)) {
lsp_debug(
- "ISIS (%s): Ignoring neighbor %s, level does not intersect",
- area->area_tag, sysid_print(adj->sysid));
+ "ISIS (%s): Ignoring neighbor %pSY, level does not intersect",
+ area->area_tag, adj->sysid);
continue;
}
@@ -1753,8 +1744,8 @@ static void lsp_build_pseudo(struct isis_lsp *lsp, struct isis_circuit *circuit,
&& !(level == IS_LEVEL_2
&& adj->sys_type == ISIS_SYSTYPE_L2_IS)) {
lsp_debug(
- "ISIS (%s): Ignoring neighbor %s, level does not match",
- area->area_tag, sysid_print(adj->sysid));
+ "ISIS (%s): Ignoring neighbor %pSY, level does not match",
+ area->area_tag, adj->sysid);
continue;
}
@@ -1762,18 +1753,16 @@ static void lsp_build_pseudo(struct isis_lsp *lsp, struct isis_circuit *circuit,
if (circuit->area->oldmetric) {
isis_tlvs_add_oldstyle_reach(lsp->tlvs, ne_id, 0);
lsp_debug(
- "ISIS (%s): Adding %s.%02x as old-style neighbor (peer)",
- area->area_tag, sysid_print(ne_id),
- LSP_PSEUDO_ID(ne_id));
+ "ISIS (%s): Adding %pPN as old-style neighbor (peer)",
+ area->area_tag, ne_id);
}
if (circuit->area->newmetric) {
isis_tlvs_add_extended_reach(lsp->tlvs,
ISIS_MT_IPV4_UNICAST,
ne_id, 0, NULL);
lsp_debug(
- "ISIS (%s): Adding %s.%02x as te-style neighbor (peer)",
- area->area_tag, sysid_print(ne_id),
- LSP_PSEUDO_ID(ne_id));
+ "ISIS (%s): Adding %pPN as te-style neighbor (peer)",
+ area->area_tag, ne_id);
}
}
list_delete(&adj_list);
@@ -1832,10 +1821,9 @@ int lsp_generate_pseudo(struct isis_circuit *circuit, int level)
if (IS_DEBUG_UPDATE_PACKETS) {
zlog_debug(
- "ISIS-Upd (%s): Built L%d Pseudo LSP %s, len %hu, seq 0x%08x, cksum 0x%04hx, lifetime %hus, refresh %hus",
- circuit->area->area_tag, level,
- rawlspid_print(lsp->hdr.lsp_id), lsp->hdr.pdu_len,
- lsp->hdr.seqno, lsp->hdr.checksum,
+ "ISIS-Upd (%s): Built L%d Pseudo LSP %pLS, len %hu, seq 0x%08x, cksum 0x%04hx, lifetime %hus, refresh %hus",
+ circuit->area->area_tag, level, lsp->hdr.lsp_id,
+ lsp->hdr.pdu_len, lsp->hdr.seqno, lsp->hdr.checksum,
lsp->hdr.rem_lifetime, refresh_time);
}
@@ -1863,8 +1851,8 @@ static int lsp_regenerate_pseudo(struct isis_circuit *circuit, int level)
if (!lsp) {
flog_err(EC_LIB_DEVELOPMENT,
- "lsp_regenerate_pseudo: no l%d LSP %s found!", level,
- rawlspid_print(lsp_id));
+ "lsp_regenerate_pseudo: no l%d LSP %pLS found!", level,
+ lsp_id);
return ISIS_ERROR;
}
@@ -1887,10 +1875,9 @@ static int lsp_regenerate_pseudo(struct isis_circuit *circuit, int level)
if (IS_DEBUG_UPDATE_PACKETS) {
zlog_debug(
- "ISIS-Upd (%s): Refreshed L%d Pseudo LSP %s, len %hu, seq 0x%08x, cksum 0x%04hx, lifetime %hus, refresh %hus",
- circuit->area->area_tag, level,
- rawlspid_print(lsp->hdr.lsp_id), lsp->hdr.pdu_len,
- lsp->hdr.seqno, lsp->hdr.checksum,
+ "ISIS-Upd (%s): Refreshed L%d Pseudo LSP %pLS, len %hu, seq 0x%08x, cksum 0x%04hx, lifetime %hus, refresh %hus",
+ circuit->area->area_tag, level, lsp->hdr.lsp_id,
+ lsp->hdr.pdu_len, lsp->hdr.seqno, lsp->hdr.checksum,
lsp->hdr.rem_lifetime, refresh_time);
}
@@ -2101,10 +2088,9 @@ void lsp_tick(struct event *thread)
if (lsp->age_out == 0) {
zlog_debug(
- "ISIS-Upd (%s): L%u LSP %s seq 0x%08x aged out",
+ "ISIS-Upd (%s): L%u LSP %pLS seq 0x%08x aged out",
area->area_tag, lsp->level,
- rawlspid_print(lsp->hdr.lsp_id),
- lsp->hdr.seqno);
+ lsp->hdr.lsp_id, lsp->hdr.seqno);
/* if we're aging out fragment 0, lsp_destroy()
* below will delete all other fragments too,
@@ -2207,11 +2193,10 @@ void _lsp_flood(struct isis_lsp *lsp, struct isis_circuit *circuit,
const char *func, const char *file, int line)
{
if (IS_DEBUG_FLOODING) {
- zlog_debug("Flooding LSP %s%s%s (From %s %s:%d)",
- rawlspid_print(lsp->hdr.lsp_id),
- circuit ? " except on " : "",
- circuit ? circuit->interface->name : "",
- func, file, line);
+ zlog_debug("Flooding LSP %pLS%s%s (From %s %s:%d)",
+ lsp->hdr.lsp_id, circuit ? " except on " : "",
+ circuit ? circuit->interface->name : "", func, file,
+ line);
}
if (!fabricd)
diff --git a/isisd/isis_misc.c b/isisd/isis_misc.c
index 95d24036ec..09ffa3479a 100644
--- a/isisd/isis_misc.c
+++ b/isisd/isis_misc.c
@@ -32,48 +32,13 @@
#include "isisd/isis_dynhn.h"
/* staticly assigned vars for printing purposes */
+static char sys_hostname[ISO_SYSID_STRLEN];
struct in_addr new_prefix;
-/* len of xx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xx */
-/* + place for #0 termination */
-char isonet[51];
/* len of xxYxxMxWxdxxhxxmxxs + place for #0 termination */
char datestring[20];
char nlpidstring[30];
/*
- * This converts the isonet to its printable format
- */
-const char *isonet_print(const uint8_t *from, int len)
-{
- int i = 0;
- char tbuf[4];
- isonet[0] = '\0';
-
- if (!from)
- return "unknown";
-
- while (i < len) {
- if (i & 1) {
- snprintf(tbuf, sizeof(tbuf), "%02x", *(from + i));
- strlcat(isonet, tbuf, sizeof(isonet));
- } else {
- if (i == (len - 1)) { /* No dot at the end of address */
- snprintf(tbuf, sizeof(tbuf), "%02x",
- *(from + i));
- strlcat(isonet, tbuf, sizeof(isonet));
- } else {
- snprintf(tbuf, sizeof(tbuf), "%02x.",
- *(from + i));
- strlcat(isonet, tbuf, sizeof(isonet));
- }
- }
- i++;
- }
-
- return isonet;
-}
-
-/*
* Returns 0 on error, length of buff on ok
* extract dot from the dotted str, and insert all the number in a buff
*/
@@ -307,60 +272,6 @@ const char *isis_hello_padding2string(int hello_padding_type)
return NULL; /* not reached */
}
-/*
- * Print functions - we print to static vars
- */
-const char *snpa_print(const uint8_t *from)
-{
- return isis_format_id(from, ISIS_SYS_ID_LEN);
-}
-
-const char *sysid_print(const uint8_t *from)
-{
- return isis_format_id(from, ISIS_SYS_ID_LEN);
-}
-
-const char *rawlspid_print(const uint8_t *from)
-{
- return isis_format_id(from, 8);
-}
-
-#define FORMAT_ID_SIZE sizeof("0000.0000.0000.00-00")
-const char *isis_format_id(const uint8_t *id, size_t len)
-{
-#define FORMAT_BUF_COUNT 4
- static char buf_ring[FORMAT_BUF_COUNT][FORMAT_ID_SIZE];
- static size_t cur_buf = 0;
-
- char *rv;
-
- cur_buf++;
- if (cur_buf >= FORMAT_BUF_COUNT)
- cur_buf = 0;
-
- rv = buf_ring[cur_buf];
-
- if (!id) {
- snprintf(rv, FORMAT_ID_SIZE, "unknown");
- return rv;
- }
-
- if (len < 6) {
- snprintf(rv, FORMAT_ID_SIZE, "Short ID");
- return rv;
- }
-
- snprintf(rv, FORMAT_ID_SIZE, "%02x%02x.%02x%02x.%02x%02x", id[0], id[1],
- id[2], id[3], id[4], id[5]);
-
- if (len > 6)
- snprintf(rv + 14, FORMAT_ID_SIZE - 14, ".%02x", id[6]);
- if (len > 7)
- snprintf(rv + 17, FORMAT_ID_SIZE - 17, "-%02x", id[7]);
-
- return rv;
-}
-
const char *time2string(uint32_t time)
{
uint32_t rest;
@@ -474,7 +385,8 @@ const char *print_sys_hostname(const uint8_t *sysid)
return dyn->hostname;
}
- return sysid_print(sysid);
+ snprintfrr(sys_hostname, ISO_SYSID_STRLEN, "%pSY", sysid);
+ return sys_hostname;
}
/*
@@ -508,11 +420,11 @@ void zlog_dump_data(void *data, int len)
/* store hex str (for left side) */
snprintf(bytestr, sizeof(bytestr), "%02X ", *p);
- strncat(hexstr, bytestr, sizeof(hexstr) - strlen(hexstr) - 1);
+ strlcat(hexstr, bytestr, sizeof(hexstr) - strlen(hexstr) - 1);
/* store char str (for right side) */
snprintf(bytestr, sizeof(bytestr), "%c", c);
- strncat(charstr, bytestr,
+ strlcat(charstr, bytestr,
sizeof(charstr) - strlen(charstr) - 1);
if ((i % 16) == 0) {
@@ -523,9 +435,9 @@ void zlog_dump_data(void *data, int len)
charstr[0] = 0;
} else if ((i % 8) == 0) {
/* half line: add whitespaces */
- strncat(hexstr, " ",
+ strlcat(hexstr, " ",
sizeof(hexstr) - strlen(hexstr) - 1);
- strncat(charstr, " ",
+ strlcat(charstr, " ",
sizeof(charstr) - strlen(charstr) - 1);
}
p++; /* next byte */
diff --git a/isisd/isis_misc.h b/isisd/isis_misc.h
index 01d9abe869..3a1d136b1d 100644
--- a/isisd/isis_misc.h
+++ b/isisd/isis_misc.h
@@ -28,11 +28,6 @@ int sysid2buff(uint8_t *, const char *);
/*
* Printing functions
*/
-const char *isonet_print(const uint8_t *, int len);
-const char *sysid_print(const uint8_t *);
-const char *snpa_print(const uint8_t *);
-const char *rawlspid_print(const uint8_t *);
-const char *isis_format_id(const uint8_t *id, size_t len);
const char *time2string(uint32_t);
const char *nlpid2str(uint8_t nlpid);
/* typedef struct nlpids nlpids; */
diff --git a/isisd/isis_mt.c b/isisd/isis_mt.c
index fcc0f53815..d04a24dc46 100644
--- a/isisd/isis_mt.c
+++ b/isisd/isis_mt.c
@@ -507,8 +507,8 @@ static void tlvs_add_mt_set(struct isis_area *area, struct isis_tlvs *tlvs,
/* Check if MT is enable for this area */
if (!area_is_mt(area)) {
lsp_debug(
- "ISIS (%s): Adding %s.%02x as te-style neighbor (MT disable)",
- area->area_tag, sysid_print(id), LSP_PSEUDO_ID(id));
+ "ISIS (%s): Adding %pPN as te-style neighbor (MT disable)",
+ area->area_tag, id);
isis_tlvs_add_extended_reach(tlvs, ISIS_MT_DISABLE, id, metric,
ext);
return;
@@ -518,15 +518,12 @@ static void tlvs_add_mt_set(struct isis_area *area, struct isis_tlvs *tlvs,
for (unsigned int i = 0; i < mt_count; i++) {
uint16_t mtid = mt_set[i];
if (mt_set[i] == ISIS_MT_IPV4_UNICAST) {
- lsp_debug(
- "ISIS (%s): Adding %s.%02x as te-style neighbor",
- area->area_tag, sysid_print(id),
- LSP_PSEUDO_ID(id));
+ lsp_debug("ISIS (%s): Adding %pPN as te-style neighbor",
+ area->area_tag, id);
} else {
lsp_debug(
- "ISIS (%s): Adding %s.%02x as mt-style neighbor for %s",
- area->area_tag, sysid_print(id),
- LSP_PSEUDO_ID(id), isis_mtid2str(mtid));
+ "ISIS (%s): Adding %pPN as mt-style neighbor for %s",
+ area->area_tag, id, isis_mtid2str(mtid));
}
isis_tlvs_add_extended_reach(tlvs, mtid, id, metric, ext);
}
diff --git a/isisd/isis_nb_config.c b/isisd/isis_nb_config.c
index 6a9133f20b..022bfbed6e 100644
--- a/isisd/isis_nb_config.c
+++ b/isisd/isis_nb_config.c
@@ -103,14 +103,14 @@ int isis_instance_is_type_modify(struct nb_cb_modify_args *args)
}
struct sysid_iter {
- struct area_addr *addr;
+ struct iso_address *addr;
bool same;
};
static int sysid_iter_cb(const struct lyd_node *dnode, void *arg)
{
struct sysid_iter *iter = arg;
- struct area_addr addr;
+ struct iso_address addr;
const char *net;
net = yang_dnode_get_string(dnode, NULL);
@@ -130,7 +130,7 @@ static int sysid_iter_cb(const struct lyd_node *dnode, void *arg)
int isis_instance_area_address_create(struct nb_cb_create_args *args)
{
struct isis_area *area;
- struct area_addr addr, *addrr = NULL, *addrp = NULL;
+ struct iso_address addr, *addrr = NULL, *addrp = NULL;
struct listnode *node;
struct sysid_iter iter;
uint8_t buff[255];
@@ -161,7 +161,8 @@ int isis_instance_area_address_create(struct nb_cb_create_args *args)
}
break;
case NB_EV_PREPARE:
- addrr = XMALLOC(MTYPE_ISIS_AREA_ADDR, sizeof(struct area_addr));
+ addrr = XMALLOC(MTYPE_ISIS_AREA_ADDR,
+ sizeof(struct iso_address));
addrr->addr_len = dotformat2buff(buff, net_title);
memcpy(addrr->area_addr, buff, addrr->addr_len);
args->resource->ptr = addrr;
@@ -217,7 +218,7 @@ int isis_instance_area_address_create(struct nb_cb_create_args *args)
int isis_instance_area_address_destroy(struct nb_cb_destroy_args *args)
{
- struct area_addr addr, *addrp = NULL;
+ struct iso_address addr, *addrp = NULL;
struct listnode *node;
uint8_t buff[255];
struct isis_area *area;
diff --git a/isisd/isis_nb_notifications.c b/isisd/isis_nb_notifications.c
index 94b1c47d3e..5a1e312b4d 100644
--- a/isisd/isis_nb_notifications.c
+++ b/isisd/isis_nb_notifications.c
@@ -134,6 +134,7 @@ void isis_notif_lsp_too_large(const struct isis_circuit *circuit,
const char *xpath = "/frr-isisd:lsp-too-large";
struct list *arguments = yang_data_list_new();
char xpath_arg[XPATH_MAXLEN];
+ char xpath_value[ISO_SYSID_STRLEN];
struct yang_data *data;
struct isis_area *area = circuit->area;
@@ -143,7 +144,8 @@ void isis_notif_lsp_too_large(const struct isis_circuit *circuit,
data = yang_data_new_uint32(xpath_arg, pdu_size);
listnode_add(arguments, data);
snprintf(xpath_arg, sizeof(xpath_arg), "%s/lsp-id", xpath);
- data = yang_data_new_string(xpath_arg, rawlspid_print(lsp_id));
+ snprintfrr(xpath_value, ISO_SYSID_STRLEN, "%pLS", lsp_id);
+ data = yang_data_new_string(xpath_arg, xpath_value);
listnode_add(arguments, data);
hook_call(isis_hook_lsp_too_large, circuit, pdu_size, lsp_id);
@@ -180,11 +182,13 @@ void isis_notif_corrupted_lsp(const struct isis_area *area,
const char *xpath = "/frr-isisd:corrupted-lsp-detected";
struct list *arguments = yang_data_list_new();
char xpath_arg[XPATH_MAXLEN];
+ char xpath_value[ISO_SYSID_STRLEN];
struct yang_data *data;
notif_prep_instance_hdr(xpath, area, "default", arguments);
snprintf(xpath_arg, sizeof(xpath_arg), "%s/lsp-id", xpath);
- data = yang_data_new_string(xpath_arg, rawlspid_print(lsp_id));
+ snprintfrr(xpath_value, ISO_SYSID_STRLEN, "%pLS", lsp_id);
+ data = yang_data_new_string(xpath_arg, xpath_value);
listnode_add(arguments, data);
hook_call(isis_hook_corrupted_lsp, area);
@@ -201,11 +205,13 @@ void isis_notif_lsp_exceed_max(const struct isis_area *area,
const char *xpath = "/frr-isisd:attempt-to-exceed-max-sequence";
struct list *arguments = yang_data_list_new();
char xpath_arg[XPATH_MAXLEN];
+ char xpath_value[ISO_SYSID_STRLEN];
struct yang_data *data;
notif_prep_instance_hdr(xpath, area, "default", arguments);
snprintf(xpath_arg, sizeof(xpath_arg), "%s/lsp-id", xpath);
- data = yang_data_new_string(xpath_arg, rawlspid_print(lsp_id));
+ snprintfrr(xpath_value, ISO_SYSID_STRLEN, "%pLS", lsp_id);
+ data = yang_data_new_string(xpath_arg, xpath_value);
listnode_add(arguments, data);
hook_call(isis_hook_lsp_exceed_max, area, lsp_id);
@@ -299,6 +305,7 @@ void isis_notif_adj_state_change(const struct isis_adjacency *adj,
const char *xpath = "/frr-isisd:adjacency-state-change";
struct list *arguments = yang_data_list_new();
char xpath_arg[XPATH_MAXLEN];
+ char xpath_value[ISO_SYSID_STRLEN];
struct yang_data *data;
struct isis_circuit *circuit = adj->circuit;
struct isis_area *area = circuit->area;
@@ -312,7 +319,8 @@ void isis_notif_adj_state_change(const struct isis_adjacency *adj,
listnode_add(arguments, data);
}
snprintf(xpath_arg, sizeof(xpath_arg), "%s/neighbor-system-id", xpath);
- data = yang_data_new_string(xpath_arg, sysid_print(adj->sysid));
+ snprintfrr(xpath_value, ISO_SYSID_STRLEN, "%pSY", adj->sysid);
+ data = yang_data_new_string(xpath_arg, xpath_value);
listnode_add(arguments, data);
snprintf(xpath_arg, sizeof(xpath_arg), "%s/state", xpath);
@@ -389,13 +397,15 @@ void isis_notif_lsp_received(const struct isis_circuit *circuit,
const char *xpath = "/frr-isisd:lsp-received";
struct list *arguments = yang_data_list_new();
char xpath_arg[XPATH_MAXLEN];
+ char xpath_value[ISO_SYSID_STRLEN];
struct yang_data *data;
struct isis_area *area = circuit->area;
notif_prep_instance_hdr(xpath, area, "default", arguments);
notif_prepr_iface_hdr(xpath, circuit, arguments);
snprintf(xpath_arg, sizeof(xpath_arg), "%s/lsp-id", xpath);
- data = yang_data_new_string(xpath_arg, rawlspid_print(lsp_id));
+ snprintfrr(xpath_value, ISO_SYSID_STRLEN, "%pLS", lsp_id);
+ data = yang_data_new_string(xpath_arg, xpath_value);
listnode_add(arguments, data);
snprintf(xpath_arg, sizeof(xpath_arg), "%s/sequence", xpath);
data = yang_data_new_uint32(xpath_arg, seqno);
@@ -419,11 +429,13 @@ void isis_notif_lsp_gen(const struct isis_area *area, const uint8_t *lsp_id,
const char *xpath = "/frr-isisd:lsp-generation";
struct list *arguments = yang_data_list_new();
char xpath_arg[XPATH_MAXLEN];
+ char xpath_value[ISO_SYSID_STRLEN];
struct yang_data *data;
notif_prep_instance_hdr(xpath, area, "default", arguments);
snprintf(xpath_arg, sizeof(xpath_arg), "%s/lsp-id", xpath);
- data = yang_data_new_string(xpath_arg, rawlspid_print(lsp_id));
+ snprintfrr(xpath_value, ISO_SYSID_STRLEN, "%pLS", lsp_id);
+ data = yang_data_new_string(xpath_arg, xpath_value);
listnode_add(arguments, data);
snprintf(xpath_arg, sizeof(xpath_arg), "%s/sequence", xpath);
data = yang_data_new_uint32(xpath_arg, seqno);
@@ -503,13 +515,15 @@ void isis_notif_lsp_error(const struct isis_circuit *circuit,
const char *xpath = "/frr-isisd:lsp-error-detected";
struct list *arguments = yang_data_list_new();
char xpath_arg[XPATH_MAXLEN];
+ char xpath_value[ISO_SYSID_STRLEN];
struct yang_data *data;
struct isis_area *area = circuit->area;
notif_prep_instance_hdr(xpath, area, "default", arguments);
notif_prepr_iface_hdr(xpath, circuit, arguments);
snprintf(xpath_arg, sizeof(xpath_arg), "%s/lsp-id", xpath);
- data = yang_data_new_string(xpath_arg, rawlspid_print(lsp_id));
+ snprintfrr(xpath_value, ISO_SYSID_STRLEN, "%pLS", lsp_id);
+ data = yang_data_new_string(xpath_arg, xpath_value);
listnode_add(arguments, data);
snprintf(xpath_arg, sizeof(xpath_arg), "%s/raw-pdu", xpath);
data = yang_data_new_binary(xpath_arg, raw_pdu, raw_pdu_len);
@@ -530,13 +544,15 @@ void isis_notif_seqno_skipped(const struct isis_circuit *circuit,
const char *xpath = "/frr-isisd:sequence-number-skipped";
struct list *arguments = yang_data_list_new();
char xpath_arg[XPATH_MAXLEN];
+ char xpath_value[ISO_SYSID_STRLEN];
struct yang_data *data;
struct isis_area *area = circuit->area;
notif_prep_instance_hdr(xpath, area, "default", arguments);
notif_prepr_iface_hdr(xpath, circuit, arguments);
snprintf(xpath_arg, sizeof(xpath_arg), "%s/lsp-id", xpath);
- data = yang_data_new_string(xpath_arg, rawlspid_print(lsp_id));
+ snprintfrr(xpath_value, ISO_SYSID_STRLEN, "%pLS", lsp_id);
+ data = yang_data_new_string(xpath_arg, xpath_value);
listnode_add(arguments, data);
hook_call(isis_hook_seqno_skipped, circuit, lsp_id);
@@ -553,13 +569,15 @@ void isis_notif_own_lsp_purge(const struct isis_circuit *circuit,
const char *xpath = "/frr-isisd:own-lsp-purge";
struct list *arguments = yang_data_list_new();
char xpath_arg[XPATH_MAXLEN];
+ char xpath_value[ISO_SYSID_STRLEN];
struct yang_data *data;
struct isis_area *area = circuit->area;
notif_prep_instance_hdr(xpath, area, "default", arguments);
notif_prepr_iface_hdr(xpath, circuit, arguments);
snprintf(xpath_arg, sizeof(xpath_arg), "%s/lsp-id", xpath);
- data = yang_data_new_string(xpath_arg, rawlspid_print(lsp_id));
+ snprintfrr(xpath_value, ISO_SYSID_STRLEN, "%pLS", lsp_id);
+ data = yang_data_new_string(xpath_arg, xpath_value);
listnode_add(arguments, data);
hook_call(isis_hook_own_lsp_purge, circuit, lsp_id);
diff --git a/isisd/isis_nb_state.c b/isisd/isis_nb_state.c
index 13fdddf555..b7c33ed27b 100644
--- a/isisd/isis_nb_state.c
+++ b/isisd/isis_nb_state.c
@@ -132,8 +132,11 @@ lib_interface_state_isis_adjacencies_adjacency_neighbor_sysid_get_elem(
struct nb_cb_get_elem_args *args)
{
const struct isis_adjacency *adj = args->list_entry;
+ char xpath_value[ISO_SYSID_STRLEN];
- return yang_data_new_string(args->xpath, sysid_print(adj->sysid));
+ snprintfrr(xpath_value, ISO_SYSID_STRLEN, "%pSY", adj->sysid);
+
+ return yang_data_new_string(args->xpath, xpath_value);
}
/*
@@ -158,8 +161,11 @@ lib_interface_state_isis_adjacencies_adjacency_neighbor_snpa_get_elem(
struct nb_cb_get_elem_args *args)
{
const struct isis_adjacency *adj = args->list_entry;
+ char xpath_value[ISO_SYSID_STRLEN];
+
+ snprintfrr(xpath_value, ISO_SYSID_STRLEN, "%pSY", adj->snpa);
- return yang_data_new_string(args->xpath, snpa_print(adj->snpa));
+ return yang_data_new_string(args->xpath, xpath_value);
}
/*
diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c
index d489bb98ce..0cd43a7abc 100644
--- a/isisd/isis_pdu.c
+++ b/isisd/isis_pdu.c
@@ -514,9 +514,9 @@ static int process_lan_hello(struct iih_info *iih)
if (IS_DEBUG_ADJ_PACKETS) {
zlog_debug(
- "ISIS-Adj (%s): Rcvd L%d LAN IIH from %s on %s, cirType %s, cirID %u, length %zd",
- iih->circuit->area->area_tag, iih->level,
- snpa_print(iih->ssnpa), iih->circuit->interface->name,
+ "ISIS-Adj (%s): Rcvd L%d LAN IIH from %pSY on %s, cirType %s, cirID %u, length %zd",
+ iih->circuit->area->area_tag, iih->level, iih->ssnpa,
+ iih->circuit->interface->name,
circuit_t2string(iih->circuit->is_type),
iih->circuit->circuit_id,
stream_get_endp(iih->circuit->rcv_stream));
@@ -862,31 +862,32 @@ static int process_lsp(uint8_t pdu_type, struct isis_circuit *circuit,
#ifndef FABRICD
/* send northbound notification */
+ char buf[ISO_SYSID_STRLEN];
+
+ snprintfrr(buf, ISO_SYSID_STRLEN, "%pSY", hdr.lsp_id);
isis_notif_lsp_received(circuit, hdr.lsp_id, hdr.seqno, time(NULL),
- sysid_print(hdr.lsp_id));
+ buf);
#endif /* ifndef FABRICD */
if (pdu_len_validate(hdr.pdu_len, circuit)) {
- zlog_debug("ISIS-Upd (%s): LSP %s invalid LSP length %hu",
- circuit->area->area_tag, rawlspid_print(hdr.lsp_id),
- hdr.pdu_len);
+ zlog_debug("ISIS-Upd (%s): LSP %pLS invalid LSP length %hu",
+ circuit->area->area_tag, hdr.lsp_id, hdr.pdu_len);
return ISIS_WARNING;
}
if (IS_DEBUG_UPDATE_PACKETS) {
- zlog_debug("ISIS-Upd (%s): Rcvd L%d LSP %s, seq 0x%08x, cksum 0x%04hx, lifetime %hus, len %hu, on %s",
- circuit->area->area_tag, level,
- rawlspid_print(hdr.lsp_id), hdr.seqno, hdr.checksum,
- hdr.rem_lifetime, hdr.pdu_len,
- circuit->interface->name);
+ zlog_debug(
+ "ISIS-Upd (%s): Rcvd L%d LSP %pLS, seq 0x%08x, cksum 0x%04hx, lifetime %hus, len %hu, on %s",
+ circuit->area->area_tag, level, hdr.lsp_id, hdr.seqno,
+ hdr.checksum, hdr.rem_lifetime, hdr.pdu_len,
+ circuit->interface->name);
}
/* lsp is_type check */
if ((hdr.lsp_bits & IS_LEVEL_1) != IS_LEVEL_1) {
- zlog_debug(
- "ISIS-Upd (%s): LSP %s invalid LSP is type 0x%x",
- circuit->area->area_tag, rawlspid_print(hdr.lsp_id),
- hdr.lsp_bits & IS_LEVEL_1_AND_2);
+ zlog_debug("ISIS-Upd (%s): LSP %pLS invalid LSP is type 0x%x",
+ circuit->area->area_tag, hdr.lsp_id,
+ hdr.lsp_bits & IS_LEVEL_1_AND_2);
/* continue as per RFC1122 Be liberal in what you accept, and
* conservative in what you send */
}
@@ -896,27 +897,25 @@ static int process_lsp(uint8_t pdu_type, struct isis_circuit *circuit,
if (iso_csum_verify(STREAM_DATA(circuit->rcv_stream) + 12,
hdr.pdu_len - 12, hdr.checksum, 12)) {
zlog_debug(
- "ISIS-Upd (%s): LSP %s invalid LSP checksum 0x%04hx",
- circuit->area->area_tag, rawlspid_print(hdr.lsp_id),
- hdr.checksum);
+ "ISIS-Upd (%s): LSP %pLS invalid LSP checksum 0x%04hx",
+ circuit->area->area_tag, hdr.lsp_id, hdr.checksum);
return ISIS_WARNING;
}
/* 7.3.15.1 a) 1 - external domain circuit will discard lsps */
if (circuit->ext_domain) {
zlog_debug(
- "ISIS-Upd (%s): LSP %s received at level %d over circuit with externalDomain = true",
- circuit->area->area_tag, rawlspid_print(hdr.lsp_id),
- level);
+ "ISIS-Upd (%s): LSP %pLS received at level %d over circuit with externalDomain = true",
+ circuit->area->area_tag, hdr.lsp_id, level);
return ISIS_WARNING;
}
/* 7.3.15.1 a) 2,3 - manualL2OnlyMode not implemented */
if (!(circuit->is_type & level)) {
zlog_debug(
- "ISIS-Upd (%s): LSP %s received at level %d over circuit of type %s",
- circuit->area->area_tag, rawlspid_print(hdr.lsp_id),
- level, circuit_t2string(circuit->is_type));
+ "ISIS-Upd (%s): LSP %pLS received at level %d over circuit of type %s",
+ circuit->area->area_tag, hdr.lsp_id, level,
+ circuit_t2string(circuit->is_type));
return ISIS_WARNING;
}
@@ -1016,11 +1015,11 @@ static int process_lsp(uint8_t pdu_type, struct isis_circuit *circuit,
if (circuit->circ_type == CIRCUIT_T_BROADCAST) {
if (!isis_adj_lookup_snpa(ssnpa,
circuit->u.bc.adjdb[level - 1])) {
- zlog_debug("(%s): DS ======= LSP %s, seq 0x%08x, cksum 0x%04hx, lifetime %hus on %s",
- circuit->area->area_tag,
- rawlspid_print(hdr.lsp_id), hdr.seqno,
- hdr.checksum, hdr.rem_lifetime,
- circuit->interface->name);
+ zlog_debug(
+ "(%s): DS ======= LSP %pLS, seq 0x%08x, cksum 0x%04hx, lifetime %hus on %s",
+ circuit->area->area_tag, hdr.lsp_id, hdr.seqno,
+ hdr.checksum, hdr.rem_lifetime,
+ circuit->interface->name);
goto out; /* Silently discard */
}
}
@@ -1057,9 +1056,9 @@ dontcheckadj:
if (lsp && (lsp->hdr.seqno == hdr.seqno)
&& (lsp->hdr.checksum != hdr.checksum)
&& hdr.rem_lifetime) {
- zlog_warn("ISIS-Upd (%s): LSP %s seq 0x%08x with confused checksum received.",
- circuit->area->area_tag, rawlspid_print(hdr.lsp_id),
- hdr.seqno);
+ zlog_warn(
+ "ISIS-Upd (%s): LSP %pLS seq 0x%08x with confused checksum received.",
+ circuit->area->area_tag, hdr.lsp_id, hdr.seqno);
hdr.rem_lifetime = 0;
lsp_confusion = true;
} else
@@ -1153,10 +1152,9 @@ dontcheckadj:
}
if (IS_DEBUG_UPDATE_PACKETS)
zlog_debug(
- "ISIS-Upd (%s): (1) re-originating LSP %s new seq 0x%08x",
+ "ISIS-Upd (%s): (1) re-originating LSP %pLS new seq 0x%08x",
circuit->area->area_tag,
- rawlspid_print(hdr.lsp_id),
- lsp->hdr.seqno);
+ hdr.lsp_id, lsp->hdr.seqno);
} else {
/* our own LSP with 0 remaining life time */
#ifndef FABRICD
@@ -1194,9 +1192,8 @@ dontcheckadj:
#endif /* ifndef FABRICD */
if (IS_DEBUG_UPDATE_PACKETS) {
zlog_debug(
- "ISIS-Upd (%s): (2) re-originating LSP %s new seq 0x%08x",
- circuit->area->area_tag,
- rawlspid_print(hdr.lsp_id),
+ "ISIS-Upd (%s): (2) re-originating LSP %pLS new seq 0x%08x",
+ circuit->area->area_tag, hdr.lsp_id,
lsp->hdr.seqno);
}
lsp_flood(lsp, NULL);
@@ -1361,9 +1358,9 @@ static int process_snp(uint8_t pdu_type, struct isis_circuit *circuit,
if (!is_csnp && (circuit->circ_type == CIRCUIT_T_BROADCAST)
&& !circuit->u.bc.is_dr[level - 1]) {
zlog_debug(
- "ISIS-Snp (%s): Rcvd L%d %cSNP from %s on %s, skipping: we are not the DIS",
- circuit->area->area_tag, level, typechar,
- snpa_print(ssnpa), circuit->interface->name);
+ "ISIS-Snp (%s): Rcvd L%d %cSNP from %pSY on %s, skipping: we are not the DIS",
+ circuit->area->area_tag, level, typechar, ssnpa,
+ circuit->interface->name);
return ISIS_OK;
}
@@ -1452,16 +1449,16 @@ static int process_snp(uint8_t pdu_type, struct isis_circuit *circuit,
/* debug isis snp-packets */
if (IS_DEBUG_SNP_PACKETS) {
- zlog_debug("ISIS-Snp (%s): Rcvd L%d %cSNP from %s on %s",
- circuit->area->area_tag, level, typechar,
- snpa_print(ssnpa), circuit->interface->name);
+ zlog_debug("ISIS-Snp (%s): Rcvd L%d %cSNP from %pSY on %s",
+ circuit->area->area_tag, level, typechar, ssnpa,
+ circuit->interface->name);
for (struct isis_lsp_entry *entry = entry_head; entry;
entry = entry->next) {
zlog_debug(
- "ISIS-Snp (%s): %cSNP entry %s, seq 0x%08x, cksum 0x%04hx, lifetime %hus",
- circuit->area->area_tag, typechar,
- rawlspid_print(entry->id), entry->seqno,
- entry->checksum, entry->rem_lifetime);
+ "ISIS-Snp (%s): %cSNP entry %pLS, seq 0x%08x, cksum 0x%04hx, lifetime %hus",
+ circuit->area->area_tag, typechar, entry->id,
+ entry->seqno, entry->checksum,
+ entry->rem_lifetime);
}
}
@@ -2479,11 +2476,11 @@ void send_lsp(struct isis_circuit *circuit, struct isis_lsp *lsp,
if (stream_get_endp(lsp->pdu) > stream_get_size(circuit->snd_stream)) {
flog_err(
EC_ISIS_PACKET,
- "ISIS-Upd (%s): Can't send L%d LSP %s, seq 0x%08x, cksum 0x%04hx, lifetime %hus on %s. LSP Size is %zu while interface stream size is %zu.",
- circuit->area->area_tag, lsp->level,
- rawlspid_print(lsp->hdr.lsp_id), lsp->hdr.seqno,
- lsp->hdr.checksum, lsp->hdr.rem_lifetime,
- circuit->interface->name, stream_get_endp(lsp->pdu),
+ "ISIS-Upd (%s): Can't send L%d LSP %pLS, seq 0x%08x, cksum 0x%04hx, lifetime %hus on %s. LSP Size is %zu while interface stream size is %zu.",
+ circuit->area->area_tag, lsp->level, lsp->hdr.lsp_id,
+ lsp->hdr.seqno, lsp->hdr.checksum,
+ lsp->hdr.rem_lifetime, circuit->interface->name,
+ stream_get_endp(lsp->pdu),
stream_get_size(circuit->snd_stream));
#ifndef FABRICD
/* send a northbound notification */
@@ -2507,14 +2504,14 @@ void send_lsp(struct isis_circuit *circuit, struct isis_lsp *lsp,
}
if (IS_DEBUG_UPDATE_PACKETS) {
- zlog_debug("ISIS-Upd (%s): Sending %sL%d LSP %s, seq 0x%08x, cksum 0x%04hx, lifetime %hus on %s",
- circuit->area->area_tag,
- (tx_type == TX_LSP_CIRCUIT_SCOPED)
- ? "Circuit scoped " : "",
- lsp->level,
- rawlspid_print(lsp->hdr.lsp_id), lsp->hdr.seqno,
- lsp->hdr.checksum, lsp->hdr.rem_lifetime,
- circuit->interface->name);
+ zlog_debug(
+ "ISIS-Upd (%s): Sending %sL%d LSP %pLS, seq 0x%08x, cksum 0x%04hx, lifetime %hus on %s",
+ circuit->area->area_tag,
+ (tx_type == TX_LSP_CIRCUIT_SCOPED) ? "Circuit scoped "
+ : "",
+ lsp->level, lsp->hdr.lsp_id, lsp->hdr.seqno,
+ lsp->hdr.checksum, lsp->hdr.rem_lifetime,
+ circuit->interface->name);
if (IS_DEBUG_PACKET_DUMP)
zlog_dump_data(STREAM_DATA(circuit->snd_stream),
stream_get_endp(circuit->snd_stream));
diff --git a/isisd/isis_snmp.c b/isisd/isis_snmp.c
index fa566c5470..f9e3780e29 100644
--- a/isisd/isis_snmp.c
+++ b/isisd/isis_snmp.c
@@ -259,11 +259,6 @@
/* Declare static local variables for convenience. */
SNMP_LOCAL_VARIABLES
-/* If ARRAY_SIZE is not available use a primitive substitution */
-#ifndef ARRAY_SIZE
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
-#endif
-
/*
* Define time function, it serves two purposes
* 1. Uses unint32_t for unix time and encapsulates
@@ -425,7 +420,7 @@ static struct isis_func_to_prefix isis_func_to_prefix_arr[] = {
{isis_snmp_find_isadj_ipaddr, {ISIS_ISADJIPADDR_ENTRY}, 4},
{isis_snmp_find_isadj_prot_supp, {ISIS_ISADJPROTSUPP_ENTRY}, 4},
};
-static size_t isis_func_to_prefix_count = ARRAY_SIZE(isis_func_to_prefix_arr);
+static size_t isis_func_to_prefix_count = array_size(isis_func_to_prefix_arr);
static struct variable isis_var_arr[] = {
{ISIS_SYS_VERSION, INTEGER, RONLY, isis_snmp_find_sys_object},
@@ -554,7 +549,7 @@ static struct variable isis_var_arr[] = {
isis_snmp_find_isadj_prot_supp},
};
-static const size_t isis_var_count = ARRAY_SIZE(isis_var_arr);
+static const size_t isis_var_count = array_size(isis_var_arr);
/* Minimal set of hard-coded data */
#define ISIS_VERSION (1)
@@ -838,12 +833,12 @@ static int isis_snmp_conv_next(uint8_t *buf, size_t max_len, size_t *out_len,
*/
static int isis_snmp_area_addr_lookup_exact(oid *oid_idx, size_t oid_idx_len,
struct isis_area **ret_area,
- struct area_addr **ret_addr)
+ struct iso_address **ret_addr)
{
uint8_t cmp_buf[ISIS_SNMP_OSI_ADDR_LEN_MAX];
size_t addr_len;
struct isis_area *area = NULL;
- struct area_addr *addr = NULL;
+ struct iso_address *addr = NULL;
struct listnode *addr_node;
struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
@@ -885,15 +880,15 @@ static int isis_snmp_area_addr_lookup_exact(oid *oid_idx, size_t oid_idx_len,
static int isis_snmp_area_addr_lookup_next(oid *oid_idx, size_t oid_idx_len,
struct isis_area **ret_area,
- struct area_addr **ret_addr)
+ struct iso_address **ret_addr)
{
uint8_t cmp_buf[ISIS_SNMP_OSI_ADDR_LEN_MAX];
size_t addr_len;
int try_exact = 0;
struct isis_area *found_area = NULL;
struct isis_area *area = NULL;
- struct area_addr *found_addr = NULL;
- struct area_addr *addr = NULL;
+ struct iso_address *found_addr = NULL;
+ struct iso_address *addr = NULL;
struct listnode *addr_node;
struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
@@ -1506,7 +1501,7 @@ static uint8_t *isis_snmp_find_man_area(struct variable *v, oid *name,
WriteMethod **write_method)
{
int res;
- struct area_addr *area_addr = NULL;
+ struct iso_address *area_addr = NULL;
oid *oid_idx;
size_t oid_idx_len;
size_t off = 0;
@@ -2490,6 +2485,11 @@ static uint8_t *isis_snmp_find_isadj(struct variable *v, oid *name,
uint32_t delta_ticks;
time_t now_time;
+ /* Ring buffer to print SNPA */
+#define FORMAT_BUF_COUNT 4
+ static char snpa[FORMAT_BUF_COUNT][ISO_SYSID_STRLEN];
+ static size_t cur_buf = 0;
+
*write_method = NULL;
if (*length <= v->namelen) {
@@ -2536,9 +2536,10 @@ static uint8_t *isis_snmp_find_isadj(struct variable *v, oid *name,
return SNMP_INTEGER(adj->threeway_state);
case ISIS_ISADJ_NEIGHSNPAADDRESS: {
- const char *snpa = (char *)snpa_print(adj->snpa);
- *var_len = strlen(snpa);
- return (uint8_t *)snpa;
+ cur_buf = (cur_buf + 1) % FORMAT_BUF_COUNT;
+ snprintfrr(snpa[cur_buf], ISO_SYSID_STRLEN, "%pSY", adj->snpa);
+ *var_len = strlen(snpa[cur_buf]);
+ return (uint8_t *)snpa[cur_buf];
}
case ISIS_ISADJ_NEIGHSYSTYPE:
@@ -2859,7 +2860,7 @@ static int isis_snmp_db_overload_update(const struct isis_area *area)
/* Put in trap value */
snmp_varlist_add_variable(&notification_vars, isis_snmp_trap_var,
- ARRAY_SIZE(isis_snmp_trap_var), ASN_OBJECT_ID,
+ array_size(isis_snmp_trap_var), ASN_OBJECT_ID,
(uint8_t *)&isis_snmp_trap_val_db_overload,
sizeof(isis_snmp_trap_val_db_overload));
@@ -2868,11 +2869,11 @@ static int isis_snmp_db_overload_update(const struct isis_area *area)
snmp_varlist_add_variable(
&notification_vars, isis_snmp_trap_data_var_sys_level_index,
- ARRAY_SIZE(isis_snmp_trap_data_var_sys_level_index), INTEGER,
+ array_size(isis_snmp_trap_data_var_sys_level_index), INTEGER,
(uint8_t *)&val, sizeof(val));
/* Patch sys_level_state with proper index */
- off = ARRAY_SIZE(isis_snmp_trap_data_var_sys_level_state) - 1;
+ off = array_size(isis_snmp_trap_data_var_sys_level_state) - 1;
isis_snmp_trap_data_var_sys_level_state[off] = val;
/* Prepare data */
@@ -2883,7 +2884,7 @@ static int isis_snmp_db_overload_update(const struct isis_area *area)
snmp_varlist_add_variable(
&notification_vars, isis_snmp_trap_data_var_sys_level_state,
- ARRAY_SIZE(isis_snmp_trap_data_var_sys_level_state), INTEGER,
+ array_size(isis_snmp_trap_data_var_sys_level_state), INTEGER,
(uint8_t *)&val, sizeof(val));
send_v2trap(notification_vars);
@@ -2905,7 +2906,7 @@ static int isis_snmp_lsp_exceed_max_update(const struct isis_area *area,
/* Put in trap value */
snmp_varlist_add_variable(&notification_vars, isis_snmp_trap_var,
- ARRAY_SIZE(isis_snmp_trap_var), ASN_OBJECT_ID,
+ array_size(isis_snmp_trap_var), ASN_OBJECT_ID,
(uint8_t *)&isis_snmp_trap_val_lsp_exceed_max,
sizeof(isis_snmp_trap_val_lsp_exceed_max));
@@ -2914,12 +2915,12 @@ static int isis_snmp_lsp_exceed_max_update(const struct isis_area *area,
snmp_varlist_add_variable(
&notification_vars, isis_snmp_trap_data_var_sys_level_index,
- ARRAY_SIZE(isis_snmp_trap_data_var_sys_level_index), INTEGER,
+ array_size(isis_snmp_trap_data_var_sys_level_index), INTEGER,
(uint8_t *)&val, sizeof(val));
snmp_varlist_add_variable(
&notification_vars, isis_snmp_trap_data_var_pdu_lsp_id,
- ARRAY_SIZE(isis_snmp_trap_data_var_pdu_lsp_id), STRING, lsp_id,
+ array_size(isis_snmp_trap_data_var_pdu_lsp_id), STRING, lsp_id,
ISIS_SYS_ID_LEN + 2);
send_v2trap(notification_vars);
@@ -2962,18 +2963,18 @@ static void isis_snmp_update_worker_a(const struct isis_circuit *circuit,
/* Put in trap value */
memcpy(var_name, isis_snmp_notifications,
sizeof(isis_snmp_notifications));
- var_count = ARRAY_SIZE(isis_snmp_notifications);
+ var_count = array_size(isis_snmp_notifications);
var_name[var_count++] = trap_id;
/* Put in trap value */
snmp_varlist_add_variable(&notification_vars, isis_snmp_trap_var,
- ARRAY_SIZE(isis_snmp_trap_var), ASN_OBJECT_ID,
+ array_size(isis_snmp_trap_var), ASN_OBJECT_ID,
(uint8_t *)var_name, var_count * sizeof(oid));
val = circuit->is_type;
snmp_varlist_add_variable(
&notification_vars, isis_snmp_trap_data_var_sys_level_index,
- ARRAY_SIZE(isis_snmp_trap_data_var_sys_level_index), INTEGER,
+ array_size(isis_snmp_trap_data_var_sys_level_index), INTEGER,
(uint8_t *)&val, sizeof(val));
if (oid_a_len != 0) {
@@ -2992,7 +2993,7 @@ static void isis_snmp_update_worker_a(const struct isis_circuit *circuit,
snmp_varlist_add_variable(
&notification_vars, isis_snmp_trap_data_var_circ_if_index,
- ARRAY_SIZE(isis_snmp_trap_data_var_circ_if_index), UNSIGNED32,
+ array_size(isis_snmp_trap_data_var_circ_if_index), UNSIGNED32,
(uint8_t *)&val, sizeof(val));
@@ -3042,18 +3043,18 @@ static void isis_snmp_update_worker_b(const struct isis_circuit *circuit,
/* Put in trap value */
memcpy(var_name, isis_snmp_notifications,
sizeof(isis_snmp_notifications));
- var_count = ARRAY_SIZE(isis_snmp_notifications);
+ var_count = array_size(isis_snmp_notifications);
var_name[var_count++] = trap_id;
/* Put in trap value */
snmp_varlist_add_variable(&notification_vars, isis_snmp_trap_var,
- ARRAY_SIZE(isis_snmp_trap_var), ASN_OBJECT_ID,
+ array_size(isis_snmp_trap_var), ASN_OBJECT_ID,
(uint8_t *)var_name, var_count * sizeof(oid));
val = circuit->is_type;
snmp_varlist_add_variable(
&notification_vars, isis_snmp_trap_data_var_sys_level_index,
- ARRAY_SIZE(isis_snmp_trap_data_var_sys_level_index), INTEGER,
+ array_size(isis_snmp_trap_data_var_sys_level_index), INTEGER,
(uint8_t *)&val, sizeof(val));
if (circuit->interface == NULL)
@@ -3063,7 +3064,7 @@ static void isis_snmp_update_worker_b(const struct isis_circuit *circuit,
snmp_varlist_add_variable(
&notification_vars, isis_snmp_trap_data_var_circ_if_index,
- ARRAY_SIZE(isis_snmp_trap_data_var_circ_if_index), UNSIGNED32,
+ array_size(isis_snmp_trap_data_var_circ_if_index), UNSIGNED32,
(uint8_t *)&val, sizeof(val));
@@ -3108,9 +3109,9 @@ static int isis_snmp_id_len_mismatch_update(const struct isis_circuit *circuit,
isis_snmp_update_worker_a(
circuit, ISIS_TRAP_ID_LEN_MISMATCH,
isis_snmp_trap_data_var_pdu_field_len,
- ARRAY_SIZE(isis_snmp_trap_data_var_pdu_field_len), UNSIGNED32,
+ array_size(isis_snmp_trap_data_var_pdu_field_len), UNSIGNED32,
&val, sizeof(val), isis_snmp_trap_data_var_pdu_fragment,
- ARRAY_SIZE(isis_snmp_trap_data_var_pdu_fragment), STRING,
+ array_size(isis_snmp_trap_data_var_pdu_fragment), STRING,
raw_pdu, raw_pdu_len);
return 0;
}
@@ -3133,10 +3134,10 @@ isis_snmp_max_area_addr_mismatch_update(const struct isis_circuit *circuit,
isis_snmp_update_worker_a(
circuit, ISIS_TRAP_MAX_AREA_ADDR_MISMATCH,
isis_snmp_trap_data_var_pdu_max_area_addr,
- ARRAY_SIZE(isis_snmp_trap_data_var_pdu_max_area_addr),
+ array_size(isis_snmp_trap_data_var_pdu_max_area_addr),
UNSIGNED32, &val, sizeof(val),
isis_snmp_trap_data_var_pdu_fragment,
- ARRAY_SIZE(isis_snmp_trap_data_var_pdu_fragment), STRING,
+ array_size(isis_snmp_trap_data_var_pdu_fragment), STRING,
raw_pdu, raw_pdu_len);
return 0;
}
@@ -3150,7 +3151,7 @@ static int isis_snmp_own_lsp_purge_update(const struct isis_circuit *circuit,
isis_snmp_update_worker_a(
circuit, ISIS_TRAP_OWN_LSP_PURGE, NULL, 0, STRING, NULL, 0,
isis_snmp_trap_data_var_pdu_lsp_id,
- ARRAY_SIZE(isis_snmp_trap_data_var_pdu_lsp_id), STRING, lsp_id,
+ array_size(isis_snmp_trap_data_var_pdu_lsp_id), STRING, lsp_id,
ISIS_SYS_ID_LEN + 2);
return 0;
}
@@ -3164,7 +3165,7 @@ static int isis_snmp_seqno_skipped_update(const struct isis_circuit *circuit,
isis_snmp_update_worker_a(
circuit, ISIS_TRAP_SEQNO_SKIPPED, NULL, 0, STRING, NULL, 0,
isis_snmp_trap_data_var_pdu_lsp_id,
- ARRAY_SIZE(isis_snmp_trap_data_var_pdu_lsp_id), STRING, lsp_id,
+ array_size(isis_snmp_trap_data_var_pdu_lsp_id), STRING, lsp_id,
ISIS_SYS_ID_LEN + 2);
return 0;
}
@@ -3183,7 +3184,7 @@ isis_snmp_authentication_type_failure_update(const struct isis_circuit *circuit,
isis_snmp_update_worker_a(
circuit, ISIS_TRAP_AUTHEN_TYPE_FAILURE, NULL, 0, STRING, NULL,
0, isis_snmp_trap_data_var_pdu_fragment,
- ARRAY_SIZE(isis_snmp_trap_data_var_pdu_fragment), STRING,
+ array_size(isis_snmp_trap_data_var_pdu_fragment), STRING,
raw_pdu, raw_pdu_len);
return 0;
}
@@ -3201,7 +3202,7 @@ isis_snmp_authentication_failure_update(const struct isis_circuit *circuit,
isis_snmp_update_worker_a(
circuit, ISIS_TRAP_AUTHEN_FAILURE, NULL, 0, STRING, NULL, 0,
isis_snmp_trap_data_var_pdu_fragment,
- ARRAY_SIZE(isis_snmp_trap_data_var_pdu_fragment), STRING,
+ array_size(isis_snmp_trap_data_var_pdu_fragment), STRING,
raw_pdu, raw_pdu_len);
return 0;
}
@@ -3223,9 +3224,9 @@ static int isis_snmp_version_skew_update(const struct isis_circuit *circuit,
isis_snmp_update_worker_b(
circuit, ISIS_TRAP_VERSION_SKEW,
isis_snmp_trap_data_var_pdu_proto_ver,
- ARRAY_SIZE(isis_snmp_trap_data_var_pdu_proto_ver), UNSIGNED32,
+ array_size(isis_snmp_trap_data_var_pdu_proto_ver), UNSIGNED32,
&val, sizeof(val), isis_snmp_trap_data_var_pdu_fragment,
- ARRAY_SIZE(isis_snmp_trap_data_var_pdu_fragment), STRING,
+ array_size(isis_snmp_trap_data_var_pdu_fragment), STRING,
raw_pdu, raw_pdu_len);
return 0;
}
@@ -3248,7 +3249,7 @@ static int isis_snmp_area_mismatch_update(const struct isis_circuit *circuit,
/* Put in trap value */
snmp_varlist_add_variable(&notification_vars, isis_snmp_trap_var,
- ARRAY_SIZE(isis_snmp_trap_var), ASN_OBJECT_ID,
+ array_size(isis_snmp_trap_var), ASN_OBJECT_ID,
(uint8_t *)&isis_snmp_trap_val_area_mismatch,
sizeof(isis_snmp_trap_val_area_mismatch));
@@ -3260,7 +3261,7 @@ static int isis_snmp_area_mismatch_update(const struct isis_circuit *circuit,
snmp_varlist_add_variable(
&notification_vars, isis_snmp_trap_data_var_circ_if_index,
- ARRAY_SIZE(isis_snmp_trap_data_var_circ_if_index), UNSIGNED32,
+ array_size(isis_snmp_trap_data_var_circ_if_index), UNSIGNED32,
(uint8_t *)&val, sizeof(val));
@@ -3269,7 +3270,7 @@ static int isis_snmp_area_mismatch_update(const struct isis_circuit *circuit,
snmp_varlist_add_variable(
&notification_vars, isis_snmp_trap_data_var_pdu_fragment,
- ARRAY_SIZE(isis_snmp_trap_data_var_pdu_fragment), STRING,
+ array_size(isis_snmp_trap_data_var_pdu_fragment), STRING,
raw_pdu, raw_pdu_len);
send_v2trap(notification_vars);
@@ -3292,7 +3293,7 @@ static int isis_snmp_reject_adjacency_update(const struct isis_circuit *circuit,
isis_snmp_update_worker_a(
circuit, ISIS_TRAP_REJ_ADJACENCY, NULL, 0, STRING, NULL, 0,
isis_snmp_trap_data_var_pdu_fragment,
- ARRAY_SIZE(isis_snmp_trap_data_var_pdu_fragment), STRING,
+ array_size(isis_snmp_trap_data_var_pdu_fragment), STRING,
raw_pdu, raw_pdu_len);
return 0;
}
@@ -3307,9 +3308,9 @@ static int isis_snmp_lsp_too_large_update(const struct isis_circuit *circuit,
isis_snmp_update_worker_b(
circuit, ISIS_TRAP_LSP_TOO_LARGE,
isis_snmp_trap_data_var_pdu_lsp_size,
- ARRAY_SIZE(isis_snmp_trap_data_var_pdu_lsp_size), UNSIGNED32,
+ array_size(isis_snmp_trap_data_var_pdu_lsp_size), UNSIGNED32,
&pdu_size, sizeof(pdu_size), isis_snmp_trap_data_var_pdu_lsp_id,
- ARRAY_SIZE(isis_snmp_trap_data_var_pdu_lsp_id), STRING, lsp_id,
+ array_size(isis_snmp_trap_data_var_pdu_lsp_id), STRING, lsp_id,
ISIS_SYS_ID_LEN + 2);
return 0;
}
@@ -3334,9 +3335,9 @@ static int isis_snmp_adj_state_change_update(const struct isis_adjacency *adj)
isis_snmp_update_worker_b(
adj->circuit, ISIS_TRAP_ADJ_STATE_CHANGE,
isis_snmp_trap_data_var_pdu_lsp_id,
- ARRAY_SIZE(isis_snmp_trap_data_var_pdu_lsp_id), STRING, lsp_id,
+ array_size(isis_snmp_trap_data_var_pdu_lsp_id), STRING, lsp_id,
ISIS_SYS_ID_LEN + 2, isis_snmp_trap_data_var_adj_state,
- ARRAY_SIZE(isis_snmp_trap_data_var_adj_state), INTEGER, &val,
+ array_size(isis_snmp_trap_data_var_adj_state), INTEGER, &val,
sizeof(val));
return 0;
}
@@ -3359,7 +3360,7 @@ static int isis_snmp_lsp_error_update(const struct isis_circuit *circuit,
/* Put in trap value */
snmp_varlist_add_variable(&notification_vars, isis_snmp_trap_var,
- ARRAY_SIZE(isis_snmp_trap_var), ASN_OBJECT_ID,
+ array_size(isis_snmp_trap_var), ASN_OBJECT_ID,
(uint8_t *)&isis_snmp_trap_val_lsp_error,
sizeof(isis_snmp_trap_val_lsp_error));
@@ -3368,13 +3369,13 @@ static int isis_snmp_lsp_error_update(const struct isis_circuit *circuit,
snmp_varlist_add_variable(
&notification_vars, isis_snmp_trap_data_var_sys_level_index,
- ARRAY_SIZE(isis_snmp_trap_data_var_sys_level_index), INTEGER,
+ array_size(isis_snmp_trap_data_var_sys_level_index), INTEGER,
(uint8_t *)&val, sizeof(val));
snmp_varlist_add_variable(
&notification_vars, isis_snmp_trap_data_var_pdu_lsp_id,
- ARRAY_SIZE(isis_snmp_trap_data_var_pdu_lsp_id), STRING, lsp_id,
+ array_size(isis_snmp_trap_data_var_pdu_lsp_id), STRING, lsp_id,
ISIS_SYS_ID_LEN + 2);
/* Prepare data */
@@ -3385,7 +3386,7 @@ static int isis_snmp_lsp_error_update(const struct isis_circuit *circuit,
snmp_varlist_add_variable(
&notification_vars, isis_snmp_trap_data_var_circ_if_index,
- ARRAY_SIZE(isis_snmp_trap_data_var_circ_if_index), UNSIGNED32,
+ array_size(isis_snmp_trap_data_var_circ_if_index), UNSIGNED32,
(uint8_t *)&val, sizeof(val));
/* Prepare data */
@@ -3394,7 +3395,7 @@ static int isis_snmp_lsp_error_update(const struct isis_circuit *circuit,
snmp_varlist_add_variable(
&notification_vars, isis_snmp_trap_data_var_pdu_fragment,
- ARRAY_SIZE(isis_snmp_trap_data_var_pdu_fragment), STRING,
+ array_size(isis_snmp_trap_data_var_pdu_fragment), STRING,
raw_pdu, raw_pdu_len);
/* Prepare data */
@@ -3402,7 +3403,7 @@ static int isis_snmp_lsp_error_update(const struct isis_circuit *circuit,
snmp_varlist_add_variable(
&notification_vars, isis_snmp_trap_data_var_error_offset,
- ARRAY_SIZE(isis_snmp_trap_data_var_error_offset), UNSIGNED32,
+ array_size(isis_snmp_trap_data_var_error_offset), UNSIGNED32,
(uint8_t *)&val, sizeof(val));
/* Prepare data */
@@ -3410,7 +3411,7 @@ static int isis_snmp_lsp_error_update(const struct isis_circuit *circuit,
snmp_varlist_add_variable(
&notification_vars, isis_snmp_trap_data_var_error_tlv_type,
- ARRAY_SIZE(isis_snmp_trap_data_var_error_tlv_type), UNSIGNED32,
+ array_size(isis_snmp_trap_data_var_error_tlv_type), UNSIGNED32,
(uint8_t *)&val, sizeof(val));
send_v2trap(notification_vars);
diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c
index bfe3758cd8..8597049ac0 100644
--- a/isisd/isis_spf.c
+++ b/isisd/isis_spf.c
@@ -1067,8 +1067,8 @@ end:
&& !isis_level2_adj_up(spftree->area)) {
struct prefix_pair ip_info = { {0} };
if (IS_DEBUG_RTE_EVENTS)
- zlog_debug("ISIS-Spf (%s): add default %s route",
- rawlspid_print(lsp->hdr.lsp_id),
+ zlog_debug("ISIS-Spf (%pLS): add default %s route",
+ lsp->hdr.lsp_id,
spftree->family == AF_INET ? "ipv4"
: "ipv6");
@@ -1207,9 +1207,8 @@ static void isis_spf_preload_tent(struct isis_spftree *spftree,
if (isis_lfa_excise_adj_check(spftree, adj_id)) {
if (IS_DEBUG_LFA)
- zlog_debug("ISIS-SPF: excising adjacency %s",
- isis_format_id(sadj->id,
- ISIS_SYS_ID_LEN + 1));
+ zlog_debug("ISIS-SPF: excising adjacency %pPN",
+ sadj->id);
continue;
}
@@ -1324,8 +1323,8 @@ static void spf_adj_list_parse_tlv(struct isis_spftree *spftree,
LSP_FRAGMENT(lspid) = 0;
lsp = lsp_search(spftree->lspdb, lspid);
if (lsp == NULL || lsp->hdr.rem_lifetime == 0) {
- zlog_warn("ISIS-SPF: No LSP found from root to L%d %s",
- spftree->level, rawlspid_print(lspid));
+ zlog_warn("ISIS-SPF: No LSP found from root to L%d %pLS",
+ spftree->level, lspid);
return;
}
@@ -1663,9 +1662,8 @@ static void isis_spf_loop(struct isis_spftree *spftree,
lsp = lsp_for_vertex(spftree, vertex);
if (!lsp) {
- zlog_warn("ISIS-SPF: No LSP found for %s",
- isis_format_id(vertex->N.id,
- sizeof(vertex->N.id)));
+ zlog_warn("ISIS-SPF: No LSP found for %pPN",
+ vertex->N.id);
continue;
}
diff --git a/isisd/isis_sr.c b/isisd/isis_sr.c
index cb330603e4..e43b84ab2e 100644
--- a/isisd/isis_sr.c
+++ b/isisd/isis_sr.c
@@ -1022,14 +1022,14 @@ static void show_node(struct vty *vty, struct isis_area *area, int level)
if (!cap)
continue;
- ttable_add_row(
- tt, "%s|%u - %u|%u - %u|%s|%u",
- sysid_print(lsp->hdr.lsp_id), cap->srgb.lower_bound,
- cap->srgb.lower_bound + cap->srgb.range_size - 1,
- cap->srlb.lower_bound,
- cap->srlb.lower_bound + cap->srlb.range_size - 1,
- cap->algo[0] == SR_ALGORITHM_SPF ? "SPF" : "S-SPF",
- cap->msd);
+ ttable_add_row(tt, "%pSY|%u - %u|%u - %u|%s|%u",
+ lsp->hdr.lsp_id, cap->srgb.lower_bound,
+ cap->srgb.lower_bound + cap->srgb.range_size - 1,
+ cap->srlb.lower_bound,
+ cap->srlb.lower_bound + cap->srlb.range_size - 1,
+ cap->algo[0] == SR_ALGORITHM_SPF ? "SPF"
+ : "S-SPF",
+ cap->msd);
}
/* Dump the generated table. */
diff --git a/isisd/isis_te.c b/isisd/isis_te.c
index 45d763fd69..4e180ead61 100644
--- a/isisd/isis_te.c
+++ b/isisd/isis_te.c
@@ -903,7 +903,7 @@ static int lsp_to_edge_cb(const uint8_t *id, uint32_t metric, bool old_metric,
struct ls_edge *edge, *dst;
struct ls_attributes *attr;
- te_debug(" |- Process Extended IS for %s", sysid_print(id));
+ te_debug(" |- Process Extended IS for %pSY", id);
/* Check parameters */
if (old_metric || !args || !tlvs)
@@ -1075,16 +1075,29 @@ static int lsp_to_subnet_cb(const struct prefix *prefix, uint32_t metric,
}
if (!std)
prefix_copy(&p, prefix);
- else
+ else {
+ /* Remove old subnet if any before prefix adjustment */
+ subnet = ls_find_subnet(args->ted, prefix);
+ if (subnet) {
+ if (args->export) {
+ subnet->status = DELETE;
+ isis_te_export(LS_MSG_TYPE_PREFIX, subnet);
+ }
+ te_debug(" |- Remove subnet with prefix %pFX",
+ &subnet->key);
+ ls_subnet_del_all(args->ted, subnet);
+ }
te_debug(" |- Adjust prefix %pFX with local address to: %pFX",
prefix, &p);
+ }
/* Search existing Subnet in TED ... */
- subnet = ls_find_subnet(args->ted, p);
+ subnet = ls_find_subnet(args->ted, &p);
/* ... and create a new Subnet if not found */
if (!subnet) {
- ls_pref = ls_prefix_new(vertex->node->adv, p);
+ ls_pref = ls_prefix_new(vertex->node->adv, &p);
subnet = ls_subnet_add(args->ted, ls_pref);
+ /* Stop processing if we are unable to create a new subnet */
if (!subnet)
return LSP_ITER_CONTINUE;
}
@@ -1167,14 +1180,14 @@ static void isis_te_parse_lsp(struct mpls_te_area *mta, struct isis_lsp *lsp)
ted = mta->ted;
- te_debug("ISIS-TE(%s): Parse LSP %s", lsp->area->area_tag,
- sysid_print(lsp->hdr.lsp_id));
+ te_debug("ISIS-TE(%s): Parse LSP %pSY", lsp->area->area_tag,
+ lsp->hdr.lsp_id);
/* First parse LSP to obtain the corresponding Vertex */
vertex = lsp_to_vertex(ted, lsp);
if (!vertex) {
- zlog_warn("Unable to build Vertex from LSP %s. Abort!",
- sysid_print(lsp->hdr.lsp_id));
+ zlog_warn("Unable to build Vertex from LSP %pSY. Abort!",
+ lsp->hdr.lsp_id);
return;
}
@@ -1238,8 +1251,8 @@ static void isis_te_delete_lsp(struct mpls_te_area *mta, struct isis_lsp *lsp)
if (!IS_MPLS_TE(mta) || !mta->ted || !lsp)
return;
- te_debug("ISIS-TE(%s): Delete Link State TED objects from LSP %s",
- lsp->area->area_tag, sysid_print(lsp->hdr.lsp_id));
+ te_debug("ISIS-TE(%s): Delete Link State TED objects from LSP %pSY",
+ lsp->area->area_tag, lsp->hdr.lsp_id);
/* Compute Link State Node ID from IS-IS sysID ... */
if (lsp->level == ISIS_LEVEL1)
@@ -1822,7 +1835,7 @@ static int show_ted(struct vty *vty, struct cmd_token *argv[], int argc,
return CMD_WARNING_CONFIG_FAILED;
}
/* Get the Subnet from the Link State Database */
- subnet = ls_find_subnet(ted, pref);
+ subnet = ls_find_subnet(ted, &pref);
if (!subnet) {
vty_out(vty, "No subnet found for ID %pFX\n",
&pref);
@@ -1835,7 +1848,7 @@ static int show_ted(struct vty *vty, struct cmd_token *argv[], int argc,
return CMD_WARNING_CONFIG_FAILED;
}
/* Get the Subnet from the Link State Database */
- subnet = ls_find_subnet(ted, pref);
+ subnet = ls_find_subnet(ted, &pref);
if (!subnet) {
vty_out(vty, "No subnet found for ID %pFX\n",
&pref);
diff --git a/isisd/isis_tlvs.c b/isisd/isis_tlvs.c
index b52a38be7f..3b6db0ee17 100644
--- a/isisd/isis_tlvs.c
+++ b/isisd/isis_tlvs.c
@@ -661,7 +661,7 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
sbuf_push(
buf, indent,
"Lan-Adjacency-SID: %u, Weight: %hhu, Flags: F:%c B:%c, V:%c, L:%c, S:%c, P:%c\n"
- " Neighbor-ID: %s\n",
+ " Neighbor-ID: %pSY\n",
lan->sid, lan->weight,
lan->flags & EXT_SUBTLV_LINK_ADJ_SID_FFLG
? '1'
@@ -681,7 +681,7 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
lan->flags & EXT_SUBTLV_LINK_ADJ_SID_PFLG
? '1'
: '0',
- isis_format_id(lan->neighbor_id, 6));
+ lan->neighbor_id);
}
}
}
@@ -1590,14 +1590,14 @@ static void format_item_area_address(uint16_t mtid, struct isis_item *i,
int indent)
{
struct isis_area_address *addr = (struct isis_area_address *)i;
+ struct iso_address iso_addr;
- if (json) {
- json_object_string_add(json, "area-addr",
- isonet_print(addr->addr, addr->len));
- } else {
- sbuf_push(buf, indent, "Area Address: %s\n",
- isonet_print(addr->addr, addr->len));
- }
+ memcpy(iso_addr.area_addr, addr->addr, ISO_ADDR_SIZE);
+ iso_addr.addr_len = addr->len;
+ if (json)
+ json_object_string_addf(json, "area-addr", "%pIS", &iso_addr);
+ else
+ sbuf_push(buf, indent, "Area Address: %pIS\n", &iso_addr);
}
static void free_item_area_address(struct isis_item *i)
@@ -1678,17 +1678,18 @@ static void format_item_oldstyle_reach(uint16_t mtid, struct isis_item *i,
struct json_object *json, int indent)
{
struct isis_oldstyle_reach *r = (struct isis_oldstyle_reach *)i;
+ char sys_id[ISO_SYSID_STRLEN];
+ snprintfrr(sys_id, ISO_SYSID_STRLEN, "%pPN", r->id);
if (json) {
struct json_object *old_json;
old_json = json_object_new_object();
json_object_object_add(json, "old-reach-style", old_json);
- json_object_string_add(old_json, "is-reach",
- isis_format_id(r->id, 7));
+ json_object_string_add(old_json, "is-reach", sys_id);
json_object_int_add(old_json, "metric", r->metric);
} else
sbuf_push(buf, indent, "IS Reachability: %s (Metric: %hhu)\n",
- isis_format_id(r->id, 7), r->metric);
+ sys_id, r->metric);
}
static void free_item_oldstyle_reach(struct isis_item *i)
@@ -1760,13 +1761,13 @@ static void format_item_lan_neighbor(uint16_t mtid, struct isis_item *i,
int indent)
{
struct isis_lan_neighbor *n = (struct isis_lan_neighbor *)i;
+ char sys_id[ISO_SYSID_STRLEN];
- if (json) {
- json_object_string_add(json, "lan-neighbor",
- isis_format_id(n->mac, 6));
- } else
- sbuf_push(buf, indent, "LAN Neighbor: %s\n",
- isis_format_id(n->mac, 6));
+ snprintfrr(sys_id, ISO_SYSID_STRLEN, "%pSY", n->mac);
+ if (json)
+ json_object_string_add(json, "lan-neighbor", sys_id);
+ else
+ sbuf_push(buf, indent, "LAN Neighbor: %s\n", sys_id);
}
static void free_item_lan_neighbor(struct isis_item *i)
@@ -1831,23 +1832,25 @@ static void format_item_lsp_entry(uint16_t mtid, struct isis_item *i,
int indent)
{
struct isis_lsp_entry *e = (struct isis_lsp_entry *)i;
+ char sys_id[ISO_SYSID_STRLEN];
+ snprintfrr(sys_id, ISO_SYSID_STRLEN, "%pLS", e->id);
if (json) {
char buf[255];
struct json_object *lsp_json;
lsp_json = json_object_new_object();
json_object_object_add(json, "lsp-entry", lsp_json);
- json_object_string_add(lsp_json, "id", isis_format_id(e->id, 8));
+ json_object_string_add(lsp_json, "id", sys_id);
snprintfrr(buf,sizeof(buf),"0x%08x",e->seqno);
json_object_string_add(lsp_json, "seq", buf);
snprintfrr(buf,sizeof(buf),"0x%04hx",e->checksum);
json_object_string_add(lsp_json, "chksum", buf);
json_object_int_add(lsp_json, "lifetime", e->checksum);
} else
- sbuf_push(buf, indent,
- "LSP Entry: %s, seq 0x%08x, cksum 0x%04hx, lifetime %hus\n",
- isis_format_id(e->id, 8), e->seqno, e->checksum,
- e->rem_lifetime);
+ sbuf_push(
+ buf, indent,
+ "LSP Entry: %s, seq 0x%08x, cksum 0x%04hx, lifetime %hus\n",
+ sys_id, e->seqno, e->checksum, e->rem_lifetime);
}
static void free_item_lsp_entry(struct isis_item *i)
@@ -1919,7 +1922,9 @@ static void format_item_extended_reach(uint16_t mtid, struct isis_item *i,
struct json_object *json, int indent)
{
struct isis_extended_reach *r = (struct isis_extended_reach *)i;
+ char sys_id[ISO_SYSID_STRLEN];
+ snprintfrr(sys_id, ISO_SYSID_STRLEN, "%pPN", r->id);
if (json) {
struct json_object *reach_json;
reach_json = json_object_new_object();
@@ -1927,8 +1932,7 @@ static void format_item_extended_reach(uint16_t mtid, struct isis_item *i,
json_object_string_add(
reach_json, "mt-id",
(mtid == ISIS_MT_IPV4_UNICAST) ? "Extended" : "MT");
- json_object_string_add(reach_json, "id",
- isis_format_id(r->id, 7));
+ json_object_string_add(reach_json, "id", sys_id);
json_object_int_add(reach_json, "metric", r->metric);
if (mtid != ISIS_MT_IPV4_UNICAST)
json_object_string_add(reach_json, "mt-name",
@@ -1940,7 +1944,7 @@ static void format_item_extended_reach(uint16_t mtid, struct isis_item *i,
} else {
sbuf_push(buf, indent, "%s Reachability: %s (Metric: %u)",
(mtid == ISIS_MT_IPV4_UNICAST) ? "Extended" : "MT",
- isis_format_id(r->id, 7), r->metric);
+ sys_id, r->metric);
if (mtid != ISIS_MT_IPV4_UNICAST)
sbuf_push(buf, 0, " %s", isis_mtid2str(mtid));
sbuf_push(buf, 0, "\n");
@@ -3125,9 +3129,12 @@ static void
format_tlv_threeway_adj(const struct isis_threeway_adj *threeway_adj,
struct sbuf *buf, struct json_object *json, int indent)
{
+ char sys_id[ISO_SYSID_STRLEN];
+
if (!threeway_adj)
return;
+ snprintfrr(sys_id, ISO_SYSID_STRLEN, "%pSY", threeway_adj->neighbor_id);
if (json) {
struct json_object *three_json;
three_json = json_object_new_object();
@@ -3140,9 +3147,7 @@ format_tlv_threeway_adj(const struct isis_threeway_adj *threeway_adj,
threeway_adj->local_circuit_id);
if (!threeway_adj->neighbor_set)
return;
- json_object_string_add(
- three_json, "neigh-system-id",
- isis_format_id(threeway_adj->neighbor_id, 6));
+ json_object_string_add(three_json, "neigh-system-id", sys_id);
json_object_int_add(three_json, "neigh-ext-circuit-id",
threeway_adj->neighbor_circuit_id);
} else {
@@ -3155,8 +3160,7 @@ format_tlv_threeway_adj(const struct isis_threeway_adj *threeway_adj,
if (!threeway_adj->neighbor_set)
return;
- sbuf_push(buf, indent, " Neighbor System ID: %s\n",
- isis_format_id(threeway_adj->neighbor_id, 6));
+ sbuf_push(buf, indent, " Neighbor System ID: %s\n", sys_id);
sbuf_push(buf, indent, " Neighbor Extended Circuit ID: %u\n",
threeway_adj->neighbor_circuit_id);
}
@@ -3988,33 +3992,29 @@ static void format_tlv_purge_originator(struct isis_purge_originator *poi,
struct sbuf *buf,
struct json_object *json, int indent)
{
+ char sen_id[ISO_SYSID_STRLEN];
+ char gen_id[ISO_SYSID_STRLEN];
+
if (!poi)
return;
+ snprintfrr(gen_id, ISO_SYSID_STRLEN, "%pSY", poi->generator);
+ if (poi->sender_set)
+ snprintfrr(sen_id, ISO_SYSID_STRLEN, "%pSY", poi->sender);
+
if (json) {
struct json_object *purge_json;
purge_json = json_object_new_object();
json_object_object_add(json, "purge_originator", purge_json);
- json_object_string_add(
- purge_json, "id",
- isis_format_id(poi->generator, sizeof(poi->generator)));
- if (poi->sender_set) {
- json_object_string_add(
- purge_json, "rec-from",
- isis_format_id(poi->sender,
- sizeof(poi->sender)));
- }
+ json_object_string_add(purge_json, "id", gen_id);
+ if (poi->sender_set)
+ json_object_string_add(purge_json, "rec-from", sen_id);
} else {
sbuf_push(buf, indent, "Purge Originator Identification:\n");
- sbuf_push(
- buf, indent, " Generator: %s\n",
- isis_format_id(poi->generator, sizeof(poi->generator)));
- if (poi->sender_set) {
- sbuf_push(buf, indent, " Received-From: %s\n",
- isis_format_id(poi->sender,
- sizeof(poi->sender)));
- }
+ sbuf_push(buf, indent, " Generator: %s\n", gen_id);
+ if (poi->sender_set)
+ sbuf_push(buf, indent, " Received-From: %s\n", sen_id);
}
}
@@ -5271,14 +5271,14 @@ void isis_tlvs_add_area_addresses(struct isis_tlvs *tlvs,
struct list *addresses)
{
struct listnode *node;
- struct area_addr *area_addr;
+ struct iso_address *area_addr;
for (ALL_LIST_ELEMENTS_RO(addresses, node, area_addr)) {
struct isis_area_address *a =
XCALLOC(MTYPE_ISIS_TLV, sizeof(*a));
a->len = area_addr->addr_len;
- memcpy(a->addr, area_addr->area_addr, 20);
+ memcpy(a->addr, area_addr->area_addr, ISO_ADDR_SIZE);
append_item(&tlvs->area_addresses, (struct isis_item *)a);
}
}
@@ -5475,7 +5475,7 @@ bool isis_tlvs_area_addresses_match(struct isis_tlvs *tlvs,
for (struct isis_area_address *addr = addr_head; addr;
addr = addr->next) {
struct listnode *node;
- struct area_addr *a;
+ struct iso_address *a;
for (ALL_LIST_ELEMENTS_RO(addresses, node, a)) {
if (a->addr_len == addr->len
diff --git a/isisd/isis_tx_queue.c b/isisd/isis_tx_queue.c
index ec2d50d60a..caf97f1174 100644
--- a/isisd/isis_tx_queue.c
+++ b/isisd/isis_tx_queue.c
@@ -126,12 +126,12 @@ void _isis_tx_queue_add(struct isis_tx_queue *queue,
return;
if (IS_DEBUG_TX_QUEUE) {
- zlog_debug("Add LSP %s to %s queue as %s LSP. (From %s %s:%d)",
- rawlspid_print(lsp->hdr.lsp_id),
- queue->circuit->interface->name,
- (type == TX_LSP_CIRCUIT_SCOPED) ?
- "circuit scoped" : "regular",
- func, file, line);
+ zlog_debug(
+ "Add LSP %pLS to %s queue as %s LSP. (From %s %s:%d)",
+ lsp->hdr.lsp_id, queue->circuit->interface->name,
+ (type == TX_LSP_CIRCUIT_SCOPED) ? "circuit scoped"
+ : "regular",
+ func, file, line);
}
struct isis_tx_queue_entry *e = tx_queue_find(queue, lsp);
@@ -164,9 +164,8 @@ void _isis_tx_queue_del(struct isis_tx_queue *queue, struct isis_lsp *lsp,
return;
if (IS_DEBUG_TX_QUEUE) {
- zlog_debug("Remove LSP %s from %s queue. (From %s %s:%d)",
- rawlspid_print(lsp->hdr.lsp_id),
- queue->circuit->interface->name,
+ zlog_debug("Remove LSP %pLS from %s queue. (From %s %s:%d)",
+ lsp->hdr.lsp_id, queue->circuit->interface->name,
func, file, line);
}
diff --git a/isisd/isisd.c b/isisd/isisd.c
index c6369a884e..fd6b91b42e 100644
--- a/isisd/isisd.c
+++ b/isisd/isisd.c
@@ -272,7 +272,7 @@ void isis_area_del_circuit(struct isis_area *area, struct isis_circuit *circuit)
static void delete_area_addr(void *arg)
{
- struct area_addr *addr = (struct area_addr *)arg;
+ struct iso_address *addr = (struct iso_address *)arg;
XFREE(MTYPE_ISIS_AREA_ADDR, addr);
}
@@ -809,8 +809,8 @@ static void area_set_mt_overload(struct isis_area *area, uint16_t mtid,
int area_net_title(struct vty *vty, const char *net_title)
{
VTY_DECLVAR_CONTEXT(isis_area, area);
- struct area_addr *addr;
- struct area_addr *addrp;
+ struct iso_address *addr;
+ struct iso_address *addrp;
struct listnode *node;
uint8_t buff[255];
@@ -823,14 +823,14 @@ int area_net_title(struct vty *vty, const char *net_title)
return CMD_ERR_NOTHING_TODO;
}
- addr = XMALLOC(MTYPE_ISIS_AREA_ADDR, sizeof(struct area_addr));
+ addr = XMALLOC(MTYPE_ISIS_AREA_ADDR, sizeof(struct iso_address));
addr->addr_len = dotformat2buff(buff, net_title);
memcpy(addr->area_addr, buff, addr->addr_len);
#ifdef EXTREME_DEBUG
zlog_debug("added area address %s for area %s (address length %d)",
net_title, area->area_tag, addr->addr_len);
#endif /* EXTREME_DEBUG */
- if (addr->addr_len < 8 || addr->addr_len > 20) {
+ if (addr->addr_len < ISO_ADDR_MIN || addr->addr_len > ISO_ADDR_SIZE) {
vty_out(vty,
"area address must be at least 8..20 octets long (%d)\n",
addr->addr_len);
@@ -852,8 +852,8 @@ int area_net_title(struct vty *vty, const char *net_title)
memcpy(area->isis->sysid, GETSYSID(addr), ISIS_SYS_ID_LEN);
area->isis->sysid_set = 1;
if (IS_DEBUG_EVENTS)
- zlog_debug("Router has SystemID %s",
- sysid_print(area->isis->sysid));
+ zlog_debug("Router has SystemID %pSY",
+ area->isis->sysid);
} else {
/*
* Check that the SystemID portions match
@@ -899,12 +899,12 @@ int area_net_title(struct vty *vty, const char *net_title)
int area_clear_net_title(struct vty *vty, const char *net_title)
{
VTY_DECLVAR_CONTEXT(isis_area, area);
- struct area_addr addr, *addrp = NULL;
+ struct iso_address addr, *addrp = NULL;
struct listnode *node;
uint8_t buff[255];
addr.addr_len = dotformat2buff(buff, net_title);
- if (addr.addr_len < 8 || addr.addr_len > 20) {
+ if (addr.addr_len < ISO_ADDR_MIN || addr.addr_len > ISO_ADDR_SIZE) {
vty_out(vty,
"Unsupported area address length %d, should be 8...20 \n",
addr.addr_len);
@@ -2348,11 +2348,11 @@ static void common_isis_summary_json(struct json_object *json,
time_t cur;
char uptime[MONOTIME_STRLEN];
char stier[5];
+
json_object_string_add(json, "vrf", isis->name);
json_object_int_add(json, "process-id", isis->process_id);
if (isis->sysid_set)
- json_object_string_add(json, "system-id",
- sysid_print(isis->sysid));
+ json_object_string_addf(json, "system-id", "%pSY", isis->sysid);
cur = time(NULL);
cur -= isis->uptime;
@@ -2380,16 +2380,11 @@ static void common_isis_summary_json(struct json_object *json,
}
if (listcount(area->area_addrs) > 0) {
- struct area_addr *area_addr;
+ struct iso_address *area_addr;
for (ALL_LIST_ELEMENTS_RO(area->area_addrs, node2,
- area_addr)) {
- json_object_string_add(
- area_json, "net",
- isonet_print(area_addr->area_addr,
- area_addr->addr_len +
- ISIS_SYS_ID_LEN +
- 1));
- }
+ area_addr))
+ json_object_string_addf(area_json, "net",
+ "%pISl", area_addr);
}
tx_pdu_json = json_object_new_object();
@@ -2462,8 +2457,7 @@ static void common_isis_summary_vty(struct vty *vty, struct isis *isis)
vty_out(vty, "vrf : %s\n", isis->name);
vty_out(vty, "Process Id : %ld\n", isis->process_id);
if (isis->sysid_set)
- vty_out(vty, "System Id : %s\n",
- sysid_print(isis->sysid));
+ vty_out(vty, "System Id : %pSY\n", isis->sysid);
vty_out(vty, "Up time : ");
vty_out_timestr(vty, isis->uptime);
@@ -2485,15 +2479,10 @@ static void common_isis_summary_vty(struct vty *vty, struct isis *isis)
}
if (listcount(area->area_addrs) > 0) {
- struct area_addr *area_addr;
+ struct iso_address *area_addr;
for (ALL_LIST_ELEMENTS_RO(area->area_addrs, node2,
- area_addr)) {
- vty_out(vty, " Net: %s\n",
- isonet_print(area_addr->area_addr,
- area_addr->addr_len
- + ISIS_SYS_ID_LEN
- + 1));
- }
+ area_addr))
+ vty_out(vty, " Net: %pISl\n", area_addr);
}
vty_out(vty, " TX counters per PDU type:\n");
@@ -3497,15 +3486,10 @@ static int isis_config_write(struct vty *vty)
write++;
/* ISIS - Net */
if (listcount(area->area_addrs) > 0) {
- struct area_addr *area_addr;
+ struct iso_address *area_addr;
for (ALL_LIST_ELEMENTS_RO(area->area_addrs,
node2, area_addr)) {
- vty_out(vty, " net %s\n",
- isonet_print(
- area_addr->area_addr,
- area_addr->addr_len
- + ISIS_SYS_ID_LEN
- + 1));
+ vty_out(vty, " net %pISl\n", area_addr);
write++;
}
}
diff --git a/isisd/isisd.h b/isisd/isisd.h
index e0f7ca882e..12d9cd36c4 100644
--- a/isisd/isisd.h
+++ b/isisd/isisd.h
@@ -24,6 +24,7 @@
#include "isis_lfa.h"
#include "qobj.h"
#include "ldp_sync.h"
+#include "iso.h"
DECLARE_MGROUP(ISISD);
@@ -87,7 +88,7 @@ struct isis {
uint32_t router_id; /* Router ID from zebra */
struct list *area_list; /* list of IS-IS areas */
uint8_t max_area_addrs; /* maximumAreaAdresses */
- struct area_addr *man_area_addrs; /* manualAreaAddresses */
+ struct iso_address *man_area_addrs; /* manualAreaAddresses */
time_t uptime; /* when did we start */
struct event *t_dync_clean; /* dynamic hostname cache cleanup thread */
uint32_t circuit_ids_used[8]; /* 256 bits to track circuit ids 1 through 255 */
diff --git a/lib/compiler.h b/lib/compiler.h
index d12e282832..29fcfbefbf 100644
--- a/lib/compiler.h
+++ b/lib/compiler.h
@@ -439,6 +439,14 @@ _Static_assert(sizeof(_uint64_t) == 8 && sizeof(_int64_t) == 8,
#pragma diag_suppress 167
#endif /* __INTELISENSE__ */
+#if defined(__GNUC__) && (__GNUC__ >= 3)
+#define likely(_x) __builtin_expect(!!(_x), 1)
+#define unlikely(_x) __builtin_expect(!!(_x), 0)
+#else
+#define likely(_x) !!(_x)
+#define unlikely(_x) !!(_x)
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/cspf.c b/lib/cspf.c
index b92c9cb395..6a0fb7f63c 100644
--- a/lib/cspf.c
+++ b/lib/cspf.c
@@ -88,7 +88,7 @@ static struct c_path *cpath_copy(struct c_path *dest, const struct c_path *src)
*
* @param path Constrained Path structure to be deleted
*/
-static void cpath_del(struct c_path *path)
+void cpath_del(struct c_path *path)
{
if (!path)
return;
diff --git a/lib/cspf.h b/lib/cspf.h
index 3eceaa04af..bba685a617 100644
--- a/lib/cspf.h
+++ b/lib/cspf.h
@@ -191,6 +191,8 @@ extern void cspf_del(struct cspf *algo);
*/
extern struct c_path *compute_p2p_path(struct cspf *algo, struct ls_ted *ted);
+extern void cpath_del(struct c_path *path);
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/if_rmap.c b/lib/if_rmap.c
index 27c41aaa27..0d305a7af1 100644
--- a/lib/if_rmap.c
+++ b/lib/if_rmap.c
@@ -10,6 +10,7 @@
#include "memory.h"
#include "if.h"
#include "if_rmap.h"
+#include "ripd/ripd.h"
DEFINE_MTYPE_STATIC(LIB, IF_RMAP_CTX, "Interface route map container");
DEFINE_MTYPE_STATIC(LIB, IF_RMAP_CTX_NAME,
@@ -186,8 +187,13 @@ DEFUN (if_rmap,
int idx_in_out = 2;
int idx_ifname = 3;
enum if_rmap_type type;
- struct if_rmap_ctx *ctx =
- (struct if_rmap_ctx *)listnode_head(if_rmap_ctx_list);
+ struct if_rmap_ctx *ctx;
+ const struct lyd_node *dnode;
+ struct rip *rip;
+
+ dnode = yang_dnode_get(running_config->dnode, VTY_CURR_XPATH);
+ rip = nb_running_get_entry(dnode, NULL, true);
+ ctx = rip->if_rmap_ctx;
if (strncmp(argv[idx_in_out]->text, "in", 1) == 0)
type = IF_RMAP_IN;
@@ -278,7 +284,7 @@ void if_rmap_ctx_delete(struct if_rmap_ctx *ctx)
listnode_delete(if_rmap_ctx_list, ctx);
hash_clean_and_free(&ctx->ifrmaphash, (void (*)(void *))if_rmap_free);
if (ctx->name)
- XFREE(MTYPE_IF_RMAP_CTX_NAME, ctx);
+ XFREE(MTYPE_IF_RMAP_CTX_NAME, ctx->name);
XFREE(MTYPE_IF_RMAP_CTX, ctx);
}
@@ -289,8 +295,7 @@ struct if_rmap_ctx *if_rmap_ctx_create(const char *name)
ctx = XCALLOC(MTYPE_IF_RMAP_CTX, sizeof(struct if_rmap_ctx));
- if (ctx->name)
- ctx->name = XSTRDUP(MTYPE_IF_RMAP_CTX_NAME, name);
+ ctx->name = XSTRDUP(MTYPE_IF_RMAP_CTX_NAME, name);
ctx->ifrmaphash = hash_create_size(4, if_rmap_hash_make, if_rmap_hash_cmp,
"Interface Route-Map Hash");
if (!if_rmap_ctx_list)
diff --git a/lib/iso.c b/lib/iso.c
new file mode 100644
index 0000000000..fe97776ade
--- /dev/null
+++ b/lib/iso.c
@@ -0,0 +1,144 @@
+/*
+ * ISO Network functions - iso_net.c
+ *
+ * Author: Olivier Dugeon <olivier.dugeon@orange.com>
+ *
+ * Copyright (C) 2023 Orange http://www.orange.com
+ *
+ * This file is part of Free Range Routing (FRR).
+ *
+ * FRR is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * FRR is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "compiler.h"
+
+#include <string.h>
+#include <ctype.h>
+#include <time.h>
+
+#include "printfrr.h"
+#include "iso.h"
+
+/**
+ * Print ISO System ID as 0000.0000.0000
+ *
+ * @param Print buffer
+ * @param Print argument
+ * @param Pointer to the System ID to be printed
+ *
+ * @return Number of printed characters
+ */
+printfrr_ext_autoreg_p("SY", printfrr_iso_sysid);
+static ssize_t printfrr_iso_sysid(struct fbuf *buf, struct printfrr_eargs *ea,
+ const void *vptr)
+{
+ const uint8_t *id = vptr;
+
+ if (!id)
+ return bputs(buf, "(null)");
+
+ return bprintfrr(buf, "%02x%02x.%02x%02x.%02x%02x",
+ id[0], id[1], id[2], id[3], id[4], id[5]);
+}
+
+/**
+ * Print ISO Pseudo Node system ID as 0000.0000.0000.00
+ *
+ * @param Print buffer
+ * @param Print argument
+ * @param Pointer to the System ID to be printed
+ *
+ * @return Number of printed characters
+ */
+printfrr_ext_autoreg_p("PN", printfrr_iso_pseudo);
+static ssize_t printfrr_iso_pseudo(struct fbuf *buf, struct printfrr_eargs *ea,
+ const void *vptr)
+{
+ const uint8_t *id = vptr;
+
+ if (!id)
+ return bputs(buf, "(null)");
+
+ return bprintfrr(buf, "%02x%02x.%02x%02x.%02x%02x.%02x",
+ id[0], id[1], id[2], id[3], id[4], id[5], id[6]);
+}
+
+/**
+ * Print ISO LSP Fragment System ID as 0000.0000.0000.00-00
+ *
+ * @param Print buffer
+ * @param Print argument
+ * @param Pointer to the System ID to be printed
+ *
+ * @return Number of printed characters
+ */
+printfrr_ext_autoreg_p("LS", printfrr_iso_frag_id);
+static ssize_t printfrr_iso_frag_id(struct fbuf *buf, struct printfrr_eargs *ea,
+ const void *vptr)
+{
+ const uint8_t *id = vptr;
+
+ if (!id)
+ return bputs(buf, "(null)");
+
+ return bprintfrr(buf, "%02x%02x.%02x%02x.%02x%02x.%02x-%02x",
+ id[0], id[1], id[2], id[3], id[4], id[5], id[6],
+ id[7]);
+}
+
+/**
+ * Print ISO Network address as 00.0000.0000.0000 ... with the System ID
+ * as 0000.0000.0000.00 when long 'l' option is added to '%pIS'
+ *
+ * @param Print buffer
+ * @param Print argument
+ * @param Pointer to the ISO Network address
+ *
+ * @return Number of printed characters
+ */
+printfrr_ext_autoreg_p("IS", printfrr_iso_addr);
+static ssize_t printfrr_iso_addr(struct fbuf *buf, struct printfrr_eargs *ea,
+ const void *vptr)
+{
+ const struct iso_address *ia = vptr;
+ uint8_t len = 0;
+ int i = 0;
+ ssize_t ret = 0;
+
+ if (ea->fmt[0] == 'l') {
+ len = 7; /* ISO SYSTEM ID + 1 */
+ ea->fmt++;
+ }
+
+ if (!ia)
+ return bputs(buf, "(null)");
+
+ len += ia->addr_len;
+ while (i < len) {
+ /* No dot for odd index and at the end of address */
+ if ((i & 1) || (i == (len - 1)))
+ ret += bprintfrr(buf, "%02x", ia->area_addr[i]);
+ else
+ ret += bprintfrr(buf, "%02x.", ia->area_addr[i]);
+ i++;
+ }
+
+ return ret;
+}
+
diff --git a/lib/iso.h b/lib/iso.h
new file mode 100644
index 0000000000..975d3c154b
--- /dev/null
+++ b/lib/iso.h
@@ -0,0 +1,49 @@
+/*
+ * ISO Network definition - iso_net.h
+ *
+ * Author: Olivier Dugeon <olivier.dugeon@orange.com>
+ *
+ * Copyright (C) 2023 Orange http://www.orange.com
+ *
+ * This file is part of Free Range Routing (FRR).
+ *
+ * FRR is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * FRR is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef LIB_ISO_H_
+#define LIB_ISO_H_
+
+#include "compiler.h"
+
+/* len of "xx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xx" + '\0' */
+#define ISO_ADDR_STRLEN 51
+#define ISO_ADDR_MIN 8
+#define ISO_ADDR_SIZE 20
+struct iso_address {
+ uint8_t addr_len;
+ uint8_t area_addr[ISO_ADDR_SIZE];
+};
+
+/* len of "xxxx.xxxx.xxxx.xx-xx" + '\0' */
+#define ISO_SYSID_STRLEN 21
+
+#ifdef _FRR_ATTRIBUTE_PRINTFRR
+#pragma FRR printfrr_ext "%pSY" (uint8_t *)
+#pragma FRR printfrr_ext "%pPN" (uint8_t *)
+#pragma FRR printfrr_ext "%pLS" (uint8_t *)
+#pragma FRR printfrr_ext "%pIS" (struct iso_address *)
+#endif
+
+#endif /* LIB_ISO_H_ */
diff --git a/lib/link_state.c b/lib/link_state.c
index 589c0ae704..076030a839 100644
--- a/lib/link_state.c
+++ b/lib/link_state.c
@@ -26,6 +26,7 @@
#include "printfrr.h"
#include <lib/json.h>
#include "link_state.h"
+#include "iso.h"
/* Link State Memory allocation */
DEFINE_MTYPE_STATIC(LIB, LS_DB, "Link State Database");
@@ -333,7 +334,7 @@ int ls_attributes_same(struct ls_attributes *l1, struct ls_attributes *l2)
/**
* Link State prefix management functions
*/
-struct ls_prefix *ls_prefix_new(struct ls_node_id adv, struct prefix p)
+struct ls_prefix *ls_prefix_new(struct ls_node_id adv, struct prefix *p)
{
struct ls_prefix *new;
@@ -342,7 +343,7 @@ struct ls_prefix *ls_prefix_new(struct ls_node_id adv, struct prefix p)
new = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_prefix));
new->adv = adv;
- new->pref = p;
+ new->pref = *p;
return new;
}
@@ -889,7 +890,7 @@ struct ls_subnet *ls_subnet_update(struct ls_ted *ted, struct ls_prefix *pref)
if (pref == NULL)
return NULL;
- old = ls_find_subnet(ted, pref->pref);
+ old = ls_find_subnet(ted, &pref->pref);
if (old) {
if (!ls_prefix_same(old->ls_pref, pref)) {
ls_prefix_del(old->ls_pref);
@@ -942,11 +943,12 @@ void ls_subnet_del_all(struct ls_ted *ted, struct ls_subnet *subnet)
ls_subnet_del(ted, subnet);
}
-struct ls_subnet *ls_find_subnet(struct ls_ted *ted, const struct prefix prefix)
+struct ls_subnet *ls_find_subnet(struct ls_ted *ted,
+ const struct prefix *prefix)
{
struct ls_subnet subnet = {};
- subnet.key = prefix;
+ subnet.key = *prefix;
return subnets_find(&ted->subnets, &subnet);
}
@@ -1846,7 +1848,7 @@ struct ls_subnet *ls_msg2subnet(struct ls_ted *ted, struct ls_message *msg,
subnet->status = UPDATE;
break;
case LS_MSG_EVENT_DELETE:
- subnet = ls_find_subnet(ted, pref->pref);
+ subnet = ls_find_subnet(ted, &pref->pref);
if (subnet) {
if (delete)
ls_subnet_del_all(ted, subnet);
@@ -1965,13 +1967,9 @@ static const char *const status2txt[] = {
static const char *ls_node_id_to_text(struct ls_node_id lnid, char *str,
size_t size)
{
- if (lnid.origin == ISIS_L1 || lnid.origin == ISIS_L2) {
- uint8_t *id;
-
- id = lnid.id.iso.sys_id;
- snprintfrr(str, size, "%02x%02x.%02x%02x.%02x%02x", id[0],
- id[1], id[2], id[3], id[4], id[5]);
- } else
+ if (lnid.origin == ISIS_L1 || lnid.origin == ISIS_L2)
+ snprintfrr(str, size, "%pSY", lnid.id.iso.sys_id);
+ else
snprintfrr(str, size, "%pI4", &lnid.id.ip.addr);
return str;
diff --git a/lib/link_state.h b/lib/link_state.h
index e6a6388ba4..b75f035431 100644
--- a/lib/link_state.h
+++ b/lib/link_state.h
@@ -314,7 +314,7 @@ extern int ls_attributes_same(struct ls_attributes *a1,
*
* @return New Link State Prefix
*/
-extern struct ls_prefix *ls_prefix_new(struct ls_node_id adv, struct prefix p);
+extern struct ls_prefix *ls_prefix_new(struct ls_node_id adv, struct prefix *p);
/**
* Remove Link State Prefix. Data Structure is freed.
@@ -709,7 +709,7 @@ extern void ls_subnet_del_all(struct ls_ted *ted, struct ls_subnet *subnet);
* @return Subnet if found, NULL otherwise
*/
extern struct ls_subnet *ls_find_subnet(struct ls_ted *ted,
- const struct prefix prefix);
+ const struct prefix *prefix);
/**
* Create a new Link State Data Base.
diff --git a/lib/prefix.c b/lib/prefix.c
index a6aae08a6a..b8cad910f4 100644
--- a/lib/prefix.c
+++ b/lib/prefix.c
@@ -1399,7 +1399,7 @@ bool ipv4_unicast_valid(const struct in_addr *addr)
if (IPV4_CLASS_D(ip))
return false;
- if (IPV4_CLASS_E(ip)) {
+ if (IPV4_NET0(ip) || IPV4_NET127(ip) || IPV4_CLASS_E(ip)) {
if (cmd_allow_reserved_ranges_get())
return true;
else
diff --git a/lib/prefix.h b/lib/prefix.h
index 9c57283706..88a228b55c 100644
--- a/lib/prefix.h
+++ b/lib/prefix.h
@@ -499,11 +499,8 @@ extern int macstr2prefix_evpn(const char *str, struct prefix_evpn *p);
/* NOTE: This routine expects the address argument in network byte order. */
static inline bool ipv4_martian(const struct in_addr *addr)
{
- in_addr_t ip = ntohl(addr->s_addr);
-
- if (IPV4_NET0(ip) || IPV4_NET127(ip) || !ipv4_unicast_valid(addr)) {
+ if (!ipv4_unicast_valid(addr))
return true;
- }
return false;
}
diff --git a/lib/routemap.c b/lib/routemap.c
index 16da81fa74..20dcd2a53d 100644
--- a/lib/routemap.c
+++ b/lib/routemap.c
@@ -669,7 +669,7 @@ static struct route_map *route_map_add(const char *name)
if (!map->ipv6_prefix_table)
map->ipv6_prefix_table = route_table_init();
- if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))
+ if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)))
zlog_debug("Add route-map %s", name);
return map;
}
@@ -689,7 +689,7 @@ static void route_map_free_map(struct route_map *map)
while ((index = map->head) != NULL)
route_map_index_delete(index, 0);
- if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))
+ if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)))
zlog_debug("Deleting route-map %s", map->name);
list = &route_map_master;
@@ -706,6 +706,9 @@ static void route_map_free_map(struct route_map *map)
else
list->head = map->next;
+ route_table_finish(map->ipv4_prefix_table);
+ route_table_finish(map->ipv6_prefix_table);
+
hash_release(route_map_master_hash, map);
XFREE(MTYPE_ROUTE_MAP_NAME, map->name);
XFREE(MTYPE_ROUTE_MAP, map);
@@ -1120,7 +1123,7 @@ void route_map_index_delete(struct route_map_index *index, int notify)
QOBJ_UNREG(index);
- if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))
+ if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)))
zlog_debug("Deleting route-map %s sequence %d",
index->map->name, index->pref);
@@ -1231,7 +1234,7 @@ route_map_index_add(struct route_map *map, enum route_map_type type, int pref)
route_map_notify_dependencies(map->name, RMAP_EVENT_CALL_ADDED);
}
- if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))
+ if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)))
zlog_debug("Route-map %s add sequence %d, type: %s",
map->name, pref, route_map_type_str(type));
@@ -1811,10 +1814,8 @@ route_map_get_index(struct route_map *map, const struct prefix *prefix,
* must be AF_INET or AF_INET6 in order for the lookup to succeed. So if
* the AF doesn't line up with the LPM trees, skip the optimization.
*/
- if (map->optimization_disabled ||
- (prefix->family == AF_INET && !map->ipv4_prefix_table) ||
- (prefix->family == AF_INET6 && !map->ipv6_prefix_table)) {
- if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))
+ if (map->optimization_disabled) {
+ if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)))
zlog_debug(
"Skipping route-map optimization for route-map: %s, pfx: %pFX, family: %d",
map->name, prefix, prefix->family);
@@ -1826,9 +1827,6 @@ route_map_get_index(struct route_map *map, const struct prefix *prefix,
else
table = map->ipv6_prefix_table;
- if (!table)
- return NULL;
-
do {
candidate_rmap_list =
route_map_get_index_list(&rn, prefix, table);
@@ -1914,19 +1912,10 @@ static void route_map_pfx_table_add_default(afi_t afi,
p.family = afi2family(afi);
p.prefixlen = 0;
- if (p.family == AF_INET) {
- table = index->map->ipv4_prefix_table;
- if (!table)
- index->map->ipv4_prefix_table = route_table_init();
-
+ if (p.family == AF_INET)
table = index->map->ipv4_prefix_table;
- } else {
- table = index->map->ipv6_prefix_table;
- if (!table)
- index->map->ipv6_prefix_table = route_table_init();
-
+ else
table = index->map->ipv6_prefix_table;
- }
/* Add default route to table */
rn = route_node_get(table, &p);
@@ -2317,8 +2306,6 @@ static void route_map_pfx_tbl_update(route_map_event_t event,
struct route_map_index *index, afi_t afi,
const char *plist_name)
{
- struct route_map *rmap = NULL;
-
if (!index)
return;
@@ -2332,19 +2319,6 @@ static void route_map_pfx_tbl_update(route_map_event_t event,
route_map_pfx_table_del_default(AFI_IP, index);
route_map_pfx_table_del_default(AFI_IP6, index);
- if ((index->map->head == NULL) && (index->map->tail == NULL)) {
- rmap = index->map;
-
- if (rmap->ipv4_prefix_table) {
- route_table_finish(rmap->ipv4_prefix_table);
- rmap->ipv4_prefix_table = NULL;
- }
-
- if (rmap->ipv6_prefix_table) {
- route_table_finish(rmap->ipv6_prefix_table);
- rmap->ipv6_prefix_table = NULL;
- }
- }
return;
}
@@ -2569,12 +2543,14 @@ route_map_result_t route_map_apply_ext(struct route_map *map,
*/
if (prefix->family == AF_EVPN) {
if (evpn_prefix2prefix(prefix, &conv) != 0) {
- if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))
+ if (unlikely(CHECK_FLAG(rmap_debug,
+ DEBUG_ROUTEMAP_DETAIL)))
zlog_debug(
"Unable to convert EVPN prefix %pFX into IPv4/IPv6 prefix. Falling back to non-optimized route-map lookup",
prefix);
} else {
- if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))
+ if (unlikely(CHECK_FLAG(rmap_debug,
+ DEBUG_ROUTEMAP_DETAIL)))
zlog_debug(
"Converted EVPN prefix %pFX into %pFX for optimized route-map lookup",
prefix, &conv);
@@ -2586,13 +2562,13 @@ route_map_result_t route_map_apply_ext(struct route_map *map,
index = route_map_get_index(map, prefix, match_object, &match_ret);
if (index) {
index->applied++;
- if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))
+ if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)))
zlog_debug(
"Best match route-map: %s, sequence: %d for pfx: %pFX, result: %s",
map->name, index->pref, prefix,
route_map_cmd_result_str(match_ret));
} else {
- if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))
+ if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)))
zlog_debug(
"No best match sequence for pfx: %pFX in route-map: %s, result: %s",
prefix, map->name,
@@ -2615,7 +2591,7 @@ route_map_result_t route_map_apply_ext(struct route_map *map,
/* Apply this index. */
match_ret = route_map_apply_match(&index->match_list,
prefix, match_object);
- if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)) {
+ if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))) {
zlog_debug(
"Route-map: %s, sequence: %d, prefix: %pFX, result: %s",
map->name, index->pref, prefix,
@@ -2728,7 +2704,7 @@ route_map_result_t route_map_apply_ext(struct route_map *map,
}
route_map_apply_end:
- if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))
+ if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)))
zlog_debug("Route-map: %s, prefix: %pFX, result: %s",
(map ? map->name : "null"), prefix,
route_map_result_str(ret));
@@ -2783,7 +2759,7 @@ static void route_map_clear_reference(struct hash_bucket *bucket, void *arg)
tmp_dep_data.rname = arg;
dep_data = hash_release(dep->dep_rmap_hash, &tmp_dep_data);
if (dep_data) {
- if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))
+ if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)))
zlog_debug("Clearing reference for %s to %s count: %d",
dep->dep_name, tmp_dep_data.rname,
dep_data->refcnt);
@@ -2803,7 +2779,7 @@ static void route_map_clear_all_references(char *rmap_name)
{
int i;
- if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))
+ if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)))
zlog_debug("Clearing references for %s", rmap_name);
for (i = 1; i < ROUTE_MAP_DEP_MAX; i++) {
@@ -2879,7 +2855,7 @@ static int route_map_dep_update(struct hash *dephash, const char *dep_name,
case RMAP_EVENT_LLIST_ADDED:
case RMAP_EVENT_CALL_ADDED:
case RMAP_EVENT_FILTER_ADDED:
- if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))
+ if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)))
zlog_debug("Adding dependency for filter %s in route-map %s",
dep_name, rmap_name);
dep = (struct route_map_dep *)hash_get(
@@ -2908,7 +2884,7 @@ static int route_map_dep_update(struct hash *dephash, const char *dep_name,
case RMAP_EVENT_LLIST_DELETED:
case RMAP_EVENT_CALL_DELETED:
case RMAP_EVENT_FILTER_DELETED:
- if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))
+ if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)))
zlog_debug("Deleting dependency for filter %s in route-map %s",
dep_name, rmap_name);
dep = (struct route_map_dep *)hash_get(dephash, dname, NULL);
@@ -3034,7 +3010,7 @@ static void route_map_process_dependency(struct hash_bucket *bucket, void *data)
dep_data = bucket->data;
rmap_name = dep_data->rname;
- if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))
+ if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)))
zlog_debug("Notifying %s of dependency", rmap_name);
if (route_map_master.event_hook)
(*route_map_master.event_hook)(rmap_name);
@@ -3082,7 +3058,7 @@ void route_map_notify_dependencies(const char *affected_name,
if (!dep->this_hash)
dep->this_hash = upd8_hash;
- if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))
+ if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)))
zlog_debug("Filter %s updated", dep->dep_name);
hash_iterate(dep->dep_rmap_hash, route_map_process_dependency,
(void *)event);
diff --git a/lib/subdir.am b/lib/subdir.am
index 0f5bbef0b2..83eecbee57 100644
--- a/lib/subdir.am
+++ b/lib/subdir.am
@@ -47,6 +47,7 @@ lib_libfrr_la_SOURCES = \
lib/if_rmap.c \
lib/imsg-buffer.c \
lib/imsg.c \
+ lib/iso.c \
lib/jhash.c \
lib/json.c \
lib/keychain.c \
@@ -224,6 +225,7 @@ pkginclude_HEADERS += \
lib/if_rmap.h \
lib/imsg.h \
lib/ipaddr.h \
+ lib/iso.h \
lib/jhash.h \
lib/json.h \
lib/keychain.h \
diff --git a/lib/vty.c b/lib/vty.c
index d0a6677788..974f5380d3 100644
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -2400,7 +2400,7 @@ static void vty_timeout(struct event *thread)
}
/* Read up configuration file from file_name. */
-static void vty_read_file(struct nb_config *config, FILE *confp)
+void vty_read_file(struct nb_config *config, FILE *confp)
{
int ret;
struct vty *vty;
diff --git a/lib/vty.h b/lib/vty.h
index 66d3355329..5114238f6a 100644
--- a/lib/vty.h
+++ b/lib/vty.h
@@ -369,6 +369,7 @@ extern void vty_pass_fd(struct vty *vty, int fd);
extern bool vty_read_config(struct nb_config *config, const char *config_file,
char *config_default_dir);
+extern void vty_read_file(struct nb_config *config, FILE *confp);
extern void vty_time_print(struct vty *, int);
extern void vty_serv_sock(const char *, unsigned short, const char *);
extern void vty_close(struct vty *);
diff --git a/lib/zclient.c b/lib/zclient.c
index 95093a56f5..d42cb20191 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -4294,6 +4294,8 @@ int32_t zapi_capabilities_decode(struct stream *s, struct zapi_cap *api)
memset(api, 0, sizeof(*api));
+ api->safi = SAFI_UNICAST;
+
STREAM_GETL(s, api->cap);
switch (api->cap) {
case ZEBRA_CLIENT_GR_CAPABILITIES:
diff --git a/mgmtd/mgmt.h b/mgmtd/mgmt.h
index 4d186c176b..9579b02230 100644
--- a/mgmtd/mgmt.h
+++ b/mgmtd/mgmt.h
@@ -62,6 +62,8 @@ struct mgmt_master {
};
extern struct mgmt_master *mm;
+extern char const *const mgmt_daemons[];
+extern uint mgmt_daemons_count;
/* Inline functions */
static inline unsigned long timeval_elapsed(struct timeval a, struct timeval b)
diff --git a/mgmtd/mgmt_ds.c b/mgmtd/mgmt_ds.c
index 1724afb182..10b3cecb92 100644
--- a/mgmtd/mgmt_ds.c
+++ b/mgmtd/mgmt_ds.c
@@ -87,7 +87,6 @@ static int mgmt_ds_replace_dst_with_src_ds(struct mgmt_ds_ctx *src,
struct mgmt_ds_ctx *dst)
{
struct lyd_node *dst_dnode, *src_dnode;
- struct ly_out *out;
if (!src || !dst)
return -1;
@@ -117,13 +116,6 @@ static int mgmt_ds_replace_dst_with_src_ds(struct mgmt_ds_ctx *src,
nb_config_diff_del_changes(&src->root.cfg_root->cfg_chgs);
}
- if (dst->ds_id == MGMTD_DS_RUNNING) {
- if (ly_out_new_filepath(MGMTD_STARTUP_DS_FILE_PATH, &out)
- == LY_SUCCESS)
- mgmt_ds_dump_in_memory(dst, "", LYD_JSON, out);
- ly_out_free(out, NULL, 0);
- }
-
/* TODO: Update the versions if nb_config present */
return 0;
@@ -134,7 +126,6 @@ static int mgmt_ds_merge_src_with_dst_ds(struct mgmt_ds_ctx *src,
{
int ret;
struct lyd_node **dst_dnode, *src_dnode;
- struct ly_out *out;
if (!src || !dst)
return -1;
@@ -159,13 +150,6 @@ static int mgmt_ds_merge_src_with_dst_ds(struct mgmt_ds_ctx *src,
nb_config_diff_del_changes(&src->root.cfg_root->cfg_chgs);
}
- if (dst->ds_id == MGMTD_DS_RUNNING) {
- if (ly_out_new_filepath(MGMTD_STARTUP_DS_FILE_PATH, &out)
- == LY_SUCCESS)
- mgmt_ds_dump_in_memory(dst, "", LYD_JSON, out);
- ly_out_free(out, NULL, 0);
- }
-
return 0;
}
@@ -200,8 +184,6 @@ void mgmt_ds_reset_candidate(void)
int mgmt_ds_init(struct mgmt_master *mm)
{
- struct lyd_node *root;
-
if (mgmt_ds_mm || mm->running_ds || mm->candidate_ds || mm->oper_ds)
assert(!"MGMTD: Call ds_init only once!");
@@ -209,12 +191,6 @@ int mgmt_ds_init(struct mgmt_master *mm)
if (!running_config)
assert(!"MGMTD: Call ds_init after frr_init only!");
- if (mgmt_ds_load_cfg_from_file(MGMTD_STARTUP_DS_FILE_PATH, &root)
- == 0) {
- nb_config_free(running_config);
- running_config = nb_config_new(root);
- }
-
running.root.cfg_root = running_config;
running.config_ds = true;
running.ds_id = MGMTD_DS_RUNNING;
diff --git a/mgmtd/mgmt_ds.h b/mgmtd/mgmt_ds.h
index 89a2ea9425..8d01f3d5b1 100644
--- a/mgmtd/mgmt_ds.h
+++ b/mgmtd/mgmt_ds.h
@@ -24,8 +24,6 @@
#define MGMTD_DS_NAME_CANDIDATE "candidate"
#define MGMTD_DS_NAME_OPERATIONAL "operational"
-#define MGMTD_STARTUP_DS_FILE_PATH DAEMON_DB_DIR "/frr_startup.json"
-
#define FOREACH_MGMTD_DS_ID(id) \
for ((id) = MGMTD_DS_NONE; (id) < MGMTD_DS_MAX_ID; (id)++)
diff --git a/mgmtd/mgmt_main.c b/mgmtd/mgmt_main.c
index 7d176059f5..08c999260d 100644
--- a/mgmtd/mgmt_main.c
+++ b/mgmtd/mgmt_main.c
@@ -17,6 +17,13 @@
#include "routing_nb.h"
+char const *const mgmt_daemons[] = {
+#ifdef HAVE_STATICD
+ "staticd",
+#endif
+};
+uint mgmt_daemons_count = array_size(mgmt_daemons);
+
/* mgmt options, we use GNU getopt library. */
static const struct option longopts[] = {
{"skip_runas", no_argument, NULL, 'S'},
diff --git a/mgmtd/mgmt_vty.c b/mgmtd/mgmt_vty.c
index 79fa54a791..cb09544fdc 100644
--- a/mgmtd/mgmt_vty.c
+++ b/mgmtd/mgmt_vty.c
@@ -10,6 +10,8 @@
#include "command.h"
#include "json.h"
+#include "northbound_cli.h"
+
#include "mgmtd/mgmt.h"
#include "mgmtd/mgmt_be_server.h"
#include "mgmtd/mgmt_be_adapter.h"
@@ -386,12 +388,14 @@ static struct cmd_node debug_node = {
.config_write = config_write_mgmt_debug,
};
-static int config_write_mgmt_debug(struct vty *vty)
+static int config_write_mgmt_debug_helper(struct vty *vty, bool config)
{
int n = mgmt_debug_be + mgmt_debug_fe + mgmt_debug_ds + mgmt_debug_txn;
if (!n)
return 0;
- if (n == 4) {
+
+ if (config && mgmt_debug_be && mgmt_debug_fe && mgmt_debug_ds &&
+ mgmt_debug_txn) {
vty_out(vty, "debug mgmt all\n");
return 0;
}
@@ -411,12 +415,26 @@ static int config_write_mgmt_debug(struct vty *vty)
return 0;
}
-DEFPY(debug_mgmt,
- debug_mgmt_cmd,
+static int config_write_mgmt_debug(struct vty *vty)
+{
+ return config_write_mgmt_debug_helper(vty, true);
+}
+
+DEFUN_NOSH(show_debugging_mgmt, show_debugging_mgmt_cmd,
+ "show debugging [mgmt]", SHOW_STR DEBUG_STR "MGMT Information\n")
+{
+ vty_out(vty, "MGMT debugging status:\n");
+
+ config_write_mgmt_debug_helper(vty, false);
+
+ cmd_show_lib_debugs(vty);
+
+ return CMD_SUCCESS;
+}
+
+DEFPY(debug_mgmt, debug_mgmt_cmd,
"[no$no] debug mgmt <all$all|{backend$be|datastore$ds|frontend$fe|transaction$txn}>",
- NO_STR
- DEBUG_STR
- MGMTD_STR
+ NO_STR DEBUG_STR MGMTD_STR
"All debug\n"
"Back-end debug\n"
"Datastore debug\n"
@@ -439,6 +457,33 @@ DEFPY(debug_mgmt,
return CMD_SUCCESS;
}
+/*
+ * Analog of `frr_config_read_in()`, instead of our config file though we loop
+ * over all daemons that have transitioned to mgmtd, loading their configs
+ */
+static int mgmt_config_pre_hook(struct event_loop *loop)
+{
+ FILE *confp;
+ char *p;
+
+ for (uint i = 0; i < mgmt_daemons_count; i++) {
+ p = asprintfrr(MTYPE_TMP, "%s/%s.conf", frr_sysconfdir,
+ mgmt_daemons[i]);
+ confp = fopen(p, "r");
+ if (confp == NULL) {
+ if (errno != ENOENT)
+ zlog_err("%s: couldn't read config file %s: %s",
+ __func__, p, safe_strerror(errno));
+ } else {
+ zlog_info("mgmtd: reading daemon config from %s", p);
+ vty_read_file(vty_shared_candidate_config, confp);
+ fclose(confp);
+ }
+ XFREE(MTYPE_TMP, p);
+ }
+ return 0;
+}
+
void mgmt_vty_init(void)
{
/*
@@ -452,6 +497,8 @@ void mgmt_vty_init(void)
static_vty_init();
#endif
+ hook_register(frr_config_pre, mgmt_config_pre_hook);
+
install_node(&debug_node);
install_element(VIEW_NODE, &show_mgmt_be_adapter_cmd);
@@ -479,6 +526,8 @@ void mgmt_vty_init(void)
install_element(ENABLE_NODE, &mgmt_performance_measurement_cmd);
install_element(ENABLE_NODE, &mgmt_reset_performance_stats_cmd);
+ install_element(ENABLE_NODE, &show_debugging_mgmt_cmd);
+
/*
* TODO: Register and handlers for auto-completion here.
*/
diff --git a/mgmtd/mgmt_vty.c.safe b/mgmtd/mgmt_vty.c.safe
deleted file mode 100644
index c43485c92b..0000000000
--- a/mgmtd/mgmt_vty.c.safe
+++ /dev/null
@@ -1,506 +0,0 @@
-/*
- * MGMTD VTY Interface
- * Copyright (C) 2021 Vmware, Inc.
- * Pushpasis Sarkar <spushpasis@vmware.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <zebra.h>
-
-#include "command.h"
-#include "json.h"
-#include "mgmtd/mgmt.h"
-#include "mgmtd/mgmt_be_server.h"
-#include "mgmtd/mgmt_be_adapter.h"
-#include "mgmtd/mgmt_fe_server.h"
-#include "mgmtd/mgmt_fe_adapter.h"
-#include "mgmtd/mgmt_ds.h"
-#include "mgmtd/mgmt_history.h"
-
-#include "mgmtd/mgmt_vty_clippy.c"
-
-DEFPY(show_mgmt_be_adapter,
- show_mgmt_be_adapter_cmd,
- "show mgmt backend-adapter all",
- SHOW_STR
- MGMTD_STR
- MGMTD_BE_ADAPTER_STR
- "Display all Backend Adapters\n")
-{
- mgmt_be_adapter_status_write(vty);
-
- return CMD_SUCCESS;
-}
-
-DEFPY(show_mgmt_be_xpath_reg,
- show_mgmt_be_xpath_reg_cmd,
- "show mgmt backend-yang-xpath-registry",
- SHOW_STR
- MGMTD_STR
- "Backend Adapter YANG Xpath Registry\n")
-{
- mgmt_be_xpath_register_write(vty);
-
- return CMD_SUCCESS;
-}
-
-DEFPY(show_mgmt_fe_adapter,
- show_mgmt_fe_adapter_cmd,
- "show mgmt frontend-adapter all",
- SHOW_STR MGMTD_STR MGMTD_FE_ADAPTER_STR "Display all Frontend Adapters\n")
-{
- mgmt_fe_adapter_status_write(vty, false);
-
- return CMD_SUCCESS;
-}
-
-DEFPY(show_mgmt_fe_adapter_detail, show_mgmt_fe_adapter_detail_cmd,
- "show mgmt frontend-adapter all detail",
- SHOW_STR MGMTD_STR MGMTD_FE_ADAPTER_STR
- "Display all Frontend Adapters\n"
- "Details of commit stats\n")
-{
- mgmt_fe_adapter_status_write(vty, true);
-
- return CMD_SUCCESS;
-}
-
-DEFPY_HIDDEN(mgmt_performance_measurement,
- mgmt_performance_measurement_cmd,
- "[no] mgmt performance-measurement",
- NO_STR
- MGMTD_STR
- "Enable performance measurement\n")
-{
- if (no)
- mgmt_fe_adapter_perf_measurement(vty, false);
- else
- mgmt_fe_adapter_perf_measurement(vty, true);
-
- return CMD_SUCCESS;
-}
-
-DEFPY(mgmt_reset_performance_stats,
- mgmt_reset_performance_stats_cmd,
- "mgmt reset-statistics",
- MGMTD_STR
- "Reset the Performance measurement statistics\n")
-{
- mgmt_fe_adapter_reset_perf_stats(vty);
-
- return CMD_SUCCESS;
-}
-
-DEFPY(show_mgmt_txn,
- show_mgmt_txn_cmd,
- "show mgmt transaction all",
- SHOW_STR
- MGMTD_STR
- MGMTD_TXN_STR
- "Display all Transactions\n")
-{
- mgmt_txn_status_write(vty);
-
- return CMD_SUCCESS;
-}
-
-DEFPY(show_mgmt_ds,
- show_mgmt_ds_cmd,
- "show mgmt datastore [all|candidate|operational|running]$dsname",
- SHOW_STR
- MGMTD_STR
- MGMTD_DS_STR
- "All datastores (default)\n"
- "Candidate datastore\n"
- "Operational datastore\n"
- "Running datastore\n")
-{
- struct mgmt_ds_ctx *ds_ctx;
-
- if (!dsname || dsname[0] == 'a') {
- mgmt_ds_status_write(vty);
- return CMD_SUCCESS;
- }
- ds_ctx = mgmt_ds_get_ctx_by_id(mm, mgmt_ds_name2id(dsname));
- if (!ds_ctx) {
- vty_out(vty, "ERROR: Could not access %s datastore!\n", dsname);
- return CMD_ERR_NO_MATCH;
- }
- mgmt_ds_status_write_one(vty, ds_ctx);
-
- return CMD_SUCCESS;
-}
-
-DEFPY(mgmt_commit,
- mgmt_commit_cmd,
- "mgmt commit <check|apply|abort>$type",
- MGMTD_STR
- "Commit action\n"
- "Validate the set of config commands\n"
- "Validate and apply the set of config commands\n"
- "Abort and drop the set of config commands recently added\n")
-{
- bool validate_only = type[0] == 'c';
- bool abort = type[1] == 'b';
-
- if (vty_mgmt_send_commit_config(vty, validate_only, abort) != 0)
- return CMD_WARNING_CONFIG_FAILED;
- return CMD_SUCCESS;
-}
-
-DEFPY(mgmt_set_config_data, mgmt_set_config_data_cmd,
- "mgmt set-config WORD$path VALUE",
- MGMTD_STR
- "Set configuration data\n"
- "XPath expression specifying the YANG data path\n"
- "Value of the data to set\n")
-{
- strlcpy(vty->cfg_changes[0].xpath, path,
- sizeof(vty->cfg_changes[0].xpath));
- vty->cfg_changes[0].value = value;
- vty->cfg_changes[0].operation = NB_OP_CREATE;
- vty->num_cfg_changes = 1;
-
- vty->no_implicit_commit = true;
- vty_mgmt_send_config_data(vty);
- vty->no_implicit_commit = false;
- return CMD_SUCCESS;
-}
-
-DEFPY(mgmt_delete_config_data, mgmt_delete_config_data_cmd,
- "mgmt delete-config WORD$path",
- MGMTD_STR
- "Delete configuration data\n"
- "XPath expression specifying the YANG data path\n")
-{
-
- strlcpy(vty->cfg_changes[0].xpath, path,
- sizeof(vty->cfg_changes[0].xpath));
- vty->cfg_changes[0].value = NULL;
- vty->cfg_changes[0].operation = NB_OP_DESTROY;
- vty->num_cfg_changes = 1;
-
- vty->no_implicit_commit = true;
- vty_mgmt_send_config_data(vty);
- vty->no_implicit_commit = false;
- return CMD_SUCCESS;
-}
-
-DEFPY(show_mgmt_get_config, show_mgmt_get_config_cmd,
- "show mgmt get-config [candidate|operational|running]$dsname WORD$path",
- SHOW_STR MGMTD_STR
- "Get configuration data from a specific configuration datastore\n"
- "Candidate datastore (default)\n"
- "Operational datastore\n"
- "Running datastore\n"
- "XPath expression specifying the YANG data path\n")
-{
- const char *xpath_list[VTY_MAXCFGCHANGES] = {0};
- Mgmtd__DatastoreId datastore = MGMTD_DS_CANDIDATE;
-
- if (dsname)
- datastore = mgmt_ds_name2id(dsname);
-
- xpath_list[0] = path;
- vty_mgmt_send_get_config(vty, datastore, xpath_list, 1);
- return CMD_SUCCESS;
-}
-
-DEFPY(show_mgmt_get_data, show_mgmt_get_data_cmd,
- "show mgmt get-data [candidate|operational|running]$dsname WORD$path",
- SHOW_STR MGMTD_STR
- "Get data from a specific datastore\n"
- "Candidate datastore\n"
- "Operational datastore (default)\n"
- "Running datastore\n"
- "XPath expression specifying the YANG data path\n")
-{
- const char *xpath_list[VTY_MAXCFGCHANGES] = {0};
- Mgmtd__DatastoreId datastore = MGMTD_DS_OPERATIONAL;
-
- if (dsname)
- datastore = mgmt_ds_name2id(dsname);
-
- xpath_list[0] = path;
- vty_mgmt_send_get_data(vty, datastore, xpath_list, 1);
- return CMD_SUCCESS;
-}
-
-DEFPY(show_mgmt_dump_data,
- show_mgmt_dump_data_cmd,
- "show mgmt datastore-contents [candidate|operational|running]$dsname [xpath WORD$path] [file WORD$filepath] <json|xml>$fmt",
- SHOW_STR
- MGMTD_STR
- "Get Datastore contents from a specific datastore\n"
- "Candidate datastore (default)\n"
- "Operational datastore\n"
- "Running datastore\n"
- "XPath expression specifying the YANG data path\n"
- "XPath string\n"
- "Dump the contents to a file\n"
- "Full path of the file\n"
- "json output\n"
- "xml output\n")
-{
- struct mgmt_ds_ctx *ds_ctx;
- Mgmtd__DatastoreId datastore = MGMTD_DS_CANDIDATE;
- LYD_FORMAT format = fmt[0] == 'j' ? LYD_JSON : LYD_XML;
- FILE *f = NULL;
-
- if (datastore)
- datastore = mgmt_ds_name2id(dsname);
-
- ds_ctx = mgmt_ds_get_ctx_by_id(mm, datastore);
- if (!ds_ctx) {
- vty_out(vty, "ERROR: Could not access datastore!\n");
- return CMD_ERR_NO_MATCH;
- }
-
- if (filepath) {
- f = fopen(filepath, "w");
- if (!f) {
- vty_out(vty,
- "Could not open file pointed by filepath %s\n",
- filepath);
- return CMD_SUCCESS;
- }
- }
-
- mgmt_ds_dump_tree(vty, ds_ctx, path, f, format);
-
- if (f)
- fclose(f);
- return CMD_SUCCESS;
-}
-
-DEFPY(show_mgmt_map_xpath,
- show_mgmt_map_xpath_cmd,
- "show mgmt yang-xpath-subscription WORD$path",
- SHOW_STR
- MGMTD_STR
- "Get YANG Backend Subscription\n"
- "XPath expression specifying the YANG data path\n")
-{
- mgmt_be_xpath_subscr_info_write(vty, path);
- return CMD_SUCCESS;
-}
-
-DEFPY(mgmt_load_config,
- mgmt_load_config_cmd,
- "mgmt load-config WORD$filepath <merge|replace>$type",
- MGMTD_STR
- "Load configuration onto Candidate Datastore\n"
- "Full path of the file\n"
- "Merge configuration with contents of Candidate Datastore\n"
- "Replace the existing contents of Candidate datastore\n")
-{
- bool merge = type[0] == 'm' ? true : false;
- struct mgmt_ds_ctx *ds_ctx;
- int ret;
-
- if (access(filepath, F_OK) == -1) {
- vty_out(vty, "ERROR: File %s : %s\n", filepath,
- strerror(errno));
- return CMD_ERR_NO_FILE;
- }
-
- ds_ctx = mgmt_ds_get_ctx_by_id(mm, MGMTD_DS_CANDIDATE);
- if (!ds_ctx) {
- vty_out(vty, "ERROR: Could not access Candidate datastore!\n");
- return CMD_ERR_NO_MATCH;
- }
-
- ret = mgmt_ds_load_config_from_file(ds_ctx, filepath, merge);
- if (ret != 0)
- vty_out(vty, "Error with parsing the file with error code %d\n",
- ret);
- return CMD_SUCCESS;
-}
-
-DEFPY(mgmt_save_config,
- mgmt_save_config_cmd,
- "mgmt save-config <candidate|running>$dsname WORD$filepath",
- MGMTD_STR
- "Save configuration from datastore\n"
- "Candidate datastore\n"
- "Running datastore\n"
- "Full path of the file\n")
-{
- Mgmtd__DatastoreId datastore = mgmt_ds_name2id(dsname);
- struct mgmt_ds_ctx *ds_ctx;
- FILE *f;
-
- ds_ctx = mgmt_ds_get_ctx_by_id(mm, datastore);
- if (!ds_ctx) {
- vty_out(vty, "ERROR: Could not access the '%s' datastore!\n",
- dsname);
- return CMD_ERR_NO_MATCH;
- }
-
- if (!filepath) {
- vty_out(vty, "ERROR: No file path mentioned!\n");
- return CMD_ERR_NO_MATCH;
- }
-
- f = fopen(filepath, "w");
- if (!f) {
- vty_out(vty, "Could not open file pointed by filepath %s\n",
- filepath);
- return CMD_SUCCESS;
- }
-
- mgmt_ds_dump_tree(vty, ds_ctx, "/", f, LYD_JSON);
-
- fclose(f);
-
- return CMD_SUCCESS;
-}
-
-DEFPY(show_mgmt_cmt_hist,
- show_mgmt_cmt_hist_cmd,
- "show mgmt commit-history",
- SHOW_STR
- MGMTD_STR
- "Show commit history\n")
-{
- show_mgmt_cmt_history(vty);
- return CMD_SUCCESS;
-}
-
-DEFPY(mgmt_rollback,
- mgmt_rollback_cmd,
- "mgmt rollback <commit-id WORD$commit | last [(1-10)]$last>",
- MGMTD_STR
- "Rollback commits\n"
- "Rollback to commit ID\n"
- "Commit-ID\n"
- "Rollbak n commits\n"
- "Number of commits\n")
-{
- if (commit)
- mgmt_history_rollback_by_id(vty, commit);
- else
- mgmt_history_rollback_n(vty, last);
-
- return CMD_SUCCESS;
-}
-
-static int config_write_mgmt_debug(struct vty *vty);
-static struct cmd_node debug_node = {
- .name = "debug",
- .node = DEBUG_NODE,
- .prompt = "",
- .config_write = config_write_mgmt_debug,
-};
-
-static int config_write_mgmt_debug(struct vty *vty)
-{
- int n = mgmt_debug_be + mgmt_debug_fe + mgmt_debug_ds + mgmt_debug_txn;
- if (!n)
- return 0;
- if (n == 4) {
- vty_out(vty, "debug mgmt all\n");
- return 0;
- }
-
- vty_out(vty, "debug mgmt");
- if (mgmt_debug_be)
- vty_out(vty, " backend");
- if (mgmt_debug_ds)
- vty_out(vty, " datastore");
- if (mgmt_debug_fe)
- vty_out(vty, " frontend");
- if (mgmt_debug_txn)
- vty_out(vty, " transaction");
-
- vty_out(vty, "\n");
-
- return 0;
-}
-
-DEFPY(debug_mgmt,
- debug_mgmt_cmd,
- "[no$no] debug mgmt <all$all|{backend$be|datastore$ds|frontend$fe|transaction$txn}>",
- NO_STR
- DEBUG_STR
- MGMTD_STR
- "All debug\n"
- "Back-end debug\n"
- "Datastore debug\n"
- "Front-end debug\n"
- "Transaction debug\n")
-{
- bool set = !no;
- if (all)
- be = fe = ds = txn = set ? all : NULL;
-
- if (be)
- mgmt_debug_be = set;
- if (ds)
- mgmt_debug_ds = set;
- if (fe)
- mgmt_debug_fe = set;
- if (txn)
- mgmt_debug_txn = set;
-
- return CMD_SUCCESS;
-}
-
-void mgmt_vty_init(void)
-{
- /*
- * Initialize command handling from VTYSH connection.
- * Call command initialization routines defined by
- * backend components that are moved to new MGMTD infra
- * here one by one.
- */
-#if HAVE_STATICD
- extern void static_vty_init(void);
- static_vty_init();
-#endif
-
- install_node(&debug_node);
-
- install_element(VIEW_NODE, &show_mgmt_be_adapter_cmd);
- install_element(VIEW_NODE, &show_mgmt_be_xpath_reg_cmd);
- install_element(VIEW_NODE, &show_mgmt_fe_adapter_cmd);
- install_element(VIEW_NODE, &show_mgmt_fe_adapter_detail_cmd);
- install_element(VIEW_NODE, &show_mgmt_txn_cmd);
- install_element(VIEW_NODE, &show_mgmt_ds_cmd);
- install_element(VIEW_NODE, &show_mgmt_get_config_cmd);
- install_element(VIEW_NODE, &show_mgmt_get_data_cmd);
- install_element(VIEW_NODE, &show_mgmt_dump_data_cmd);
- install_element(VIEW_NODE, &show_mgmt_map_xpath_cmd);
- install_element(VIEW_NODE, &show_mgmt_cmt_hist_cmd);
-
- install_element(CONFIG_NODE, &mgmt_commit_cmd);
- install_element(CONFIG_NODE, &mgmt_set_config_data_cmd);
- install_element(CONFIG_NODE, &mgmt_delete_config_data_cmd);
- install_element(CONFIG_NODE, &mgmt_load_config_cmd);
- install_element(CONFIG_NODE, &mgmt_save_config_cmd);
- install_element(CONFIG_NODE, &mgmt_rollback_cmd);
-
- install_element(VIEW_NODE, &debug_mgmt_cmd);
- install_element(CONFIG_NODE, &debug_mgmt_cmd);
-
- /* Enable view */
- install_element(ENABLE_NODE, &mgmt_performance_measurement_cmd);
- install_element(ENABLE_NODE, &mgmt_reset_performance_stats_cmd);
-
- /*
- * TODO: Register and handlers for auto-completion here.
- */
-}
diff --git a/nhrpd/debug.h b/nhrpd/debug.h
index e9428fa90a..f2c7022ad4 100644
--- a/nhrpd/debug.h
+++ b/nhrpd/debug.h
@@ -1,13 +1,5 @@
#include "log.h"
-#if defined(__GNUC__) && (__GNUC__ >= 3)
-#define likely(_x) __builtin_expect(!!(_x), 1)
-#define unlikely(_x) __builtin_expect(!!(_x), 0)
-#else
-#define likely(_x) !!(_x)
-#define unlikely(_x) !!(_x)
-#endif
-
#define NHRP_DEBUG_COMMON (1 << 0)
#define NHRP_DEBUG_KERNEL (1 << 1)
#define NHRP_DEBUG_IF (1 << 2)
diff --git a/ospfd/ospf_abr.c b/ospfd/ospf_abr.c
index e14586c5ee..ded520889f 100644
--- a/ospfd/ospf_abr.c
+++ b/ospfd/ospf_abr.c
@@ -54,6 +54,7 @@ static void ospf_area_range_free(struct ospf_area_range *range)
}
static void ospf_area_range_add(struct ospf_area *area,
+ struct route_table *ranges,
struct ospf_area_range *range)
{
struct route_node *rn;
@@ -64,7 +65,7 @@ static void ospf_area_range_add(struct ospf_area *area,
p.prefix = range->addr;
apply_mask_ipv4(&p);
- rn = route_node_get(area->ranges, (struct prefix *)&p);
+ rn = route_node_get(ranges, (struct prefix *)&p);
if (rn->info)
route_unlock_node(rn);
else
@@ -75,10 +76,12 @@ static void ospf_area_range_delete(struct ospf_area *area,
struct route_node *rn)
{
struct ospf_area_range *range = rn->info;
+ bool nssa = CHECK_FLAG(range->flags, OSPF_AREA_RANGE_NSSA);
- if (range->specifics != 0)
+ if (ospf_area_range_active(range) &&
+ CHECK_FLAG(range->flags, OSPF_AREA_RANGE_ADVERTISE))
ospf_delete_discard_route(area->ospf, area->ospf->new_table,
- (struct prefix_ipv4 *)&rn->p);
+ (struct prefix_ipv4 *)&rn->p, nssa);
ospf_area_range_free(range);
rn->info = NULL;
@@ -87,11 +90,12 @@ static void ospf_area_range_delete(struct ospf_area *area,
}
struct ospf_area_range *ospf_area_range_lookup(struct ospf_area *area,
+ struct route_table *ranges,
struct prefix_ipv4 *p)
{
struct route_node *rn;
- rn = route_node_lookup(area->ranges, (struct prefix *)p);
+ rn = route_node_lookup(ranges, (struct prefix *)p);
if (rn) {
route_unlock_node(rn);
return rn->info;
@@ -133,11 +137,12 @@ struct ospf_area_range *ospf_area_range_lookup_next(struct ospf_area *area,
}
static struct ospf_area_range *ospf_area_range_match(struct ospf_area *area,
+ struct route_table *ranges,
struct prefix_ipv4 *p)
{
struct route_node *node;
- node = route_node_match(area->ranges, (struct prefix *)p);
+ node = route_node_match(ranges, (struct prefix *)p);
if (node) {
route_unlock_node(node);
return node->info;
@@ -153,7 +158,7 @@ struct ospf_area_range *ospf_area_range_match_any(struct ospf *ospf,
struct listnode *node;
for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area))
- if ((range = ospf_area_range_match(area, p)))
+ if ((range = ospf_area_range_match(area, area->ranges, p)))
return range;
return NULL;
@@ -169,17 +174,13 @@ static int ospf_area_actively_attached(struct ospf_area *area)
return area->act_ints;
}
-int ospf_area_range_set(struct ospf *ospf, struct in_addr area_id,
- struct prefix_ipv4 *p, int advertise)
+int ospf_area_range_set(struct ospf *ospf, struct ospf_area *area,
+ struct route_table *ranges, struct prefix_ipv4 *p,
+ int advertise, bool nssa)
{
- struct ospf_area *area;
struct ospf_area_range *range;
- area = ospf_area_get(ospf, area_id);
- if (area == NULL)
- return 0;
-
- range = ospf_area_range_lookup(area, p);
+ range = ospf_area_range_lookup(area, ranges, p);
if (range != NULL) {
if (!CHECK_FLAG(advertise, OSPF_AREA_RANGE_ADVERTISE))
range->cost_config = OSPF_AREA_RANGE_COST_UNSPEC;
@@ -190,7 +191,7 @@ int ospf_area_range_set(struct ospf *ospf, struct in_addr area_id,
ospf_schedule_abr_task(ospf);
} else {
range = ospf_area_range_new(p);
- ospf_area_range_add(area, range);
+ ospf_area_range_add(area, ranges, range);
ospf_schedule_abr_task(ospf);
}
@@ -201,20 +202,19 @@ int ospf_area_range_set(struct ospf *ospf, struct in_addr area_id,
range->cost_config = OSPF_AREA_RANGE_COST_UNSPEC;
}
+ if (nssa)
+ SET_FLAG(range->flags, OSPF_AREA_RANGE_NSSA);
+
return 1;
}
-int ospf_area_range_cost_set(struct ospf *ospf, struct in_addr area_id,
- struct prefix_ipv4 *p, uint32_t cost)
+int ospf_area_range_cost_set(struct ospf *ospf, struct ospf_area *area,
+ struct route_table *ranges, struct prefix_ipv4 *p,
+ uint32_t cost)
{
- struct ospf_area *area;
struct ospf_area_range *range;
- area = ospf_area_get(ospf, area_id);
- if (area == NULL)
- return 0;
-
- range = ospf_area_range_lookup(area, p);
+ range = ospf_area_range_lookup(area, ranges, p);
if (range == NULL)
return 0;
@@ -227,17 +227,12 @@ int ospf_area_range_cost_set(struct ospf *ospf, struct in_addr area_id,
return 1;
}
-int ospf_area_range_unset(struct ospf *ospf, struct in_addr area_id,
- struct prefix_ipv4 *p)
+int ospf_area_range_unset(struct ospf *ospf, struct ospf_area *area,
+ struct route_table *ranges, struct prefix_ipv4 *p)
{
- struct ospf_area *area;
struct route_node *rn;
- area = ospf_area_lookup_by_area_id(ospf, area_id);
- if (area == NULL)
- return 0;
-
- rn = route_node_lookup(area->ranges, (struct prefix *)p);
+ rn = route_node_lookup(ranges, (struct prefix *)p);
if (rn == NULL)
return 0;
@@ -249,14 +244,12 @@ int ospf_area_range_unset(struct ospf *ospf, struct in_addr area_id,
return 1;
}
-int ospf_area_range_substitute_set(struct ospf *ospf, struct in_addr area_id,
+int ospf_area_range_substitute_set(struct ospf *ospf, struct ospf_area *area,
struct prefix_ipv4 *p, struct prefix_ipv4 *s)
{
- struct ospf_area *area;
struct ospf_area_range *range;
- area = ospf_area_get(ospf, area_id);
- range = ospf_area_range_lookup(area, p);
+ range = ospf_area_range_lookup(area, area->ranges, p);
if (range != NULL) {
if (!CHECK_FLAG(range->flags, OSPF_AREA_RANGE_ADVERTISE)
@@ -264,7 +257,7 @@ int ospf_area_range_substitute_set(struct ospf *ospf, struct in_addr area_id,
ospf_schedule_abr_task(ospf);
} else {
range = ospf_area_range_new(p);
- ospf_area_range_add(area, range);
+ ospf_area_range_add(area, area->ranges, range);
ospf_schedule_abr_task(ospf);
}
@@ -276,17 +269,12 @@ int ospf_area_range_substitute_set(struct ospf *ospf, struct in_addr area_id,
return 1;
}
-int ospf_area_range_substitute_unset(struct ospf *ospf, struct in_addr area_id,
+int ospf_area_range_substitute_unset(struct ospf *ospf, struct ospf_area *area,
struct prefix_ipv4 *p)
{
- struct ospf_area *area;
struct ospf_area_range *range;
- area = ospf_area_lookup_by_area_id(ospf, area_id);
- if (area == NULL)
- return 0;
-
- range = ospf_area_range_lookup(area, p);
+ range = ospf_area_range_lookup(area, area->ranges, p);
if (range == NULL)
return 0;
@@ -538,8 +526,7 @@ void ospf_check_abr_status(struct ospf *ospf)
}
static void ospf_abr_update_aggregate(struct ospf_area_range *range,
- struct ospf_route * or,
- struct ospf_area *area)
+ uint32_t cost, struct ospf_area *area)
{
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("%s: Start", __func__);
@@ -557,20 +544,18 @@ static void ospf_abr_update_aggregate(struct ospf_area_range *range,
range->cost = range->cost_config;
} else {
- if (range->specifics == 0) {
+ if (!ospf_area_range_active(range)) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("%s: use or->cost %d", __func__,
- or->cost);
+ zlog_debug("%s: use cost %d", __func__, cost);
- range->cost = or->cost; /* 1st time get 1st cost */
+ range->cost = cost; /* 1st time get 1st cost */
}
- if (or->cost > range->cost) {
+ if (cost > range->cost) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("%s: update to %d", __func__,
- or->cost);
+ zlog_debug("%s: update to %d", __func__, cost);
- range->cost = or->cost;
+ range->cost = cost;
}
}
@@ -605,6 +590,7 @@ static int ospf_abr_translate_nssa(struct ospf_area *area, struct ospf_lsa *lsa)
struct ospf_lsa *old = NULL, *new = NULL;
struct as_external_lsa *ext7;
struct prefix_ipv4 p;
+ struct ospf_area_range *range;
if (!CHECK_FLAG(lsa->data->options, OSPF_OPTION_NP)) {
if (IS_DEBUG_OSPF_NSSA)
@@ -646,6 +632,18 @@ static int ospf_abr_translate_nssa(struct ospf_area *area, struct ospf_lsa *lsa)
return 1;
}
+ range = ospf_area_range_match(area, area->nssa_ranges, &p);
+ if (range) {
+ if (IS_DEBUG_OSPF_NSSA)
+ zlog_debug("Suppressed by range %pI4/%u of area %pI4",
+ &range->addr, range->masklen,
+ &area->area_id);
+
+ ospf_abr_update_aggregate(range, GET_METRIC(ext7->e[0].metric),
+ area);
+ return 1;
+ }
+
if (old && CHECK_FLAG(old->flags, OSPF_LSA_APPROVED)) {
if (IS_DEBUG_OSPF_NSSA)
zlog_debug(
@@ -675,17 +673,27 @@ static int ospf_abr_translate_nssa(struct ospf_area *area, struct ospf_lsa *lsa)
}
}
- /* Area where Aggregate testing will be inserted, just like summary
- advertisements */
- /* ospf_abr_check_nssa_range (p_arg, lsa-> cost, lsa -> area); */
-
return 0;
}
-static void ospf_abr_translate_nssa_range(struct prefix_ipv4 *p, uint32_t cost)
+static void ospf_abr_translate_nssa_range(struct ospf *ospf,
+ struct prefix_ipv4 *p, uint32_t cost)
{
- /* The Type-7 is created from the aggregated prefix and forwarded
- for lsa installation and flooding... to be added... */
+ struct external_info ei = {};
+ struct ospf_lsa *lsa;
+
+ prefix_copy(&ei.p, p);
+ ei.type = ZEBRA_ROUTE_OSPF;
+ ei.route_map_set.metric = cost;
+ ei.route_map_set.metric_type = -1;
+
+ lsa = ospf_external_info_find_lsa(ospf, p);
+ if (lsa)
+ lsa = ospf_external_lsa_refresh(ospf, lsa, &ei,
+ LSA_REFRESH_FORCE, true);
+ else
+ lsa = ospf_external_lsa_originate(ospf, &ei);
+ SET_FLAG(lsa->flags, OSPF_LSA_LOCAL_XLT);
}
void ospf_abr_announce_network_to_area(struct prefix_ipv4 *p, uint32_t cost,
@@ -892,9 +900,11 @@ static void ospf_abr_announce_network(struct ospf *ospf, struct prefix_ipv4 *p,
zlog_debug(
"%s: this is intra-area route to %pFX",
__func__, p);
- if ((range = ospf_area_range_match(or_area, p))
- && !ospf_area_is_transit(area))
- ospf_abr_update_aggregate(range, or, area);
+ if ((range = ospf_area_range_match(
+ or_area, or_area->ranges, p)) &&
+ !ospf_area_is_transit(area))
+ ospf_abr_update_aggregate(range, or->cost,
+ area);
else
ospf_abr_announce_network_to_area(p, or->cost,
area);
@@ -1345,7 +1355,7 @@ static void ospf_abr_unapprove_summaries(struct ospf *ospf)
zlog_debug("%s: Stop", __func__);
}
-static void ospf_abr_prepare_aggregates(struct ospf *ospf)
+static void ospf_abr_prepare_aggregates(struct ospf *ospf, bool nssa)
{
struct listnode *node;
struct route_node *rn;
@@ -1356,7 +1366,14 @@ static void ospf_abr_prepare_aggregates(struct ospf *ospf)
zlog_debug("%s: Start", __func__);
for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) {
- for (rn = route_top(area->ranges); rn; rn = route_next(rn))
+ struct route_table *ranges;
+
+ if (nssa)
+ ranges = area->nssa_ranges;
+ else
+ ranges = area->ranges;
+
+ for (rn = route_top(ranges); rn; rn = route_next(rn))
if ((range = rn->info) != NULL) {
range->cost = 0;
range->specifics = 0;
@@ -1409,7 +1426,7 @@ static void ospf_abr_announce_aggregates(struct ospf *ospf)
p.prefixlen = range->subst_masklen;
}
- if (range->specifics) {
+ if (ospf_area_range_active(range)) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("%s: active range",
__func__);
@@ -1452,13 +1469,11 @@ static void ospf_abr_announce_aggregates(struct ospf *ospf)
zlog_debug("%s: Stop", __func__);
}
-static void
-ospf_abr_send_nssa_aggregates(struct ospf *ospf) /* temporarily turned off */
+static void ospf_abr_send_nssa_aggregates(struct ospf *ospf)
{
- struct listnode *node; /*, n; */
- struct ospf_area *area; /*, *ar; */
+ struct listnode *node;
+ struct ospf_area *area;
struct route_node *rn;
- struct ospf_area_range *range;
struct prefix_ipv4 p;
if (IS_DEBUG_OSPF_NSSA)
@@ -1472,20 +1487,13 @@ ospf_abr_send_nssa_aggregates(struct ospf *ospf) /* temporarily turned off */
zlog_debug("%s: looking at area %pI4", __func__,
&area->area_id);
- for (rn = route_top(area->ranges); rn; rn = route_next(rn)) {
- if (rn->info == NULL)
- continue;
+ for (rn = route_top(area->nssa_ranges); rn;
+ rn = route_next(rn)) {
+ struct ospf_area_range *range;
range = rn->info;
-
- if (!CHECK_FLAG(range->flags,
- OSPF_AREA_RANGE_ADVERTISE)) {
- if (IS_DEBUG_OSPF_NSSA)
- zlog_debug(
- "%s: discarding suppress-ranges",
- __func__);
+ if (!range)
continue;
- }
p.family = AF_INET;
p.prefix = range->addr;
@@ -1495,14 +1503,9 @@ ospf_abr_send_nssa_aggregates(struct ospf *ospf) /* temporarily turned off */
zlog_debug("%s: this is range: %pFX", __func__,
&p);
- if (CHECK_FLAG(range->flags,
- OSPF_AREA_RANGE_SUBSTITUTE)) {
- p.family = AF_INET;
- p.prefix = range->subst_addr;
- p.prefixlen = range->subst_masklen;
- }
-
- if (range->specifics) {
+ if (ospf_area_range_active(range)
+ && CHECK_FLAG(range->flags,
+ OSPF_AREA_RANGE_ADVERTISE)) {
if (IS_DEBUG_OSPF_NSSA)
zlog_debug("%s: active range",
__func__);
@@ -1512,7 +1515,8 @@ ospf_abr_send_nssa_aggregates(struct ospf *ospf) /* temporarily turned off */
* translate, Install (as Type-5), Approve, and
* Flood
*/
- ospf_abr_translate_nssa_range(&p, range->cost);
+ ospf_abr_translate_nssa_range(ospf, &p,
+ range->cost);
}
} /* all area ranges*/
} /* all areas */
@@ -1807,6 +1811,82 @@ static void ospf_abr_announce_non_dna_routers(struct event *thread)
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,
struct ospf_lsa *lsa)
{
@@ -1874,30 +1954,39 @@ static void ospf_abr_remove_unapproved_summaries(struct ospf *ospf)
zlog_debug("%s: Stop", __func__);
}
-static void ospf_abr_manage_discard_routes(struct ospf *ospf)
+static void ospf_abr_manage_discard_routes(struct ospf *ospf, bool nssa)
{
struct listnode *node, *nnode;
struct route_node *rn;
struct ospf_area *area;
- struct ospf_area_range *range;
- for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area))
- for (rn = route_top(area->ranges); rn; rn = route_next(rn))
- if ((range = rn->info) != NULL)
- if (CHECK_FLAG(range->flags,
- OSPF_AREA_RANGE_ADVERTISE)) {
- if (range->specifics)
- ospf_add_discard_route(
- ospf, ospf->new_table,
- area,
- (struct prefix_ipv4
- *)&rn->p);
- else
- ospf_delete_discard_route(
- ospf, ospf->new_table,
- (struct prefix_ipv4
- *)&rn->p);
- }
+ for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) {
+ struct route_table *ranges;
+
+ if (nssa)
+ ranges = area->nssa_ranges;
+ else
+ ranges = area->ranges;
+
+ for (rn = route_top(ranges); rn; rn = route_next(rn)) {
+ struct ospf_area_range *range;
+
+ range = rn->info;
+ if (!range)
+ continue;
+
+ if (ospf_area_range_active(range)
+ && CHECK_FLAG(range->flags,
+ OSPF_AREA_RANGE_ADVERTISE))
+ ospf_add_discard_route(
+ ospf, ospf->new_table, area,
+ (struct prefix_ipv4 *)&rn->p, nssa);
+ else
+ ospf_delete_discard_route(
+ ospf, ospf->new_table,
+ (struct prefix_ipv4 *)&rn->p, nssa);
+ }
+ }
}
/* This is the function taking care about ABR NSSA, i.e. NSSA
@@ -1925,7 +2014,7 @@ static void ospf_abr_manage_discard_routes(struct ospf *ospf)
For External Calculations, any NSSA areas use the Type-7 AREA-LSDB,
any ABR-non-NSSA areas use the Type-5 GLOBAL-LSDB. */
-static void ospf_abr_nssa_task(struct ospf *ospf) /* called only if any_nssa */
+void ospf_abr_nssa_task(struct ospf *ospf) /* called only if any_nssa */
{
if (ospf->gr_info.restart_in_progress)
return;
@@ -1952,7 +2041,7 @@ static void ospf_abr_nssa_task(struct ospf *ospf) /* called only if any_nssa */
/* RESET all Ranges in every Area, same as summaries */
if (IS_DEBUG_OSPF_NSSA)
zlog_debug("%s: NSSA initialize aggregates", __func__);
- ospf_abr_prepare_aggregates(ospf); /*TURNED OFF just for now */
+ ospf_abr_prepare_aggregates(ospf, true);
/* For all NSSAs, Type-7s, translate to 5's, INSTALL/FLOOD, or
* Aggregate as Type-7
@@ -1983,7 +2072,7 @@ static void ospf_abr_nssa_task(struct ospf *ospf) /* called only if any_nssa */
zlog_debug("%s: remove unapproved translates", __func__);
ospf_abr_remove_unapproved_translates(ospf);
- ospf_abr_manage_discard_routes(ospf); /* same as normal...discard */
+ ospf_abr_manage_discard_routes(ospf, true);
if (IS_DEBUG_OSPF_NSSA)
zlog_debug("%s: Stop", __func__);
@@ -2012,7 +2101,7 @@ void ospf_abr_task(struct ospf *ospf)
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("%s: prepare aggregates", __func__);
- ospf_abr_prepare_aggregates(ospf);
+ ospf_abr_prepare_aggregates(ospf, false);
if (IS_OSPF_ABR(ospf)) {
if (IS_DEBUG_OSPF_EVENT)
@@ -2031,6 +2120,11 @@ void ospf_abr_task(struct ospf *ospf)
zlog_debug("%s: announce stub defaults", __func__);
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) {
OSPF_LOG_DEBUG(IS_DEBUG_OSPF_EVENT,
"%s(): announce non-DNArouters",
@@ -2050,7 +2144,7 @@ void ospf_abr_task(struct ospf *ospf)
zlog_debug("%s: remove unapproved summaries", __func__);
ospf_abr_remove_unapproved_summaries(ospf);
- ospf_abr_manage_discard_routes(ospf);
+ ospf_abr_manage_discard_routes(ospf, false);
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("%s: Stop", __func__);
diff --git a/ospfd/ospf_abr.h b/ospfd/ospf_abr.h
index 19d444b125..cc2b2b0548 100644
--- a/ospfd/ospf_abr.h
+++ b/ospfd/ospf_abr.h
@@ -16,6 +16,7 @@
#define OSPF_AREA_RANGE_ADVERTISE (1 << 0)
#define OSPF_AREA_RANGE_SUBSTITUTE (1 << 1)
+#define OSPF_AREA_RANGE_NSSA (1 << 2)
/* Area range. */
struct ospf_area_range {
@@ -44,23 +45,23 @@ struct ospf_area_range {
/* Prototypes. */
extern struct ospf_area_range *ospf_area_range_lookup(struct ospf_area *,
+ struct route_table *,
struct prefix_ipv4 *);
-
-extern struct ospf_area_range *ospf_some_area_range_match(struct prefix_ipv4 *);
-
extern struct ospf_area_range *
ospf_area_range_lookup_next(struct ospf_area *, struct in_addr *, int);
-extern int ospf_area_range_set(struct ospf *, struct in_addr,
- struct prefix_ipv4 *, int);
-extern int ospf_area_range_cost_set(struct ospf *, struct in_addr,
- struct prefix_ipv4 *, uint32_t);
-extern int ospf_area_range_unset(struct ospf *, struct in_addr,
- struct prefix_ipv4 *);
-extern int ospf_area_range_substitute_set(struct ospf *, struct in_addr,
+extern int ospf_area_range_set(struct ospf *, struct ospf_area *,
+ struct route_table *, struct prefix_ipv4 *, int,
+ bool);
+extern int ospf_area_range_cost_set(struct ospf *, struct ospf_area *,
+ struct route_table *, struct prefix_ipv4 *,
+ uint32_t);
+extern int ospf_area_range_unset(struct ospf *, struct ospf_area *,
+ struct route_table *, struct prefix_ipv4 *);
+extern int ospf_area_range_substitute_set(struct ospf *, struct ospf_area *,
struct prefix_ipv4 *,
struct prefix_ipv4 *);
-extern int ospf_area_range_substitute_unset(struct ospf *, struct in_addr,
+extern int ospf_area_range_substitute_unset(struct ospf *, struct ospf_area *,
struct prefix_ipv4 *);
extern struct ospf_area_range *ospf_area_range_match_any(struct ospf *,
struct prefix_ipv4 *);
@@ -69,10 +70,12 @@ extern int ospf_act_bb_connection(struct ospf *);
extern void ospf_check_abr_status(struct ospf *);
extern void ospf_abr_task(struct ospf *);
+extern void ospf_abr_nssa_task(struct ospf *ospf);
extern void ospf_schedule_abr_task(struct ospf *);
extern void ospf_abr_announce_network_to_area(struct prefix_ipv4 *, uint32_t,
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_generate_indication_lsa(struct ospf *ospf,
const struct ospf_area *area);
diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c
index 82f7b96fd5..87b683b15d 100644
--- a/ospfd/ospf_lsa.c
+++ b/ospfd/ospf_lsa.c
@@ -1654,9 +1654,6 @@ struct in_addr ospf_get_nssa_ip(struct ospf_area *area)
if (best_default.s_addr != INADDR_ANY)
return best_default;
- if (best_default.s_addr != INADDR_ANY)
- return best_default;
-
return fwd;
}
@@ -1868,8 +1865,7 @@ static struct ospf_lsa *ospf_external_lsa_new(struct ospf *ospf,
}
/* As Type-7 */
-static void ospf_install_flood_nssa(struct ospf *ospf, struct ospf_lsa *lsa,
- struct external_info *ei)
+static void ospf_install_flood_nssa(struct ospf *ospf, struct ospf_lsa *lsa)
{
struct ospf_lsa *new;
struct as_external_lsa *extlsa;
@@ -2253,7 +2249,7 @@ struct ospf_lsa *ospf_external_lsa_originate(struct ospf *ospf,
/* stay away from translated LSAs! */
!(CHECK_FLAG(new->flags, OSPF_LSA_LOCAL_XLT)))
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. */
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
@@ -2266,6 +2262,100 @@ struct ospf_lsa *ospf_external_lsa_originate(struct ospf *ospf,
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)
{
int type;
@@ -2611,8 +2701,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 (ospf->anyNSSA && !(CHECK_FLAG(new->flags, OSPF_LSA_LOCAL_XLT)))
- ospf_install_flood_nssa(ospf, new,
- ei); /* Install/Flood per new rules */
+ ospf_install_flood_nssa(ospf,
+ new); /* Install/Flood per new rules */
/* Register self-originated LSA to refresh queue.
* Translated LSAs should not be registered, but refreshed upon
diff --git a/ospfd/ospf_lsa.h b/ospfd/ospf_lsa.h
index 8ab293f4db..d5ca0694cc 100644
--- a/ospfd/ospf_lsa.h
+++ b/ospfd/ospf_lsa.h
@@ -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 *,
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 struct ospf_lsa *ospf_lsa_lookup(struct ospf *ospf, struct ospf_area *,
uint32_t, struct in_addr,
diff --git a/ospfd/ospf_network.c b/ospfd/ospf_network.c
index d3f30ce1ee..bd5cd7682a 100644
--- a/ospfd/ospf_network.c
+++ b/ospfd/ospf_network.c
@@ -111,7 +111,7 @@ int ospf_if_drop_alldrouters(struct ospf *top, struct prefix *p,
"can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %pI4, ifindex %u, AllDRouters): %s",
top->fd, &p->u.prefix4, ifindex,
safe_strerror(errno));
- else
+ else if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
"interface %pI4 [%u] leave AllDRouters Multicast group.",
&p->u.prefix4, ifindex);
@@ -159,7 +159,6 @@ int ospf_sock_init(struct ospf *ospf)
{
int ospf_sock;
int ret, hincl = 1;
- int bufsize = (8 * 1024 * 1024);
/* silently ignore. already done */
if (ospf->fd > 0)
@@ -213,9 +212,28 @@ int ospf_sock_init(struct ospf *ospf)
ospf_sock);
}
- setsockopt_so_sendbuf(ospf_sock, bufsize);
- setsockopt_so_recvbuf(ospf_sock, bufsize);
+ /* Update socket buffer sizes */
+ ospf_sock_bufsize_update(ospf, ospf_sock, OSPF_SOCK_BOTH);
ospf->fd = ospf_sock;
return ret;
}
+
+/*
+ * Update a socket bufsize(s), based on its ospf instance
+ */
+void ospf_sock_bufsize_update(const struct ospf *ospf, int sock,
+ enum ospf_sock_type_e type)
+{
+ int bufsize;
+
+ if (type == OSPF_SOCK_BOTH || type == OSPF_SOCK_RECV) {
+ bufsize = ospf->recv_sock_bufsize;
+ setsockopt_so_recvbuf(sock, bufsize);
+ }
+
+ if (type == OSPF_SOCK_BOTH || type == OSPF_SOCK_SEND) {
+ bufsize = ospf->send_sock_bufsize;
+ setsockopt_so_sendbuf(sock, bufsize);
+ }
+}
diff --git a/ospfd/ospf_network.h b/ospfd/ospf_network.h
index 33fd8980bf..d9b579c04a 100644
--- a/ospfd/ospf_network.h
+++ b/ospfd/ospf_network.h
@@ -16,4 +16,14 @@ extern int ospf_if_drop_alldrouters(struct ospf *, struct prefix *, ifindex_t);
extern int ospf_if_ipmulticast(struct ospf *, struct prefix *, ifindex_t);
extern int ospf_sock_init(struct ospf *ospf);
+enum ospf_sock_type_e {
+ OSPF_SOCK_NONE = 0,
+ OSPF_SOCK_RECV,
+ OSPF_SOCK_SEND,
+ OSPF_SOCK_BOTH
+};
+
+void ospf_sock_bufsize_update(const struct ospf *ospf, int sock,
+ enum ospf_sock_type_e type);
+
#endif /* _ZEBRA_OSPF_NETWORK_H */
diff --git a/ospfd/ospf_route.c b/ospfd/ospf_route.c
index 5f18bff1cf..75868056ad 100644
--- a/ospfd/ospf_route.c
+++ b/ospfd/ospf_route.c
@@ -1008,7 +1008,8 @@ void ospf_prune_unreachable_routers(struct route_table *rtrs)
}
int ospf_add_discard_route(struct ospf *ospf, struct route_table *rt,
- struct ospf_area *area, struct prefix_ipv4 *p)
+ struct ospf_area *area, struct prefix_ipv4 *p,
+ bool nssa)
{
struct route_node *rn;
struct ospf_route * or, *new_or;
@@ -1027,7 +1028,7 @@ int ospf_add_discard_route(struct ospf *ospf, struct route_table *rt,
or = rn->info;
- if (or->path_type == OSPF_PATH_INTRA_AREA) {
+ if (!nssa && or->path_type == OSPF_PATH_INTRA_AREA) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("%s: an intra-area route exists",
__func__);
@@ -1054,7 +1055,10 @@ int ospf_add_discard_route(struct ospf *ospf, struct route_table *rt,
new_or->cost = 0;
new_or->u.std.area_id = area->area_id;
new_or->u.std.external_routing = area->external_routing;
- new_or->path_type = OSPF_PATH_INTER_AREA;
+ if (nssa)
+ new_or->path_type = OSPF_PATH_TYPE2_EXTERNAL;
+ else
+ new_or->path_type = OSPF_PATH_INTER_AREA;
rn->info = new_or;
ospf_zebra_add_discard(ospf, p);
@@ -1063,7 +1067,7 @@ int ospf_add_discard_route(struct ospf *ospf, struct route_table *rt,
}
void ospf_delete_discard_route(struct ospf *ospf, struct route_table *rt,
- struct prefix_ipv4 *p)
+ struct prefix_ipv4 *p, bool nssa)
{
struct route_node *rn;
struct ospf_route * or ;
@@ -1081,7 +1085,7 @@ void ospf_delete_discard_route(struct ospf *ospf, struct route_table *rt,
or = rn->info;
- if (or->path_type == OSPF_PATH_INTRA_AREA) {
+ if (!nssa && or->path_type == OSPF_PATH_INTRA_AREA) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("%s: an intra-area route exists", __func__);
return;
diff --git a/ospfd/ospf_route.h b/ospfd/ospf_route.h
index 2582067aec..7639a0049e 100644
--- a/ospfd/ospf_route.h
+++ b/ospfd/ospf_route.h
@@ -152,9 +152,10 @@ extern void ospf_route_subst_nexthops(struct ospf_route *, struct list *);
extern void ospf_prune_unreachable_networks(struct route_table *);
extern void ospf_prune_unreachable_routers(struct route_table *);
extern int ospf_add_discard_route(struct ospf *, struct route_table *,
- struct ospf_area *, struct prefix_ipv4 *);
+ struct ospf_area *, struct prefix_ipv4 *,
+ bool);
extern void ospf_delete_discard_route(struct ospf *, struct route_table *,
- struct prefix_ipv4 *);
+ struct prefix_ipv4 *, bool);
extern int ospf_route_match_same(struct route_table *, struct prefix_ipv4 *,
struct ospf_route *);
diff --git a/ospfd/ospf_routemap.c b/ospfd/ospf_routemap.c
index 3087008819..3d5c5aa2d5 100644
--- a/ospfd/ospf_routemap.c
+++ b/ospfd/ospf_routemap.c
@@ -120,7 +120,7 @@ route_match_ip_nexthop(void *rule, const struct prefix *prefix, void *object)
alist = access_list_lookup(AFI_IP, (char *)rule);
if (alist == NULL) {
- if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))
+ if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)))
zlog_debug(
"%s: Access-List Specified: %s does not exist defaulting to NO_MATCH",
__func__, (char *)rule);
@@ -168,7 +168,7 @@ route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix,
plist = prefix_list_lookup(AFI_IP, (char *)rule);
if (plist == NULL) {
- if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))
+ if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)))
zlog_debug(
"%s: Prefix List %s specified does not exist defaulting to NO_MATCH",
__func__, (char *)rule);
@@ -245,7 +245,7 @@ route_match_ip_address(void *rule, const struct prefix *prefix, void *object)
alist = access_list_lookup(AFI_IP, (char *)rule);
if (alist == NULL) {
- if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))
+ if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)))
zlog_debug(
"%s: Access-List Specified: %s does not exist defaulting to NO_MATCH",
__func__, (char *)rule);
@@ -286,7 +286,7 @@ route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
plist = prefix_list_lookup(AFI_IP, (char *)rule);
if (plist == NULL) {
- if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))
+ if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)))
zlog_debug(
"%s: Prefix List %s specified does not exist defaulting to NO_MATCH",
__func__, (char *)rule);
diff --git a/ospfd/ospf_snmp.c b/ospfd/ospf_snmp.c
index 2982cc7d6f..fcc43e7311 100644
--- a/ospfd/ospf_snmp.c
+++ b/ospfd/ospf_snmp.c
@@ -1112,7 +1112,7 @@ static struct ospf_area_range *ospfAreaRangeLookup(struct variable *v,
oid2in_addr(offset, IN_ADDR_SIZE, range_net);
p.prefix = *range_net;
- return ospf_area_range_lookup(area, &p);
+ return ospf_area_range_lookup(area, area->ranges, &p);
} else {
/* Set OID offset for Area ID. */
offset = name + v->namelen;
diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c
index dc9dd34303..b140027147 100644
--- a/ospfd/ospf_te.c
+++ b/ospfd/ospf_te.c
@@ -1781,7 +1781,7 @@ static void ospf_te_update_link(struct ls_ted *ted, struct ls_vertex *vertex,
* @param metric Standard metric attached to this Edge
*/
static void ospf_te_update_subnet(struct ls_ted *ted, struct ls_vertex *vertex,
- struct prefix p, uint8_t metric)
+ struct prefix *p, uint8_t metric)
{
struct ls_subnet *subnet;
struct ls_prefix *ls_pref;
@@ -1840,7 +1840,7 @@ static void ospf_te_delete_subnet(struct ls_ted *ted, struct in_addr addr)
p.family = AF_INET;
p.prefixlen = IPV4_MAX_BITLEN;
p.u.prefix4 = addr;
- subnet = ls_find_subnet(ted, p);
+ subnet = ls_find_subnet(ted, &p);
/* Remove subnet if found */
if (subnet) {
@@ -1933,7 +1933,7 @@ static int ospf_te_parse_router_lsa(struct ls_ted *ted, struct ospf_lsa *lsa)
p.prefixlen = IPV4_MAX_BITLEN;
p.u.prefix4 = rl->link[i].link_data;
metric = ntohs(rl->link[i].metric);
- ospf_te_update_subnet(ted, vertex, p, metric);
+ ospf_te_update_subnet(ted, vertex, &p, metric);
break;
case LSA_LINK_TYPE_STUB:
/* Keep only /32 prefix */
@@ -1942,7 +1942,7 @@ static int ospf_te_parse_router_lsa(struct ls_ted *ted, struct ospf_lsa *lsa)
p.family = AF_INET;
p.u.prefix4 = rl->link[i].link_id;
metric = ntohs(rl->link[i].metric);
- ospf_te_update_subnet(ted, vertex, p, metric);
+ ospf_te_update_subnet(ted, vertex, &p, metric);
}
break;
default:
@@ -2074,12 +2074,12 @@ static void ospf_te_update_remote_asbr(struct ls_ted *ted, struct ls_edge *edge)
p.family = AF_INET;
p.prefixlen = IPV4_MAX_BITLEN;
p.u.prefix4 = attr->standard.local;
- ospf_te_update_subnet(ted, edge->source, p, attr->standard.te_metric);
+ ospf_te_update_subnet(ted, edge->source, &p, attr->standard.te_metric);
p.family = AF_INET;
p.prefixlen = IPV4_MAX_BITLEN;
p.u.prefix4 = attr->standard.remote_addr;
- ospf_te_update_subnet(ted, vertex, p, attr->standard.te_metric);
+ ospf_te_update_subnet(ted, vertex, &p, attr->standard.te_metric);
/* Connect Edge to the remote Vertex */
if (edge->destination == NULL) {
@@ -2625,14 +2625,14 @@ static int ospf_te_parse_ext_pref(struct ls_ted *ted, struct ospf_lsa *lsa)
pref.family = AF_INET;
pref.prefixlen = ext->pref_length;
pref.u.prefix4 = ext->address;
- subnet = ls_find_subnet(ted, pref);
+ subnet = ls_find_subnet(ted, &pref);
/* Create new Link State Prefix if not found */
if (!subnet) {
lnid.origin = OSPFv2;
lnid.id.ip.addr = lsa->data->adv_router;
lnid.id.ip.area_id = lsa->area->area_id;
- ls_pref = ls_prefix_new(lnid, pref);
+ ls_pref = ls_prefix_new(lnid, &pref);
/* and add it to the TED */
subnet = ls_subnet_add(ted, ls_pref);
}
@@ -2698,7 +2698,7 @@ static int ospf_te_delete_ext_pref(struct ls_ted *ted, struct ospf_lsa *lsa)
pref.family = AF_INET;
pref.prefixlen = ext->pref_length;
pref.u.prefix4 = ext->address;
- subnet = ls_find_subnet(ted, pref);
+ subnet = ls_find_subnet(ted, &pref);
/* Check if there is a corresponding subnet */
if (!subnet)
@@ -4398,7 +4398,7 @@ DEFUN (show_ip_ospf_mpls_te_db,
return CMD_WARNING_CONFIG_FAILED;
}
/* Get the Subnet from the Link State Database */
- subnet = ls_find_subnet(OspfMplsTE.ted, pref);
+ subnet = ls_find_subnet(OspfMplsTE.ted, &pref);
if (!subnet) {
vty_out(vty, "No subnet found for ID %pFX\n",
&pref);
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index 8c0afd8527..9b918798c0 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -611,6 +611,7 @@ DEFUN (ospf_area_range,
"Advertised metric for this range\n")
{
VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
+ struct ospf_area *area;
int idx_ipv4_number = 1;
int idx_ipv4_prefixlen = 3;
int idx_cost = 6;
@@ -622,12 +623,14 @@ DEFUN (ospf_area_range,
VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg);
str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p);
- ospf_area_range_set(ospf, area_id, &p, OSPF_AREA_RANGE_ADVERTISE);
- ospf_area_display_format_set(ospf, ospf_area_get(ospf, area_id),
- format);
+ area = ospf_area_get(ospf, area_id);
+ ospf_area_display_format_set(ospf, area, format);
+
+ ospf_area_range_set(ospf, area, area->ranges, &p,
+ OSPF_AREA_RANGE_ADVERTISE, false);
if (argc > 5) {
cost = strtoul(argv[idx_cost]->arg, NULL, 10);
- ospf_area_range_cost_set(ospf, area_id, &p, cost);
+ ospf_area_range_cost_set(ospf, area, area->ranges, &p, cost);
}
return CMD_SUCCESS;
@@ -647,6 +650,7 @@ DEFUN (ospf_area_range_cost,
"Network prefix to be announced instead of range\n")
{
VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
+ struct ospf_area *area;
int idx_ipv4_number = 1;
int idx_ipv4_prefixlen = 3;
int idx = 4;
@@ -658,19 +662,20 @@ DEFUN (ospf_area_range_cost,
VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg);
str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p);
- ospf_area_range_set(ospf, area_id, &p, OSPF_AREA_RANGE_ADVERTISE);
- ospf_area_display_format_set(ospf, ospf_area_get(ospf, area_id),
- format);
+ area = ospf_area_get(ospf, area_id);
+ ospf_area_display_format_set(ospf, area, format);
+ ospf_area_range_set(ospf, area, area->ranges, &p,
+ OSPF_AREA_RANGE_ADVERTISE, false);
if (argv_find(argv, argc, "cost", &idx)) {
cost = strtoul(argv[idx + 1]->arg, NULL, 10);
- ospf_area_range_cost_set(ospf, area_id, &p, cost);
+ ospf_area_range_cost_set(ospf, area, area->ranges, &p, cost);
}
idx = 4;
if (argv_find(argv, argc, "substitute", &idx)) {
str2prefix_ipv4(argv[idx + 1]->arg, &s);
- ospf_area_range_substitute_set(ospf, area_id, &p, &s);
+ ospf_area_range_substitute_set(ospf, area, &p, &s);
}
return CMD_SUCCESS;
@@ -687,6 +692,7 @@ DEFUN (ospf_area_range_not_advertise,
"DoNotAdvertise this range\n")
{
VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
+ struct ospf_area *area;
int idx_ipv4_number = 1;
int idx_ipv4_prefixlen = 3;
struct prefix_ipv4 p;
@@ -696,10 +702,11 @@ DEFUN (ospf_area_range_not_advertise,
VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg);
str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p);
- ospf_area_range_set(ospf, area_id, &p, 0);
- ospf_area_display_format_set(ospf, ospf_area_get(ospf, area_id),
- format);
- ospf_area_range_substitute_unset(ospf, area_id, &p);
+ area = ospf_area_get(ospf, area_id);
+ ospf_area_display_format_set(ospf, area, format);
+
+ ospf_area_range_set(ospf, area, area->ranges, &p, 0, false);
+ ospf_area_range_substitute_unset(ospf, area, &p);
return CMD_SUCCESS;
}
@@ -721,6 +728,7 @@ DEFUN (no_ospf_area_range,
"DoNotAdvertise this range\n")
{
VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
+ struct ospf_area *area;
int idx_ipv4_number = 2;
int idx_ipv4_prefixlen = 4;
struct prefix_ipv4 p;
@@ -730,7 +738,10 @@ DEFUN (no_ospf_area_range,
VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg);
str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p);
- ospf_area_range_unset(ospf, area_id, &p);
+ area = ospf_area_get(ospf, area_id);
+ ospf_area_display_format_set(ospf, area, format);
+
+ ospf_area_range_unset(ospf, area, area->ranges, &p);
return CMD_SUCCESS;
}
@@ -748,6 +759,7 @@ DEFUN (no_ospf_area_range_substitute,
"Network prefix to be announced instead of range\n")
{
VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
+ struct ospf_area *area;
int idx_ipv4_number = 2;
int idx_ipv4_prefixlen = 4;
int idx_ipv4_prefixlen_2 = 6;
@@ -759,7 +771,10 @@ DEFUN (no_ospf_area_range_substitute,
str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p);
str2prefix_ipv4(argv[idx_ipv4_prefixlen_2]->arg, &s);
- ospf_area_range_substitute_unset(ospf, area_id, &p);
+ area = ospf_area_get(ospf, area_id);
+ ospf_area_display_format_set(ospf, area, format);
+
+ ospf_area_range_substitute_unset(ospf, area, &p);
return CMD_SUCCESS;
}
@@ -1433,15 +1448,35 @@ DEFUN (no_ospf_area_stub_no_summary,
return CMD_SUCCESS;
}
-static int ospf_area_nssa_cmd_handler(struct vty *vty, int argc,
- struct cmd_token **argv, int cfg_nosum,
- int nosum)
+DEFPY (ospf_area_nssa,
+ ospf_area_nssa_cmd,
+ "area <A.B.C.D|(0-4294967295)>$area_str nssa\
+ [{\
+ <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\
+ |suppress-fa$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"
+ "Configure NSSA-ABR for translate election (default)\n"
+ "Configure NSSA-ABR to never 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"
+ "Suppress forwarding address\n")
{
VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
struct in_addr area_id;
int ret, format;
- VTY_GET_OSPF_AREA_ID_NO_BB("NSSA", area_id, format, argv[1]->arg);
+ VTY_GET_OSPF_AREA_ID_NO_BB("NSSA", area_id, format, area_str);
ret = ospf_area_nssa_set(ospf, area_id);
ospf_area_display_format_set(ospf, ospf_area_get(ospf, area_id),
@@ -1452,14 +1487,14 @@ static int ospf_area_nssa_cmd_handler(struct vty *vty, int argc,
return CMD_WARNING_CONFIG_FAILED;
}
- if (argc > 3) {
- if (strncmp(argv[3]->text, "translate-c", 11) == 0)
+ if (translator_role) {
+ if (strncmp(translator_role, "translate-c", 11) == 0)
ospf_area_nssa_translator_role_set(
ospf, area_id, OSPF_NSSA_ROLE_CANDIDATE);
- else if (strncmp(argv[3]->text, "translate-n", 11) == 0)
+ else if (strncmp(translator_role, "translate-n", 11) == 0)
ospf_area_nssa_translator_role_set(
ospf, area_id, OSPF_NSSA_ROLE_NEVER);
- else if (strncmp(argv[3]->text, "translate-a", 11) == 0)
+ else if (strncmp(translator_role, "translate-a", 11) == 0)
ospf_area_nssa_translator_role_set(
ospf, area_id, OSPF_NSSA_ROLE_ALWAYS);
} else {
@@ -1467,12 +1502,27 @@ static int ospf_area_nssa_cmd_handler(struct vty *vty, int argc,
OSPF_NSSA_ROLE_CANDIDATE);
}
- if (cfg_nosum) {
- if (nosum)
- ospf_area_no_summary_set(ospf, area_id);
- else
- ospf_area_no_summary_unset(ospf, area_id);
- }
+ 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)
+ ospf_area_nssa_no_summary_set(ospf, area_id);
+ else
+ ospf_area_no_summary_unset(ospf, area_id);
+
+ if (suppress_fa)
+ ospf_area_nssa_suppress_fa_set(ospf, area_id);
+ else
+ ospf_area_nssa_suppress_fa_unset(ospf, area_id);
/* Flush the external LSA for the specified area */
ospf_flush_lsa_from_area(ospf, area_id, OSPF_AS_EXTERNAL_LSA);
@@ -1482,168 +1532,125 @@ static int ospf_area_nssa_cmd_handler(struct vty *vty, int argc,
return CMD_SUCCESS;
}
-
-DEFUN (ospf_area_nssa_translate,
- ospf_area_nssa_translate_cmd,
- "area <A.B.C.D|(0-4294967295)> nssa <translate-candidate|translate-never|translate-always>",
+DEFPY (no_ospf_area_nssa,
+ no_ospf_area_nssa_cmd,
+ "no area <A.B.C.D|(0-4294967295)>$area_str nssa\
+ [{\
+ <translate-candidate|translate-never|translate-always>\
+ |default-information-originate [{metric (0-16777214)|metric-type (1-2)}]\
+ |no-summary\
+ |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"
"Configure NSSA-ABR for translate election (default)\n"
"Configure NSSA-ABR to never translate\n"
- "Configure NSSA-ABR to always translate\n")
-{
- return ospf_area_nssa_cmd_handler(vty, argc, argv, 0, 0);
-}
-
-DEFUN (ospf_area_nssa,
- ospf_area_nssa_cmd,
- "area <A.B.C.D|(0-4294967295)> nssa",
- "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")
-{
- 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")
+ "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"
+ "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);
+ VTY_GET_OSPF_AREA_ID_NO_BB("NSSA", area_id, format, area_str);
- ospf_area_display_format_set(ospf, ospf_area_get(ospf, area_id),
- format);
+ /* Flush the NSSA LSA for the specified area */
+ ospf_flush_lsa_from_area(ospf, area_id, OSPF_AS_NSSA_LSA);
+ 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_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",
+DEFPY (ospf_area_nssa_range,
+ ospf_area_nssa_range_cmd,
+ "area <A.B.C.D|(0-4294967295)>$area_str nssa range A.B.C.D/M$prefix [<not-advertise$not_adv|cost (0-16777215)$cost>]",
"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"
- "Do not inject inter-area routes into nssa\n")
+ "Configured address range\n"
+ "Specify IPv4 prefix\n"
+ "Do not advertise\n"
+ "User specified metric for this range\n"
+ "Advertised metric for this range\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_no_summary_set(ospf, area_id);
-
- ospf_schedule_abr_task(ospf);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_ospf_area_nssa_no_summary,
- no_ospf_area_nssa_no_summary_cmd,
- "no area <A.B.C.D|(0-4294967295)> nssa no-summary",
- 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"
- "Do not inject inter-area routes into nssa\n")
-{
- int idx_ipv4_number = 2;
+ struct ospf_area *area;
struct in_addr area_id;
int format;
+ int advertise = 0;
- VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
+ VTY_GET_OSPF_AREA_ID(area_id, format, area_str);
+ area = ospf_area_get(ospf, area_id);
+ ospf_area_display_format_set(ospf, area, format);
- VTY_GET_OSPF_AREA_ID_NO_BB("nssa", area_id, format,
- argv[idx_ipv4_number]->arg);
+ if (area->external_routing != OSPF_AREA_NSSA) {
+ vty_out(vty, "%% First configure %s as an NSSA area\n",
+ area_str);
+ return CMD_WARNING;
+ }
- ospf_area_display_format_set(ospf, ospf_area_get(ospf, area_id),
- format);
- ospf_area_no_summary_unset(ospf, area_id);
+ if (!not_adv)
+ advertise = OSPF_AREA_RANGE_ADVERTISE;
- ospf_schedule_abr_task(ospf);
+ ospf_area_range_set(ospf, area, area->nssa_ranges,
+ (struct prefix_ipv4 *)prefix, advertise, true);
+ if (cost_str)
+ ospf_area_range_cost_set(ospf, area, area->nssa_ranges,
+ (struct prefix_ipv4 *)prefix, cost);
return CMD_SUCCESS;
}
-DEFUN (no_ospf_area_nssa,
- no_ospf_area_nssa_cmd,
- "no area <A.B.C.D|(0-4294967295)> nssa [<translate-candidate|translate-never|translate-always>]",
+DEFPY (no_ospf_area_nssa_range,
+ no_ospf_area_nssa_range_cmd,
+ "no area <A.B.C.D|(0-4294967295)>$area_str nssa range A.B.C.D/M$prefix [<not-advertise|cost (0-16777215)>]",
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"
- "Configure NSSA-ABR for translate election (default)\n"
- "Configure NSSA-ABR to never translate\n"
- "Configure NSSA-ABR to always translate\n")
+ "Configured address range\n"
+ "Specify IPv4 prefix\n"
+ "Do not advertise\n"
+ "User specified metric for this range\n"
+ "Advertised metric for this range\n")
{
VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
- int idx_ipv4_number = 2;
+ struct ospf_area *area;
struct in_addr area_id;
int format;
- VTY_GET_OSPF_AREA_ID_NO_BB("NSSA", area_id, format,
- argv[idx_ipv4_number]->arg);
+ VTY_GET_OSPF_AREA_ID(area_id, format, area_str);
+ area = ospf_area_get(ospf, area_id);
+ ospf_area_display_format_set(ospf, area, format);
- /* Flush the NSSA LSA for the specified area */
- ospf_flush_lsa_from_area(ospf, area_id, OSPF_AS_NSSA_LSA);
- ospf_area_nssa_unset(ospf, area_id, argc);
+ if (area->external_routing != OSPF_AREA_NSSA) {
+ vty_out(vty, "%% First configure %s as an NSSA area\n",
+ area_str);
+ return CMD_WARNING;
+ }
- ospf_schedule_abr_task(ospf);
+ ospf_area_range_unset(ospf, area, area->nssa_ranges,
+ (struct prefix_ipv4 *)prefix);
return CMD_SUCCESS;
}
-
DEFUN (ospf_area_default_cost,
ospf_area_default_cost_cmd,
"area <A.B.C.D|(0-4294967295)> default-cost (0-16777215)",
@@ -3396,6 +3403,23 @@ static int show_ip_ospf_common(struct vty *vty, struct ospf *ospf,
/* show LDP-Sync status */
ospf_ldp_sync_show_info(vty, ospf, json_vrf, json ? 1 : 0);
+ /* Socket buffer sizes */
+ if (json) {
+ if (ospf->recv_sock_bufsize != OSPF_DEFAULT_SOCK_BUFSIZE)
+ json_object_int_add(json_vrf, "recvSockBufsize",
+ ospf->recv_sock_bufsize);
+ if (ospf->send_sock_bufsize != OSPF_DEFAULT_SOCK_BUFSIZE)
+ json_object_int_add(json_vrf, "sendSockBufsize",
+ ospf->send_sock_bufsize);
+ } else {
+ if (ospf->recv_sock_bufsize != OSPF_DEFAULT_SOCK_BUFSIZE)
+ vty_out(vty, " Receive socket bufsize: %u\n",
+ ospf->recv_sock_bufsize);
+ if (ospf->send_sock_bufsize != OSPF_DEFAULT_SOCK_BUFSIZE)
+ vty_out(vty, " Send socket bufsize: %u\n",
+ ospf->send_sock_bufsize);
+ }
+
/* Show each area status. */
for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area))
show_ip_ospf_area(vty, area, json_areas, json ? 1 : 0);
@@ -5065,6 +5089,7 @@ static void show_ip_ospf_neighbor_detail_sub(struct vty *vty,
json_object *json_neigh = NULL, *json_neigh_array = NULL;
char neigh_str[INET_ADDRSTRLEN] = {0};
char neigh_state[16] = {0};
+ struct ospf_neighbor *nbr_dr, *nbr_bdr;
if (use_json) {
if (prev_nbr &&
@@ -5192,19 +5217,38 @@ static void show_ip_ospf_neighbor_detail_sub(struct vty *vty,
}
}
- /* Show Designated Rotuer ID. */
- if (use_json)
- json_object_string_addf(json_neigh, "routerDesignatedId",
- "%pI4", &nbr->d_router);
- else
- vty_out(vty, " DR is %pI4,", &nbr->d_router);
+ /* Show Designated Router ID. */
+ if (DR(oi).s_addr == INADDR_ANY) {
+ if (!use_json)
+ vty_out(vty,
+ " No designated router on this network\n");
+ } else {
+ nbr_dr = ospf_nbr_lookup_by_addr(oi->nbrs, &DR(oi));
+ if (nbr_dr) {
+ if (use_json)
+ json_object_string_addf(
+ json_neigh, "routerDesignatedId",
+ "%pI4", &nbr_dr->router_id);
+ else
+ vty_out(vty, " DR is %pI4,",
+ &nbr_dr->router_id);
+ }
+ }
- /* Show Backup Designated Rotuer ID. */
- if (use_json)
- json_object_string_addf(json_neigh, "routerDesignatedBackupId",
- "%pI4", &nbr->bd_router);
- else
- vty_out(vty, " BDR is %pI4\n", &nbr->bd_router);
+ /* Show Backup Designated Router ID. */
+ nbr_bdr = ospf_nbr_lookup_by_addr(oi->nbrs, &BDR(oi));
+ if (nbr_bdr == NULL) {
+ if (!use_json)
+ vty_out(vty,
+ " No backup designated router on this network\n");
+ } else {
+ if (use_json)
+ json_object_string_addf(json_neigh,
+ "routerDesignatedBackupId",
+ "%pI4", &nbr_bdr->router_id);
+ else
+ vty_out(vty, " BDR is %pI4\n", &nbr_bdr->router_id);
+ }
/* Show options. */
if (use_json) {
@@ -11981,29 +12025,62 @@ static int config_write_ospf_area(struct vty *vty, struct ospf *ospf)
vty_out(vty, " no-summary\n");
vty_out(vty, "\n");
} else if (area->external_routing == OSPF_AREA_NSSA) {
+ vty_out(vty, " area %s nssa", buf);
+
switch (area->NSSATranslatorRole) {
case OSPF_NSSA_ROLE_NEVER:
- vty_out(vty,
- " area %s nssa translate-never\n",
- buf);
+ vty_out(vty, " translate-never");
break;
case OSPF_NSSA_ROLE_ALWAYS:
- vty_out(vty,
- " area %s nssa translate-always\n",
- buf);
+ vty_out(vty, " translate-always");
break;
case OSPF_NSSA_ROLE_CANDIDATE:
- vty_out(vty, " area %s nssa \n", buf);
break;
}
- if (area->no_summary)
+
+ if (area->nssa_default_originate.enabled) {
vty_out(vty,
- " area %s nssa no-summary\n",
- buf);
+ " 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)
+ vty_out(vty, " no-summary");
if (area->suppress_fa)
- vty_out(vty,
- " area %s nssa suppress-fa\n",
- buf);
+ vty_out(vty, " suppress-fa");
+ vty_out(vty, "\n");
+
+ for (rn1 = route_top(area->nssa_ranges); rn1;
+ rn1 = route_next(rn1)) {
+ struct ospf_area_range *range;
+
+ range = rn1->info;
+ if (!range)
+ continue;
+
+ vty_out(vty, " area %s nssa range %pFX",
+ buf, &rn1->p);
+
+ if (range->cost_config !=
+ OSPF_AREA_RANGE_COST_UNSPEC)
+ vty_out(vty, " cost %u",
+ range->cost_config);
+
+ if (!CHECK_FLAG(
+ range->flags,
+ OSPF_AREA_RANGE_ADVERTISE))
+ vty_out(vty, " not-advertise");
+
+ vty_out(vty, "\n");
+ }
}
if (area->default_cost != 1)
@@ -12490,6 +12567,22 @@ static int ospf_config_write_one(struct vty *vty, struct ospf *ospf)
/* LDP-Sync print */
ospf_ldp_sync_write_config(vty, ospf);
+ /* Socket buffer sizes */
+ if (ospf->recv_sock_bufsize != OSPF_DEFAULT_SOCK_BUFSIZE) {
+ if (ospf->send_sock_bufsize == ospf->recv_sock_bufsize)
+ vty_out(vty, " socket buffer all %u\n",
+ ospf->recv_sock_bufsize);
+ else
+ vty_out(vty, " socket buffer recv %u\n",
+ ospf->recv_sock_bufsize);
+ }
+
+ if (ospf->send_sock_bufsize != OSPF_DEFAULT_SOCK_BUFSIZE &&
+ ospf->send_sock_bufsize != ospf->recv_sock_bufsize)
+ vty_out(vty, " socket buffer send %u\n",
+ ospf->send_sock_bufsize);
+
+
vty_out(vty, "exit\n");
write++;
@@ -12946,6 +13039,42 @@ DEFPY(no_flood_reduction_area, no_flood_reduction_area_cmd,
return CMD_SUCCESS;
}
+DEFPY(ospf_socket_bufsizes,
+ ospf_socket_bufsizes_cmd,
+ "[no] socket buffer <send$send_val | recv$recv_val | all$all_val> \
+ ![(1-4000000000)$bufsize]",
+ NO_STR
+ "Socket parameters\n"
+ "Buffer size configuration\n"
+ "Send buffer size\n"
+ "Receive buffer size\n"
+ "Both send and receive buffer sizes\n"
+ "Buffer size, in bytes\n")
+{
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
+ uint32_t recvsz, sendsz;
+
+ if (no)
+ bufsize = OSPF_DEFAULT_SOCK_BUFSIZE;
+
+ if (all_val) {
+ recvsz = bufsize;
+ sendsz = bufsize;
+ } else if (send_val) {
+ sendsz = bufsize;
+ recvsz = ospf->recv_sock_bufsize;
+ } else if (recv_val) {
+ recvsz = bufsize;
+ sendsz = ospf->send_sock_bufsize;
+ } else
+ return CMD_SUCCESS;
+
+ /* React to a change by modifying existing sockets */
+ ospf_update_bufsize(ospf, recvsz, sendsz);
+
+ return CMD_SUCCESS;
+}
+
void ospf_vty_clear_init(void)
{
install_element(ENABLE_NODE, &clear_ip_ospf_interface_cmd);
@@ -13029,12 +13158,9 @@ void ospf_vty_init(void)
/* "area nssa" commands. */
install_element(OSPF_NODE, &ospf_area_nssa_cmd);
- 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_nssa_range_cmd);
+ install_element(OSPF_NODE, &no_ospf_area_nssa_range_cmd);
install_element(OSPF_NODE, &ospf_area_default_cost_cmd);
install_element(OSPF_NODE, &no_ospf_area_default_cost_cmd);
@@ -13112,6 +13238,8 @@ void ospf_vty_init(void)
install_element(OSPF_NODE, &flood_reduction_area_cmd);
install_element(OSPF_NODE, &no_flood_reduction_area_cmd);
+ install_element(OSPF_NODE, &ospf_socket_bufsizes_cmd);
+
/* Init interface related vty commands. */
ospf_vty_if_init();
diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c
index 3e02d3c33e..3f967e41e4 100644
--- a/ospfd/ospf_zebra.c
+++ b/ospfd/ospf_zebra.c
@@ -20,6 +20,7 @@
#include "log.h"
#include "route_opaque.h"
#include "lib/bfd.h"
+#include "lib/lib_errors.h"
#include "nexthop.h"
#include "ospfd/ospfd.h"
@@ -1470,6 +1471,61 @@ static int ospf_zebra_read_route(ZAPI_CALLBACK_ARGS)
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)
{
@@ -2132,6 +2188,7 @@ static zclient_handler *const ospf_handlers[] = {
[ZEBRA_REDISTRIBUTE_ROUTE_ADD] = 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,
diff --git a/ospfd/ospf_zebra.h b/ospfd/ospf_zebra.h
index 711b1e7a61..86a5678fc4 100644
--- a/ospfd/ospf_zebra.h
+++ b/ospfd/ospf_zebra.h
@@ -69,6 +69,7 @@ extern int ospf_redistribute_set(struct ospf *, struct ospf_redist *, int,
unsigned short, int, int);
extern int ospf_redistribute_unset(struct ospf *, int, unsigned short);
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_unset(struct ospf *, int, const char *);
extern void ospf_routemap_set(struct ospf_redist *, const char *);
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index 112ddfedb7..15ce1c48a4 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -420,6 +420,9 @@ struct ospf *ospf_new_alloc(unsigned short instance, const char *name)
new->fd = -1;
+ new->recv_sock_bufsize = OSPF_DEFAULT_SOCK_BUFSIZE;
+ new->send_sock_bufsize = OSPF_DEFAULT_SOCK_BUFSIZE;
+
return new;
}
@@ -963,6 +966,7 @@ struct ospf_area *ospf_area_new(struct ospf *ospf, struct in_addr area_id)
new->oiflist = list_new();
new->ranges = route_table_init();
+ new->nssa_ranges = route_table_init();
if (area_id.s_addr == OSPF_AREA_BACKBONE)
ospf->backbone = new;
@@ -1006,6 +1010,7 @@ static void ospf_area_free(struct ospf_area *area)
ospf_lsa_unlock(&area->router_lsa_self);
route_table_finish(area->ranges);
+ route_table_finish(area->nssa_ranges);
list_delete(&area->oiflist);
if (EXPORT_NAME(area))
@@ -1029,13 +1034,14 @@ void ospf_area_check_free(struct ospf *ospf, struct in_addr area_id)
struct ospf_area *area;
area = ospf_area_lookup_by_area_id(ospf, area_id);
- if (area && listcount(area->oiflist) == 0 && area->ranges->top == NULL
- && !ospf_vl_count(ospf, area)
- && area->shortcut_configured == OSPF_SHORTCUT_DEFAULT
- && area->external_routing == OSPF_AREA_DEFAULT
- && area->no_summary == 0 && area->default_cost == 1
- && EXPORT_NAME(area) == NULL && IMPORT_NAME(area) == NULL
- && area->auth_type == OSPF_AUTH_NULL) {
+ if (area && listcount(area->oiflist) == 0 &&
+ area->ranges->top == NULL && area->nssa_ranges->top == NULL &&
+ !ospf_vl_count(ospf, area) &&
+ area->shortcut_configured == OSPF_SHORTCUT_DEFAULT &&
+ area->external_routing == OSPF_AREA_DEFAULT &&
+ area->no_summary == 0 && area->default_cost == 1 &&
+ EXPORT_NAME(area) == NULL && IMPORT_NAME(area) == NULL &&
+ area->auth_type == OSPF_AUTH_NULL) {
listnode_delete(ospf->areas, area);
ospf_area_free(area);
}
@@ -1701,7 +1707,7 @@ int ospf_area_nssa_set(struct ospf *ospf, struct in_addr area_id)
return 1;
}
-int ospf_area_nssa_unset(struct ospf *ospf, struct in_addr area_id, int argc)
+int ospf_area_nssa_unset(struct ospf *ospf, struct in_addr area_id)
{
struct ospf_area *area;
@@ -1709,22 +1715,14 @@ int ospf_area_nssa_unset(struct ospf *ospf, struct in_addr area_id, int argc)
if (area == NULL)
return 0;
- /* argc < 5 -> 'no area x nssa' */
- if (argc < 5 && area->external_routing == OSPF_AREA_NSSA) {
- 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 =
- OSPF_NSSA_TRANS_STABLE_DEFAULT;
- ospf_area_type_set(area, OSPF_AREA_DEFAULT);
- } else {
- ospf_area_nssa_translator_role_set(ospf, area_id,
- OSPF_NSSA_ROLE_CANDIDATE);
- }
-
+ 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 = OSPF_NSSA_TRANS_STABLE_DEFAULT;
+ ospf_area_type_set(area, OSPF_AREA_DEFAULT);
ospf_area_check_free(ospf, area_id);
return 1;
@@ -1782,6 +1780,51 @@ int ospf_area_nssa_translator_role_set(struct ospf *ospf,
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,
const char *list_name)
{
@@ -2140,6 +2183,32 @@ int ospf_nbr_nbma_poll_interval_unset(struct ospf *ospf, struct in_addr addr)
return 1;
}
+/*
+ * Update socket bufsize(s), usually after config change
+ */
+void ospf_update_bufsize(struct ospf *ospf, uint32_t recvsize,
+ uint32_t sendsize)
+{
+ enum ospf_sock_type_e type = OSPF_SOCK_NONE;
+
+ /* Figure out whether there's been a change */
+ if (recvsize != ospf->recv_sock_bufsize) {
+ type = OSPF_SOCK_RECV;
+ ospf->recv_sock_bufsize = recvsize;
+
+ if (sendsize != ospf->send_sock_bufsize) {
+ type = OSPF_SOCK_BOTH;
+ ospf->send_sock_bufsize = sendsize;
+ }
+ } else if (sendsize != ospf->send_sock_bufsize) {
+ type = OSPF_SOCK_SEND;
+ ospf->send_sock_bufsize = sendsize;
+ }
+
+ if (type != OSPF_SOCK_NONE)
+ ospf_sock_bufsize_update(ospf, ospf->fd, type);
+}
+
void ospf_master_init(struct event_loop *master)
{
memset(&ospf_master, 0, sizeof(ospf_master));
diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h
index 6727d802a6..1b66d4d930 100644
--- a/ospfd/ospfd.h
+++ b/ospfd/ospfd.h
@@ -67,6 +67,9 @@
#define OSPF_LS_REFRESH_SHIFT (60 * 15)
#define OSPF_LS_REFRESH_JITTER 60
+/* Default socket buffer size */
+#define OSPF_DEFAULT_SOCK_BUFSIZE (8 * 1024 * 1024)
+
struct ospf_external {
unsigned short instance;
struct route_table *external_info;
@@ -302,6 +305,18 @@ struct ospf {
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_SLOTS \
((OSPF_LS_REFRESH_TIME + OSPF_LS_REFRESH_SHIFT) \
@@ -412,6 +427,10 @@ struct ospf {
/* Flood Reduction configuration state */
bool fr_configured;
+ /* Socket buffer sizes */
+ uint32_t recv_sock_bufsize;
+ uint32_t send_sock_bufsize;
+
QOBJ_FIELDS;
};
DECLARE_QOBJ_TYPE(ospf);
@@ -517,6 +536,7 @@ struct ospf_area {
#define OSPF_TRANSIT_FALSE 0
#define OSPF_TRANSIT_TRUE 1
struct route_table *ranges; /* Configured Area Ranges. */
+ struct route_table *nssa_ranges; /* Configured NSSA Area Ranges. */
/* RFC3137 stub router state flags for area */
uint8_t stub_router_state;
@@ -561,6 +581,13 @@ struct ospf_area {
#define PREFIX_LIST_OUT(A) (A)->plist_out.list
#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. */
struct vertex *spf;
struct list *spf_vertex_list;
@@ -697,14 +724,18 @@ extern int ospf_area_no_summary_set(struct ospf *ospf, struct in_addr area_id);
extern int ospf_area_no_summary_unset(struct ospf *ospf,
struct in_addr area_id);
extern int ospf_area_nssa_set(struct ospf *ospf, struct in_addr area_id);
-extern int ospf_area_nssa_unset(struct ospf *ospf, struct in_addr area_id,
- int argc);
+extern int ospf_area_nssa_unset(struct ospf *ospf, struct in_addr area_id);
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 *ospf,
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,
struct ospf_area *area_id,
const char *list_name);
@@ -769,6 +800,9 @@ int ospf_area_nssa_no_summary_set(struct ospf *ospf, struct in_addr area_id);
const char *ospf_get_name(const struct ospf *ospf);
extern struct ospf_interface *add_ospf_interface(struct connected *co,
struct ospf_area *area);
+/* Update socket bufsize(s), after config change */
+void ospf_update_bufsize(struct ospf *ospf, uint32_t recvsize,
+ uint32_t sendsize);
extern int p_spaces_compare_func(const struct p_space *a,
const struct p_space *b);
diff --git a/pathd/path_ted.c b/pathd/path_ted.c
index d8ddd8cdc8..fd5c342d84 100644
--- a/pathd/path_ted.c
+++ b/pathd/path_ted.c
@@ -268,7 +268,7 @@ uint32_t path_ted_query_type_c(struct prefix *prefix, uint8_t algo)
switch (prefix->family) {
case AF_INET:
case AF_INET6:
- subnet = ls_find_subnet(ted_state_g.ted, *prefix);
+ subnet = ls_find_subnet(ted_state_g.ted, prefix);
if (subnet) {
if ((CHECK_FLAG(subnet->ls_pref->flags, LS_PREF_SR))
&& (subnet->ls_pref->sr.algo == algo))
@@ -298,7 +298,7 @@ uint32_t path_ted_query_type_e(struct prefix *prefix, uint32_t iface_id)
switch (prefix->family) {
case AF_INET:
case AF_INET6:
- subnet = ls_find_subnet(ted_state_g.ted, *prefix);
+ subnet = ls_find_subnet(ted_state_g.ted, prefix);
if (subnet && subnet->vertex
&& subnet->vertex->outgoing_edges) {
/* from the vertex linked in subnet */
diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c
index d284912d1d..ead02d8bd7 100644
--- a/pimd/pim_iface.c
+++ b/pimd/pim_iface.c
@@ -982,6 +982,12 @@ int pim_if_add_vif(struct interface *ifp, bool ispimreg, bool is_vxlan_term)
zlog_warn("%s: ifindex=%d < 1 on interface %s", __func__,
ifp->ifindex, ifp->name);
return -2;
+ } else if ((ifp->ifindex == 0) &&
+ ((strncmp(ifp->name, "pimreg", 6)) &&
+ (strncmp(ifp->name, "pim6reg", 7)))) {
+ zlog_warn("%s: ifindex=%d == 0 on interface %s", __func__,
+ ifp->ifindex, ifp->name);
+ return -2;
}
ifaddr = pim_ifp->primary_address;
diff --git a/ripd/rip_nb.c b/ripd/rip_nb.c
index 9947c01af5..c332b2a5b7 100644
--- a/ripd/rip_nb.c
+++ b/ripd/rip_nb.c
@@ -338,6 +338,66 @@ const struct frr_yang_module_info frr_ripd_info = {
},
},
{
+ .xpath = "/frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop",
+ .cbs = {
+ .get_next = ripd_instance_state_routes_route_nexthops_nexthop_get_next,
+ }
+ },
+ {
+ .xpath = "/frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/nh-type",
+ .cbs = {
+ .get_elem = ripd_instance_state_routes_route_nexthops_nexthop_nh_type_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/protocol",
+ .cbs = {
+ .get_elem = ripd_instance_state_routes_route_nexthops_nexthop_protocol_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/rip-type",
+ .cbs = {
+ .get_elem = ripd_instance_state_routes_route_nexthops_nexthop_rip_type_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/gateway",
+ .cbs = {
+ .get_elem = ripd_instance_state_routes_route_nexthops_nexthop_gateway_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/interface",
+ .cbs = {
+ .get_elem = ripd_instance_state_routes_route_nexthops_nexthop_interface_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/from",
+ .cbs = {
+ .get_elem = ripd_instance_state_routes_route_nexthops_nexthop_from_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/tag",
+ .cbs = {
+ .get_elem = ripd_instance_state_routes_route_nexthops_nexthop_tag_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/external-metric",
+ .cbs = {
+ .get_elem = ripd_instance_state_routes_route_nexthops_nexthop_external_metric_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/expire-time",
+ .cbs = {
+ .get_elem = ripd_instance_state_routes_route_nexthops_nexthop_expire_time_get_elem,
+ }
+ },
+ {
.xpath = "/frr-ripd:ripd/instance/state/routes/route/metric",
.cbs = {
.get_elem = ripd_instance_state_routes_route_metric_get_elem,
diff --git a/ripd/rip_nb.h b/ripd/rip_nb.h
index 99114c9928..a30e579e1c 100644
--- a/ripd/rip_nb.h
+++ b/ripd/rip_nb.h
@@ -89,6 +89,37 @@ struct yang_data *ripd_instance_state_routes_route_interface_get_elem(
struct nb_cb_get_elem_args *args);
struct yang_data *ripd_instance_state_routes_route_metric_get_elem(
struct nb_cb_get_elem_args *args);
+const void *ripd_instance_state_routes_route_nexthops_nexthop_get_next(
+ struct nb_cb_get_next_args *args);
+struct yang_data *
+ripd_instance_state_routes_route_nexthops_nexthop_nh_type_get_elem(
+ struct nb_cb_get_elem_args *args);
+struct yang_data *
+ripd_instance_state_routes_route_nexthops_nexthop_protocol_get_elem(
+ struct nb_cb_get_elem_args *args);
+struct yang_data *
+ripd_instance_state_routes_route_nexthops_nexthop_rip_type_get_elem(
+ struct nb_cb_get_elem_args *args);
+struct yang_data *
+ripd_instance_state_routes_route_nexthops_nexthop_gateway_get_elem(
+ struct nb_cb_get_elem_args *args);
+struct yang_data *
+ripd_instance_state_routes_route_nexthops_nexthop_interface_get_elem(
+ struct nb_cb_get_elem_args *args);
+struct yang_data *
+ripd_instance_state_routes_route_nexthops_nexthop_from_get_elem(
+ struct nb_cb_get_elem_args *args);
+struct yang_data *
+ripd_instance_state_routes_route_nexthops_nexthop_tag_get_elem(
+ struct nb_cb_get_elem_args *args);
+struct yang_data *
+ripd_instance_state_routes_route_nexthops_nexthop_external_metric_get_elem(
+ struct nb_cb_get_elem_args *args);
+struct yang_data *
+ripd_instance_state_routes_route_nexthops_nexthop_expire_time_get_elem(
+ struct nb_cb_get_elem_args *args);
+struct yang_data *ripd_instance_state_routes_route_metric_get_elem(
+ struct nb_cb_get_elem_args *args);
int clear_rip_route_rpc(struct nb_cb_rpc_args *args);
int lib_interface_rip_split_horizon_modify(struct nb_cb_modify_args *args);
int lib_interface_rip_v2_broadcast_modify(struct nb_cb_modify_args *args);
diff --git a/ripd/rip_nb_state.c b/ripd/rip_nb_state.c
index 0e2931b464..fa0d382a0e 100644
--- a/ripd/rip_nb_state.c
+++ b/ripd/rip_nb_state.c
@@ -207,10 +207,171 @@ struct yang_data *ripd_instance_state_routes_route_prefix_get_elem(
const struct route_node *rn = args->list_entry;
const struct rip_info *rinfo = listnode_head(rn->info);
+ assert(rinfo);
return yang_data_new_ipv4p(args->xpath, &rinfo->rp->p);
}
/*
+ * XPath: /frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop
+ */
+const void *ripd_instance_state_routes_route_nexthops_nexthop_get_next(
+ struct nb_cb_get_next_args *args)
+{
+ const struct route_node *rn = args->parent_list_entry;
+ const struct listnode *node = args->list_entry;
+
+ assert(rn);
+ if (node)
+ return listnextnode(node);
+ assert(rn->info);
+ return listhead((struct list *)rn->info);
+}
+
+static inline const struct rip_info *get_rip_info(const void *info)
+{
+ return (const struct rip_info *)listgetdata(
+ (const struct listnode *)info);
+}
+
+/*
+ * XPath: /frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/nh-type
+ */
+struct yang_data *
+ripd_instance_state_routes_route_nexthops_nexthop_nh_type_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ const struct rip_info *rinfo = get_rip_info(args->list_entry);
+
+ assert(rinfo);
+ return yang_data_new_enum(args->xpath, rinfo->nh.type);
+}
+
+/*
+ * XPath: /frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/protocol
+ */
+struct yang_data *
+ripd_instance_state_routes_route_nexthops_nexthop_protocol_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ const struct rip_info *rinfo = get_rip_info(args->list_entry);
+
+ assert(rinfo);
+ return yang_data_new_enum(args->xpath, rinfo->type);
+}
+
+/*
+ * XPath: /frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/rip-type
+ */
+struct yang_data *
+ripd_instance_state_routes_route_nexthops_nexthop_rip_type_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ const struct rip_info *rinfo = get_rip_info(args->list_entry);
+
+ assert(rinfo);
+ return yang_data_new_enum(args->xpath, rinfo->sub_type);
+}
+
+/*
+ * XPath: /frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/gateway
+ */
+struct yang_data *
+ripd_instance_state_routes_route_nexthops_nexthop_gateway_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ const struct rip_info *rinfo = get_rip_info(args->list_entry);
+
+ if (rinfo->nh.type != NEXTHOP_TYPE_IPV4 &&
+ rinfo->nh.type != NEXTHOP_TYPE_IPV4_IFINDEX)
+ return NULL;
+
+ return yang_data_new_ipv4(args->xpath, &rinfo->nh.gate.ipv4);
+}
+
+/*
+ * XPath: /frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/interface
+ */
+struct yang_data *
+ripd_instance_state_routes_route_nexthops_nexthop_interface_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ const struct rip_info *rinfo = get_rip_info(args->list_entry);
+ const struct rip *rip = rip_info_get_instance(rinfo);
+
+ if (rinfo->nh.type != NEXTHOP_TYPE_IFINDEX &&
+ rinfo->nh.type != NEXTHOP_TYPE_IPV4_IFINDEX)
+ return NULL;
+
+ return yang_data_new_string(
+ args->xpath,
+ ifindex2ifname(rinfo->nh.ifindex, rip->vrf->vrf_id));
+}
+
+/*
+ * XPath: /frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/from
+ */
+struct yang_data *
+ripd_instance_state_routes_route_nexthops_nexthop_from_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ const struct rip_info *rinfo = get_rip_info(args->list_entry);
+
+ if (rinfo->type != ZEBRA_ROUTE_RIP || rinfo->sub_type != RIP_ROUTE_RTE)
+ return NULL;
+
+ return yang_data_new_ipv4(args->xpath, &rinfo->from);
+}
+
+/*
+ * XPath: /frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/tag
+ */
+struct yang_data *
+ripd_instance_state_routes_route_nexthops_nexthop_tag_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ const struct rip_info *rinfo = get_rip_info(args->list_entry);
+
+ return yang_data_new_uint32(args->xpath, rinfo->tag);
+}
+
+/*
+ * XPath:
+ * /frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/external-metric
+ */
+struct yang_data *
+ripd_instance_state_routes_route_nexthops_nexthop_external_metric_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ const struct rip_info *rinfo = get_rip_info(args->list_entry);
+
+ if ((rinfo->type == ZEBRA_ROUTE_RIP &&
+ rinfo->sub_type == RIP_ROUTE_RTE) ||
+ rinfo->metric == RIP_METRIC_INFINITY || rinfo->external_metric == 0)
+ return NULL;
+ return yang_data_new_uint32(args->xpath, rinfo->external_metric);
+}
+
+/*
+ * XPath:
+ * /frr-ripd:ripd/instance/state/routes/route/nexthops/nexthop/expire-time
+ */
+struct yang_data *
+ripd_instance_state_routes_route_nexthops_nexthop_expire_time_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ const struct rip_info *rinfo = get_rip_info(args->list_entry);
+ struct event *event;
+
+ if ((event = rinfo->t_timeout) == NULL)
+ event = rinfo->t_garbage_collect;
+ if (!event)
+ return NULL;
+
+ return yang_data_new_uint32(args->xpath,
+ event_timer_remain_second(event));
+}
+
+/*
* XPath: /frr-ripd:ripd/instance/state/routes/route/next-hop
*/
struct yang_data *ripd_instance_state_routes_route_next_hop_get_elem(
diff --git a/ripd/ripd.c b/ripd/ripd.c
index ae4d93b4f5..7dbe2bbccf 100644
--- a/ripd/ripd.c
+++ b/ripd/ripd.c
@@ -1500,7 +1500,7 @@ static int rip_send_packet(uint8_t *buf, int size, struct sockaddr_in *to,
ret = sendmsg(rip->sock, &msg, 0);
if (IS_RIP_DEBUG_EVENT)
- zlog_debug("SEND to %pI4%d", &sin.sin_addr,
+ zlog_debug("SEND to %pI4 port %d", &sin.sin_addr,
ntohs(sin.sin_port));
if (ret < 0)
@@ -2836,16 +2836,11 @@ uint8_t rip_distance_apply(struct rip *rip, struct rip_info *rinfo)
if (access_list_apply(alist, &rinfo->rp->p)
== FILTER_DENY)
return 0;
-
- return rdistance->distance;
- } else
- return rdistance->distance;
+ }
+ return rdistance->distance;
}
- if (rip->distance)
- return rip->distance;
-
- return 0;
+ return rip->distance;
}
static void rip_distance_show(struct vty *vty, struct rip *rip)
diff --git a/sharpd/sharp_vty.c b/sharpd/sharp_vty.c
index 77b562d6a6..0d7ba34530 100644
--- a/sharpd/sharp_vty.c
+++ b/sharpd/sharp_vty.c
@@ -1059,7 +1059,7 @@ DEFUN (show_sharp_ted,
return CMD_WARNING_CONFIG_FAILED;
}
/* Get the Subnet from the Link State Database */
- subnet = ls_find_subnet(sg.ted, pref);
+ subnet = ls_find_subnet(sg.ted, &pref);
if (!subnet) {
vty_out(vty, "No subnet found for ID %pFX\n",
&pref);
@@ -1245,6 +1245,7 @@ DEFPY (show_sharp_cspf,
}
if (path->status != SUCCESS) {
vty_out(vty, "Path computation failed: %d\n", path->status);
+ cpath_del(path);
return CMD_SUCCESS;
}
@@ -1260,7 +1261,7 @@ DEFPY (show_sharp_cspf,
&edge->attributes->standard.remote6);
}
vty_out(vty, "\n");
-
+ cpath_del(path);
return CMD_SUCCESS;
}
diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c
index 17ad705969..91fb7f03b1 100644
--- a/sharpd/sharp_zebra.c
+++ b/sharpd/sharp_zebra.c
@@ -790,7 +790,7 @@ static int sharp_opaque_handler(ZAPI_CALLBACK_ARGS)
zclient->session_id, info.type);
if (info.type == LINK_STATE_UPDATE) {
- lse = ls_stream2ted(sg.ted, s, false);
+ lse = ls_stream2ted(sg.ted, s, true);
if (lse) {
zlog_debug(" |- Got %s %s from Link State Database",
status2txt[lse->status],
diff --git a/staticd/static_main.c b/staticd/static_main.c
index 09f22318ff..9809d9751a 100644
--- a/staticd/static_main.c
+++ b/staticd/static_main.c
@@ -161,6 +161,10 @@ static const struct frr_yang_module_info *const staticd_yang_modules[] = {
#define STATIC_VTY_PORT 2616
+/*
+ * NOTE: .flags == FRR_NO_SPLIT_CONFIG to avoid reading split config, mgmtd will
+ * do this for us now
+ */
FRR_DAEMON_INFO(staticd, STATIC, .vty_port = STATIC_VTY_PORT,
.proghelp = "Implementation of STATIC.",
@@ -170,7 +174,8 @@ FRR_DAEMON_INFO(staticd, STATIC, .vty_port = STATIC_VTY_PORT,
.privs = &static_privs, .yang_modules = staticd_yang_modules,
.n_yang_modules = array_size(staticd_yang_modules),
-);
+
+ .flags = FRR_NO_SPLIT_CONFIG);
int main(int argc, char **argv, char **envp)
{
@@ -210,9 +215,12 @@ int main(int argc, char **argv, char **envp)
routing_control_plane_protocols_register_vrf_dependency();
- snprintf(backup_config_file, sizeof(backup_config_file),
- "%s/zebra.conf", frr_sysconfdir);
- staticd_di.backup_config_file = backup_config_file;
+ /*
+ * We set FRR_NO_SPLIT_CONFIG flag to avoid reading our config, but we
+ * still need to write one if vtysh tells us to. Setting the host
+ * config filename does this.
+ */
+ host_config_set(config_default);
frr_config_fork();
frr_run(master);
diff --git a/tests/bgpd/test_mp_attr.c b/tests/bgpd/test_mp_attr.c
index 54596dbdfb..ae7903e0cc 100644
--- a/tests/bgpd/test_mp_attr.c
+++ b/tests/bgpd/test_mp_attr.c
@@ -1042,9 +1042,9 @@ static void parse_test(struct peer *peer, struct test_segment *t, int type)
if (!parse_ret) {
if (type == BGP_ATTR_MP_REACH_NLRI)
- nlri_ret = bgp_nlri_parse(peer, &attr, &nlri, 0);
+ nlri_ret = bgp_nlri_parse(peer, &attr, &nlri, false);
else if (type == BGP_ATTR_MP_UNREACH_NLRI)
- nlri_ret = bgp_nlri_parse(peer, &attr, &nlri, 1);
+ nlri_ret = bgp_nlri_parse(peer, &attr, &nlri, true);
}
handle_result(peer, t, parse_ret, nlri_ret);
}
diff --git a/tests/lib/subdir.am b/tests/lib/subdir.am
index 1bc092a49e..e950d0120d 100644
--- a/tests/lib/subdir.am
+++ b/tests/lib/subdir.am
@@ -15,7 +15,7 @@ tests_lib_test_frrscript_CFLAGS = $(TESTS_CFLAGS)
tests_lib_test_frrscript_CPPFLAGS = $(TESTS_CPPFLAGS)
tests_lib_test_frrscript_LDADD = $(ALL_TESTS_LDADD)
tests_lib_test_frrscript_SOURCES = tests/lib/test_frrscript.c
-EXTRA_DIST += tests/lib/test_frrscript.py
+EXTRA_DIST += tests/lib/test_frrscript.py tests/lib/script1.lua
##############################################################################
diff --git a/tests/topotests/all_protocol_startup/r1/ospf6d.conf-pre-v4 b/tests/topotests/all_protocol_startup/r1/ospf6d.conf-pre-v4
index 6d870f355f..9ce2f2e825 100644
--- a/tests/topotests/all_protocol_startup/r1/ospf6d.conf-pre-v4
+++ b/tests/topotests/all_protocol_startup/r1/ospf6d.conf-pre-v4
@@ -1,9 +1,9 @@
log file ospf6d.log
!
-debug ospf6 lsa unknown
-debug ospf6 zebra
-debug ospf6 interface
-debug ospf6 neighbor
+!debug ospf6 lsa unknown
+!debug ospf6 zebra
+!debug ospf6 interface
+!debug ospf6 neighbor
!
interface r1-eth4
!
diff --git a/tests/topotests/all_protocol_startup/test_all_protocol_startup.py b/tests/topotests/all_protocol_startup/test_all_protocol_startup.py
index f7c3a4c19d..92bb99c8f2 100644
--- a/tests/topotests/all_protocol_startup/test_all_protocol_startup.py
+++ b/tests/topotests/all_protocol_startup/test_all_protocol_startup.py
@@ -288,6 +288,17 @@ def test_converge_protocols():
thisDir = os.path.dirname(os.path.realpath(__file__))
+ # We need loopback to have a link local so it always is the
+ # "selected" router for fe80::/64 when we static compare below.
+ print("Adding link-local to loopback for stable results")
+ cmd = (
+ "mac=`cat /sys/class/net/lo/address`; echo lo: $mac;"
+ " [ -z \"$mac\" ] && continue; IFS=':'; set $mac; unset IFS;"
+ " ip address add dev lo scope link"
+ " fe80::$(printf %02x $((0x$1 ^ 2)))$2:${3}ff:fe$4:$5$6/64"
+ )
+ net["r1"].cmd_raises(cmd)
+
print("\n\n** Waiting for protocols convergence")
print("******************************************\n")
diff --git a/tests/topotests/bfd_topo3/r5/bfdd.conf b/tests/topotests/bfd_topo3/r5/bfdd.conf
index 6d4483acc4..ec62d8d275 100644
--- a/tests/topotests/bfd_topo3/r5/bfdd.conf
+++ b/tests/topotests/bfd_topo3/r5/bfdd.conf
@@ -1,6 +1,6 @@
-debug bfd network
-debug bfd peer
-debug bfd zebra
+!debug bfd network
+!debug bfd peer
+!debug bfd zebra
!
bfd
profile slow-tx
diff --git a/tests/topotests/bfd_topo3/r6/bfdd.conf b/tests/topotests/bfd_topo3/r6/bfdd.conf
index 6d4483acc4..ec62d8d275 100644
--- a/tests/topotests/bfd_topo3/r6/bfdd.conf
+++ b/tests/topotests/bfd_topo3/r6/bfdd.conf
@@ -1,6 +1,6 @@
-debug bfd network
-debug bfd peer
-debug bfd zebra
+!debug bfd network
+!debug bfd peer
+!debug bfd zebra
!
bfd
profile slow-tx
diff --git a/tests/topotests/bgp_accept_own/ce1/bgpd.conf b/tests/topotests/bgp_accept_own/ce1/bgpd.conf
index fa53a42919..44f95b9bb3 100644
--- a/tests/topotests/bgp_accept_own/ce1/bgpd.conf
+++ b/tests/topotests/bgp_accept_own/ce1/bgpd.conf
@@ -1,5 +1,5 @@
!
-debug bgp updates
+!debug bgp updates
!
router bgp 65010
no bgp ebgp-requires-policy
diff --git a/tests/topotests/bgp_accept_own/ce2/bgpd.conf b/tests/topotests/bgp_accept_own/ce2/bgpd.conf
index cdf8898c90..d60fdcf7cb 100644
--- a/tests/topotests/bgp_accept_own/ce2/bgpd.conf
+++ b/tests/topotests/bgp_accept_own/ce2/bgpd.conf
@@ -1,5 +1,5 @@
!
-debug bgp updates
+!debug bgp updates
!
router bgp 65020
no bgp ebgp-requires-policy
diff --git a/tests/topotests/bgp_accept_own/pe1/bgpd.conf b/tests/topotests/bgp_accept_own/pe1/bgpd.conf
index 109e0eadbb..15466b4259 100644
--- a/tests/topotests/bgp_accept_own/pe1/bgpd.conf
+++ b/tests/topotests/bgp_accept_own/pe1/bgpd.conf
@@ -1,8 +1,8 @@
!
-debug bgp updates
-debug bgp vpn leak-from-vrf
-debug bgp vpn leak-to-vrf
-debug bgp nht
+!debug bgp updates
+!debug bgp vpn leak-from-vrf
+!debug bgp vpn leak-to-vrf
+!debug bgp nht
!
router bgp 65001
bgp router-id 10.10.10.10
diff --git a/tests/topotests/bgp_accept_own/rr1/bgpd.conf b/tests/topotests/bgp_accept_own/rr1/bgpd.conf
index 4f0a6ab0f1..ad0ee3e471 100644
--- a/tests/topotests/bgp_accept_own/rr1/bgpd.conf
+++ b/tests/topotests/bgp_accept_own/rr1/bgpd.conf
@@ -1,5 +1,5 @@
!
-debug bgp updates
+!debug bgp updates
!
router bgp 65001
bgp router-id 10.10.10.101
diff --git a/tests/topotests/bgp_comm_list_match/r2/bgpd.conf b/tests/topotests/bgp_comm_list_match/r2/bgpd.conf
index 35ad2d32e6..98a9780688 100644
--- a/tests/topotests/bgp_comm_list_match/r2/bgpd.conf
+++ b/tests/topotests/bgp_comm_list_match/r2/bgpd.conf
@@ -1,5 +1,5 @@
!
-debug bgp updates
+!debug bgp updates
!
router bgp 65002
no bgp ebgp-requires-policy
diff --git a/tests/topotests/bgp_confed1/r1/bgpd.conf b/tests/topotests/bgp_confed1/r1/bgpd.conf
index 8413ef7fc3..107d2ad8d2 100644
--- a/tests/topotests/bgp_confed1/r1/bgpd.conf
+++ b/tests/topotests/bgp_confed1/r1/bgpd.conf
@@ -1,7 +1,7 @@
-debug bgp neighbor-events
-debug bgp nht
-debug bgp updates in
-debug bgp updates out
+!debug bgp neighbor-events
+!debug bgp nht
+!debug bgp updates in
+!debug bgp updates out
!
router bgp 100
no bgp ebgp-requires-policy
diff --git a/tests/topotests/bgp_confed1/r2/bgpd.conf b/tests/topotests/bgp_confed1/r2/bgpd.conf
index 9f6a9852de..fe13dfe729 100644
--- a/tests/topotests/bgp_confed1/r2/bgpd.conf
+++ b/tests/topotests/bgp_confed1/r2/bgpd.conf
@@ -1,7 +1,7 @@
-debug bgp neighbor-events
-debug bgp nht
-debug bgp updates in
-debug bgp updates out
+!debug bgp neighbor-events
+!debug bgp nht
+!debug bgp updates in
+!debug bgp updates out
!
router bgp 200
no bgp ebgp-requires-policy
diff --git a/tests/topotests/bgp_confed1/r3/bgpd.conf b/tests/topotests/bgp_confed1/r3/bgpd.conf
index 3a018a42b3..74d5fd6e29 100644
--- a/tests/topotests/bgp_confed1/r3/bgpd.conf
+++ b/tests/topotests/bgp_confed1/r3/bgpd.conf
@@ -1,7 +1,7 @@
-debug bgp neighbor-events
-debug bgp nht
-debug bgp updates in
-debug bgp updates out
+!debug bgp neighbor-events
+!debug bgp nht
+!debug bgp updates in
+!debug bgp updates out
!
router bgp 300
no bgp ebgp-requires-policy
diff --git a/tests/topotests/bgp_confed1/r4/bgpd.conf b/tests/topotests/bgp_confed1/r4/bgpd.conf
index 134f221543..89a85e5a34 100644
--- a/tests/topotests/bgp_confed1/r4/bgpd.conf
+++ b/tests/topotests/bgp_confed1/r4/bgpd.conf
@@ -1,7 +1,7 @@
-debug bgp neighbor-events
-debug bgp nht
-debug bgp updates in
-debug bgp updates out
+!debug bgp neighbor-events
+!debug bgp nht
+!debug bgp updates in
+!debug bgp updates out
!
router bgp 400
no bgp ebgp-requires-policy
diff --git a/tests/topotests/bgp_dont_capability_negotiate/r1/bgpd.conf b/tests/topotests/bgp_dont_capability_negotiate/r1/bgpd.conf
index e2ff1df965..2f76d59d4a 100644
--- a/tests/topotests/bgp_dont_capability_negotiate/r1/bgpd.conf
+++ b/tests/topotests/bgp_dont_capability_negotiate/r1/bgpd.conf
@@ -1,5 +1,5 @@
!
-debug bgp neighbor
+!debug bgp neighbor
!
router bgp 65001
no bgp ebgp-requires-policy
diff --git a/tests/topotests/bgp_evpn_vxlan_svd_topo1/test_bgp_evpn_vxlan_svd.py b/tests/topotests/bgp_evpn_vxlan_svd_topo1/test_bgp_evpn_vxlan_svd.py
index f8af210ed7..8b9631175a 100755
--- a/tests/topotests/bgp_evpn_vxlan_svd_topo1/test_bgp_evpn_vxlan_svd.py
+++ b/tests/topotests/bgp_evpn_vxlan_svd_topo1/test_bgp_evpn_vxlan_svd.py
@@ -463,8 +463,8 @@ def test_ip_pe1_learn():
host1 = tgen.gears["host1"]
pe1 = tgen.gears["PE1"]
pe2 = tgen.gears["PE2"]
- pe2.vtysh_cmd("debug zebra vxlan")
- pe2.vtysh_cmd("debug zebra kernel")
+ #pe2.vtysh_cmd("debug zebra vxlan")
+ #pe2.vtysh_cmd("debug zebra kernel")
# lets populate that arp cache
host1.run("ping -c1 10.10.1.1")
ip_learn_test(tgen, host1, pe1, pe2, "10.10.1.55")
@@ -482,8 +482,8 @@ def test_ip_pe2_learn():
host2 = tgen.gears["host2"]
pe1 = tgen.gears["PE1"]
pe2 = tgen.gears["PE2"]
- pe1.vtysh_cmd("debug zebra vxlan")
- pe1.vtysh_cmd("debug zebra kernel")
+ #pe1.vtysh_cmd("debug zebra vxlan")
+ #pe1.vtysh_cmd("debug zebra kernel")
# lets populate that arp cache
host2.run("ping -c1 10.10.1.3")
ip_learn_test(tgen, host2, pe2, pe1, "10.10.1.56")
diff --git a/tests/topotests/bgp_evpn_vxlan_topo1/test_bgp_evpn_vxlan.py b/tests/topotests/bgp_evpn_vxlan_topo1/test_bgp_evpn_vxlan.py
index 48b79ab5ee..6561833d6e 100755
--- a/tests/topotests/bgp_evpn_vxlan_topo1/test_bgp_evpn_vxlan.py
+++ b/tests/topotests/bgp_evpn_vxlan_topo1/test_bgp_evpn_vxlan.py
@@ -385,8 +385,8 @@ def test_ip_pe1_learn():
host1 = tgen.gears["host1"]
pe1 = tgen.gears["PE1"]
pe2 = tgen.gears["PE2"]
- pe2.vtysh_cmd("debug zebra vxlan")
- pe2.vtysh_cmd("debug zebra kernel")
+ #pe2.vtysh_cmd("debug zebra vxlan")
+ #pe2.vtysh_cmd("debug zebra kernel")
# lets populate that arp cache
host1.run("ping -c1 10.10.1.1")
ip_learn_test(tgen, host1, pe1, pe2, "10.10.1.55")
@@ -404,8 +404,8 @@ def test_ip_pe2_learn():
host2 = tgen.gears["host2"]
pe1 = tgen.gears["PE1"]
pe2 = tgen.gears["PE2"]
- pe1.vtysh_cmd("debug zebra vxlan")
- pe1.vtysh_cmd("debug zebra kernel")
+ #pe1.vtysh_cmd("debug zebra vxlan")
+ #pe1.vtysh_cmd("debug zebra kernel")
# lets populate that arp cache
host2.run("ping -c1 10.10.1.3")
ip_learn_test(tgen, host2, pe2, pe1, "10.10.1.56")
diff --git a/tests/topotests/bgp_labeled_unicast_addpath/test_bgp_labeled_unicast_addpath.py b/tests/topotests/bgp_labeled_unicast_addpath/test_bgp_labeled_unicast_addpath.py
index 3af779c427..f4bb487e40 100644
--- a/tests/topotests/bgp_labeled_unicast_addpath/test_bgp_labeled_unicast_addpath.py
+++ b/tests/topotests/bgp_labeled_unicast_addpath/test_bgp_labeled_unicast_addpath.py
@@ -82,53 +82,23 @@ def test_bgp_addpath_labeled_unicast():
r3 = tgen.gears["r3"]
r4 = tgen.gears["r4"]
- def _bgp_check_advertised_routes(prefix_num):
- output = json.loads(
- r3.vtysh_cmd(
- "show bgp ipv4 labeled-unicast neighbors 192.168.34.4 advertised-routes json"
- )
- )
+ def _bgp_check_received_routes(pfxcount):
+ output = json.loads(r4.vtysh_cmd("show bgp ipv4 labeled-unicast summary json"))
expected = {
- "advertisedRoutes": {
- "10.0.0.1/32": {
- "appliedStatusSymbols": {
- "*": True,
- ">": True,
- "=": True,
- }
+ "peers": {
+ "192.168.34.3": {
+ "pfxRcd": pfxcount,
+ "state": "Established",
}
- },
- "totalPrefixCounter": prefix_num,
+ }
}
return topotest.json_cmp(output, expected)
- test_func = functools.partial(_bgp_check_advertised_routes, 2)
+ test_func = functools.partial(_bgp_check_received_routes, 2)
_, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
assert (
result is None
- ), "Failed to advertise labeled-unicast with addpath (multipath)"
-
- def _bgp_check_received_routes():
- output = json.loads(r4.vtysh_cmd("show bgp ipv4 labeled-unicast json"))
- expected = {
- "routes": {
- "10.0.0.1/32": [
- {
- "valid": True,
- "path": "65003 65001",
- },
- {
- "valid": True,
- "path": "65003 65002",
- },
- ]
- }
- }
- return topotest.json_cmp(output, expected)
-
- test_func = functools.partial(_bgp_check_received_routes)
- _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
- assert result is None, "Failed to receive labeled-unicast with addpath (multipath)"
+ ), "Failed to receive labeled-unicast with addpath (multipath=2)"
step("Enable BGP session for R5")
r3.vtysh_cmd(
@@ -139,11 +109,11 @@ def test_bgp_addpath_labeled_unicast():
"""
)
- test_func = functools.partial(_bgp_check_advertised_routes, 3)
+ test_func = functools.partial(_bgp_check_received_routes, 3)
_, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
assert (
result is None
- ), "Failed to advertise labeled-unicast with addpath (multipath)"
+ ), "Failed to receive labeled-unicast with addpath (multipath=3)"
step("Disable BGP session for R5")
r3.vtysh_cmd(
@@ -154,11 +124,11 @@ def test_bgp_addpath_labeled_unicast():
"""
)
- test_func = functools.partial(_bgp_check_advertised_routes, 2)
+ test_func = functools.partial(_bgp_check_received_routes, 2)
_, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
assert (
result is None
- ), "Failed to advertise labeled-unicast with addpath (multipath)"
+ ), "Failed to receive labeled-unicast with addpath (multipath=2)"
if __name__ == "__main__":
diff --git a/tests/topotests/bgp_prefix_list_any/r2/bgpd.conf b/tests/topotests/bgp_prefix_list_any/r2/bgpd.conf
index 77f7c5581b..733205928f 100644
--- a/tests/topotests/bgp_prefix_list_any/r2/bgpd.conf
+++ b/tests/topotests/bgp_prefix_list_any/r2/bgpd.conf
@@ -1,5 +1,5 @@
!
-debug bgp updates
+!debug bgp updates
!
router bgp 65002
no bgp ebgp-requires-policy
diff --git a/tests/topotests/bgp_route_map_delay_timer/r1/bgpd.conf b/tests/topotests/bgp_route_map_delay_timer/r1/bgpd.conf
index 04dc73a06d..e5325c91bc 100644
--- a/tests/topotests/bgp_route_map_delay_timer/r1/bgpd.conf
+++ b/tests/topotests/bgp_route_map_delay_timer/r1/bgpd.conf
@@ -1,6 +1,6 @@
!
-debug bgp updates
-debug bgp neighbor
+!debug bgp updates
+!debug bgp neighbor
!
bgp route-map delay-timer 5
!
diff --git a/tests/topotests/bgp_route_map_vpn_import/r1/bgpd.conf b/tests/topotests/bgp_route_map_vpn_import/r1/bgpd.conf
index c9ad0b1a5b..4aa11ec9d0 100644
--- a/tests/topotests/bgp_route_map_vpn_import/r1/bgpd.conf
+++ b/tests/topotests/bgp_route_map_vpn_import/r1/bgpd.conf
@@ -1,9 +1,9 @@
!
-debug bgp updates
-debug bgp vpn leak-from-vrf
-debug bgp vpn leak-to-vrf
-debug bgp nht
-debug route-map
+!debug bgp updates
+!debug bgp vpn leak-from-vrf
+!debug bgp vpn leak-to-vrf
+!debug bgp nht
+!debug route-map
!
router bgp 65001
bgp router-id 10.10.10.10
diff --git a/tests/topotests/bgp_route_origin_parser/pe1/bgpd.conf b/tests/topotests/bgp_route_origin_parser/pe1/bgpd.conf
new file mode 100644
index 0000000000..1929dfa69b
--- /dev/null
+++ b/tests/topotests/bgp_route_origin_parser/pe1/bgpd.conf
@@ -0,0 +1,2 @@
+router bgp 65001
+ neighbor 192.168.2.1 remote-as external
diff --git a/tests/topotests/bgp_route_origin_parser/test_bgp_route_origin_parser.py b/tests/topotests/bgp_route_origin_parser/test_bgp_route_origin_parser.py
new file mode 100644
index 0000000000..673efc2c73
--- /dev/null
+++ b/tests/topotests/bgp_route_origin_parser/test_bgp_route_origin_parser.py
@@ -0,0 +1,129 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# April 03 2023, Trey Aspelund <taspelund@nvidia.com>
+#
+# Copyright (C) 2023 NVIDIA Corporation
+#
+# Test if the CLI parser for RT/SoO ecoms correctly
+# constrain user input to valid 4-byte ASN values.
+#
+
+import os
+import sys
+import json
+import pytest
+import functools
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.common_config import step
+
+pytestmark = [pytest.mark.bgpd]
+
+
+def build_topo(tgen):
+ tgen.add_router("pe1")
+
+
+def setup_module(mod):
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+ pe1 = tgen.gears["pe1"]
+ pe1.load_config(TopoRouter.RD_BGP, os.path.join(CWD, "pe1/bgpd.conf"))
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_route_origin_parser():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ pe1 = tgen.gears["pe1"]
+
+ def _invalid_soo_accepted():
+ pe1.vtysh_cmd(
+ """
+ configure terminal
+ router bgp 65001
+ address-family ipv4 unicast
+ neighbor 192.168.2.1 soo 4294967296:65
+ """
+ )
+ run_cfg = pe1.vtysh_cmd("show run")
+ return "soo" in run_cfg
+
+ def _max_soo_accepted():
+ pe1.vtysh_cmd(
+ """
+ configure terminal
+ router bgp 65001
+ address-family ipv4 unicast
+ neighbor 192.168.2.1 soo 4294967295:65
+ """
+ )
+ run_cfg = pe1.vtysh_cmd("show run")
+ return "soo 4294967295:65" in run_cfg
+
+ def _invalid_rt_accepted():
+ pe1.vtysh_cmd(
+ """
+ configure terminal
+ router bgp 65001
+ address-family ipv4 unicast
+ rt vpn both 4294967296:65
+ """
+ )
+ run_cfg = pe1.vtysh_cmd("show run")
+ return "rt vpn" in run_cfg
+
+ def _max_rt_accepted():
+ pe1.vtysh_cmd(
+ """
+ configure terminal
+ router bgp 65001
+ address-family ipv4 unicast
+ rt vpn both 4294967295:65
+ """
+ )
+ run_cfg = pe1.vtysh_cmd("show run")
+ return "rt vpn both 4294967295:65" in run_cfg
+
+ step(
+ "Configure invalid 4-byte value SoO (4294967296:65), this should not be accepted"
+ )
+ test_func = functools.partial(_invalid_soo_accepted)
+ _, result = topotest.run_and_expect(test_func, False, count=30, wait=0.5)
+ assert result is False, "invalid 4-byte value of SoO accepted"
+
+ step("Configure max 4-byte value SoO (4294967295:65), this should be accepted")
+ test_func = functools.partial(_max_soo_accepted)
+ _, result = topotest.run_and_expect(test_func, True, count=30, wait=0.5)
+ assert result is True, "max 4-byte value of SoO not accepted"
+
+ step(
+ "Configure invalid 4-byte value RT (4294967296:65), this should not be accepted"
+ )
+ test_func = functools.partial(_invalid_rt_accepted)
+ _, result = topotest.run_and_expect(test_func, False, count=30, wait=0.5)
+ assert result is False, "invalid 4-byte value of RT accepted"
+
+ step("Configure max 4-byte value RT (4294967295:65), this should be accepted")
+ test_func = functools.partial(_max_rt_accepted)
+ _, result = topotest.run_and_expect(test_func, True, count=30, wait=0.5)
+ assert result is True, "max 4-byte value of RT not accepted"
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_snmp_bgp4v2mib/r2/bgpd.conf b/tests/topotests/bgp_snmp_bgp4v2mib/r2/bgpd.conf
index 3512e66cec..cf0013e1b7 100644
--- a/tests/topotests/bgp_snmp_bgp4v2mib/r2/bgpd.conf
+++ b/tests/topotests/bgp_snmp_bgp4v2mib/r2/bgpd.conf
@@ -1,5 +1,5 @@
!
-debug bgp updates
+!debug bgp updates
!
router bgp 65002
no bgp ebgp-requires-policy
diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r1/zebra.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r1/zebra.conf
index a9319a6aed..cbc5ce1f09 100644
--- a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r1/zebra.conf
+++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r1/zebra.conf
@@ -7,9 +7,9 @@ log stdout notifications
log monitor notifications
log commands
!
-debug zebra packet
-debug zebra dplane
-debug zebra kernel
+!debug zebra packet
+!debug zebra dplane
+!debug zebra kernel
!
interface eth0
ipv6 address 2001::1/64
diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r2/zebra.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r2/zebra.conf
index 9e5fa0ac07..449ca74d5e 100644
--- a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r2/zebra.conf
+++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r2/zebra.conf
@@ -7,9 +7,9 @@ log stdout notifications
log monitor notifications
log commands
!
-debug zebra packet
-debug zebra dplane
-debug zebra kernel
+!debug zebra packet
+!debug zebra dplane
+!debug zebra kernel
!
interface eth0
ipv6 address 2001::2/64
diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf3/r1/zebra.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf3/r1/zebra.conf
index 2c560dfc06..f913b9f002 100644
--- a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf3/r1/zebra.conf
+++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf3/r1/zebra.conf
@@ -7,9 +7,9 @@ log stdout notifications
log monitor notifications
log commands
!
-debug zebra packet
-debug zebra dplane
-debug zebra kernel
+!debug zebra packet
+!debug zebra dplane
+!debug zebra kernel
!
interface eth0
ipv6 address 2001::1/64
diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf3/r2/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf3/r2/bgpd.conf
index 8700f12d63..4ab5b98c12 100644
--- a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf3/r2/bgpd.conf
+++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf3/r2/bgpd.conf
@@ -1,6 +1,6 @@
frr defaults traditional
!
-bgp send-extra-data zebra
+!bgp send-extra-data zebra
!
hostname r2
password zebra
diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf3/r2/zebra.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf3/r2/zebra.conf
index b9277a9a8c..201d0cce23 100644
--- a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf3/r2/zebra.conf
+++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf3/r2/zebra.conf
@@ -7,9 +7,9 @@ log stdout notifications
log monitor notifications
log commands
!
-debug zebra packet
-debug zebra dplane
-debug zebra kernel
+!debug zebra packet
+!debug zebra dplane
+!debug zebra kernel
!
interface eth0
ipv6 address 2001::2/64
diff --git a/tests/topotests/bgp_suppress_fib/r2/bgpd.allowas_in.conf b/tests/topotests/bgp_suppress_fib/r2/bgpd.allowas_in.conf
index caebb0e922..fb6980a139 100644
--- a/tests/topotests/bgp_suppress_fib/r2/bgpd.allowas_in.conf
+++ b/tests/topotests/bgp_suppress_fib/r2/bgpd.allowas_in.conf
@@ -2,12 +2,12 @@ access-list access seq 10 permit 192.168.1.1/32
!
ip route 192.168.1.1/32 10.0.0.10
!
-debug bgp bestpath
-debug bgp nht
-debug bgp updates
-debug bgp update-groups
-debug bgp zebra
-debug zebra rib detail
+!debug bgp bestpath
+!debug bgp nht
+!debug bgp updates
+!debug bgp update-groups
+!debug bgp zebra
+!debug zebra rib detail
!
router bgp 2
address-family ipv4 uni
diff --git a/tests/topotests/bgp_suppress_fib/r2/bgpd.conf b/tests/topotests/bgp_suppress_fib/r2/bgpd.conf
index 010e86aad7..129b812036 100644
--- a/tests/topotests/bgp_suppress_fib/r2/bgpd.conf
+++ b/tests/topotests/bgp_suppress_fib/r2/bgpd.conf
@@ -1,6 +1,6 @@
-debug bgp updates
-debug bgp bestpath 40.0.0.0/8
-debug bgp zebra
+!debug bgp updates
+!debug bgp bestpath 40.0.0.0/8
+!debug bgp zebra
!
router bgp 2
no bgp ebgp-requires-policy
@@ -8,4 +8,4 @@ router bgp 2
neighbor 10.0.0.1 remote-as 1
neighbor 10.0.0.10 remote-as 3
address-family ipv4 uni
- network 60.0.0.0/24 \ No newline at end of file
+ network 60.0.0.0/24
diff --git a/tests/topotests/bgp_vrf_md5_peering/r1/bgpd.conf b/tests/topotests/bgp_vrf_md5_peering/r1/bgpd.conf
index 8d8f64158f..9f2ee19357 100644
--- a/tests/topotests/bgp_vrf_md5_peering/r1/bgpd.conf
+++ b/tests/topotests/bgp_vrf_md5_peering/r1/bgpd.conf
@@ -1,5 +1,5 @@
!
-debug bgp neighbor
+!debug bgp neighbor
!
router bgp 65534 vrf public
bgp router-id 10.0.0.1
diff --git a/tests/topotests/config_timing/test_config_timing.py b/tests/topotests/config_timing/test_config_timing.py
index 8de6f9bf70..5c1b97262c 100644
--- a/tests/topotests/config_timing/test_config_timing.py
+++ b/tests/topotests/config_timing/test_config_timing.py
@@ -133,7 +133,7 @@ def test_static_timing():
delta = (datetime.datetime.now() - tstamp).total_seconds()
tot_delta += delta
- router.logger.info(
+ router.logger.debug(
"\nvtysh command => {}\nvtysh output <= {}\nin {}s".format(
load_command, output, delta
)
@@ -152,7 +152,7 @@ def test_static_timing():
# Number of static routes
router = tgen.gears["r1"]
- output = router.run("vtysh -h | grep address-sanitizer")
+ output = router.net.cmd_legacy("vtysh -h | grep address-sanitizer", warn=False)
if output == "":
logger.info("No Address Sanitizer, generating 10000 routes")
prefix_count = 10000
diff --git a/tests/topotests/isis_snmp/r5/ldpdconf b/tests/topotests/isis_snmp/r5/ldpdconf
index fc700608b5..b3d10b07ec 100644
--- a/tests/topotests/isis_snmp/r5/ldpdconf
+++ b/tests/topotests/isis_snmp/r5/ldpdconf
@@ -1,10 +1,10 @@
hostname r5
log file ldpd.log
!
-debug mpls ldp zebra
-debug mpls ldp event
-debug mpls ldp errors
-debug mpls ldp sync
+!debug mpls ldp zebra
+!debug mpls ldp event
+!debug mpls ldp errors
+!debug mpls ldp sync
!
mpls ldp
router-id 3.3.3.3
diff --git a/tests/topotests/lib/common_config.py b/tests/topotests/lib/common_config.py
index e5a1e75837..d19d8db75c 100644
--- a/tests/topotests/lib/common_config.py
+++ b/tests/topotests/lib/common_config.py
@@ -492,7 +492,7 @@ def save_initial_config_on_routers(tgen):
# Get all running configs in parallel
procs = {}
for rname in router_list:
- logger.info("Fetching running config for router %s", rname)
+ logger.debug("Fetching running config for router %s", rname)
procs[rname] = router_list[rname].popen(
["/usr/bin/env", "vtysh", "-c", "show running-config no-header"],
stdin=None,
@@ -548,7 +548,7 @@ def reset_config_on_routers(tgen, routerName=None):
#
procs = {}
for rname in router_list:
- logger.info("Fetching running config for router %s", rname)
+ logger.debug("Fetching running config for router %s", rname)
procs[rname] = router_list[rname].popen(
["/usr/bin/env", "vtysh", "-c", "show running-config no-header"],
stdin=None,
@@ -570,7 +570,7 @@ def reset_config_on_routers(tgen, routerName=None):
#
procs = {}
for rname in router_list:
- logger.info(
+ logger.debug(
"Generating delta for router %s to new configuration (gen %d)", rname, gen
)
procs[rname] = tgen.net.popen(
@@ -599,7 +599,7 @@ def reset_config_on_routers(tgen, routerName=None):
#
procs = {}
for rname in router_list:
- logger.info("Applying delta config on router %s", rname)
+ logger.debug("Applying delta config on router %s", rname)
procs[rname] = router_list[rname].popen(
["/usr/bin/env", "vtysh", "-f", delta_fmt.format(rname, gen)],
@@ -611,7 +611,7 @@ def reset_config_on_routers(tgen, routerName=None):
output, _ = p.communicate()
vtysh_command = "vtysh -f {}".format(delta_fmt.format(rname, gen))
if not p.returncode:
- router_list[rname].logger.info(
+ router_list[rname].logger.debug(
'\nvtysh config apply => "{}"\nvtysh output <= "{}"'.format(
vtysh_command, output
)
@@ -640,7 +640,7 @@ def reset_config_on_routers(tgen, routerName=None):
if show_router_config:
procs = {}
for rname in router_list:
- logger.info("Fetching running config for router %s", rname)
+ logger.debug("Fetching running config for router %s", rname)
procs[rname] = router_list[rname].popen(
["/usr/bin/env", "vtysh", "-c", "show running-config no-header"],
stdin=None,
@@ -657,7 +657,7 @@ def reset_config_on_routers(tgen, routerName=None):
output,
)
else:
- logger.info(
+ logger.debug(
"Configuration on router %s after reset:\n%s", rname, output
)
@@ -742,7 +742,7 @@ def load_config_to_routers(tgen, routers, save_bkup=False):
frr_cfg_bkup = frr_cfg_bkup_fmt.format(rname)
with open(frr_cfg_file, "r+") as cfg:
data = cfg.read()
- logger.info(
+ logger.debug(
"Applying following configuration on router %s (gen: %d):\n%s",
rname,
gen,
@@ -775,7 +775,7 @@ def load_config_to_routers(tgen, routers, save_bkup=False):
frr_cfg_file = frr_cfg_file_fmt.format(rname)
vtysh_command = "vtysh -f " + frr_cfg_file
if not p.returncode:
- router_list[rname].logger.info(
+ router_list[rname].logger.debug(
'\nvtysh config apply => "{}"\nvtysh output <= "{}"'.format(
vtysh_command, output
)
@@ -821,7 +821,7 @@ def load_config_to_routers(tgen, routers, save_bkup=False):
output,
)
else:
- logger.info("New configuration for router %s:\n%s", rname, output)
+ logger.debug("New configuration for router %s:\n%s", rname, output)
logger.debug("Exiting API: load_config_to_routers")
return not errors
@@ -957,10 +957,10 @@ def generate_support_bundle():
bundle_procs[rname] = tgen.net[rname].popen(gen_sup_cmd, stdin=None)
for rname, rnode in router_list.items():
- logger.info("Waiting on support bundle for %s", rname)
+ logger.debug("Waiting on support bundle for %s", rname)
output, error = bundle_procs[rname].communicate()
if output:
- logger.info(
+ logger.debug(
"Output from collecting support bundle for %s:\n%s", rname, output
)
if error:
@@ -1234,15 +1234,15 @@ def add_interfaces_to_vlan(tgen, input_dict):
cmd = "ip link add link {} name {} type vlan id {}".format(
interface, vlan_intf, vlan
)
- logger.info("[DUT: %s]: Running command: %s", dut, cmd)
+ logger.debug("[DUT: %s]: Running command: %s", dut, cmd)
result = rnode.run(cmd)
- logger.info("result %s", result)
+ logger.debug("result %s", result)
# Bringing interface up
cmd = "ip link set {} up".format(vlan_intf)
- logger.info("[DUT: %s]: Running command: %s", dut, cmd)
+ logger.debug("[DUT: %s]: Running command: %s", dut, cmd)
result = rnode.run(cmd)
- logger.info("result %s", result)
+ logger.debug("result %s", result)
# Assigning IP address
ifaddr = ipaddress.ip_interface(
@@ -1254,9 +1254,9 @@ def add_interfaces_to_vlan(tgen, input_dict):
cmd = "ip -{0} a flush {1} scope global && ip a add {2} dev {1} && ip l set {1} up".format(
ifaddr.version, vlan_intf, ifaddr
)
- logger.info("[DUT: %s]: Running command: %s", dut, cmd)
+ logger.debug("[DUT: %s]: Running command: %s", dut, cmd)
result = rnode.run(cmd)
- logger.info("result %s", result)
+ logger.debug("result %s", result)
def tcpdump_capture_start(
@@ -1567,12 +1567,16 @@ def create_vrf_cfg(tgen, topo, input_dict=None, build=False):
vrf["name"], vrf["id"]
)
- logger.info("[DUT: %s]: Running kernel cmd [%s]", c_router, cmd)
+ logger.debug(
+ "[DUT: %s]: Running kernel cmd [%s]", c_router, cmd
+ )
rnode.run(cmd)
# Kernel cmd - Bring down VRF
cmd = "ip link set dev {} down".format(name)
- logger.info("[DUT: %s]: Running kernel cmd [%s]", c_router, cmd)
+ logger.debug(
+ "[DUT: %s]: Running kernel cmd [%s]", c_router, cmd
+ )
rnode.run(cmd)
else:
@@ -1581,14 +1585,14 @@ def create_vrf_cfg(tgen, topo, input_dict=None, build=False):
cmd = "ip link add {} type vrf table {}".format(
name, table_id
)
- logger.info(
+ logger.debug(
"[DUT: %s]: Running kernel cmd " "[%s]", c_router, cmd
)
rnode.run(cmd)
# Kernel cmd - Bring up VRF
cmd = "ip link set dev {} up".format(name)
- logger.info(
+ logger.debug(
"[DUT: %s]: Running kernel " "cmd [%s]", c_router, cmd
)
rnode.run(cmd)
@@ -1616,7 +1620,7 @@ def create_vrf_cfg(tgen, topo, input_dict=None, build=False):
interface_name, _vrf
)
- logger.info(
+ logger.debug(
"[DUT: %s]: Running" " kernel cmd [%s]",
c_router,
cmd,
@@ -1683,7 +1687,7 @@ def create_interface_in_kernel(
cmd = "ip -{0} a flush {1} scope global && ip a add {2} dev {1} && ip l set {1} up".format(
ifaddr.version, name, ifaddr
)
- logger.info("[DUT: %s]: Running command: %s", dut, cmd)
+ logger.debug("[DUT: %s]: Running command: %s", dut, cmd)
rnode.run(cmd)
if vrf:
@@ -1715,7 +1719,7 @@ def shutdown_bringup_interface_in_kernel(tgen, dut, intf_name, ifaceaction=False
action = "down"
cmd = "{} {} {}".format(cmd, intf_name, action)
- logger.info("[DUT: %s]: Running command: %s", dut, cmd)
+ logger.debug("[DUT: %s]: Running command: %s", dut, cmd)
rnode.run(cmd)
@@ -1968,7 +1972,7 @@ def retry(retry_timeout, initial_wait=0, expected=True, diag_pct=0.75):
)
if initial_wait > 0:
- logger.info("Waiting for [%s]s as initial delay", initial_wait)
+ logger.debug("Waiting for [%s]s as initial delay", initial_wait)
sleep(initial_wait)
invert_logic = not _expected
@@ -2027,13 +2031,13 @@ def retry(retry_timeout, initial_wait=0, expected=True, diag_pct=0.75):
return saved_failure
if saved_failure:
- logger.info(
+ logger.debug(
"RETRY DIAG: [failure] Sleeping %ds until next retry with %.1f retry time left - too see if timeout was too short",
retry_sleep,
seconds_left,
)
else:
- logger.info(
+ logger.debug(
"Sleeping %ds until next retry with %.1f retry time left",
retry_sleep,
seconds_left,
@@ -3357,7 +3361,19 @@ def socat_send_mld_join(
# Run socat command to send IGMP join
logger.info("[DUT: {}]: Running command: [{}]".format(server, socat_cmd))
- output = rnode.run("set +m; {} sleep 0.5".format(socat_cmd))
+ output = rnode.run("set +m; {} echo $!".format(socat_cmd))
+
+ # Check if socat join process is running
+ if output:
+ pid = output.split()[0]
+ rnode.run("touch /var/run/frr/socat_join.pid")
+ rnode.run("echo %s >> /var/run/frr/socat_join.pid" % pid)
+ else:
+ errormsg = "Socat join is not sent for {}. Error {}".format(
+ mld_group, output
+ )
+ logger.error(output)
+ return errormsg
logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
return True
@@ -3415,7 +3431,7 @@ def socat_send_pim6_traffic(
if multicast_hops:
socat_cmd += "multicast-hops=255'"
- socat_cmd += " &>{}/socat.logs &".format(tgen.logdir)
+ socat_cmd += " >{}/socat.logs &".format(tgen.logdir)
# Run socat command to send pim6 traffic
logger.info(
@@ -3435,7 +3451,20 @@ def socat_send_pim6_traffic(
)
rnode.run("chmod 755 {}".format(traffic_shell_script))
- output = rnode.run("{} &> /dev/null".format(traffic_shell_script))
+ output = rnode.run("{} &>/dev/null & echo $!".format(traffic_shell_script))
+
+ # Check if socat traffic process is running
+ if output:
+ pid = output.split()[0]
+ rnode.run("touch /var/run/frr/socat_traffic.pid")
+ rnode.run("echo %s >> /var/run/frr/socat_traffic.pid" % pid)
+
+ else:
+ errormsg = "Socat traffic is not sent for {}. Error {}".format(
+ mld_group, output
+ )
+ logger.error(output)
+ return errormsg
logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
return True
@@ -3465,18 +3494,30 @@ def kill_socat(tgen, dut=None, action=None):
if dut is not None and router != dut:
continue
+ traffic_shell_script = "{}/{}/traffic.sh".format(tgen.logdir, router)
+ pid_socat_join = rnode.run("cat /var/run/frr/socat_join.pid")
+ pid_socat_traffic = rnode.run("cat /var/run/frr/socat_traffic.pid")
if action == "remove_mld_join":
- cmd = "ps -ef | grep socat | grep UDP6-RECV | grep {}".format(router)
+ pids = pid_socat_join
elif action == "remove_mld_traffic":
- cmd = "ps -ef | grep socat | grep UDP6-SEND | grep {}".format(router)
+ pids = pid_socat_traffic
else:
- cmd = "ps -ef | grep socat".format(router)
-
- awk_cmd = "awk -F' ' '{print $2}' | xargs kill -9 &>/dev/null &"
- cmd = "{} | {}".format(cmd, awk_cmd)
+ pids = "\n".join([pid_socat_join, pid_socat_traffic])
- logger.debug("[DUT: {}]: Running command: [{}]".format(router, cmd))
- rnode.run(cmd)
+ if os.path.exists(traffic_shell_script):
+ cmd = (
+ "ps -ef | grep %s | awk -F' ' '{print $2}' | xargs kill -9"
+ % traffic_shell_script
+ )
+ logger.debug("[DUT: {}]: Running command: [{}]".format(router, cmd))
+ rnode.run(cmd)
+
+ for pid in pids.split("\n"):
+ pid = pid.strip()
+ if pid.isdigit():
+ cmd = "set +m; kill -9 %s &> /dev/null" % pid
+ logger.debug("[DUT: {}]: Running command: [{}]".format(router, cmd))
+ rnode.run(cmd)
logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
diff --git a/tests/topotests/lib/micronet_compat.py b/tests/topotests/lib/micronet_compat.py
index 5a69c56d8d..edbd360084 100644
--- a/tests/topotests/lib/micronet_compat.py
+++ b/tests/topotests/lib/micronet_compat.py
@@ -161,12 +161,10 @@ class Mininet(Micronet):
g_mnet_inst = None
- def __init__(self, controller=None):
+ def __init__(self):
"""
Create a Micronet.
"""
- assert not controller
-
if Mininet.g_mnet_inst is not None:
Mininet.g_mnet_inst.stop()
Mininet.g_mnet_inst = self
diff --git a/tests/topotests/lib/topogen.py b/tests/topotests/lib/topogen.py
index 41da660b7d..f5b3ad06d9 100644
--- a/tests/topotests/lib/topogen.py
+++ b/tests/topotests/lib/topogen.py
@@ -212,7 +212,10 @@ class Topogen(object):
# Mininet(Micronet) to build the actual topology.
assert not inspect.isclass(topodef)
- self.net = Mininet(controller=None)
+ self.net = Mininet()
+
+ # Adjust the parent namespace
+ topotest.fix_netns_limits(self.net)
# New direct way: Either a dictionary defines the topology or a build function
# is supplied, or a json filename all of which build the topology by calling
@@ -504,7 +507,7 @@ class Topogen(object):
def set_error(self, message, code=None):
"Sets an error message and signal other tests to skip."
- logger.info(message)
+ logger.info("setting error msg: %s", message)
# If no code is defined use a sequential number
if code is None:
@@ -799,7 +802,7 @@ class TopoRouter(TopoGear):
grep_cmd = "grep 'ip {}' {}".format(daemonstr, source)
else:
grep_cmd = "grep 'router {}' {}".format(daemonstr, source)
- result = self.run(grep_cmd).strip()
+ result = self.run(grep_cmd, warn=False).strip()
if result:
self.load_config(daemon)
else:
@@ -822,7 +825,7 @@ class TopoRouter(TopoGear):
all routers.
"""
daemonstr = self.RD.get(daemon)
- self.logger.info('loading "{}" configuration: {}'.format(daemonstr, source))
+ self.logger.debug('loading "{}" configuration: {}'.format(daemonstr, source))
self.net.loadConf(daemonstr, source, param)
def check_router_running(self):
@@ -945,16 +948,16 @@ class TopoRouter(TopoGear):
vtysh_command = 'vtysh {} -c "{}" 2>/dev/null'.format(dparam, command)
- self.logger.info('vtysh command => "{}"'.format(command))
+ self.logger.debug('vtysh command => "{}"'.format(command))
output = self.run(vtysh_command)
dbgout = output.strip()
if dbgout:
if "\n" in dbgout:
dbgout = dbgout.replace("\n", "\n\t")
- self.logger.info("vtysh result:\n\t{}".format(dbgout))
+ self.logger.debug("vtysh result:\n\t{}".format(dbgout))
else:
- self.logger.info('vtysh result: "{}"'.format(dbgout))
+ self.logger.debug('vtysh result: "{}"'.format(dbgout))
if isjson is False:
return output
@@ -994,7 +997,7 @@ class TopoRouter(TopoGear):
dbgcmds = commands if is_string(commands) else "\n".join(commands)
dbgcmds = "\t" + dbgcmds.replace("\n", "\n\t")
- self.logger.info("vtysh command => FILE:\n{}".format(dbgcmds))
+ self.logger.debug("vtysh command => FILE:\n{}".format(dbgcmds))
res = self.run(vtysh_command)
os.unlink(fname)
@@ -1003,9 +1006,9 @@ class TopoRouter(TopoGear):
if dbgres:
if "\n" in dbgres:
dbgres = dbgres.replace("\n", "\n\t")
- self.logger.info("vtysh result:\n\t{}".format(dbgres))
+ self.logger.debug("vtysh result:\n\t{}".format(dbgres))
else:
- self.logger.info('vtysh result: "{}"'.format(dbgres))
+ self.logger.debug('vtysh result: "{}"'.format(dbgres))
return res
def report_memory_leaks(self, testname):
diff --git a/tests/topotests/lib/topotest.py b/tests/topotests/lib/topotest.py
index d35b908e12..86a7f2000f 100644
--- a/tests/topotests/lib/topotest.py
+++ b/tests/topotests/lib/topotest.py
@@ -352,7 +352,7 @@ def run_and_expect(func, what, count=20, wait=3):
count, wait
)
- logger.info(
+ logger.debug(
"'{}' polling started (interval {} secs, maximum {} tries)".format(
func_name, wait, count
)
@@ -366,7 +366,7 @@ def run_and_expect(func, what, count=20, wait=3):
continue
end_time = time.time()
- logger.info(
+ logger.debug(
"'{}' succeeded after {:.2f} seconds".format(
func_name, end_time - start_time
)
@@ -409,7 +409,7 @@ def run_and_expect_type(func, etype, count=20, wait=3, avalue=None):
count, wait
)
- logger.info(
+ logger.debug(
"'{}' polling started (interval {} secs, maximum wait {} secs)".format(
func_name, wait, int(wait * count)
)
@@ -432,7 +432,7 @@ def run_and_expect_type(func, etype, count=20, wait=3, avalue=None):
continue
end_time = time.time()
- logger.info(
+ logger.debug(
"'{}' succeeded after {:.2f} seconds".format(
func_name, end_time - start_time
)
@@ -1130,7 +1130,7 @@ def _sysctl_atleast(commander, variable, min_value):
valstr = " ".join([str(x) for x in min_value])
else:
valstr = str(min_value)
- logger.info("Increasing sysctl %s from %s to %s", variable, cur_val, valstr)
+ logger.debug("Increasing sysctl %s from %s to %s", variable, cur_val, valstr)
commander.cmd_raises('sysctl -w {}="{}"\n'.format(variable, valstr))
@@ -1161,7 +1161,7 @@ def _sysctl_assure(commander, variable, value):
valstr = " ".join([str(x) for x in value])
else:
valstr = str(value)
- logger.info("Changing sysctl %s from %s to %s", variable, cur_val, valstr)
+ logger.debug("Changing sysctl %s from %s to %s", variable, cur_val, valstr)
commander.cmd_raises('sysctl -w {}="{}"\n'.format(variable, valstr))
@@ -1204,7 +1204,7 @@ def rlimit_atleast(rname, min_value, raises=False):
soft, hard = cval
if soft < min_value:
nval = (min_value, hard if min_value < hard else min_value)
- logger.info("Increasing rlimit %s from %s to %s", rname, cval, nval)
+ logger.debug("Increasing rlimit %s from %s to %s", rname, cval, nval)
resource.setrlimit(rname, nval)
except subprocess.CalledProcessError as error:
logger.warning(
@@ -1478,11 +1478,11 @@ class Router(Node):
logger.info("%s: stopping %s", self.name, ", ".join([x[0] for x in running]))
for name, pid in running:
- logger.info("{}: sending SIGTERM to {}".format(self.name, name))
+ logger.debug("{}: sending SIGTERM to {}".format(self.name, name))
try:
os.kill(pid, signal.SIGTERM)
except OSError as err:
- logger.info(
+ logger.debug(
"%s: could not kill %s (%s): %s", self.name, name, pid, str(err)
)
@@ -1526,7 +1526,10 @@ class Router(Node):
def removeIPs(self):
for interface in self.intfNames():
try:
- self.intf_ip_cmd(interface, "ip address flush " + interface)
+ self.intf_ip_cmd(interface, "ip -4 address flush " + interface)
+ self.intf_ip_cmd(
+ interface, "ip -6 address flush " + interface + " scope global"
+ )
except Exception as ex:
logger.error("%s can't remove IPs %s", self, str(ex))
# pdb.set_trace()
@@ -1560,7 +1563,7 @@ class Router(Node):
router_relative = os.path.join(script_dir, self.name, tail)
if self.path_exists(router_relative):
source = router_relative
- self.logger.info(
+ self.logger.debug(
"using router relative configuration: {}".format(source)
)
@@ -1617,7 +1620,7 @@ class Router(Node):
# Auto-Started staticd has no config, so it will read from zebra config
else:
- logger.info("No daemon {} known".format(daemon))
+ logger.warning("No daemon {} known".format(daemon))
# print "Daemons after:", self.daemons
def runInWindow(self, cmd, title=None):
@@ -1859,7 +1862,7 @@ class Router(Node):
else "",
)
else:
- logger.info("%s: %s %s started", self, self.routertype, daemon)
+ logger.debug("%s: %s %s started", self, self.routertype, daemon)
# Start mgmtd first
if "mgmtd" in daemons_list:
@@ -1888,15 +1891,6 @@ class Router(Node):
while "snmpd" in daemons_list:
daemons_list.remove("snmpd")
- if daemons is None:
- # Fix Link-Local Addresses on initial startup
- # Somehow (on Mininet only), Zebra removes the IPv6 Link-Local addresses on start. Fix this
- _, output, _ = self.cmd_status(
- "for i in `ls /sys/class/net/` ; do mac=`cat /sys/class/net/$i/address`; echo $i: $mac; [ -z \"$mac\" ] && continue; IFS=':'; set $mac; unset IFS; ip address add dev $i scope link fe80::$(printf %02x $((0x$1 ^ 2)))$2:${3}ff:fe$4:$5$6/64; done",
- stderr=subprocess.STDOUT,
- )
- logger.debug("Set MACs:\n%s", output)
-
# Now start all the other daemons
for daemon in daemons_list:
if self.daemons[daemon] == 0:
@@ -1934,7 +1928,7 @@ class Router(Node):
daemonpidfile = d.rstrip()
daemonpid = self.cmd("cat %s" % daemonpidfile).rstrip()
if daemonpid.isdigit() and pid_exists(int(daemonpid)):
- logger.info(
+ logger.debug(
"{}: killing {}".format(
self.name,
os.path.basename(daemonpidfile.rsplit(".", 1)[0]),
@@ -2198,7 +2192,7 @@ class Router(Node):
log = self.getStdErr(daemon)
if "memstats" in log:
# Found memory leak
- logger.info(
+ logger.warning(
"\nRouter {} {} StdErr Log:\n{}".format(self.name, daemon, log)
)
if not leakfound:
diff --git a/tests/topotests/mgmt_tests/test_yang_mgmt.py b/tests/topotests/mgmt_tests/test_yang_mgmt.py
index 06c18d7dfa..921b4e622c 100644
--- a/tests/topotests/mgmt_tests/test_yang_mgmt.py
+++ b/tests/topotests/mgmt_tests/test_yang_mgmt.py
@@ -217,7 +217,9 @@ def test_mgmt_commit_check(request):
]
}
}
- result = verify_rib(tgen, "ipv4", dut, input_dict_4, protocol=protocol)
+ result = verify_rib(
+ tgen, "ipv4", dut, input_dict_4, protocol=protocol, expected=False
+ )
assert (
result is not True
), "Testcase {} : Failed" "Error: Routes is missing in RIB".format(tc_name)
@@ -319,7 +321,9 @@ def test_mgmt_commit_abort(request):
]
}
}
- result = verify_rib(tgen, "ipv4", dut, input_dict_4, protocol=protocol)
+ result = verify_rib(
+ tgen, "ipv4", dut, input_dict_4, protocol=protocol, expected=False
+ )
assert (
result is not True
), "Testcase {} : Failed" "Error: Routes is missing in RIB".format(tc_name)
@@ -372,7 +376,7 @@ def test_mgmt_delete_config(request):
assert (
result is True
), "Testcase {} : Failed" "Error: Routes is missing in RIB".format(tc_name)
-
+
step("Mgmt delete config")
raw_config = {
"r1": {
@@ -387,7 +391,9 @@ def test_mgmt_delete_config(request):
assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
step("Verify that the route is deleted from RIB")
- result = verify_rib(tgen, "ipv4", dut, input_dict_4, protocol=protocol)
+ result = verify_rib(
+ tgen, "ipv4", dut, input_dict_4, protocol=protocol, expected=False
+ )
assert (
result is not True
), "Testcase {} : Failed" "Error: Routes is still present in RIB".format(tc_name)
@@ -461,7 +467,9 @@ def test_mgmt_chaos_stop_start_frr(request):
dut = "r1"
protocol = "static"
input_dict_4 = {"r1": {"static_routes": [{"network": "192.1.11.200/32"}]}}
- result = verify_rib(tgen, "ipv4", dut, input_dict_4, protocol=protocol)
+ result = verify_rib(
+ tgen, "ipv4", dut, input_dict_4, protocol=protocol, expected=False
+ )
assert (
result is not True
), "Testcase {} : Failed" "Error: Routes still present in RIB".format(tc_name)
diff --git a/tests/topotests/multicast_pim6_sm_topo1/test_multicast_pim6_sm1.py b/tests/topotests/multicast_pim6_sm_topo1/test_multicast_pim6_sm1.py
index a76ff2dd9c..87b04b41be 100644
--- a/tests/topotests/multicast_pim6_sm_topo1/test_multicast_pim6_sm1.py
+++ b/tests/topotests/multicast_pim6_sm_topo1/test_multicast_pim6_sm1.py
@@ -62,6 +62,7 @@ from lib.common_config import (
socat_send_mld_join,
socat_send_pim6_traffic,
get_frr_ipv6_linklocal,
+ kill_socat,
)
from lib.bgp import create_router_bgp
from lib.pim import (
@@ -158,10 +159,6 @@ def setup_module(mod):
# Creating configuration from JSON
build_config_from_json(tgen, tgen.json_topo)
- # XXX Replace this using "with McastTesterHelper()... " in each test if possible.
- global app_helper
- app_helper = McastTesterHelper(tgen)
-
logger.info("Running setup_module() done")
@@ -172,7 +169,8 @@ def teardown_module():
tgen = get_topogen()
- app_helper.cleanup()
+ # Clean up socat
+ kill_socat(tgen)
# Stop toplogy and Remove tmp files
tgen.stop_topology()
diff --git a/tests/topotests/multicast_pim6_sm_topo1/test_multicast_pim6_sm2.py b/tests/topotests/multicast_pim6_sm_topo1/test_multicast_pim6_sm2.py
index ceef68fece..788a839918 100644
--- a/tests/topotests/multicast_pim6_sm_topo1/test_multicast_pim6_sm2.py
+++ b/tests/topotests/multicast_pim6_sm_topo1/test_multicast_pim6_sm2.py
@@ -53,6 +53,7 @@ from lib.common_config import (
socat_send_mld_join,
socat_send_pim6_traffic,
get_frr_ipv6_linklocal,
+ kill_socat,
)
from lib.bgp import create_router_bgp
from lib.pim import (
@@ -149,10 +150,6 @@ def setup_module(mod):
# Creating configuration from JSON
build_config_from_json(tgen, tgen.json_topo)
- # XXX Replace this using "with McastTesterHelper()... " in each test if possible.
- global app_helper
- app_helper = McastTesterHelper(tgen)
-
logger.info("Running setup_module() done")
@@ -163,7 +160,8 @@ def teardown_module():
tgen = get_topogen()
- app_helper.cleanup()
+ # Clean up socat
+ kill_socat(tgen)
# Stop toplogy and Remove tmp files
tgen.stop_topology()
diff --git a/tests/topotests/multicast_pim6_static_rp_topo1/test_multicast_pim6_static_rp1.py b/tests/topotests/multicast_pim6_static_rp_topo1/test_multicast_pim6_static_rp1.py
index 95b4004e14..977cd477c8 100755
--- a/tests/topotests/multicast_pim6_static_rp_topo1/test_multicast_pim6_static_rp1.py
+++ b/tests/topotests/multicast_pim6_static_rp_topo1/test_multicast_pim6_static_rp1.py
@@ -172,6 +172,9 @@ def teardown_module():
logger.info("Running teardown_module to delete topology")
tgen = get_topogen()
+ # Clean up socat
+ kill_socat(tgen)
+
# Stop toplogy and Remove tmp files
tgen.stop_topology()
diff --git a/tests/topotests/multicast_pim6_static_rp_topo1/test_multicast_pim6_static_rp2.py b/tests/topotests/multicast_pim6_static_rp_topo1/test_multicast_pim6_static_rp2.py
index 2fedb6e517..a61164baa2 100755
--- a/tests/topotests/multicast_pim6_static_rp_topo1/test_multicast_pim6_static_rp2.py
+++ b/tests/topotests/multicast_pim6_static_rp_topo1/test_multicast_pim6_static_rp2.py
@@ -176,6 +176,9 @@ def teardown_module():
logger.info("Running teardown_module to delete topology")
tgen = get_topogen()
+ # Clean up socat
+ kill_socat(tgen)
+
# Stop toplogy and Remove tmp files
tgen.stop_topology()
diff --git a/tests/topotests/ospf6_ecmp_inter_area/r1/ospf6d.conf b/tests/topotests/ospf6_ecmp_inter_area/r1/ospf6d.conf
index 6c7cb96240..e6e5733010 100644
--- a/tests/topotests/ospf6_ecmp_inter_area/r1/ospf6d.conf
+++ b/tests/topotests/ospf6_ecmp_inter_area/r1/ospf6d.conf
@@ -1,35 +1,35 @@
-debug ospf6 lsa all
-debug ospf6 message all
-debug ospf6 route all
-debug ospf6 spf time
-debug ospf6 spf database
-debug ospf6 zebra send
-debug ospf6 zebra recv
-
-debug ospf6 lsa router
-debug ospf6 lsa router originate
-debug ospf6 lsa router examine
-debug ospf6 lsa router flooding
-debug ospf6 lsa as-external
-debug ospf6 lsa as-external originate
-debug ospf6 lsa as-external examine
-debug ospf6 lsa as-external flooding
-debug ospf6 lsa intra-prefix
-debug ospf6 lsa intra-prefix originate
-debug ospf6 lsa intra-prefix examine
-debug ospf6 lsa intra-prefix flooding
-debug ospf6 border-routers
-debug ospf6 zebra
-debug ospf6 interface
-debug ospf6 neighbor
-debug ospf6 flooding
-debug ospf6 gr helper
-debug ospf6 spf process
-debug ospf6 route intra-area
-debug ospf6 route inter-area
-debug ospf6 abr
-debug ospf6 asbr
-debug ospf6 nssa
+!debug ospf6 lsa all
+!debug ospf6 message all
+!debug ospf6 route all
+!debug ospf6 spf time
+!debug ospf6 spf database
+!debug ospf6 zebra send
+!debug ospf6 zebra recv
+!
+!debug ospf6 lsa router
+!debug ospf6 lsa router originate
+!debug ospf6 lsa router examine
+!debug ospf6 lsa router flooding
+!debug ospf6 lsa as-external
+!debug ospf6 lsa as-external originate
+!debug ospf6 lsa as-external examine
+!debug ospf6 lsa as-external flooding
+!debug ospf6 lsa intra-prefix
+!debug ospf6 lsa intra-prefix originate
+!debug ospf6 lsa intra-prefix examine
+!debug ospf6 lsa intra-prefix flooding
+!debug ospf6 border-routers
+!debug ospf6 zebra
+!debug ospf6 interface
+!debug ospf6 neighbor
+!debug ospf6 flooding
+!debug ospf6 gr helper
+!debug ospf6 spf process
+!debug ospf6 route intra-area
+!debug ospf6 route inter-area
+!debug ospf6 abr
+!debug ospf6 asbr
+!debug ospf6 nssa
!
interface r1-eth0
ipv6 ospf6 area 0
diff --git a/tests/topotests/ospf_nssa_topo1/__init__.py b/tests/topotests/ospf_nssa_topo1/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/__init__.py
diff --git a/tests/topotests/ospf_nssa_topo1/rt1/ospfd.conf b/tests/topotests/ospf_nssa_topo1/rt1/ospfd.conf
new file mode 100644
index 0000000000..6d23c84806
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt1/ospfd.conf
@@ -0,0 +1,22 @@
+password 1
+hostname rt1
+log file ospfd.log
+!
+! debug ospf sr
+! debug ospf te
+! debug ospf event
+! debug ospf lsa
+! debug ospf zebra
+!
+interface lo
+ ip ospf area 0
+!
+interface eth-rt2
+ ip ospf network point-to-point
+ ip ospf area 0
+ ip ospf hello-interval 3
+ ip ospf dead-interval 12
+!
+router ospf
+ router-id 1.1.1.1
+!
diff --git a/tests/topotests/ospf_nssa_topo1/rt1/staticd.conf b/tests/topotests/ospf_nssa_topo1/rt1/staticd.conf
new file mode 100644
index 0000000000..7ba3dc7591
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt1/staticd.conf
@@ -0,0 +1,6 @@
+log file staticd.log
+!
+hostname rt1
+!
+line vty
+!
diff --git a/tests/topotests/ospf_nssa_topo1/rt1/step1/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt1/step1/show_ip_ospf_route.ref
new file mode 100644
index 0000000000..ac34417bda
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt1/step1/show_ip_ospf_route.ref
@@ -0,0 +1,115 @@
+{
+ "1.1.1.1\/32":{
+ "routeType":"N",
+ "cost":0,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"lo"
+ }
+ ]
+ },
+ "2.2.2.2\/32":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "3.3.3.3\/32":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "4.4.4.4\/32":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.1.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.2.0\/24":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.3.0\/24":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.0",
+ "routerType":"abr",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.1\/32":{
+ "routeType":"N E2",
+ "cost":20,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.2\/32":{
+ "routeType":"N E2",
+ "cost":20,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf_nssa_topo1/rt1/step10/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt1/step10/show_ip_ospf_route.ref
new file mode 100644
index 0000000000..ac34417bda
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt1/step10/show_ip_ospf_route.ref
@@ -0,0 +1,115 @@
+{
+ "1.1.1.1\/32":{
+ "routeType":"N",
+ "cost":0,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"lo"
+ }
+ ]
+ },
+ "2.2.2.2\/32":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "3.3.3.3\/32":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "4.4.4.4\/32":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.1.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.2.0\/24":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.3.0\/24":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.0",
+ "routerType":"abr",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.1\/32":{
+ "routeType":"N E2",
+ "cost":20,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.2\/32":{
+ "routeType":"N E2",
+ "cost":20,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf_nssa_topo1/rt1/step2/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt1/step2/show_ip_ospf_route.ref
new file mode 100644
index 0000000000..ac34417bda
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt1/step2/show_ip_ospf_route.ref
@@ -0,0 +1,115 @@
+{
+ "1.1.1.1\/32":{
+ "routeType":"N",
+ "cost":0,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"lo"
+ }
+ ]
+ },
+ "2.2.2.2\/32":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "3.3.3.3\/32":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "4.4.4.4\/32":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.1.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.2.0\/24":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.3.0\/24":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.0",
+ "routerType":"abr",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.1\/32":{
+ "routeType":"N E2",
+ "cost":20,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.2\/32":{
+ "routeType":"N E2",
+ "cost":20,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf_nssa_topo1/rt1/step3/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt1/step3/show_ip_ospf_route.ref
new file mode 100644
index 0000000000..ac34417bda
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt1/step3/show_ip_ospf_route.ref
@@ -0,0 +1,115 @@
+{
+ "1.1.1.1\/32":{
+ "routeType":"N",
+ "cost":0,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"lo"
+ }
+ ]
+ },
+ "2.2.2.2\/32":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "3.3.3.3\/32":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "4.4.4.4\/32":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.1.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.2.0\/24":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.3.0\/24":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.0",
+ "routerType":"abr",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.1\/32":{
+ "routeType":"N E2",
+ "cost":20,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.2\/32":{
+ "routeType":"N E2",
+ "cost":20,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf_nssa_topo1/rt1/step4/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt1/step4/show_ip_ospf_route.ref
new file mode 100644
index 0000000000..6a05555eec
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt1/step4/show_ip_ospf_route.ref
@@ -0,0 +1,103 @@
+{
+ "1.1.1.1\/32":{
+ "routeType":"N",
+ "cost":0,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"lo"
+ }
+ ]
+ },
+ "2.2.2.2\/32":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "3.3.3.3\/32":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "4.4.4.4\/32":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.1.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.2.0\/24":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.3.0\/24":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.0",
+ "routerType":"abr",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.0\/24":{
+ "routeType":"N E2",
+ "cost":10,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf_nssa_topo1/rt1/step5/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt1/step5/show_ip_ospf_route.ref
new file mode 100644
index 0000000000..6a05555eec
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt1/step5/show_ip_ospf_route.ref
@@ -0,0 +1,103 @@
+{
+ "1.1.1.1\/32":{
+ "routeType":"N",
+ "cost":0,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"lo"
+ }
+ ]
+ },
+ "2.2.2.2\/32":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "3.3.3.3\/32":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "4.4.4.4\/32":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.1.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.2.0\/24":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.3.0\/24":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.0",
+ "routerType":"abr",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.0\/24":{
+ "routeType":"N E2",
+ "cost":10,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf_nssa_topo1/rt1/step6/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt1/step6/show_ip_ospf_route.ref
new file mode 100644
index 0000000000..2d3c8c485f
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt1/step6/show_ip_ospf_route.ref
@@ -0,0 +1,91 @@
+{
+ "1.1.1.1\/32":{
+ "routeType":"N",
+ "cost":0,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"lo"
+ }
+ ]
+ },
+ "2.2.2.2\/32":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "3.3.3.3\/32":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "4.4.4.4\/32":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.1.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.2.0\/24":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.3.0\/24":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.0",
+ "routerType":"abr",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf_nssa_topo1/rt1/step7/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt1/step7/show_ip_ospf_route.ref
new file mode 100644
index 0000000000..6a05555eec
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt1/step7/show_ip_ospf_route.ref
@@ -0,0 +1,103 @@
+{
+ "1.1.1.1\/32":{
+ "routeType":"N",
+ "cost":0,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"lo"
+ }
+ ]
+ },
+ "2.2.2.2\/32":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "3.3.3.3\/32":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "4.4.4.4\/32":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.1.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.2.0\/24":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.3.0\/24":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.0",
+ "routerType":"abr",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.0\/24":{
+ "routeType":"N E2",
+ "cost":10,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf_nssa_topo1/rt1/step8/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt1/step8/show_ip_ospf_route.ref
new file mode 100644
index 0000000000..f41ee3b698
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt1/step8/show_ip_ospf_route.ref
@@ -0,0 +1,103 @@
+{
+ "1.1.1.1\/32":{
+ "routeType":"N",
+ "cost":0,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"lo"
+ }
+ ]
+ },
+ "2.2.2.2\/32":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "3.3.3.3\/32":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "4.4.4.4\/32":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.1.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.2.0\/24":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.3.0\/24":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.0",
+ "routerType":"abr",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.0\/24":{
+ "routeType":"N E2",
+ "cost":10,
+ "type2cost":1000,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf_nssa_topo1/rt1/step9/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt1/step9/show_ip_ospf_route.ref
new file mode 100644
index 0000000000..2d3c8c485f
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt1/step9/show_ip_ospf_route.ref
@@ -0,0 +1,91 @@
+{
+ "1.1.1.1\/32":{
+ "routeType":"N",
+ "cost":0,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"lo"
+ }
+ ]
+ },
+ "2.2.2.2\/32":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "3.3.3.3\/32":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "4.4.4.4\/32":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.1.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.2.0\/24":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.3.0\/24":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.0",
+ "routerType":"abr",
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "via":"eth-rt2"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf_nssa_topo1/rt1/zebra.conf b/tests/topotests/ospf_nssa_topo1/rt1/zebra.conf
new file mode 100644
index 0000000000..1df100564e
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt1/zebra.conf
@@ -0,0 +1,18 @@
+log file zebra.log
+!
+hostname rt1
+!
+! debug zebra kernel
+! debug zebra packet
+! debug zebra mpls
+!
+interface lo
+ ip address 1.1.1.1/32
+!
+interface eth-rt2
+ ip address 10.0.1.1/24
+!
+ip forwarding
+!
+line vty
+!
diff --git a/tests/topotests/ospf_nssa_topo1/rt2/ospfd.conf b/tests/topotests/ospf_nssa_topo1/rt2/ospfd.conf
new file mode 100644
index 0000000000..12884d2ea9
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt2/ospfd.conf
@@ -0,0 +1,35 @@
+password 1
+hostname rt2
+log file ospfd.log
+!
+! debug ospf sr
+! debug ospf te
+! debug ospf event
+! debug ospf lsa
+! debug ospf zebra
+!
+interface lo
+ ip ospf area 0
+!
+interface eth-rt1
+ ip ospf network point-to-point
+ ip ospf area 0
+ ip ospf hello-interval 3
+ ip ospf dead-interval 12
+!
+interface eth-rt3
+ ip ospf network point-to-point
+ ip ospf area 1
+ ip ospf hello-interval 3
+ ip ospf dead-interval 12
+!
+interface eth-rt4
+ ip ospf network point-to-point
+ ip ospf area 1
+ ip ospf hello-interval 3
+ ip ospf dead-interval 12
+!
+router ospf
+ router-id 2.2.2.2
+ area 1 nssa
+!
diff --git a/tests/topotests/ospf_nssa_topo1/rt2/staticd.conf b/tests/topotests/ospf_nssa_topo1/rt2/staticd.conf
new file mode 100644
index 0000000000..b6d4233a4f
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt2/staticd.conf
@@ -0,0 +1,6 @@
+log file staticd.log
+!
+hostname rt2
+!
+line vty
+!
diff --git a/tests/topotests/ospf_nssa_topo1/rt2/step1/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt2/step1/show_ip_ospf_route.ref
new file mode 100644
index 0000000000..c09411741a
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt2/step1/show_ip_ospf_route.ref
@@ -0,0 +1,127 @@
+{
+ "1.1.1.1\/32":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.1",
+ "via":"eth-rt1"
+ }
+ ]
+ },
+ "2.2.2.2\/32":{
+ "routeType":"N",
+ "cost":0,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"lo"
+ }
+ ]
+ },
+ "3.3.3.3\/32":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.3",
+ "via":"eth-rt3"
+ }
+ ]
+ },
+ "4.4.4.4\/32":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.4",
+ "via":"eth-rt4"
+ }
+ ]
+ },
+ "10.0.1.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt1"
+ }
+ ]
+ },
+ "10.0.2.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt3"
+ }
+ ]
+ },
+ "10.0.3.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt4"
+ }
+ ]
+ },
+ "3.3.3.3":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.1",
+ "routerType":"asbr",
+ "nexthops":[
+ {
+ "ip":"10.0.2.3",
+ "via":"eth-rt3"
+ }
+ ]
+ },
+ "4.4.4.4":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.1",
+ "routerType":"asbr",
+ "nexthops":[
+ {
+ "ip":"10.0.3.4",
+ "via":"eth-rt4"
+ }
+ ]
+ },
+ "172.16.1.1\/32":{
+ "routeType":"N E2",
+ "cost":10,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.3.4",
+ "via":"eth-rt4"
+ }
+ ]
+ },
+ "172.16.1.2\/32":{
+ "routeType":"N E2",
+ "cost":10,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.3.4",
+ "via":"eth-rt4"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf_nssa_topo1/rt2/step10/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt2/step10/show_ip_ospf_route.ref
new file mode 100644
index 0000000000..c09411741a
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt2/step10/show_ip_ospf_route.ref
@@ -0,0 +1,127 @@
+{
+ "1.1.1.1\/32":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.1",
+ "via":"eth-rt1"
+ }
+ ]
+ },
+ "2.2.2.2\/32":{
+ "routeType":"N",
+ "cost":0,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"lo"
+ }
+ ]
+ },
+ "3.3.3.3\/32":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.3",
+ "via":"eth-rt3"
+ }
+ ]
+ },
+ "4.4.4.4\/32":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.4",
+ "via":"eth-rt4"
+ }
+ ]
+ },
+ "10.0.1.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt1"
+ }
+ ]
+ },
+ "10.0.2.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt3"
+ }
+ ]
+ },
+ "10.0.3.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt4"
+ }
+ ]
+ },
+ "3.3.3.3":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.1",
+ "routerType":"asbr",
+ "nexthops":[
+ {
+ "ip":"10.0.2.3",
+ "via":"eth-rt3"
+ }
+ ]
+ },
+ "4.4.4.4":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.1",
+ "routerType":"asbr",
+ "nexthops":[
+ {
+ "ip":"10.0.3.4",
+ "via":"eth-rt4"
+ }
+ ]
+ },
+ "172.16.1.1\/32":{
+ "routeType":"N E2",
+ "cost":10,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.3.4",
+ "via":"eth-rt4"
+ }
+ ]
+ },
+ "172.16.1.2\/32":{
+ "routeType":"N E2",
+ "cost":10,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.3.4",
+ "via":"eth-rt4"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf_nssa_topo1/rt2/step2/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt2/step2/show_ip_ospf_route.ref
new file mode 100644
index 0000000000..a67dfb4685
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt2/step2/show_ip_ospf_route.ref
@@ -0,0 +1,139 @@
+{
+ "1.1.1.1\/32":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.1",
+ "via":"eth-rt1"
+ }
+ ]
+ },
+ "2.2.2.2\/32":{
+ "routeType":"N",
+ "cost":0,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"lo"
+ }
+ ]
+ },
+ "3.3.3.3\/32":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.3",
+ "via":"eth-rt3"
+ }
+ ]
+ },
+ "4.4.4.4\/32":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.4",
+ "via":"eth-rt4"
+ }
+ ]
+ },
+ "10.0.1.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt1"
+ }
+ ]
+ },
+ "10.0.2.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt3"
+ }
+ ]
+ },
+ "10.0.3.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt4"
+ }
+ ]
+ },
+ "3.3.3.3":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.1",
+ "routerType":"asbr",
+ "nexthops":[
+ {
+ "ip":"10.0.2.3",
+ "via":"eth-rt3"
+ }
+ ]
+ },
+ "4.4.4.4":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.1",
+ "routerType":"asbr",
+ "nexthops":[
+ {
+ "ip":"10.0.3.4",
+ "via":"eth-rt4"
+ }
+ ]
+ },
+ "0.0.0.0\/0":{
+ "routeType":"N E2",
+ "cost":10,
+ "type2cost":1,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.2.3",
+ "via":"eth-rt3"
+ }
+ ]
+ },
+ "172.16.1.1\/32":{
+ "routeType":"N E2",
+ "cost":10,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.3.4",
+ "via":"eth-rt4"
+ }
+ ]
+ },
+ "172.16.1.2\/32":{
+ "routeType":"N E2",
+ "cost":10,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.3.4",
+ "via":"eth-rt4"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf_nssa_topo1/rt2/step3/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt2/step3/show_ip_ospf_route.ref
new file mode 100644
index 0000000000..c09411741a
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt2/step3/show_ip_ospf_route.ref
@@ -0,0 +1,127 @@
+{
+ "1.1.1.1\/32":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.1",
+ "via":"eth-rt1"
+ }
+ ]
+ },
+ "2.2.2.2\/32":{
+ "routeType":"N",
+ "cost":0,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"lo"
+ }
+ ]
+ },
+ "3.3.3.3\/32":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.3",
+ "via":"eth-rt3"
+ }
+ ]
+ },
+ "4.4.4.4\/32":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.4",
+ "via":"eth-rt4"
+ }
+ ]
+ },
+ "10.0.1.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt1"
+ }
+ ]
+ },
+ "10.0.2.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt3"
+ }
+ ]
+ },
+ "10.0.3.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt4"
+ }
+ ]
+ },
+ "3.3.3.3":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.1",
+ "routerType":"asbr",
+ "nexthops":[
+ {
+ "ip":"10.0.2.3",
+ "via":"eth-rt3"
+ }
+ ]
+ },
+ "4.4.4.4":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.1",
+ "routerType":"asbr",
+ "nexthops":[
+ {
+ "ip":"10.0.3.4",
+ "via":"eth-rt4"
+ }
+ ]
+ },
+ "172.16.1.1\/32":{
+ "routeType":"N E2",
+ "cost":10,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.3.4",
+ "via":"eth-rt4"
+ }
+ ]
+ },
+ "172.16.1.2\/32":{
+ "routeType":"N E2",
+ "cost":10,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.3.4",
+ "via":"eth-rt4"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf_nssa_topo1/rt2/step4/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt2/step4/show_ip_ospf_route.ref
new file mode 100644
index 0000000000..c7dd93c6e9
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt2/step4/show_ip_ospf_route.ref
@@ -0,0 +1,129 @@
+{
+ "1.1.1.1\/32":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.1",
+ "via":"eth-rt1"
+ }
+ ]
+ },
+ "2.2.2.2\/32":{
+ "routeType":"N",
+ "cost":0,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"lo"
+ }
+ ]
+ },
+ "3.3.3.3\/32":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.3",
+ "via":"eth-rt3"
+ }
+ ]
+ },
+ "4.4.4.4\/32":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.4",
+ "via":"eth-rt4"
+ }
+ ]
+ },
+ "10.0.1.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt1"
+ }
+ ]
+ },
+ "10.0.2.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt3"
+ }
+ ]
+ },
+ "10.0.3.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt4"
+ }
+ ]
+ },
+ "172.16.1.0\/24":{
+ },
+ "3.3.3.3":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.1",
+ "routerType":"asbr",
+ "nexthops":[
+ {
+ "ip":"10.0.2.3",
+ "via":"eth-rt3"
+ }
+ ]
+ },
+ "4.4.4.4":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.1",
+ "routerType":"asbr",
+ "nexthops":[
+ {
+ "ip":"10.0.3.4",
+ "via":"eth-rt4"
+ }
+ ]
+ },
+ "172.16.1.1\/32":{
+ "routeType":"N E2",
+ "cost":10,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.3.4",
+ "via":"eth-rt4"
+ }
+ ]
+ },
+ "172.16.1.2\/32":{
+ "routeType":"N E2",
+ "cost":10,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.3.4",
+ "via":"eth-rt4"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf_nssa_topo1/rt2/step5/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt2/step5/show_ip_ospf_route.ref
new file mode 100644
index 0000000000..9c3cfff6c0
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt2/step5/show_ip_ospf_route.ref
@@ -0,0 +1,117 @@
+{
+ "1.1.1.1\/32":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.1",
+ "via":"eth-rt1"
+ }
+ ]
+ },
+ "2.2.2.2\/32":{
+ "routeType":"N",
+ "cost":0,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"lo"
+ }
+ ]
+ },
+ "3.3.3.3\/32":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.3",
+ "via":"eth-rt3"
+ }
+ ]
+ },
+ "4.4.4.4\/32":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.4",
+ "via":"eth-rt4"
+ }
+ ]
+ },
+ "10.0.1.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt1"
+ }
+ ]
+ },
+ "10.0.2.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt3"
+ }
+ ]
+ },
+ "10.0.3.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt4"
+ }
+ ]
+ },
+ "172.16.1.0\/24":{
+ },
+ "3.3.3.3":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.1",
+ "routerType":"asbr",
+ "nexthops":[
+ {
+ "ip":"10.0.2.3",
+ "via":"eth-rt3"
+ }
+ ]
+ },
+ "4.4.4.4":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.1",
+ "routerType":"asbr",
+ "nexthops":[
+ {
+ "ip":"10.0.3.4",
+ "via":"eth-rt4"
+ }
+ ]
+ },
+ "172.16.1.2\/32":{
+ "routeType":"N E2",
+ "cost":10,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.3.4",
+ "via":"eth-rt4"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf_nssa_topo1/rt2/step6/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt2/step6/show_ip_ospf_route.ref
new file mode 100644
index 0000000000..f6bbdfa594
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt2/step6/show_ip_ospf_route.ref
@@ -0,0 +1,103 @@
+{
+ "1.1.1.1\/32":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.1",
+ "via":"eth-rt1"
+ }
+ ]
+ },
+ "2.2.2.2\/32":{
+ "routeType":"N",
+ "cost":0,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"lo"
+ }
+ ]
+ },
+ "3.3.3.3\/32":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.3",
+ "via":"eth-rt3"
+ }
+ ]
+ },
+ "4.4.4.4\/32":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.4",
+ "via":"eth-rt4"
+ }
+ ]
+ },
+ "10.0.1.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt1"
+ }
+ ]
+ },
+ "10.0.2.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt3"
+ }
+ ]
+ },
+ "10.0.3.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt4"
+ }
+ ]
+ },
+ "3.3.3.3":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.1",
+ "routerType":"asbr",
+ "nexthops":[
+ {
+ "ip":"10.0.2.3",
+ "via":"eth-rt3"
+ }
+ ]
+ },
+ "4.4.4.4":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.1",
+ "routerType":"asbr",
+ "nexthops":[
+ {
+ "ip":"10.0.3.4",
+ "via":"eth-rt4"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf_nssa_topo1/rt2/step7/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt2/step7/show_ip_ospf_route.ref
new file mode 100644
index 0000000000..c7dd93c6e9
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt2/step7/show_ip_ospf_route.ref
@@ -0,0 +1,129 @@
+{
+ "1.1.1.1\/32":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.1",
+ "via":"eth-rt1"
+ }
+ ]
+ },
+ "2.2.2.2\/32":{
+ "routeType":"N",
+ "cost":0,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"lo"
+ }
+ ]
+ },
+ "3.3.3.3\/32":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.3",
+ "via":"eth-rt3"
+ }
+ ]
+ },
+ "4.4.4.4\/32":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.4",
+ "via":"eth-rt4"
+ }
+ ]
+ },
+ "10.0.1.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt1"
+ }
+ ]
+ },
+ "10.0.2.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt3"
+ }
+ ]
+ },
+ "10.0.3.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt4"
+ }
+ ]
+ },
+ "172.16.1.0\/24":{
+ },
+ "3.3.3.3":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.1",
+ "routerType":"asbr",
+ "nexthops":[
+ {
+ "ip":"10.0.2.3",
+ "via":"eth-rt3"
+ }
+ ]
+ },
+ "4.4.4.4":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.1",
+ "routerType":"asbr",
+ "nexthops":[
+ {
+ "ip":"10.0.3.4",
+ "via":"eth-rt4"
+ }
+ ]
+ },
+ "172.16.1.1\/32":{
+ "routeType":"N E2",
+ "cost":10,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.3.4",
+ "via":"eth-rt4"
+ }
+ ]
+ },
+ "172.16.1.2\/32":{
+ "routeType":"N E2",
+ "cost":10,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.3.4",
+ "via":"eth-rt4"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf_nssa_topo1/rt2/step8/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt2/step8/show_ip_ospf_route.ref
new file mode 100644
index 0000000000..c7dd93c6e9
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt2/step8/show_ip_ospf_route.ref
@@ -0,0 +1,129 @@
+{
+ "1.1.1.1\/32":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.1",
+ "via":"eth-rt1"
+ }
+ ]
+ },
+ "2.2.2.2\/32":{
+ "routeType":"N",
+ "cost":0,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"lo"
+ }
+ ]
+ },
+ "3.3.3.3\/32":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.3",
+ "via":"eth-rt3"
+ }
+ ]
+ },
+ "4.4.4.4\/32":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.4",
+ "via":"eth-rt4"
+ }
+ ]
+ },
+ "10.0.1.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt1"
+ }
+ ]
+ },
+ "10.0.2.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt3"
+ }
+ ]
+ },
+ "10.0.3.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt4"
+ }
+ ]
+ },
+ "172.16.1.0\/24":{
+ },
+ "3.3.3.3":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.1",
+ "routerType":"asbr",
+ "nexthops":[
+ {
+ "ip":"10.0.2.3",
+ "via":"eth-rt3"
+ }
+ ]
+ },
+ "4.4.4.4":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.1",
+ "routerType":"asbr",
+ "nexthops":[
+ {
+ "ip":"10.0.3.4",
+ "via":"eth-rt4"
+ }
+ ]
+ },
+ "172.16.1.1\/32":{
+ "routeType":"N E2",
+ "cost":10,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.3.4",
+ "via":"eth-rt4"
+ }
+ ]
+ },
+ "172.16.1.2\/32":{
+ "routeType":"N E2",
+ "cost":10,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.3.4",
+ "via":"eth-rt4"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf_nssa_topo1/rt2/step9/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt2/step9/show_ip_ospf_route.ref
new file mode 100644
index 0000000000..c09411741a
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt2/step9/show_ip_ospf_route.ref
@@ -0,0 +1,127 @@
+{
+ "1.1.1.1\/32":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":"10.0.1.1",
+ "via":"eth-rt1"
+ }
+ ]
+ },
+ "2.2.2.2\/32":{
+ "routeType":"N",
+ "cost":0,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"lo"
+ }
+ ]
+ },
+ "3.3.3.3\/32":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.3",
+ "via":"eth-rt3"
+ }
+ ]
+ },
+ "4.4.4.4\/32":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.4",
+ "via":"eth-rt4"
+ }
+ ]
+ },
+ "10.0.1.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.0",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt1"
+ }
+ ]
+ },
+ "10.0.2.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt3"
+ }
+ ]
+ },
+ "10.0.3.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt4"
+ }
+ ]
+ },
+ "3.3.3.3":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.1",
+ "routerType":"asbr",
+ "nexthops":[
+ {
+ "ip":"10.0.2.3",
+ "via":"eth-rt3"
+ }
+ ]
+ },
+ "4.4.4.4":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.1",
+ "routerType":"asbr",
+ "nexthops":[
+ {
+ "ip":"10.0.3.4",
+ "via":"eth-rt4"
+ }
+ ]
+ },
+ "172.16.1.1\/32":{
+ "routeType":"N E2",
+ "cost":10,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.3.4",
+ "via":"eth-rt4"
+ }
+ ]
+ },
+ "172.16.1.2\/32":{
+ "routeType":"N E2",
+ "cost":10,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.3.4",
+ "via":"eth-rt4"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf_nssa_topo1/rt2/zebra.conf b/tests/topotests/ospf_nssa_topo1/rt2/zebra.conf
new file mode 100644
index 0000000000..fa274ebade
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt2/zebra.conf
@@ -0,0 +1,24 @@
+log file zebra.log
+!
+hostname rt2
+!
+! debug zebra kernel
+! debug zebra packet
+! debug zebra mpls
+!
+interface lo
+ ip address 2.2.2.2/32
+!
+interface eth-rt1
+ ip address 10.0.1.2/24
+!
+interface eth-rt3
+ ip address 10.0.2.2/24
+!
+interface eth-rt4
+ ip address 10.0.3.2/24
+!
+ip forwarding
+!
+line vty
+!
diff --git a/tests/topotests/ospf_nssa_topo1/rt3/ospfd.conf b/tests/topotests/ospf_nssa_topo1/rt3/ospfd.conf
new file mode 100644
index 0000000000..9691a7c512
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt3/ospfd.conf
@@ -0,0 +1,24 @@
+password 1
+hostname rt3
+log file ospfd.log
+!
+! debug ospf sr
+! debug ospf te
+! debug ospf event
+! debug ospf lsa
+! debug ospf zebra
+!
+interface lo
+ ip ospf area 1
+!
+interface eth-rt2
+ ip ospf network point-to-point
+ ip ospf area 1
+ ip ospf hello-interval 3
+ ip ospf dead-interval 12
+!
+router ospf
+ router-id 3.3.3.3
+ area 1 nssa
+ redistribute connected
+!
diff --git a/tests/topotests/ospf_nssa_topo1/rt3/staticd.conf b/tests/topotests/ospf_nssa_topo1/rt3/staticd.conf
new file mode 100644
index 0000000000..f0edd6c9ca
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt3/staticd.conf
@@ -0,0 +1,8 @@
+log file staticd.log
+!
+hostname rt3
+!
+ip route 0.0.0.0/0 Null0
+!
+line vty
+!
diff --git a/tests/topotests/ospf_nssa_topo1/rt3/step1/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt3/step1/show_ip_ospf_route.ref
new file mode 100644
index 0000000000..a2d078ab13
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt3/step1/show_ip_ospf_route.ref
@@ -0,0 +1,138 @@
+{
+ "0.0.0.0\/0":{
+ "routeType":"N IA",
+ "cost":11,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "1.1.1.1\/32":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2\/32":{
+ "routeType":"N IA",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "3.3.3.3\/32":{
+ "routeType":"N",
+ "cost":0,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"lo"
+ }
+ ]
+ },
+ "4.4.4.4\/32":{
+ "routeType":"N",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.1.0\/24":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.2.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.3.0\/24":{
+ "routeType":"N",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.1",
+ "routerType":"abr",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "4.4.4.4":{
+ "routeType":"R ",
+ "cost":20,
+ "area":"0.0.0.1",
+ "routerType":"asbr",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.1\/32":{
+ "routeType":"N E2",
+ "cost":20,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.2\/32":{
+ "routeType":"N E2",
+ "cost":20,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf_nssa_topo1/rt3/step10/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt3/step10/show_ip_ospf_route.ref
new file mode 100644
index 0000000000..4619067abd
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt3/step10/show_ip_ospf_route.ref
@@ -0,0 +1,150 @@
+{
+ "0.0.0.0\/0":{
+ "routeType":"N IA",
+ "cost":11,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "1.1.1.1\/32":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2\/32":{
+ "routeType":"N IA",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "3.3.3.3\/32":{
+ "routeType":"N",
+ "cost":0,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"lo"
+ }
+ ]
+ },
+ "4.4.4.4\/32":{
+ "routeType":"N",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.1.0\/24":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.2.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.3.0\/24":{
+ "routeType":"N",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.1",
+ "routerType":"abr",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "4.4.4.4":{
+ "routeType":"R ",
+ "cost":20,
+ "area":"0.0.0.1",
+ "routerType":"asbr",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.0\/24":{
+ "routeType":"N E2",
+ "cost":10,
+ "type2cost":1000,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.1\/32":{
+ "routeType":"N E2",
+ "cost":20,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.2\/32":{
+ "routeType":"N E2",
+ "cost":20,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf_nssa_topo1/rt3/step2/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt3/step2/show_ip_ospf_route.ref
new file mode 100644
index 0000000000..a2d078ab13
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt3/step2/show_ip_ospf_route.ref
@@ -0,0 +1,138 @@
+{
+ "0.0.0.0\/0":{
+ "routeType":"N IA",
+ "cost":11,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "1.1.1.1\/32":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2\/32":{
+ "routeType":"N IA",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "3.3.3.3\/32":{
+ "routeType":"N",
+ "cost":0,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"lo"
+ }
+ ]
+ },
+ "4.4.4.4\/32":{
+ "routeType":"N",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.1.0\/24":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.2.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.3.0\/24":{
+ "routeType":"N",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.1",
+ "routerType":"abr",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "4.4.4.4":{
+ "routeType":"R ",
+ "cost":20,
+ "area":"0.0.0.1",
+ "routerType":"asbr",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.1\/32":{
+ "routeType":"N E2",
+ "cost":20,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.2\/32":{
+ "routeType":"N E2",
+ "cost":20,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf_nssa_topo1/rt3/step3/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt3/step3/show_ip_ospf_route.ref
new file mode 100644
index 0000000000..a2d078ab13
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt3/step3/show_ip_ospf_route.ref
@@ -0,0 +1,138 @@
+{
+ "0.0.0.0\/0":{
+ "routeType":"N IA",
+ "cost":11,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "1.1.1.1\/32":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2\/32":{
+ "routeType":"N IA",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "3.3.3.3\/32":{
+ "routeType":"N",
+ "cost":0,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"lo"
+ }
+ ]
+ },
+ "4.4.4.4\/32":{
+ "routeType":"N",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.1.0\/24":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.2.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.3.0\/24":{
+ "routeType":"N",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.1",
+ "routerType":"abr",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "4.4.4.4":{
+ "routeType":"R ",
+ "cost":20,
+ "area":"0.0.0.1",
+ "routerType":"asbr",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.1\/32":{
+ "routeType":"N E2",
+ "cost":20,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.2\/32":{
+ "routeType":"N E2",
+ "cost":20,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf_nssa_topo1/rt3/step4/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt3/step4/show_ip_ospf_route.ref
new file mode 100644
index 0000000000..10387215b2
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt3/step4/show_ip_ospf_route.ref
@@ -0,0 +1,150 @@
+{
+ "0.0.0.0\/0":{
+ "routeType":"N IA",
+ "cost":11,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "1.1.1.1\/32":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2\/32":{
+ "routeType":"N IA",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "3.3.3.3\/32":{
+ "routeType":"N",
+ "cost":0,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"lo"
+ }
+ ]
+ },
+ "4.4.4.4\/32":{
+ "routeType":"N",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.1.0\/24":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.2.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.3.0\/24":{
+ "routeType":"N",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.1",
+ "routerType":"abr",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "4.4.4.4":{
+ "routeType":"R ",
+ "cost":20,
+ "area":"0.0.0.1",
+ "routerType":"asbr",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.0\/24":{
+ "routeType":"N E2",
+ "cost":10,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.1\/32":{
+ "routeType":"N E2",
+ "cost":20,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.2\/32":{
+ "routeType":"N E2",
+ "cost":20,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf_nssa_topo1/rt3/step5/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt3/step5/show_ip_ospf_route.ref
new file mode 100644
index 0000000000..4f8eaf1eaa
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt3/step5/show_ip_ospf_route.ref
@@ -0,0 +1,138 @@
+{
+ "0.0.0.0\/0":{
+ "routeType":"N IA",
+ "cost":11,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "1.1.1.1\/32":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2\/32":{
+ "routeType":"N IA",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "3.3.3.3\/32":{
+ "routeType":"N",
+ "cost":0,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"lo"
+ }
+ ]
+ },
+ "4.4.4.4\/32":{
+ "routeType":"N",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.1.0\/24":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.2.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.3.0\/24":{
+ "routeType":"N",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.1",
+ "routerType":"abr",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "4.4.4.4":{
+ "routeType":"R ",
+ "cost":20,
+ "area":"0.0.0.1",
+ "routerType":"asbr",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.0\/24":{
+ "routeType":"N E2",
+ "cost":10,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.2\/32":{
+ "routeType":"N E2",
+ "cost":20,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf_nssa_topo1/rt3/step6/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt3/step6/show_ip_ospf_route.ref
new file mode 100644
index 0000000000..41e9f6718a
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt3/step6/show_ip_ospf_route.ref
@@ -0,0 +1,126 @@
+{
+ "0.0.0.0\/0":{
+ "routeType":"N IA",
+ "cost":11,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "1.1.1.1\/32":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2\/32":{
+ "routeType":"N IA",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "3.3.3.3\/32":{
+ "routeType":"N",
+ "cost":0,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"lo"
+ }
+ ]
+ },
+ "4.4.4.4\/32":{
+ "routeType":"N",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.1.0\/24":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.2.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.3.0\/24":{
+ "routeType":"N",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.1",
+ "routerType":"abr",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "4.4.4.4":{
+ "routeType":"R ",
+ "cost":20,
+ "area":"0.0.0.1",
+ "routerType":"asbr",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.0\/24":{
+ "routeType":"N E2",
+ "cost":10,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf_nssa_topo1/rt3/step7/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt3/step7/show_ip_ospf_route.ref
new file mode 100644
index 0000000000..10387215b2
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt3/step7/show_ip_ospf_route.ref
@@ -0,0 +1,150 @@
+{
+ "0.0.0.0\/0":{
+ "routeType":"N IA",
+ "cost":11,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "1.1.1.1\/32":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2\/32":{
+ "routeType":"N IA",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "3.3.3.3\/32":{
+ "routeType":"N",
+ "cost":0,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"lo"
+ }
+ ]
+ },
+ "4.4.4.4\/32":{
+ "routeType":"N",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.1.0\/24":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.2.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.3.0\/24":{
+ "routeType":"N",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.1",
+ "routerType":"abr",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "4.4.4.4":{
+ "routeType":"R ",
+ "cost":20,
+ "area":"0.0.0.1",
+ "routerType":"asbr",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.0\/24":{
+ "routeType":"N E2",
+ "cost":10,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.1\/32":{
+ "routeType":"N E2",
+ "cost":20,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.2\/32":{
+ "routeType":"N E2",
+ "cost":20,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf_nssa_topo1/rt3/step8/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt3/step8/show_ip_ospf_route.ref
new file mode 100644
index 0000000000..4619067abd
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt3/step8/show_ip_ospf_route.ref
@@ -0,0 +1,150 @@
+{
+ "0.0.0.0\/0":{
+ "routeType":"N IA",
+ "cost":11,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "1.1.1.1\/32":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2\/32":{
+ "routeType":"N IA",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "3.3.3.3\/32":{
+ "routeType":"N",
+ "cost":0,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"lo"
+ }
+ ]
+ },
+ "4.4.4.4\/32":{
+ "routeType":"N",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.1.0\/24":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.2.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.3.0\/24":{
+ "routeType":"N",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.1",
+ "routerType":"abr",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "4.4.4.4":{
+ "routeType":"R ",
+ "cost":20,
+ "area":"0.0.0.1",
+ "routerType":"asbr",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.0\/24":{
+ "routeType":"N E2",
+ "cost":10,
+ "type2cost":1000,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.1\/32":{
+ "routeType":"N E2",
+ "cost":20,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.2\/32":{
+ "routeType":"N E2",
+ "cost":20,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf_nssa_topo1/rt3/step9/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt3/step9/show_ip_ospf_route.ref
new file mode 100644
index 0000000000..4619067abd
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt3/step9/show_ip_ospf_route.ref
@@ -0,0 +1,150 @@
+{
+ "0.0.0.0\/0":{
+ "routeType":"N IA",
+ "cost":11,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "1.1.1.1\/32":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2\/32":{
+ "routeType":"N IA",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "3.3.3.3\/32":{
+ "routeType":"N",
+ "cost":0,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"lo"
+ }
+ ]
+ },
+ "4.4.4.4\/32":{
+ "routeType":"N",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.1.0\/24":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.2.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.3.0\/24":{
+ "routeType":"N",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.1",
+ "routerType":"abr",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "4.4.4.4":{
+ "routeType":"R ",
+ "cost":20,
+ "area":"0.0.0.1",
+ "routerType":"asbr",
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.0\/24":{
+ "routeType":"N E2",
+ "cost":10,
+ "type2cost":1000,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.1\/32":{
+ "routeType":"N E2",
+ "cost":20,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.2\/32":{
+ "routeType":"N E2",
+ "cost":20,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "via":"eth-rt2"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf_nssa_topo1/rt3/zebra.conf b/tests/topotests/ospf_nssa_topo1/rt3/zebra.conf
new file mode 100644
index 0000000000..d943540f3b
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt3/zebra.conf
@@ -0,0 +1,18 @@
+log file zebra.log
+!
+hostname rt3
+!
+! debug zebra kernel
+! debug zebra packet
+! debug zebra mpls
+!
+interface lo
+ ip address 3.3.3.3/32
+!
+interface eth-rt2
+ ip address 10.0.2.3/24
+!
+ip forwarding
+!
+line vty
+!
diff --git a/tests/topotests/ospf_nssa_topo1/rt4/ospfd.conf b/tests/topotests/ospf_nssa_topo1/rt4/ospfd.conf
new file mode 100644
index 0000000000..cba7cf71ed
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt4/ospfd.conf
@@ -0,0 +1,24 @@
+password 1
+hostname rt4
+log file ospfd.log
+!
+! debug ospf sr
+! debug ospf te
+! debug ospf event
+! debug ospf lsa
+! debug ospf zebra
+!
+interface lo
+ ip ospf area 1
+!
+interface eth-rt2
+ ip ospf network point-to-point
+ ip ospf area 1
+ ip ospf hello-interval 3
+ ip ospf dead-interval 12
+!
+router ospf
+ router-id 4.4.4.4
+ area 1 nssa
+ redistribute static
+!
diff --git a/tests/topotests/ospf_nssa_topo1/rt4/staticd.conf b/tests/topotests/ospf_nssa_topo1/rt4/staticd.conf
new file mode 100644
index 0000000000..e00ee5dfea
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt4/staticd.conf
@@ -0,0 +1,9 @@
+log file staticd.log
+!
+hostname rt4
+!
+ip route 172.16.1.1/32 Null0
+ip route 172.16.1.2/32 Null0
+!
+line vty
+!
diff --git a/tests/topotests/ospf_nssa_topo1/rt4/step1/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt4/step1/show_ip_ospf_route.ref
new file mode 100644
index 0000000000..e57f542f1c
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt4/step1/show_ip_ospf_route.ref
@@ -0,0 +1,114 @@
+{
+ "0.0.0.0\/0":{
+ "routeType":"N IA",
+ "cost":11,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "1.1.1.1\/32":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2\/32":{
+ "routeType":"N IA",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "3.3.3.3\/32":{
+ "routeType":"N",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "4.4.4.4\/32":{
+ "routeType":"N",
+ "cost":0,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"lo"
+ }
+ ]
+ },
+ "10.0.1.0\/24":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.2.0\/24":{
+ "routeType":"N",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.3.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.1",
+ "routerType":"abr",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "3.3.3.3":{
+ "routeType":"R ",
+ "cost":20,
+ "area":"0.0.0.1",
+ "routerType":"asbr",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf_nssa_topo1/rt4/step10/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt4/step10/show_ip_ospf_route.ref
new file mode 100644
index 0000000000..82a0e1a9b4
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt4/step10/show_ip_ospf_route.ref
@@ -0,0 +1,126 @@
+{
+ "0.0.0.0\/0":{
+ "routeType":"N IA",
+ "cost":11,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "1.1.1.1\/32":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2\/32":{
+ "routeType":"N IA",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "3.3.3.3\/32":{
+ "routeType":"N",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "4.4.4.4\/32":{
+ "routeType":"N",
+ "cost":0,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"lo"
+ }
+ ]
+ },
+ "10.0.1.0\/24":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.2.0\/24":{
+ "routeType":"N",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.3.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.1",
+ "routerType":"abr",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "3.3.3.3":{
+ "routeType":"R ",
+ "cost":20,
+ "area":"0.0.0.1",
+ "routerType":"asbr",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.0\/24":{
+ "routeType":"N E2",
+ "cost":10,
+ "type2cost":1000,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf_nssa_topo1/rt4/step2/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt4/step2/show_ip_ospf_route.ref
new file mode 100644
index 0000000000..e57f542f1c
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt4/step2/show_ip_ospf_route.ref
@@ -0,0 +1,114 @@
+{
+ "0.0.0.0\/0":{
+ "routeType":"N IA",
+ "cost":11,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "1.1.1.1\/32":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2\/32":{
+ "routeType":"N IA",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "3.3.3.3\/32":{
+ "routeType":"N",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "4.4.4.4\/32":{
+ "routeType":"N",
+ "cost":0,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"lo"
+ }
+ ]
+ },
+ "10.0.1.0\/24":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.2.0\/24":{
+ "routeType":"N",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.3.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.1",
+ "routerType":"abr",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "3.3.3.3":{
+ "routeType":"R ",
+ "cost":20,
+ "area":"0.0.0.1",
+ "routerType":"asbr",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf_nssa_topo1/rt4/step3/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt4/step3/show_ip_ospf_route.ref
new file mode 100644
index 0000000000..e57f542f1c
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt4/step3/show_ip_ospf_route.ref
@@ -0,0 +1,114 @@
+{
+ "0.0.0.0\/0":{
+ "routeType":"N IA",
+ "cost":11,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "1.1.1.1\/32":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2\/32":{
+ "routeType":"N IA",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "3.3.3.3\/32":{
+ "routeType":"N",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "4.4.4.4\/32":{
+ "routeType":"N",
+ "cost":0,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"lo"
+ }
+ ]
+ },
+ "10.0.1.0\/24":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.2.0\/24":{
+ "routeType":"N",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.3.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.1",
+ "routerType":"abr",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "3.3.3.3":{
+ "routeType":"R ",
+ "cost":20,
+ "area":"0.0.0.1",
+ "routerType":"asbr",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf_nssa_topo1/rt4/step4/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt4/step4/show_ip_ospf_route.ref
new file mode 100644
index 0000000000..5f51b3b3b8
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt4/step4/show_ip_ospf_route.ref
@@ -0,0 +1,126 @@
+{
+ "0.0.0.0\/0":{
+ "routeType":"N IA",
+ "cost":11,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "1.1.1.1\/32":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2\/32":{
+ "routeType":"N IA",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "3.3.3.3\/32":{
+ "routeType":"N",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "4.4.4.4\/32":{
+ "routeType":"N",
+ "cost":0,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"lo"
+ }
+ ]
+ },
+ "10.0.1.0\/24":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.2.0\/24":{
+ "routeType":"N",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.3.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.1",
+ "routerType":"abr",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "3.3.3.3":{
+ "routeType":"R ",
+ "cost":20,
+ "area":"0.0.0.1",
+ "routerType":"asbr",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.0\/24":{
+ "routeType":"N E2",
+ "cost":10,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf_nssa_topo1/rt4/step5/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt4/step5/show_ip_ospf_route.ref
new file mode 100644
index 0000000000..5f51b3b3b8
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt4/step5/show_ip_ospf_route.ref
@@ -0,0 +1,126 @@
+{
+ "0.0.0.0\/0":{
+ "routeType":"N IA",
+ "cost":11,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "1.1.1.1\/32":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2\/32":{
+ "routeType":"N IA",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "3.3.3.3\/32":{
+ "routeType":"N",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "4.4.4.4\/32":{
+ "routeType":"N",
+ "cost":0,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"lo"
+ }
+ ]
+ },
+ "10.0.1.0\/24":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.2.0\/24":{
+ "routeType":"N",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.3.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.1",
+ "routerType":"abr",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "3.3.3.3":{
+ "routeType":"R ",
+ "cost":20,
+ "area":"0.0.0.1",
+ "routerType":"asbr",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.0\/24":{
+ "routeType":"N E2",
+ "cost":10,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf_nssa_topo1/rt4/step6/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt4/step6/show_ip_ospf_route.ref
new file mode 100644
index 0000000000..5f51b3b3b8
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt4/step6/show_ip_ospf_route.ref
@@ -0,0 +1,126 @@
+{
+ "0.0.0.0\/0":{
+ "routeType":"N IA",
+ "cost":11,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "1.1.1.1\/32":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2\/32":{
+ "routeType":"N IA",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "3.3.3.3\/32":{
+ "routeType":"N",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "4.4.4.4\/32":{
+ "routeType":"N",
+ "cost":0,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"lo"
+ }
+ ]
+ },
+ "10.0.1.0\/24":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.2.0\/24":{
+ "routeType":"N",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.3.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.1",
+ "routerType":"abr",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "3.3.3.3":{
+ "routeType":"R ",
+ "cost":20,
+ "area":"0.0.0.1",
+ "routerType":"asbr",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.0\/24":{
+ "routeType":"N E2",
+ "cost":10,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf_nssa_topo1/rt4/step7/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt4/step7/show_ip_ospf_route.ref
new file mode 100644
index 0000000000..5f51b3b3b8
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt4/step7/show_ip_ospf_route.ref
@@ -0,0 +1,126 @@
+{
+ "0.0.0.0\/0":{
+ "routeType":"N IA",
+ "cost":11,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "1.1.1.1\/32":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2\/32":{
+ "routeType":"N IA",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "3.3.3.3\/32":{
+ "routeType":"N",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "4.4.4.4\/32":{
+ "routeType":"N",
+ "cost":0,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"lo"
+ }
+ ]
+ },
+ "10.0.1.0\/24":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.2.0\/24":{
+ "routeType":"N",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.3.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.1",
+ "routerType":"abr",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "3.3.3.3":{
+ "routeType":"R ",
+ "cost":20,
+ "area":"0.0.0.1",
+ "routerType":"asbr",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.0\/24":{
+ "routeType":"N E2",
+ "cost":10,
+ "type2cost":20,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf_nssa_topo1/rt4/step8/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt4/step8/show_ip_ospf_route.ref
new file mode 100644
index 0000000000..82a0e1a9b4
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt4/step8/show_ip_ospf_route.ref
@@ -0,0 +1,126 @@
+{
+ "0.0.0.0\/0":{
+ "routeType":"N IA",
+ "cost":11,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "1.1.1.1\/32":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2\/32":{
+ "routeType":"N IA",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "3.3.3.3\/32":{
+ "routeType":"N",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "4.4.4.4\/32":{
+ "routeType":"N",
+ "cost":0,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"lo"
+ }
+ ]
+ },
+ "10.0.1.0\/24":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.2.0\/24":{
+ "routeType":"N",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.3.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.1",
+ "routerType":"abr",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "3.3.3.3":{
+ "routeType":"R ",
+ "cost":20,
+ "area":"0.0.0.1",
+ "routerType":"asbr",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.0\/24":{
+ "routeType":"N E2",
+ "cost":10,
+ "type2cost":1000,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf_nssa_topo1/rt4/step9/show_ip_ospf_route.ref b/tests/topotests/ospf_nssa_topo1/rt4/step9/show_ip_ospf_route.ref
new file mode 100644
index 0000000000..82a0e1a9b4
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt4/step9/show_ip_ospf_route.ref
@@ -0,0 +1,126 @@
+{
+ "0.0.0.0\/0":{
+ "routeType":"N IA",
+ "cost":11,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "1.1.1.1\/32":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2\/32":{
+ "routeType":"N IA",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "3.3.3.3\/32":{
+ "routeType":"N",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "4.4.4.4\/32":{
+ "routeType":"N",
+ "cost":0,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"lo"
+ }
+ ]
+ },
+ "10.0.1.0\/24":{
+ "routeType":"N IA",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.2.0\/24":{
+ "routeType":"N",
+ "cost":20,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "10.0.3.0\/24":{
+ "routeType":"N",
+ "cost":10,
+ "area":"0.0.0.1",
+ "nexthops":[
+ {
+ "ip":" ",
+ "directlyAttachedTo":"eth-rt2"
+ }
+ ]
+ },
+ "2.2.2.2":{
+ "routeType":"R ",
+ "cost":10,
+ "area":"0.0.0.1",
+ "routerType":"abr",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "3.3.3.3":{
+ "routeType":"R ",
+ "cost":20,
+ "area":"0.0.0.1",
+ "routerType":"asbr",
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ },
+ "172.16.1.0\/24":{
+ "routeType":"N E2",
+ "cost":10,
+ "type2cost":1000,
+ "tag":0,
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "via":"eth-rt2"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf_nssa_topo1/rt4/zebra.conf b/tests/topotests/ospf_nssa_topo1/rt4/zebra.conf
new file mode 100644
index 0000000000..588febe70b
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/rt4/zebra.conf
@@ -0,0 +1,18 @@
+log file zebra.log
+!
+hostname rt4
+!
+! debug zebra kernel
+! debug zebra packet
+! debug zebra mpls
+!
+interface lo
+ ip address 4.4.4.4/32
+!
+interface eth-rt2
+ ip address 10.0.3.4/24
+!
+ip forwarding
+!
+line vty
+!
diff --git a/tests/topotests/ospf_nssa_topo1/test_ospf_nssa_topo1.py b/tests/topotests/ospf_nssa_topo1/test_ospf_nssa_topo1.py
new file mode 100644
index 0000000000..432ddf0986
--- /dev/null
+++ b/tests/topotests/ospf_nssa_topo1/test_ospf_nssa_topo1.py
@@ -0,0 +1,416 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: ISC
+
+#
+# test_ospf_nssa_topo1.py
+# Part of NetDEF Topology Tests
+#
+# Copyright (c) 2023 by
+# Network Device Education Foundation, Inc. ("NetDEF")
+#
+
+"""
+test_ospf_nssa_topo1.py:
+
+ +---------+
+ | RT1 |
+ | 1.1.1.1 |
+ +---------+
+ |eth-rt2
+ |
+ |10.0.1.0/24
+ |
+ |eth-rt1
+ +---------+
+ | RT2 |
+ | 2.2.2.2 |
+ +---------+
+ eth-rt3| |eth-rt4
+ | |
+ 10.0.2.0/24 | | 10.0.3.0/24
+ +---------+ +--------+
+ | |
+ |eth-rt2 |eth-rt2
+ +---------+ +---------+
+ | RT3 | | RT4 |
+ | 3.3.3.3 | | 4.4.4.4 |
+ +---------+ +---------+
+
+"""
+
+import os
+import sys
+import pytest
+import json
+from functools import partial
+
+# 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
+from lib.topolog import logger
+
+# Required to instantiate the topology builder class.
+
+pytestmark = [pytest.mark.ospfd]
+
+
+def build_topo(tgen):
+ "Build function"
+
+ #
+ # Define FRR Routers
+ #
+ for router in ["rt1", "rt2", "rt3", "rt4"]:
+ tgen.add_router(router)
+
+ #
+ # Define connections
+ #
+ switch = tgen.add_switch("s1")
+ switch.add_link(tgen.gears["rt1"], nodeif="eth-rt2")
+ switch.add_link(tgen.gears["rt2"], nodeif="eth-rt1")
+
+ switch = tgen.add_switch("s2")
+ switch.add_link(tgen.gears["rt2"], nodeif="eth-rt3")
+ switch.add_link(tgen.gears["rt3"], nodeif="eth-rt2")
+
+ switch = tgen.add_switch("s3")
+ switch.add_link(tgen.gears["rt2"], nodeif="eth-rt4")
+ switch.add_link(tgen.gears["rt4"], nodeif="eth-rt2")
+
+
+def setup_module(mod):
+ "Sets up the pytest environment"
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ # For all registered routers, load the zebra 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_STATIC, os.path.join(CWD, "{}/staticd.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()
+
+ # This function tears down the whole topology.
+ tgen.stop_topology()
+
+
+def print_cmd_result(rname, command):
+ print(get_topogen().gears[rname].vtysh_cmd(command, isjson=False))
+
+
+def router_compare_json_output(rname, command, reference):
+ "Compare router JSON output"
+
+ logger.info('Comparing router "%s" "%s" output', rname, command)
+
+ tgen = get_topogen()
+ filename = "{}/{}/{}".format(CWD, rname, reference)
+ expected = json.loads(open(filename).read())
+
+ # Run test function until we get an result. Wait at most 60 seconds.
+ test_func = partial(topotest.router_json_cmp, tgen.gears[rname], command, expected)
+ _, diff = topotest.run_and_expect(test_func, None, count=120, wait=0.5)
+ assertmsg = '"{}" JSON output mismatches the expected result'.format(rname)
+ assert diff is None, assertmsg
+
+
+#
+# Step 1
+#
+# Test initial network convergence
+#
+def test_rib_step1():
+ logger.info("Test (step 1): test initial network convergence")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ for rname in ["rt1", "rt2", "rt3", "rt4"]:
+ router_compare_json_output(
+ rname, "show ip ospf route json", "step1/show_ip_ospf_route.ref"
+ )
+
+
+#
+# Step 2
+#
+# Action(s):
+# -rt3: configure an NSSA default route
+#
+# Expected changes:
+# -rt2: add NSSA default route pointing to rt3
+#
+def test_rib_step2():
+ logger.info("Test (step 2): verify OSPF routes")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Adding NSSA default on rt4")
+ tgen.net["rt3"].cmd(
+ 'vtysh -c "conf t" -c "router ospf" -c "area 1 nssa default-information-originate"'
+ )
+
+ for rname in ["rt1", "rt2", "rt3", "rt4"]:
+ router_compare_json_output(
+ rname, "show ip ospf route json", "step2/show_ip_ospf_route.ref"
+ )
+
+
+#
+# Step 3
+#
+# Action(s):
+# -rt3: remove NSSA default route
+#
+# Expected changes:
+# -rt2: remove NSSA default route
+#
+def test_rib_step3():
+ logger.info("Test (step 3): verify OSPF routes")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Removing NSSA default on rt4")
+ tgen.net["rt3"].cmd(
+ 'vtysh -c "conf t" -c "router ospf" -c "area 1 nssa"'
+ )
+
+ for rname in ["rt1", "rt2", "rt3", "rt4"]:
+ router_compare_json_output(
+ rname, "show ip ospf route json", "step3/show_ip_ospf_route.ref"
+ )
+
+
+#
+# Step 4
+#
+# Action(s):
+# -rt2: configure an NSSA range for 172.16.1.0/24
+#
+# Expected changes:
+# -rt1: the 172.16.1.1/32 and 172.16.1.2/32 routes should be removed
+# -rt1: the 172.16.1.0/24 route should be added
+#
+def test_rib_step4():
+ logger.info("Test (step 4): verify OSPF routes")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Configuring NSSA range on rt2")
+ tgen.net["rt2"].cmd(
+ 'vtysh -c "conf t" -c "router ospf" -c "area 1 nssa range 172.16.1.0/24"'
+ )
+
+ for rname in ["rt1", "rt2", "rt3", "rt4"]:
+ router_compare_json_output(
+ rname, "show ip ospf route json", "step4/show_ip_ospf_route.ref"
+ )
+
+
+#
+# Step 5
+#
+# Action(s):
+# -rt4: remove the 172.16.1.1/32 static route
+#
+# Expected changes:
+# -None (the 172.16.1.0/24 range is still active because of 172.16.1.2/32)
+#
+def test_rib_step5():
+ logger.info("Test (step 5): verify OSPF routes")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Removing first static route in rt4")
+ tgen.net["rt4"].cmd('vtysh -c "conf t" -c "no ip route 172.16.1.1/32 Null0"')
+
+ for rname in ["rt1", "rt2", "rt3", "rt4"]:
+ router_compare_json_output(
+ rname, "show ip ospf route json", "step5/show_ip_ospf_route.ref"
+ )
+
+
+#
+# Step 6
+#
+# Action(s):
+# -rt4: remove the 172.16.1.2/32 static route
+#
+# Expected changes:
+# -rt1: remove the 172.16.1.0/24 route since the NSSA range is no longer active
+#
+def test_rib_step6():
+ logger.info("Test (step 6): verify OSPF routes")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Removing second static route in rt4")
+ tgen.net["rt4"].cmd('vtysh -c "conf t" -c "no ip route 172.16.1.2/32 Null0"')
+
+ for rname in ["rt1", "rt2", "rt3", "rt4"]:
+ router_compare_json_output(
+ rname, "show ip ospf route json", "step6/show_ip_ospf_route.ref"
+ )
+
+
+#
+# Step 7
+#
+# Action(s):
+# -rt4: readd the 172.16.1.1/32 and 172.16.1.2/32 static routes
+#
+# Expected changes:
+# -rt1: readd the 172.16.1.0/24 route since the NSSA range is active again
+#
+def test_rib_step7():
+ logger.info("Test (step 7): verify OSPF routes")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Readding static routes in rt4")
+ tgen.net["rt4"].cmd('vtysh -c "conf t" -c "ip route 172.16.1.1/32 Null0"')
+ tgen.net["rt4"].cmd('vtysh -c "conf t" -c "ip route 172.16.1.2/32 Null0"')
+
+ for rname in ["rt1", "rt2", "rt3", "rt4"]:
+ router_compare_json_output(
+ rname, "show ip ospf route json", "step7/show_ip_ospf_route.ref"
+ )
+
+
+#
+# Step 8
+#
+# Action(s):
+# -rt2: update the NSSA range with a static cost
+#
+# Expected changes:
+# -rt1: update the metric of the 172.16.1.0/24 route from 20 to 1000
+#
+def test_rib_step8():
+ logger.info("Test (step 8): verify OSPF routes")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Updating the NSSA range cost on rt2")
+ tgen.net["rt2"].cmd(
+ 'vtysh -c "conf t" -c "router ospf" -c "area 1 nssa range 172.16.1.0/24 cost 1000"'
+ )
+
+ for rname in ["rt1", "rt2", "rt3", "rt4"]:
+ router_compare_json_output(
+ rname, "show ip ospf route json", "step8/show_ip_ospf_route.ref"
+ )
+
+
+#
+# Step 9
+#
+# Action(s):
+# -rt2: update the NSSA range to not advertise itself
+#
+# Expected changes:
+# -rt1: the 172.16.1.0/24 route should be removed
+#
+def test_rib_step9():
+ logger.info("Test (step 9): verify OSPF routes")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Updating the NSSA range to not advertise itself")
+ tgen.net["rt2"].cmd(
+ 'vtysh -c "conf t" -c "router ospf" -c "area 1 nssa range 172.16.1.0/24 not-advertise"'
+ )
+
+ for rname in ["rt1", "rt2", "rt3", "rt4"]:
+ router_compare_json_output(
+ rname, "show ip ospf route json", "step9/show_ip_ospf_route.ref"
+ )
+
+
+#
+# Step 10
+#
+# Action(s):
+# -rt2: remove the NSSA range
+#
+# Expected changes:
+# -rt1: the 172.16.1.1/32 and 172.16.1.2/32 routes should be added
+#
+def test_rib_step10():
+ logger.info("Test (step 10): verify OSPF routes")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Removing NSSA range on rt2")
+ tgen.net["rt2"].cmd(
+ 'vtysh -c "conf t" -c "router ospf" -c "no area 1 nssa range 172.16.1.0/24"'
+ )
+
+ for rname in ["rt1", "rt2", "rt3", "rt4"]:
+ router_compare_json_output(
+ rname, "show ip ospf route json", "step10/show_ip_ospf_route.ref"
+ )
+
+
+# Memory leak test template
+def test_memory_leak():
+ "Run the memory leak test and report results."
+ tgen = get_topogen()
+ if not tgen.is_memleak_enabled():
+ pytest.skip("Memory leak test/report is disabled")
+
+ tgen.report_memory_leaks()
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.py b/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.py
index 5b1a53b895..d5583ac06a 100644
--- a/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.py
+++ b/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.py
@@ -111,9 +111,7 @@ def ospf_unconfigure_suppress_fa(router_name, area):
tgen = get_topogen()
router = tgen.gears[router_name]
- router.vtysh_cmd(
- "conf t\nrouter ospf\nno area {} nssa suppress-fa\nexit\n".format(area)
- )
+ router.vtysh_cmd("conf t\nrouter ospf\narea {} nssa\nexit\n".format(area))
def ospf_get_lsa_type5(router_name):
diff --git a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_single_area.py b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_single_area.py
index 6f23294a1a..7199f160fe 100644
--- a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_single_area.py
+++ b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_single_area.py
@@ -1079,53 +1079,6 @@ def test_ospfv3_show_p1(request):
result = create_debug_log_config(tgen, input_dict)
- # Code coverage steps #Do Not upstream
- input_dict_config = {
- "r1": {
- "raw_config": [
- "end",
- "debug ospf6 event",
- "debug ospf6 gr helper",
- "debug ospf6 ism events",
- "debug ospf6 ism status",
- "debug ospf6 ism timers",
- "debug ospf6 nsm events",
- "debug ospf6 nsm status",
- "debug ospf6 nsm timers ",
- "debug ospf6 nssa",
- "debug ospf6 lsa aggregate",
- "debug ospf6 lsa flooding ",
- "debug ospf6 lsa generate",
- "debug ospf6 lsa install ",
- "debug ospf6 lsa refresh",
- "debug ospf6 packet all detail",
- "debug ospf6 packet all recv",
- "debug ospf6 packet all send",
- "debug ospf6 packet dd detail",
- "debug ospf6 packet dd recv",
- "debug ospf6 packet dd send ",
- "debug ospf6 packet hello detail",
- "debug ospf6 packet hello recv",
- "debug ospf6 packet hello send",
- "debug ospf6 packet ls-ack detail",
- "debug ospf6 packet ls-ack recv",
- "debug ospf6 packet ls-ack send",
- "debug ospf6 packet ls-request detail",
- "debug ospf6 packet ls-request recv",
- "debug ospf6 packet ls-request send",
- "debug ospf6 packet ls-update detail",
- "debug ospf6 packet ls-update recv",
- "debug ospf6 packet ls-update send",
- "debug ospf6 sr",
- "debug ospf6 te ",
- "debug ospf6 zebra interface",
- "debug ospf6 zebra redistribute",
- ]
- }
- }
-
- apply_raw_config(tgen, input_dict_config)
-
for rtr in topo["routers"]:
clear_ospf(tgen, rtr, ospf="ospf6")
diff --git a/tests/topotests/rip_allow_ecmp/__init__.py b/tests/topotests/rip_allow_ecmp/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/rip_allow_ecmp/__init__.py
diff --git a/tests/topotests/rip_allow_ecmp/r1/frr.conf b/tests/topotests/rip_allow_ecmp/r1/frr.conf
new file mode 100644
index 0000000000..d8eb9a31d3
--- /dev/null
+++ b/tests/topotests/rip_allow_ecmp/r1/frr.conf
@@ -0,0 +1,9 @@
+!
+int r1-eth0
+ ip address 192.168.1.1/24
+!
+router rip
+ allow-ecmp
+ network 192.168.1.0/24
+ timers basic 5 15 10
+exit
diff --git a/tests/topotests/rip_allow_ecmp/r2/frr.conf b/tests/topotests/rip_allow_ecmp/r2/frr.conf
new file mode 100644
index 0000000000..d7ea6f3102
--- /dev/null
+++ b/tests/topotests/rip_allow_ecmp/r2/frr.conf
@@ -0,0 +1,13 @@
+!
+int lo
+ ip address 10.10.10.1/32
+!
+int r2-eth0
+ ip address 192.168.1.2/24
+!
+router rip
+ network 192.168.1.0/24
+ network 10.10.10.1/32
+ timers basic 5 15 10
+exit
+
diff --git a/tests/topotests/rip_allow_ecmp/r3/frr.conf b/tests/topotests/rip_allow_ecmp/r3/frr.conf
new file mode 100644
index 0000000000..2362c47b84
--- /dev/null
+++ b/tests/topotests/rip_allow_ecmp/r3/frr.conf
@@ -0,0 +1,13 @@
+!
+int lo
+ ip address 10.10.10.1/32
+!
+int r3-eth0
+ ip address 192.168.1.3/24
+!
+router rip
+ network 192.168.1.0/24
+ network 10.10.10.1/32
+ timers basic 5 15 10
+exit
+
diff --git a/tests/topotests/rip_allow_ecmp/test_rip_allow_ecmp.py b/tests/topotests/rip_allow_ecmp/test_rip_allow_ecmp.py
new file mode 100644
index 0000000000..b0ba146984
--- /dev/null
+++ b/tests/topotests/rip_allow_ecmp/test_rip_allow_ecmp.py
@@ -0,0 +1,124 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: ISC
+
+# Copyright (c) 2023 by
+# Donatas Abraitis <donatas@opensourcerouting.org>
+#
+
+"""
+Test if RIP `allow-ecmp` command works correctly.
+"""
+
+import os
+import sys
+import json
+import pytest
+import functools
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+
+pytestmark = [pytest.mark.ripd]
+
+
+def setup_module(mod):
+ topodef = {"s1": ("r1", "r2", "r3")}
+ tgen = Topogen(topodef, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ for _, (rname, router) in enumerate(router_list.items(), 1):
+ router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname)))
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_rip_allow_ecmp():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r1 = tgen.gears["r1"]
+
+ def _show_rip_routes():
+ output = json.loads(
+ r1.vtysh_cmd("show yang operational-data /frr-ripd:ripd ripd")
+ )
+ try:
+ output = output["frr-ripd:ripd"]["instance"][0]["state"]["routes"]
+ except KeyError:
+ return False
+
+ expected = {
+ "route": [
+ {
+ "prefix": "10.10.10.1/32",
+ "nexthops": {
+ "nexthop": [
+ {
+ "nh-type": "ip4",
+ "protocol": "rip",
+ "rip-type": "normal",
+ "gateway": "192.168.1.2",
+ "from": "192.168.1.2",
+ "tag": 0,
+ },
+ {
+ "nh-type": "ip4",
+ "protocol": "rip",
+ "rip-type": "normal",
+ "gateway": "192.168.1.3",
+ "from": "192.168.1.3",
+ "tag": 0,
+ },
+ ]
+ },
+ "metric": 2,
+ },
+ ]
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_show_rip_routes)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assert result is None, "Can't see 10.10.10.1/32 as multipath in `show ip rip`"
+
+ def _show_routes():
+ output = json.loads(r1.vtysh_cmd("show ip route json"))
+ expected = {
+ "10.10.10.1/32": [
+ {
+ "nexthops": [
+ {
+ "ip": "192.168.1.2",
+ "active": True,
+ },
+ {
+ "ip": "192.168.1.3",
+ "active": True,
+ },
+ ]
+ }
+ ]
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_show_routes)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assert result is None, "Can't see 10.10.10.1/32 as multipath in `show ip route`"
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/zebra_rib/test_zebra_rib.py b/tests/topotests/zebra_rib/test_zebra_rib.py
index 6137471ea6..e2863218b0 100644
--- a/tests/topotests/zebra_rib/test_zebra_rib.py
+++ b/tests/topotests/zebra_rib/test_zebra_rib.py
@@ -51,7 +51,8 @@ def config_macvlan(tgen, r_str, device, macvlan):
def setup_module(mod):
"Sets up the pytest environment"
- topodef = {"s1": ("r1", "r1", "r1", "r1", "r1", "r1", "r1", "r1")}
+ # 8 links to 8 switches on r1
+ topodef = {"s{}".format(x): ("r1",) for x in range(1, 9)}
tgen = Topogen(topodef, mod.__name__)
tgen.start_topology()
diff --git a/yang/frr-ripd.yang b/yang/frr-ripd.yang
index 746bf35d28..24fe588854 100644
--- a/yang/frr-ripd.yang
+++ b/yang/frr-ripd.yang
@@ -13,6 +13,9 @@ module frr-ripd {
import frr-interface {
prefix frr-interface;
}
+ import frr-nexthop {
+ prefix frr-nexthop;
+ }
import frr-vrf {
prefix frr-vrf;
}
@@ -60,6 +63,7 @@ module frr-ripd {
description
"Changed interface references to use
frr-interface:interface-ref typedef";
+ reference "FRRouting";
}
revision 2017-12-06 {
description
@@ -69,10 +73,35 @@ module frr-ripd {
RFC 2453: RIP Version 2.";
}
+ typedef rip-route-type {
+ type enumeration {
+ enum normal {
+ value 0;
+ description "Normal RIP route type.";
+ }
+ enum static {
+ value 1;
+ description "Static RIP route type.";
+ }
+ enum default {
+ value 2;
+ description "Default RIP route type.";
+ }
+ enum redistribute {
+ value 3;
+ description "Redistribute RIP route type.";
+ }
+ enum interface {
+ value 4;
+ description "Interface RIP route type.";
+ }
+ }
+ description
+ "Types of RIP routes.";
+ }
+
container ripd {
- /*
- * Routing instance configuration.
- */
+ description "rip routing instance data";
list instance {
key "vrf";
description
@@ -229,9 +258,9 @@ module frr-ripd {
"Redistributes routes learned from other routing protocols.";
leaf protocol {
type frr-route-types:frr-route-types-v4;
+ must '. != "rip"';
description
"Routing protocol.";
- must '. != "rip"';
}
leaf route-map {
type frr-route-map:route-map-ref;
@@ -291,11 +320,8 @@ module frr-ripd {
}
}
container version {
+ description "version of rip";
leaf receive {
- must
- '(. = "1" and ../send = "1") or ' +
- '(. = "2" and ../send = "2") or ' +
- '(. = "1-2" and ../send = "2")';
type enumeration {
enum "1" {
value 1;
@@ -313,15 +339,15 @@ module frr-ripd {
"Accept both RIPv1 and RIPv2 updates.";
}
}
+ must
+ '(. = "1" and ../send = "1") or ' +
+ '(. = "2" and ../send = "2") or ' +
+ '(. = "1-2" and ../send = "2")';
default "1-2";
description
"Advertisement reception - Version control.";
}
leaf send {
- must
- '(../receive = "1" and . = "1") or ' +
- '(../receive = "2" and . = "2") or ' +
- '(../receive = "1-2" and . = "2")';
type enumeration {
enum "1" {
value 1;
@@ -334,6 +360,10 @@ module frr-ripd {
"Send RIPv2 updates only.";
}
}
+ must
+ '(../receive = "1" and . = "1") or ' +
+ '(../receive = "2" and . = "2") or ' +
+ '(../receive = "1-2" and . = "2")';
default "2";
description
"Advertisement transmission - Version control.";
@@ -399,23 +429,81 @@ module frr-ripd {
separated by the slash (/) character. The range of
values for the prefix-length is 0 to 32.";
}
+ container nexthops {
+ description "container of nexthops";
+ list nexthop {
+ description "A list of nexthop objects.";
+ leaf nh-type {
+ type frr-nexthop:nexthop-type;
+ mandatory true;
+ description
+ "The nexthop type.";
+ }
+ leaf protocol {
+ type frr-route-types:frr-route-types-v4;
+ description
+ "The protocol originating this route.";
+ }
+ leaf rip-type {
+ type rip-route-type;
+ description
+ "The RIP type of route.";
+ }
+ leaf gateway {
+ type inet:ipv4-address;
+ description
+ "The nexthop gateway address.";
+ }
+ leaf interface {
+ type frr-interface:interface-ref;
+ description
+ "The nexthop egress interface.";
+ }
+ leaf from {
+ type inet:ipv4-address;
+ description
+ "The nexthop gateway address.";
+ }
+ leaf tag {
+ type uint32;
+ default "0";
+ description
+ "Route tag";
+ }
+ leaf external-metric {
+ type uint32;
+ description
+ "External metric if learned from external protocol.";
+ }
+ leaf expire-time {
+ type uint32;
+ description
+ "Seconds before route expires.";
+ }
+ }
+ }
+ leaf metric {
+ type uint8 {
+ range "0..16";
+ }
+ description
+ "Route metric.";
+ }
+ /*
+ * Replaced by container `nexthops` above.
+ */
leaf next-hop {
type inet:ipv4-address;
+ status deprecated;
description
"Next hop IPv4 address.";
}
leaf interface {
type frr-interface:interface-ref;
+ status deprecated;
description
"The interface that the route uses.";
}
- leaf metric {
- type uint8 {
- range "0..16";
- }
- description
- "Route metric.";
- }
}
}
}
@@ -426,6 +514,7 @@ module frr-ripd {
* Per-interface configuration data
*/
augment "/frr-interface:lib/frr-interface:interface" {
+ description "rip interface data";
container rip {
description
"RIP interface parameters.";
diff --git a/zebra/dpdk/zebra_dplane_dpdk.c b/zebra/dpdk/zebra_dplane_dpdk.c
index b13daa3a97..fc140b07a3 100644
--- a/zebra/dpdk/zebra_dplane_dpdk.c
+++ b/zebra/dpdk/zebra_dplane_dpdk.c
@@ -645,7 +645,7 @@ static int zd_dpdk_init(void)
zd_dpdk_vty_init();
frr_with_privs (&zserv_privs) {
- rc = rte_eal_init(ARRAY_SIZE(argv), argv);
+ rc = rte_eal_init(array_size(argv), argv);
}
if (rc < 0) {
zlog_warn("EAL init failed %s", rte_strerror(rte_errno));
diff --git a/zebra/main.c b/zebra/main.c
index ba43ae910b..81a3066445 100644
--- a/zebra/main.c
+++ b/zebra/main.c
@@ -175,11 +175,6 @@ static void sigint(void)
if (zrouter.lsp_process_q)
work_queue_free_and_null(&zrouter.lsp_process_q);
- vrf_terminate();
-
- ns_walk_func(zebra_ns_early_shutdown, NULL, NULL);
- zebra_ns_notify_close();
-
access_list_reset();
prefix_list_reset();
/*
@@ -190,6 +185,8 @@ static void sigint(void)
*/
zebra_routemap_finish();
+ rib_update_finish();
+
list_delete(&zrouter.client_list);
/* Indicate that all new dplane work has been enqueued. When that
@@ -207,6 +204,11 @@ void zebra_finalize(struct event *dummy)
{
zlog_info("Zebra final shutdown");
+ vrf_terminate();
+
+ ns_walk_func(zebra_ns_early_shutdown, NULL, NULL);
+ zebra_ns_notify_close();
+
/* Stop dplane thread and finish any cleanup */
zebra_dplane_shutdown();
diff --git a/zebra/rib.h b/zebra/rib.h
index 0e897881e4..a56bb05d68 100644
--- a/zebra/rib.h
+++ b/zebra/rib.h
@@ -180,7 +180,7 @@ struct route_entry {
* sub-queue 9: any other origin (if any) typically those that
* don't generate routes
*/
-#define MQ_SIZE 10
+#define MQ_SIZE 11
struct meta_queue {
struct list *subq[MQ_SIZE];
uint32_t size; /* sum of lengths of all subqueues */
@@ -323,6 +323,7 @@ enum rib_update_event {
RIB_UPDATE_OTHER,
RIB_UPDATE_MAX
};
+void rib_update_finish(void);
int route_entry_update_nhe(struct route_entry *re,
struct nhg_hash_entry *new_nhghe);
@@ -601,6 +602,12 @@ static inline struct nexthop_group *rib_get_fib_backup_nhg(
return &(re->fib_backup_ng);
}
+extern void zebra_gr_process_client(afi_t afi, vrf_id_t vrf_id, uint8_t proto,
+ uint8_t instance);
+
+extern int rib_add_gr_run(afi_t afi, vrf_id_t vrf_id, uint8_t proto,
+ uint8_t instance);
+
extern void zebra_vty_init(void);
extern pid_t pid;
diff --git a/zebra/zebra_gr.c b/zebra/zebra_gr.c
index 96d598f7c4..cf2056b7ac 100644
--- a/zebra/zebra_gr.c
+++ b/zebra/zebra_gr.c
@@ -42,8 +42,8 @@ static struct zserv *zebra_gr_find_stale_client(struct zserv *client);
static void zebra_gr_route_stale_delete_timer_expiry(struct event *thread);
static int32_t zebra_gr_delete_stale_routes(struct client_gr_info *info);
static void zebra_gr_process_client_stale_routes(struct zserv *client,
- vrf_id_t vrf_id);
-
+ struct client_gr_info *info);
+static void zebra_gr_delete_stale_route_table_afi(struct event *event);
/*
* Debug macros.
*/
@@ -53,7 +53,6 @@ static void zebra_gr_process_client_stale_routes(struct zserv *client,
zlog_debug(msg, ##__VA_ARGS__); \
} while (0)
-
/*
* Client connection functions
*/
@@ -82,11 +81,12 @@ void zebra_gr_stale_client_cleanup(struct list *client_list)
if (info->t_stale_removal != NULL) {
EVENT_OFF(info->t_stale_removal);
info->t_stale_removal = NULL;
+ info->do_delete = true;
/* Process the stale routes */
event_execute(
zrouter.master,
zebra_gr_route_stale_delete_timer_expiry,
- info, 1);
+ info, 0);
}
}
}
@@ -101,6 +101,8 @@ static struct client_gr_info *zebra_gr_client_info_create(struct zserv *client)
info = XCALLOC(MTYPE_ZEBRA_GR, sizeof(struct client_gr_info));
+ info->stale_client_ptr = client;
+
TAILQ_INSERT_TAIL(&(client->gr_info_queue), info, gr_info);
return info;
}
@@ -108,8 +110,8 @@ static struct client_gr_info *zebra_gr_client_info_create(struct zserv *client)
/*
* A helper function to delete and destroy client info.
*/
-static void zebra_gr_client_info_delte(struct zserv *client,
- struct client_gr_info *info)
+static void zebra_gr_client_info_delete(struct zserv *client,
+ struct client_gr_info *info)
{
struct vrf *vrf = vrf_lookup_by_id(info->vrf_id);
@@ -117,8 +119,6 @@ static void zebra_gr_client_info_delte(struct zserv *client,
EVENT_OFF(info->t_stale_removal);
- XFREE(MTYPE_ZEBRA_GR, info->current_prefix);
-
LOG_GR("%s: Instance info is being deleted for client %s vrf %s(%u)",
__func__, zebra_route_string(client->proto), VRF_LOGNAME(vrf),
info->vrf_id);
@@ -164,7 +164,6 @@ int32_t zebra_gr_client_disconnect(struct zserv *client)
zebra_gr_route_stale_delete_timer_expiry, info,
info->stale_removal_time,
&info->t_stale_removal);
- info->current_afi = AFI_IP;
info->stale_client_ptr = client;
info->stale_client = true;
LOG_GR("%s: Client %s vrf %s(%u) Stale timer update to %d",
@@ -287,31 +286,65 @@ void zebra_gr_client_reconnect(struct zserv *client)
zserv_client_delete(old_client);
}
+struct zebra_gr_afi_clean {
+ struct client_gr_info *info;
+ afi_t afi;
+ uint8_t proto;
+ uint8_t instance;
+
+ struct event *t_gac;
+};
+
/*
* Functions to deal with capabilities
*/
/*
- * Update the graceful restart information
- * for the client instance.
- * This function handles all the capabilities that are received.
+ * Function to decode and call appropriate functions
+ * to handle client capabilities.
*/
-static void zebra_client_update_info(struct zserv *client, struct zapi_cap *api)
+void zread_client_capabilities(ZAPI_HANDLER_ARGS)
{
+ struct zapi_cap api;
struct client_gr_info *info = NULL;
+ struct stream *s;
+ struct vrf *vrf;
+
+ s = msg;
+
+ if (zapi_capabilities_decode(s, &api)) {
+ LOG_GR("%s: Error in reading capabilities for client %s",
+ __func__, zebra_route_string(client->proto));
+ return;
+ }
+
+ vrf = vrf_lookup_by_id(api.vrf_id);
+
+ /*
+ * If this ever matters uncomment and add safi to the
+ * arrays as needed to track
+ */
+ if (api.safi != SAFI_UNICAST)
+ return;
+
+ /* GR only for dynamic clients */
+ if (client->proto <= ZEBRA_ROUTE_CONNECT) {
+ LOG_GR("%s: GR capabilities for client %s not supported",
+ __func__, zebra_route_string(client->proto));
+ return;
+ }
/* Find the bgp information for the specified vrf id */
TAILQ_FOREACH (info, &client->gr_info_queue, gr_info) {
- if (info->vrf_id == api->vrf_id)
+ if (info->vrf_id == api.vrf_id)
break;
}
-
/*
* If the command is delete, then cancel the stale timer and
* delete the bgp info
*/
- switch (api->cap) {
+ switch (api.cap) {
case ZEBRA_CLIENT_GR_DISABLE:
if (!info)
return;
@@ -323,7 +356,7 @@ static void zebra_client_update_info(struct zserv *client, struct zapi_cap *api)
if ((info->gr_enable) && (client->gr_instance_count > 0))
client->gr_instance_count--;
- zebra_gr_client_info_delte(client, info);
+ zebra_gr_client_info_delete(client, info);
break;
case ZEBRA_CLIENT_GR_CAPABILITIES:
/* Allocate bgp info */
@@ -332,18 +365,16 @@ static void zebra_client_update_info(struct zserv *client, struct zapi_cap *api)
/* Update other parameters */
if (!info->gr_enable) {
- struct vrf *vrf = vrf_lookup_by_id(api->vrf_id);
-
client->gr_instance_count++;
LOG_GR("%s: Cient %s vrf %s(%u) GR enabled count %d",
__func__, zebra_route_string(client->proto),
- VRF_LOGNAME(vrf), api->vrf_id,
+ VRF_LOGNAME(vrf), api.vrf_id,
client->gr_instance_count);
- info->capabilities = api->cap;
- info->stale_removal_time = api->stale_removal_time;
- info->vrf_id = api->vrf_id;
+ info->capabilities = api.cap;
+ info->stale_removal_time = api.stale_removal_time;
+ info->vrf_id = api.vrf_id;
info->gr_enable = true;
}
break;
@@ -353,107 +384,54 @@ static void zebra_client_update_info(struct zserv *client, struct zapi_cap *api)
/* Update the stale removal timer */
if (info && info->t_stale_removal == NULL) {
- struct vrf *vrf = vrf_lookup_by_id(info->vrf_id);
LOG_GR("%s: vrf %s(%u) Stale time: %d is now update to: %d",
__func__, VRF_LOGNAME(vrf), info->vrf_id,
info->stale_removal_time,
- api->stale_removal_time);
+ api.stale_removal_time);
- info->stale_removal_time = api->stale_removal_time;
+ info->stale_removal_time = api.stale_removal_time;
}
break;
case ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE:
if (!info) {
- LOG_GR("%s: Client %s route update complete for AFI %d, SAFI %d",
- __func__, zebra_route_string(client->proto),
- api->afi, api->safi);
- } else {
- struct vrf *vrf = vrf_lookup_by_id(info->vrf_id);
-
- LOG_GR("%s: Client %s vrf %s(%u) route update complete for AFI %d, SAFI %d",
+ LOG_GR("%s: Client %s route update complete for AFI %d, SAFI %d, no Graceful Restart communication, returning",
__func__, zebra_route_string(client->proto),
- VRF_LOGNAME(vrf), info->vrf_id, api->afi,
- api->safi);
- info->route_sync[api->afi][api->safi] = true;
+ api.afi, api.safi);
+ return;
}
+
+ LOG_GR("%s: Client %s vrf %s(%u) route update complete for AFI %d, SAFI %d",
+ __func__, zebra_route_string(client->proto),
+ VRF_LOGNAME(vrf), info->vrf_id, api.afi, api.safi);
+ info->route_sync[api.afi] = true;
+
+ /*
+ * Schedule for after anything already in the meta Q
+ */
+ rib_add_gr_run(api.afi, api.vrf_id, client->proto,
+ client->instance);
+ zebra_gr_process_client_stale_routes(client, info);
break;
case ZEBRA_CLIENT_ROUTE_UPDATE_PENDING:
if (!info) {
LOG_GR("%s: Client %s route update pending for AFI %d, SAFI %d",
__func__, zebra_route_string(client->proto),
- api->afi, api->safi);
+ api.afi, api.safi);
} else {
- struct vrf *vrf = vrf_lookup_by_id(info->vrf_id);
-
LOG_GR("%s: Client %s vrf %s(%u) route update pending for AFI %d, SAFI %d",
__func__, zebra_route_string(client->proto),
- VRF_LOGNAME(vrf), info->vrf_id, api->afi,
- api->safi);
+ VRF_LOGNAME(vrf), info->vrf_id, api.afi,
+ api.safi);
- info->af_enabled[api->afi][api->safi] = true;
+ info->af_enabled[api.afi] = true;
}
break;
}
}
/*
- * Handler for capabilities that are received from client.
- */
-static void zebra_client_capabilities_handler(struct zserv *client,
- struct zapi_cap *api)
-{
- switch (api->cap) {
- case ZEBRA_CLIENT_GR_CAPABILITIES:
- case ZEBRA_CLIENT_ROUTE_UPDATE_PENDING:
- case ZEBRA_CLIENT_GR_DISABLE:
- case ZEBRA_CLIENT_RIB_STALE_TIME:
- /*
- * For all the cases we need to update the client info.
- */
- zebra_client_update_info(client, api);
- break;
- case ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE:
- /*
- * After client info has been updated delete all
- * stale routes
- */
- zebra_client_update_info(client, api);
- zebra_gr_process_client_stale_routes(client, api->vrf_id);
- break;
- }
-}
-
-/*
- * Function to decode and call appropriate functions
- * to handle client capabilities.
- */
-void zread_client_capabilities(ZAPI_HANDLER_ARGS)
-{
- struct zapi_cap api;
- struct stream *s;
-
- s = msg;
-
- if (zapi_capabilities_decode(s, &api)) {
- LOG_GR("%s: Error in reading capabilities for client %s",
- __func__, zebra_route_string(client->proto));
- return;
- }
-
- /* GR only for dynamic clients */
- if (client->proto <= ZEBRA_ROUTE_CONNECT) {
- LOG_GR("%s: GR capabilities for client %s not supported",
- __func__, zebra_route_string(client->proto));
- return;
- }
- /* Call the capabilities handler */
- zebra_client_capabilities_handler(client, &api);
-}
-
-
-/*
* Stale route handling
*/
@@ -470,10 +448,6 @@ static void zebra_gr_route_stale_delete_timer_expiry(struct event *thread)
client = (struct zserv *)info->stale_client_ptr;
- /* Set the flag to indicate all stale route deletion */
- if (thread->u.val == 1)
- info->do_delete = true;
-
cnt = zebra_gr_delete_stale_routes(info);
/* Restart the timer */
@@ -492,8 +466,6 @@ static void zebra_gr_route_stale_delete_timer_expiry(struct event *thread)
__func__, zebra_route_string(client->proto),
VRF_LOGNAME(vrf), info->vrf_id);
- XFREE(MTYPE_ZEBRA_GR, info->current_prefix);
- info->current_afi = 0;
zebra_gr_delete_stale_client(info);
}
}
@@ -502,14 +474,13 @@ static void zebra_gr_route_stale_delete_timer_expiry(struct event *thread)
/*
* Function to process to check if route entry is stale
* or has been updated.
+ *
+ * Returns true when a node is deleted else false
*/
-static void zebra_gr_process_route_entry(struct zserv *client,
+static bool zebra_gr_process_route_entry(struct zserv *client,
struct route_node *rn,
struct route_entry *re)
{
- if ((client == NULL) || (rn == NULL) || (re == NULL))
- return;
-
/* If the route is not refreshed after restart, delete the entry */
if (re->uptime < client->restart_time) {
if (IS_ZEBRA_DEBUG_RIB)
@@ -517,7 +488,62 @@ static void zebra_gr_process_route_entry(struct zserv *client,
__func__, zebra_route_string(client->proto),
&rn->p);
rib_delnode(rn, re);
+
+ return true;
}
+
+ return false;
+}
+
+static void zebra_gr_delete_stale_route_table_afi(struct event *event)
+{
+ struct zebra_gr_afi_clean *gac = EVENT_ARG(event);
+ struct route_table *table;
+ struct route_node *rn;
+ struct route_entry *re, *next;
+ struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(gac->info->vrf_id);
+ int32_t n = 0;
+
+ if (!zvrf)
+ goto done;
+
+ table = zvrf->table[gac->afi][SAFI_UNICAST];
+ if (!table)
+ goto done;
+
+ for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) {
+ RNODE_FOREACH_RE_SAFE (rn, re, next) {
+ if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
+ continue;
+
+ /* If the route refresh is received
+ * after restart then do not delete
+ * the route
+ */
+
+ if (re->type == gac->proto &&
+ re->instance == gac->instance &&
+ zebra_gr_process_route_entry(
+ gac->info->stale_client_ptr, rn, re))
+ n++;
+
+ /* If the max route count is reached
+ * then timer thread will be restarted
+ * Store the current prefix and afi
+ */
+ if ((n >= ZEBRA_MAX_STALE_ROUTE_COUNT) &&
+ (gac->info->do_delete == false)) {
+ event_add_timer(
+ zrouter.master,
+ zebra_gr_delete_stale_route_table_afi,
+ gac, ZEBRA_DEFAULT_STALE_UPDATE_DELAY,
+ &gac->t_gac);
+ }
+ }
+ }
+
+done:
+ XFREE(MTYPE_ZEBRA_GR, gac);
}
/*
@@ -528,19 +554,11 @@ static void zebra_gr_process_route_entry(struct zserv *client,
static int32_t zebra_gr_delete_stale_route(struct client_gr_info *info,
struct zebra_vrf *zvrf)
{
- struct route_node *rn, *curr;
- struct route_entry *re;
- struct route_entry *next;
- struct route_table *table;
- int32_t n = 0;
- afi_t afi, curr_afi;
+ afi_t afi;
uint8_t proto;
uint16_t instance;
struct zserv *s_client;
- if ((info == NULL) || (zvrf == NULL))
- return -1;
-
s_client = info->stale_client_ptr;
if (s_client == NULL) {
LOG_GR("%s: Stale client %s(%u) not present", __func__,
@@ -550,69 +568,18 @@ static int32_t zebra_gr_delete_stale_route(struct client_gr_info *info,
proto = s_client->proto;
instance = s_client->instance;
- curr_afi = info->current_afi;
LOG_GR("%s: Client %s %s(%u) stale routes are being deleted", __func__,
zebra_route_string(proto), zvrf->vrf->name, zvrf->vrf->vrf_id);
/* Process routes for all AFI */
- for (afi = curr_afi; afi < AFI_MAX; afi++) {
- table = zvrf->table[afi][SAFI_UNICAST];
+ for (afi = AFI_IP; afi < AFI_MAX; afi++) {
- if (table) {
- /*
- * If the current prefix is NULL then get the first
- * route entry in the table
- */
- if (info->current_prefix == NULL) {
- rn = route_top(table);
- if (rn == NULL)
- continue;
- curr = rn;
- } else
- /* Get the next route entry */
- curr = route_table_get_next(
- table, info->current_prefix);
-
- for (rn = curr; rn; rn = srcdest_route_next(rn)) {
- RNODE_FOREACH_RE_SAFE (rn, re, next) {
- if (CHECK_FLAG(re->status,
- ROUTE_ENTRY_REMOVED))
- continue;
- /* If the route refresh is received
- * after restart then do not delete
- * the route
- */
- if (re->type == proto
- && re->instance == instance) {
- zebra_gr_process_route_entry(
- s_client, rn, re);
- n++;
- }
-
- /* If the max route count is reached
- * then timer thread will be restarted
- * Store the current prefix and afi
- */
- if ((n >= ZEBRA_MAX_STALE_ROUTE_COUNT)
- && (info->do_delete == false)) {
- info->current_afi = afi;
- info->current_prefix = XCALLOC(
- MTYPE_ZEBRA_GR,
- sizeof(struct prefix));
- prefix_copy(
- info->current_prefix,
- &rn->p);
- return n;
- }
- }
- }
- }
/*
- * Reset the current prefix to indicate processing completion
- * of the current AFI
+ * Schedule for immediately after anything in the
+ * meta-Q
*/
- XFREE(MTYPE_ZEBRA_GR, info->current_prefix);
+ rib_add_gr_run(afi, info->vrf_id, proto, instance);
}
return 0;
}
@@ -623,21 +590,13 @@ static int32_t zebra_gr_delete_stale_route(struct client_gr_info *info,
*/
static int32_t zebra_gr_delete_stale_routes(struct client_gr_info *info)
{
- struct vrf *vrf;
struct zebra_vrf *zvrf;
uint64_t cnt = 0;
if (info == NULL)
return -1;
- /* Get the current VRF */
- vrf = vrf_lookup_by_id(info->vrf_id);
- if (vrf == NULL) {
- LOG_GR("%s: Invalid VRF specified %u", __func__, info->vrf_id);
- return -1;
- }
-
- zvrf = vrf->info;
+ zvrf = zebra_vrf_lookup_by_id(info->vrf_id);
if (zvrf == NULL) {
LOG_GR("%s: Invalid VRF entry %u", __func__, info->vrf_id);
return -1;
@@ -652,49 +611,63 @@ static int32_t zebra_gr_delete_stale_routes(struct client_gr_info *info)
* and cancels the stale timer
*/
static void zebra_gr_process_client_stale_routes(struct zserv *client,
- vrf_id_t vrf_id)
+ struct client_gr_info *info)
{
- struct client_gr_info *info = NULL;
afi_t afi;
- safi_t safi;
-
- TAILQ_FOREACH (info, &client->gr_info_queue, gr_info) {
- if (info->vrf_id == vrf_id)
- break;
- }
if (info == NULL)
return;
/* Check if route update completed for all AFI, SAFI */
- FOREACH_AFI_SAFI_NSF (afi, safi) {
- if (info->af_enabled[afi][safi]) {
- if (!info->route_sync[afi][safi]) {
- struct vrf *vrf = vrf_lookup_by_id(vrf_id);
-
- LOG_GR("%s: Client %s vrf: %s(%u) route update not completed for AFI %d, SAFI %d",
- __func__,
- zebra_route_string(client->proto),
- VRF_LOGNAME(vrf), info->vrf_id, afi,
- safi);
- return;
- }
+ for (afi = AFI_IP; afi < AFI_MAX; afi++) {
+ if (info->af_enabled[afi] && !info->route_sync[afi]) {
+ struct vrf *vrf = vrf_lookup_by_id(info->vrf_id);
+
+ LOG_GR("%s: Client %s vrf: %s(%u) route update not completed for AFI %d",
+ __func__, zebra_route_string(client->proto),
+ VRF_LOGNAME(vrf), info->vrf_id, afi);
+ return;
}
}
/*
* Route update completed for all AFI, SAFI
- * Cancel the stale timer and process the routes
+ * Cancel the stale timer, routes are already being processed
*/
if (info->t_stale_removal) {
- struct vrf *vrf = vrf_lookup_by_id(vrf_id);
+ struct vrf *vrf = vrf_lookup_by_id(info->vrf_id);
LOG_GR("%s: Client %s canceled stale delete timer vrf %s(%d)",
__func__, zebra_route_string(client->proto),
VRF_LOGNAME(vrf), info->vrf_id);
EVENT_OFF(info->t_stale_removal);
- event_execute(zrouter.master,
- zebra_gr_route_stale_delete_timer_expiry, info,
- 0);
}
}
+
+void zebra_gr_process_client(afi_t afi, vrf_id_t vrf_id, uint8_t proto,
+ uint8_t instance)
+{
+ struct zserv *client = zserv_find_client(proto, instance);
+ struct client_gr_info *info = NULL;
+ struct zebra_gr_afi_clean *gac;
+
+ if (client == NULL)
+ return;
+
+ TAILQ_FOREACH (info, &client->gr_info_queue, gr_info) {
+ if (info->vrf_id == vrf_id)
+ break;
+ }
+
+ if (info == NULL)
+ return;
+
+ gac = XCALLOC(MTYPE_ZEBRA_GR, sizeof(*gac));
+ gac->info = info;
+ gac->afi = afi;
+ gac->proto = proto;
+ gac->instance = instance;
+
+ event_add_event(zrouter.master, zebra_gr_delete_stale_route_table_afi,
+ gac, 0, &gac->t_gac);
+}
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 7a9d0c0ed6..32cfa4d04c 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -64,7 +64,12 @@ DEFINE_HOOK(rib_update, (struct route_node * rn, const char *reason),
DEFINE_HOOK(rib_shutdown, (struct route_node * rn), (rn));
-/* Meta Q's specific names */
+/*
+ * Meta Q's specific names
+ *
+ * If you add something here ensure that you
+ * change MQ_SIZE as well over in rib.h
+ */
enum meta_queue_indexes {
META_QUEUE_NHG,
META_QUEUE_EVPN,
@@ -76,6 +81,7 @@ enum meta_queue_indexes {
META_QUEUE_NOTBGP,
META_QUEUE_BGP,
META_QUEUE_OTHER,
+ META_QUEUE_GR_RUN,
};
/* Each route type's string and default distance value. */
@@ -250,6 +256,8 @@ static const char *subqueue2str(enum meta_queue_indexes index)
return "BGP Routes";
case META_QUEUE_OTHER:
return "Other Routes";
+ case META_QUEUE_GR_RUN:
+ return "Graceful Restart";
}
return "Unknown";
@@ -3089,6 +3097,23 @@ static void process_subq_early_route(struct listnode *lnode)
process_subq_early_route_add(ere);
}
+struct meta_q_gr_run {
+ afi_t afi;
+ vrf_id_t vrf_id;
+ uint8_t proto;
+ uint8_t instance;
+};
+
+static void process_subq_gr_run(struct listnode *lnode)
+{
+ struct meta_q_gr_run *gr_run = listgetdata(lnode);
+
+ zebra_gr_process_client(gr_run->afi, gr_run->vrf_id, gr_run->proto,
+ gr_run->instance);
+
+ XFREE(MTYPE_WQ_WRAPPER, gr_run);
+}
+
/*
* Examine the specified subqueue; process one entry and return 1 if
* there is a node, return 0 otherwise.
@@ -3122,6 +3147,9 @@ static unsigned int process_subq(struct list *subq,
case META_QUEUE_OTHER:
process_subq_route(lnode, qindex);
break;
+ case META_QUEUE_GR_RUN:
+ process_subq_gr_run(lnode);
+ break;
}
list_delete_node(subq, lnode);
@@ -3727,6 +3755,20 @@ static void early_route_meta_queue_free(struct meta_queue *mq, struct list *l,
}
}
+static void rib_meta_queue_gr_run_free(struct meta_queue *mq, struct list *l,
+ struct zebra_vrf *zvrf)
+{
+ struct meta_q_gr_run *gr_run;
+ struct listnode *node, *nnode;
+
+ for (ALL_LIST_ELEMENTS(l, node, nnode, gr_run)) {
+ if (zvrf && zvrf->vrf->vrf_id != gr_run->vrf_id)
+ continue;
+
+ XFREE(MTYPE_WQ_WRAPPER, gr_run);
+ }
+}
+
void meta_queue_free(struct meta_queue *mq, struct zebra_vrf *zvrf)
{
enum meta_queue_indexes i;
@@ -3754,6 +3796,9 @@ void meta_queue_free(struct meta_queue *mq, struct zebra_vrf *zvrf)
case META_QUEUE_OTHER:
rib_meta_queue_free(mq, mq->subq[i], zvrf);
break;
+ case META_QUEUE_GR_RUN:
+ rib_meta_queue_gr_run_free(mq, mq->subq[i], zvrf);
+ break;
}
if (!zvrf)
list_delete(&mq->subq[i]);
@@ -4094,6 +4139,17 @@ void _route_entry_dump(const char *func, union prefixconstptr pp,
zlog_debug("%s: dump complete", straddr);
}
+static int rib_meta_queue_gr_run_add(struct meta_queue *mq, void *data)
+{
+ listnode_add(mq->subq[META_QUEUE_GR_RUN], data);
+ mq->size++;
+
+ if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+ zlog_debug("Graceful Run adding");
+
+ return 0;
+}
+
static int rib_meta_queue_early_route_add(struct meta_queue *mq, void *data)
{
struct zebra_early_route *ere = data;
@@ -4110,6 +4166,20 @@ static int rib_meta_queue_early_route_add(struct meta_queue *mq, void *data)
return 0;
}
+int rib_add_gr_run(afi_t afi, vrf_id_t vrf_id, uint8_t proto, uint8_t instance)
+{
+ struct meta_q_gr_run *gr_run;
+
+ gr_run = XCALLOC(MTYPE_WQ_WRAPPER, sizeof(*gr_run));
+
+ gr_run->afi = afi;
+ gr_run->proto = proto;
+ gr_run->vrf_id = vrf_id;
+ gr_run->instance = instance;
+
+ return mq_add_handler(gr_run, rib_meta_queue_gr_run_add);
+}
+
struct route_entry *zebra_rib_route_entry_new(vrf_id_t vrf_id, int type,
uint8_t instance, uint32_t flags,
uint32_t nhe_id,
@@ -4410,6 +4480,22 @@ static void rib_update_handler(struct event *thread)
*/
static struct event *t_rib_update_threads[RIB_UPDATE_MAX];
+void rib_update_finish(void)
+{
+ int i;
+
+ for (i = RIB_UPDATE_KERNEL; i < RIB_UPDATE_MAX; i++) {
+ if (event_is_scheduled(t_rib_update_threads[i])) {
+ struct rib_update_ctx *ctx;
+
+ ctx = EVENT_ARG(t_rib_update_threads[i]);
+
+ rib_update_ctx_fini(&ctx);
+ EVENT_OFF(t_rib_update_threads[i]);
+ }
+ }
+}
+
/* Schedule a RIB update event for all vrfs */
void rib_update(enum rib_update_event event)
{
@@ -4418,6 +4504,9 @@ void rib_update(enum rib_update_event event)
if (event_is_scheduled(t_rib_update_threads[event]))
return;
+ if (zebra_router_in_shutdown())
+ return;
+
ctx = rib_update_ctx_init(0, event);
event_add_event(zrouter.master, rib_update_handler, ctx, 0,
diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c
index d9a7ee465a..142501b149 100644
--- a/zebra/zebra_routemap.c
+++ b/zebra/zebra_routemap.c
@@ -1041,7 +1041,7 @@ route_match_ip_next_hop(void *rule, const struct prefix *prefix, void *object)
}
alist = access_list_lookup(AFI_IP, (char *)rule);
if (alist == NULL) {
- if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))
+ if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)))
zlog_debug(
"%s: Access-List Specified: %s does not exist defaulting to NO_MATCH",
__func__, (char *)rule);
@@ -1104,7 +1104,7 @@ route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix,
}
plist = prefix_list_lookup(AFI_IP, (char *)rule);
if (plist == NULL) {
- if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))
+ if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)))
zlog_debug(
"%s: Prefix List %s specified does not exist defaulting to NO_MATCH",
__func__, (char *)rule);
@@ -1145,7 +1145,7 @@ route_match_address(afi_t afi, void *rule, const struct prefix *prefix,
alist = access_list_lookup(afi, (char *)rule);
if (alist == NULL) {
- if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))
+ if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)))
zlog_debug(
"%s: Access-List Specified: %s does not exist defaulting to NO_MATCH",
__func__, (char *)rule);
@@ -1207,7 +1207,7 @@ route_match_address_prefix_list(void *rule, const struct prefix *prefix,
plist = prefix_list_lookup(afi, (char *)rule);
if (plist == NULL) {
- if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))
+ if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)))
zlog_debug(
"%s: Prefix List %s specified does not exist defaulting to NO_MATCH",
__func__, (char *)rule);
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index c370ad9169..36290f99e0 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -2582,19 +2582,18 @@ void zebra_vxlan_print_specific_rmac_l3vni(struct vty *vty, vni_t l3vni,
struct zebra_mac *zrmac = NULL;
json_object *json = NULL;
+ if (use_json)
+ json = json_object_new_object();
+
if (!is_evpn_enabled()) {
- if (use_json)
- vty_out(vty, "{}\n");
+ vty_json(vty, json);
return;
}
- if (use_json)
- json = json_object_new_object();
-
zl3vni = zl3vni_lookup(l3vni);
if (!zl3vni) {
if (use_json)
- vty_out(vty, "{}\n");
+ vty_json(vty, json);
else
vty_out(vty, "%% L3-VNI %u doesn't exist\n", l3vni);
return;
@@ -2603,7 +2602,7 @@ void zebra_vxlan_print_specific_rmac_l3vni(struct vty *vty, vni_t l3vni,
zrmac = zl3vni_rmac_lookup(zl3vni, rmac);
if (!zrmac) {
if (use_json)
- vty_out(vty, "{}\n");
+ vty_json(vty, json);
else
vty_out(vty,
"%% Requested RMAC doesn't exist in L3-VNI %u\n",
@@ -2624,13 +2623,18 @@ void zebra_vxlan_print_rmacs_l3vni(struct vty *vty, vni_t l3vni, bool use_json)
struct rmac_walk_ctx wctx;
json_object *json = NULL;
- if (!is_evpn_enabled())
+ if (use_json)
+ json = json_object_new_object();
+
+ if (!is_evpn_enabled()) {
+ vty_json(vty, json);
return;
+ }
zl3vni = zl3vni_lookup(l3vni);
if (!zl3vni) {
if (use_json)
- vty_out(vty, "{}\n");
+ vty_json(vty, json);
else
vty_out(vty, "%% L3-VNI %u does not exist\n", l3vni);
return;
@@ -2639,9 +2643,6 @@ void zebra_vxlan_print_rmacs_l3vni(struct vty *vty, vni_t l3vni, bool use_json)
if (!num_rmacs)
return;
- if (use_json)
- json = json_object_new_object();
-
memset(&wctx, 0, sizeof(wctx));
wctx.vty = vty;
wctx.json = json;
@@ -2663,15 +2664,14 @@ void zebra_vxlan_print_rmacs_all_l3vni(struct vty *vty, bool use_json)
json_object *json = NULL;
void *args[2];
+ if (use_json)
+ json = json_object_new_object();
+
if (!is_evpn_enabled()) {
- if (use_json)
- vty_out(vty, "{}\n");
+ vty_json(vty, json);
return;
}
- if (use_json)
- json = json_object_new_object();
-
args[0] = vty;
args[1] = json;
hash_iterate(zrouter.l3vni_table,
@@ -2690,15 +2690,14 @@ void zebra_vxlan_print_specific_nh_l3vni(struct vty *vty, vni_t l3vni,
struct zebra_neigh *n = NULL;
json_object *json = NULL;
+ if (use_json)
+ json = json_object_new_object();
+
if (!is_evpn_enabled()) {
- if (use_json)
- vty_out(vty, "{}\n");
+ vty_json(vty, json);
return;
}
- if (use_json)
- json = json_object_new_object();
-
/* If vni=0 passed, assume svd lookup */
if (!l3vni)
n = svd_nh_lookup(ip);
@@ -2799,15 +2798,14 @@ void zebra_vxlan_print_nh_all_l3vni(struct vty *vty, bool use_json)
json_object *json = NULL;
void *args[2];
+ if (use_json)
+ json = json_object_new_object();
+
if (!is_evpn_enabled()) {
- if (use_json)
- vty_out(vty, "{}\n");
+ vty_json(vty, json);
return;
}
- if (use_json)
- json = json_object_new_object();
-
args[0] = vty;
args[1] = json;
hash_iterate(zrouter.l3vni_table,
@@ -2828,24 +2826,23 @@ void zebra_vxlan_print_l3vni(struct vty *vty, vni_t vni, bool use_json)
json_object *json = NULL;
struct zebra_l3vni *zl3vni = NULL;
+ if (use_json)
+ json = json_object_new_object();
+
if (!is_evpn_enabled()) {
- if (use_json)
- vty_out(vty, "{}\n");
+ vty_json(vty, json);
return;
}
zl3vni = zl3vni_lookup(vni);
if (!zl3vni) {
if (use_json)
- vty_out(vty, "{}\n");
+ vty_json(vty, json);
else
vty_out(vty, "%% VNI %u does not exist\n", vni);
return;
}
- if (use_json)
- json = json_object_new_object();
-
args[0] = vty;
args[1] = json;
zl3vni_print(zl3vni, (void *)args);
@@ -2900,12 +2897,18 @@ void zebra_vxlan_print_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf,
struct neigh_walk_ctx wctx;
json_object *json = NULL;
- if (!is_evpn_enabled())
+ if (use_json)
+ json = json_object_new_object();
+
+ if (!is_evpn_enabled()) {
+ vty_json(vty, json);
return;
+ }
+
zevpn = zebra_evpn_lookup(vni);
if (!zevpn) {
if (use_json)
- vty_out(vty, "{}\n");
+ vty_json(vty, json);
else
vty_out(vty, "%% VNI %u does not exist\n", vni);
return;
@@ -2914,9 +2917,6 @@ void zebra_vxlan_print_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf,
if (!num_neigh)
return;
- if (use_json)
- json = json_object_new_object();
-
/* Since we have IPv6 addresses to deal with which can vary widely in
* size, we try to be a bit more elegant in display by first computing
* the maximum width.
@@ -2951,12 +2951,14 @@ void zebra_vxlan_print_neigh_all_vni(struct vty *vty, struct zebra_vrf *zvrf,
json_object *json = NULL;
void *args[3];
- if (!is_evpn_enabled())
- return;
-
if (use_json)
json = json_object_new_object();
+ if (!is_evpn_enabled()) {
+ vty_json(vty, json);
+ return;
+ }
+
args[0] = vty;
args[1] = json;
args[2] = (void *)(ptrdiff_t)print_dup;
@@ -2979,12 +2981,14 @@ void zebra_vxlan_print_neigh_all_vni_detail(struct vty *vty,
json_object *json = NULL;
void *args[3];
- if (!is_evpn_enabled())
- return;
-
if (use_json)
json = json_object_new_object();
+ if (!is_evpn_enabled()) {
+ vty_json(vty, json);
+ return;
+ }
+
args[0] = vty;
args[1] = json;
args[2] = (void *)(ptrdiff_t)print_dup;
@@ -3008,12 +3012,18 @@ void zebra_vxlan_print_specific_neigh_vni(struct vty *vty,
struct zebra_neigh *n;
json_object *json = NULL;
- if (!is_evpn_enabled())
+ if (use_json)
+ json = json_object_new_object();
+
+ if (!is_evpn_enabled()) {
+ vty_json(vty, json);
return;
+ }
+
zevpn = zebra_evpn_lookup(vni);
if (!zevpn) {
if (use_json)
- vty_out(vty, "{}\n");
+ vty_json(vty, json);
else
vty_out(vty, "%% VNI %u does not exist\n", vni);
return;
@@ -3026,8 +3036,6 @@ void zebra_vxlan_print_specific_neigh_vni(struct vty *vty,
vni);
return;
}
- if (use_json)
- json = json_object_new_object();
zebra_evpn_print_neigh(n, vty, json);
@@ -3048,12 +3056,18 @@ void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf,
struct neigh_walk_ctx wctx;
json_object *json = NULL;
- if (!is_evpn_enabled())
+ if (use_json)
+ json = json_object_new_object();
+
+ if (!is_evpn_enabled()) {
+ vty_json(vty, json);
return;
+ }
+
zevpn = zebra_evpn_lookup(vni);
if (!zevpn) {
if (use_json)
- vty_out(vty, "{}\n");
+ vty_json(vty, json);
else
vty_out(vty, "%% VNI %u does not exist\n", vni);
return;
@@ -3062,9 +3076,6 @@ void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf,
if (!num_neigh)
return;
- if (use_json)
- json = json_object_new_object();
-
memset(&wctx, 0, sizeof(wctx));
wctx.zevpn = zevpn;
wctx.vty = vty;
@@ -3094,12 +3105,20 @@ void zebra_vxlan_print_neigh_vni_dad(struct vty *vty,
struct neigh_walk_ctx wctx;
json_object *json = NULL;
- if (!is_evpn_enabled())
+ if (use_json)
+ json = json_object_new_object();
+
+ if (!is_evpn_enabled()) {
+ vty_json(vty, json);
return;
+ }
zevpn = zebra_evpn_lookup(vni);
if (!zevpn) {
- vty_out(vty, "%% VNI %u does not exist\n", vni);
+ if (use_json)
+ vty_json(vty, json);
+ else
+ vty_out(vty, "%% VNI %u does not exist\n", vni);
return;
}
@@ -3111,9 +3130,6 @@ void zebra_vxlan_print_neigh_vni_dad(struct vty *vty,
if (!num_neigh)
return;
- if (use_json)
- json = json_object_new_object();
-
/* Since we have IPv6 addresses to deal with which can vary widely in
* size, we try to be a bit more elegant in display by first computing
* the maximum width.
@@ -3155,8 +3171,12 @@ void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf,
json_object *json = NULL;
json_object *json_mac = NULL;
- if (!is_evpn_enabled())
+ if (!is_evpn_enabled()) {
+ if (use_json)
+ vty_out(vty, "{}\n");
return;
+ }
+
zevpn = zebra_evpn_lookup(vni);
if (!zevpn) {
if (use_json)
@@ -3218,13 +3238,13 @@ void zebra_vxlan_print_macs_all_vni(struct vty *vty, struct zebra_vrf *zvrf,
struct mac_walk_ctx wctx;
json_object *json = NULL;
+ if (use_json)
+ json = json_object_new_object();
+
if (!is_evpn_enabled()) {
- if (use_json)
- vty_out(vty, "{}\n");
+ vty_json(vty, json);
return;
}
- if (use_json)
- json = json_object_new_object();
memset(&wctx, 0, sizeof(wctx));
wctx.vty = vty;
@@ -3246,13 +3266,13 @@ void zebra_vxlan_print_macs_all_vni_detail(struct vty *vty,
struct mac_walk_ctx wctx;
json_object *json = NULL;
+ if (use_json)
+ json = json_object_new_object();
+
if (!is_evpn_enabled()) {
- if (use_json)
- vty_out(vty, "{}\n");
+ vty_json(vty, json);
return;
}
- if (use_json)
- json = json_object_new_object();
memset(&wctx, 0, sizeof(wctx));
wctx.vty = vty;
@@ -3275,12 +3295,14 @@ void zebra_vxlan_print_macs_all_vni_vtep(struct vty *vty,
struct mac_walk_ctx wctx;
json_object *json = NULL;
- if (!is_evpn_enabled())
- return;
-
if (use_json)
json = json_object_new_object();
+ if (!is_evpn_enabled()) {
+ vty_json(vty, json);
+ return;
+ }
+
memset(&wctx, 0, sizeof(wctx));
wctx.vty = vty;
wctx.flags = SHOW_REMOTE_MAC_FROM_VTEP;
@@ -3303,13 +3325,18 @@ void zebra_vxlan_print_specific_mac_vni(struct vty *vty, struct zebra_vrf *zvrf,
struct zebra_mac *mac;
json_object *json = NULL;
- if (!is_evpn_enabled())
+ if (use_json)
+ json = json_object_new_object();
+
+ if (!is_evpn_enabled()) {
+ vty_json(vty, json);
return;
+ }
zevpn = zebra_evpn_lookup(vni);
if (!zevpn) {
if (use_json)
- vty_out(vty, "{}\n");
+ vty_json(vty, json);
else
vty_out(vty, "%% VNI %u does not exist\n", vni);
return;
@@ -3317,7 +3344,7 @@ void zebra_vxlan_print_specific_mac_vni(struct vty *vty, struct zebra_vrf *zvrf,
mac = zebra_evpn_mac_lookup(zevpn, macaddr);
if (!mac) {
if (use_json)
- vty_out(vty, "{}\n");
+ vty_json(vty, json);
else
vty_out(vty,
"%% Requested MAC does not exist in VNI %u\n",
@@ -3325,10 +3352,8 @@ void zebra_vxlan_print_specific_mac_vni(struct vty *vty, struct zebra_vrf *zvrf,
return;
}
- if (use_json)
- json = json_object_new_object();
-
zebra_evpn_print_mac(mac, vty, json);
+
if (use_json)
vty_json(vty, json);
}
@@ -3693,8 +3718,11 @@ void zebra_vxlan_print_macs_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf,
json_object *json = NULL;
json_object *json_mac = NULL;
- if (!is_evpn_enabled())
+ if (!is_evpn_enabled()) {
+ vty_json(vty, json);
return;
+ }
+
zevpn = zebra_evpn_lookup(vni);
if (!zevpn) {
if (use_json)
@@ -3745,12 +3773,14 @@ void zebra_vxlan_print_vni(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni,
struct zebra_l3vni *zl3vni = NULL;
struct zebra_evpn *zevpn = NULL;
- if (!is_evpn_enabled())
- return;
-
if (use_json)
json = json_object_new_object();
+ if (!is_evpn_enabled()) {
+ vty_json(vty, json);
+ return;
+ }
+
args[0] = vty;
args[1] = json;
@@ -3787,8 +3817,13 @@ void zebra_vxlan_print_evpn(struct vty *vty, bool uj)
json_object *json = NULL;
struct zebra_vrf *zvrf = NULL;
- if (!is_evpn_enabled())
+ if (uj)
+ json = json_object_new_object();
+
+ if (!is_evpn_enabled()) {
+ vty_json(vty, json);
return;
+ }
zvrf = zebra_vrf_get_evpn();
@@ -3797,7 +3832,6 @@ void zebra_vxlan_print_evpn(struct vty *vty, bool uj)
num_vnis = num_l2vnis + num_l3vnis;
if (uj) {
- json = json_object_new_object();
json_object_string_add(json, "advertiseGatewayMacip",
zvrf->advertise_gw_macip ? "Yes" : "No");
json_object_string_add(json, "advertiseSviMacip",
@@ -3860,12 +3894,15 @@ void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf,
json_object *json = NULL;
void *args[2];
- if (!is_evpn_enabled())
- return;
-
if (use_json)
json = json_object_new_object();
- else
+
+ if (!is_evpn_enabled()) {
+ vty_json(vty, json);
+ return;
+ }
+
+ if (!use_json)
vty_out(vty, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI",
"Type", "VxLAN IF", "# MACs", "# ARPs",
"# Remote VTEPs", "Tenant VRF");
@@ -3943,8 +3980,11 @@ void zebra_vxlan_print_vnis_detail(struct vty *vty, struct zebra_vrf *zvrf,
struct zebra_ns *zns = NULL;
struct zebra_evpn_show zes;
- if (!is_evpn_enabled())
+ if (!is_evpn_enabled()) {
+ if (use_json)
+ vty_out(vty, "{}\n");
return;
+ }
zns = zebra_ns_lookup(NS_DEFAULT);
if (!zns)
diff --git a/zebra/zserv.c b/zebra/zserv.c
index 70707866ee..6abd49310c 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -1152,10 +1152,6 @@ static void zebra_show_stale_client_detail(struct vty *vty,
info->t_stale_removal));
}
}
- vty_out(vty, "Current AFI : %d\n", info->current_afi);
- if (info->current_prefix)
- vty_out(vty, "Current prefix : %pFX\n",
- info->current_prefix);
}
}
vty_out(vty, "\n");
diff --git a/zebra/zserv.h b/zebra/zserv.h
index aa58a3a299..90aa4d53f4 100644
--- a/zebra/zserv.h
+++ b/zebra/zserv.h
@@ -51,9 +51,6 @@ struct client_gr_info {
/* VRF for which GR enabled */
vrf_id_t vrf_id;
- /* AFI */
- afi_t current_afi;
-
/* Stale time and GR cap */
uint32_t stale_removal_time;
enum zserv_client_capabilities capabilities;
@@ -64,11 +61,10 @@ struct client_gr_info {
bool stale_client;
/* Route sync and enable flags for AFI/SAFI */
- bool af_enabled[AFI_MAX][SAFI_MAX];
- bool route_sync[AFI_MAX][SAFI_MAX];
+ bool af_enabled[AFI_MAX];
+ bool route_sync[AFI_MAX];
/* Book keeping */
- struct prefix *current_prefix;
void *stale_client_ptr;
struct event *t_stale_removal;