]> git.proxmox.com Git - mirror_frr.git/commitdiff
Merge pull request #13183 from Pdoijode/pdoijode/pim-json-changes
authorJafar Al-Gharaibeh <jafar@atcorp.com>
Wed, 12 Apr 2023 04:46:18 +0000 (23:46 -0500)
committerGitHub <noreply@github.com>
Wed, 12 Apr 2023 04:46:18 +0000 (23:46 -0500)
pimd: Option to get IGMP groups and sources for a particular interface

236 files changed:
alpine/APKBUILD.in
babeld/babeld.c
babeld/babeld.h
babeld/util.h
bgpd/bgp_attr.c
bgpd/bgp_bfd.c
bgpd/bgp_bmp.c
bgpd/bgp_dump.c
bgpd/bgp_ecommunity.c
bgpd/bgp_evpn.c
bgpd/bgp_evpn.h
bgpd/bgp_evpn_mh.c
bgpd/bgp_flowspec.c
bgpd/bgp_flowspec.h
bgpd/bgp_mplsvpn.c
bgpd/bgp_packet.c
bgpd/bgp_packet.h
bgpd/bgp_route.c
bgpd/bgp_route.h
bgpd/bgp_routemap.c
bgpd/bgp_vty.c
bgpd/bgp_zebra.c
bgpd/bgpd.c
bgpd/bgpd.h
configure.ac
doc/developer/logging.rst
doc/user/basic.rst
doc/user/bgp.rst
doc/user/isisd.rst
doc/user/mgmtd.rst
doc/user/ospfd.rst
doc/user/overview.rst
isisd/fabricd.c
isisd/isis_adjacency.c
isisd/isis_adjacency.h
isisd/isis_circuit.c
isisd/isis_cli.c
isisd/isis_common.h
isisd/isis_dynhn.c
isisd/isis_events.c
isisd/isis_lfa.c
isisd/isis_lsp.c
isisd/isis_misc.c
isisd/isis_misc.h
isisd/isis_mt.c
isisd/isis_nb.c
isisd/isis_nb.h
isisd/isis_nb_config.c
isisd/isis_nb_notifications.c
isisd/isis_nb_state.c
isisd/isis_pdu.c
isisd/isis_pdu.h
isisd/isis_pdu_counter.c
isisd/isis_pdu_counter.h
isisd/isis_snmp.c
isisd/isis_spf.c
isisd/isis_sr.c
isisd/isis_te.c
isisd/isis_tlvs.c
isisd/isis_tx_queue.c
isisd/isisd.c
isisd/isisd.h
lib/compiler.h
lib/cspf.c
lib/cspf.h
lib/if_rmap.c
lib/iso.c [new file with mode: 0644]
lib/iso.h [new file with mode: 0644]
lib/link_state.c
lib/link_state.h
lib/prefix.c
lib/prefix.h
lib/routemap.c
lib/subdir.am
lib/vty.c
lib/vty.h
lib/zclient.c
mgmtd/mgmt.h
mgmtd/mgmt_ds.c
mgmtd/mgmt_ds.h
mgmtd/mgmt_main.c
mgmtd/mgmt_vty.c
mgmtd/mgmt_vty.c.safe [deleted file]
nhrpd/debug.h
ospfd/ospf_abr.c
ospfd/ospf_abr.h
ospfd/ospf_lsa.c
ospfd/ospf_lsa.h
ospfd/ospf_network.c
ospfd/ospf_network.h
ospfd/ospf_route.c
ospfd/ospf_route.h
ospfd/ospf_routemap.c
ospfd/ospf_snmp.c
ospfd/ospf_te.c
ospfd/ospf_vty.c
ospfd/ospf_zebra.c
ospfd/ospf_zebra.h
ospfd/ospfd.c
ospfd/ospfd.h
pathd/path_ted.c
pimd/pim_iface.c
ripd/rip_nb.c
ripd/rip_nb.h
ripd/rip_nb_state.c
ripd/ripd.c
sharpd/sharp_vty.c
sharpd/sharp_zebra.c
staticd/static_main.c
tests/bgpd/test_mp_attr.c
tests/lib/subdir.am
tests/topotests/all_protocol_startup/r1/ospf6d.conf-pre-v4
tests/topotests/all_protocol_startup/test_all_protocol_startup.py
tests/topotests/bfd_topo3/r5/bfdd.conf
tests/topotests/bfd_topo3/r6/bfdd.conf
tests/topotests/bgp_accept_own/ce1/bgpd.conf
tests/topotests/bgp_accept_own/ce2/bgpd.conf
tests/topotests/bgp_accept_own/pe1/bgpd.conf
tests/topotests/bgp_accept_own/rr1/bgpd.conf
tests/topotests/bgp_comm_list_match/r2/bgpd.conf
tests/topotests/bgp_confed1/r1/bgpd.conf
tests/topotests/bgp_confed1/r2/bgpd.conf
tests/topotests/bgp_confed1/r3/bgpd.conf
tests/topotests/bgp_confed1/r4/bgpd.conf
tests/topotests/bgp_dont_capability_negotiate/r1/bgpd.conf
tests/topotests/bgp_evpn_vxlan_svd_topo1/test_bgp_evpn_vxlan_svd.py
tests/topotests/bgp_evpn_vxlan_topo1/test_bgp_evpn_vxlan.py
tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_up.py
tests/topotests/bgp_labeled_unicast_addpath/test_bgp_labeled_unicast_addpath.py
tests/topotests/bgp_lu_explicitnull/r1/bgpd.conf [new file with mode: 0644]
tests/topotests/bgp_lu_explicitnull/r1/zebra.conf [new file with mode: 0644]
tests/topotests/bgp_lu_explicitnull/r2/bgpd.conf [new file with mode: 0644]
tests/topotests/bgp_lu_explicitnull/r2/zebra.conf [new file with mode: 0644]
tests/topotests/bgp_lu_explicitnull/test_bgp_lu_explicitnull.py [new file with mode: 0644]
tests/topotests/bgp_prefix_list_any/r2/bgpd.conf
tests/topotests/bgp_route_map_delay_timer/r1/bgpd.conf
tests/topotests/bgp_route_map_vpn_import/r1/bgpd.conf
tests/topotests/bgp_route_origin_parser/pe1/bgpd.conf [new file with mode: 0644]
tests/topotests/bgp_route_origin_parser/test_bgp_route_origin_parser.py [new file with mode: 0644]
tests/topotests/bgp_snmp_bgp4v2mib/r2/bgpd.conf
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r1/zebra.conf
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r2/zebra.conf
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf3/r1/zebra.conf
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf3/r2/bgpd.conf
tests/topotests/bgp_srv6l3vpn_to_bgp_vrf3/r2/zebra.conf
tests/topotests/bgp_suppress_fib/r2/bgpd.allowas_in.conf
tests/topotests/bgp_suppress_fib/r2/bgpd.conf
tests/topotests/bgp_vrf_md5_peering/r1/bgpd.conf
tests/topotests/config_timing/test_config_timing.py
tests/topotests/isis_snmp/r5/ldpdconf
tests/topotests/lib/common_config.py
tests/topotests/lib/micronet_compat.py
tests/topotests/lib/topogen.py
tests/topotests/lib/topotest.py
tests/topotests/mgmt_tests/test_yang_mgmt.py
tests/topotests/multicast_pim6_sm_topo1/test_multicast_pim6_sm1.py
tests/topotests/multicast_pim6_sm_topo1/test_multicast_pim6_sm2.py
tests/topotests/multicast_pim6_static_rp_topo1/test_multicast_pim6_static_rp1.py
tests/topotests/multicast_pim6_static_rp_topo1/test_multicast_pim6_static_rp2.py
tests/topotests/ospf6_ecmp_inter_area/r1/ospf6d.conf
tests/topotests/ospf_nssa_topo1/__init__.py [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt1/ospfd.conf [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt1/staticd.conf [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt1/step1/show_ip_ospf_route.ref [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt1/step10/show_ip_ospf_route.ref [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt1/step2/show_ip_ospf_route.ref [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt1/step3/show_ip_ospf_route.ref [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt1/step4/show_ip_ospf_route.ref [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt1/step5/show_ip_ospf_route.ref [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt1/step6/show_ip_ospf_route.ref [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt1/step7/show_ip_ospf_route.ref [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt1/step8/show_ip_ospf_route.ref [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt1/step9/show_ip_ospf_route.ref [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt1/zebra.conf [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt2/ospfd.conf [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt2/staticd.conf [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt2/step1/show_ip_ospf_route.ref [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt2/step10/show_ip_ospf_route.ref [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt2/step2/show_ip_ospf_route.ref [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt2/step3/show_ip_ospf_route.ref [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt2/step4/show_ip_ospf_route.ref [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt2/step5/show_ip_ospf_route.ref [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt2/step6/show_ip_ospf_route.ref [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt2/step7/show_ip_ospf_route.ref [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt2/step8/show_ip_ospf_route.ref [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt2/step9/show_ip_ospf_route.ref [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt2/zebra.conf [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt3/ospfd.conf [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt3/staticd.conf [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt3/step1/show_ip_ospf_route.ref [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt3/step10/show_ip_ospf_route.ref [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt3/step2/show_ip_ospf_route.ref [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt3/step3/show_ip_ospf_route.ref [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt3/step4/show_ip_ospf_route.ref [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt3/step5/show_ip_ospf_route.ref [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt3/step6/show_ip_ospf_route.ref [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt3/step7/show_ip_ospf_route.ref [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt3/step8/show_ip_ospf_route.ref [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt3/step9/show_ip_ospf_route.ref [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt3/zebra.conf [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt4/ospfd.conf [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt4/staticd.conf [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt4/step1/show_ip_ospf_route.ref [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt4/step10/show_ip_ospf_route.ref [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt4/step2/show_ip_ospf_route.ref [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt4/step3/show_ip_ospf_route.ref [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt4/step4/show_ip_ospf_route.ref [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt4/step5/show_ip_ospf_route.ref [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt4/step6/show_ip_ospf_route.ref [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt4/step7/show_ip_ospf_route.ref [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt4/step8/show_ip_ospf_route.ref [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt4/step9/show_ip_ospf_route.ref [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/rt4/zebra.conf [new file with mode: 0644]
tests/topotests/ospf_nssa_topo1/test_ospf_nssa_topo1.py [new file with mode: 0644]
tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.py
tests/topotests/ospfv3_basic_functionality/test_ospfv3_single_area.py
tests/topotests/rip_allow_ecmp/__init__.py [new file with mode: 0644]
tests/topotests/rip_allow_ecmp/r1/frr.conf [new file with mode: 0644]
tests/topotests/rip_allow_ecmp/r2/frr.conf [new file with mode: 0644]
tests/topotests/rip_allow_ecmp/r3/frr.conf [new file with mode: 0644]
tests/topotests/rip_allow_ecmp/test_rip_allow_ecmp.py [new file with mode: 0644]
tests/topotests/zebra_rib/test_zebra_rib.py
yang/frr-isisd.yang
yang/frr-ripd.yang
zebra/dpdk/zebra_dplane_dpdk.c
zebra/interface.c
zebra/interface.h
zebra/main.c
zebra/rib.h
zebra/zebra_dplane.c
zebra/zebra_gr.c
zebra/zebra_rib.c
zebra/zebra_routemap.c
zebra/zebra_vxlan.c
zebra/zserv.c
zebra/zserv.h

index fef7a61ccc8947bdce13e7d39c57e0ef46713d2f..fd3c02f47e69867cd4e08a50b129c9da93ed6832 100644 (file)
@@ -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)
 }
 
index 4ce92c520472603d1013ea470f852b9ba57985a7..f4c932971eb0e010cd0fcd1131e133c0a9bc61b6 100644 (file)
@@ -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
 }
index 6c51af48a89572c97f56a29c90c62ad87555afe0..619550f651f7579669240e85f8fb324ccb206866 100644 (file)
@@ -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)
index 5e5843543a22cba1e47e7438caf370c3dc155b7e..8535d4dd6a173aa605bb5b2c853cd1b46e99179f 100644 (file)
@@ -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 */
 
index c35e45275c9bab538dcb23e5143127b08080287e..5b06bc3913759f0483a8620ce73a35421e029d07 100644 (file)
@@ -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
@@ -2998,19 +3003,6 @@ bgp_attr_psid_sub(uint8_t type, uint16_t length,
                                args->total);
                }
 
-               /*
-                * 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
@@ -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",
index a51bcb1a1a6fae5012ceccf2cb88c50d0fefacaf..d1ddfd046025e1be25da3b3d25d4078725d86fda 100644 (file)
@@ -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);
index 73dbf4ab2b4ec8f0446b37c5bc78007154cd39a0..baf164679c725586c871eaaa0c7df7e46d2e4037 100644 (file)
@@ -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,
index c78e740ec9671a56aea4f68ecc23d6591d8b2730..fe77e7e2500630d3ad0a3ba821cf3434ed541dc7 100644 (file)
@@ -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);
 
index 541da9ecd6886edd97270962401fe5c525f2069b..dc1905868bd20d8221787dd925a8e1dcb9b52257 100644 (file)
@@ -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)
index 78e96d130c06a28d92b4ddd5ca1d04ed33216ed7..81117e94ef467384ecc6257a246af6fde7308acf 100644 (file)
@@ -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
index 1dce4820d680a05a67bbe8f202c1aa14cad388d6..a034bfbd7ec8006001ab638e6ed2afe1035fc1fe 100644 (file)
@@ -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);
index d821d4d5829d7e4f263a670f7a1f2ee6a4224c18..4aff93514fbeaaefdd4502bdfc63ffb25e659ec3 100644 (file)
@@ -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)) {
@@ -2608,6 +2609,9 @@ static void bgp_evpn_es_show_entry_detail(struct vty *vty,
                                    listcount(es->macip_global_path_list));
                json_object_int_add(json, "inconsistentVniVtepCount",
                                es->incons_evi_vtep_cnt);
+               if (es->flags & BGP_EVPNES_LOCAL)
+                       json_object_int_add(json, "localEsDfPreference",
+                                           es->df_pref);
                if (listcount(es->es_vtep_list)) {
                        json_vteps = json_object_new_array();
                        for (ALL_LIST_ELEMENTS_RO(es->es_vtep_list, node,
index f9debe43cd45b350defdc326defe5f9c7bad42df..70bdbaf0356f94cdc24a687c0eff71d5de7b59e6 100644 (file)
@@ -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)",
index 58fc1775ab2be6e479b7c85fd5a491629cc38c0b..bc2f00511e0de103c745d7a4bb06a0dacdfdf504 100644 (file)
@@ -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);
 
index c08f95cdf43b11b088f5778550acac61f11b5f01..63168f1e7a826ccbbbf38a5b340bb5418d3c3474 100644 (file)
@@ -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)
index 1c76828a2f2063c085a7c5f590bc52048f57afae..9469a0778f9722be2737910baa05a1687e2d8e95 100644 (file)
@@ -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:
index c072bbc235160a4e8b6c90ea6ff6616f0168a2b2..04bdb81849bd806822166016380c9b71776e81dd 100644 (file)
@@ -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);
index 4441e86fbbf8fbdc3f4f4f4eb6b1de930081a5e7..b49206adceb5191b344b9dfd7ba74274a2844f21 100644 (file)
@@ -3070,7 +3070,9 @@ static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
  * the IMPLICIT_NULL label. This is pretty specialized: it's only called
  * in a path where we basically _know_ this is a BGP-LU route.
  */
-static bool bgp_lu_need_imp_null(const struct bgp_path_info *new_select)
+static bool bgp_lu_need_null_label(struct bgp *bgp,
+                                  const struct bgp_path_info *new_select,
+                                  afi_t afi, mpls_label_t *label)
 {
        /* Certain types get imp null; so do paths where the nexthop is
         * not labeled.
@@ -3079,12 +3081,20 @@ static bool bgp_lu_need_imp_null(const struct bgp_path_info *new_select)
            || new_select->sub_type == BGP_ROUTE_AGGREGATE
            || new_select->sub_type == BGP_ROUTE_REDISTRIBUTE)
                return true;
-       else if (new_select->extra == NULL ||
-                !bgp_is_valid_label(&new_select->extra->label[0]))
-               /* TODO -- should be configurable? */
+       else if (new_select->extra &&
+                bgp_is_valid_label(&new_select->extra->label[0]))
+               return false;
+       if (label == NULL)
                return true;
+       if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_LU_EXPLICIT_NULL))
+               /* Disable PHP : explicit-null */
+               *label = afi == AFI_IP ? MPLS_LABEL_IPV4_EXPLICIT_NULL
+                                      : MPLS_LABEL_IPV6_EXPLICIT_NULL;
        else
-               return false;
+               /* Enforced PHP popping: implicit-null */
+               *label = MPLS_LABEL_IMPLICIT_NULL;
+
+       return true;
 }
 
 /*
@@ -3113,6 +3123,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
        struct bgp_path_info *old_select;
        struct bgp_path_info_pair old_and_new;
        int debug = 0;
+       mpls_label_t mpls_label_null;
 
        if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
                if (dest)
@@ -3167,7 +3178,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
         * Right now, since we only deal with per-prefix labels, it is not
         * necessary to do this upon changes to best path. Exceptions:
         * - label index has changed -> recalculate resulting label
-        * - path_info sub_type changed -> switch to/from implicit-null
+        * - path_info sub_type changed -> switch to/from null label value
         * - no valid label (due to removed static label binding) -> get new one
         */
        if (bgp->allocate_mpls_labels[afi][safi]) {
@@ -3176,11 +3187,12 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
                            || bgp_label_index_differs(new_select, old_select)
                            || new_select->sub_type != old_select->sub_type
                            || !bgp_is_valid_label(&dest->local_label)) {
-                               /* Enforced penultimate hop popping:
-                                * implicit-null for local routes, aggregate
-                                * and redistributed routes
+                               /* control label imposition for local routes,
+                                * aggregate and redistributed routes
                                 */
-                               if (bgp_lu_need_imp_null(new_select)) {
+                               mpls_label_null = MPLS_LABEL_IMPLICIT_NULL;
+                               if (bgp_lu_need_null_label(bgp, new_select, afi,
+                                                          &mpls_label_null)) {
                                        if (CHECK_FLAG(
                                                    dest->flags,
                                                    BGP_NODE_REGISTERED_FOR_LABEL)
@@ -3189,8 +3201,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
                                                    BGP_NODE_LABEL_REQUESTED))
                                                bgp_unregister_for_label(dest);
                                        dest->local_label = mpls_lse_encode(
-                                               MPLS_LABEL_IMPLICIT_NULL, 0, 0,
-                                               1);
+                                               mpls_label_null, 0, 0, 1);
                                        bgp_set_valid_label(&dest->local_label);
                                } else
                                        bgp_register_for_label(dest,
@@ -3838,6 +3849,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 +8355,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 +8539,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 +11614,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 +11660,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, "} ");
 
index b48e8eda1125a5bd4437461fd1b10c5fd3a895c3..a64144b62557fcb1197bd42814ad1ca6194e834e 100644 (file)
@@ -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);
index 4faf4a9f15ce290dc18e0921a6f3dbb8d68f64d3..32ecb083beca51ccd503d4bdf407b5770ac583c5 100644 (file)
@@ -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);
index 4bbbced806822bb52f19c211683ab5d1c3e0ea24..de781d6b1e72bc009308f69e0559b05050314d0f 100644 (file)
@@ -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;
@@ -2802,6 +2820,21 @@ DEFUN(no_bgp_ebgp_requires_policy, no_bgp_ebgp_requires_policy_cmd,
        return CMD_SUCCESS;
 }
 
+DEFPY(bgp_lu_uses_explicit_null, bgp_lu_uses_explicit_null_cmd,
+      "[no] bgp labeled-unicast explicit-null",
+      NO_STR BGP_STR
+      "BGP Labeled-unicast options\n"
+      "Use explicit-null label values for local prefixes\n")
+{
+       VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+       if (no)
+               UNSET_FLAG(bgp->flags, BGP_FLAG_LU_EXPLICIT_NULL);
+       else
+               SET_FLAG(bgp->flags, BGP_FLAG_LU_EXPLICIT_NULL);
+       return CMD_SUCCESS;
+}
+
 DEFUN(bgp_suppress_duplicates, bgp_suppress_duplicates_cmd,
       "bgp suppress-duplicates",
       BGP_STR
@@ -11036,10 +11069,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 +11082,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;
 }
@@ -18220,6 +18250,9 @@ int bgp_config_write(struct vty *vty)
                                        ? ""
                                        : "no ");
 
+               if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_LU_EXPLICIT_NULL))
+                       vty_out(vty, " bgp labeled-unicast explicit-null\n");
+
                /* draft-ietf-idr-deprecate-as-set-confed-set */
                if (bgp->reject_as_sets)
                        vty_out(vty, " bgp reject-as-sets\n");
@@ -19139,6 +19172,9 @@ void bgp_vty_init(void)
        install_element(BGP_NODE, &bgp_ebgp_requires_policy_cmd);
        install_element(BGP_NODE, &no_bgp_ebgp_requires_policy_cmd);
 
+       /* bgp labeled-unicast explicit-null */
+       install_element(BGP_NODE, &bgp_lu_uses_explicit_null_cmd);
+
        /* bgp suppress-duplicates */
        install_element(BGP_NODE, &bgp_suppress_duplicates_cmd);
        install_element(BGP_NODE, &no_bgp_suppress_duplicates_cmd);
index 3d659d48d44d177a292147a285157bda5e1e5d74..96b1f3e00f4c1776e9f9028b240869b7643a2838 100644 (file)
@@ -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
index 97238bc38b14d924361387176959736b1dc0f02c..9d7a1f967e5f5aee336d23d7bcf61344f76d5762 100644 (file)
@@ -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) {
index a08a2870ee7ce54fa1342e57ceb75a8c24c04715..b6491bf7995381c670ddd8c39935ff1d422a4c22 100644 (file)
@@ -500,6 +500,8 @@ struct bgp {
 #define BGP_FLAG_HARD_ADMIN_RESET (1ULL << 31)
 /* Evaluate the AIGP attribute during the best path selection process */
 #define BGP_FLAG_COMPARE_AIGP (1ULL << 32)
+/* For BGP-LU, force local prefixes to use explicit-null label */
+#define BGP_FLAG_LU_EXPLICIT_NULL (1ULL << 33)
 
        /* BGP default address-families.
         * New peers inherit enabled afi/safis from bgp instance.
index f3968df2aad1849ffa7885819b74ef05e1eaf11b..79288c67e967c53d8854fba42d288b07597e5913 100644 (file)
@@ -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
index b7021b69a12acd8f63294daffa9ca0d1545ca5a8..2fe0a5989b94d8a81612fb3ac1a49cb39653d50f 100644 (file)
@@ -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
 ^^^^^^^^^^^^^^^
 
index 254dad8303b17dd620096a28b63539930688b6f2..337cfff9378ff1b969cf63696f840f5e26997916 100644 (file)
@@ -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:
index 946f0699f271cfcb55e585d067dcc94d68537048..97d7ce6b7571c5496583e072da3c7650f8060ae3 100644 (file)
@@ -2767,6 +2767,17 @@ happened automatically if local-role is set.
    value of his role (by setting local-role on his side). Otherwise, a Role
    Mismatch Notification will be sent.
 
+Labeled unicast
+---------------
+
+*bgpd* supports labeled information, as per :rfc:`3107`.
+
+.. clicmd:: bgp labeled-unicast explicit-null
+
+By default, locally advertised prefixes use the `implicit-null` label to
+encode in the outgoing NLRI. The following command uses the `explicit-null`
+label value for all the BGP instances.
+
 .. _bgp-l3vpn-vrfs:
 
 L3VPN VRFs
index 90c13d4f932878c031864aa894a61f0c6bc324fc..88fa78ddfa2c4a2eef9916587ccd761d0ac00618 100644 (file)
@@ -68,6 +68,10 @@ writing, *isisd* does not support multiple ISIS processes.
 
    Log changes in adjacency state.
 
+.. clicmd:: log-pdu-drops
+
+   Log any dropped PDUs.
+
 .. clicmd:: metric-style [narrow | transition | wide]
 
    Set old-style (ISO 10589) or new-style packet formats:
index 6ea7e7891a0067f28775c3a0aa75d348114095d6..6614a568f849c73f78c9d19d11463c5e85e42071 100644 (file)
@@ -70,14 +70,6 @@ Frontend Interface and MGMTd:
     database.
   - Data can be retrieved anytime using GET_CONFIG/GET_DATA API.
 
- - Startup Database:
-
-  - Consists of configuration data items only.
-  - This is a copy of Running database that is stored in persistent
-    storage and is used to load configurations on Running database during
-    MGMT daemon startup.
-  - Data cannot be edited/retrieved directly via Frontend interface.
-
  - Operational Database:
 
   - Consists of non-configurational data items.
@@ -313,8 +305,7 @@ MGMT Configuration commands
 .. clicmd:: mgmt commit apply
 
     This command commits any uncommited changes in the Candidate DB to the
-    Running DB. It also dumps a copy of the tree in JSON format into
-    frr_startup.json.
+    Running DB.
 
 .. clicmd:: mgmt commit check
 
index 30d55f34a722ed4a69d05755414cda3a04da5379..a99785204b4582f20f02906af8f2bf3d0c6f0d72 100644 (file)
@@ -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)
 
 
index 4a24fa52be565e59a15252c344582ac5108fab94..5ea33d62c956da95e60d92e3b57f7068976c03de 100644 (file)
@@ -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
 ----
index 4fd39498a0bd57024c794b48bf6804addad2f782..0be36e175ac49602a83f40b4dfbbfe0be122e439 100644 (file)
@@ -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;
index 1871078cc165734824784f9b484099a0e73796da..30b71537e0e5ea2062e426062c77f9bf3b718abc 100644 (file)
@@ -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) {
index f02f7a68eac6a9c6a3e793adf7fe974dce2c6052..c0c8e68145d2633946169be5c949e3b5ecf07612 100644 (file)
@@ -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;
index 124dcdd86d5b2abf068e01aa1b15b0058f331962..feab45123383e3027376080b57b446bb43f042d0 100644 (file)
@@ -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");
index 7e1bb9255c491b984c43f6321e7a1c3bce737c2d..ee51e468587009a15b709b903593f84c874217a7 100644 (file)
@@ -3025,6 +3025,26 @@ void cli_show_isis_log_adjacency(struct vty *vty, const struct lyd_node *dnode,
        vty_out(vty, " log-adjacency-changes\n");
 }
 
+/*
+ * XPath: /frr-isisd:isis/instance/log-pdu-drops
+ */
+DEFPY_YANG(log_pdu_drops, log_pdu_drops_cmd, "[no] log-pdu-drops",
+          NO_STR "Log any dropped PDUs\n")
+{
+       nb_cli_enqueue_change(vty, "./log-pdu-drops", NB_OP_MODIFY,
+                             no ? "false" : "true");
+
+       return nb_cli_apply_changes(vty, NULL);
+}
+
+void cli_show_isis_log_pdu_drops(struct vty *vty, const struct lyd_node *dnode,
+                                bool show_defaults)
+{
+       if (!yang_dnode_get_bool(dnode, NULL))
+               vty_out(vty, " no");
+       vty_out(vty, " log-pdu-drops\n");
+}
+
 /*
  * XPath: /frr-isisd:isis/instance/mpls/ldp-sync
  */
@@ -3290,6 +3310,7 @@ void isis_cli_init(void)
        install_element(INTERFACE_NODE, &isis_ti_lfa_cmd);
 
        install_element(ISIS_NODE, &log_adj_changes_cmd);
+       install_element(ISIS_NODE, &log_pdu_drops_cmd);
 
        install_element(ISIS_NODE, &isis_mpls_ldp_sync_cmd);
        install_element(ISIS_NODE, &no_isis_mpls_ldp_sync_cmd);
index c908dc2e24632c3d0af7d05c48ed709c8115b966..2ded68f84d5b5ef24c0488f9cf38755d886cdb6b 100644 (file)
 #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
index 446e52201998c3068aae4bce3c2078c4c225b728..61c49d08a742af88b924940594941561ffba9bd8 100644 (file)
@@ -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;
 }
 
index 8a2a2ab971edd084dd1bf4f36f03d67a478bb727..32231a079f1af104800e085d00a65d180eb2e74a 100644 (file)
@@ -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;
 }
index 7a25a9253553385e304d10a1a92580b8b99382a5..abb6168393cd9e6c3e3ee616fce4ea17e50e3b36 100644 (file)
@@ -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;
                }
 
index d569f6bd5be66e67685b5d5bcb03ee4954884863..fb69448d042c966635803c01c7bbe23a2be2a4ad 100644 (file)
@@ -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)
index 95d24036ec534f900abf913ca013cddc07a5c6c7..09ffa3479a62056f888498af636225aa96eed32b 100644 (file)
 #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 */
index 01d9abe8693346cf6e64a711894f1692dc1403a1..3a1d136b1d926e61020ef49df0fe9559a6334df1 100644 (file)
@@ -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; */
index fcc0f53815edd8d07a80ac708ac060c7e1d6875d..d04a24dc46838c5bc271be883f4cc6af3285f680 100644 (file)
@@ -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);
        }
index 7dc3a0eb3da6025cc425e478b903a29a26653f0f..9141bfc46ce7b10e5dc1112a56e46f59e3d1a66b 100644 (file)
@@ -558,6 +558,13 @@ const struct frr_yang_module_info frr_isisd_info = {
                                .modify = isis_instance_log_adjacency_changes_modify,
                        },
                },
+               {
+                       .xpath = "/frr-isisd:isis/instance/log-pdu-drops",
+                       .cbs = {
+                               .cli_show = cli_show_isis_log_pdu_drops,
+                               .modify = isis_instance_log_pdu_drops_modify,
+                       },
+               },
                {
                        .xpath = "/frr-isisd:isis/instance/mpls-te",
                        .cbs = {
index 480b2ce04132927a660a08e543ce854b30408c43..9a1f1f786f41febcc2f0705b1bca35cb3af1213f 100644 (file)
@@ -196,6 +196,7 @@ int isis_instance_fast_reroute_level_2_remote_lfa_prefix_list_modify(
 int isis_instance_fast_reroute_level_2_remote_lfa_prefix_list_destroy(
        struct nb_cb_destroy_args *args);
 int isis_instance_log_adjacency_changes_modify(struct nb_cb_modify_args *args);
+int isis_instance_log_pdu_drops_modify(struct nb_cb_modify_args *args);
 int isis_instance_mpls_te_create(struct nb_cb_create_args *args);
 int isis_instance_mpls_te_destroy(struct nb_cb_destroy_args *args);
 int isis_instance_mpls_te_router_address_modify(struct nb_cb_modify_args *args);
@@ -609,6 +610,8 @@ void cli_show_ip_isis_priority(struct vty *vty, const struct lyd_node *dnode,
                               bool show_defaults);
 void cli_show_isis_log_adjacency(struct vty *vty, const struct lyd_node *dnode,
                                 bool show_defaults);
+void cli_show_isis_log_pdu_drops(struct vty *vty, const struct lyd_node *dnode,
+                                bool show_defaults);
 void cli_show_isis_mpls_ldp_sync(struct vty *vty, const struct lyd_node *dnode,
                                 bool show_defaults);
 void cli_show_isis_mpls_ldp_sync_holddown(struct vty *vty,
index 3817465a643a3796b873051873f7a9ce30ab7708..022bfbed6e4480c8047be925744eed1879e941f8 100644 (file)
@@ -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;
@@ -1829,6 +1830,23 @@ int isis_instance_log_adjacency_changes_modify(struct nb_cb_modify_args *args)
        return NB_OK;
 }
 
+/*
+ * XPath: /frr-isisd:isis/instance/log-pdu-drops
+ */
+int isis_instance_log_pdu_drops_modify(struct nb_cb_modify_args *args)
+{
+       struct isis_area *area;
+       bool log = yang_dnode_get_bool(args->dnode, NULL);
+
+       if (args->event != NB_EV_APPLY)
+               return NB_OK;
+
+       area = nb_running_get_entry(args->dnode, NULL, true);
+       area->log_pdu_drops = log ? 1 : 0;
+
+       return NB_OK;
+}
+
 /*
  * XPath: /frr-isisd:isis/instance/mpls-te
  */
index 94b1c47d3efe15dce277d6f184c3d25e4300ee43..5a1e312b4dbfb4ed5ce5ade906fd10b2e6dbd59e 100644 (file)
@@ -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);
index 13fdddf555c92f1f9dff2439a51b8f8da739057f..b7c33ed27b8b7b1b89fd11aec1d8f9af32a25beb 100644 (file)
@@ -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);
 }
 
 /*
index d53d43ad0ecb5cca964750097bd03acb55f2ac78..0cd43a7abc9e5cfef40c5878c6ed33e93f1e7972 100644 (file)
@@ -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);
                }
        }
 
@@ -1654,14 +1651,14 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa)
        if (idrp == ISO9542_ESIS) {
                flog_err(EC_LIB_DEVELOPMENT,
                         "No support for ES-IS packet IDRP=%hhx", idrp);
-               pdu_counter_count(circuit->area->pdu_drop_counters, pdu_type);
+               pdu_counter_count_drop(circuit->area, pdu_type);
                return ISIS_ERROR;
        }
 
        if (idrp != ISO10589_ISIS) {
                flog_err(EC_ISIS_PACKET, "Not an IS-IS packet IDRP=%hhx",
                         idrp);
-               pdu_counter_count(circuit->area->pdu_drop_counters, pdu_type);
+               pdu_counter_count_drop(circuit->area, pdu_type);
                return ISIS_ERROR;
        }
 
@@ -1672,7 +1669,7 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa)
                isis_notif_version_skew(circuit, version1, raw_pdu,
                                        sizeof(raw_pdu));
 #endif /* ifndef FABRICD */
-               pdu_counter_count(circuit->area->pdu_drop_counters, pdu_type);
+               pdu_counter_count_drop(circuit->area, pdu_type);
                return ISIS_WARNING;
        }
 
@@ -1696,14 +1693,14 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa)
                isis_notif_id_len_mismatch(circuit, id_len, raw_pdu,
                                           sizeof(raw_pdu));
 #endif /* ifndef FABRICD */
-               pdu_counter_count(circuit->area->pdu_drop_counters, pdu_type);
+               pdu_counter_count_drop(circuit->area, pdu_type);
                return ISIS_ERROR;
        }
 
        uint8_t expected_length;
        if (pdu_size(pdu_type, &expected_length)) {
                zlog_warn("Unsupported ISIS PDU %hhu", pdu_type);
-               pdu_counter_count(circuit->area->pdu_drop_counters, pdu_type);
+               pdu_counter_count_drop(circuit->area, pdu_type);
                return ISIS_WARNING;
        }
 
@@ -1711,7 +1708,7 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa)
                flog_err(EC_ISIS_PACKET,
                         "Expected fixed header length = %hhu but got %hhu",
                         expected_length, length);
-               pdu_counter_count(circuit->area->pdu_drop_counters, pdu_type);
+               pdu_counter_count_drop(circuit->area, pdu_type);
                return ISIS_ERROR;
        }
 
@@ -1719,7 +1716,7 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa)
                flog_err(
                        EC_ISIS_PACKET,
                        "PDU is too short to contain fixed header of given PDU type.");
-               pdu_counter_count(circuit->area->pdu_drop_counters, pdu_type);
+               pdu_counter_count_drop(circuit->area, pdu_type);
                return ISIS_ERROR;
        }
 
@@ -1730,14 +1727,14 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa)
                isis_notif_version_skew(circuit, version2, raw_pdu,
                                        sizeof(raw_pdu));
 #endif /* ifndef FABRICD */
-               pdu_counter_count(circuit->area->pdu_drop_counters, pdu_type);
+               pdu_counter_count_drop(circuit->area, pdu_type);
                return ISIS_WARNING;
        }
 
        if (circuit->is_passive) {
                zlog_warn("Received ISIS PDU on passive circuit %s",
                          circuit->interface->name);
-               pdu_counter_count(circuit->area->pdu_drop_counters, pdu_type);
+               pdu_counter_count_drop(circuit->area, pdu_type);
                return ISIS_WARNING;
        }
 
@@ -1756,7 +1753,7 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa)
                isis_notif_max_area_addr_mismatch(circuit, max_area_addrs,
                                                  raw_pdu, sizeof(raw_pdu));
 #endif /* ifndef FABRICD */
-               pdu_counter_count(circuit->area->pdu_drop_counters, pdu_type);
+               pdu_counter_count_drop(circuit->area, pdu_type);
                return ISIS_ERROR;
        }
 
@@ -1765,8 +1762,7 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa)
        case L2_LAN_HELLO:
        case P2P_HELLO:
                if (fabricd && pdu_type != P2P_HELLO) {
-                       pdu_counter_count(circuit->area->pdu_drop_counters,
-                                         pdu_type);
+                       pdu_counter_count_drop(circuit->area, pdu_type);
                        return ISIS_ERROR;
                }
 
@@ -1777,8 +1773,7 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa)
        case FS_LINK_STATE:
                if (fabricd && pdu_type != L2_LINK_STATE &&
                    pdu_type != FS_LINK_STATE) {
-                       pdu_counter_count(circuit->area->pdu_drop_counters,
-                                         pdu_type);
+                       pdu_counter_count_drop(circuit->area, pdu_type);
                        return ISIS_ERROR;
                }
 
@@ -1791,12 +1786,12 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa)
                retval = process_snp(pdu_type, circuit, ssnpa);
                break;
        default:
-               pdu_counter_count(circuit->area->pdu_drop_counters, pdu_type);
+               pdu_counter_count_drop(circuit->area, pdu_type);
                return ISIS_ERROR;
        }
 
        if (retval != ISIS_OK)
-               pdu_counter_count(circuit->area->pdu_drop_counters, pdu_type);
+               pdu_counter_count_drop(circuit->area, pdu_type);
 
        return retval;
 }
@@ -2481,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 */
@@ -2509,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));
@@ -2554,3 +2549,37 @@ out:
                isis_tx_queue_del(circuit->tx_queue, lsp);
        }
 }
+
+void isis_log_pdu_drops(struct isis_area *area, const char *pdu_type)
+{
+       uint64_t total_drops = 0;
+
+       for (int i = 0; i < PDU_COUNTER_SIZE; i++) {
+               if (!area->pdu_drop_counters[i])
+                       continue;
+               total_drops += area->pdu_drop_counters[i];
+       }
+
+       zlog_info("PDU drop detected of type: %s. %" PRIu64
+                 " Total Drops; %" PRIu64 " L1 IIH drops;  %" PRIu64
+                 " L2 IIH drops; %" PRIu64 " P2P IIH drops; %" PRIu64
+                 " L1 LSP drops; %" PRIu64 " L2 LSP drops; %" PRIu64
+                 " FS LSP drops; %" PRIu64 " L1 CSNP drops; %" PRIu64
+                 " L2 CSNP drops; %" PRIu64 " L1 PSNP drops; %" PRIu64
+                 " L2 PSNP drops.",
+                 pdu_type, total_drops,
+                 pdu_counter_get_count(area->pdu_drop_counters, L1_LAN_HELLO),
+                 pdu_counter_get_count(area->pdu_drop_counters, L2_LAN_HELLO),
+                 pdu_counter_get_count(area->pdu_drop_counters, P2P_HELLO),
+                 pdu_counter_get_count(area->pdu_drop_counters, L1_LINK_STATE),
+                 pdu_counter_get_count(area->pdu_drop_counters, L2_LINK_STATE),
+                 pdu_counter_get_count(area->pdu_drop_counters, FS_LINK_STATE),
+                 pdu_counter_get_count(area->pdu_drop_counters,
+                                       L1_COMPLETE_SEQ_NUM),
+                 pdu_counter_get_count(area->pdu_drop_counters,
+                                       L2_COMPLETE_SEQ_NUM),
+                 pdu_counter_get_count(area->pdu_drop_counters,
+                                       L1_PARTIAL_SEQ_NUM),
+                 pdu_counter_get_count(area->pdu_drop_counters,
+                                       L2_PARTIAL_SEQ_NUM));
+}
index ccd89a70f1b0676c74b761bfa7cfd1300ed590d7..5303c61d38a273ea39bfadcb5ef000dce5ea3b7d 100644 (file)
@@ -206,4 +206,6 @@ void send_lsp(struct isis_circuit *circuit,
 void fill_fixed_hdr(uint8_t pdu_type, struct stream *stream);
 int send_hello(struct isis_circuit *circuit, int level);
 int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa);
+void isis_log_pdu_drops(struct isis_area *area, const char *pdu_type);
+
 #endif /* _ZEBRA_ISIS_PDU_H */
index 9d07b5e5989d3017296a93b38a59ae357f6683b0..a3605a32a16234db97ea524d474844565379a6f3 100644 (file)
@@ -8,10 +8,10 @@
 
 #include "vty.h"
 
-#include "isisd/isis_pdu_counter.h"
 #include "isisd/isisd.h"
 #include "isisd/isis_circuit.h"
 #include "isisd/isis_pdu.h"
+#include "isisd/isis_pdu_counter.h"
 
 static int pdu_type_to_counter_index(uint8_t pdu_type)
 {
@@ -91,3 +91,23 @@ void pdu_counter_print(struct vty *vty, const char *prefix,
                        pdu_counter_index_to_name(i), counter[i]);
        }
 }
+
+void pdu_counter_count_drop(struct isis_area *area, uint8_t pdu_type)
+{
+       pdu_counter_count(area->pdu_drop_counters, pdu_type);
+
+       if (area->log_pdu_drops) {
+               isis_log_pdu_drops(
+                       area, pdu_counter_index_to_name(
+                                     pdu_type_to_counter_index(pdu_type)));
+       }
+}
+
+uint64_t pdu_counter_get_count(pdu_counter_t counter, uint8_t pdu_type)
+{
+       int index = pdu_type_to_counter_index(pdu_type);
+
+       if (index < 0)
+               return -1;
+       return counter[index];
+}
index c53c47368f46af0224ec346df9331e7e40474612..5c35b4fb51daf27cc7b0cd072f169b1bf02675cb 100644 (file)
@@ -24,5 +24,7 @@ typedef uint64_t pdu_counter_t[PDU_COUNTER_SIZE];
 void pdu_counter_print(struct vty *vty, const char *prefix,
                       pdu_counter_t counter);
 void pdu_counter_count(pdu_counter_t counter, uint8_t pdu_type);
+void pdu_counter_count_drop(struct isis_area *area, uint8_t pdu_type);
+uint64_t pdu_counter_get_count(pdu_counter_t counter, uint8_t pdu_type);
 
 #endif
index fa566c5470dafc1cdb3bb46b34bd92f8efc5ab61..f9e3780e29e3c78ffcb34a038bdf8139fd5af266 100644 (file)
 /* 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);
index bfe3758cd898d77e18aad50b3d08eb6a658616ab..8597049ac098a170981950637b3008fe534cfcb9 100644 (file)
@@ -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;
                }
 
index cb330603e4198588eb1cc6b84e9f349f9f26dab5..e43b84ab2e4d5385c20457cd31b801297a29d8b3 100644 (file)
@@ -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. */
index 45d763fd698150d9e7bec924534fabe5f17254b6..4e180ead6189cd6a935e51abc8e08d2dae116127 100644 (file)
@@ -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);
index b52a38be7f878398158d446fdf10ea003cbfb829..3b6db0ee17f488c774a583db2f7f2b850d2631ba 100644 (file)
@@ -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
index ec2d50d60a47d643d504f06f8564bb681f07bee4..caf97f11749c9315b6b5e33753e4af0c959c44cf 100644 (file)
@@ -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);
        }
 
index c6369a884e3b626ed23804616aabe17489da0cbf..fd6b91b42e1f5af10874940d15281e660ddd3736 100644 (file)
@@ -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++;
                                }
                        }
index 0b1f1cb620c18e85b5e461297b135453cbef890a..12d9cd36c4f2c81e10b1db3bdb8ae8882466964a 100644 (file)
@@ -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 */
@@ -195,6 +196,8 @@ struct isis_area {
        int ip_circuits;
        /* logging adjacency changes? */
        uint8_t log_adj_changes;
+       /* logging pdu drops? */
+       uint8_t log_pdu_drops;
        /* multi topology settings */
        struct list *mt_settings;
        /* MPLS-TE settings */
index d12e2828326f1d914ad93b61697919591d047097..29fcfbefbf2d6c0593d38abe8bf587bd5e5e1281 100644 (file)
@@ -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
index b92c9cb395de42e350e721cf50d514a94b887225..6a0fb7f63cc20b3bb0c3dd27bbdd2bea8f44f9ca 100644 (file)
@@ -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;
index 3eceaa04af05302a9dffe6f6daa22dd298f0518c..bba685a6172d907b2a328f19246cb65d684b8a81 100644 (file)
@@ -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
index 27c41aaa27b430a33e481ff011606e1f2ce09366..0d305a7af1ad5dfbadc094ff484037f3eab90170 100644 (file)
@@ -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 (file)
index 0000000..fe97776
--- /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 (file)
index 0000000..975d3c1
--- /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_ */
index 589c0ae704c4c38147a171a0db5e850b04919790..076030a83974ee00b061ff2258d967dcdc73aa76 100644 (file)
@@ -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;
index e6a6388ba41334b8f38afade0f19259750a6d603..b75f035431c187da3dce68cbd7912720989c4410 100644 (file)
@@ -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.
index a6aae08a6a563567c7b83cd287d59ada2e8c8a74..b8cad910f423e825b65add7138c78839380a2f44 100644 (file)
@@ -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
index 9c5728370615dd947c9b45a914efc46aaaba99f6..88a228b55c3a9bbec76e943e75d0eb5a4e324852 100644 (file)
@@ -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;
 }
 
index 16da81fa746255f5834b38712ae4ab28a3083d0e..20dcd2a53d4dc73589f666ee4e8509e7c7a69ad2 100644 (file)
@@ -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);
index 0f5bbef0b251c1650ef184c7d1d72ee1c8aa8937..83eecbee577638db4a788202fa6d6f1520248bed 100644 (file)
@@ -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 \
index d0a667778812c22822528d2ad30f318c7bec3b47..974f5380d38bce9ab7c170a1e905bb3a9a33a4a6 100644 (file)
--- 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;
index 66d3355329d7982fdb4ce9445b7ee268f41c50cd..5114238f6af2f7aab055f4c2ec28f966c90bf701 100644 (file)
--- 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 *);
index 95093a56f5d9e9aaa022762c14ed256372441555..d42cb2019189a9cfab18463e0cef3a62ab66fa92 100644 (file)
@@ -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:
index 4d186c176b1d31ee9443277d18a1b15d80ebd156..9579b0223050b6915fd3018076539a95b8ef27aa 100644 (file)
@@ -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)
index 1724afb1829a7617518802fdfd265c24406a4f43..10b3cecb920e06d1a7925c42d76e54edb97f7140 100644 (file)
@@ -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;
index 89a2ea94259f796202ce3e1a6179e57c06714f3a..8d01f3d5b19fd6e49a327e376ce2bb13b51239c7 100644 (file)
@@ -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)++)
 
index 7d176059f57646550fd5c80a1287177861a14521..08c999260d462760afd3094887f2f1a513c52fce 100644 (file)
 #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'},
index 79fa54a791d2e6f07d4c68b5eb258843f5161914..cb09544fdc459453a9030066765ccfb5c1bc6c17 100644 (file)
@@ -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 (file)
index c43485c..0000000
+++ /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.
-        */
-}
index e9428fa90a0e9fbb1aab5ce8236fa45b0cccdce9..f2c7022ad409298087020d3c2f8a30d503313116 100644 (file)
@@ -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)
index e14586c5ee031048f7f989240a6942b97cd4c4a6..ded520889f4f9f03419e5acae54674d9560f2ff1 100644 (file)
@@ -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__);
index 19d444b125cf06aa2321b10faa10c4c2731f8675..cc2b2b05481f5333bacd78b40c4cdbcc86ec5e12 100644 (file)
@@ -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);
index 82f7b96fd508049cfdf8b67011ffa7bc0c60b716..87b683b15d0f30a7ee9aa7a6e8a42a1c331990ac 100644 (file)
@@ -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
index 8ab293f4dbdda16100d92835896f9c6531d65485..d5ca0694ccb204bd890e1593c1586cb9cd24dfd3 100644 (file)
@@ -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,
index d3f30ce1ee81c93ec10ad522afbb39dc44a3b4ff..bd5cd7682a6034be245ec99825b2691d78d8f764 100644 (file)
@@ -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);
+       }
+}
index 33fd8980bff20366716be1a3fd495f5358977574..d9b579c04a448260e76667cf1d72c31ea6d13264 100644 (file)
@@ -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 */
index 5f18bff1cf79996de3b9523a3e982fc669cc0e5d..75868056adb31c51aa6d8def2ed3acfc670eb91e 100644 (file)
@@ -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;
index 2582067aece7af3f28cad144257da447464268df..7639a0049e1263eed1c454d23f4fc9e88a423977 100644 (file)
@@ -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 *);
 
index 3087008819275c7a97fa0040d083fc9c56a7dc4f..3d5c5aa2d572c99d0e4f598701e45fa2cf18d242 100644 (file)
@@ -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);
index 2982cc7d6f2114e2130fbe67980b2b695600a773..fcc43e7311c2bae2ac7522bfa4ff91522543bfab 100644 (file)
@@ -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;
index dc9dd34303644c96085220d26fd6e475abe311a7..b140027147f3a3eb5280929fcae047b97b7b6258 100644 (file)
@@ -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);
index 8c0afd8527e45ff811c341c2d7e3adbc0a47287a..9b918798c04c11ff30e5c5bdbdbe75067f77fec4 100644 (file)
@@ -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();
 
index 3e02d3c33e1dcfa5179bdd769fa7b34a2bf9ced3..3f967e41e4829ceed77d54e2553eecdaafcbd567 100644 (file)
@@ -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,
 
index 711b1e7a61e3c32c954924ff1c9f802653dc7320..86a5678fc4fa89917f3c794ad7b181d91394ec81 100644 (file)
@@ -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 *);
index 112ddfedb7c4440820f1f0d50017fe9ac48bc9a5..15ce1c48a436d6fa773bc7db5acfc80e825644a4 100644 (file)
@@ -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));
index 6727d802a65faddb932a24ead0a38c790b479894..1b66d4d9304c97e2fc2b7d744962f4c41a97bfbe 100644 (file)
@@ -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);
index d8ddd8cdc88f7d08a50ae8049f64dfb1747f2aab..fd5c342d842649804a209b1172d18bbbab6ece56 100644 (file)
@@ -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 */
index d284912d1d26d8d0ec6000a5c00025a636226254..ead02d8bd753cfe14a3b1f49a7b792c874120f20 100644 (file)
@@ -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;
index 9947c01af56b2b060544b446223e00ff11f5b8e1..c332b2a5b7fdc412a06919627bbcc3aa1f5509f3 100644 (file)
@@ -337,6 +337,66 @@ const struct frr_yang_module_info frr_ripd_info = {
                                .get_elem = ripd_instance_state_routes_route_interface_get_elem,
                        },
                },
+               {
+                        .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 = {
index 99114c99288ad6ceb7445e2c3e3fa8cb5c3d52ff..a30e579e1cbd39b36a97e16652c895e03d3e87fc 100644 (file)
@@ -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);
index 0e2931b464ff9a025a451e61ebfdcdde5cc99b1e..fa0d382a0e095915b2228743e36e8aaa34aeca8f 100644 (file)
@@ -207,9 +207,170 @@ 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
  */
index ae4d93b4f5853f82835077737dcb02a877bb0fab..7dbe2bbccf7d696bf0f127bc5049fa8e5e307670 100644 (file)
@@ -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)
index 77b562d6a61ef69023152b8e865e2ef54ad8737e..0d7ba345302a12d18c8d014d609d4d77094c502c 100644 (file)
@@ -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;
 }
 
index 17ad70596968e02ff845e0dd55aa3cf97f238f72..91fb7f03b107c822e6de1b54fc7a31b606493ebf 100644 (file)
@@ -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],
index 09f22318ffc2d2556db18b8c1f485c0559be56e7..9809d9751ad804c70cda2667e16eeb3e88a70000 100644 (file)
@@ -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);
index 54596dbdfb014d0cf80e76124249c02bc3e48c00..ae7903e0ccfc4adf7041972be539d522aa896018 100644 (file)
@@ -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);
 }
index 1bc092a49e6185a941ef97346667e7b95dcd3d81..e950d0120d3697cc25e1ad955eb25d698112d3b0 100644 (file)
@@ -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
 
 
 ##############################################################################
index 6d870f355f927be3a5db22938dadf39f6c2a23e1..9ce2f2e8258fef7c78f68c0ecd7cee78d62c19ad 100644 (file)
@@ -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
 !
index f7c3a4c19d29333b20a99379e43df9a84835efae..92bb99c8f24e182b05e98e9c2f621b661ce5baca 100644 (file)
@@ -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")
 
index 6d4483acc4f7c2237df3c8810ebba002b6afe9c2..ec62d8d275a55153fad9ae129386029ee09beae5 100644 (file)
@@ -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
index 6d4483acc4f7c2237df3c8810ebba002b6afe9c2..ec62d8d275a55153fad9ae129386029ee09beae5 100644 (file)
@@ -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
index fa53a4291997cbea0e143c8445dc7331ae72b387..44f95b9bb33a8a68ce59c3e6ec2a9ab39124dae4 100644 (file)
@@ -1,5 +1,5 @@
 !
-debug bgp updates
+!debug bgp updates
 !
 router bgp 65010
  no bgp ebgp-requires-policy
index cdf8898c90d776247f4e3280b83965b28e79c29c..d60fdcf7cbaf57c3e15c105df59647c24d57d1d1 100644 (file)
@@ -1,5 +1,5 @@
 !
-debug bgp updates
+!debug bgp updates
 !
 router bgp 65020
  no bgp ebgp-requires-policy
index 109e0eadbb1dc103a2206824965d3fa2384fe5dd..15466b4259c28e326256cc5e297bc8cf6e8a38b1 100644 (file)
@@ -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
index 4f0a6ab0f1b7ecbe1db6b185969d8f89cd87c0ab..ad0ee3e471c0a309a701da72a3adebf22d422e5d 100644 (file)
@@ -1,5 +1,5 @@
 !
-debug bgp updates
+!debug bgp updates
 !
 router bgp 65001
  bgp router-id 10.10.10.101
index 35ad2d32e6d458fb563a7a442770cf74411243cb..98a9780688883e524b20e5e58493e6789c5934e8 100644 (file)
@@ -1,5 +1,5 @@
 !
-debug bgp updates
+!debug bgp updates
 !
 router bgp 65002
  no bgp ebgp-requires-policy
index 8413ef7fc37261e2c6011737bfbe93d3d9e5e8e7..107d2ad8d2049abc4ed67393e711914b6c89d3e4 100644 (file)
@@ -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
index 9f6a9852de06be0d663f7d21ca1d3f08dcbc0581..fe13dfe729943e8fda188ee90ce650ddcddb82cf 100644 (file)
@@ -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
index 3a018a42b30812cd2b302026113f63255d3c629e..74d5fd6e290c1e5d30270eb8cc443ebe66fe12b3 100644 (file)
@@ -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
index 134f221543ca818e42914b37a9e2d9948c9e94e0..89a85e5a34bb0026a46f687b4d20cf789a475e62 100644 (file)
@@ -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
index e2ff1df9657fbda8f24bddcceda0fe79aa1ba24d..2f76d59d4ab72018a49403c8ac2401adfc9e46d6 100644 (file)
@@ -1,5 +1,5 @@
 !
-debug bgp neighbor
+!debug bgp neighbor
 !
 router bgp 65001
  no bgp ebgp-requires-policy
index f8af210ed73a257c4c275c50c5e84c24ce4d7d5f..65c0c3532a9cc3189861f5f40da6232960014818 100755 (executable)
@@ -83,6 +83,7 @@ def build_topo(tgen):
     switch.add_link(tgen.gears["PE2"])
     switch.add_link(tgen.gears["host2"])
 
+
 def setup_pe_router(tgen, pe_name, tunnel_local_ip, svi_ip, intf):
     pe = tgen.gears[pe_name]
 
@@ -100,7 +101,9 @@ def setup_pe_router(tgen, pe_name, tunnel_local_ip, svi_ip, intf):
 
     # setup single vxlan device
     pe.run(
-        "ip link add dev vxlan0 type vxlan dstport 4789 local {0} nolearning external".format(tunnel_local_ip)
+        "ip link add dev vxlan0 type vxlan dstport 4789 local {0} nolearning external".format(
+            tunnel_local_ip
+        )
     )
     pe.run("ip link set dev vxlan0 master bridge")
     pe.run("bridge link set dev vxlan0 vlan_tunnel on")
@@ -136,10 +139,12 @@ def setup_pe_router(tgen, pe_name, tunnel_local_ip, svi_ip, intf):
         pe.run("bridge vlan add dev vxlan0 vid 300")
         pe.run("bridge vlan add dev vxlan0 vid 300 tunnel_info id 300")
 
+
 def setup_p_router(tgen, p_name):
     p1 = tgen.gears[p_name]
     p1.run("sysctl -w net.ipv4.ip_forward=1")
 
+
 def setup_module(mod):
     "Sets up the pytest environment"
 
@@ -180,7 +185,7 @@ def teardown_module(mod):
     "Teardown the pytest environment"
     tgen = get_topogen()
 
-    #tgen.mininet_cli()
+    # tgen.mininet_cli()
     # This function tears down the whole topology.
     tgen.stop_topology()
 
@@ -204,17 +209,21 @@ def check_vni_macs_present(tgen, router, vni, maclist):
             )
     return None
 
+
 def check_flood_entry_present(pe, vni, vtep):
     if not topotest.iproute2_is_fdb_get_capable():
         return None
 
-    output = pe.run("bridge fdb get 00:00:00:00:00:00 dev vxlan0 vni {} self".format(vni))
+    output = pe.run(
+        "bridge fdb get 00:00:00:00:00:00 dev vxlan0 vni {} self".format(vni)
+    )
 
     if str(vtep) not in output:
         return output
 
     return None
 
+
 def test_pe1_converge_evpn():
     "Wait for protocol convergence"
 
@@ -231,6 +240,15 @@ def test_pe1_converge_evpn():
     _, result = topotest.run_and_expect(test_func, None, count=45, wait=1)
     assertmsg = '"{}" JSON output mismatches'.format(pe1.name)
 
+    # Let's ensure that the hosts have actually tried talking to
+    # each other.  Otherwise under certain startup conditions
+    # they may not actually do any l2 arp'ing and as such
+    # the bridges won't know about the hosts on their networks
+    host1 = tgen.gears["host1"]
+    host1.run("ping -c 1 10.10.1.56")
+    host2 = tgen.gears["host2"]
+    host2.run("ping -c 1 10.10.1.55")
+
     test_func = partial(
         check_vni_macs_present,
         tgen,
@@ -249,11 +267,12 @@ def test_pe1_converge_evpn():
     assertmsg = '"{}" Flood FDB Entry for VTEP {} not found'.format(pe1.name, vtep)
     assert result is None, assertmsg
 
+
 def test_pe2_converge_evpn():
     "Wait for protocol convergence"
 
     tgen = get_topogen()
-#Don't run this test if we have any failure.
+    # Don't run this test if we have any failure.
     if tgen.routers_have_failure():
         pytest.skip(tgen.errors)
 
@@ -284,6 +303,7 @@ def test_pe2_converge_evpn():
     assertmsg = '"{}" Flood FDB Entry for VTEP {} not found'.format(pe2.name, vtep)
     assert result is None, assertmsg
 
+
 def mac_learn_test(host, local):
     "check the host MAC gets learned by the VNI"
 
@@ -389,11 +409,11 @@ def ip_learn_test(tgen, host, local, remote, ip_addr):
         if "HWaddr" in line_items[0]:
             mac = line_items[1]
             break
-    #print(host_output)
+    # print(host_output)
 
     # check we have a local association between the MAC and IP
     local_output = local.vtysh_cmd("show evpn mac vni 101 mac {} json".format(mac))
-    #print(local_output)
+    # print(local_output)
     local_output_json = json.loads(local_output)
     mac_type = local_output_json[mac]["type"]
     assertmsg = "Failed to learn local IP address on host {}".format(host.name)
@@ -417,7 +437,7 @@ def ip_learn_test(tgen, host, local, remote, ip_addr):
         remote_output = remote.vtysh_cmd(
             "show evpn mac vni 101 mac {} json".format(mac)
         )
-        #print(remote_output)
+        # print(remote_output)
         remote_output_json = json.loads(remote_output)
         type = remote_output_json[mac]["type"]
         if not remote_output_json[mac]["neighbors"] == "none":
@@ -431,12 +451,12 @@ def ip_learn_test(tgen, host, local, remote, ip_addr):
         count += 1
         sleep(1)
 
-    #print("tries: {}".format(count))
+    # print("tries: {}".format(count))
     assertmsg = "{} remote learned mac no address: {} ".format(host.name, mac)
     # some debug for this failure
     if not converged == True:
         log_output = remote.run("cat zebra.log")
-        #print(log_output)
+        # print(log_output)
 
     assert converged == True, assertmsg
     if remote_output_json[mac]["neighbors"]["active"]:
@@ -463,8 +483,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,13 +502,14 @@ 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")
     # tgen.mininet_cli()
 
+
 def show_dvni_route(pe, vni, prefix, vrf):
     output = pe.vtysh_cmd("show ip route vrf {} {}".format(vrf, prefix))
 
@@ -502,6 +523,7 @@ def show_dvni_route(pe, vni, prefix, vrf):
 
     return None
 
+
 def test_dvni():
     "test Downstream VNI works as expected importing into PE1"
 
@@ -517,7 +539,7 @@ def test_dvni():
     _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
     assertmsg = '"{}" DVNI route {} not found'.format(pe1.name, prefix)
     assert result is None, assertmsg
-    #tgen.mininet_cli()
+    # tgen.mininet_cli()
 
 
 def test_memory_leak():
index 48b79ab5eed6f2566a93917c6c67a9db9cd088e8..288404301215c98c21437af02d1f19165255f637 100755 (executable)
@@ -164,6 +164,15 @@ def test_pe1_converge_evpn():
     _, result = topotest.run_and_expect(test_func, None, count=45, wait=1)
     assertmsg = '"{}" JSON output mismatches'.format(pe1.name)
 
+    # Let's ensure that the hosts have actually tried talking to
+    # each other.  Otherwise under certain startup conditions
+    # they may not actually do any l2 arp'ing and as such
+    # the bridges won't know about the hosts on their networks
+    host1 = tgen.gears["host1"]
+    host1.run("ping -c 1 10.10.1.56")
+    host2 = tgen.gears["host2"]
+    host2.run("ping -c 1 10.10.1.55")
+
     test_func = partial(
         check_vni_macs_present,
         tgen,
@@ -171,6 +180,7 @@ def test_pe1_converge_evpn():
         101,
         (("host1", "host1-eth0"), ("host2", "host2-eth0")),
     )
+
     _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
     if result:
         logger.warning("%s", result)
@@ -385,8 +395,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 +414,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")
index eaa6aa4c3072c7269397c08cbc54a1fad118e45b..46993c7d9a4658be8d13caa2c842121a186b63b4 100644 (file)
@@ -62,6 +62,25 @@ else:
         "pass",
         "Adding {} routes".format(num),
     )
+    luCommand(
+        "ce1",
+        'vtysh -c "show ip route summ" | grep "sharp" | cut -d " " -f 33',
+        str(num),
+        "wait",
+        "See all sharp routes in rib on ce1",
+        wait,
+        wait_time=10,
+        )
+    luCommand(
+        "ce2",
+        'vtysh -c "show ip route summ" | grep "sharp" | cut -d " " -f 33',
+        str(num),
+        "wait",
+        "See all sharp routes in rib on ce2",
+        wait,
+        wait_time=10,
+        )
+
     rtrs = ["ce1", "ce2", "ce3"]
     for rtr in rtrs:
         luCommand(
index 3af779c427c24b12ea254f8c2823b08806fa1121..f4bb487e4091238245e75f3620267208c7a9d12e 100644 (file)
@@ -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_lu_explicitnull/r1/bgpd.conf b/tests/topotests/bgp_lu_explicitnull/r1/bgpd.conf
new file mode 100644 (file)
index 0000000..a31439c
--- /dev/null
@@ -0,0 +1,15 @@
+router bgp 65500
+ bgp router-id 192.0.2.1
+ no bgp ebgp-requires-policy
+ bgp labeled-unicast explicit-null
+ neighbor 192.0.2.2 remote-as 65501
+!
+ address-family ipv4 unicast
+  no neighbor 192.0.2.2 activate
+  network 192.168.2.1/32
+ exit-address-family
+ !
+ address-family ipv4 labeled-unicast
+  neighbor 192.0.2.2 activate
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_lu_explicitnull/r1/zebra.conf b/tests/topotests/bgp_lu_explicitnull/r1/zebra.conf
new file mode 100644 (file)
index 0000000..b845748
--- /dev/null
@@ -0,0 +1,6 @@
+interface r1-eth0
+ ip address 192.0.2.1/24
+!
+interface r1-eth1
+ ip address 192.168.2.1/32
+!
\ No newline at end of file
diff --git a/tests/topotests/bgp_lu_explicitnull/r2/bgpd.conf b/tests/topotests/bgp_lu_explicitnull/r2/bgpd.conf
new file mode 100644 (file)
index 0000000..41c2b9b
--- /dev/null
@@ -0,0 +1,15 @@
+router bgp 65501
+ bgp router-id 192.0.2.2
+ no bgp ebgp-requires-policy
+ bgp labeled-unicast explicit-null
+ neighbor 192.0.2.1 remote-as 65500
+!
+ address-family ipv4 unicast
+  no neighbor 192.0.2.1 activate
+  network 192.168.2.2/32
+ exit-address-family
+ !
+ address-family ipv4 labeled-unicast
+  neighbor 192.0.2.1 activate
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_lu_explicitnull/r2/zebra.conf b/tests/topotests/bgp_lu_explicitnull/r2/zebra.conf
new file mode 100644 (file)
index 0000000..9a63961
--- /dev/null
@@ -0,0 +1,6 @@
+interface r2-eth0
+ ip address 192.0.2.2/24
+!
+interface r2-eth1
+ ip address 192.168.2.2/32
+!
diff --git a/tests/topotests/bgp_lu_explicitnull/test_bgp_lu_explicitnull.py b/tests/topotests/bgp_lu_explicitnull/test_bgp_lu_explicitnull.py
new file mode 100644 (file)
index 0000000..d53ac68
--- /dev/null
@@ -0,0 +1,194 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: ISC
+#
+# test_bgp_explicitnull.py
+#
+# Part of NetDEF Topology Tests
+#
+# Copyright 2023 by 6WIND S.A.
+#
+
+"""
+test_bgp_lu_explicitnull.py: Test BGP LU label allocation
+"""
+
+import os
+import sys
+import json
+import functools
+import pytest
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+
+
+pytestmark = [pytest.mark.bgpd]
+
+
+# Basic scenario for BGP-LU. Nodes are directly connected.
+# The 192.168.2.2/32 prefix is advertised from r2 to r1
+# The explicit-null label should be used
+# The 192.168.2.1/32 prefix is advertised from r1 to r2
+# The explicit-null label should be used
+# Traffic from 192.168.2.1 to 192.168.2.2 should use explicit-null label
+#
+#  AS65500    BGP-LU        AS65501
+# +-----+                +-----+
+# |     |.1            .2|     |
+# |  1  +----------------+  2  + 192.168.0.2/32
+# |     |   192.0.2.0/24 |     |
+# +-----+                +-----+
+
+
+def build_topo(tgen):
+    "Build function"
+
+    # Create routers
+    tgen.add_router("r1")
+    tgen.add_router("r2")
+
+    # r1-r2
+    switch = tgen.add_switch("s1")
+    switch.add_link(tgen.gears["r1"])
+    switch.add_link(tgen.gears["r2"])
+
+    # r1
+    switch = tgen.add_switch("s2")
+    switch.add_link(tgen.gears["r1"])
+
+    # r2
+    switch = tgen.add_switch("s3")
+    switch.add_link(tgen.gears["r2"])
+
+
+def setup_module(mod):
+    "Sets up the pytest environment"
+    # This function initiates the topology build with Topogen...
+    tgen = Topogen(build_topo, mod.__name__)
+
+    # Skip if no mpls support
+    if not tgen.hasmpls:
+        logger.info("MPLS is not available, skipping test")
+        pytest.skip("MPLS is not available, skipping")
+        return
+
+    # ... and here it calls Mininet initialization functions.
+    tgen.start_topology()
+
+    # This is a sample of configuration loading.
+    router_list = tgen.routers()
+
+    # Enable mpls input for routers, so we can ping
+    sval = "net.mpls.conf.{}.input"
+    topotest.sysctl_assure(router_list["r2"], sval.format("r2-eth0"), 1)
+    topotest.sysctl_assure(router_list["r1"], sval.format("r1-eth0"), 1)
+
+    # For all registred 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_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
+        )
+
+    # After loading the configurations, this function loads configured daemons.
+    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 check_show_ip_label_prefix_found(router, ipversion, prefix, label):
+    output = json.loads(
+        router.vtysh_cmd("show {} route {} json".format(ipversion, prefix))
+    )
+    expected = {prefix: [{"prefix": prefix, "nexthops": [{"fib": True, "labels": [label]}]}]}
+    ret = topotest.json_cmp(output, expected)
+    if ret is None:
+        return "not good"
+    return None
+
+def test_converge_bgplu():
+    "Wait for protocol convergence"
+
+    tgen = get_topogen()
+    # Don't run this test if we have any failure.
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+
+    # tgen.mininet_cli();
+    r1 = tgen.gears["r1"]
+    r2 = tgen.gears["r2"]
+    # Check r1 gets prefix 192.168.2.2/32
+    test_func = functools.partial(
+        check_show_ip_label_prefix_found,
+        tgen.gears["r1"],
+        "ip",
+        "192.168.2.2/32",
+        "0",
+    )
+    success, result = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
+    assert (
+        success
+    ), "r1, prefix 192.168.2.2/32 from r2 not present"
+
+    # Check r2 gets prefix 192.168.2.1/32
+    test_func = functools.partial(
+        check_show_ip_label_prefix_found,
+        tgen.gears["r2"],
+        "ip",
+        "192.168.2.1/32",
+        "0",
+    )
+    success, result = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
+    assert (
+        success
+    ), "r2, prefix 192.168.2.1/32 from r1 not present"
+
+def test_traffic_connectivity():
+    "Wait for protocol convergence"
+
+    tgen = get_topogen()
+    # Don't run this test if we have any failure.
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+
+    def _check_ping(name, dest_addr, src_addr):
+        tgen = get_topogen()
+        output = tgen.gears[name].run("ping {} -c 1 -w 1 -I {}".format(dest_addr, src_addr))
+        logger.info(output)
+        if " 0% packet loss" not in output:
+            return True
+
+    logger.info("r1, check ping 192.168.2.2 from 192.168.2.1 is OK")
+    tgen = get_topogen()
+    func = functools.partial(_check_ping, "r1", "192.168.2.2", "192.168.2.1")
+    # tgen.mininet_cli()
+    success, result = topotest.run_and_expect(func, None, count=10, wait=0.5)
+    assert result is None, "r1, ping to 192.168.2.2 from 192.168.2.1 fails"
+
+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))
index 77f7c5581b22accb4453e160a3ab2b7a40f69c33..733205928f3e222f6bbaa0cfb1a893d23f06d5cc 100644 (file)
@@ -1,5 +1,5 @@
 !
-debug bgp updates
+!debug bgp updates
 !
 router bgp 65002
  no bgp ebgp-requires-policy
index 04dc73a06dbba1f52f9051f624755c8f42a1859f..e5325c91bcafdc206b3f52f556d59bdd37004777 100644 (file)
@@ -1,6 +1,6 @@
 !
-debug bgp updates
-debug bgp neighbor
+!debug bgp updates
+!debug bgp neighbor
 !
 bgp route-map delay-timer 5
 !
index c9ad0b1a5bd1b9535ea3b64778fd5c69d131a537..4aa11ec9d07f6736a4190af668ac343c28cda5bd 100644 (file)
@@ -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 (file)
index 0000000..1929dfa
--- /dev/null
@@ -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 (file)
index 0000000..673efc2
--- /dev/null
@@ -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))
index 3512e66cec608905b4c65962321b6c12ae21b9af..cf0013e1b7a1439549787348a3067de06192e524 100644 (file)
@@ -1,5 +1,5 @@
 !
-debug bgp updates
+!debug bgp updates
 !
 router bgp 65002
  no bgp ebgp-requires-policy
index a9319a6aeddbd454f50093d2f58b3f25d8a9fbcc..cbc5ce1f099d1671385289ae12be0a6e572f01dd 100644 (file)
@@ -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
index 9e5fa0ac073f6cd344754e296793c1b065e2d7cc..449ca74d5e9b5af09a5f31fecffa44710deb245b 100644 (file)
@@ -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
index 2c560dfc066b044d2335538ddc1bab896ad1b76f..f913b9f0029250ce55dc1f43b16dbd3b79660119 100644 (file)
@@ -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
index 8700f12d635c51890e209407ea70f84da0fa1811..4ab5b98c12a2bccbaaab7da269a173d6afa7cc26 100644 (file)
@@ -1,6 +1,6 @@
 frr defaults traditional
 !
-bgp send-extra-data zebra
+!bgp send-extra-data zebra
 !
 hostname r2
 password zebra
index b9277a9a8cdf2282050fe043c6f61b41e28770b1..201d0cce23f33c8e20483f8c1fe48eaa29afdb3a 100644 (file)
@@ -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
index caebb0e9221d81ec919b613a3e1ce94c70c13e6a..fb6980a13988448ccccc601e12ec8cd6e2f22e62 100644 (file)
@@ -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
index 010e86aad704a10ef0f86da60b1eaa857282d249..129b812036f4394dfe5165fa26761a6a587c5e03 100644 (file)
@@ -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
index 8d8f64158ff46c985c96f81a02991049be8e2c49..9f2ee19357e67eeb238a38d214ff2cdd96d6947d 100644 (file)
@@ -1,5 +1,5 @@
 !
-debug bgp neighbor
+!debug bgp neighbor
 !
 router bgp 65534 vrf public
  bgp router-id 10.0.0.1
index 8de6f9bf7082a0ef9bef54d856bf22aab1288811..5c1b97262c95eb8ba9cb4e8de553856d898b9abc 100644 (file)
@@ -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
index fc700608b5342f8a5078c5c876a0019b5bb1e90b..b3d10b07ecdb46e1c1c0ba48ffa3a59e4e3cf145 100644 (file)
@@ -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
index e5a1e758379c1aa312c9fc00eb0678e1f95e38f4..d19d8db75cbddf81b2356352389c9d9d4d65e15c 100644 (file)
@@ -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))
 
index 5a69c56d8dde7e259c18a7157e765d39b32d5991..edbd3600848a8497acda760eb443b5fb1738018a 100644 (file)
@@ -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
index 41da660b7d027afd1fae978147784cfd072efd47..f5b3ad06d94db26fb8b077f955a7d13faf809944 100644 (file)
@@ -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):
index d35b908e120ed9851dcefdbdd5c674b0f8465a2c..86a7f2000f3a683af86f7ee8bf12f322b5c08814 100644 (file)
@@ -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:
index 06c18d7dfae56dcb37f85f75d74048cae39f81d9..921b4e622cb811a06bdd1016efcc9d191ec5e801 100644 (file)
@@ -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)
index a76ff2dd9cf195ae98a0fc41f347cefa870288ed..87b04b41beb24e34b88c86367e72460a18762178 100644 (file)
@@ -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()
index ceef68fece03b9b0b451fce14374c835ab2bf709..788a839918b04da4c1c12324c3acd1a354ebd035 100644 (file)
@@ -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()
index 95b4004e14a837e437dc9c194c5d6690c7b55a99..977cd477c87e38fb92c87d5a8a607c25df0e15a8 100755 (executable)
@@ -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()
 
index 2fedb6e517e58eac224c3fdd3723b4aa644f0e45..a61164baa2c0a24aa22b49fe3dedf53c790c8388 100755 (executable)
@@ -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()
 
index 6c7cb9624082a1f1d6a40204b8d10f9210135dd2..e6e5733010fbcab259ad268fca5b039c7776c7d1 100644 (file)
@@ -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 (file)
index 0000000..e69de29
diff --git a/tests/topotests/ospf_nssa_topo1/rt1/ospfd.conf b/tests/topotests/ospf_nssa_topo1/rt1/ospfd.conf
new file mode 100644 (file)
index 0000000..6d23c84
--- /dev/null
@@ -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 (file)
index 0000000..7ba3dc7
--- /dev/null
@@ -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 (file)
index 0000000..ac34417
--- /dev/null
@@ -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 (file)
index 0000000..ac34417
--- /dev/null
@@ -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 (file)
index 0000000..ac34417
--- /dev/null
@@ -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 (file)
index 0000000..ac34417
--- /dev/null
@@ -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 (file)
index 0000000..6a05555
--- /dev/null
@@ -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 (file)
index 0000000..6a05555
--- /dev/null
@@ -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 (file)
index 0000000..2d3c8c4
--- /dev/null
@@ -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 (file)
index 0000000..6a05555
--- /dev/null
@@ -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 (file)
index 0000000..f41ee3b
--- /dev/null
@@ -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 (file)
index 0000000..2d3c8c4
--- /dev/null
@@ -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 (file)
index 0000000..1df1005
--- /dev/null
@@ -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 (file)
index 0000000..12884d2
--- /dev/null
@@ -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 (file)
index 0000000..b6d4233
--- /dev/null
@@ -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 (file)
index 0000000..c094117
--- /dev/null
@@ -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 (file)
index 0000000..c094117
--- /dev/null
@@ -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 (file)
index 0000000..a67dfb4
--- /dev/null
@@ -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 (file)
index 0000000..c094117
--- /dev/null
@@ -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 (file)
index 0000000..c7dd93c
--- /dev/null
@@ -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 (file)
index 0000000..9c3cfff
--- /dev/null
@@ -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 (file)
index 0000000..f6bbdfa
--- /dev/null
@@ -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 (file)
index 0000000..c7dd93c
--- /dev/null
@@ -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 (file)
index 0000000..c7dd93c
--- /dev/null
@@ -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 (file)
index 0000000..c094117
--- /dev/null
@@ -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 (file)
index 0000000..fa274eb
--- /dev/null
@@ -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 (file)
index 0000000..9691a7c
--- /dev/null
@@ -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 (file)
index 0000000..f0edd6c
--- /dev/null
@@ -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 (file)
index 0000000..a2d078a
--- /dev/null
@@ -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 (file)
index 0000000..4619067
--- /dev/null
@@ -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 (file)
index 0000000..a2d078a
--- /dev/null
@@ -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 (file)
index 0000000..a2d078a
--- /dev/null
@@ -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 (file)
index 0000000..1038721
--- /dev/null
@@ -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 (file)
index 0000000..4f8eaf1
--- /dev/null
@@ -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 (file)
index 0000000..41e9f67
--- /dev/null
@@ -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 (file)
index 0000000..1038721
--- /dev/null
@@ -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 (file)
index 0000000..4619067
--- /dev/null
@@ -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 (file)
index 0000000..4619067
--- /dev/null
@@ -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 (file)
index 0000000..d943540
--- /dev/null
@@ -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 (file)
index 0000000..cba7cf7
--- /dev/null
@@ -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 (file)
index 0000000..e00ee5d
--- /dev/null
@@ -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 (file)
index 0000000..e57f542
--- /dev/null
@@ -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 (file)
index 0000000..82a0e1a
--- /dev/null
@@ -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 (file)
index 0000000..e57f542
--- /dev/null
@@ -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 (file)
index 0000000..e57f542
--- /dev/null
@@ -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 (file)
index 0000000..5f51b3b
--- /dev/null
@@ -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 (file)
index 0000000..5f51b3b
--- /dev/null
@@ -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 (file)
index 0000000..5f51b3b
--- /dev/null
@@ -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 (file)
index 0000000..5f51b3b
--- /dev/null
@@ -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 (file)
index 0000000..82a0e1a
--- /dev/null
@@ -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 (file)
index 0000000..82a0e1a
--- /dev/null
@@ -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 (file)
index 0000000..588febe
--- /dev/null
@@ -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 (file)
index 0000000..432ddf0
--- /dev/null
@@ -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))
index 5b1a53b895b33323c7238185731870c92acf29fd..d5583ac06abb3220c98277138b55d318cdc25772 100644 (file)
@@ -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):
index 6f23294a1adddea957ad4cd7a97f59bfd70e3adc..7199f160fe5b94e38759d2bac235269de03bdf51 100644 (file)
@@ -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 (file)
index 0000000..e69de29
diff --git a/tests/topotests/rip_allow_ecmp/r1/frr.conf b/tests/topotests/rip_allow_ecmp/r1/frr.conf
new file mode 100644 (file)
index 0000000..d8eb9a3
--- /dev/null
@@ -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 (file)
index 0000000..d7ea6f3
--- /dev/null
@@ -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 (file)
index 0000000..2362c47
--- /dev/null
@@ -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 (file)
index 0000000..b0ba146
--- /dev/null
@@ -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))
index 6137471ea69096795015fd037dd6b94568c202ef..e2863218b0c1546f49e5d3e045c15d293f82e126 100644 (file)
@@ -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()
 
index 66ec6a410d5b682c6086183ebc7b1d26573dec46..de925b48238a887dd62f37e0f5edafe775ff71c9 100644 (file)
@@ -1594,6 +1594,13 @@ module frr-isisd {
           "Log changes to the IS-IS adjacencies in this area.";
       }
 
+      leaf log-pdu-drops {
+        type boolean;
+        default "false";
+        description
+          "Log any dropped PDUs in this area.";
+      }
+
       container mpls-te {
         presence "Present if MPLS-TE is enabled.";
         description
index 746bf35d28fe286b80ba87c67cd67f6dc87d22d8..24fe58885446a6126ed8d17d567b846924a1cd90 100644 (file)
@@ -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.";
index b13daa3a97bc6d1309cab3ac866c0282b237a98b..fc140b07a34dbe1ba398f383c5eeb6423f338632 100644 (file)
@@ -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));
index 03376afc09f7d3938e610aa7dfcd4a14df0380bc..496a85e676af8878847331c9e03ba0959aac30cd 100644 (file)
@@ -137,6 +137,8 @@ static int if_zebra_new_hook(struct interface *ifp)
        zebra_if->multicast = IF_ZEBRA_DATA_UNSPEC;
        zebra_if->shutdown = IF_ZEBRA_DATA_OFF;
 
+       zebra_if->link_nsid = NS_UNKNOWN;
+
        zebra_if_nhg_dependents_init(zebra_if);
 
        zebra_ptm_if_init(zebra_if);
@@ -305,6 +307,14 @@ struct interface *if_lookup_by_name_per_ns(struct zebra_ns *ns,
        return NULL;
 }
 
+struct interface *if_lookup_by_index_per_nsid(ns_id_t ns_id, uint32_t ifindex)
+{
+       struct zebra_ns *zns;
+
+       zns = zebra_ns_lookup(ns_id);
+       return zns ? if_lookup_by_index_per_ns(zns, ifindex) : NULL;
+}
+
 const char *ifindex2ifname_per_ns(struct zebra_ns *zns, unsigned int ifindex)
 {
        struct interface *ifp;
@@ -991,7 +1001,6 @@ void if_up(struct interface *ifp, bool install_connected)
 {
        struct zebra_if *zif;
        struct interface *link_if;
-       struct zebra_vrf *zvrf = ifp->vrf->info;
 
        zif = ifp->info;
        zif->up_count++;
@@ -1024,8 +1033,7 @@ void if_up(struct interface *ifp, bool install_connected)
                link_if = ifp;
                zebra_vxlan_svi_up(ifp, link_if);
        } else if (IS_ZEBRA_IF_VLAN(ifp)) {
-               link_if = if_lookup_by_index_per_ns(zvrf->zns,
-                                                   zif->link_ifindex);
+               link_if = zif->link;
                if (link_if)
                        zebra_vxlan_svi_up(ifp, link_if);
        } else if (IS_ZEBRA_IF_MACVLAN(ifp)) {
@@ -1049,7 +1057,6 @@ void if_down(struct interface *ifp)
 {
        struct zebra_if *zif;
        struct interface *link_if;
-       struct zebra_vrf *zvrf = ifp->vrf->info;
 
        zif = ifp->info;
        zif->down_count++;
@@ -1068,8 +1075,7 @@ void if_down(struct interface *ifp)
                link_if = ifp;
                zebra_vxlan_svi_down(ifp, link_if);
        } else if (IS_ZEBRA_IF_VLAN(ifp)) {
-               link_if = if_lookup_by_index_per_ns(zvrf->zns,
-                                                   zif->link_ifindex);
+               link_if = zif->link;
                if (link_if)
                        zebra_vxlan_svi_down(ifp, link_if);
        } else if (IS_ZEBRA_IF_MACVLAN(ifp)) {
@@ -1109,6 +1115,7 @@ void zebra_if_update_link(struct interface *ifp, ifindex_t link_ifindex,
        if (IS_ZEBRA_IF_VETH(ifp))
                return;
        zif = (struct zebra_if *)ifp->info;
+       zif->link_nsid = ns_id;
        zif->link_ifindex = link_ifindex;
        zif->link = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id),
                                              link_ifindex);
@@ -1145,8 +1152,8 @@ void zebra_if_update_all_links(struct zebra_ns *zns)
 
                /* update SVI linkages */
                if ((zif->link_ifindex != IFINDEX_INTERNAL) && !zif->link) {
-                       zif->link = if_lookup_by_index_per_ns(
-                               zns, zif->link_ifindex);
+                       zif->link = if_lookup_by_index_per_nsid(
+                               zif->link_nsid, zif->link_ifindex);
                        if (IS_ZEBRA_DEBUG_KERNEL)
                                zlog_debug("interface %s/%d's lower fixup to %s/%d",
                                                ifp->name, ifp->ifindex,
index 4c6ebaa11dd784731ae082f0c5313a04b7adc431..e5545d6ba0895826ccdda777ee94050ef7116fb5 100644 (file)
@@ -195,6 +195,7 @@ struct zebra_if {
        struct list *mac_list;
 
        /* Link fields - for sub-interfaces. */
+       ns_id_t link_nsid;
        ifindex_t link_ifindex;
        struct interface *link;
 
@@ -259,6 +260,8 @@ extern struct interface *if_lookup_by_index_per_ns(struct zebra_ns *, uint32_t);
 extern struct interface *if_lookup_by_name_per_ns(struct zebra_ns *,
                                                  const char *);
 extern struct interface *if_link_per_ns(struct zebra_ns *, struct interface *);
+extern struct interface *if_lookup_by_index_per_nsid(ns_id_t nsid,
+                                                    uint32_t ifindex);
 extern const char *ifindex2ifname_per_ns(struct zebra_ns *, unsigned int);
 
 extern void if_unlink_per_ns(struct interface *);
index ba43ae910b175538e51aa9caffdafc975c5343c2..81a30664453a5e43ebd247a7ae8a919bb7817afc 100644 (file)
@@ -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();
 
index 0e897881e440d4cb0c7774b967a0c187f4271ef7..a56bb05d684ef3731ce7e43788cc99d6c01745ea 100644 (file)
@@ -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;
index fb1ebc682737d76fcf7e0a27006ebc9b95c69409..f9253ebf76cb6d7d9e3ac16a470008fa65291bd0 100644 (file)
@@ -6853,10 +6853,6 @@ void zebra_dplane_shutdown(void)
 
        zdplane_info.dg_run = false;
 
-       if (zdplane_info.dg_t_update)
-               event_cancel_async(zdplane_info.dg_t_update->master,
-                                  &zdplane_info.dg_t_update, NULL);
-
        frr_pthread_stop(zdplane_info.dg_pthread, NULL);
 
        /* Destroy pthread */
index 96d598f7c424b33bd3b5e995bdf01aa5d40c968e..cf2056b7acfd1cfd89088417bc2bddaab818da8d 100644 (file)
@@ -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,106 +384,53 @@ 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);
+}
index 7a9d0c0ed6219749f242ff3966d023fb8fc4937f..32cfa4d04c97da359d4e631f7df3bdb84c767bce 100644 (file)
@@ -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,
index d9a7ee465a9fcb2d8f86cf612f13deb863681ef2..142501b14994168e08158bb9439f53bc7b301552 100644 (file)
@@ -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);
index c370ad9169d836c80cd4599cf409aa1528d4a24e..36290f99e0d1d9d3e2dd2c52a773f446e247d6d3 100644 (file)
@@ -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)
index 70707866ee286092a81865de8881c8e1527ea4fc..6abd49310c5acae58fa6febdfa8e75d0d7ffaae2 100644 (file)
@@ -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");
index aa58a3a29948c5942c78416caa833314c3712098..90aa4d53f46d647e02c7c530b9d1b00fb96bc3cc 100644 (file)
@@ -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;