summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/lib/test_printfrr.c115
-rw-r--r--tests/lib/test_table.c4
-rw-r--r--tests/topotests/all-protocol-startup/r1/show_bgp_ipv4-post4.1.ref1
-rw-r--r--tests/topotests/all-protocol-startup/r1/show_bgp_ipv4-post5.0.ref1
-rw-r--r--tests/topotests/all-protocol-startup/r1/show_bgp_ipv4-post6.1.ref1
-rw-r--r--tests/topotests/all-protocol-startup/r1/show_bgp_ipv6-post4.1.ref1
-rw-r--r--tests/topotests/all-protocol-startup/r1/show_bgp_ipv6_post6.1.ref1
-rw-r--r--tests/topotests/all-protocol-startup/test_all_protocol_startup.py12
-rw-r--r--tests/topotests/bfd-profiles-topo1/r1/bfd-peers-initial.json4
-rw-r--r--tests/topotests/bfd-profiles-topo1/r1/ospfd.conf2
-rw-r--r--tests/topotests/bfd-profiles-topo1/r6/bfd-peers-initial.json4
-rw-r--r--tests/topotests/bgp-default-ipv4-ipv6-unicast/__init__.py0
-rw-r--r--tests/topotests/bgp-default-ipv4-ipv6-unicast/r1/bgpd.conf3
-rw-r--r--tests/topotests/bgp-default-ipv4-ipv6-unicast/r1/zebra.conf7
-rw-r--r--tests/topotests/bgp-default-ipv4-ipv6-unicast/r2/bgpd.conf5
-rw-r--r--tests/topotests/bgp-default-ipv4-ipv6-unicast/r2/zebra.conf6
-rw-r--r--tests/topotests/bgp-default-ipv4-ipv6-unicast/r3/bgpd.conf4
-rw-r--r--tests/topotests/bgp-default-ipv4-ipv6-unicast/r3/zebra.conf6
-rw-r--r--tests/topotests/bgp-default-ipv4-ipv6-unicast/test_bgp-default-ipv4-ipv6-unicast.py140
-rw-r--r--tests/topotests/bgp-ebgp-common-subnet-nexthop-unchanged/__init__.py0
-rw-r--r--tests/topotests/bgp-ebgp-common-subnet-nexthop-unchanged/r1/bgpd.conf7
-rw-r--r--tests/topotests/bgp-ebgp-common-subnet-nexthop-unchanged/r1/zebra.conf7
-rw-r--r--tests/topotests/bgp-ebgp-common-subnet-nexthop-unchanged/r2/bgpd.conf3
-rw-r--r--tests/topotests/bgp-ebgp-common-subnet-nexthop-unchanged/r2/zebra.conf4
-rw-r--r--tests/topotests/bgp-ebgp-common-subnet-nexthop-unchanged/r3/bgpd.conf5
-rw-r--r--tests/topotests/bgp-ebgp-common-subnet-nexthop-unchanged/r3/zebra.conf4
-rw-r--r--tests/topotests/bgp-ebgp-common-subnet-nexthop-unchanged/test_bgp-ebgp-common-subnet-nexthop-unchanged.py127
-rw-r--r--tests/topotests/bgp-ecmp-topo1/test_bgp_ecmp_topo1.py4
-rw-r--r--tests/topotests/bgp-ecmp-topo2/test_ebgp_ecmp_topo2.py4
-rw-r--r--tests/topotests/bgp-ecmp-topo2/test_ibgp_ecmp_topo2.py4
-rw-r--r--tests/topotests/bgp-evpn-mh/test_evpn_mh.py2
-rwxr-xr-xtests/topotests/bgp-snmp-mplsl3vpn/test_bgp_snmp_mplsvpn.py6
-rw-r--r--tests/topotests/bgp_evpn_rt5/test_bgp_evpn.py12
-rw-r--r--tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1.py227
-rw-r--r--tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2.py225
-rwxr-xr-xtests/topotests/bgp_instance_del_test/test_bgp_instance_del_test.py3
-rw-r--r--tests/topotests/bgp_ipv6_rtadv/test_bgp_ipv6_rtadv.py3
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_vrf/customize.py24
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_vrf.py3
-rw-r--r--tests/topotests/bgp_large_community/test_bgp_large_community_topo_2.py24
-rw-r--r--tests/topotests/bgp_lu_topo1/test_bgp_lu.py4
-rw-r--r--tests/topotests/bgp_multi_vrf_topo1/test_bgp_multi_vrf_topo1.py30
-rw-r--r--tests/topotests/bgp_multi_vrf_topo2/test_bgp_multi_vrf_topo2.py26
-rw-r--r--tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_1-post4.1.ref1
-rw-r--r--tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_1-post6.1.ref1
-rw-r--r--tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_2-post4.1.ref1
-rw-r--r--tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_2-post6.1.ref1
-rw-r--r--tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_3-post4.1.ref1
-rw-r--r--tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_3-post6.1.ref1
-rw-r--r--tests/topotests/bgp_peer-group/test_bgp_peer-group.py3
-rw-r--r--tests/topotests/bgp_peer-type_multipath-relax/exabgp.env53
-rwxr-xr-xtests/topotests/bgp_peer-type_multipath-relax/peer1/exa-receive.py38
-rw-r--r--tests/topotests/bgp_peer-type_multipath-relax/peer1/exa_readpipe.py19
-rw-r--r--tests/topotests/bgp_peer-type_multipath-relax/peer1/exabgp.cfg21
-rwxr-xr-xtests/topotests/bgp_peer-type_multipath-relax/peer2/exa-receive.py38
-rw-r--r--tests/topotests/bgp_peer-type_multipath-relax/peer2/exa_readpipe.py19
-rw-r--r--tests/topotests/bgp_peer-type_multipath-relax/peer2/exabgp.cfg21
-rwxr-xr-xtests/topotests/bgp_peer-type_multipath-relax/peer3/exa-receive.py38
-rw-r--r--tests/topotests/bgp_peer-type_multipath-relax/peer3/exa_readpipe.py19
-rw-r--r--tests/topotests/bgp_peer-type_multipath-relax/peer3/exabgp.cfg21
-rwxr-xr-xtests/topotests/bgp_peer-type_multipath-relax/peer4/exa-receive.py38
-rw-r--r--tests/topotests/bgp_peer-type_multipath-relax/peer4/exa_readpipe.py19
-rw-r--r--tests/topotests/bgp_peer-type_multipath-relax/peer4/exabgp.cfg21
-rw-r--r--tests/topotests/bgp_peer-type_multipath-relax/r1/bgpd.conf16
-rw-r--r--tests/topotests/bgp_peer-type_multipath-relax/r1/multipath.json50
-rw-r--r--tests/topotests/bgp_peer-type_multipath-relax/r1/not-multipath.json50
-rw-r--r--tests/topotests/bgp_peer-type_multipath-relax/r1/prefix1-eBGP-confed.json33
-rw-r--r--tests/topotests/bgp_peer-type_multipath-relax/r1/prefix1-eBGP-iBGP.json33
-rw-r--r--tests/topotests/bgp_peer-type_multipath-relax/r1/prefix1-no-recursive.json35
-rw-r--r--tests/topotests/bgp_peer-type_multipath-relax/r1/prefix1-recursive.json36
-rw-r--r--tests/topotests/bgp_peer-type_multipath-relax/r1/prefix1.json33
-rw-r--r--tests/topotests/bgp_peer-type_multipath-relax/r1/prefix3-ip-route.json23
-rw-r--r--tests/topotests/bgp_peer-type_multipath-relax/r1/prefix3-no-recursive.json21
-rw-r--r--tests/topotests/bgp_peer-type_multipath-relax/r1/prefix3-recursive.json23
-rw-r--r--tests/topotests/bgp_peer-type_multipath-relax/r1/zebra.conf27
-rw-r--r--tests/topotests/bgp_peer-type_multipath-relax/r2/bgpd.conf19
-rw-r--r--tests/topotests/bgp_peer-type_multipath-relax/r2/staticd.conf4
-rw-r--r--tests/topotests/bgp_peer-type_multipath-relax/r2/zebra.conf19
-rwxr-xr-xtests/topotests/bgp_peer-type_multipath-relax/test_bgp_peer-type_multipath-relax.py386
-rw-r--r--tests/topotests/bgp_recursive_route_ebgp_multi_hop/test_bgp_recursive_route_ebgp_multi_hop.py102
-rw-r--r--tests/topotests/bgp_sender-as-path-loop-detection/test_bgp_sender-as-path-loop-detection.py3
-rw-r--r--tests/topotests/bgp_vrf_dynamic_route_leak/test_bgp_vrf_dynamic_route_leak_topo1.py7
-rw-r--r--tests/topotests/bgp_vrf_lite_ipv6_rtadv/test_bgp_vrf_lite_ipv6_rtadv.py28
-rwxr-xr-xtests/topotests/conftest.py187
-rwxr-xr-xtests/topotests/isis-snmp/test_isis_snmp.py98
-rw-r--r--tests/topotests/isis-topo1-vrf/r1/r1_topology.json82
-rw-r--r--tests/topotests/isis-topo1-vrf/r2/r2_topology.json84
-rw-r--r--tests/topotests/isis-topo1-vrf/r3/r3_topology.json158
-rw-r--r--tests/topotests/isis-topo1-vrf/r4/r4_topology.json158
-rw-r--r--tests/topotests/isis-topo1-vrf/r5/r5_topology.json160
-rw-r--r--tests/topotests/isis-topo1-vrf/test_isis_topo1_vrf.py123
-rw-r--r--tests/topotests/ldp-snmp/test_ldp_snmp_topo1.py191
-rw-r--r--tests/topotests/lib/bgp.py9
-rw-r--r--tests/topotests/lib/common_config.py192
-rw-r--r--tests/topotests/lib/ospf.py4
-rw-r--r--tests/topotests/lib/topotest.py163
-rw-r--r--tests/topotests/multicast-pim-bsm-topo1/test_mcast_pim_bsmp_01.py72
-rw-r--r--tests/topotests/multicast-pim-bsm-topo2/test_mcast_pim_bsmp_02.py18
-rwxr-xr-xtests/topotests/multicast-pim-sm-topo3/test_multicast_pim_sm_topo3.py16
-rwxr-xr-xtests/topotests/multicast-pim-sm-topo3/test_multicast_pim_sm_topo4.py62
-rwxr-xr-xtests/topotests/multicast-pim-static-rp-topo1/test_multicast_pim_static_rp.py353
-rw-r--r--tests/topotests/nhrp-topo/r1/nhrp4_cache.json29
-rw-r--r--tests/topotests/nhrp-topo/r1/nhrp_route4.json25
-rw-r--r--tests/topotests/nhrp-topo/r1/nhrpd.conf10
-rw-r--r--tests/topotests/nhrp-topo/r1/zebra.conf12
-rw-r--r--tests/topotests/nhrp-topo/r2/nhrp4_cache.json29
-rw-r--r--tests/topotests/nhrp-topo/r2/nhrp_route4.json25
-rw-r--r--tests/topotests/nhrp-topo/r2/nhrpd.conf10
-rw-r--r--tests/topotests/nhrp-topo/r2/zebra.conf12
-rw-r--r--tests/topotests/nhrp-topo/r3/zebra.conf11
-rw-r--r--tests/topotests/nhrp-topo/test_nhrp_topo.dot73
-rw-r--r--tests/topotests/nhrp-topo/test_nhrp_topo.py221
-rw-r--r--tests/topotests/ospf-sr-topo1/test_ospf_sr_topo1.py7
-rwxr-xr-xtests/topotests/ospf-te-topo1/__init__.py0
-rw-r--r--tests/topotests/ospf-te-topo1/r1/ospfd.conf23
-rw-r--r--tests/topotests/ospf-te-topo1/r1/zebra.conf21
-rw-r--r--tests/topotests/ospf-te-topo1/r2/ospfd.conf34
-rw-r--r--tests/topotests/ospf-te-topo1/r2/zebra.conf33
-rw-r--r--tests/topotests/ospf-te-topo1/r3/ospfd.conf24
-rw-r--r--tests/topotests/ospf-te-topo1/r3/zebra.conf22
-rw-r--r--tests/topotests/ospf-te-topo1/r4/ospfd.conf22
-rw-r--r--tests/topotests/ospf-te-topo1/r4/zebra.conf12
-rw-r--r--tests/topotests/ospf-te-topo1/reference/ted_step1.json577
-rw-r--r--tests/topotests/ospf-te-topo1/reference/ted_step2.json477
-rw-r--r--tests/topotests/ospf-te-topo1/reference/ted_step3.json409
-rw-r--r--tests/topotests/ospf-te-topo1/reference/ted_step4.json490
-rw-r--r--tests/topotests/ospf-te-topo1/reference/ted_step5.json614
-rw-r--r--tests/topotests/ospf-te-topo1/reference/ted_step6.json615
-rw-r--r--tests/topotests/ospf-te-topo1/reference/ted_step7.json456
-rw-r--r--tests/topotests/ospf-te-topo1/test_ospf_te_topo1.py300
-rw-r--r--tests/topotests/ospf-topo1/r1/ospf6d.conf-pre-v49
-rw-r--r--tests/topotests/ospf-topo1/r2/ospf6d.conf-pre-v49
-rw-r--r--tests/topotests/ospf-topo1/r3/ospf6d.conf-pre-v410
-rw-r--r--tests/topotests/ospf-topo1/r4/ospf6d.conf-pre-v49
-rw-r--r--tests/topotests/ospf-topo1/test_ospf_topo1.py84
-rw-r--r--tests/topotests/ospf6-topo1/r1/ospf6d.conf4
-rw-r--r--tests/topotests/ospf6-topo1/r2/ospf6d.conf4
-rw-r--r--tests/topotests/ospf6-topo1/r3/ospf6d.conf6
-rw-r--r--tests/topotests/ospf6-topo1/r4/ospf6d.conf4
-rw-r--r--tests/topotests/ospf6-topo1/test_ospf6_topo1.py78
-rw-r--r--tests/topotests/ospf6-topo2/r1/ospf6d.conf9
-rw-r--r--tests/topotests/ospf6-topo2/r1/zebra.conf5
-rw-r--r--tests/topotests/ospf6-topo2/r2/ospf6d.conf17
-rw-r--r--tests/topotests/ospf6-topo2/r2/zebra.conf8
-rw-r--r--tests/topotests/ospf6-topo2/r3/ospf6d.conf10
-rw-r--r--tests/topotests/ospf6-topo2/r3/zebra.conf8
-rw-r--r--tests/topotests/ospf6-topo2/test_ospf6_topo2.dot71
-rw-r--r--tests/topotests/ospf6-topo2/test_ospf6_topo2.pngbin0 -> 31523 bytes
-rw-r--r--tests/topotests/ospf6-topo2/test_ospf6_topo2.py184
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_chaos.py38
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_ecmp.py42
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_ecmp_lan.py14
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_lan.py7
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_routemaps.py98
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py32
-rwxr-xr-xtests/topotests/ospf_suppress_fa/__init__.py0
-rw-r--r--tests/topotests/ospf_suppress_fa/r1/ospfd.conf9
-rw-r--r--tests/topotests/ospf_suppress_fa/r1/zebra.conf4
-rw-r--r--tests/topotests/ospf_suppress_fa/r2/ospfd.conf16
-rw-r--r--tests/topotests/ospf_suppress_fa/r2/zebra.conf7
-rw-r--r--tests/topotests/ospf_suppress_fa/r3/ospfd.conf11
-rw-r--r--tests/topotests/ospf_suppress_fa/r3/zebra.conf8
-rw-r--r--tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.dot66
-rw-r--r--tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.dot.jpgbin0 -> 33501 bytes
-rw-r--r--tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.py192
-rw-r--r--tests/topotests/static_routing_with_ebgp/test_static_routes_topo4_ebgp.py7
-rw-r--r--tests/topotests/static_routing_with_ibgp/test_static_routes_topo4_ibgp.py7
167 files changed, 8848 insertions, 1359 deletions
diff --git a/tests/lib/test_printfrr.c b/tests/lib/test_printfrr.c
index 24de3fa88d..21b3a916b8 100644
--- a/tests/lib/test_printfrr.c
+++ b/tests/lib/test_printfrr.c
@@ -59,21 +59,88 @@ static void printcmp(const char *fmt, ...)
errors++;
}
-static void printchk(const char *ref, const char *fmt, ...) PRINTFRR(2, 3);
-static void printchk(const char *ref, const char *fmt, ...)
+static int printchk(const char *ref, const char *fmt, ...) PRINTFRR(2, 3);
+static int printchk(const char *ref, const char *fmt, ...)
{
va_list ap;
char bufrr[256];
+ bool truncfail = false;
+ size_t i;
+ size_t expectlen;
+
memset(bufrr, 0xcc, sizeof(bufrr));
va_start(ap, fmt);
- vsnprintfrr(bufrr, sizeof(bufrr), fmt, ap);
+ expectlen = vsnprintfrr(NULL, 0, fmt, ap);
+ va_end(ap);
+
+ va_start(ap, fmt);
+ vsnprintfrr(bufrr, 7, fmt, ap);
va_end(ap);
- printf("fmt: \"%s\"\nref: \"%s\"\nfrr: \"%s\"\n%s\n\n",
+ if (strnlen(bufrr, 7) == 7)
+ truncfail = true;
+ if (strnlen(bufrr, 7) < 7 && strncmp(ref, bufrr, 6) != 0)
+ truncfail = true;
+ for (i = 7; i < sizeof(bufrr); i++)
+ if (bufrr[i] != (char)0xcc) {
+ truncfail = true;
+ break;
+ }
+
+ if (truncfail) {
+ printf("truncation test FAILED:\n"
+ "fmt: \"%s\"\nref: \"%s\"\nfrr[:7]: \"%s\"\n%s\n\n",
+ fmt, ref, bufrr, strcmp(ref, bufrr) ? "ERROR" : "ok");
+ errors++;
+ }
+
+ struct fmt_outpos outpos[16];
+ struct fbuf fb = {
+ .buf = bufrr,
+ .pos = bufrr,
+ .len = sizeof(bufrr) - 1,
+ .outpos = outpos,
+ .outpos_n = array_size(outpos),
+ };
+
+ va_start(ap, fmt);
+ vbprintfrr(&fb, fmt, ap);
+ fb.pos[0] = '\0';
+ va_end(ap);
+
+ printf("fmt: \"%s\"\nref: \"%s\"\nfrr: \"%s\"\n%s\n",
fmt, ref, bufrr, strcmp(ref, bufrr) ? "ERROR" : "ok");
if (strcmp(ref, bufrr))
errors++;
+ if (strlen(bufrr) != expectlen) {
+ printf("return value <> length mismatch\n");
+ errors++;
+ }
+
+ for (size_t i = 0; i < fb.outpos_i; i++)
+ printf("\t[%zu: %u..%u] = \"%.*s\"\n", i,
+ outpos[i].off_start,
+ outpos[i].off_end,
+ (int)(outpos[i].off_end - outpos[i].off_start),
+ bufrr + outpos[i].off_start);
+ printf("\n");
+ return 0;
+}
+
+static void test_va(const char *ref, const char *fmt, ...) PRINTFRR(2, 3);
+static void test_va(const char *ref, const char *fmt, ...)
+{
+ struct va_format vaf;
+ va_list ap;
+
+ va_start(ap, fmt);
+ vaf.fmt = fmt;
+ vaf.va = &ap;
+
+ printchk(ref, "VA [%pVA] %s", &vaf, "--");
+
+ va_end(ap);
}
int main(int argc, char **argv)
@@ -112,9 +179,12 @@ int main(int argc, char **argv)
inet_aton("192.168.1.2", &ip);
printchk("192.168.1.2", "%pI4", &ip);
printchk(" 192.168.1.2", "%20pI4", &ip);
+ printchk("192.168.1.2 ", "%-20pI4", &ip);
printcmp("%p", &ip);
+ test_va("VA [192.168.1.2 1234] --", "%pI4 %u", &ip, 1234);
+
snprintfrr(buf, sizeof(buf), "test%s", "#1");
csnprintfrr(buf, sizeof(buf), "test%s", "#2");
assert(strcmp(buf, "test#1test#2") == 0);
@@ -146,5 +216,42 @@ int main(int argc, char **argv)
sg.src.s_addr = INADDR_ANY;
printchk("(*,224.1.2.3)", "%pSG4", &sg);
+ uint8_t randhex[] = { 0x12, 0x34, 0x00, 0xca, 0xfe, 0x00, 0xaa, 0x55 };
+
+ FMT_NSTD(printchk("12 34 00 ca fe 00 aa 55", "%.8pHX", randhex));
+ FMT_NSTD(printchk("12 34 00 ca fe 00 aa 55", "%.*pHX",
+ (int)sizeof(randhex), randhex));
+ FMT_NSTD(printchk("12 34 00 ca", "%.4pHX", randhex));
+
+ printchk("12 34 00 ca fe 00 aa 55", "%8pHX", randhex);
+ printchk("12 34 00 ca fe 00 aa 55", "%*pHX",
+ (int)sizeof(randhex), randhex);
+ printchk("12 34 00 ca", "%4pHX", randhex);
+
+ printchk("", "%pHX", randhex);
+
+ printchk("12:34:00:ca:fe:00:aa:55", "%8pHXc", randhex);
+ printchk("123400cafe00aa55", "%8pHXn", randhex);
+
+ printchk("/test/pa\\ th/\\~spe\\ncial\\x01/file.name", "%pSE",
+ "/test/pa th/~spe\ncial\x01/file.name");
+ printchk("/test/pa\\ th/\\~spe\\n", "%17pSE",
+ "/test/pa th/~spe\ncial\x01/file.name");
+
+ char nulltest[] = { 'n', 'u', 0, 'l', 'l' };
+
+ printchk("nu\\x00ll", "%5pSE", nulltest);
+ printchk("nu\\x00ll", "%*pSE", 5, nulltest);
+
+ printchk("bl\\\"ah\\x01te[st\\nab]c", "%pSQ",
+ "bl\"ah\x01te[st\nab]c");
+ printchk("\"bl\\\"ah\\x01te[st\\nab]c\"", "%pSQq",
+ "bl\"ah\x01te[st\nab]c");
+ printchk("\"bl\\\"ah\\x01te[st\\x0aab\\]c\"", "%pSQqs",
+ "bl\"ah\x01te[st\nab]c");
+ printchk("\"\"", "%pSQqn", "");
+ printchk("\"\"", "%pSQqn", (char *)NULL);
+ printchk("(null)", "%pSQq", (char *)NULL);
+
return !!errors;
}
diff --git a/tests/lib/test_table.c b/tests/lib/test_table.c
index 290657bd56..9b6539e3bc 100644
--- a/tests/lib/test_table.c
+++ b/tests/lib/test_table.c
@@ -20,7 +20,7 @@
*/
#include <zebra.h>
-
+#include "printfrr.h"
#include "prefix.h"
#include "table.h"
@@ -113,7 +113,7 @@ static void print_subtree(struct route_node *rn, const char *legend,
printf(" ");
}
- printf("%s: %pFX", legend, &rn->p);
+ printfrr("%s: %pFX", legend, &rn->p);
if (!rn->info) {
printf(" (internal)");
}
diff --git a/tests/topotests/all-protocol-startup/r1/show_bgp_ipv4-post4.1.ref b/tests/topotests/all-protocol-startup/r1/show_bgp_ipv4-post4.1.ref
index 6cc23a465c..b38701a53d 100644
--- a/tests/topotests/all-protocol-startup/r1/show_bgp_ipv4-post4.1.ref
+++ b/tests/topotests/all-protocol-startup/r1/show_bgp_ipv4-post4.1.ref
@@ -3,6 +3,7 @@ Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
+RPKI validation codes: V valid, I invalid, N Not found
Network Next Hop Metric LocPrf Weight Path
*> 192.168.0.0 0.0.0.0 0 32768 i
diff --git a/tests/topotests/all-protocol-startup/r1/show_bgp_ipv4-post5.0.ref b/tests/topotests/all-protocol-startup/r1/show_bgp_ipv4-post5.0.ref
index 2f348a7b77..82b64c0d98 100644
--- a/tests/topotests/all-protocol-startup/r1/show_bgp_ipv4-post5.0.ref
+++ b/tests/topotests/all-protocol-startup/r1/show_bgp_ipv4-post5.0.ref
@@ -3,6 +3,7 @@ Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
+RPKI validation codes: V valid, I invalid, N Not found
Network Next Hop Metric LocPrf Weight Path
*> 192.168.0.0/24 0.0.0.0 0 32768 i
diff --git a/tests/topotests/all-protocol-startup/r1/show_bgp_ipv4-post6.1.ref b/tests/topotests/all-protocol-startup/r1/show_bgp_ipv4-post6.1.ref
index d36d045397..fd333b3084 100644
--- a/tests/topotests/all-protocol-startup/r1/show_bgp_ipv4-post6.1.ref
+++ b/tests/topotests/all-protocol-startup/r1/show_bgp_ipv4-post6.1.ref
@@ -4,6 +4,7 @@ Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
+RPKI validation codes: V valid, I invalid, N Not found
Network Next Hop Metric LocPrf Weight Path
*> 192.168.0.0/24 0.0.0.0 0 32768 i
diff --git a/tests/topotests/all-protocol-startup/r1/show_bgp_ipv6-post4.1.ref b/tests/topotests/all-protocol-startup/r1/show_bgp_ipv6-post4.1.ref
index 8bb5da72be..20034b7408 100644
--- a/tests/topotests/all-protocol-startup/r1/show_bgp_ipv6-post4.1.ref
+++ b/tests/topotests/all-protocol-startup/r1/show_bgp_ipv6-post4.1.ref
@@ -3,6 +3,7 @@ Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
+RPKI validation codes: V valid, I invalid, N Not found
Network Next Hop Metric LocPrf Weight Path
*> fc00::/64 :: 0 32768 i
diff --git a/tests/topotests/all-protocol-startup/r1/show_bgp_ipv6_post6.1.ref b/tests/topotests/all-protocol-startup/r1/show_bgp_ipv6_post6.1.ref
index de91b247d8..5b5f8596cf 100644
--- a/tests/topotests/all-protocol-startup/r1/show_bgp_ipv6_post6.1.ref
+++ b/tests/topotests/all-protocol-startup/r1/show_bgp_ipv6_post6.1.ref
@@ -4,6 +4,7 @@ Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
+RPKI validation codes: V valid, I invalid, N Not found
Network Next Hop Metric LocPrf Weight Path
*> fc00::/64 :: 0 32768 i
diff --git a/tests/topotests/all-protocol-startup/test_all_protocol_startup.py b/tests/topotests/all-protocol-startup/test_all_protocol_startup.py
index c858571254..c10e32ad0a 100644
--- a/tests/topotests/all-protocol-startup/test_all_protocol_startup.py
+++ b/tests/topotests/all-protocol-startup/test_all_protocol_startup.py
@@ -346,9 +346,9 @@ def test_converge_protocols():
print("Show that v4 routes are right\n")
v4_routesFile = "%s/r%s/ipv4_routes.ref" % (thisDir, i)
- expected = net["r%s" % i].cmd(
- "sort {} 2> /dev/null".format(v4_routesFile)
- ).rstrip()
+ expected = (
+ net["r%s" % i].cmd("sort {} 2> /dev/null".format(v4_routesFile)).rstrip()
+ )
expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
actual = (
@@ -379,9 +379,9 @@ def test_converge_protocols():
print("Show that v6 routes are right\n")
v6_routesFile = "%s/r%s/ipv6_routes.ref" % (thisDir, i)
- expected = net["r%s" % i].cmd(
- "sort {} 2> /dev/null".format(v6_routesFile)
- ).rstrip()
+ expected = (
+ net["r%s" % i].cmd("sort {} 2> /dev/null".format(v6_routesFile)).rstrip()
+ )
expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
actual = (
diff --git a/tests/topotests/bfd-profiles-topo1/r1/bfd-peers-initial.json b/tests/topotests/bfd-profiles-topo1/r1/bfd-peers-initial.json
index bab24c4fa0..86a7e5139c 100644
--- a/tests/topotests/bfd-profiles-topo1/r1/bfd-peers-initial.json
+++ b/tests/topotests/bfd-profiles-topo1/r1/bfd-peers-initial.json
@@ -6,14 +6,14 @@
"interface": "r1-eth1",
"multihop": false,
"peer": "172.16.100.2",
- "receive-interval": 300,
+ "receive-interval": 800,
"remote-detect-multiplier": 3,
"remote-diagnostic": "ok",
"remote-id": "*",
"remote-receive-interval": 300,
"remote-transmit-interval": 300,
"status": "up",
- "transmit-interval": 300,
+ "transmit-interval": 800,
"uptime": "*",
"vrf": "default"
},
diff --git a/tests/topotests/bfd-profiles-topo1/r1/ospfd.conf b/tests/topotests/bfd-profiles-topo1/r1/ospfd.conf
index 4798d17c40..fcea5d48fc 100644
--- a/tests/topotests/bfd-profiles-topo1/r1/ospfd.conf
+++ b/tests/topotests/bfd-profiles-topo1/r1/ospfd.conf
@@ -2,7 +2,7 @@ interface r1-eth1
ip ospf area 0
ip ospf hello-interval 2
ip ospf dead-interval 10
- ip ospf bfd
+ ip ospf bfd profile slowtx
!
router ospf
ospf router-id 10.254.254.1
diff --git a/tests/topotests/bfd-profiles-topo1/r6/bfd-peers-initial.json b/tests/topotests/bfd-profiles-topo1/r6/bfd-peers-initial.json
index 4e6fa869ba..ec973eb365 100644
--- a/tests/topotests/bfd-profiles-topo1/r6/bfd-peers-initial.json
+++ b/tests/topotests/bfd-profiles-topo1/r6/bfd-peers-initial.json
@@ -10,8 +10,8 @@
"remote-detect-multiplier": 3,
"remote-diagnostic": "ok",
"remote-id": "*",
- "remote-receive-interval": 300,
- "remote-transmit-interval": 300,
+ "remote-receive-interval": 800,
+ "remote-transmit-interval": 800,
"status": "up",
"transmit-interval": 300,
"uptime": "*",
diff --git a/tests/topotests/bgp-default-ipv4-ipv6-unicast/__init__.py b/tests/topotests/bgp-default-ipv4-ipv6-unicast/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bgp-default-ipv4-ipv6-unicast/__init__.py
diff --git a/tests/topotests/bgp-default-ipv4-ipv6-unicast/r1/bgpd.conf b/tests/topotests/bgp-default-ipv4-ipv6-unicast/r1/bgpd.conf
new file mode 100644
index 0000000000..bf39152ea8
--- /dev/null
+++ b/tests/topotests/bgp-default-ipv4-ipv6-unicast/r1/bgpd.conf
@@ -0,0 +1,3 @@
+!
+router bgp 65001
+!
diff --git a/tests/topotests/bgp-default-ipv4-ipv6-unicast/r1/zebra.conf b/tests/topotests/bgp-default-ipv4-ipv6-unicast/r1/zebra.conf
new file mode 100644
index 0000000000..697765168d
--- /dev/null
+++ b/tests/topotests/bgp-default-ipv4-ipv6-unicast/r1/zebra.conf
@@ -0,0 +1,7 @@
+!
+interface r1-eth0
+ ip address 192.168.255.1/24
+!
+ip forwarding
+!
+
diff --git a/tests/topotests/bgp-default-ipv4-ipv6-unicast/r2/bgpd.conf b/tests/topotests/bgp-default-ipv4-ipv6-unicast/r2/bgpd.conf
new file mode 100644
index 0000000000..abbd1b86fa
--- /dev/null
+++ b/tests/topotests/bgp-default-ipv4-ipv6-unicast/r2/bgpd.conf
@@ -0,0 +1,5 @@
+!
+router bgp 65001
+ no bgp default ipv4-unicast
+ bgp default ipv6-unicast
+!
diff --git a/tests/topotests/bgp-default-ipv4-ipv6-unicast/r2/zebra.conf b/tests/topotests/bgp-default-ipv4-ipv6-unicast/r2/zebra.conf
new file mode 100644
index 0000000000..606c17bec9
--- /dev/null
+++ b/tests/topotests/bgp-default-ipv4-ipv6-unicast/r2/zebra.conf
@@ -0,0 +1,6 @@
+!
+interface r2-eth0
+ ip address 192.168.255.2/24
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp-default-ipv4-ipv6-unicast/r3/bgpd.conf b/tests/topotests/bgp-default-ipv4-ipv6-unicast/r3/bgpd.conf
new file mode 100644
index 0000000000..a405c047ca
--- /dev/null
+++ b/tests/topotests/bgp-default-ipv4-ipv6-unicast/r3/bgpd.conf
@@ -0,0 +1,4 @@
+!
+router bgp 65001
+ bgp default ipv6-unicast
+!
diff --git a/tests/topotests/bgp-default-ipv4-ipv6-unicast/r3/zebra.conf b/tests/topotests/bgp-default-ipv4-ipv6-unicast/r3/zebra.conf
new file mode 100644
index 0000000000..e9fdfb70c5
--- /dev/null
+++ b/tests/topotests/bgp-default-ipv4-ipv6-unicast/r3/zebra.conf
@@ -0,0 +1,6 @@
+!
+interface r3-eth0
+ ip address 192.168.255.3/24
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp-default-ipv4-ipv6-unicast/test_bgp-default-ipv4-ipv6-unicast.py b/tests/topotests/bgp-default-ipv4-ipv6-unicast/test_bgp-default-ipv4-ipv6-unicast.py
new file mode 100644
index 0000000000..c1dbf0ebec
--- /dev/null
+++ b/tests/topotests/bgp-default-ipv4-ipv6-unicast/test_bgp-default-ipv4-ipv6-unicast.py
@@ -0,0 +1,140 @@
+#!/usr/bin/env python
+
+#
+# Copyright (c) 2021 by
+# Donatas Abraitis <donatas.abraitis@gmail.com>
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+Test if `bgp default ipv4-unicast` and `bgp default ipv6-unicast`
+commands work as expected.
+
+STEP 1: 'Check if neighbor 192.168.255.254 is enabled for ipv4 address-family only'
+STEP 2: 'Check if neighbor 192.168.255.254 is enabled for ipv6 address-family only'
+STEP 3: 'Check if neighbor 192.168.255.254 is enabled for ipv4 and ipv6 address-families'
+"""
+
+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.topolog import logger
+from mininet.topo import Topo
+from lib.common_config import step
+
+
+class TemplateTopo(Topo):
+ def build(self, *_args, **_opts):
+ tgen = get_topogen(self)
+
+ for routern in range(1, 5):
+ tgen.add_router("r{}".format(routern))
+
+ switch = tgen.add_switch("s1")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r2"])
+ switch.add_link(tgen.gears["r3"])
+ switch.add_link(tgen.gears["r4"])
+
+
+def setup_module(mod):
+ tgen = Topogen(TemplateTopo, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ for i, (rname, router) in enumerate(router_list.items(), 1):
+ 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))
+ )
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_default_ipv4_ipv6_unicast():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ step("Check if neighbor 192.168.255.254 is enabled for ipv4 address-family only")
+
+ def _bgp_neighbor_ipv4_af_only():
+ tgen.gears["r1"].vtysh_cmd(
+ "conf t\nrouter bgp\nneighbor 192.168.255.254 remote-as external"
+ )
+
+ output = json.loads(tgen.gears["r1"].vtysh_cmd("show bgp summary json"))
+
+ if "ipv4Unicast" in output and "ipv6Unicast" not in output:
+ return True
+ return False
+
+ assert _bgp_neighbor_ipv4_af_only() == True
+
+ step("Check if neighbor 192.168.255.254 is enabled for ipv6 address-family only")
+
+ def _bgp_neighbor_ipv6_af_only():
+ tgen.gears["r2"].vtysh_cmd(
+ "conf t\nrouter bgp\nneighbor 192.168.255.254 remote-as external"
+ )
+
+ output = json.loads(tgen.gears["r2"].vtysh_cmd("show bgp summary json"))
+
+ if "ipv4Unicast" not in output and "ipv6Unicast" in output:
+ return True
+ return False
+
+ assert _bgp_neighbor_ipv6_af_only() == True
+
+ step(
+ "Check if neighbor 192.168.255.254 is enabled for ipv4 and ipv6 address-families"
+ )
+
+ def _bgp_neighbor_ipv4_and_ipv6_af():
+ tgen.gears["r3"].vtysh_cmd(
+ "conf t\nrouter bgp\nneighbor 192.168.255.254 remote-as external"
+ )
+
+ output = json.loads(tgen.gears["r3"].vtysh_cmd("show bgp summary json"))
+
+ if "ipv4Unicast" in output and "ipv6Unicast" in output:
+ return True
+ return False
+
+ assert _bgp_neighbor_ipv4_and_ipv6_af() == True
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp-ebgp-common-subnet-nexthop-unchanged/__init__.py b/tests/topotests/bgp-ebgp-common-subnet-nexthop-unchanged/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bgp-ebgp-common-subnet-nexthop-unchanged/__init__.py
diff --git a/tests/topotests/bgp-ebgp-common-subnet-nexthop-unchanged/r1/bgpd.conf b/tests/topotests/bgp-ebgp-common-subnet-nexthop-unchanged/r1/bgpd.conf
new file mode 100644
index 0000000000..c320bb5d11
--- /dev/null
+++ b/tests/topotests/bgp-ebgp-common-subnet-nexthop-unchanged/r1/bgpd.conf
@@ -0,0 +1,7 @@
+router bgp 65001
+ no bgp ebgp-requires-policy
+ neighbor 192.168.1.101 remote-as external
+ address-family ipv4 unicast
+ redistribute connected
+ exit-address-family
+!
diff --git a/tests/topotests/bgp-ebgp-common-subnet-nexthop-unchanged/r1/zebra.conf b/tests/topotests/bgp-ebgp-common-subnet-nexthop-unchanged/r1/zebra.conf
new file mode 100644
index 0000000000..1782edc2a5
--- /dev/null
+++ b/tests/topotests/bgp-ebgp-common-subnet-nexthop-unchanged/r1/zebra.conf
@@ -0,0 +1,7 @@
+!
+int lo
+ ip address 172.16.1.1/32
+!
+int r1-eth0
+ ip address 192.168.1.1/24
+!
diff --git a/tests/topotests/bgp-ebgp-common-subnet-nexthop-unchanged/r2/bgpd.conf b/tests/topotests/bgp-ebgp-common-subnet-nexthop-unchanged/r2/bgpd.conf
new file mode 100644
index 0000000000..cb712e9a8d
--- /dev/null
+++ b/tests/topotests/bgp-ebgp-common-subnet-nexthop-unchanged/r2/bgpd.conf
@@ -0,0 +1,3 @@
+router bgp 65103
+ no bgp ebgp-requires-policy
+ neighbor 192.168.1.101 remote-as external
diff --git a/tests/topotests/bgp-ebgp-common-subnet-nexthop-unchanged/r2/zebra.conf b/tests/topotests/bgp-ebgp-common-subnet-nexthop-unchanged/r2/zebra.conf
new file mode 100644
index 0000000000..968171e7b9
--- /dev/null
+++ b/tests/topotests/bgp-ebgp-common-subnet-nexthop-unchanged/r2/zebra.conf
@@ -0,0 +1,4 @@
+!
+int r2-eth0
+ ip address 192.168.1.103/24
+!
diff --git a/tests/topotests/bgp-ebgp-common-subnet-nexthop-unchanged/r3/bgpd.conf b/tests/topotests/bgp-ebgp-common-subnet-nexthop-unchanged/r3/bgpd.conf
new file mode 100644
index 0000000000..a6e3260d15
--- /dev/null
+++ b/tests/topotests/bgp-ebgp-common-subnet-nexthop-unchanged/r3/bgpd.conf
@@ -0,0 +1,5 @@
+router bgp 65000
+ bgp router-id 192.168.1.101
+ no bgp ebgp-requires-policy
+ neighbor 192.168.1.1 remote-as external
+ neighbor 192.168.1.103 remote-as external
diff --git a/tests/topotests/bgp-ebgp-common-subnet-nexthop-unchanged/r3/zebra.conf b/tests/topotests/bgp-ebgp-common-subnet-nexthop-unchanged/r3/zebra.conf
new file mode 100644
index 0000000000..ddcf862132
--- /dev/null
+++ b/tests/topotests/bgp-ebgp-common-subnet-nexthop-unchanged/r3/zebra.conf
@@ -0,0 +1,4 @@
+!
+int r3-eth0
+ ip address 192.168.1.101/24
+!
diff --git a/tests/topotests/bgp-ebgp-common-subnet-nexthop-unchanged/test_bgp-ebgp-common-subnet-nexthop-unchanged.py b/tests/topotests/bgp-ebgp-common-subnet-nexthop-unchanged/test_bgp-ebgp-common-subnet-nexthop-unchanged.py
new file mode 100644
index 0000000000..19c4c5f87d
--- /dev/null
+++ b/tests/topotests/bgp-ebgp-common-subnet-nexthop-unchanged/test_bgp-ebgp-common-subnet-nexthop-unchanged.py
@@ -0,0 +1,127 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2021 by
+# Donatas Abraitis <donatas.abraitis@gmail.com>
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+https://tools.ietf.org/html/rfc4271
+
+Check if NEXT_HOP attribute is not changed if peer X shares a
+common subnet with this address.
+
+- Otherwise, if the route being announced was learned from an
+ external peer, the speaker can use an IP address of any
+ adjacent router (known from the received NEXT_HOP attribute)
+ that the speaker itself uses for local route calculation in
+ the NEXT_HOP attribute, provided that peer X shares a common
+ subnet with this address. This is a second form of "third
+ party" NEXT_HOP attribute.
+"""
+
+import os
+import sys
+import json
+import time
+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.topolog import logger
+from mininet.topo import Topo
+
+
+class TemplateTopo(Topo):
+ def build(self, *_args, **_opts):
+ tgen = get_topogen(self)
+
+ for routern in range(1, 4):
+ tgen.add_router("r{}".format(routern))
+
+ switch = tgen.add_switch("s1")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r2"])
+ switch.add_link(tgen.gears["r3"])
+
+
+def setup_module(mod):
+ tgen = Topogen(TemplateTopo, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ for i, (rname, router) in enumerate(router_list.items(), 1):
+ 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))
+ )
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_ebgp_common_subnet_nh_unchanged():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r2 = tgen.gears["r2"]
+ r3 = tgen.gears["r3"]
+
+ def _bgp_converge(router):
+ output = json.loads(router.vtysh_cmd("show ip bgp summary json"))
+ expected = {
+ "ipv4Unicast": {
+ "peers": {
+ "192.168.1.1": {"state": "Established"},
+ "192.168.1.103": {"state": "Established"},
+ }
+ }
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_converge, r3)
+ success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+
+ assert result is None, 'Failed bgp convergence in "{}"'.format(r3)
+
+ def _bgp_nh_unchanged(router):
+ output = json.loads(router.vtysh_cmd("show ip bgp 172.16.1.1/32 json"))
+ expected = {"paths": [{"nexthops": [{"ip": "192.168.1.1"}]}]}
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_nh_unchanged, r2)
+ success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+
+ assert result is None, 'Wrong next-hop in "{}"'.format(r2)
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp-ecmp-topo1/test_bgp_ecmp_topo1.py b/tests/topotests/bgp-ecmp-topo1/test_bgp_ecmp_topo1.py
index 400e7e9bf5..75506d1a51 100644
--- a/tests/topotests/bgp-ecmp-topo1/test_bgp_ecmp_topo1.py
+++ b/tests/topotests/bgp-ecmp-topo1/test_bgp_ecmp_topo1.py
@@ -45,6 +45,10 @@ from lib.topolog import logger
# Required to instantiate the topology builder class.
from mininet.topo import Topo
+
+pytestmark = [pytest.mark.bgpd]
+
+
total_ebgp_peers = 20
#####################################################
diff --git a/tests/topotests/bgp-ecmp-topo2/test_ebgp_ecmp_topo2.py b/tests/topotests/bgp-ecmp-topo2/test_ebgp_ecmp_topo2.py
index dfe6a8074d..fffcbbd0ef 100644
--- a/tests/topotests/bgp-ecmp-topo2/test_ebgp_ecmp_topo2.py
+++ b/tests/topotests/bgp-ecmp-topo2/test_ebgp_ecmp_topo2.py
@@ -67,6 +67,10 @@ from lib.topolog import logger
from lib.bgp import verify_bgp_convergence, create_router_bgp, clear_bgp
from lib.topojson import build_topo_from_json, build_config_from_json
+
+pytestmark = [pytest.mark.bgpd, pytest.mark.staticd]
+
+
# Reading the data from JSON File for topology and configuration creation
jsonFile = "{}/ebgp_ecmp_topo2.json".format(CWD)
diff --git a/tests/topotests/bgp-ecmp-topo2/test_ibgp_ecmp_topo2.py b/tests/topotests/bgp-ecmp-topo2/test_ibgp_ecmp_topo2.py
index 2bde52af1d..342a0a4b2f 100644
--- a/tests/topotests/bgp-ecmp-topo2/test_ibgp_ecmp_topo2.py
+++ b/tests/topotests/bgp-ecmp-topo2/test_ibgp_ecmp_topo2.py
@@ -67,6 +67,10 @@ from lib.topolog import logger
from lib.bgp import verify_bgp_convergence, create_router_bgp, clear_bgp
from lib.topojson import build_topo_from_json, build_config_from_json
+
+pytestmark = [pytest.mark.bgpd, pytest.mark.staticd]
+
+
# Reading the data from JSON File for topology and configuration creation
jsonFile = "{}/ibgp_ecmp_topo2.json".format(CWD)
diff --git a/tests/topotests/bgp-evpn-mh/test_evpn_mh.py b/tests/topotests/bgp-evpn-mh/test_evpn_mh.py
index 2744920272..f389632b1e 100644
--- a/tests/topotests/bgp-evpn-mh/test_evpn_mh.py
+++ b/tests/topotests/bgp-evpn-mh/test_evpn_mh.py
@@ -35,7 +35,7 @@ import json
import platform
from functools import partial
-pytestmark = [pytest.mark.pimd]
+pytestmark = [pytest.mark.bgpd, pytest.mark.pimd]
# Save the Current Working Directory to find configuration files.
CWD = os.path.dirname(os.path.realpath(__file__))
diff --git a/tests/topotests/bgp-snmp-mplsl3vpn/test_bgp_snmp_mplsvpn.py b/tests/topotests/bgp-snmp-mplsl3vpn/test_bgp_snmp_mplsvpn.py
index db4eab9d3d..b830e16b9a 100755
--- a/tests/topotests/bgp-snmp-mplsl3vpn/test_bgp_snmp_mplsvpn.py
+++ b/tests/topotests/bgp-snmp-mplsl3vpn/test_bgp_snmp_mplsvpn.py
@@ -505,8 +505,10 @@ def test_r1_mplsvpn_VrfTable():
associated_int = r1_snmp.get(
"mplsL3VpnVrfAssociatedInterfaces.{}".format(snmp_str_to_oid("VRF-a"))
)
- assertmsg = "mplsL3VpnVrfAssociatedInterfaces incorrect should be 3 value {}".format(
- associated_int
+ assertmsg = (
+ "mplsL3VpnVrfAssociatedInterfaces incorrect should be 3 value {}".format(
+ associated_int
+ )
)
assert associated_int == "3", assertmsg
diff --git a/tests/topotests/bgp_evpn_rt5/test_bgp_evpn.py b/tests/topotests/bgp_evpn_rt5/test_bgp_evpn.py
index 222478f12d..320e6d430c 100644
--- a/tests/topotests/bgp_evpn_rt5/test_bgp_evpn.py
+++ b/tests/topotests/bgp_evpn_rt5/test_bgp_evpn.py
@@ -42,13 +42,11 @@ sys.path.append(os.path.join(CWD, "../"))
from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.topolog import logger
+from lib.common_config import adjust_router_l3mdev
# Required to instantiate the topology builder class.
from mininet.topo import Topo
-l3mdev_accept = 0
-krel = ""
-
class BGPEVPNTopo(Topo):
"Test topology builder"
@@ -73,8 +71,6 @@ class BGPEVPNTopo(Topo):
def setup_module(mod):
"Sets up the pytest environment"
- global l3mdev_accept
- global krel
tgen = Topogen(BGPEVPNTopo, mod.__name__)
tgen.start_topology()
@@ -90,18 +86,13 @@ def setup_module(mod):
)
return pytest.skip("Skipping BGP EVPN RT5 NETNS Test. Kernel not supported")
- l3mdev_accept = 1
- logger.info("setting net.ipv4.tcp_l3mdev_accept={}".format(l3mdev_accept))
-
# create VRF vrf-101 on R1 and R2
# create loop101
cmds_vrflite = [
- "sysctl -w net.ipv4.tcp_l3mdev_accept={}".format(l3mdev_accept),
"ip link add {}-vrf-101 type vrf table 101",
"ip ru add oif {}-vrf-101 table 101",
"ip ru add iif {}-vrf-101 table 101",
"ip link set dev {}-vrf-101 up",
- "sysctl -w net.ipv4.tcp_l3mdev_accept={}".format(l3mdev_accept),
"ip link add loop101 type dummy",
"ip link set dev loop101 master {}-vrf-101",
"ip link set dev loop101 up",
@@ -139,6 +130,7 @@ def setup_module(mod):
logger.info("result: " + output)
router = tgen.gears["r2"]
+ adjust_router_l3mdev(tgen, "r2")
for cmd in cmds_vrflite:
logger.info("cmd to r2: " + cmd.format("r2"))
output = router.run(cmd.format("r2"))
diff --git a/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1.py b/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1.py
index a6338d0c70..b70626fcce 100644
--- a/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1.py
+++ b/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1.py
@@ -258,10 +258,12 @@ def configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut, peer):
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
for addr_type in ADDR_TYPES:
- clear_bgp(tgen, addr_type, dut)
+ neighbor = topo["routers"][peer]["links"]["r1-link1"][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, dut, neighbor=neighbor)
for addr_type in ADDR_TYPES:
- clear_bgp(tgen, addr_type, peer)
+ neighbor = topo["routers"][dut]["links"]["r2-link1"][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, peer, neighbor=neighbor)
result = verify_bgp_convergence_from_running_config(tgen)
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
@@ -551,7 +553,7 @@ def test_BGP_GR_TC_46_p1(request):
write_test_footer(tc_name)
-def test_BGP_GR_TC_50_p1(request):
+def BGP_GR_TC_50_p1(request):
"""
Test Objective : Transition from Peer-level helper to Global inherit helper
Global Mode : None
@@ -613,9 +615,6 @@ def test_BGP_GR_TC_50_p1(request):
configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
- result = verify_bgp_convergence_from_running_config(tgen)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
-
step("Verify on R2 that R1 advertises GR capabilities as a helper node")
for addr_type in ADDR_TYPES:
@@ -721,7 +720,12 @@ def test_BGP_GR_TC_50_p1(request):
}
}
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+ result = create_router_bgp(tgen, topo, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ neighbor = topo["routers"]["r2"]["links"]["r1-link1"][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, "r1", neighbor=neighbor)
result = verify_bgp_convergence_from_running_config(tgen)
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
@@ -979,7 +983,15 @@ def test_BGP_GR_TC_51_p1(request):
}
}
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+ result = create_router_bgp(tgen, topo, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ neighbor = topo["routers"]["r2"]["links"]["r1-link1"][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, "r1", neighbor=neighbor)
+
+ result = verify_bgp_convergence_from_running_config(tgen)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
step("Verify on R2 that R1 advertises GR capabilities as a helper node")
@@ -1317,20 +1329,22 @@ def test_BGP_GR_TC_4_p0(request):
result = verify_bgp_rib(
tgen, addr_type, dut, input_topo, next_hop, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r1: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
logger.info(" Expected behavior: {}".format(result))
# Verifying RIB routes
result = verify_rib(
tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: routes are still present in ZEBRA\n Error: {}".format(
- tc_name, result
- ))
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
logger.info(" Expected behavior: {}".format(result))
logger.info("[Phase 5] : R2 is about to come up now ")
@@ -1695,10 +1709,10 @@ def test_BGP_GR_TC_6_1_2_p1(request):
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
for addr_type in ADDR_TYPES:
- clear_bgp(tgen, addr_type, "r1")
- clear_bgp(tgen, addr_type, "r2")
+ neighbor = topo["routers"]["r2"]["links"]["r1-link1"][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, "r1", neighbor=neighbor)
- result = verify_bgp_convergence_from_running_config(tgen, topo)
+ result = verify_bgp_convergence_from_running_config(tgen)
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
# Verify GR stats
@@ -1790,10 +1804,11 @@ def test_BGP_GR_TC_6_1_2_p1(request):
result = verify_r_bit(
tgen, topo, addr_type, input_dict, dut="r2", peer="r1", expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "r2: R-bit is set to True\n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r2: R-bit is set to True\n Error: {}".format(
tc_name, result
- ))
+ )
logger.info("Restart BGPd on R2 ")
kill_router_daemons(tgen, "r2", ["bgpd"])
@@ -1811,10 +1826,11 @@ def test_BGP_GR_TC_6_1_2_p1(request):
result = verify_r_bit(
tgen, topo, addr_type, input_dict, dut="r2", peer="r1", expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "r2: R-bit is set to True\n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r2: R-bit is set to True\n Error: {}".format(
tc_name, result
- ))
+ )
write_test_footer(tc_name)
@@ -2096,20 +2112,22 @@ def test_BGP_GR_TC_17_p1(request):
result = verify_bgp_rib(
tgen, addr_type, dut, input_topo, next_hop, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r1: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
logger.info(" Expected behavior: {}".format(result))
# Verifying RIB routes
result = verify_rib(
tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: routes are still present in ZEBRA\n Error: {}".format(
- tc_name, result
- ))
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
logger.info(" Expected behavior: {}".format(result))
logger.info("[Phase 5] : R2 is about to come up now ")
@@ -2128,10 +2146,11 @@ def test_BGP_GR_TC_17_p1(request):
result = verify_r_bit(
tgen, topo, addr_type, input_dict, dut="r1", peer="r2", expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: R-bit is set to True\n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: R-bit is set to True\n Error: {}".format(
tc_name, result
- ))
+ )
# Verifying BGP RIB routes
next_hop = next_hop_per_address_family(
@@ -2457,20 +2476,22 @@ def test_BGP_GR_TC_20_p1(request):
result = verify_bgp_rib(
tgen, addr_type, dut, input_topo, next_hop, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r1: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
logger.info(" Expected behavior: {}".format(result))
# Verifying RIB routes
result = verify_rib(
tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: routes are still present in ZEBRA\n Error: {}".format(
- tc_name, result
- ))
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
logger.info(" Expected behavior: {}".format(result))
logger.info("[Phase 5] : R2 is about to come up now ")
@@ -2651,10 +2672,10 @@ def test_BGP_GR_TC_31_1_p1(request):
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
for addr_type in ADDR_TYPES:
- clear_bgp(tgen, addr_type, "r1")
- clear_bgp(tgen, addr_type, "r2")
+ neighbor = topo["routers"]["r2"]["links"]["r1-link1"][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, "r1", neighbor=neighbor)
- result = verify_bgp_convergence_from_running_config(tgen, topo)
+ result = verify_bgp_convergence_from_running_config(tgen)
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
# Verify GR stats
@@ -2743,10 +2764,10 @@ def test_BGP_GR_TC_31_1_p1(request):
result = verify_rib(
tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: routes are still present in ZEBRA\n Error: {}".format(
- tc_name, result
- ))
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
logger.info("[Phase 4] : R1 is about to come up now ")
start_router_daemons(tgen, "r1", ["bgpd"])
@@ -2932,10 +2953,10 @@ def test_BGP_GR_TC_31_2_p1(request):
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
for addr_type in ADDR_TYPES:
- clear_bgp(tgen, addr_type, "r1")
- clear_bgp(tgen, addr_type, "r2")
+ neighbor = topo["routers"]["r2"]["links"]["r1-link1"][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, "r1", neighbor=neighbor)
- result = verify_bgp_convergence_from_running_config(tgen, topo)
+ result = verify_bgp_convergence_from_running_config(tgen)
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
# Verify GR stats
@@ -3225,10 +3246,12 @@ def test_BGP_GR_TC_9_p1(request):
result = verify_bgp_rib(
tgen, addr_type, dut, input_topo, next_hop, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r1: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
logger.info(" Expected behavior: {}".format(result))
# Verifying RIB routes
@@ -3236,10 +3259,10 @@ def test_BGP_GR_TC_9_p1(request):
result = verify_rib(
tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: routes are still present in ZEBRA\n Error: {}".format(
- tc_name, result
- ))
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
logger.info(" Expected behavior: {}".format(result))
logger.info("[Phase 5] : R2 is about to come up now ")
@@ -3269,10 +3292,11 @@ def test_BGP_GR_TC_9_p1(request):
result = verify_f_bit(
tgen, topo, addr_type, input_dict, dut="r1", peer="r2", expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: F-bit is set to True\n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: F-bit is set to True\n Error: {}".format(
tc_name, result
- ))
+ )
write_test_footer(tc_name)
@@ -3404,10 +3428,12 @@ def test_BGP_GR_TC_17_p1(request):
result = verify_bgp_rib(
tgen, addr_type, dut, input_topo, next_hop, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r1: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
logger.info(" Expected behavior: {}".format(result))
# Verifying RIB routes
@@ -3415,10 +3441,10 @@ def test_BGP_GR_TC_17_p1(request):
result = verify_rib(
tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: routes are still present in ZEBRA\n Error: {}".format(
- tc_name, result
- ))
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
logger.info(" Expected behavior: {}".format(result))
logger.info("[Phase 5] : R2 is about to come up now ")
@@ -3440,10 +3466,11 @@ def test_BGP_GR_TC_17_p1(request):
result = verify_r_bit(
tgen, topo, addr_type, input_dict, dut="r1", peer="r2", expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: R-bit is set to True\n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: R-bit is set to True\n Error: {}".format(
tc_name, result
- ))
+ )
# Verifying BGP RIB routes
next_hop = next_hop_per_address_family(
@@ -3663,10 +3690,12 @@ def test_BGP_GR_TC_43_p1(request):
result = verify_bgp_rib(
tgen, addr_type, dut, input_topo, next_hop, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r2: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
protocol = "bgp"
result = verify_rib(
tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
@@ -3971,10 +4000,12 @@ def test_BGP_GR_TC_44_p1(request):
result = verify_bgp_rib(
tgen, addr_type, dut, input_topo, next_hop, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r1: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
result = verify_rib(
tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
)
@@ -4999,10 +5030,10 @@ def test_BGP_GR_TC_48_p1(request):
result = verify_rib(
tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: routes are still present in ZEBRA\n Error: {}".format(
- tc_name, result
- ))
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
dut = "r2"
peer = "r1"
@@ -5013,17 +5044,19 @@ def test_BGP_GR_TC_48_p1(request):
result = verify_bgp_rib(
tgen, addr_type, dut, input_topo, next_hop, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r2: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
result = verify_rib(
tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "r2: routes are still present in ZEBRA\n Error: {}".format(
- tc_name, result
- ))
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r2: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
step("Bring up BGP on R1 and remove Peer-level GR config from R1")
@@ -5258,7 +5291,7 @@ def test_BGP_GR_TC_49_p1(request):
write_test_footer(tc_name)
-def test_BGP_GR_TC_52_p1(request):
+def BGP_GR_TC_52_p1(request):
"""
Test Objective : Transition from Peer-level disbale to Global inherit helper
Global Mode : None
@@ -5382,17 +5415,19 @@ def test_BGP_GR_TC_52_p1(request):
result = verify_bgp_rib(
tgen, addr_type, dut, input_topo, next_hop, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r1: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
result = verify_rib(
tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: routes are still present in ZEBRA\n Error: {}".format(
- tc_name, result
- ))
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
step("Bring up BGP on R2 and remove Peer-level GR config from R1")
diff --git a/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2.py b/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2.py
index 2c5dd92f54..9438b90ef8 100644
--- a/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2.py
+++ b/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2.py
@@ -251,12 +251,14 @@ def configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut, peer):
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
for addr_type in ADDR_TYPES:
- clear_bgp(tgen, addr_type, dut)
+ neighbor = topo["routers"][peer]["links"][dut][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, dut, neighbor=neighbor)
for addr_type in ADDR_TYPES:
- clear_bgp(tgen, addr_type, peer)
+ neighbor = topo["routers"][dut]["links"][peer][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, peer, neighbor=neighbor)
- result = verify_bgp_convergence_from_running_config(tgen, topo)
+ result = verify_bgp_convergence_from_running_config(tgen)
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
return True
@@ -555,10 +557,11 @@ def test_BGP_GR_TC_3_p0(request):
result = verify_eor(
tgen, topo, addr_type, input_dict, dut="r2", peer="r1", expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "r2: EOR is set to True\n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r2: EOR is set to True\n Error: {}".format(
tc_name, result
- ))
+ )
logger.info(
"Waiting for selection deferral timer({} sec)..".format(GR_SELECT_DEFER_TIMER)
@@ -701,10 +704,11 @@ def test_BGP_GR_TC_11_p0(request):
result = verify_eor(
tgen, topo, addr_type, input_dict, dut="r1", peer="r3", expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: EOR is set to True\n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: EOR is set to True\n Error: {}".format(
tc_name, result
- ))
+ )
logger.info(
"Waiting for selection deferral timer({} sec).. ".format(
@@ -731,10 +735,11 @@ def test_BGP_GR_TC_11_p0(request):
result = verify_eor(
tgen, topo, addr_type, input_dict, dut="r3", peer="r1", expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "r3: EOR is set to True\n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r3: EOR is set to True\n Error: {}".format(
tc_name, result
- ))
+ )
write_test_footer(tc_name)
@@ -930,7 +935,7 @@ def test_BGP_GR_10_p2(request):
write_test_footer(tc_name)
-def test_BGP_GR_16_p2(request):
+def BGP_GR_16_p2(request):
"""
Test Objective : Verify BGP-GR feature when restarting node
is a transit router for it's iBGP peers.
@@ -1468,35 +1473,39 @@ def test_BGP_GR_18_p1(request):
dut = "r6"
input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r6: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
logger.info(" Expected behavior: {}".format(result))
# Verifying RIB routes before shutting down BGPd daemon
result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "r6: routes are still present in ZEBRA\n Error: {}".format(
- tc_name, result
- ))
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r6: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
logger.info(" Expected behavior: {}".format(result))
# Verifying BGP RIB routes
dut = "r2"
result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r2: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
logger.info(" Expected behavior: {}".format(result))
# Verifying RIB routes before shutting down BGPd daemon
result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "r6: routes are still present in ZEBRA\n Error: {}".format(
- tc_name, result
- ))
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r6: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
logger.info(" Expected behavior: {}".format(result))
write_test_footer(tc_name)
@@ -1957,18 +1966,20 @@ def test_BGP_GR_chaos_29_p1(request):
# Verifying BGP RIB routes before shutting down BGPd daemon
input_dict = {key: topo["routers"][key] for key in ["r1"]}
result = verify_bgp_rib(tgen, addr_type, dut, input_dict, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r3: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
logger.info(" Expected behavior: {}".format(result))
# Verifying RIB routes before shutting down BGPd daemon
result = verify_rib(tgen, addr_type, dut, input_dict, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "r3: routes are still present in ZEBRA\n Error: {}".format(
- tc_name, result
- ))
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
logger.info(" Expected behavior: {}".format(result))
logger.info("[Step 4] : Start BGPd daemon on R1..")
@@ -2210,10 +2221,12 @@ def test_BGP_GR_chaos_33_p1(request):
result = verify_rib(
tgen, addr_type, dut, input_dict_2, next_hop_4, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r3: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
logger.info(" Expected behavior: {}".format(result))
if addr_type == "ipv6":
@@ -2225,10 +2238,12 @@ def test_BGP_GR_chaos_33_p1(request):
result = verify_rib(
tgen, addr_type, dut, input_dict_2, next_hop_6, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r3: routes are still present in ZEBRA\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
logger.info(" Expected behavior: {}".format(result))
logger.info("[Step 4] : Start BGPd daemon on R1 and R4..")
@@ -2409,27 +2424,30 @@ def test_BGP_GR_chaos_34_2_p1(request):
result = verify_f_bit(
tgen, topo, addr_type, input_dict, "r3", "r1", expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "r3: F-bit is set to True\n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r3: F-bit is set to True\n Error: {}".format(
tc_name, result
- ))
+ )
logger.info(" Expected behavior: {}".format(result))
# Verifying BGP RIB routes after starting BGPd daemon
input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r3: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
logger.info(" Expected behavior: {}".format(result))
# Verifying RIB routes
result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "r3: routes are still present in ZEBRA\n Error: {}".format(
- tc_name, result
- ))
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
logger.info(" Expected behavior: {}".format(result))
write_test_footer(tc_name)
@@ -2566,10 +2584,11 @@ def test_BGP_GR_chaos_34_1_p1(request):
result = verify_f_bit(
tgen, topo, addr_type, input_dict_2, "r3", "r1", expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "r3: F-bit is set to True\n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r3: F-bit is set to True\n Error: {}".format(
tc_name, result
- ))
+ )
logger.info(" Expected behavior: {}".format(result))
logger.info("[Step 3] : Kill BGPd daemon on R1..")
@@ -2585,18 +2604,20 @@ def test_BGP_GR_chaos_34_1_p1(request):
# Verifying BGP RIB routes
input_dict = {key: topo["routers"][key] for key in ["r1"]}
result = verify_bgp_rib(tgen, addr_type, dut, input_dict, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r3: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
logger.info(" Expected behavior: {}".format(result))
# Verifying RIB routes
result = verify_rib(tgen, addr_type, dut, input_dict, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "r3: routes are still present in ZEBRA\n Error: {}".format(
- tc_name, result
- ))
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
logger.info(" Expected behavior: {}".format(result))
# Start BGPd daemon on R1
@@ -2770,27 +2791,30 @@ def test_BGP_GR_chaos_32_p1(request):
result = verify_eor(
tgen, topo, addr_type, input_dict_3, dut="r5", peer="r1", expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "r5: EOR is set to TRUE\n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r5: EOR is set to TRUE\n Error: {}".format(
tc_name, result
- ))
+ )
logger.info(" Expected behavior: {}".format(result))
# Verifying BGP RIB routes after starting BGPd daemon
input_dict_1 = {key: topo["routers"][key] for key in ["r5"]}
result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r3: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
logger.info(" Expected behavior: {}".format(result))
# Verifying RIB routes
result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "r3: routes are still present in ZEBRA\n Error: {}".format(
- tc_name, result
- ))
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
logger.info(" Expected behavior: {}".format(result))
write_test_footer(tc_name)
@@ -2896,10 +2920,11 @@ def test_BGP_GR_chaos_37_p1(request):
result = verify_eor(
tgen, topo, addr_type, input_dict, dut="r3", peer="r1", expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "r3: EOR is set to True\n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r3: EOR is set to True\n Error: {}".format(
tc_name, result
- ))
+ )
logger.info(" Expected behavior: {}".format(result))
# Verifying BGP RIB routes after starting BGPd daemon
@@ -2962,10 +2987,11 @@ def test_BGP_GR_chaos_37_p1(request):
result = verify_eor(
tgen, topo, addr_type, input_dict_3, dut="r1", peer="r3", expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: EOR is set to True\n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: EOR is set to True\n Error: {}".format(
tc_name, result
- ))
+ )
write_test_footer(tc_name)
@@ -3117,18 +3143,20 @@ def test_BGP_GR_chaos_30_p1(request):
# Verifying BGP RIB routes before shutting down BGPd daemon
input_dict = {key: topo["routers"][key] for key in ["r3"]}
result = verify_bgp_rib(tgen, addr_type, dut, input_dict, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r1: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
logger.info(" Expected behavior: {}".format(result))
# Verifying RIB routes before shutting down BGPd daemon
result = verify_rib(tgen, addr_type, dut, input_dict, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: routes are still present in ZEBRA\n Error: {}".format(
- tc_name, result
- ))
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
logger.info(" Expected behavior: {}".format(result))
write_test_footer(tc_name)
@@ -3530,10 +3558,10 @@ def BGP_GR_TC_7_p1(request):
dut = "r1"
input_dict_1 = {key: topo["routers"][key] for key in ["r3"]}
result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: routes are still present in ZEBRA\n Error: {}".format(
- tc_name, result
- ))
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
write_test_footer(tc_name)
@@ -3707,10 +3735,11 @@ def test_BGP_GR_TC_23_p1(request):
result = verify_eor(
tgen, topo, addr_type, input_dict, dut="r1", peer="r2", expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: EOR is set to True\n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: EOR is set to True\n Error: {}".format(
tc_name, result
- ))
+ )
# Verifying BGP RIB routes received from router R1
dut = "r1"
@@ -3831,18 +3860,20 @@ def test_BGP_GR_20_p1(request):
dut = "r3"
input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r3: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
logger.info(" Expected behavior: {}".format(result))
# Verifying RIB routes before shutting down BGPd daemon
result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "r3: routes are still present in ZEBRA\n Error: {}".format(
- tc_name, result
- ))
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
logger.info(" Expected behavior: {}".format(result))
# Start BGPd daemon on R1
diff --git a/tests/topotests/bgp_instance_del_test/test_bgp_instance_del_test.py b/tests/topotests/bgp_instance_del_test/test_bgp_instance_del_test.py
index 47cc0eb39d..0c7e84a5a3 100755
--- a/tests/topotests/bgp_instance_del_test/test_bgp_instance_del_test.py
+++ b/tests/topotests/bgp_instance_del_test/test_bgp_instance_del_test.py
@@ -30,6 +30,9 @@ sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), "../")
from lib.ltemplate import *
+pytestmark = [pytest.mark.bgpd, pytest.mark.ldpd, pytest.mark.ospfd]
+
+
def test_check_linux_vrf():
CliOnFail = None
# For debugging, uncomment the next line
diff --git a/tests/topotests/bgp_ipv6_rtadv/test_bgp_ipv6_rtadv.py b/tests/topotests/bgp_ipv6_rtadv/test_bgp_ipv6_rtadv.py
index 783e746418..cd845be296 100644
--- a/tests/topotests/bgp_ipv6_rtadv/test_bgp_ipv6_rtadv.py
+++ b/tests/topotests/bgp_ipv6_rtadv/test_bgp_ipv6_rtadv.py
@@ -46,6 +46,9 @@ from lib.topolog import logger
from mininet.topo import Topo
+pytestmark = [pytest.mark.bgpd]
+
+
class BGPIPV6RTADVTopo(Topo):
"Test topology builder"
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/customize.py b/tests/topotests/bgp_l3vpn_to_bgp_vrf/customize.py
index 1c3c51f68e..5d97537bd0 100644
--- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/customize.py
+++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/customize.py
@@ -84,6 +84,7 @@ from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.topolog import logger
from lib.ltemplate import ltemplateRtrCmd
+from lib.common_config import adjust_router_l3mdev
# Required to instantiate the topology builder class.
from mininet.topo import Topo
@@ -145,26 +146,12 @@ class ThisTestTopo(Topo):
switch[1].add_link(tgen.gears["r3"], nodeif="r3-eth1")
-l3mdev_accept = 0
-
-
def ltemplatePreRouterStartHook():
- global l3mdev_accept
cc = ltemplateRtrCmd()
krel = platform.release()
tgen = get_topogen()
logger.info("pre router-start hook, kernel=" + krel)
- if (
- topotest.version_cmp(krel, "4.15") >= 0
- and topotest.version_cmp(krel, "4.18") <= 0
- ):
- l3mdev_accept = 1
-
- if topotest.version_cmp(krel, "5.0") >= 0:
- l3mdev_accept = 1
-
- logger.info("setting net.ipv4.tcp_l3mdev_accept={}".format(l3mdev_accept))
# check for mpls
if tgen.hasmpls != True:
logger.info("MPLS not available, skipping setup")
@@ -187,10 +174,11 @@ def ltemplatePreRouterStartHook():
"ip ru add oif {0}-cust1 table 10",
"ip ru add iif {0}-cust1 table 10",
"ip link set dev {0}-cust1 up",
- "sysctl -w net.ipv4.tcp_l3mdev_accept={}".format(l3mdev_accept),
]
for rtr in rtrs:
- router = tgen.gears[rtr]
+ # adjust handling of VRF traffic
+ adjust_router_l3mdev(tgen, rtr)
+
for cmd in cmds:
cc.doCmd(tgen, rtr, cmd.format(rtr))
cc.doCmd(tgen, rtr, "ip link set dev {0}-eth4 master {0}-cust1".format(rtr))
@@ -229,9 +217,11 @@ def ltemplatePreRouterStartHook():
"ip ru add oif {0}-cust2 table 20",
"ip ru add iif {0}-cust2 table 20",
"ip link set dev {0}-cust2 up",
- "sysctl -w net.ipv4.tcp_l3mdev_accept={}".format(l3mdev_accept),
]
for rtr in rtrs:
+ # adjust handling of VRF traffic
+ adjust_router_l3mdev(tgen, rtr)
+
for cmd in cmds:
cc.doCmd(tgen, rtr, cmd.format(rtr))
cc.doCmd(tgen, rtr, "ip link set dev {0}-eth0 master {0}-cust2".format(rtr))
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_vrf.py b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_vrf.py
index 7c154ecd15..650ba20b8c 100644
--- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_vrf.py
+++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_vrf.py
@@ -1,6 +1,7 @@
from lib.lutil import luCommand
-from customize import l3mdev_accept
+from lib.common_config import kernel_requires_l3mdev_adjustment
+l3mdev_accept = kernel_requires_l3mdev_adjustment()
l3mdev_rtrs = ["r1", "r3", "r4", "ce4"]
for rtr in l3mdev_rtrs:
luCommand(rtr, "sysctl net.ipv4.tcp_l3mdev_accept", " = \d*", "none", "")
diff --git a/tests/topotests/bgp_large_community/test_bgp_large_community_topo_2.py b/tests/topotests/bgp_large_community/test_bgp_large_community_topo_2.py
index 8e5ffe10be..84d9c48f35 100644
--- a/tests/topotests/bgp_large_community/test_bgp_large_community_topo_2.py
+++ b/tests/topotests/bgp_large_community/test_bgp_large_community_topo_2.py
@@ -598,10 +598,12 @@ def test_large_community_lists_with_rmap_apply_and_remove(request):
result = verify_bgp_community(
tgen, adt, dut, NETWORKS[adt], input_dict_4, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"largeCommunity is still present after deleting route-map \n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
write_test_footer(tc_name)
@@ -899,10 +901,10 @@ def test_large_community_lists_with_rmap_set_none(request):
dut = "r6"
for adt in ADDR_TYPES:
result = verify_bgp_community(tgen, adt, dut, NETWORKS[adt], expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "Community-list is still present \n Error: {}".format(
- tc_name, result
- ))
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Community-list is still present \n Error: {}".format(tc_name, result)
+ )
write_test_footer(tc_name)
@@ -2238,10 +2240,10 @@ def test_large_community_lists_with_rmap_match_regex(request):
result = verify_bgp_community(
tgen, adt, dut, NETWORKS[adt], input_dict_7, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "largeCommunity is still present \n Error: {}".format(
- tc_name, result
- ))
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "largeCommunity is still present \n Error: {}".format(tc_name, result)
+ )
write_test_footer(tc_name)
diff --git a/tests/topotests/bgp_lu_topo1/test_bgp_lu.py b/tests/topotests/bgp_lu_topo1/test_bgp_lu.py
index d550c38a2f..d1745674f0 100644
--- a/tests/topotests/bgp_lu_topo1/test_bgp_lu.py
+++ b/tests/topotests/bgp_lu_topo1/test_bgp_lu.py
@@ -45,6 +45,10 @@ from lib.topolog import logger
# Required to instantiate the topology builder class.
from mininet.topo import Topo
+
+pytestmark = [pytest.mark.bgpd]
+
+
# Basic scenario for BGP-LU. Nodes are directly connected.
# Node 3 is advertising many routes to 2, which advertises them
# as BGP-LU to 1; this way we get routes with actual labels, as
diff --git a/tests/topotests/bgp_multi_vrf_topo1/test_bgp_multi_vrf_topo1.py b/tests/topotests/bgp_multi_vrf_topo1/test_bgp_multi_vrf_topo1.py
index ac7ee44b25..5ecaee2ece 100644
--- a/tests/topotests/bgp_multi_vrf_topo1/test_bgp_multi_vrf_topo1.py
+++ b/tests/topotests/bgp_multi_vrf_topo1/test_bgp_multi_vrf_topo1.py
@@ -115,7 +115,7 @@ sys.path.append(os.path.join(CWD, "../lib/"))
# Import topogen and topotest helpers
from lib.topogen import Topogen, get_topogen
from mininet.topo import Topo
-
+from lib.topotest import iproute2_is_vrf_capable
from lib.common_config import (
step,
verify_rib,
@@ -215,6 +215,10 @@ def setup_module(mod):
if result is not True:
pytest.skip("Kernel requirements are not met")
+ # iproute2 needs to support VRFs for this suite to run.
+ if not iproute2_is_vrf_capable():
+ pytest.skip("Installed iproute2 version does not support VRFs")
+
testsuite_run_time = time.asctime(time.localtime(time.time()))
logger.info("Testsuite start time: {}".format(testsuite_run_time))
logger.info("=" * 40)
@@ -504,10 +508,10 @@ def test_ambiguous_overlapping_addresses_in_different_vrfs_p0(request):
)
result = verify_rib(tgen, addr_type, dut, input_dict_1, tag=500, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "Routes are present with tag value 500 \n Error: {}".format(
- tc_name, result
- ))
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Routes are present with tag value 500 \n Error: {}".format(tc_name, result)
+ )
logger.info("Expected Behavior: {}".format(result))
step(
@@ -1143,10 +1147,12 @@ def test_prefixes_leaking_p0(request):
result = verify_rib(
tgen, addr_type, dut, input_dict_1, metric=123, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"Routes are present with metric value 123 \n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
logger.info("Expected Behavior: {}".format(result))
result = verify_rib(tgen, addr_type, dut, input_dict_2, metric=123)
@@ -1157,10 +1163,12 @@ def test_prefixes_leaking_p0(request):
result = verify_rib(
tgen, addr_type, dut, input_dict_2, metric=0, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"Routes are present with metric value 0 \n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
logger.info("Expected Behavior: {}".format(result))
write_test_footer(tc_name)
diff --git a/tests/topotests/bgp_multi_vrf_topo2/test_bgp_multi_vrf_topo2.py b/tests/topotests/bgp_multi_vrf_topo2/test_bgp_multi_vrf_topo2.py
index c6e1792e84..c8d1330122 100644
--- a/tests/topotests/bgp_multi_vrf_topo2/test_bgp_multi_vrf_topo2.py
+++ b/tests/topotests/bgp_multi_vrf_topo2/test_bgp_multi_vrf_topo2.py
@@ -71,7 +71,7 @@ sys.path.append(os.path.join(CWD, "../lib/"))
# Import topogen and topotest helpers
from lib.topogen import Topogen, get_topogen
from mininet.topo import Topo
-
+from lib.topotest import iproute2_is_vrf_capable
from lib.common_config import (
step,
verify_rib,
@@ -102,6 +102,10 @@ from lib.topolog import logger
from lib.bgp import clear_bgp, verify_bgp_rib, create_router_bgp, verify_bgp_convergence
from lib.topojson import build_config_from_json, build_topo_from_json
+
+pytestmark = [pytest.mark.bgpd, pytest.mark.staticd]
+
+
# Reading the data from JSON File for topology creation
jsonFile = "{}/bgp_multi_vrf_topo2.json".format(CWD)
@@ -164,6 +168,10 @@ def setup_module(mod):
if result is not True:
pytest.skip("Kernel requirements are not met")
+ # iproute2 needs to support VRFs for this suite to run.
+ if not iproute2_is_vrf_capable():
+ pytest.skip("Installed iproute2 version does not support VRFs")
+
testsuite_run_time = time.asctime(time.localtime(time.time()))
logger.info("Testsuite start time: {}".format(testsuite_run_time))
logger.info("=" * 40)
@@ -2214,16 +2222,20 @@ def test_restart_bgpd_daemon_p1(request):
}
result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"Routes are still present in VRF RED_A and RED_B \n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
result = verify_rib(tgen, addr_type, dut, input_dict_2, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"Routes are still present in VRF BLUE_A and BLUE_B \n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
step("Bring up BGPd daemon on R1.")
start_router_daemons(tgen, "r1", ["bgpd"])
diff --git a/tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_1-post4.1.ref b/tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_1-post4.1.ref
index 9e30bf2ef0..6b20e1df5a 100644
--- a/tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_1-post4.1.ref
+++ b/tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_1-post4.1.ref
@@ -3,6 +3,7 @@ Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
+RPKI validation codes: V valid, I invalid, N Not found
Network Next Hop Metric LocPrf Weight Path
* 10.0.1.0/24 172.16.1.5 0 65005 i
diff --git a/tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_1-post6.1.ref b/tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_1-post6.1.ref
index 2cf87487ab..5469eaa1cc 100644
--- a/tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_1-post6.1.ref
+++ b/tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_1-post6.1.ref
@@ -4,6 +4,7 @@ Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
+RPKI validation codes: V valid, I invalid, N Not found
Network Next Hop Metric LocPrf Weight Path
* 10.0.1.0/24 172.16.1.5 0 65005 i
diff --git a/tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_2-post4.1.ref b/tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_2-post4.1.ref
index 39eb3134be..a64927c92d 100644
--- a/tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_2-post4.1.ref
+++ b/tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_2-post4.1.ref
@@ -3,6 +3,7 @@ Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
+RPKI validation codes: V valid, I invalid, N Not found
Network Next Hop Metric LocPrf Weight Path
* 10.0.1.0/24 172.16.1.4 0 65004 i
diff --git a/tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_2-post6.1.ref b/tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_2-post6.1.ref
index 9d1b948b5c..8d4a843b84 100644
--- a/tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_2-post6.1.ref
+++ b/tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_2-post6.1.ref
@@ -4,6 +4,7 @@ Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
+RPKI validation codes: V valid, I invalid, N Not found
Network Next Hop Metric LocPrf Weight Path
* 10.0.1.0/24 172.16.1.4 0 65004 i
diff --git a/tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_3-post4.1.ref b/tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_3-post4.1.ref
index fa53d79e88..a3b9ef0888 100644
--- a/tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_3-post4.1.ref
+++ b/tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_3-post4.1.ref
@@ -3,6 +3,7 @@ Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
+RPKI validation codes: V valid, I invalid, N Not found
Network Next Hop Metric LocPrf Weight Path
* 10.0.1.0/24 172.16.1.8 0 65008 i
diff --git a/tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_3-post6.1.ref b/tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_3-post6.1.ref
index 8b66fa67ec..117e48847a 100644
--- a/tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_3-post6.1.ref
+++ b/tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_3-post6.1.ref
@@ -4,6 +4,7 @@ Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
+RPKI validation codes: V valid, I invalid, N Not found
Network Next Hop Metric LocPrf Weight Path
* 10.0.1.0/24 172.16.1.8 0 65008 i
diff --git a/tests/topotests/bgp_peer-group/test_bgp_peer-group.py b/tests/topotests/bgp_peer-group/test_bgp_peer-group.py
index 7c7a8b87ed..21dc725793 100644
--- a/tests/topotests/bgp_peer-group/test_bgp_peer-group.py
+++ b/tests/topotests/bgp_peer-group/test_bgp_peer-group.py
@@ -39,6 +39,9 @@ from lib.topolog import logger
from mininet.topo import Topo
+pytestmark = [pytest.mark.bgpd]
+
+
class TemplateTopo(Topo):
def build(self, *_args, **_opts):
tgen = get_topogen(self)
diff --git a/tests/topotests/bgp_peer-type_multipath-relax/exabgp.env b/tests/topotests/bgp_peer-type_multipath-relax/exabgp.env
new file mode 100644
index 0000000000..6c554f5fa8
--- /dev/null
+++ b/tests/topotests/bgp_peer-type_multipath-relax/exabgp.env
@@ -0,0 +1,53 @@
+
+[exabgp.api]
+encoder = text
+highres = false
+respawn = false
+socket = ''
+
+[exabgp.bgp]
+openwait = 60
+
+[exabgp.cache]
+attributes = true
+nexthops = true
+
+[exabgp.daemon]
+daemonize = true
+pid = '/var/run/exabgp/exabgp.pid'
+user = 'exabgp'
+
+[exabgp.log]
+all = false
+configuration = true
+daemon = true
+destination = '/var/log/exabgp.log'
+enable = true
+level = INFO
+message = false
+network = true
+packets = false
+parser = false
+processes = true
+reactor = true
+rib = false
+routes = false
+short = false
+timers = false
+
+[exabgp.pdb]
+enable = false
+
+[exabgp.profile]
+enable = false
+file = ''
+
+[exabgp.reactor]
+speed = 1.0
+
+[exabgp.tcp]
+acl = false
+bind = ''
+delay = 0
+once = false
+port = 179
diff --git a/tests/topotests/bgp_peer-type_multipath-relax/peer1/exa-receive.py b/tests/topotests/bgp_peer-type_multipath-relax/peer1/exa-receive.py
new file mode 100755
index 0000000000..031ff455ca
--- /dev/null
+++ b/tests/topotests/bgp_peer-type_multipath-relax/peer1/exa-receive.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+
+"""
+exa-receive.py: Save received routes form ExaBGP into file
+"""
+
+from sys import stdin, argv
+from datetime import datetime
+
+# 1st arg is peer number
+peer = int(argv[1])
+
+# When the parent dies we are seeing continual newlines, so we only access so many before stopping
+counter = 0
+
+routesavefile = open("/tmp/peer%s-received.log" % peer, "w")
+
+while True:
+ try:
+ line = stdin.readline()
+ timestamp = datetime.now().strftime("%Y%m%d_%H:%M:%S - ")
+ routesavefile.write(timestamp + line)
+ routesavefile.flush()
+
+ if line == "":
+ counter += 1
+ if counter > 100:
+ break
+ continue
+
+ counter = 0
+ except KeyboardInterrupt:
+ pass
+ except IOError:
+ # most likely a signal during readline
+ pass
+
+routesavefile.close()
diff --git a/tests/topotests/bgp_peer-type_multipath-relax/peer1/exa_readpipe.py b/tests/topotests/bgp_peer-type_multipath-relax/peer1/exa_readpipe.py
new file mode 100644
index 0000000000..9e689a27e3
--- /dev/null
+++ b/tests/topotests/bgp_peer-type_multipath-relax/peer1/exa_readpipe.py
@@ -0,0 +1,19 @@
+#!/usr/bin/env python
+"Helper script to read api commands from a pipe and feed them to ExaBGP"
+
+import sys
+
+if len(sys.argv) != 2:
+ sys.exit(1)
+fifo = sys.argv[1]
+
+while True:
+ pipe = open(fifo, "r")
+ with pipe:
+ line = pipe.readline().strip()
+ if line != "":
+ sys.stdout.write("{}\n".format(line))
+ sys.stdout.flush()
+ pipe.close()
+
+sys.exit(0)
diff --git a/tests/topotests/bgp_peer-type_multipath-relax/peer1/exabgp.cfg b/tests/topotests/bgp_peer-type_multipath-relax/peer1/exabgp.cfg
new file mode 100644
index 0000000000..4a7dc48126
--- /dev/null
+++ b/tests/topotests/bgp_peer-type_multipath-relax/peer1/exabgp.cfg
@@ -0,0 +1,21 @@
+group controller {
+
+ process announce-routes {
+ run "/etc/exabgp/exa_readpipe.py /var/run/exabgp_peer1.in";
+ encoder text;
+ }
+
+ process receive-routes {
+ run "/etc/exabgp/exa-receive.py 1";
+ receive-routes;
+ encoder text;
+ }
+
+ neighbor 10.0.1.1 {
+ router-id 10.0.1.2;
+ local-address 10.0.1.2;
+ local-as 64510;
+ peer-as 64510;
+ }
+
+}
diff --git a/tests/topotests/bgp_peer-type_multipath-relax/peer2/exa-receive.py b/tests/topotests/bgp_peer-type_multipath-relax/peer2/exa-receive.py
new file mode 100755
index 0000000000..031ff455ca
--- /dev/null
+++ b/tests/topotests/bgp_peer-type_multipath-relax/peer2/exa-receive.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+
+"""
+exa-receive.py: Save received routes form ExaBGP into file
+"""
+
+from sys import stdin, argv
+from datetime import datetime
+
+# 1st arg is peer number
+peer = int(argv[1])
+
+# When the parent dies we are seeing continual newlines, so we only access so many before stopping
+counter = 0
+
+routesavefile = open("/tmp/peer%s-received.log" % peer, "w")
+
+while True:
+ try:
+ line = stdin.readline()
+ timestamp = datetime.now().strftime("%Y%m%d_%H:%M:%S - ")
+ routesavefile.write(timestamp + line)
+ routesavefile.flush()
+
+ if line == "":
+ counter += 1
+ if counter > 100:
+ break
+ continue
+
+ counter = 0
+ except KeyboardInterrupt:
+ pass
+ except IOError:
+ # most likely a signal during readline
+ pass
+
+routesavefile.close()
diff --git a/tests/topotests/bgp_peer-type_multipath-relax/peer2/exa_readpipe.py b/tests/topotests/bgp_peer-type_multipath-relax/peer2/exa_readpipe.py
new file mode 100644
index 0000000000..9e689a27e3
--- /dev/null
+++ b/tests/topotests/bgp_peer-type_multipath-relax/peer2/exa_readpipe.py
@@ -0,0 +1,19 @@
+#!/usr/bin/env python
+"Helper script to read api commands from a pipe and feed them to ExaBGP"
+
+import sys
+
+if len(sys.argv) != 2:
+ sys.exit(1)
+fifo = sys.argv[1]
+
+while True:
+ pipe = open(fifo, "r")
+ with pipe:
+ line = pipe.readline().strip()
+ if line != "":
+ sys.stdout.write("{}\n".format(line))
+ sys.stdout.flush()
+ pipe.close()
+
+sys.exit(0)
diff --git a/tests/topotests/bgp_peer-type_multipath-relax/peer2/exabgp.cfg b/tests/topotests/bgp_peer-type_multipath-relax/peer2/exabgp.cfg
new file mode 100644
index 0000000000..b53b054550
--- /dev/null
+++ b/tests/topotests/bgp_peer-type_multipath-relax/peer2/exabgp.cfg
@@ -0,0 +1,21 @@
+group controller {
+
+ process announce-routes {
+ run "/etc/exabgp/exa_readpipe.py /var/run/exabgp_peer2.in";
+ encoder text;
+ }
+
+ process receive-routes {
+ run "/etc/exabgp/exa-receive.py 2";
+ receive-routes;
+ encoder text;
+ }
+
+ neighbor 10.0.2.1 {
+ router-id 10.0.2.2;
+ local-address 10.0.2.2;
+ local-as 64511;
+ peer-as 64511;
+ }
+
+}
diff --git a/tests/topotests/bgp_peer-type_multipath-relax/peer3/exa-receive.py b/tests/topotests/bgp_peer-type_multipath-relax/peer3/exa-receive.py
new file mode 100755
index 0000000000..031ff455ca
--- /dev/null
+++ b/tests/topotests/bgp_peer-type_multipath-relax/peer3/exa-receive.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+
+"""
+exa-receive.py: Save received routes form ExaBGP into file
+"""
+
+from sys import stdin, argv
+from datetime import datetime
+
+# 1st arg is peer number
+peer = int(argv[1])
+
+# When the parent dies we are seeing continual newlines, so we only access so many before stopping
+counter = 0
+
+routesavefile = open("/tmp/peer%s-received.log" % peer, "w")
+
+while True:
+ try:
+ line = stdin.readline()
+ timestamp = datetime.now().strftime("%Y%m%d_%H:%M:%S - ")
+ routesavefile.write(timestamp + line)
+ routesavefile.flush()
+
+ if line == "":
+ counter += 1
+ if counter > 100:
+ break
+ continue
+
+ counter = 0
+ except KeyboardInterrupt:
+ pass
+ except IOError:
+ # most likely a signal during readline
+ pass
+
+routesavefile.close()
diff --git a/tests/topotests/bgp_peer-type_multipath-relax/peer3/exa_readpipe.py b/tests/topotests/bgp_peer-type_multipath-relax/peer3/exa_readpipe.py
new file mode 100644
index 0000000000..9e689a27e3
--- /dev/null
+++ b/tests/topotests/bgp_peer-type_multipath-relax/peer3/exa_readpipe.py
@@ -0,0 +1,19 @@
+#!/usr/bin/env python
+"Helper script to read api commands from a pipe and feed them to ExaBGP"
+
+import sys
+
+if len(sys.argv) != 2:
+ sys.exit(1)
+fifo = sys.argv[1]
+
+while True:
+ pipe = open(fifo, "r")
+ with pipe:
+ line = pipe.readline().strip()
+ if line != "":
+ sys.stdout.write("{}\n".format(line))
+ sys.stdout.flush()
+ pipe.close()
+
+sys.exit(0)
diff --git a/tests/topotests/bgp_peer-type_multipath-relax/peer3/exabgp.cfg b/tests/topotests/bgp_peer-type_multipath-relax/peer3/exabgp.cfg
new file mode 100644
index 0000000000..6a1cc2fb3f
--- /dev/null
+++ b/tests/topotests/bgp_peer-type_multipath-relax/peer3/exabgp.cfg
@@ -0,0 +1,21 @@
+group controller {
+
+ process announce-routes {
+ run "/etc/exabgp/exa_readpipe.py /var/run/exabgp_peer3.in";
+ encoder text;
+ }
+
+ process receive-routes {
+ run "/etc/exabgp/exa-receive.py 3";
+ receive-routes;
+ encoder text;
+ }
+
+ neighbor 10.0.3.1 {
+ router-id 10.0.3.2;
+ local-address 10.0.3.2;
+ local-as 64502;
+ peer-as 64501;
+ }
+
+}
diff --git a/tests/topotests/bgp_peer-type_multipath-relax/peer4/exa-receive.py b/tests/topotests/bgp_peer-type_multipath-relax/peer4/exa-receive.py
new file mode 100755
index 0000000000..031ff455ca
--- /dev/null
+++ b/tests/topotests/bgp_peer-type_multipath-relax/peer4/exa-receive.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+
+"""
+exa-receive.py: Save received routes form ExaBGP into file
+"""
+
+from sys import stdin, argv
+from datetime import datetime
+
+# 1st arg is peer number
+peer = int(argv[1])
+
+# When the parent dies we are seeing continual newlines, so we only access so many before stopping
+counter = 0
+
+routesavefile = open("/tmp/peer%s-received.log" % peer, "w")
+
+while True:
+ try:
+ line = stdin.readline()
+ timestamp = datetime.now().strftime("%Y%m%d_%H:%M:%S - ")
+ routesavefile.write(timestamp + line)
+ routesavefile.flush()
+
+ if line == "":
+ counter += 1
+ if counter > 100:
+ break
+ continue
+
+ counter = 0
+ except KeyboardInterrupt:
+ pass
+ except IOError:
+ # most likely a signal during readline
+ pass
+
+routesavefile.close()
diff --git a/tests/topotests/bgp_peer-type_multipath-relax/peer4/exa_readpipe.py b/tests/topotests/bgp_peer-type_multipath-relax/peer4/exa_readpipe.py
new file mode 100644
index 0000000000..9e689a27e3
--- /dev/null
+++ b/tests/topotests/bgp_peer-type_multipath-relax/peer4/exa_readpipe.py
@@ -0,0 +1,19 @@
+#!/usr/bin/env python
+"Helper script to read api commands from a pipe and feed them to ExaBGP"
+
+import sys
+
+if len(sys.argv) != 2:
+ sys.exit(1)
+fifo = sys.argv[1]
+
+while True:
+ pipe = open(fifo, "r")
+ with pipe:
+ line = pipe.readline().strip()
+ if line != "":
+ sys.stdout.write("{}\n".format(line))
+ sys.stdout.flush()
+ pipe.close()
+
+sys.exit(0)
diff --git a/tests/topotests/bgp_peer-type_multipath-relax/peer4/exabgp.cfg b/tests/topotests/bgp_peer-type_multipath-relax/peer4/exabgp.cfg
new file mode 100644
index 0000000000..2cc26cb80f
--- /dev/null
+++ b/tests/topotests/bgp_peer-type_multipath-relax/peer4/exabgp.cfg
@@ -0,0 +1,21 @@
+group controller {
+
+ process announce-routes {
+ run "/etc/exabgp/exa_readpipe.py /var/run/exabgp_peer4.in";
+ encoder text;
+ }
+
+ process receive-routes {
+ run "/etc/exabgp/exa-receive.py 4";
+ receive-routes;
+ encoder text;
+ }
+
+ neighbor 10.0.4.1 {
+ router-id 10.0.4.2;
+ local-address 10.0.4.2;
+ local-as 64503;
+ peer-as 64501;
+ }
+
+}
diff --git a/tests/topotests/bgp_peer-type_multipath-relax/r1/bgpd.conf b/tests/topotests/bgp_peer-type_multipath-relax/r1/bgpd.conf
new file mode 100644
index 0000000000..038f108aa8
--- /dev/null
+++ b/tests/topotests/bgp_peer-type_multipath-relax/r1/bgpd.conf
@@ -0,0 +1,16 @@
+!
+router bgp 64510
+ bgp router-id 10.0.1.1
+ no bgp ebgp-requires-policy
+ bgp confederation identifier 64501
+ bgp confederation peers 64511
+ bgp bestpath as-path multipath-relax
+ bgp bestpath compare-routerid
+ bgp bestpath peer-type multipath-relax
+ neighbor 10.0.1.2 remote-as 64510
+ neighbor 10.0.3.2 remote-as 64502
+ neighbor 10.0.4.2 remote-as 64503
+ neighbor 10.0.5.2 remote-as 64511
+!
+line vty
+!
diff --git a/tests/topotests/bgp_peer-type_multipath-relax/r1/multipath.json b/tests/topotests/bgp_peer-type_multipath-relax/r1/multipath.json
new file mode 100644
index 0000000000..11dad786f2
--- /dev/null
+++ b/tests/topotests/bgp_peer-type_multipath-relax/r1/multipath.json
@@ -0,0 +1,50 @@
+{
+ "routes": { "203.0.113.0/30": [
+ {
+ "valid":true,
+ "multipath":true,
+ "pathFrom":"external",
+ "peerId":"10.0.5.2"
+ },
+ {
+ "valid":true,
+ "bestpath":true,
+ "selectionReason":"Peer Type",
+ "pathFrom":"external",
+ "peerId":"10.0.4.2"
+ },
+ {
+ "valid":true,
+ "multipath":true,
+ "pathFrom":"internal",
+ "peerId":"10.0.1.2"
+ }
+],"203.0.113.4/30": [
+ {
+ "valid":true,
+ "bestpath":true,
+ "selectionReason":"Confed Peer Type",
+ "pathFrom":"external",
+ "peerId":"10.0.5.2"
+ },
+ {
+ "valid":true,
+ "multipath":true,
+ "pathFrom":"internal",
+ "peerId":"10.0.1.2"
+ }
+],"203.0.113.8/30": [
+ {
+ "valid":true,
+ "multipath":true,
+ "pathFrom":"external",
+ "peerId":"10.0.4.2"
+ },
+ {
+ "valid":true,
+ "bestpath":true,
+ "selectionReason":"Router ID",
+ "pathFrom":"external",
+ "peerId":"10.0.3.2"
+ }
+] } }
diff --git a/tests/topotests/bgp_peer-type_multipath-relax/r1/not-multipath.json b/tests/topotests/bgp_peer-type_multipath-relax/r1/not-multipath.json
new file mode 100644
index 0000000000..c621832157
--- /dev/null
+++ b/tests/topotests/bgp_peer-type_multipath-relax/r1/not-multipath.json
@@ -0,0 +1,50 @@
+{
+ "routes": { "203.0.113.0/30": [
+ {
+ "valid":true,
+ "multipath":null,
+ "pathFrom":"external",
+ "peerId":"10.0.5.2"
+ },
+ {
+ "valid":true,
+ "bestpath":true,
+ "selectionReason":"Peer Type",
+ "pathFrom":"external",
+ "peerId":"10.0.4.2"
+ },
+ {
+ "valid":true,
+ "multipath":null,
+ "pathFrom":"internal",
+ "peerId":"10.0.1.2"
+ }
+],"203.0.113.4/30": [
+ {
+ "valid":true,
+ "bestpath":true,
+ "selectionReason":"Confed Peer Type",
+ "pathFrom":"external",
+ "peerId":"10.0.5.2"
+ },
+ {
+ "valid":true,
+ "multipath":null,
+ "pathFrom":"internal",
+ "peerId":"10.0.1.2"
+ }
+],"203.0.113.8/30": [
+ {
+ "valid":true,
+ "multipath":true,
+ "pathFrom":"external",
+ "peerId":"10.0.4.2"
+ },
+ {
+ "valid":true,
+ "bestpath":true,
+ "selectionReason":"Router ID",
+ "pathFrom":"external",
+ "peerId":"10.0.3.2"
+ }
+] } }
diff --git a/tests/topotests/bgp_peer-type_multipath-relax/r1/prefix1-eBGP-confed.json b/tests/topotests/bgp_peer-type_multipath-relax/r1/prefix1-eBGP-confed.json
new file mode 100644
index 0000000000..22ec2c298b
--- /dev/null
+++ b/tests/topotests/bgp_peer-type_multipath-relax/r1/prefix1-eBGP-confed.json
@@ -0,0 +1,33 @@
+{
+ "203.0.113.0\/30":[
+ {
+ "prefix":"203.0.113.0\/30",
+ "protocol":"bgp",
+ "installed":true,
+ "internalNextHopNum":4,
+ "internalNextHopActiveNum":4,
+ "nexthops":[
+ {
+ "ip":"198.51.100.2",
+ "active":true,
+ "recursive":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "active":true
+ },
+ {
+ "ip":"198.51.100.10",
+ "active":true,
+ "recursive":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_peer-type_multipath-relax/r1/prefix1-eBGP-iBGP.json b/tests/topotests/bgp_peer-type_multipath-relax/r1/prefix1-eBGP-iBGP.json
new file mode 100644
index 0000000000..facddcda46
--- /dev/null
+++ b/tests/topotests/bgp_peer-type_multipath-relax/r1/prefix1-eBGP-iBGP.json
@@ -0,0 +1,33 @@
+{
+ "203.0.113.0\/30":[
+ {
+ "prefix":"203.0.113.0\/30",
+ "protocol":"bgp",
+ "installed":true,
+ "internalNextHopNum":4,
+ "internalNextHopActiveNum":4,
+ "nexthops":[
+ {
+ "ip":"198.51.100.1",
+ "active":true,
+ "recursive":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "active":true
+ },
+ {
+ "ip":"198.51.100.10",
+ "active":true,
+ "recursive":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_peer-type_multipath-relax/r1/prefix1-no-recursive.json b/tests/topotests/bgp_peer-type_multipath-relax/r1/prefix1-no-recursive.json
new file mode 100644
index 0000000000..5399ceefcc
--- /dev/null
+++ b/tests/topotests/bgp_peer-type_multipath-relax/r1/prefix1-no-recursive.json
@@ -0,0 +1,35 @@
+{
+ "prefix":"203.0.113.0\/30",
+ "paths":[
+ {
+ "valid":false,
+ "peer":{
+ "peerId":"10.0.4.2",
+ "routerId":"10.0.4.2",
+ "type":"external"
+ }
+ },
+ {
+ "valid":true,
+ "multipath":true,
+ "bestpath":{
+ "overall":true,
+ "selectionReason":"Confed Peer Type"
+ },
+ "peer":{
+ "peerId":"10.0.5.2",
+ "routerId":"10.0.5.2",
+ "type":"confed-external"
+ }
+ },
+ {
+ "valid":true,
+ "multipath":true,
+ "peer":{
+ "peerId":"10.0.1.2",
+ "routerId":"10.0.1.2",
+ "type":"confed-internal"
+ }
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_peer-type_multipath-relax/r1/prefix1-recursive.json b/tests/topotests/bgp_peer-type_multipath-relax/r1/prefix1-recursive.json
new file mode 100644
index 0000000000..7da95aed1c
--- /dev/null
+++ b/tests/topotests/bgp_peer-type_multipath-relax/r1/prefix1-recursive.json
@@ -0,0 +1,36 @@
+{
+ "prefix":"203.0.113.0\/30",
+ "paths":[
+ {
+ "valid":true,
+ "multipath":true,
+ "bestpath":{
+ "overall":true,
+ "selectionReason":"Peer Type"
+ },
+ "peer":{
+ "peerId":"10.0.4.2",
+ "routerId":"10.0.4.2",
+ "type":"external"
+ }
+ },
+ {
+ "valid":true,
+ "multipath":true,
+ "peer":{
+ "peerId":"10.0.5.2",
+ "routerId":"10.0.5.2",
+ "type":"confed-external"
+ }
+ },
+ {
+ "valid":true,
+ "multipath":true,
+ "peer":{
+ "peerId":"10.0.1.2",
+ "routerId":"10.0.1.2",
+ "type":"confed-internal"
+ }
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_peer-type_multipath-relax/r1/prefix1.json b/tests/topotests/bgp_peer-type_multipath-relax/r1/prefix1.json
new file mode 100644
index 0000000000..a90669a474
--- /dev/null
+++ b/tests/topotests/bgp_peer-type_multipath-relax/r1/prefix1.json
@@ -0,0 +1,33 @@
+{
+ "prefix":"203.0.113.0\/30",
+ "paths":[
+ {
+ "multipath":true,
+ "peer":{
+ "peerId":"10.0.5.2",
+ "routerId":"10.0.5.2",
+ "type":"confed-external"
+ }
+ },
+ {
+ "multipath":true,
+ "bestpath":{
+ "overall":true,
+ "selectionReason":"Peer Type"
+ },
+ "peer":{
+ "peerId":"10.0.4.2",
+ "routerId":"10.0.4.2",
+ "type":"external"
+ }
+ },
+ {
+ "multipath":true,
+ "peer":{
+ "peerId":"10.0.1.2",
+ "routerId":"10.0.1.2",
+ "type":"confed-internal"
+ }
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_peer-type_multipath-relax/r1/prefix3-ip-route.json b/tests/topotests/bgp_peer-type_multipath-relax/r1/prefix3-ip-route.json
new file mode 100644
index 0000000000..1bf38efcc5
--- /dev/null
+++ b/tests/topotests/bgp_peer-type_multipath-relax/r1/prefix3-ip-route.json
@@ -0,0 +1,23 @@
+{
+ "203.0.113.8\/30":[
+ {
+ "prefix":"203.0.113.8\/30",
+ "protocol":"bgp",
+ "installed":true,
+ "internalNextHopNum":2,
+ "internalNextHopActiveNum":1,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "active":true
+ },
+ {
+ "fib":null,
+ "ip":"198.51.100.10",
+ "active":null
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_peer-type_multipath-relax/r1/prefix3-no-recursive.json b/tests/topotests/bgp_peer-type_multipath-relax/r1/prefix3-no-recursive.json
new file mode 100644
index 0000000000..33d0f2d1ce
--- /dev/null
+++ b/tests/topotests/bgp_peer-type_multipath-relax/r1/prefix3-no-recursive.json
@@ -0,0 +1,21 @@
+{
+ "prefix":"203.0.113.8\/30",
+ "paths":[
+ {
+ "valid":false,
+ "peer":{
+ "peerId":"10.0.4.2",
+ "routerId":"10.0.4.2",
+ "type":"external"
+ }
+ },
+ {
+ "valid":true,
+ "peer":{
+ "peerId":"10.0.3.2",
+ "routerId":"10.0.3.2",
+ "type":"external"
+ }
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_peer-type_multipath-relax/r1/prefix3-recursive.json b/tests/topotests/bgp_peer-type_multipath-relax/r1/prefix3-recursive.json
new file mode 100644
index 0000000000..6ac2512a60
--- /dev/null
+++ b/tests/topotests/bgp_peer-type_multipath-relax/r1/prefix3-recursive.json
@@ -0,0 +1,23 @@
+{
+ "prefix":"203.0.113.8\/30",
+ "paths":[
+ {
+ "valid":true,
+ "multipath":true,
+ "peer":{
+ "peerId":"10.0.4.2",
+ "routerId":"10.0.4.2",
+ "type":"external"
+ }
+ },
+ {
+ "valid":true,
+ "multipath":true,
+ "peer":{
+ "peerId":"10.0.3.2",
+ "routerId":"10.0.3.2",
+ "type":"external"
+ }
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_peer-type_multipath-relax/r1/zebra.conf b/tests/topotests/bgp_peer-type_multipath-relax/r1/zebra.conf
new file mode 100644
index 0000000000..911aa1c39d
--- /dev/null
+++ b/tests/topotests/bgp_peer-type_multipath-relax/r1/zebra.conf
@@ -0,0 +1,27 @@
+!
+hostname r1
+!
+interface r1-eth0
+ description ExaBGP iBGP peer1
+ ip address 10.0.1.1/24
+ no link-detect
+!
+interface r1-eth1
+ description ExaBGP peer3
+ ip address 10.0.3.1/24
+ no link-detect
+!
+interface r1-eth2
+ description ExaBGP peer4
+ ip address 10.0.4.1/24
+ no link-detect
+!
+interface r1-eth3
+ description r2 confed peer
+ ip address 10.0.5.1/24
+ no link-detect
+!
+ip forwarding
+!
+line vty
+!
diff --git a/tests/topotests/bgp_peer-type_multipath-relax/r2/bgpd.conf b/tests/topotests/bgp_peer-type_multipath-relax/r2/bgpd.conf
new file mode 100644
index 0000000000..2362a19f26
--- /dev/null
+++ b/tests/topotests/bgp_peer-type_multipath-relax/r2/bgpd.conf
@@ -0,0 +1,19 @@
+!
+!log file bgpd.log
+!
+router bgp 64511
+ bgp confederation identifier 64501
+ bgp confederation peers 64510
+ bgp router-id 10.0.5.2
+ no bgp ebgp-requires-policy
+ neighbor 10.0.2.2 remote-as 64511
+ neighbor 10.0.5.1 remote-as 64510
+ !
+ address-family ipv4 unicast
+ neighbor 10.0.5.1 route-map dropall in
+ exit-address-family
+!
+route-map dropall deny 10
+!
+line vty
+!
diff --git a/tests/topotests/bgp_peer-type_multipath-relax/r2/staticd.conf b/tests/topotests/bgp_peer-type_multipath-relax/r2/staticd.conf
new file mode 100644
index 0000000000..35ebe0dc66
--- /dev/null
+++ b/tests/topotests/bgp_peer-type_multipath-relax/r2/staticd.conf
@@ -0,0 +1,4 @@
+hostname r2
+!
+ip route 198.51.100.0/24 10.0.2.2
+!
diff --git a/tests/topotests/bgp_peer-type_multipath-relax/r2/zebra.conf b/tests/topotests/bgp_peer-type_multipath-relax/r2/zebra.conf
new file mode 100644
index 0000000000..900e7d4fbc
--- /dev/null
+++ b/tests/topotests/bgp_peer-type_multipath-relax/r2/zebra.conf
@@ -0,0 +1,19 @@
+!
+!
+hostname r2
+!
+interface r2-eth0
+ description ExaBGP peer
+ ip address 10.0.2.1/24
+ no link-detect
+!
+interface r2-eth1
+ description r1 confed peer
+ ip address 10.0.5.2/24
+ no link-detect
+!
+ip forwarding
+!
+!
+line vty
+!
diff --git a/tests/topotests/bgp_peer-type_multipath-relax/test_bgp_peer-type_multipath-relax.py b/tests/topotests/bgp_peer-type_multipath-relax/test_bgp_peer-type_multipath-relax.py
new file mode 100755
index 0000000000..39a0beeb11
--- /dev/null
+++ b/tests/topotests/bgp_peer-type_multipath-relax/test_bgp_peer-type_multipath-relax.py
@@ -0,0 +1,386 @@
+#!/usr/bin/env python
+
+#
+# Part of NetDEF Topology Tests
+#
+# Copyright (c) 2021 Arista Networks, Inc.
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND Arista Networks DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+test_bgp_peer-type_multipath-relax.py:
+
+Test the effects of the "bgp bestpath peer-type multipath-relax" command
+
+- enabling the command allows eBGP, iBGP, and confed routes to be multipath
+- the choice of best path is not affected
+- disabling the command removes iBGP/confed routes from multipath
+- enabling the command does not forgive eBGP routes of the requirement
+ (when enabled) that next hops resolve over connected routes
+- a mixed-type multipath next hop, when published to zebra, does not
+ require resolving next hops over connected routes
+- with the command enabled, an all-eBGP multipath next hop still requires
+ resolving next hops over connected routes when published to zebra
+
+Topology used by the test:
+
+ eBGP +------+ iBGP
+ peer1 ---- | r1 | ---- peer3
+ | |
+peer2 ---- r2 ---- | | ---- peer4
+ iBGP confed +------+ eBGP
+
+r2 is present in this topology because ExaBGP does not currently support
+confederations so we use FRR to advertise the required AS_CONFED_SEQUENCE.
+
+Routes are advertised from different peers to form interesting multipaths.
+
+ peer1 peer2 peer3 peer4 multipath on r1
+
+203.0.113.0/30 x x x all 3
+203.0.113.4/30 x x confed-iBGP
+203.0.113.8/30 x x eBGP-only
+
+There is also a BGP-advertised route used only for recursively resolving
+next hops.
+"""
+
+import functools
+import json
+import os
+import pytest
+import sys
+
+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.topolog import logger
+from mininet.topo import Topo
+
+
+class PeerTypeRelaxTopo(Topo):
+ def build(self, *_args, **_opts):
+ "Build function"
+ tgen = get_topogen(self)
+
+ # Set up routers
+ tgen.add_router("r1") # DUT
+ tgen.add_router("r2")
+
+ # Set up peers
+ for peern in range(1, 5):
+ peer = tgen.add_exabgp_peer(
+ "peer{}".format(peern),
+ ip="10.0.{}.2/24".format(peern),
+ defaultRoute="via 10.0.{}.1".format(peern),
+ )
+ if peern == 2:
+ tgen.add_link(tgen.gears["r2"], peer)
+ else:
+ tgen.add_link(tgen.gears["r1"], peer)
+ tgen.add_link(tgen.gears["r1"], tgen.gears["r2"])
+
+
+def setup_module(mod):
+ "Sets up the pytest environment"
+ tgen = Topogen(PeerTypeRelaxTopo, mod.__name__)
+ tgen.start_topology()
+
+ # For all registered routers, load the zebra configuration file
+ for rname, router in tgen.routers().items():
+ router.run("/bin/bash {}/setup_vrfs".format(CWD))
+ 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_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
+ )
+
+ # After loading the configurations, this function loads configured daemons.
+ tgen.start_router()
+
+ # Start up exabgp peers
+ peers = tgen.exabgp_peers()
+ for peer in peers:
+ fifo_in = "/var/run/exabgp_{}.in".format(peer)
+ if os.path.exists(fifo_in):
+ os.remove(fifo_in)
+ os.mkfifo(fifo_in, 0o777)
+ logger.info("Starting ExaBGP on peer {}".format(peer))
+ peer_dir = os.path.join(CWD, peer)
+ env_file = os.path.join(CWD, "exabgp.env")
+ peers[peer].start(peer_dir, env_file)
+
+
+def teardown_module(mod):
+ "Teardown the pytest environment"
+ tgen = get_topogen()
+
+ # This function tears down the whole topology.
+ tgen.stop_topology()
+
+
+def test_bgp_peer_type_multipath_relax():
+ tgen = get_topogen()
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ def exabgp_cmd(peer, cmd):
+ pipe = open("/run/exabgp_{}.in".format(peer), "w")
+ with pipe:
+ pipe.write(cmd)
+ pipe.close()
+
+ # Prefixes used in the test
+ prefix1 = "203.0.113.0/30"
+ prefix2 = "203.0.113.4/30"
+ prefix3 = "203.0.113.8/30"
+ # Next hops used for iBGP/confed routes
+ resolved_nh1 = "198.51.100.1"
+ resolved_nh2 = "198.51.100.2"
+ # BGP route used for recursive resolution
+ bgp_resolving_prefix = "198.51.100.0/24"
+ # Next hop that will require non-connected recursive resolution
+ ebgp_resolved_nh = "198.51.100.10"
+
+ # Send a non-connected route to resolve others
+ exabgp_cmd(
+ "peer3", "announce route {} next-hop self\n".format(bgp_resolving_prefix)
+ )
+ router = tgen.gears["r1"]
+
+ # It seems that if you write to the exabgp socket too quickly in
+ # succession, requests get lost. So verify prefix1 now instead of
+ # after all the prefixes are advertised.
+ logger.info("Create and verify mixed-type multipaths")
+ exabgp_cmd(
+ "peer1",
+ "announce route {} next-hop {} as-path [ 64499 ]\n".format(
+ prefix1, resolved_nh1
+ ),
+ )
+ exabgp_cmd(
+ "peer2",
+ "announce route {} next-hop {} as-path [ 64499 ]\n".format(
+ prefix1, resolved_nh2
+ ),
+ )
+ exabgp_cmd("peer4", "announce route {} next-hop self\n".format(prefix1))
+ reffile = os.path.join(CWD, "r1/prefix1.json")
+ expected = json.loads(open(reffile).read())
+ test_func = functools.partial(
+ topotest.router_json_cmp,
+ router,
+ "show ip bgp {} json".format(prefix1),
+ expected,
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=10, wait=1)
+ assertMsg = "Mixed-type multipath not found"
+ assert res is None, assertMsg
+
+ logger.info("Create and verify eBGP and iBGP+confed multipaths")
+ exabgp_cmd(
+ "peer1",
+ "announce route {} next-hop {} as-path [ 64499 ]\n".format(
+ prefix2, resolved_nh1
+ ),
+ )
+ exabgp_cmd(
+ "peer2",
+ "announce route {} next-hop {} as-path [ 64499 ]\n".format(
+ prefix2, resolved_nh2
+ ),
+ )
+ exabgp_cmd("peer3", "announce route {} next-hop self".format(prefix3))
+ exabgp_cmd("peer4", "announce route {} next-hop self".format(prefix3))
+ reffile = os.path.join(CWD, "r1/multipath.json")
+ expected = json.loads(open(reffile).read())
+ test_func = functools.partial(
+ topotest.router_json_cmp, router, "show ip bgp json", expected
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=10, wait=1)
+ assertMsg = "Not all expected multipaths found"
+ assert res is None, assertMsg
+
+ logger.info("Toggle peer-type multipath-relax and verify the changes")
+ router.vtysh_cmd(
+ "conf\n router bgp 64510\n no bgp bestpath peer-type multipath-relax\n"
+ )
+ # This file verifies "multipath" is not set
+ reffile = os.path.join(CWD, "r1/not-multipath.json")
+ expected = json.loads(open(reffile).read())
+ test_func = functools.partial(
+ topotest.router_json_cmp, router, "show ip bgp json", expected
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=10, wait=1)
+ assertMsg = "Disabling peer-type multipath-relax did not take effect"
+ assert res is None, assertMsg
+
+ router.vtysh_cmd(
+ "conf\n router bgp 64510\n bgp bestpath peer-type multipath-relax\n"
+ )
+ reffile = os.path.join(CWD, "r1/multipath.json")
+ expected = json.loads(open(reffile).read())
+ test_func = functools.partial(
+ topotest.router_json_cmp, router, "show ip bgp json", expected
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=10, wait=1)
+ assertMsg = "Reenabling peer-type multipath-relax did not take effect"
+ assert res is None, assertMsg
+
+ logger.info("Check recursive resolution of eBGP next hops is not affected")
+ # eBGP next hop resolution rejects recursively resolved next hops by
+ # default, even with peer-type multipath-relax
+ exabgp_cmd(
+ "peer4", "announce route {} next-hop {}\n".format(prefix3, ebgp_resolved_nh)
+ )
+ reffile = os.path.join(CWD, "r1/prefix3-no-recursive.json")
+ expected = json.loads(open(reffile).read())
+ test_func = functools.partial(
+ topotest.router_json_cmp,
+ router,
+ "show ip bgp {} json".format(prefix3),
+ expected,
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=10, wait=1)
+ assertMsg = "Recursive eBGP next hop not as expected for {}".format(prefix3)
+ assert res is None, assertMsg
+
+ exabgp_cmd(
+ "peer4", "announce route {} next-hop {}\n".format(prefix1, ebgp_resolved_nh)
+ )
+ reffile = os.path.join(CWD, "r1/prefix1-no-recursive.json")
+ expected = json.loads(open(reffile).read())
+ test_func = functools.partial(
+ topotest.router_json_cmp,
+ router,
+ "show ip bgp {} json".format(prefix1),
+ expected,
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=10, wait=1)
+ assertMsg = "Recursive eBGP next hop not as expected for {}".format(prefix1)
+ assert res is None, assertMsg
+
+ # When other config allows recursively resolved eBGP next hops,
+ # such next hops in all-eBGP multipaths should be valid
+ router.vtysh_cmd("conf\n router bgp 64510\n neighbor 10.0.4.2 ebgp-multihop\n")
+ reffile = os.path.join(CWD, "r1/prefix3-recursive.json")
+ expected = json.loads(open(reffile).read())
+ test_func = functools.partial(
+ topotest.router_json_cmp,
+ router,
+ "show ip bgp {} json".format(prefix3),
+ expected,
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=10, wait=1)
+ assertMsg = "Recursive eBGP next hop not as expected for {}".format(prefix3)
+ assert res is None, assertMsg
+
+ reffile = os.path.join(CWD, "r1/prefix1-recursive.json")
+ expected = json.loads(open(reffile).read())
+ test_func = functools.partial(
+ topotest.router_json_cmp,
+ router,
+ "show ip bgp {} json".format(prefix1),
+ expected,
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=10, wait=1)
+ assertMsg = "Recursive eBGP next hop not as expected for {}".format(prefix1)
+ assert res is None, assertMsg
+
+ logger.info("Check mixed-type multipath next hop recursive resolution in FIB")
+ # There are now two eBGP-learned routes with a recursively resolved next;
+ # hop; one is all-eBGP multipath, and the other is iBGP/eBGP/
+ # confed-external. The peer-type multipath-relax feature only enables
+ # recursive resolution in FIB if any next hop is iBGP/confed-learned. The
+ # all-eBGP multipath will have only one valid next hop in the FIB.
+ reffile = os.path.join(CWD, "r1/prefix3-ip-route.json")
+ expected = json.loads(open(reffile).read())
+ test_func = functools.partial(
+ topotest.router_json_cmp,
+ router,
+ "show ip route {} json".format(prefix3),
+ expected,
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=10, wait=1)
+ assertMsg = "FIB next hops mismatch for all-eBGP multipath"
+ assert res is None, assertMsg
+
+ # check confed-external enables recursively resolved next hops by itself
+ exabgp_cmd(
+ "peer1",
+ "withdraw route {} next-hop {} as-path [ 64499 ]\n".format(
+ prefix1, resolved_nh1
+ ),
+ )
+ reffile = os.path.join(CWD, "r1/prefix1-eBGP-confed.json")
+ expected = json.loads(open(reffile).read())
+ test_func = functools.partial(
+ topotest.router_json_cmp,
+ router,
+ "show ip route {} json".format(prefix1),
+ expected,
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=10, wait=1)
+ assertMsg = "FIB next hops mismatch for eBGP+confed-external multipath"
+ assert res is None, assertMsg
+
+ # check iBGP by itself
+ exabgp_cmd(
+ "peer1",
+ "announce route {} next-hop {} as-path [ 64499 ]\n".format(
+ prefix1, resolved_nh1
+ ),
+ )
+ exabgp_cmd(
+ "peer2",
+ "withdraw route {} next-hop {} as-path [ 64499 ]\n".format(
+ prefix1, resolved_nh2
+ ),
+ )
+ reffile = os.path.join(CWD, "r1/prefix1-eBGP-iBGP.json")
+ expected = json.loads(open(reffile).read())
+ test_func = functools.partial(
+ topotest.router_json_cmp,
+ router,
+ "show ip route {} json".format(prefix1),
+ expected,
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=10, wait=1)
+ assertMsg = "FIB next hops mismatch for eBGP+iBGP multipath"
+ assert res is None, assertMsg
+
+
+def test_memory_leak():
+ "Run the memory leak test and report results."
+ tgen = get_topogen()
+ if not tgen.is_memleak_enabled():
+ pytest.skip("Memory leak test/report is disabled")
+
+ tgen.report_memory_leaks()
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_recursive_route_ebgp_multi_hop/test_bgp_recursive_route_ebgp_multi_hop.py b/tests/topotests/bgp_recursive_route_ebgp_multi_hop/test_bgp_recursive_route_ebgp_multi_hop.py
index 4764ff8945..2a98cb341d 100644
--- a/tests/topotests/bgp_recursive_route_ebgp_multi_hop/test_bgp_recursive_route_ebgp_multi_hop.py
+++ b/tests/topotests/bgp_recursive_route_ebgp_multi_hop/test_bgp_recursive_route_ebgp_multi_hop.py
@@ -86,6 +86,10 @@ from lib.bgp import (
)
from lib.topojson import build_topo_from_json, build_config_from_json
+
+pytestmark = [pytest.mark.bgpd, pytest.mark.staticd]
+
+
# Reading the data from JSON File for topology and configuration creation
jsonFile = "{}/bgp_recursive_route_ebgp_multi_hop.json".format(CWD)
try:
@@ -365,10 +369,11 @@ def test_recursive_routes_iBGP_peer_p1(request):
protocol="bgp",
expected=False,
)
- assert result is not True, ("Testcase {} : Failed \n "
- "Routes are still present \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "Routes are still present \n Error: {}".format(
tc_name, result
- ))
+ )
step("Reconfigure the same static route on R2 again")
dut = "r2"
@@ -486,10 +491,11 @@ def test_recursive_routes_iBGP_peer_p1(request):
result = verify_rib(
tgen, addr_type, "r2", input_dict_4, protocol="bgp", expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "Routes are still present \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "Routes are still present \n Error: {}".format(
tc_name, result
- ))
+ )
write_test_footer(tc_name)
@@ -598,10 +604,11 @@ def test_next_hop_as_self_ip_p1(request):
next_hop=topo["routers"]["r2"]["links"]["r4"][addr_type].split("/")[0],
expected=False,
)
- assert result is not True, ("Testcase {} : Failed \n "
- "Routes are still present \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "Routes are still present \n Error: {}".format(
tc_name, result
- ))
+ )
step("Shut interface on R2 that has IP from the subnet as BGP next-hop")
intf_r2_r4 = topo["routers"]["r2"]["links"]["r4"]["interface"]
@@ -676,10 +683,11 @@ def test_next_hop_as_self_ip_p1(request):
next_hop=topo["routers"]["r2"]["links"]["r4"][addr_type].split("/")[0],
expected=False,
)
- assert result is not True, ("Testcase {} : Failed \n "
- "Routes are still present \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "Routes are still present \n Error: {}".format(
tc_name, result
- ))
+ )
write_test_footer(tc_name)
@@ -1622,10 +1630,11 @@ def test_BGP_peering_bw_loopback_and_physical_p1(request):
step("Verify that once eBGP multi-hop is removed, BGP session goes down")
result = verify_bgp_convergence_from_running_config(tgen, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "BGP is converged \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "BGP is converged \n Error: {}".format(
tc_name, result
- ))
+ )
step("Add ebgp-multihop command on R3 again")
for addr_type in ADDR_TYPES:
@@ -1663,10 +1672,11 @@ def test_BGP_peering_bw_loopback_and_physical_p1(request):
step("Verify that BGP session goes down, when update-source is removed")
result = verify_bgp_convergence_from_running_config(tgen, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "BGP is converged \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "BGP is converged \n Error: {}".format(
tc_name, result
- ))
+ )
step("Add update-source command on R1 again")
for addr_type in ADDR_TYPES:
@@ -1715,18 +1725,20 @@ def test_BGP_peering_bw_loopback_and_physical_p1(request):
next_hop=topo["routers"]["r1"]["links"]["r3"][addr_type].split("/")[0],
expected=False,
)
- assert result is not True, ("Testcase {} : Failed \n "
- "Routes are still present \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "Routes are still present \n Error: {}".format(
tc_name, result
- ))
+ )
sleep(3)
step("Verify that BGP session goes down, when static route is removed")
result = verify_bgp_convergence_from_running_config(tgen, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "BGP is converged \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "BGP is converged \n Error: {}".format(
tc_name, result
- ))
+ )
step("Add static route on R3 again")
for addr_type in ADDR_TYPES:
@@ -1768,10 +1780,11 @@ def test_BGP_peering_bw_loopback_and_physical_p1(request):
sleep(3)
step("Verify that BGP neighborship between R1 and R3 goes down")
result = verify_bgp_convergence_from_running_config(tgen, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "BGP is converged \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "BGP is converged \n Error: {}".format(
tc_name, result
- ))
+ )
intf_r1_r3 = topo["routers"]["r1"]["links"]["r3"]["interface"]
shutdown_bringup_interface(tgen, "r1", intf_r1_r3, True)
@@ -2087,10 +2100,11 @@ def test_BGP_active_standby_preemption_and_ecmp_p1(request):
],
expected=False,
)
- assert result is not True, ("Testcase {} : Failed \n "
- "Routes are still present \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "Routes are still present \n Error: {}".format(
tc_name, result
- ))
+ )
step("Reconfigure multipath-relax command on R4")
result = create_router_bgp(tgen, topo, maxpath_relax)
@@ -2147,10 +2161,11 @@ def test_BGP_active_standby_preemption_and_ecmp_p1(request):
],
expected=False,
)
- assert result is not True, ("Testcase {} : Failed \n "
- "Routes are still present \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "Routes are still present \n Error: {}".format(
tc_name, result
- ))
+ )
step("Re-configure maximum-path 2 command on R4")
input_dict_8 = {
@@ -2338,10 +2353,11 @@ def test_password_authentication_for_eBGP_and_iBGP_peers_p1(request):
"configured but not peer routers"
)
result = verify_bgp_convergence(tgen, topo, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "BGP is converged \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "BGP is converged \n Error: {}".format(
tc_name, result
- ))
+ )
step("configure same password on R2 and R3")
for routerN in ["r2", "r3"]:
@@ -2368,10 +2384,11 @@ def test_password_authentication_for_eBGP_and_iBGP_peers_p1(request):
"strings are in CAPs on R2 and R3"
)
result = verify_bgp_convergence(tgen, topo, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "BGP is converged \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "BGP is converged \n Error: {}".format(
tc_name, result
- ))
+ )
step("Configure same password on R2 and R3 without CAPs")
for routerN in ["r2", "r3"]:
@@ -2395,10 +2412,11 @@ def test_password_authentication_for_eBGP_and_iBGP_peers_p1(request):
step("Verify if password is removed from R1, both sessions go down again")
result = verify_bgp_convergence(tgen, topo, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "BGP is converged \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "BGP is converged \n Error: {}".format(
tc_name, result
- ))
+ )
step("Configure alphanumeric password on R1 and peer routers R2,R3")
for bgp_neighbor in ["r2", "r3"]:
diff --git a/tests/topotests/bgp_sender-as-path-loop-detection/test_bgp_sender-as-path-loop-detection.py b/tests/topotests/bgp_sender-as-path-loop-detection/test_bgp_sender-as-path-loop-detection.py
index 88935ae4d1..dffe24f3a0 100644
--- a/tests/topotests/bgp_sender-as-path-loop-detection/test_bgp_sender-as-path-loop-detection.py
+++ b/tests/topotests/bgp_sender-as-path-loop-detection/test_bgp_sender-as-path-loop-detection.py
@@ -44,6 +44,9 @@ from lib.topolog import logger
from mininet.topo import Topo
+pytestmark = [pytest.mark.bgpd]
+
+
class TemplateTopo(Topo):
def build(self, *_args, **_opts):
tgen = get_topogen(self)
diff --git a/tests/topotests/bgp_vrf_dynamic_route_leak/test_bgp_vrf_dynamic_route_leak_topo1.py b/tests/topotests/bgp_vrf_dynamic_route_leak/test_bgp_vrf_dynamic_route_leak_topo1.py
index b99f1a7418..291a6e7c3a 100644
--- a/tests/topotests/bgp_vrf_dynamic_route_leak/test_bgp_vrf_dynamic_route_leak_topo1.py
+++ b/tests/topotests/bgp_vrf_dynamic_route_leak/test_bgp_vrf_dynamic_route_leak_topo1.py
@@ -498,6 +498,7 @@ def disable_route_map_to_prefer_global_next_hop(tgen, topo):
#
#####################################################
+
def test_dynamic_imported_routes_advertised_to_iBGP_peer_p0(request):
"""
TC5_FUNC_5:
@@ -762,9 +763,7 @@ def test_dynamic_imported_routes_advertised_to_iBGP_peer_p0(request):
for addr_type in ADDR_TYPES:
- step(
- "On router R1 delete static routes in vrf ISR to LOOPBACK_1"
- )
+ step("On router R1 delete static routes in vrf ISR to LOOPBACK_1")
input_routes_r1 = {
"r1": {
@@ -772,7 +771,7 @@ def test_dynamic_imported_routes_advertised_to_iBGP_peer_p0(request):
{
"network": [NETWORK1_3[addr_type], NETWORK1_4[addr_type]],
"next_hop": (intf_r2_r1[addr_type]).split("/")[0],
- "delete": True
+ "delete": True,
}
]
}
diff --git a/tests/topotests/bgp_vrf_lite_ipv6_rtadv/test_bgp_vrf_lite_ipv6_rtadv.py b/tests/topotests/bgp_vrf_lite_ipv6_rtadv/test_bgp_vrf_lite_ipv6_rtadv.py
index 97d98415db..92ee8513e1 100644
--- a/tests/topotests/bgp_vrf_lite_ipv6_rtadv/test_bgp_vrf_lite_ipv6_rtadv.py
+++ b/tests/topotests/bgp_vrf_lite_ipv6_rtadv/test_bgp_vrf_lite_ipv6_rtadv.py
@@ -42,6 +42,7 @@ sys.path.append(os.path.join(CWD, "../"))
from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.topolog import logger
+from lib.common_config import adjust_router_l3mdev
# Required to instantiate the topology builder class.
from mininet.topo import Topo
@@ -71,22 +72,6 @@ def setup_module(mod):
router_list = tgen.routers()
logger.info("Testing with VRF Lite support")
- krel = platform.release()
-
- # May need to adjust handling of vrf traffic depending on kernel version
- l3mdev_accept = 0
- if (
- topotest.version_cmp(krel, "4.15") >= 0
- and topotest.version_cmp(krel, "4.18") <= 0
- ):
- l3mdev_accept = 1
-
- if topotest.version_cmp(krel, "5.0") >= 0:
- l3mdev_accept = 1
-
- logger.info(
- "krel '{0}' setting net.ipv4.tcp_l3mdev_accept={1}".format(krel, l3mdev_accept)
- )
cmds = [
"ip link add {0}-cust1 type vrf table 1001",
@@ -99,15 +84,8 @@ def setup_module(mod):
for cmd in cmds:
output = tgen.net[rname].cmd(cmd.format(rname))
- output = tgen.net[rname].cmd("sysctl -n net.ipv4.tcp_l3mdev_accept")
- logger.info(
- "router {0}: existing tcp_l3mdev_accept was {1}".format(rname, output)
- )
-
- if l3mdev_accept:
- output = tgen.net[rname].cmd(
- "sysctl -w net.ipv4.tcp_l3mdev_accept={}".format(l3mdev_accept)
- )
+ # adjust handling of vrf traffic
+ adjust_router_l3mdev(tgen, rname)
for rname, router in router_list.items():
router.load_config(
diff --git a/tests/topotests/conftest.py b/tests/topotests/conftest.py
index 04e9961f10..cf64956bfd 100755
--- a/tests/topotests/conftest.py
+++ b/tests/topotests/conftest.py
@@ -2,12 +2,14 @@
Topotest conftest.py file.
"""
+import os
+import pdb
+import pytest
+
from lib.topogen import get_topogen, diagnose_env
from lib.topotest import json_cmp_result
+from lib.topotest import g_extra_config as topotest_extra_config
from lib.topolog import logger
-import pytest
-
-topology_only = False
def pytest_addoption(parser):
@@ -16,20 +18,72 @@ def pytest_addoption(parser):
only run the setup_module() to setup the topology without running any tests.
"""
parser.addoption(
+ "--gdb-breakpoints",
+ metavar="SYMBOL[,SYMBOL...]",
+ help="Comma-separated list of functions to set gdb breakpoints on",
+ )
+
+ parser.addoption(
+ "--gdb-daemons",
+ metavar="DAEMON[,DAEMON...]",
+ help="Comma-separated list of daemons to spawn gdb on, or 'all'",
+ )
+
+ parser.addoption(
+ "--gdb-routers",
+ metavar="ROUTER[,ROUTER...]",
+ help="Comma-separated list of routers to spawn gdb on, or 'all'",
+ )
+
+ parser.addoption(
+ "--mininet-on-error",
+ action="store_true",
+ help="Mininet cli on test failure",
+ )
+
+ parser.addoption(
+ "--pause-after",
+ action="store_true",
+ help="Pause after each test",
+ )
+
+ parser.addoption(
+ "--shell",
+ metavar="ROUTER[,ROUTER...]",
+ help="Comma-separated list of routers to spawn shell on, or 'all'",
+ )
+
+ parser.addoption(
+ "--shell-on-error",
+ action="store_true",
+ help="Spawn shell on all routers on test failure",
+ )
+
+ parser.addoption(
"--topology-only",
action="store_true",
help="Only set up this topology, don't run tests",
)
+ parser.addoption(
+ "--vtysh",
+ metavar="ROUTER[,ROUTER...]",
+ help="Comma-separated list of routers to spawn vtysh on, or 'all'",
+ )
+
+ parser.addoption(
+ "--vtysh-on-error",
+ action="store_true",
+ help="Spawn vtysh on all routers on test failure",
+ )
+
def pytest_runtest_call():
"""
This function must be run after setup_module(), it does standarized post
setup routines. It is only being used for the 'topology-only' option.
"""
- global topology_only
-
- if topology_only:
+ if topotest_extra_config["topology_only"]:
tgen = get_topogen()
if tgen is not None:
# Allow user to play with the setup.
@@ -42,6 +96,8 @@ def pytest_assertrepr_compare(op, left, right):
"""
Show proper assertion error message for json_cmp results.
"""
+ del op
+
json_result = left
if not isinstance(json_result, json_cmp_result):
json_result = right
@@ -52,43 +108,104 @@ def pytest_assertrepr_compare(op, left, right):
def pytest_configure(config):
- "Assert that the environment is correctly configured."
-
- global topology_only
+ """
+ Assert that the environment is correctly configured, and get extra config.
+ """
if not diagnose_env():
- pytest.exit("enviroment has errors, please read the logs")
+ pytest.exit("environment has errors, please read the logs")
+
+ gdb_routers = config.getoption("--gdb-routers")
+ gdb_routers = gdb_routers.split(",") if gdb_routers else []
+ topotest_extra_config["gdb_routers"] = gdb_routers
+
+ gdb_daemons = config.getoption("--gdb-daemons")
+ gdb_daemons = gdb_daemons.split(",") if gdb_daemons else []
+ topotest_extra_config["gdb_daemons"] = gdb_daemons
+
+ gdb_breakpoints = config.getoption("--gdb-breakpoints")
+ gdb_breakpoints = gdb_breakpoints.split(",") if gdb_breakpoints else []
+ topotest_extra_config["gdb_breakpoints"] = gdb_breakpoints
- if config.getoption("--topology-only"):
- topology_only = True
+ mincli_on_error = config.getoption("--mininet-on-error")
+ topotest_extra_config["mininet_on_error"] = mincli_on_error
+
+ shell = config.getoption("--shell")
+ topotest_extra_config["shell"] = shell.split(",") if shell else []
+
+ pause_after = config.getoption("--pause-after")
+
+ shell_on_error = config.getoption("--shell-on-error")
+ topotest_extra_config["shell_on_error"] = shell_on_error
+
+ vtysh = config.getoption("--vtysh")
+ topotest_extra_config["vtysh"] = vtysh.split(",") if vtysh else []
+
+ vtysh_on_error = config.getoption("--vtysh-on-error")
+ topotest_extra_config["vtysh_on_error"] = vtysh_on_error
+
+ topotest_extra_config["pause_after"] = pause_after or shell or vtysh
+
+ topotest_extra_config["topology_only"] = config.getoption("--topology-only")
def pytest_runtest_makereport(item, call):
"Log all assert messages to default logger with error level"
- # Nothing happened
- if call.excinfo is None:
- return
- parent = item.parent
- modname = parent.module.__name__
+ # Nothing happened
+ if call.when == "call":
+ pause = topotest_extra_config["pause_after"]
+ else:
+ pause = False
- # Treat skips as non errors
- if call.excinfo.typename != "AssertionError":
- logger.info(
- 'assert skipped at "{}/{}": {}'.format(
- modname, item.name, call.excinfo.value
+ if call.excinfo is None:
+ error = False
+ else:
+ parent = item.parent
+ modname = parent.module.__name__
+
+ # Treat skips as non errors, don't pause after
+ if call.excinfo.typename != "AssertionError":
+ pause = False
+ error = False
+ logger.info(
+ 'assert skipped at "{}/{}": {}'.format(
+ modname, item.name, call.excinfo.value
+ )
+ )
+ else:
+ error = True
+ # Handle assert failures
+ parent._previousfailed = item # pylint: disable=W0212
+ logger.error(
+ 'assert failed at "{}/{}": {}'.format(
+ modname, item.name, call.excinfo.value
+ )
)
- )
- return
-
- # Handle assert failures
- parent._previousfailed = item
- logger.error(
- 'assert failed at "{}/{}": {}'.format(modname, item.name, call.excinfo.value)
- )
- # (topogen) Set topology error to avoid advancing in the test.
- tgen = get_topogen()
- if tgen is not None:
- # This will cause topogen to report error on `routers_have_failure`.
- tgen.set_error("{}/{}".format(modname, item.name))
+ # (topogen) Set topology error to avoid advancing in the test.
+ tgen = get_topogen()
+ if tgen is not None:
+ # This will cause topogen to report error on `routers_have_failure`.
+ tgen.set_error("{}/{}".format(modname, item.name))
+
+ if error and topotest_extra_config["shell_on_error"]:
+ for router in tgen.routers():
+ pause = True
+ tgen.net[router].runInWindow(os.getenv("SHELL", "bash"))
+
+ if error and topotest_extra_config["vtysh_on_error"]:
+ for router in tgen.routers():
+ pause = True
+ tgen.net[router].runInWindow("vtysh")
+
+ if error and topotest_extra_config["mininet_on_error"]:
+ tgen.mininet_cli()
+
+ if pause:
+ try:
+ user = raw_input('Testing paused, "pdb" to debug, "Enter" to continue: ')
+ except NameError:
+ user = input('Testing paused, "pdb" to debug, "Enter" to continue: ')
+ if user.strip() == "pdb":
+ pdb.set_trace()
diff --git a/tests/topotests/isis-snmp/test_isis_snmp.py b/tests/topotests/isis-snmp/test_isis_snmp.py
index 1bcd0eefc6..07f3335e23 100755
--- a/tests/topotests/isis-snmp/test_isis_snmp.py
+++ b/tests/topotests/isis-snmp/test_isis_snmp.py
@@ -124,7 +124,6 @@ class TemplateTopo(Topo):
switch.add_link(tgen.gears["r3"])
-
def setup_module(mod):
"Sets up the pytest environment"
@@ -148,20 +147,24 @@ def setup_module(mod):
# Don't start the following in the CE nodes
if router.name[0] == "r":
router.load_config(
- TopoRouter.RD_ISIS, os.path.join(CWD, "{}/isisd.conf".format(rname)),
+ TopoRouter.RD_ISIS,
+ os.path.join(CWD, "{}/isisd.conf".format(rname)),
"-M snmp",
)
router.load_config(
- TopoRouter.RD_LDP, os.path.join(CWD, "{}/ldpd.conf".format(rname)),
+ TopoRouter.RD_LDP,
+ os.path.join(CWD, "{}/ldpd.conf".format(rname)),
)
router.load_config(
- TopoRouter.RD_SNMP, os.path.join(CWD, "{}/snmpd.conf".format(rname)),
+ TopoRouter.RD_SNMP,
+ os.path.join(CWD, "{}/snmpd.conf".format(rname)),
"-Le -Ivacm_conf,usmConf,iquery -V -DAgentX,trap",
)
# After loading the configurations, this function loads configured daemons.
tgen.start_router()
+
def teardown_module(mod):
"Teardown the pytest environment"
tgen = get_topogen()
@@ -169,6 +172,7 @@ def teardown_module(mod):
# This function tears down the whole topology.
tgen.stop_topology()
+
def router_compare_json_output(rname, command, reference):
"Compare router JSON output"
@@ -184,6 +188,7 @@ def router_compare_json_output(rname, command, reference):
assertmsg = '"{}" JSON output mismatches the expected result'.format(rname)
assert diff is None, assertmsg
+
def generate_oid(numoids, index1, index2):
if numoids == 1:
oid = "{}".format(index1)
@@ -200,7 +205,9 @@ def test_isis_convergence():
router_compare_json_output(
rname,
"show yang operational-data /frr-interface:lib isisd",
- "show_yang_interface_isis_adjacencies.ref")
+ "show_yang_interface_isis_adjacencies.ref",
+ )
+
def test_r1_scalar_snmp():
"Wait for protocol convergence"
@@ -213,26 +220,26 @@ def test_r1_scalar_snmp():
r1 = tgen.net.get("r1")
r1_snmp = SnmpTester(r1, "1.1.1.1", "public", "2c")
- assert r1_snmp.test_oid('isisSysVersion', "one(1)")
- assert r1_snmp.test_oid('isisSysLevelType', "level1and2(3)")
- assert r1_snmp.test_oid('isisSysID',"00 00 00 00 00 01")
- assert r1_snmp.test_oid('isisSysMaxPathSplits',"32")
- assert r1_snmp.test_oid('isisSysMaxLSPGenInt',"900 seconds")
- assert r1_snmp.test_oid('isisSysAdminState',"on(1)")
- assert r1_snmp.test_oid('isisSysMaxAge',"1200 seconds")
- assert r1_snmp.test_oid('isisSysProtSupported',"07 5 6 7")
+ assert r1_snmp.test_oid("isisSysVersion", "one(1)")
+ assert r1_snmp.test_oid("isisSysLevelType", "level1and2(3)")
+ assert r1_snmp.test_oid("isisSysID", "00 00 00 00 00 01")
+ assert r1_snmp.test_oid("isisSysMaxPathSplits", "32")
+ assert r1_snmp.test_oid("isisSysMaxLSPGenInt", "900 seconds")
+ assert r1_snmp.test_oid("isisSysAdminState", "on(1)")
+ assert r1_snmp.test_oid("isisSysMaxAge", "1200 seconds")
+ assert r1_snmp.test_oid("isisSysProtSupported", "07 5 6 7")
r2 = tgen.net.get("r2")
r2_snmp = SnmpTester(r2, "2.2.2.2", "public", "2c")
-
- assert r2_snmp.test_oid('isisSysVersion', "one(1)")
- assert r2_snmp.test_oid('isisSysLevelType', "level1and2(3)")
- assert r2_snmp.test_oid('isisSysID',"00 00 00 00 00 02")
- assert r2_snmp.test_oid('isisSysMaxPathSplits',"32")
- assert r2_snmp.test_oid('isisSysMaxLSPGenInt',"900 seconds")
- assert r2_snmp.test_oid('isisSysAdminState',"on(1)")
- assert r2_snmp.test_oid('isisSysMaxAge',"1200 seconds")
- assert r2_snmp.test_oid('isisSysProtSupported',"07 5 6 7")
+
+ assert r2_snmp.test_oid("isisSysVersion", "one(1)")
+ assert r2_snmp.test_oid("isisSysLevelType", "level1and2(3)")
+ assert r2_snmp.test_oid("isisSysID", "00 00 00 00 00 02")
+ assert r2_snmp.test_oid("isisSysMaxPathSplits", "32")
+ assert r2_snmp.test_oid("isisSysMaxLSPGenInt", "900 seconds")
+ assert r2_snmp.test_oid("isisSysAdminState", "on(1)")
+ assert r2_snmp.test_oid("isisSysMaxAge", "1200 seconds")
+ assert r2_snmp.test_oid("isisSysProtSupported", "07 5 6 7")
circtable_test = {
@@ -245,7 +252,8 @@ circtable_test = {
"isisCircMeshGroupEnabled": ["inactive(1)", "inactive(1)", "inactive(1)"],
"isisCircSmallHellos": ["false(2)", "false(2)", "false(2)"],
"isisCirc3WayEnabled": ["false(2)", "false(2)", "false(2)"],
- }
+}
+
def test_r1_isisCircTable():
tgen = get_topogen()
@@ -256,9 +264,9 @@ def test_r1_isisCircTable():
r1_snmp = SnmpTester(r1, "1.1.1.1", "public", "2c")
oids = []
- oids.append(generate_oid(1,1,0))
- oids.append(generate_oid(1,2,0))
- oids.append(generate_oid(1,3,0))
+ oids.append(generate_oid(1, 1, 0))
+ oids.append(generate_oid(1, 2, 0))
+ oids.append(generate_oid(1, 3, 0))
# check items
for item in circtable_test.keys():
@@ -267,14 +275,26 @@ def test_r1_isisCircTable():
)
assert r1_snmp.test_oid_walk(item, circtable_test[item], oids), assertmsg
+
circleveltable_test = {
"isisCircLevelMetric": ["10", "10", "10", "10"],
"isisCircLevelWideMetric": ["10", "10", "0", "0"],
"isisCircLevelISPriority": ["64", "64", "64", "64"],
"isisCircLevelHelloMultiplier": ["10", "10", "10", "10"],
- "isisCircLevelHelloTimer": ["3000 milliseconds", "3000 milliseconds", "3000 milliseconds", "3000 milliseconds"],
- "isisCircLevelMinLSPRetransInt": ["1 seconds", "1 seconds", "0 seconds", "0 seconds"],
- }
+ "isisCircLevelHelloTimer": [
+ "3000 milliseconds",
+ "3000 milliseconds",
+ "3000 milliseconds",
+ "3000 milliseconds",
+ ],
+ "isisCircLevelMinLSPRetransInt": [
+ "1 seconds",
+ "1 seconds",
+ "0 seconds",
+ "0 seconds",
+ ],
+}
+
def test_r1_isislevelCircTable():
tgen = get_topogen()
@@ -285,10 +305,10 @@ def test_r1_isislevelCircTable():
r1_snmp = SnmpTester(r1, "1.1.1.1", "public", "2c")
oids = []
- oids.append(generate_oid(2,1,"area"))
- oids.append(generate_oid(2,2,"area"))
- oids.append(generate_oid(2,3,"area"))
- oids.append(generate_oid(2,3,"domain"))
+ oids.append(generate_oid(2, 1, "area"))
+ oids.append(generate_oid(2, 2, "area"))
+ oids.append(generate_oid(2, 3, "area"))
+ oids.append(generate_oid(2, 3, "domain"))
# check items
for item in circleveltable_test.keys():
@@ -316,6 +336,7 @@ adjtable_down_test = {
"isisISAdjNeighPriority": ["64"],
}
+
def test_r1_isisAdjTable():
"check ISIS Adjacency Table"
tgen = get_topogen()
@@ -324,11 +345,11 @@ def test_r1_isisAdjTable():
r1_snmp = SnmpTester(r1, "1.1.1.1", "public", "2c")
oids = []
- oids.append(generate_oid(2,1,1))
- oids.append(generate_oid(2,2,1))
+ oids.append(generate_oid(2, 1, 1))
+ oids.append(generate_oid(2, 2, 1))
oids_down = []
- oids_down.append(generate_oid(2,1,1))
+ oids_down.append(generate_oid(2, 1, 1))
# check items
for item in adjtable_test.keys():
@@ -337,7 +358,6 @@ def test_r1_isisAdjTable():
)
assert r1_snmp.test_oid_walk(item, adjtable_test[item], oids), assertmsg
-
# shutdown interface and one adjacency should be removed
"check ISIS adjacency is removed when interface is shutdown"
r1_cmd.vtysh_cmd("conf t\ninterface r1-eth1\nshutdown")
@@ -347,7 +367,9 @@ def test_r1_isisAdjTable():
assertmsg = "{} should be {} oids {} full dict {}:".format(
item, adjtable_down_test[item], oids_down, r1_snmp.walk(item)
)
- assert r1_snmp.test_oid_walk(item, adjtable_down_test[item], oids_down), assertmsg
+ assert r1_snmp.test_oid_walk(
+ item, adjtable_down_test[item], oids_down
+ ), assertmsg
# no shutdown interface and adjacency should be restored
r1_cmd.vtysh_cmd("conf t\ninterface r1-eth1\nno shutdown")
diff --git a/tests/topotests/isis-topo1-vrf/r1/r1_topology.json b/tests/topotests/isis-topo1-vrf/r1/r1_topology.json
index 8e3cdc7bd6..1a6fe6d5c6 100644
--- a/tests/topotests/isis-topo1-vrf/r1/r1_topology.json
+++ b/tests/topotests/isis-topo1-vrf/r1/r1_topology.json
@@ -5,73 +5,73 @@
{
"vertex": "r1"
}
- ],
+ ],
"ipv6": [
{
"vertex": "r1"
}
]
- },
+ },
"level-2": {
"ipv4": [
{
"vertex": "r1"
- },
+ },
{
- "metric": "internal",
- "parent": "0",
- "type": "IP",
+ "metric": "0",
+ "parent": "r1(4)",
+ "type": "IP internal",
"vertex": "10.0.20.0/24"
- },
+ },
{
- "interface": "r1-eth0",
- "metric": "10",
- "next-hop": "r3",
- "parent": "r1(4)",
- "type": "TE-IS",
+ "interface": "r1-eth0",
+ "metric": "10",
+ "next-hop": "r3",
+ "parent": "r1(4)",
+ "type": "TE-IS",
"vertex": "r3"
- },
+ },
{
- "interface": "r3",
- "metric": "TE",
- "next-hop": "20",
- "parent": "r1-eth0",
- "type": "IP",
+ "interface": "r1-eth0",
+ "metric": "20",
+ "next-hop": "r3",
+ "parent": "r3(4)",
+ "type": "IP TE",
"vertex": "10.0.20.0/24"
- },
+ },
{
- "interface": "r3",
- "metric": "TE",
- "next-hop": "20",
- "parent": "r1-eth0",
- "type": "IP",
+ "interface": "r1-eth0",
+ "metric": "20",
+ "next-hop": "r3",
+ "parent": "r3(4)",
+ "type": "IP TE",
"vertex": "10.0.10.0/24"
}
- ],
+ ],
"ipv6": [
{
"vertex": "r1"
- },
+ },
{
- "metric": "internal",
- "parent": "0",
- "type": "IP6",
+ "metric": "0",
+ "parent": "r1(4)",
+ "type": "IP6 internal",
"vertex": "2001:db8:1:1::/64"
- },
+ },
{
- "interface": "r1-eth0",
- "metric": "10",
- "next-hop": "r3",
- "parent": "r1(4)",
- "type": "TE-IS",
+ "interface": "r1-eth0",
+ "metric": "10",
+ "next-hop": "r3",
+ "parent": "r1(4)",
+ "type": "TE-IS",
"vertex": "r3"
- },
+ },
{
- "interface": "r3",
- "metric": "internal",
- "next-hop": "20",
- "parent": "r1-eth0",
- "type": "IP6",
+ "interface": "r1-eth0",
+ "metric": "20",
+ "next-hop": "r3",
+ "parent": "r3(4)",
+ "type": "IP6 internal",
"vertex": "2001:db8:2:1::/64"
}
]
diff --git a/tests/topotests/isis-topo1-vrf/r2/r2_topology.json b/tests/topotests/isis-topo1-vrf/r2/r2_topology.json
index 72022a8167..a77f7977f9 100644
--- a/tests/topotests/isis-topo1-vrf/r2/r2_topology.json
+++ b/tests/topotests/isis-topo1-vrf/r2/r2_topology.json
@@ -5,76 +5,76 @@
{
"vertex": "r2"
}
- ],
+ ],
"ipv6": [
{
"vertex": "r2"
}
]
- },
+ },
"level-2": {
"ipv4": [
{
"vertex": "r2"
- },
+ },
{
- "metric": "internal",
- "parent": "0",
- "type": "IP",
+ "metric": "0",
+ "parent": "r2(4)",
+ "type": "IP internal",
"vertex": "10.0.21.0/24"
- },
+ },
{
- "interface": "r2-eth0",
- "metric": "10",
- "next-hop": "r4",
- "parent": "r2(4)",
- "type": "TE-IS",
+ "interface": "r2-eth0",
+ "metric": "10",
+ "next-hop": "r4",
+ "parent": "r2(4)",
+ "type": "TE-IS",
"vertex": "r4"
- },
+ },
{
- "interface": "r4",
- "metric": "TE",
- "next-hop": "20",
- "parent": "r2-eth0",
- "type": "IP",
+ "interface": "r2-eth0",
+ "metric": "20",
+ "next-hop": "r4",
+ "parent": "r4(4)",
+ "type": "IP TE",
"vertex": "10.0.21.0/24"
- },
+ },
{
- "interface": "r4",
- "metric": "TE",
- "next-hop": "20",
- "parent": "r2-eth0",
- "type": "IP",
+ "interface": "r2-eth0",
+ "metric": "20",
+ "next-hop": "r4",
+ "parent": "r4(4)",
+ "type": "IP TE",
"vertex": "10.0.11.0/24"
}
- ],
+ ],
"ipv6": [
{
"vertex": "r2"
- },
+ },
{
- "metric": "internal",
- "parent": "0",
- "type": "IP6",
+ "metric": "0",
+ "parent": "r2(4)",
+ "type": "IP6 internal",
"vertex": "2001:db8:1:2::/64"
- },
+ },
{
- "interface": "r2-eth0",
- "metric": "10",
- "next-hop": "r4",
- "parent": "r2(4)",
- "type": "TE-IS",
+ "interface": "r2-eth0",
+ "metric": "10",
+ "next-hop": "r4",
+ "parent": "r2(4)",
+ "type": "TE-IS",
"vertex": "r4"
- },
+ },
{
- "interface": "r4",
- "metric": "internal",
- "next-hop": "20",
- "parent": "r2-eth0",
- "type": "IP6",
+ "interface": "r2-eth0",
+ "metric": "20",
+ "next-hop": "r4",
+ "parent": "r4(4)",
+ "type": "IP6 internal",
"vertex": "2001:db8:2:2::/64"
}
]
}
}
-} \ No newline at end of file
+}
diff --git a/tests/topotests/isis-topo1-vrf/r3/r3_topology.json b/tests/topotests/isis-topo1-vrf/r3/r3_topology.json
index 62b895766e..1e5d331965 100644
--- a/tests/topotests/isis-topo1-vrf/r3/r3_topology.json
+++ b/tests/topotests/isis-topo1-vrf/r3/r3_topology.json
@@ -4,126 +4,126 @@
"ipv4": [
{
"vertex": "r3"
- },
+ },
{
- "metric": "internal",
- "parent": "0",
- "type": "IP",
+ "metric": "0",
+ "parent": "r3(4)",
+ "type": "IP internal",
"vertex": "10.0.10.0/24"
- },
+ },
{
- "interface": "r3-eth1",
- "metric": "10",
- "next-hop": "r5",
- "parent": "r3(4)",
- "type": "TE-IS",
+ "interface": "r3-eth1",
+ "metric": "10",
+ "next-hop": "r5",
+ "parent": "r3(4)",
+ "type": "TE-IS",
"vertex": "r5"
- },
+ },
{
- "interface": "r5",
- "metric": "TE",
- "next-hop": "20",
- "parent": "r3-eth1",
- "type": "IP",
+ "interface": "r3-eth1",
+ "metric": "20",
+ "next-hop": "r5",
+ "parent": "r5(4)",
+ "type": "IP TE",
"vertex": "10.0.10.0/24"
- },
+ },
{
- "interface": "r5",
- "metric": "TE",
- "next-hop": "20",
- "parent": "r3-eth1",
- "type": "IP",
+ "interface": "r3-eth1",
+ "metric": "20",
+ "next-hop": "r5",
+ "parent": "r5(4)",
+ "type": "IP TE",
"vertex": "10.0.11.0/24"
- },
+ },
{
- "interface": "r5",
- "metric": "TE",
- "next-hop": "30",
- "parent": "r3-eth1",
- "type": "IP",
+ "interface": "r3-eth1",
+ "metric": "30",
+ "next-hop": "r5",
+ "parent": "r4(4)",
+ "type": "IP TE",
"vertex": "10.0.21.0/24"
}
- ],
+ ],
"ipv6": [
{
"vertex": "r3"
- },
+ },
{
- "metric": "internal",
- "parent": "0",
- "type": "IP6",
+ "metric": "0",
+ "parent": "r3(4)",
+ "type": "IP6 internal",
"vertex": "2001:db8:2:1::/64"
- },
+ },
{
- "interface": "r3-eth1",
- "metric": "10",
- "next-hop": "r5",
- "parent": "r3(4)",
- "type": "TE-IS",
+ "interface": "r3-eth1",
+ "metric": "10",
+ "next-hop": "r5",
+ "parent": "r3(4)",
+ "type": "TE-IS",
"vertex": "r5"
- },
+ },
{
- "interface": "r5",
- "metric": "internal",
- "next-hop": "20",
- "parent": "r3-eth1",
- "type": "IP6",
+ "interface": "r3-eth1",
+ "metric": "20",
+ "next-hop": "r5",
+ "parent": "r5(4)",
+ "type": "IP6 internal",
"vertex": "2001:db8:2:2::/64"
- },
+ },
{
- "interface": "r5",
- "metric": "internal",
- "next-hop": "30",
- "parent": "r3-eth1",
- "type": "IP6",
+ "interface": "r3-eth1",
+ "metric": "30",
+ "next-hop": "r5",
+ "parent": "r4(4)",
+ "type": "IP6 internal",
"vertex": "2001:db8:1:2::/64"
}
]
- },
+ },
"level-2": {
"ipv4": [
{
"vertex": "r3"
- },
+ },
{
- "metric": "internal",
- "parent": "0",
- "type": "IP",
+ "metric": "0",
+ "parent": "r3(4)",
+ "type": "IP internal",
"vertex": "10.0.20.0/24"
- },
+ },
{
- "interface": "r3-eth0",
- "metric": "10",
- "next-hop": "r3",
- "parent": "r3(4)",
- "type": "TE-IS",
+ "interface": "r3-eth0",
+ "metric": "10",
+ "next-hop": "r3",
+ "parent": "r3(4)",
+ "type": "TE-IS",
"vertex": "r3"
- },
+ },
{
- "interface": "r3",
- "metric": "TE",
- "next-hop": "20",
- "parent": "r3-eth0",
- "type": "IP",
+ "interface": "r3-eth0",
+ "metric": "20",
+ "next-hop": "r3",
+ "parent": "r3(4)",
+ "type": "IP TE",
"vertex": "10.0.20.0/24"
}
- ],
+ ],
"ipv6": [
{
"vertex": "r3"
- },
+ },
{
- "metric": "internal",
- "parent": "0",
- "type": "IP6",
+ "metric": "0",
+ "parent": "r3(4)",
+ "type": "IP6 internal",
"vertex": "2001:db8:1:1::/64"
- },
+ },
{
- "interface": "r3-eth0",
- "metric": "10",
- "next-hop": "r3",
- "parent": "r3(4)",
- "type": "TE-IS",
+ "interface": "r3-eth0",
+ "metric": "10",
+ "next-hop": "r3",
+ "parent": "r3(4)",
+ "type": "TE-IS",
"vertex": "r3"
}
]
diff --git a/tests/topotests/isis-topo1-vrf/r4/r4_topology.json b/tests/topotests/isis-topo1-vrf/r4/r4_topology.json
index 0d69550cad..34f5ac9ca4 100644
--- a/tests/topotests/isis-topo1-vrf/r4/r4_topology.json
+++ b/tests/topotests/isis-topo1-vrf/r4/r4_topology.json
@@ -4,126 +4,126 @@
"ipv4": [
{
"vertex": "r4"
- },
+ },
{
- "metric": "internal",
- "parent": "0",
- "type": "IP",
+ "metric": "0",
+ "parent": "r4(4)",
+ "type": "IP internal",
"vertex": "10.0.11.0/24"
- },
+ },
{
- "interface": "r4-eth1",
- "metric": "10",
- "next-hop": "r5",
- "parent": "r4(4)",
- "type": "TE-IS",
+ "interface": "r4-eth1",
+ "metric": "10",
+ "next-hop": "r5",
+ "parent": "r4(4)",
+ "type": "TE-IS",
"vertex": "r5"
- },
+ },
{
- "interface": "r5",
- "metric": "TE",
- "next-hop": "20",
- "parent": "r4-eth1",
- "type": "IP",
+ "interface": "r4-eth1",
+ "metric": "20",
+ "next-hop": "r5",
+ "parent": "r5(4)",
+ "type": "IP TE",
"vertex": "10.0.10.0/24"
- },
+ },
{
- "interface": "r5",
- "metric": "TE",
- "next-hop": "20",
- "parent": "r4-eth1",
- "type": "IP",
+ "interface": "r4-eth1",
+ "metric": "20",
+ "next-hop": "r5",
+ "parent": "r5(4)",
+ "type": "IP TE",
"vertex": "10.0.11.0/24"
- },
+ },
{
- "interface": "r5",
- "metric": "TE",
- "next-hop": "30",
- "parent": "r4-eth1",
- "type": "IP",
+ "interface": "r4-eth1",
+ "metric": "30",
+ "next-hop": "r5",
+ "parent": "r3(4)",
+ "type": "IP TE",
"vertex": "10.0.20.0/24"
}
- ],
+ ],
"ipv6": [
{
"vertex": "r4"
- },
+ },
{
- "metric": "internal",
- "parent": "0",
- "type": "IP6",
+ "metric": "0",
+ "parent": "r4(4)",
+ "type": "IP6 internal",
"vertex": "2001:db8:2:2::/64"
- },
+ },
{
- "interface": "r4-eth1",
- "metric": "10",
- "next-hop": "r5",
- "parent": "r4(4)",
- "type": "TE-IS",
+ "interface": "r4-eth1",
+ "metric": "10",
+ "next-hop": "r5",
+ "parent": "r4(4)",
+ "type": "TE-IS",
"vertex": "r5"
- },
+ },
{
- "interface": "r5",
- "metric": "internal",
- "next-hop": "20",
- "parent": "r4-eth1",
- "type": "IP6",
+ "interface": "r4-eth1",
+ "metric": "20",
+ "next-hop": "r5",
+ "parent": "r5(4)",
+ "type": "IP6 internal",
"vertex": "2001:db8:2:1::/64"
- },
+ },
{
- "interface": "r5",
- "metric": "internal",
- "next-hop": "30",
- "parent": "r4-eth1",
- "type": "IP6",
+ "interface": "r4-eth1",
+ "metric": "30",
+ "next-hop": "r5",
+ "parent": "r3(4)",
+ "type": "IP6 internal",
"vertex": "2001:db8:1:1::/64"
}
]
- },
+ },
"level-2": {
"ipv4": [
{
"vertex": "r4"
- },
+ },
{
- "metric": "internal",
- "parent": "0",
- "type": "IP",
+ "metric": "0",
+ "parent": "r4(4)",
+ "type": "IP internal",
"vertex": "10.0.21.0/24"
- },
+ },
{
- "interface": "r4-eth0",
- "metric": "10",
- "next-hop": "r2",
- "parent": "r4(4)",
- "type": "TE-IS",
+ "interface": "r4-eth0",
+ "metric": "10",
+ "next-hop": "r2",
+ "parent": "r4(4)",
+ "type": "TE-IS",
"vertex": "r2"
- },
+ },
{
- "interface": "r2",
- "metric": "TE",
- "next-hop": "20",
- "parent": "r4-eth0",
- "type": "IP",
+ "interface": "r4-eth0",
+ "metric": "20",
+ "next-hop": "r2",
+ "parent": "r2(4)",
+ "type": "IP TE",
"vertex": "10.0.21.0/24"
}
- ],
+ ],
"ipv6": [
{
"vertex": "r4"
- },
+ },
{
- "metric": "internal",
- "parent": "0",
- "type": "IP6",
+ "metric": "0",
+ "parent": "r4(4)",
+ "type": "IP6 internal",
"vertex": "2001:db8:1:2::/64"
- },
+ },
{
- "interface": "r4-eth0",
- "metric": "10",
- "next-hop": "r2",
- "parent": "r4(4)",
- "type": "TE-IS",
+ "interface": "r4-eth0",
+ "metric": "10",
+ "next-hop": "r2",
+ "parent": "r4(4)",
+ "type": "TE-IS",
"vertex": "r2"
}
]
diff --git a/tests/topotests/isis-topo1-vrf/r5/r5_topology.json b/tests/topotests/isis-topo1-vrf/r5/r5_topology.json
index b4ed6a069d..ace56536e9 100644
--- a/tests/topotests/isis-topo1-vrf/r5/r5_topology.json
+++ b/tests/topotests/isis-topo1-vrf/r5/r5_topology.json
@@ -4,121 +4,121 @@
"ipv4": [
{
"vertex": "r5"
- },
+ },
{
- "metric": "internal",
- "parent": "0",
- "type": "IP",
+ "metric": "0",
+ "parent": "r5(4)",
+ "type": "IP internal",
"vertex": "10.0.10.0/24"
- },
+ },
{
- "metric": "internal",
- "parent": "0",
- "type": "IP",
+ "metric": "0",
+ "parent": "r5(4)",
+ "type": "IP internal",
"vertex": "10.0.11.0/24"
- },
+ },
{
- "interface": "r5-eth0",
- "metric": "10",
- "next-hop": "r3",
- "parent": "r5(4)",
- "type": "TE-IS",
+ "interface": "r5-eth0",
+ "metric": "10",
+ "next-hop": "r3",
+ "parent": "r5(4)",
+ "type": "TE-IS",
"vertex": "r3"
- },
+ },
{
- "interface": "r5-eth1",
- "metric": "10",
- "next-hop": "r4",
- "parent": "r5(4)",
- "type": "TE-IS",
+ "interface": "r5-eth1",
+ "metric": "10",
+ "next-hop": "r4",
+ "parent": "r5(4)",
+ "type": "TE-IS",
"vertex": "r4"
- },
+ },
{
- "interface": "r3",
- "metric": "TE",
- "next-hop": "20",
- "parent": "r5-eth0",
- "type": "IP",
+ "interface": "r5-eth0",
+ "metric": "20",
+ "next-hop": "r3",
+ "parent": "r3(4)",
+ "type": "IP TE",
"vertex": "10.0.20.0/24"
- },
+ },
{
- "interface": "r3",
- "metric": "TE",
- "next-hop": "20",
- "parent": "r5-eth0",
- "type": "IP",
+ "interface": "r5-eth0",
+ "metric": "20",
+ "next-hop": "r3",
+ "parent": "r3(4)",
+ "type": "IP TE",
"vertex": "10.0.10.0/24"
- },
+ },
{
- "interface": "r4",
- "metric": "TE",
- "next-hop": "20",
- "parent": "r5-eth1",
- "type": "IP",
+ "interface": "r5-eth1",
+ "metric": "20",
+ "next-hop": "r4",
+ "parent": "r4(4)",
+ "type": "IP TE",
"vertex": "10.0.21.0/24"
- },
+ },
{
- "interface": "r4",
- "metric": "TE",
- "next-hop": "20",
- "parent": "r5-eth1",
- "type": "IP",
+ "interface": "r5-eth1",
+ "metric": "20",
+ "next-hop": "r4",
+ "parent": "r4(4)",
+ "type": "IP TE",
"vertex": "10.0.11.0/24"
}
- ],
+ ],
"ipv6": [
{
"vertex": "r5"
- },
+ },
{
- "metric": "internal",
- "parent": "0",
- "type": "IP6",
+ "metric": "0",
+ "parent": "r5(4)",
+ "type": "IP6 internal",
"vertex": "2001:db8:2:1::/64"
- },
+ },
{
- "metric": "internal",
- "parent": "0",
- "type": "IP6",
+ "metric": "0",
+ "parent": "r5(4)",
+ "type": "IP6 internal",
"vertex": "2001:db8:2:2::/64"
- },
+ },
{
- "interface": "r5-eth0",
- "metric": "10",
- "next-hop": "r3",
- "parent": "r5(4)",
- "type": "TE-IS",
+ "interface": "r5-eth0",
+ "metric": "10",
+ "next-hop": "r3",
+ "parent": "r5(4)",
+ "type": "TE-IS",
"vertex": "r3"
- },
+ },
{
- "interface": "r5-eth1",
- "metric": "10",
- "next-hop": "r4",
- "parent": "r5(4)",
- "type": "TE-IS",
+ "interface": "r5-eth1",
+ "metric": "10",
+ "next-hop": "r4",
+ "parent": "r5(4)",
+ "type": "TE-IS",
"vertex": "r4"
- },
+ },
{
- "interface": "r3",
- "metric": "internal",
- "next-hop": "20",
- "parent": "r5-eth0",
- "type": "IP6",
+ "interface": "r5-eth0",
+ "metric": "20",
+ "next-hop": "r3",
+ "parent": "r3(4)",
+ "type": "IP6 internal",
"vertex": "2001:db8:1:1::/64"
- },
+ },
{
- "interface": "r4",
- "metric": "internal",
- "next-hop": "20",
- "parent": "r5-eth1",
- "type": "IP6",
+ "interface": "r5-eth1",
+ "metric": "20",
+ "next-hop": "r4",
+ "parent": "r4(4)",
+ "type": "IP6 internal",
"vertex": "2001:db8:1:2::/64"
}
]
- },
+ },
"level-2": {
- "ipv4": [],
+ "ipv4": [],
"ipv6": []
}
}
-} \ No newline at end of file
+}
diff --git a/tests/topotests/isis-topo1-vrf/test_isis_topo1_vrf.py b/tests/topotests/isis-topo1-vrf/test_isis_topo1_vrf.py
index 6ab78c385e..b7fe0c2ddb 100644
--- a/tests/topotests/isis-topo1-vrf/test_isis_topo1_vrf.py
+++ b/tests/topotests/isis-topo1-vrf/test_isis_topo1_vrf.py
@@ -40,11 +40,30 @@ sys.path.append(os.path.join(CWD, "../"))
from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.topolog import logger
+from lib.topotest import iproute2_is_vrf_capable
+from lib.common_config import (
+ required_linux_kernel_version,
+ adjust_router_l3mdev,
+)
from mininet.topo import Topo
pytestmark = [pytest.mark.isisd]
+VERTEX_TYPE_LIST = [
+ "pseudo_IS",
+ "pseudo_TE-IS",
+ "IS",
+ "TE-IS",
+ "ES",
+ "IP internal",
+ "IP external",
+ "IP TE",
+ "IP6 internal",
+ "IP6 external",
+ "UNKNOWN",
+]
+
class ISISTopo1(Topo):
"Simple two layer ISIS vrf topology"
@@ -91,22 +110,6 @@ def setup_module(mod):
tgen.start_topology()
logger.info("Testing with VRF Lite support")
- krel = platform.release()
-
- # May need to adjust handling of vrf traffic depending on kernel version
- l3mdev_accept = 0
- if (
- topotest.version_cmp(krel, "4.15") >= 0
- and topotest.version_cmp(krel, "4.18") <= 0
- ):
- l3mdev_accept = 1
-
- if topotest.version_cmp(krel, "5.0") >= 0:
- l3mdev_accept = 1
-
- logger.info(
- "krel '{0}' setting net.ipv4.tcp_l3mdev_accept={1}".format(krel, l3mdev_accept)
- )
cmds = [
"ip link add {0}-cust1 type vrf table 1001",
@@ -120,15 +123,9 @@ def setup_module(mod):
# create VRF rx-cust1 and link rx-eth0 to rx-cust1
for cmd in cmds:
output = tgen.net[rname].cmd(cmd.format(rname))
- output = tgen.net[rname].cmd("sysctl -n net.ipv4.tcp_l3mdev_accept")
- logger.info(
- "router {0}: existing tcp_l3mdev_accept was {1}".format(rname, output)
- )
- if l3mdev_accept:
- output = tgen.net[rname].cmd(
- "sysctl -w net.ipv4.tcp_l3mdev_accept={}".format(l3mdev_accept)
- )
+ # adjust handling of vrf traffic
+ adjust_router_l3mdev(tgen, rname)
for rname, router in tgen.routers().items():
router.load_config(
@@ -193,18 +190,21 @@ def test_isis_route_installation():
def test_isis_linux_route_installation():
-
- dist = platform.dist()
-
- if dist[1] == "16.04":
- pytest.skip("Kernel not supported for vrf")
-
"Check whether all expected routes are present and installed in the OS"
tgen = get_topogen()
# Don't run this test if we have any failure.
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
+ # Required linux kernel version for this suite to run.
+ result = required_linux_kernel_version("4.15")
+ if result is not True:
+ pytest.skip("Kernel requirements are not met")
+
+ # iproute2 needs to support VRFs for this suite to run.
+ if not iproute2_is_vrf_capable():
+ pytest.skip("Installed iproute2 version does not support VRFs")
+
logger.info("Checking routers for installed ISIS vrf routes in OS")
# Check for routes in `ip route show vrf {}-cust1`
for rname, router in tgen.routers().items():
@@ -236,18 +236,21 @@ def test_isis_route6_installation():
def test_isis_linux_route6_installation():
-
- dist = platform.dist()
-
- if dist[1] == "16.04":
- pytest.skip("Kernel not supported for vrf")
-
"Check whether all expected routes are present and installed in the OS"
tgen = get_topogen()
# Don't run this test if we have any failure.
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
+ # Required linux kernel version for this suite to run.
+ result = required_linux_kernel_version("4.15")
+ if result is not True:
+ pytest.skip("Kernel requirements are not met")
+
+ # iproute2 needs to support VRFs for this suite to run.
+ if not iproute2_is_vrf_capable():
+ pytest.skip("Installed iproute2 version does not support VRFs")
+
logger.info("Checking routers for installed ISIS vrf IPv6 routes in OS")
# Check for routes in `ip -6 route show vrf {}-cust1`
for rname, router in tgen.routers().items():
@@ -308,6 +311,7 @@ def parse_topology(lines, level):
areas = {}
area = None
ipv = None
+ vertex_type_regex = "|".join(VERTEX_TYPE_LIST)
for line in lines:
area_match = re.match(r"Area (.+):", line)
@@ -327,44 +331,57 @@ def parse_topology(lines, level):
ipv = "ipv4"
continue
- item_match = re.match(r"([^ ]+) ([^ ]+) ([^ ]+) ([^ ]+) ([^ ]+) ([^ ]+)", line)
- if item_match is not None:
+ item_match = re.match(
+ r"([^\s]+) ([^\s]+) ([^\s]+) ([^\s]+) ([^\s]+) ([^\s]+)", line
+ )
+ if (
+ item_match is not None
+ and item_match.group(1) == "Vertex"
+ and item_match.group(2) == "Type"
+ and item_match.group(3) == "Metric"
+ and item_match.group(4) == "Next-Hop"
+ and item_match.group(5) == "Interface"
+ and item_match.group(6) == "Parent"
+ ):
# Skip header
- if (
- item_match.group(1) == "Vertex"
- and item_match.group(2) == "Type"
- and item_match.group(3) == "Metric"
- and item_match.group(4) == "Next-Hop"
- and item_match.group(5) == "Interface"
- and item_match.group(6) == "Parent"
- ):
- continue
+ continue
+ item_match = re.match(
+ r"([^\s]+) ({}) ([0]|([1-9][0-9]*)) ([^\s]+) ([^\s]+) ([^\s]+)".format(
+ vertex_type_regex
+ ),
+ line,
+ )
+ if item_match is not None:
areas[area][level][ipv].append(
{
"vertex": item_match.group(1),
"type": item_match.group(2),
"metric": item_match.group(3),
- "next-hop": item_match.group(4),
- "interface": item_match.group(5),
- "parent": item_match.group(6),
+ "next-hop": item_match.group(5),
+ "interface": item_match.group(6),
+ "parent": item_match.group(7),
}
)
continue
- item_match = re.match(r"([^ ]+) ([^ ]+) ([^ ]+) ([^ ]+)", line)
+ item_match = re.match(
+ r"([^\s]+) ({}) ([0]|([1-9][0-9]*)) ([^\s]+)".format(vertex_type_regex),
+ line,
+ )
+
if item_match is not None:
areas[area][level][ipv].append(
{
"vertex": item_match.group(1),
"type": item_match.group(2),
"metric": item_match.group(3),
- "parent": item_match.group(4),
+ "parent": item_match.group(5),
}
)
continue
- item_match = re.match(r"([^ ]+)", line)
+ item_match = re.match(r"([^\s]+)", line)
if item_match is not None:
areas[area][level][ipv].append({"vertex": item_match.group(1)})
continue
diff --git a/tests/topotests/ldp-snmp/test_ldp_snmp_topo1.py b/tests/topotests/ldp-snmp/test_ldp_snmp_topo1.py
index 4144f9b261..f47d906157 100644
--- a/tests/topotests/ldp-snmp/test_ldp_snmp_topo1.py
+++ b/tests/topotests/ldp-snmp/test_ldp_snmp_topo1.py
@@ -141,15 +141,16 @@ def setup_module(mod):
TopoRouter.RD_ISIS, os.path.join(CWD, "{}/isisd.conf".format(rname))
)
router.load_config(
- TopoRouter.RD_LDP, os.path.join(CWD, "{}/ldpd.conf".format(rname)),
- "-M snmp"
+ TopoRouter.RD_LDP,
+ os.path.join(CWD, "{}/ldpd.conf".format(rname)),
+ "-M snmp",
)
router.load_config(
- TopoRouter.RD_SNMP, os.path.join(CWD, "{}/snmpd.conf".format(rname)),
- "-Le -Ivacm_conf,usmConf,iquery -V -DAgentX,trap"
+ TopoRouter.RD_SNMP,
+ os.path.join(CWD, "{}/snmpd.conf".format(rname)),
+ "-Le -Ivacm_conf,usmConf,iquery -V -DAgentX,trap",
)
-
tgen.start_router()
@@ -199,7 +200,7 @@ def test_rib():
# Skip if previous fatal error condition is raised
# TODO: disabling this check to avoid 'snmpd not running' errors
- #if tgen.routers_have_failure():
+ # if tgen.routers_have_failure():
# pytest.skip(tgen.errors)
for rname in ["r1", "r2", "r3"]:
@@ -212,7 +213,7 @@ def test_ldp_adjacencies():
# Skip if previous fatal error condition is raised
# TODO: disabling this check to avoid 'snmpd not running' errors
- #if tgen.routers_have_failure():
+ # if tgen.routers_have_failure():
# pytest.skip(tgen.errors)
for rname in ["r1", "r2", "r3"]:
@@ -226,7 +227,7 @@ def test_ldp_neighbors():
tgen = get_topogen()
# Skip if previous fatal error condition is raised
- #if tgen.routers_have_failure():
+ # if tgen.routers_have_failure():
# pytest.skip(tgen.errors)
for rname in ["r1", "r2", "r3"]:
@@ -242,8 +243,8 @@ def test_r1_ldp_lsr_objects():
r1 = tgen.net.get("r1")
r1_snmp = SnmpTester(r1, "1.1.1.1", "public", "2c")
- assert r1_snmp.test_oid('mplsLdpLsrId', "01 01 01 01")
- assert r1_snmp.test_oid('mplsLdpLsrLoopDetectionCapable', 'none(1)')
+ assert r1_snmp.test_oid("mplsLdpLsrId", "01 01 01 01")
+ assert r1_snmp.test_oid("mplsLdpLsrLoopDetectionCapable", "none(1)")
def test_r1_ldp_entity_table():
@@ -253,52 +254,31 @@ def test_r1_ldp_entity_table():
r1 = tgen.net.get("r1")
r1_snmp = SnmpTester(r1, "1.1.1.1", "public", "2c")
- assert r1_snmp.test_oid_walk(
- 'mplsLdpEntityLdpId', ['1.1.1.1:0'])
- assert r1_snmp.test_oid_walk(
- 'mplsLdpEntityIndex', ['1'])
- assert r1_snmp.test_oid_walk(
- 'mplsLdpEntityProtocolVersion', ['1'])
- assert r1_snmp.test_oid_walk(
- 'mplsLdpEntityAdminStatus', ['enable(1)'])
- assert r1_snmp.test_oid_walk(
- 'mplsLdpEntityOperStatus', ['enabled(2)'])
- assert r1_snmp.test_oid_walk(
- 'mplsLdpEntityTcpPort', ['646'])
- assert r1_snmp.test_oid_walk(
- 'mplsLdpEntityUdpDscPort', ['646'])
- assert r1_snmp.test_oid_walk(
- 'mplsLdpEntityMaxPduLength', ['4096 octets'])
- assert r1_snmp.test_oid_walk(
- 'mplsLdpEntityKeepAliveHoldTimer', ['180 seconds'])
- assert r1_snmp.test_oid_walk(
- 'mplsLdpEntityHelloHoldTimer', ['0 seconds'])
- assert r1_snmp.test_oid_walk(
- 'mplsLdpEntityInitSessionThreshold', ['0'])
- assert r1_snmp.test_oid_walk(
- 'mplsLdpEntityLabelDistMethod', ['downstreamUnsolicited(2)'])
- assert r1_snmp.test_oid_walk(
- 'mplsLdpEntityLabelRetentionMode', ['liberal(2)'])
- assert r1_snmp.test_oid_walk(
- 'mplsLdpEntityPathVectorLimit', ['0'])
- assert r1_snmp.test_oid_walk(
- 'mplsLdpEntityHopCountLimit', ['0'])
- assert r1_snmp.test_oid_walk(
- 'mplsLdpEntityTransportAddrKind', ['loopback(2)'])
- assert r1_snmp.test_oid_walk(
- 'mplsLdpEntityTargetPeer', ['true(1)'])
- assert r1_snmp.test_oid_walk(
- 'mplsLdpEntityTargetPeerAddrType', ['ipv4(1)'])
- assert r1_snmp.test_oid_walk(
- 'mplsLdpEntityTargetPeerAddr', ['01 01 01 01'])
- assert r1_snmp.test_oid_walk(
- 'mplsLdpEntityLabelType', ['generic(1)'])
- assert r1_snmp.test_oid_walk(
- 'mplsLdpEntityDiscontinuityTime', ['(0) 0:00:00.00'])
- assert r1_snmp.test_oid_walk(
- 'mplsLdpEntityStorageType', ['nonVolatile(3)'])
- assert r1_snmp.test_oid_walk(
- 'mplsLdpEntityRowStatus', ['createAndGo(4)'])
+ assert r1_snmp.test_oid_walk("mplsLdpEntityLdpId", ["1.1.1.1:0"])
+ assert r1_snmp.test_oid_walk("mplsLdpEntityIndex", ["1"])
+ assert r1_snmp.test_oid_walk("mplsLdpEntityProtocolVersion", ["1"])
+ assert r1_snmp.test_oid_walk("mplsLdpEntityAdminStatus", ["enable(1)"])
+ assert r1_snmp.test_oid_walk("mplsLdpEntityOperStatus", ["enabled(2)"])
+ assert r1_snmp.test_oid_walk("mplsLdpEntityTcpPort", ["646"])
+ assert r1_snmp.test_oid_walk("mplsLdpEntityUdpDscPort", ["646"])
+ assert r1_snmp.test_oid_walk("mplsLdpEntityMaxPduLength", ["4096 octets"])
+ assert r1_snmp.test_oid_walk("mplsLdpEntityKeepAliveHoldTimer", ["180 seconds"])
+ assert r1_snmp.test_oid_walk("mplsLdpEntityHelloHoldTimer", ["0 seconds"])
+ assert r1_snmp.test_oid_walk("mplsLdpEntityInitSessionThreshold", ["0"])
+ assert r1_snmp.test_oid_walk(
+ "mplsLdpEntityLabelDistMethod", ["downstreamUnsolicited(2)"]
+ )
+ assert r1_snmp.test_oid_walk("mplsLdpEntityLabelRetentionMode", ["liberal(2)"])
+ assert r1_snmp.test_oid_walk("mplsLdpEntityPathVectorLimit", ["0"])
+ assert r1_snmp.test_oid_walk("mplsLdpEntityHopCountLimit", ["0"])
+ assert r1_snmp.test_oid_walk("mplsLdpEntityTransportAddrKind", ["loopback(2)"])
+ assert r1_snmp.test_oid_walk("mplsLdpEntityTargetPeer", ["true(1)"])
+ assert r1_snmp.test_oid_walk("mplsLdpEntityTargetPeerAddrType", ["ipv4(1)"])
+ assert r1_snmp.test_oid_walk("mplsLdpEntityTargetPeerAddr", ["01 01 01 01"])
+ assert r1_snmp.test_oid_walk("mplsLdpEntityLabelType", ["generic(1)"])
+ assert r1_snmp.test_oid_walk("mplsLdpEntityDiscontinuityTime", ["(0) 0:00:00.00"])
+ assert r1_snmp.test_oid_walk("mplsLdpEntityStorageType", ["nonVolatile(3)"])
+ assert r1_snmp.test_oid_walk("mplsLdpEntityRowStatus", ["createAndGo(4)"])
def test_r1_ldp_entity_stats_table():
@@ -308,32 +288,23 @@ def test_r1_ldp_entity_stats_table():
r1 = tgen.net.get("r1")
r1_snmp = SnmpTester(r1, "1.1.1.1", "public", "2c")
+ assert r1_snmp.test_oid_walk("mplsLdpEntityStatsSessionAttempts", ["0"])
assert r1_snmp.test_oid_walk(
- 'mplsLdpEntityStatsSessionAttempts', ['0'])
- assert r1_snmp.test_oid_walk(
- 'mplsLdpEntityStatsSessionRejectedNoHelloErrors', ['0'])
- assert r1_snmp.test_oid_walk(
- 'mplsLdpEntityStatsSessionRejectedAdErrors', ['0'])
- assert r1_snmp.test_oid_walk(
- 'mplsLdpEntityStatsSessionRejectedMaxPduErrors', ['0'])
- assert r1_snmp.test_oid_walk(
- 'mplsLdpEntityStatsSessionRejectedLRErrors', ['0'])
- assert r1_snmp.test_oid_walk(
- 'mplsLdpEntityStatsBadLdpIdentifierErrors', ['0'])
- assert r1_snmp.test_oid_walk(
- 'mplsLdpEntityStatsBadPduLengthErrors', ['0'])
- assert r1_snmp.test_oid_walk(
- 'mplsLdpEntityStatsBadMessageLengthErrors', ['0'])
- assert r1_snmp.test_oid_walk(
- 'mplsLdpEntityStatsBadTlvLengthErrors', ['0'])
- assert r1_snmp.test_oid_walk(
- 'mplsLdpEntityStatsMalformedTlvValueErrors', ['0'])
- assert r1_snmp.test_oid_walk(
- 'mplsLdpEntityStatsKeepAliveTimerExpErrors', ['0'])
+ "mplsLdpEntityStatsSessionRejectedNoHelloErrors", ["0"]
+ )
+ assert r1_snmp.test_oid_walk("mplsLdpEntityStatsSessionRejectedAdErrors", ["0"])
+ assert r1_snmp.test_oid_walk("mplsLdpEntityStatsSessionRejectedMaxPduErrors", ["0"])
+ assert r1_snmp.test_oid_walk("mplsLdpEntityStatsSessionRejectedLRErrors", ["0"])
+ assert r1_snmp.test_oid_walk("mplsLdpEntityStatsBadLdpIdentifierErrors", ["0"])
+ assert r1_snmp.test_oid_walk("mplsLdpEntityStatsBadPduLengthErrors", ["0"])
+ assert r1_snmp.test_oid_walk("mplsLdpEntityStatsBadMessageLengthErrors", ["0"])
+ assert r1_snmp.test_oid_walk("mplsLdpEntityStatsBadTlvLengthErrors", ["0"])
+ assert r1_snmp.test_oid_walk("mplsLdpEntityStatsMalformedTlvValueErrors", ["0"])
+ assert r1_snmp.test_oid_walk("mplsLdpEntityStatsKeepAliveTimerExpErrors", ["0"])
assert r1_snmp.test_oid_walk(
- 'mplsLdpEntityStatsShutdownReceivedNotifications', ['0'])
- assert r1_snmp.test_oid_walk(
- 'mplsLdpEntityStatsShutdownSentNotifications', ['0'])
+ "mplsLdpEntityStatsShutdownReceivedNotifications", ["0"]
+ )
+ assert r1_snmp.test_oid_walk("mplsLdpEntityStatsShutdownSentNotifications", ["0"])
def test_r1_ldp_peer_table():
@@ -343,17 +314,16 @@ def test_r1_ldp_peer_table():
r1 = tgen.net.get("r1")
r1_snmp = SnmpTester(r1, "1.1.1.1", "public", "2c")
+ assert r1_snmp.test_oid_walk("mplsLdpPeerLdpId", ["2.2.2.2:0", "3.3.3.3:0"])
assert r1_snmp.test_oid_walk(
- 'mplsLdpPeerLdpId', ['2.2.2.2:0', '3.3.3.3:0'])
- assert r1_snmp.test_oid_walk(
- 'mplsLdpPeerLabelDistMethod',
- ['downstreamUnsolicited(2)', 'downstreamUnsolicited(2)'])
- assert r1_snmp.test_oid_walk(
- 'mplsLdpPeerPathVectorLimit', ['0', '0'])
+ "mplsLdpPeerLabelDistMethod",
+ ["downstreamUnsolicited(2)", "downstreamUnsolicited(2)"],
+ )
+ assert r1_snmp.test_oid_walk("mplsLdpPeerPathVectorLimit", ["0", "0"])
+ assert r1_snmp.test_oid_walk("mplsLdpPeerTransportAddrType", ["ipv4(1)", "ipv4(1)"])
assert r1_snmp.test_oid_walk(
- 'mplsLdpPeerTransportAddrType', ['ipv4(1)', 'ipv4(1)'])
- assert r1_snmp.test_oid_walk(
- 'mplsLdpPeerTransportAddr', ['02 02 02 02', '03 03 03 03'])
+ "mplsLdpPeerTransportAddr", ["02 02 02 02", "03 03 03 03"]
+ )
def test_r1_ldp_session_table():
@@ -363,18 +333,20 @@ def test_r1_ldp_session_table():
r1 = tgen.net.get("r1")
r1_snmp = SnmpTester(r1, "1.1.1.1", "public", "2c")
- assert r1_snmp.test_oid_walk('mplsLdpSessionState',
- ['operational(5)', 'operational(5)'])
- assert r1_snmp.test_oid_walk('mplsLdpSessionRole',
- ['passive(3)', 'passive(3)'])
- assert r1_snmp.test_oid_walk('mplsLdpSessionProtocolVersion',
- ['1', '1'])
- assert r1_snmp.test_oid_walk('mplsLdpSessionKeepAliveTime',
- ['180 seconds', '180 seconds'])
- assert r1_snmp.test_oid_walk('mplsLdpSessionMaxPduLength',
- ['4096 octets', '4096 octets'])
- assert r1_snmp.test_oid_walk('mplsLdpSessionDiscontinuityTime',
- ['(0) 0:00:00.00', '(0) 0:00:00.00'])
+ assert r1_snmp.test_oid_walk(
+ "mplsLdpSessionState", ["operational(5)", "operational(5)"]
+ )
+ assert r1_snmp.test_oid_walk("mplsLdpSessionRole", ["passive(3)", "passive(3)"])
+ assert r1_snmp.test_oid_walk("mplsLdpSessionProtocolVersion", ["1", "1"])
+ assert r1_snmp.test_oid_walk(
+ "mplsLdpSessionKeepAliveTime", ["180 seconds", "180 seconds"]
+ )
+ assert r1_snmp.test_oid_walk(
+ "mplsLdpSessionMaxPduLength", ["4096 octets", "4096 octets"]
+ )
+ assert r1_snmp.test_oid_walk(
+ "mplsLdpSessionDiscontinuityTime", ["(0) 0:00:00.00", "(0) 0:00:00.00"]
+ )
def test_r1_ldp_session_stats_table():
@@ -384,10 +356,8 @@ def test_r1_ldp_session_stats_table():
r1 = tgen.net.get("r1")
r1_snmp = SnmpTester(r1, "1.1.1.1", "public", "2c")
- assert r1_snmp.test_oid_walk(
- 'mplsLdpSessionStatsUnknownMesTypeErrors', ['0', '0'])
- assert r1_snmp.test_oid_walk(
- 'mplsLdpSessionStatsUnknownTlvErrors', ['0', '0'])
+ assert r1_snmp.test_oid_walk("mplsLdpSessionStatsUnknownMesTypeErrors", ["0", "0"])
+ assert r1_snmp.test_oid_walk("mplsLdpSessionStatsUnknownTlvErrors", ["0", "0"])
def test_r1_ldp_hello_adjacency_table():
@@ -397,12 +367,11 @@ def test_r1_ldp_hello_adjacency_table():
r1 = tgen.net.get("r1")
r1_snmp = SnmpTester(r1, "1.1.1.1", "public", "2c")
- assert r1_snmp.test_oid_walk('mplsLdpHelloAdjacencyIndex',
- ['1', '2', '1'])
- assert r1_snmp.test_oid_walk('mplsLdpHelloAdjacencyHoldTime',
- ['15', '45', '15'])
- assert r1_snmp.test_oid_walk('mplsLdpHelloAdjacencyType',
- ['link(1)', 'targeted(2)', 'link(1)'])
+ assert r1_snmp.test_oid_walk("mplsLdpHelloAdjacencyIndex", ["1", "2", "1"])
+ assert r1_snmp.test_oid_walk("mplsLdpHelloAdjacencyHoldTime", ["15", "45", "15"])
+ assert r1_snmp.test_oid_walk(
+ "mplsLdpHelloAdjacencyType", ["link(1)", "targeted(2)", "link(1)"]
+ )
# Memory leak test template
diff --git a/tests/topotests/lib/bgp.py b/tests/topotests/lib/bgp.py
index 867831e114..d2212d1807 100644
--- a/tests/topotests/lib/bgp.py
+++ b/tests/topotests/lib/bgp.py
@@ -43,7 +43,7 @@ from lib.common_config import (
run_frr_cmd,
FRRCFG_FILE,
retry,
- get_ipv6_linklocal_address
+ get_ipv6_linklocal_address,
)
LOGDIR = "/tmp/topotests/"
@@ -1582,7 +1582,7 @@ def verify_bgp_convergence_from_running_config(tgen, dut=None):
return True
-def clear_bgp(tgen, addr_type, router, vrf=None):
+def clear_bgp(tgen, addr_type, router, vrf=None, neighbor=None):
"""
This API is to clear bgp neighborship by running
clear ip bgp */clear bgp ipv6 * command,
@@ -1593,6 +1593,7 @@ def clear_bgp(tgen, addr_type, router, vrf=None):
* `addr_type`: ip type ipv4/ipv6
* `router`: device under test
* `vrf`: vrf name
+ * `neighbor`: Neighbor for which bgp needs to be cleared
Usage
-----
@@ -1616,12 +1617,16 @@ def clear_bgp(tgen, addr_type, router, vrf=None):
if vrf:
for _vrf in vrf:
run_frr_cmd(rnode, "clear ip bgp vrf {} *".format(_vrf))
+ elif neighbor:
+ run_frr_cmd(rnode, "clear bgp ipv4 {}".format(neighbor))
else:
run_frr_cmd(rnode, "clear ip bgp *")
elif addr_type == "ipv6":
if vrf:
for _vrf in vrf:
run_frr_cmd(rnode, "clear bgp vrf {} ipv6 *".format(_vrf))
+ elif neighbor:
+ run_frr_cmd(rnode, "clear bgp ipv6 {}".format(neighbor))
else:
run_frr_cmd(rnode, "clear bgp ipv6 *")
else:
diff --git a/tests/topotests/lib/common_config.py b/tests/topotests/lib/common_config.py
index a4c98924b6..ead593d2ca 100644
--- a/tests/topotests/lib/common_config.py
+++ b/tests/topotests/lib/common_config.py
@@ -72,6 +72,59 @@ config.read(PYTESTINI_PATH)
config_section = "topogen"
+# Debug logs for daemons
+DEBUG_LOGS = {
+ "pimd": [
+ "debug msdp events",
+ "debug msdp packets",
+ "debug igmp events",
+ "debug igmp trace",
+ "debug mroute",
+ "debug mroute detail",
+ "debug pim events",
+ "debug pim packets",
+ "debug pim trace",
+ "debug pim zebra",
+ "debug pim bsm",
+ "debug pim packets joins",
+ "debug pim packets register",
+ "debug pim nht",
+ ],
+ "bgpd": [
+ "debug bgp neighbor-events",
+ "debug bgp updates",
+ "debug bgp zebra",
+ "debug bgp nht",
+ "debug bgp neighbor-events",
+ "debug bgp graceful-restart",
+ "debug bgp update-groups",
+ "debug bgp vpn leak-from-vrf",
+ "debug bgp vpn leak-to-vrf",
+ "debug bgp zebr",
+ "debug bgp updates",
+ "debug bgp nht",
+ "debug bgp neighbor-events",
+ "debug vrf",
+ ],
+ "zebra": [
+ "debug zebra events",
+ "debug zebra rib",
+ "debug zebra vxlan",
+ "debug zebra nht",
+ ],
+ "ospf": [
+ "debug ospf event",
+ "debug ospf ism",
+ "debug ospf lsa",
+ "debug ospf nsm",
+ "debug ospf nssa",
+ "debug ospf packet all",
+ "debug ospf sr",
+ "debug ospf te",
+ "debug ospf zebra",
+ ],
+}
+
if config.has_option("topogen", "verbosity"):
loglevel = config.get("topogen", "verbosity")
loglevel = loglevel.upper()
@@ -249,6 +302,7 @@ def create_common_configuration(
config_map = OrderedDict(
{
"general_config": "! FRR General Config\n",
+ "debug_log_config": "! Debug log Config\n",
"interface_config": "! Interfaces Config\n",
"static_route": "! Static Route Config\n",
"prefix_list": "! Prefix List Config\n",
@@ -1052,6 +1106,89 @@ def tcpdump_capture_stop(tgen, router):
return True
+def create_debug_log_config(tgen, input_dict, build=False):
+ """
+ Enable/disable debug logs for any protocol with defined debug
+ options and logs would be saved to created log file
+
+ Parameters
+ ----------
+ * `tgen` : Topogen object
+ * `input_dict` : details to enable debug logs for protocols
+ * `build` : Only for initial setup phase this is set as True.
+
+
+ Usage:
+ ------
+ input_dict = {
+ "r2": {
+ "debug":{
+ "log_file" : "debug.log",
+ "enable": ["pimd", "zebra"],
+ "disable": {
+ "bgpd":[
+ 'debug bgp neighbor-events',
+ 'debug bgp updates',
+ 'debug bgp zebra',
+ ]
+ }
+ }
+ }
+ }
+
+ result = create_debug_log_config(tgen, input_dict)
+
+ Returns
+ -------
+ True or False
+ """
+
+ result = False
+ try:
+ for router in input_dict.keys():
+ debug_config = []
+ if "debug" in input_dict[router]:
+ debug_dict = input_dict[router]["debug"]
+
+ disable_logs = debug_dict.setdefault("disable", None)
+ enable_logs = debug_dict.setdefault("enable", None)
+ log_file = debug_dict.setdefault("log_file", None)
+
+ if log_file:
+ _log_file = os.path.join(LOGDIR, tgen.modname, log_file)
+ debug_config.append("log file {} \n".format(_log_file))
+
+ if type(enable_logs) is list:
+ for daemon in enable_logs:
+ for debug_log in DEBUG_LOGS[daemon]:
+ debug_config.append("{}".format(debug_log))
+ elif type(enable_logs) is dict:
+ for daemon, debug_logs in enable_logs.items():
+ for debug_log in debug_logs:
+ debug_config.append("{}".format(debug_log))
+
+ if type(disable_logs) is list:
+ for daemon in disable_logs:
+ for debug_log in DEBUG_LOGS[daemon]:
+ debug_config.append("no {}".format(debug_log))
+ elif type(disable_logs) is dict:
+ for daemon, debug_logs in disable_logs.items():
+ for debug_log in debug_logs:
+ debug_config.append("no {}".format(debug_log))
+
+ result = create_common_configuration(
+ tgen, router, debug_config, "debug_log_config", build=build
+ )
+ except InvalidCLIError:
+ # Traceback
+ errormsg = traceback.format_exc()
+ logger.error(errormsg)
+ return errormsg
+
+ logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
+ return result
+
+
#############################################
# Common APIs, will be used by all protocols
#############################################
@@ -3728,7 +3865,7 @@ def get_ipv6_linklocal_address(topo, node, intf):
"""
tgen = get_topogen()
ext_nh = tgen.net[node].get_ipv6_linklocal()
- req_nh = topo[node]['links'][intf]['interface']
+ req_nh = topo[node]["links"][intf]["interface"]
llip = None
for llips in ext_nh:
if llips[0] == req_nh:
@@ -3736,8 +3873,9 @@ def get_ipv6_linklocal_address(topo, node, intf):
logger.info("Link local ip found = %s", llip)
return llip
- errormsg = "Failed: Link local ip not found on router {}, "\
- "interface {}".format(node, intf)
+ errormsg = "Failed: Link local ip not found on router {}, " "interface {}".format(
+ node, intf
+ )
return errormsg
@@ -4372,3 +4510,51 @@ def verify_ip_nht(tgen, input_dict):
logger.debug("Exiting lib API: verify_ip_nht()")
return False
+
+
+def kernel_requires_l3mdev_adjustment():
+ """
+ Checks if the L3 master device needs to be adjusted to handle VRF traffic
+ based on kernel version.
+
+ Returns
+ -------
+ 1 or 0
+ """
+
+ if version_cmp(platform.release(), "4.15") >= 0:
+ return 1
+ return 0
+
+
+def adjust_router_l3mdev(tgen, router):
+ """
+ Adjusts a routers L3 master device to handle VRF traffic depending on kernel
+ version.
+
+ Parameters
+ ----------
+ * `tgen` : tgen object
+ * `router` : router id to be configured.
+
+ Returns
+ -------
+ True
+ """
+
+ l3mdev_accept = kernel_requires_l3mdev_adjustment()
+
+ logger.info(
+ "router {0}: setting net.ipv4.tcp_l3mdev_accept={1}".format(
+ router, l3mdev_accept
+ )
+ )
+
+ output = tgen.net[router].cmd("sysctl -n net.ipv4.tcp_l3mdev_accept")
+ logger.info("router {0}: existing tcp_l3mdev_accept was {1}".format(router, output))
+
+ tgen.net[router].cmd(
+ "sysctl -w net.ipv4.tcp_l3mdev_accept={}".format(l3mdev_accept)
+ )
+
+ return True
diff --git a/tests/topotests/lib/ospf.py b/tests/topotests/lib/ospf.py
index 9f642411b5..04a12d0eec 100644
--- a/tests/topotests/lib/ospf.py
+++ b/tests/topotests/lib/ospf.py
@@ -344,9 +344,7 @@ def config_ospf_interface(tgen, topo, input_dict=None, build=False, load_config=
for lnk in input_dict[router]["links"].keys():
if "ospf" not in input_dict[router]["links"][lnk]:
logger.debug(
- "Router %s: ospf config is not present in"
- "input_dict",
- router
+ "Router %s: ospf config is not present in" "input_dict", router
)
continue
ospf_data = input_dict[router]["links"][lnk]["ospf"]
diff --git a/tests/topotests/lib/topotest.py b/tests/topotests/lib/topotest.py
index 5cc1a6981d..2a46115850 100644
--- a/tests/topotests/lib/topotest.py
+++ b/tests/topotests/lib/topotest.py
@@ -50,6 +50,9 @@ from mininet.node import Node, OVSSwitch, Host
from mininet.log import setLogLevel, info
from mininet.cli import CLI
from mininet.link import Intf
+from mininet.term import makeTerm
+
+g_extra_config = {}
def gdb_core(obj, daemon, corefiles):
@@ -516,6 +519,43 @@ def normalize_text(text):
return text
+def is_linux():
+ """
+ Parses unix name output to check if running on GNU/Linux.
+
+ Returns True if running on Linux, returns False otherwise.
+ """
+
+ if os.uname()[0] == "Linux":
+ return True
+ return False
+
+
+def iproute2_is_vrf_capable():
+ """
+ Checks if the iproute2 version installed on the system is capable of
+ handling VRFs by interpreting the output of the 'ip' utility found in PATH.
+
+ Returns True if capability can be detected, returns False otherwise.
+ """
+
+ if is_linux():
+ try:
+ subp = subprocess.Popen(
+ ["ip", "route", "show", "vrf"],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ stdin=subprocess.PIPE,
+ )
+ iproute2_err = subp.communicate()[1].splitlines()[0].split()[0]
+
+ if iproute2_err != "Error:":
+ return True
+ except Exception:
+ pass
+ return False
+
+
def module_present_linux(module, load):
"""
Returns whether `module` is present.
@@ -1303,6 +1343,28 @@ class Router(Node):
logger.info("No daemon {} known".format(daemon))
# print "Daemons after:", self.daemons
+ # Run a command in a new window (gnome-terminal, screen, tmux, xterm)
+ def runInWindow(self, cmd, title=None):
+ topo_terminal = os.getenv("FRR_TOPO_TERMINAL")
+ if topo_terminal or ("TMUX" not in os.environ and "STY" not in os.environ):
+ term = topo_terminal if topo_terminal else "xterm"
+ makeTerm(self, title=title if title else cmd, term=term, cmd=cmd)
+ else:
+ nscmd = "sudo nsenter -m -n -t {} {}".format(self.pid, cmd)
+ if "TMUX" in os.environ:
+ self.cmd("tmux select-layout main-horizontal")
+ wcmd = "tmux split-window -h"
+ cmd = "{} {}".format(wcmd, nscmd)
+ elif "STY" in os.environ:
+ if os.path.exists(
+ "/run/screen/S-{}/{}".format(os.environ["USER"], os.environ["STY"])
+ ):
+ wcmd = "screen"
+ else:
+ wcmd = "sudo -u {} screen".format(os.environ["SUDO_USER"])
+ cmd = "{} {}".format(wcmd, nscmd)
+ self.cmd(cmd)
+
def startRouter(self, tgen=None):
# Disable integrated-vtysh-config
self.cmd(
@@ -1355,6 +1417,14 @@ class Router(Node):
return "LDP/MPLS Tests need mpls kernel modules"
self.cmd("echo 100000 > /proc/sys/net/mpls/platform_labels")
+ shell_routers = g_extra_config["shell"]
+ if "all" in shell_routers or self.name in shell_routers:
+ self.runInWindow(os.getenv("SHELL", "bash"))
+
+ vtysh_routers = g_extra_config["vtysh"]
+ if "all" in vtysh_routers or self.name in vtysh_routers:
+ self.runInWindow("vtysh")
+
if self.daemons["eigrpd"] == 1:
eigrpd_path = os.path.join(self.daemondir, "eigrpd")
if not os.path.isfile(eigrpd_path):
@@ -1381,6 +1451,10 @@ class Router(Node):
def startRouterDaemons(self, daemons=None):
"Starts all FRR daemons for this router."
+ gdb_breakpoints = g_extra_config["gdb_breakpoints"]
+ gdb_daemons = g_extra_config["gdb_daemons"]
+ gdb_routers = g_extra_config["gdb_routers"]
+
bundle_data = ""
if os.path.exists("/etc/frr/support_bundle_commands.conf"):
@@ -1410,7 +1484,7 @@ class Router(Node):
# If `daemons` was specified then some upper API called us with
# specific daemons, otherwise just use our own configuration.
daemons_list = []
- if daemons != None:
+ if daemons is not None:
daemons_list = daemons
else:
# Append all daemons configured.
@@ -1418,47 +1492,64 @@ class Router(Node):
if self.daemons[daemon] == 1:
daemons_list.append(daemon)
- # Start Zebra first
- if "zebra" in daemons_list:
- zebra_path = os.path.join(self.daemondir, "zebra")
- zebra_option = self.daemons_options["zebra"]
- self.cmd(
- "ASAN_OPTIONS=log_path=zebra.asan {0} {1} --log file:zebra.log --log-level debug -s 90000000 -d > zebra.out 2> zebra.err".format(
- zebra_path, zebra_option
+ def start_daemon(daemon, extra_opts=None):
+ daemon_opts = self.daemons_options.get(daemon, "")
+ rediropt = " > {0}.out 2> {0}.err".format(daemon)
+ if daemon == "snmpd":
+ binary = "/usr/sbin/snmpd"
+ cmdenv = ""
+ cmdopt = "{} -C -c /etc/frr/snmpd.conf -p ".format(
+ daemon_opts
+ ) + "/var/run/{}/snmpd.pid -x /etc/frr/agentx".format(self.routertype)
+ else:
+ binary = os.path.join(self.daemondir, daemon)
+ cmdenv = "ASAN_OPTIONS=log_path={0}.asan".format(daemon)
+ cmdopt = "{} --log file:{}.log --log-level debug".format(
+ daemon_opts, daemon
)
- )
- logger.debug("{}: {} zebra started".format(self, self.routertype))
+ if extra_opts:
+ cmdopt += " " + extra_opts
- # Remove `zebra` so we don't attempt to start it again.
+ if (
+ (gdb_routers or gdb_daemons)
+ and (
+ not gdb_routers or self.name in gdb_routers or "all" in gdb_routers
+ )
+ and (not gdb_daemons or daemon in gdb_daemons or "all" in gdb_daemons)
+ ):
+ if daemon == "snmpd":
+ cmdopt += " -f "
+
+ cmdopt += rediropt
+ gdbcmd = "sudo -E gdb " + binary
+ if gdb_breakpoints:
+ gdbcmd += " -ex 'set breakpoint pending on'"
+ for bp in gdb_breakpoints:
+ gdbcmd += " -ex 'b {}'".format(bp)
+ gdbcmd += " -ex 'run {}'".format(cmdopt)
+
+ self.runInWindow(gdbcmd, daemon)
+ else:
+ if daemon != "snmpd":
+ cmdopt += " -d "
+ cmdopt += rediropt
+ self.cmd(" ".join([cmdenv, binary, cmdopt]))
+ logger.info("{}: {} {} started".format(self, self.routertype, daemon))
+
+ # Start Zebra first
+ if "zebra" in daemons_list:
+ start_daemon("zebra", "-s 90000000")
while "zebra" in daemons_list:
daemons_list.remove("zebra")
# Start staticd next if required
if "staticd" in daemons_list:
- staticd_path = os.path.join(self.daemondir, "staticd")
- staticd_option = self.daemons_options["staticd"]
- self.cmd(
- "ASAN_OPTIONS=log_path=staticd.asan {0} {1} --log file:staticd.log --log-level debug -d > staticd.out 2> staticd.err".format(
- staticd_path, staticd_option
- )
- )
- logger.debug("{}: {} staticd started".format(self, self.routertype))
-
- # Remove `staticd` so we don't attempt to start it again.
+ start_daemon("staticd")
while "staticd" in daemons_list:
daemons_list.remove("staticd")
if "snmpd" in daemons_list:
- snmpd_path = "/usr/sbin/snmpd"
- snmpd_option = self.daemons_options["snmpd"]
- self.cmd(
- "{0} {1} -C -c /etc/frr/snmpd.conf -p /var/run/{2}/snmpd.pid -x /etc/frr/agentx > snmpd.out 2> snmpd.err".format(
- snmpd_path, snmpd_option, self.routertype
- )
- )
- logger.info("{}: {} snmpd started".format(self, self.routertype))
-
- # Remove `snmpd` so we don't attempt to start it again.
+ start_daemon("snmpd")
while "snmpd" in daemons_list:
daemons_list.remove("snmpd")
@@ -1470,17 +1561,9 @@ class Router(Node):
# Now start all the other daemons
for daemon in daemons_list:
- # Skip disabled daemons and zebra
if self.daemons[daemon] == 0:
continue
-
- daemon_path = os.path.join(self.daemondir, daemon)
- self.cmd(
- "ASAN_OPTIONS=log_path={2}.asan {0} {1} --log file:{2}.log --log-level debug -d > {2}.out 2> {2}.err".format(
- daemon_path, self.daemons_options.get(daemon, ""), daemon
- )
- )
- logger.debug("{}: {} {} started".format(self, self.routertype, daemon))
+ start_daemon(daemon)
# Check if daemons are running.
rundaemons = self.cmd("ls -1 /var/run/%s/*.pid" % self.routertype)
diff --git a/tests/topotests/multicast-pim-bsm-topo1/test_mcast_pim_bsmp_01.py b/tests/topotests/multicast-pim-bsm-topo1/test_mcast_pim_bsmp_01.py
index 6b7180978e..cd398a5111 100644
--- a/tests/topotests/multicast-pim-bsm-topo1/test_mcast_pim_bsmp_01.py
+++ b/tests/topotests/multicast-pim-bsm-topo1/test_mcast_pim_bsmp_01.py
@@ -648,7 +648,11 @@ def test_BSR_CRP_with_blackhole_address_p1(request):
input_dict = {
"i1": {"static_routes": [{"network": BSR1_ADDR, "next_hop": next_hop_rp}]},
"l1": {"static_routes": [{"network": BSR1_ADDR, "next_hop": next_hop_lhr}]},
- "f1": {"static_routes": [{"network": CRP, "next_hop": next_hop_fhr, "delete": True}]},
+ "f1": {
+ "static_routes": [
+ {"network": CRP, "next_hop": next_hop_fhr, "delete": True}
+ ]
+ },
}
result = create_static_routes(tgen, input_dict)
@@ -692,10 +696,11 @@ def test_BSR_CRP_with_blackhole_address_p1(request):
step("Verify if b1 chosen as BSR in l1")
result = verify_pim_bsr(tgen, topo, "l1", BSR_IP_1, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "b1 is not chosen as BSR in l1 \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "b1 is not chosen as BSR in l1 \n Error: {}".format(
tc_name, result
- ))
+ )
state_after = verify_pim_interface_traffic(tgen, state_dict)
assert isinstance(
@@ -841,10 +846,12 @@ def test_new_router_fwd_p0(request):
# Verify bsr state in l1
step("Verify no BSR in l1 as i1 would not forward the no-forward bsm")
result = verify_pim_bsr(tgen, topo, "l1", bsr_ip, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"BSR data is present after no-forward bsm also \n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
# unconfigure unicast bsm on f1-i1-eth2
step("unconfigure unicast bsm on f1-i1-eth2, will forward with only mcast")
@@ -966,10 +973,11 @@ def test_int_bsm_config_p1(request):
result = verify_ip_mroutes(
tgen, "i1", src_addr, GROUP_ADDRESS, iif, oil, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "Mroutes are still present \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "Mroutes are still present \n Error: {}".format(
tc_name, result
- ))
+ )
# unconfigure bsm processing on f1 on f1-i1-eth2
step("unconfigure bsm processing on f1 in f1-i1-eth2, will drop bsm")
@@ -989,20 +997,21 @@ def test_int_bsm_config_p1(request):
# Verify bsr state in i1
step("Verify if b1 is not chosen as BSR in i1")
result = verify_pim_bsr(tgen, topo, "i1", bsr_ip, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "b1 is chosen as BSR in i1 \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "b1 is chosen as BSR in i1 \n Error: {}".format(
tc_name, result
- ))
+ )
# check if mroute still not installed because of rp not available
step("check if mroute still not installed because of rp not available")
result = verify_ip_mroutes(
tgen, "i1", src_addr, GROUP_ADDRESS, iif, oil, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "mroute installed but rp not available \n Error: {}".format(
- tc_name, result
- ))
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "mroute installed but rp not available \n Error: {}".format(tc_name, result)
+ )
# configure bsm processing on i1 on f1-i1-eth2
step("configure bsm processing on f1 in f1-i1-eth2, will accept bsm")
@@ -1464,10 +1473,11 @@ def test_BSM_timeout_p0(request):
tgen, topo, "f1", group, rp_source="BSR", expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "bsr has not aged out in f1 \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "bsr has not aged out in f1 \n Error: {}".format(
tc_name, result
- ))
+ )
# Verify RP mapping removed after hold timer expires
group = "225.1.1.1/32"
@@ -1491,20 +1501,23 @@ def test_BSM_timeout_p0(request):
result = verify_join_state_and_timer(
tgen, dut, iif, src_addr, GROUP_ADDRESS, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"join state is up and join timer is running in l1 \n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
# Verify ip mroute is not installed
step("Verify mroute not installed in l1")
result = verify_ip_mroutes(
tgen, dut, src_addr, GROUP_ADDRESS, iif, oil, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "mroute installed in l1 \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "mroute installed in l1 \n Error: {}".format(
tc_name, result
- ))
+ )
step("clear BSM database before moving to next case")
clear_bsrp_data(tgen, topo)
@@ -1657,10 +1670,11 @@ def test_iif_join_state_p0(request):
result = verify_ip_mroutes(
tgen, dut, src_addr, GROUP_ADDRESS, iif, oil, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "mroute installed in l1 \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "mroute installed in l1 \n Error: {}".format(
tc_name, result
- ))
+ )
# Add back route for RP to make it reachable
step("Add back route for RP to make it reachable")
diff --git a/tests/topotests/multicast-pim-bsm-topo2/test_mcast_pim_bsmp_02.py b/tests/topotests/multicast-pim-bsm-topo2/test_mcast_pim_bsmp_02.py
index 5fc5e52518..199746d5f6 100644
--- a/tests/topotests/multicast-pim-bsm-topo2/test_mcast_pim_bsmp_02.py
+++ b/tests/topotests/multicast-pim-bsm-topo2/test_mcast_pim_bsmp_02.py
@@ -104,6 +104,10 @@ from lib.pim import (
from lib.topolog import logger
from lib.topojson import build_topo_from_json, build_config_from_json
+
+pytestmark = [pytest.mark.pimd]
+
+
# Reading the data from JSON File for topology creation
jsonFile = "{}/mcast_pim_bsmp_02.json".format(CWD)
try:
@@ -454,10 +458,11 @@ def test_starg_mroute_p0(request):
result = verify_ip_mroutes(
tgen, dut, src_addr, GROUP_ADDRESS, iif, oil, wait=20, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "mroute installed in l1 \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "mroute installed in l1 \n Error: {}".format(
tc_name, result
- ))
+ )
# Send BSM again to configure rp
step("Add back RP by sending BSM from b1")
@@ -807,10 +812,11 @@ def test_BSR_election_p0(request):
# Verify bsr state in FHR
step("Verify if b2 is not chosen as bsr in f1")
result = verify_pim_bsr(tgen, topo, "f1", bsr_ip2, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "b2 is chosen as bsr in f1 \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "b2 is chosen as bsr in f1 \n Error: {}".format(
tc_name, result
- ))
+ )
# Verify if b1 is still chosen as bsr
step("Verify if b1 is still chosen as bsr in f1")
diff --git a/tests/topotests/multicast-pim-sm-topo3/test_multicast_pim_sm_topo3.py b/tests/topotests/multicast-pim-sm-topo3/test_multicast_pim_sm_topo3.py
index 1c22654541..33f476de44 100755
--- a/tests/topotests/multicast-pim-sm-topo3/test_multicast_pim_sm_topo3.py
+++ b/tests/topotests/multicast-pim-sm-topo3/test_multicast_pim_sm_topo3.py
@@ -3487,11 +3487,11 @@ def test_prune_sent_to_LHR_and_FHR_when_PIMnbr_down_p2(request):
IGMP_JOIN_RANGE_1,
expected=False,
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"upstream is still present after shut the link from "
- "FHR to RP from RP node \n Error: {}".format(
- tc_name, result
- ))
+ "FHR to RP from RP node \n Error: {}".format(tc_name, result)
+ )
step(" No shut the link from FHR to RP from RP node")
@@ -3638,11 +3638,11 @@ def test_prune_sent_to_LHR_and_FHR_when_PIMnbr_down_p2(request):
IGMP_JOIN_RANGE_1,
expected=False,
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"upstream is still present after shut the link from "
- "FHR to RP from FHR node \n Error: {}".format(
- tc_name, result
- ))
+ "FHR to RP from FHR node \n Error: {}".format(tc_name, result)
+ )
step(" No shut the link from FHR to RP from FHR node")
diff --git a/tests/topotests/multicast-pim-sm-topo3/test_multicast_pim_sm_topo4.py b/tests/topotests/multicast-pim-sm-topo3/test_multicast_pim_sm_topo4.py
index 68b7849c2b..1081b764ac 100755
--- a/tests/topotests/multicast-pim-sm-topo3/test_multicast_pim_sm_topo4.py
+++ b/tests/topotests/multicast-pim-sm-topo3/test_multicast_pim_sm_topo4.py
@@ -490,10 +490,12 @@ def test_mroute_when_RP_reachable_default_route_p2(request):
data["oil"],
expected=False,
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"mroutes(S,G) are present after delete of static routes on c1 \n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
result = verify_upstream_iif(
tgen,
@@ -503,10 +505,12 @@ def test_mroute_when_RP_reachable_default_route_p2(request):
IGMP_JOIN_RANGE_1,
expected=False,
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"upstream is present after delete of static routes on c1 \n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
for data in input_dict_starg:
result = verify_ip_mroutes(
@@ -518,10 +522,12 @@ def test_mroute_when_RP_reachable_default_route_p2(request):
data["oil"],
expected=False,
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"mroutes(*,G) are present after delete of static routes on c1 \n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
result = verify_upstream_iif(
tgen,
@@ -531,10 +537,12 @@ def test_mroute_when_RP_reachable_default_route_p2(request):
IGMP_JOIN_RANGE_1,
expected=False,
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"upstream is present after delete of static routes on c1 \n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
step("Configure default routes on c2")
@@ -557,10 +565,12 @@ def test_mroute_when_RP_reachable_default_route_p2(request):
result = verify_pim_rp_info(
tgen, topo, dut, GROUP_RANGE_1, "Unknown", rp_address, SOURCE, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"RP info is unknown after removing static route from c2 \n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
step("Verify (s,g) populated after adding default route ")
@@ -787,10 +797,11 @@ def test_mroute_with_RP_default_route_all_nodes_p2(request):
data["oil"],
expected=False,
)
- assert result is not True, ("Testcase {} : Failed \n "
- "mroutes are still present \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "mroutes are still present \n Error: {}".format(
tc_name, result
- ))
+ )
result = verify_upstream_iif(
tgen,
@@ -800,10 +811,11 @@ def test_mroute_with_RP_default_route_all_nodes_p2(request):
IGMP_JOIN_RANGE_1,
expected=False,
)
- assert result is not True, ("Testcase {} : Failed \n "
- "upstream is still present \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "upstream is still present \n Error: {}".format(
tc_name, result
- ))
+ )
step("Configure default routes on all the nodes")
@@ -840,10 +852,12 @@ def test_mroute_with_RP_default_route_all_nodes_p2(request):
result = verify_pim_rp_info(
tgen, topo, dut, GROUP_RANGE_1, "Unknown", rp_address, SOURCE, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"RP info is unknown after removing static route from c2 \n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
step("Verify (s,g) populated after adding default route ")
diff --git a/tests/topotests/multicast-pim-static-rp-topo1/test_multicast_pim_static_rp.py b/tests/topotests/multicast-pim-static-rp-topo1/test_multicast_pim_static_rp.py
index 1317ec67b4..e90230eb3b 100755
--- a/tests/topotests/multicast-pim-static-rp-topo1/test_multicast_pim_static_rp.py
+++ b/tests/topotests/multicast-pim-static-rp-topo1/test_multicast_pim_static_rp.py
@@ -423,10 +423,12 @@ def test_add_delete_static_RP_p0(request):
dut = "r1"
interface = "r1-r0-eth0"
result = verify_igmp_groups(tgen, dut, interface, GROUP_ADDRESS, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r1: igmp group present without any IGMP join \n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
step("r1: Verify show ip pim interface traffic without any IGMP join")
state_dict = {"r1": {"r1-r2-eth1": ["pruneTx"]}}
@@ -492,26 +494,29 @@ def test_add_delete_static_RP_p0(request):
result = verify_pim_rp_info(
tgen, topo, dut, GROUP_RANGE_ALL, iif, rp_address, SOURCE, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: RP info present \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: RP info present \n Error: {}".format(
tc_name, result
- ))
+ )
step("r1: Verify upstream IIF interface")
result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: upstream IIF interface present \n Error: {}".format(
- tc_name, result
- ))
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r1: upstream IIF interface present \n Error: {}".format(tc_name, result)
+ )
step("r1: Verify upstream join state and join timer")
result = verify_join_state_and_timer(
tgen, dut, iif, STAR, GROUP_ADDRESS, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r1: upstream join state is up and join timer is running \n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
step("r1: Verify PIM state")
result = verify_pim_state(tgen, dut, iif, oif, GROUP_ADDRESS, expected=False)
@@ -521,10 +526,11 @@ def test_add_delete_static_RP_p0(request):
step("r1: Verify ip mroutes")
result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: mroutes are still present \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: mroutes are still present \n Error: {}".format(
tc_name, result
- ))
+ )
step("r1: Verify show ip pim interface traffic without any IGMP join")
state_after = verify_pim_interface_traffic(tgen, state_dict)
@@ -681,10 +687,12 @@ def test_SPT_RPT_path_same_p1(request):
result = verify_join_state_and_timer(
tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r3: (S, G) upstream join state is up and join timer is running\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
step("r3: Verify (S, G) ip mroutes")
oif = "r3-r2-eth1"
@@ -811,17 +819,19 @@ def test_not_reachable_static_RP_p0(request):
"using show ip pim state"
)
result = verify_pim_state(tgen, dut, iif, oif, GROUP_ADDRESS, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"OIL is not same and IIF is not cleared on R1 \n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
step("r1: upstream IIF should be unknown , verify using show ip pim" "upstream")
result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: upstream IIF is not unknown \n Error: {}".format(
- tc_name, result
- ))
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r1: upstream IIF is not unknown \n Error: {}".format(tc_name, result)
+ )
step(
"r1: join state should not be joined and join timer should stop,"
@@ -830,10 +840,12 @@ def test_not_reachable_static_RP_p0(request):
result = verify_join_state_and_timer(
tgen, dut, iif, STAR, GROUP_ADDRESS, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r1: join state is joined and timer is not stopped \n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
step(
"r1: (*,G) prune is sent towards the RP interface, verify using"
@@ -850,10 +862,12 @@ def test_not_reachable_static_RP_p0(request):
step("r1: (*, G) cleared from mroute table using show ip mroute")
result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r1: (*, G) are not cleared from mroute table \n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
logger.info("Expected behavior: {}".format(result))
# Uncomment next line for debugging
@@ -920,10 +934,11 @@ def test_add_RP_after_join_received_p1(request):
result = verify_pim_rp_info(
tgen, topo, dut, GROUP_RANGE_ALL, iif, rp_address, SOURCE, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: rp-info is present \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: rp-info is present \n Error: {}".format(
tc_name, result
- ))
+ )
step("joinTx value before join sent")
state_dict = {"r1": {"r1-r2-eth1": ["joinTx"]}}
@@ -944,34 +959,38 @@ def test_add_RP_after_join_received_p1(request):
step("r1: Verify upstream IIF interface")
result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: upstream IFF interface is present \n Error: {}".format(
- tc_name, result
- ))
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r1: upstream IFF interface is present \n Error: {}".format(tc_name, result)
+ )
step("r1: Verify upstream join state and join timer")
result = verify_join_state_and_timer(
tgen, dut, iif, STAR, GROUP_ADDRESS, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r1: upstream join state is joined and timer is running \n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
step("r1: Verify PIM state")
result = verify_pim_state(tgen, dut, iif, oif, GROUP_ADDRESS, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: PIM state is up\n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: PIM state is up\n Error: {}".format(
tc_name, result
- ))
+ )
step("r1: Verify ip mroutes")
result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: mroutes are still present\n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: mroutes are still present\n Error: {}".format(
tc_name, result
- ))
+ )
step("r1: Configure static RP")
input_dict = {
@@ -1095,33 +1114,37 @@ def test_reachable_static_RP_after_join_p0(request):
step("r1 : Verify upstream IIF interface")
iif = "r1-r2-eth1"
result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: upstream IIF interface is present\n Error: {}".format(
- tc_name, result
- ))
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r1: upstream IIF interface is present\n Error: {}".format(tc_name, result)
+ )
step("r1 : Verify upstream join state and join timer")
result = verify_join_state_and_timer(
tgen, dut, iif, STAR, GROUP_ADDRESS, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r1: upstream join state is joined and timer is running\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
step("r1 : Verify PIM state")
result = verify_pim_state(tgen, dut, iif, oif, GROUP_ADDRESS, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: PIM state is up\n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: PIM state is up\n Error: {}".format(
tc_name, result
- ))
+ )
step("r1 : Verify ip mroutes")
result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: mroutes are still present\n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: mroutes are still present\n Error: {}".format(
tc_name, result
- ))
+ )
step("r1: Make RP reachable")
intf = "r1-r2-eth1"
@@ -1362,10 +1385,12 @@ def test_send_join_on_higher_preffered_rp_p1(request):
result = verify_pim_rp_info(
tgen, topo, dut, GROUP_RANGE, oif, rp_address_2, SOURCE, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r1: rp-info is present for group 225.1.1.1 \n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
step(
"r1 : Verify RPF interface updated in mroute when higher preferred"
@@ -1619,11 +1644,11 @@ def test_RP_configured_as_LHR_1_p1(request):
result = verify_join_state_and_timer(
tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r3: (S, G) upstream join state is joined and join"
- " timer is running \n Error: {}".format(
- tc_name, result
- ))
+ " timer is running \n Error: {}".format(tc_name, result)
+ )
step("r3: Verify (S, G) ip mroutes")
oif = "r3-r1-eth0"
@@ -1828,10 +1853,12 @@ def test_RP_configured_as_LHR_2_p1(request):
result = verify_join_state_and_timer(
tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
step("r3: Verify (S, G) ip mroutes")
oif = "r3-r1-eth0"
@@ -2036,10 +2063,12 @@ def test_RP_configured_as_FHR_1_p1(request):
result = verify_join_state_and_timer(
tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
step("r3: Verify (S, G) ip mroutes")
oif = "r3-r1-eth0"
@@ -2245,10 +2274,12 @@ def test_RP_configured_as_FHR_2_p2(request):
result = verify_join_state_and_timer(
tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
step("r3: Verify (S, G) ip mroutes")
oif = "r3-r1-eth0"
@@ -2372,10 +2403,12 @@ def test_SPT_RPT_path_different_p1(request):
result = verify_join_state_and_timer(
tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
step("r3: Verify (S, G) ip mroutes")
oif = "r3-r1-eth0"
@@ -2394,10 +2427,12 @@ def test_SPT_RPT_path_different_p1(request):
result = verify_join_state_and_timer(
tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r2: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
step("r2: Verify (S, G) ip mroutes")
oif = "none"
@@ -2623,10 +2658,12 @@ def test_restart_pimd_process_p2(request):
result = verify_join_state_and_timer(
tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
step("r3: Verify (S, G) ip mroutes")
oif = "r3-r1-eth0"
@@ -2791,10 +2828,12 @@ def test_multiple_groups_same_RP_address_p2(request):
result = verify_join_state_and_timer(
tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
step("r3: Verify (S, G) ip mroutes")
oif = "r3-r1-eth0"
@@ -2813,10 +2852,12 @@ def test_multiple_groups_same_RP_address_p2(request):
result = verify_join_state_and_timer(
tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r2: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
step("r2: Verify (S, G) ip mroutes")
oif = "none"
@@ -2932,10 +2973,12 @@ def test_multiple_groups_same_RP_address_p2(request):
result = verify_join_state_and_timer(
tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r2: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
step("r2: Verify (S, G) ip mroutes")
oif = "none"
@@ -2952,10 +2995,12 @@ def test_multiple_groups_same_RP_address_p2(request):
result = verify_join_state_and_timer(
tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
step("r3: Verify (S, G) ip mroutes")
oif = "r3-r1-eth0"
@@ -3132,10 +3177,12 @@ def test_multiple_groups_different_RP_address_p2(request):
result = verify_join_state_and_timer(
tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r2: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
step("r2: Verify (S, G) ip mroutes")
oif = "none"
@@ -3154,10 +3201,12 @@ def test_multiple_groups_different_RP_address_p2(request):
result = verify_join_state_and_timer(
tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
step("r3: Verify (S, G) ip mroutes")
oif = "r3-r1-eth0"
@@ -3224,10 +3273,12 @@ def test_multiple_groups_different_RP_address_p2(request):
result = verify_join_state_and_timer(
tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r4: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
step("r4: Verify (S, G) ip mroutes")
oif = "none"
@@ -3399,10 +3450,12 @@ def test_multiple_groups_different_RP_address_p2(request):
result = verify_join_state_and_timer(
tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r2: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
step("r2: Verify (S, G) ip mroutes")
oif = "none"
@@ -3421,10 +3474,12 @@ def test_multiple_groups_different_RP_address_p2(request):
result = verify_join_state_and_timer(
tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
step("r3: Verify (S, G) ip mroutes")
oif = "r3-r1-eth0"
@@ -3491,10 +3546,12 @@ def test_multiple_groups_different_RP_address_p2(request):
result = verify_join_state_and_timer(
tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r4: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
step("r4: Verify (S, G) ip mroutes")
oif = "none"
@@ -3513,10 +3570,12 @@ def test_multiple_groups_different_RP_address_p2(request):
result = verify_join_state_and_timer(
tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
step("r3: Verify (S, G) ip mroutes")
oif = "r3-r1-eth0"
@@ -3643,30 +3702,36 @@ def test_shutdown_primary_path_p1(request):
iif = "r1-r3-eth2"
oif = "r1-r0-eth0"
result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r1: (*,G) mroutes are not cleared after shut of R1 to R3 link\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
step("r2: Verify (*, G) ip mroutes")
dut = "r2"
iif = "lo"
oif = "r2-r3-eth1"
result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r2: (*,G) mroutes are not cleared after shut of R1 to R3 link\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
step("r3: Verify (*, G) ip mroutes")
dut = "r3"
iif = "r3-r2-eth1"
oif = "r3-r1-eth0"
result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r3: (*,G) mroutes are not cleared after shut of R1 to R3 link\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
step("r3: No shutdown the link from R1 to R3 from R3 node")
dut = "r3"
@@ -3826,20 +3891,24 @@ def test_delete_RP_shut_noshut_upstream_interface_p1(request):
iif = "r1-r2-eth1"
oif = "r1-r0-eth0"
result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r1: (*,G) mroutes are not cleared after shut of R1 to R0 link\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
step("r2: Verify (*, G) ip mroutes cleared")
dut = "r2"
iif = "lo"
oif = "r2-r1-eth0"
result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r2: (*,G) mroutes are not cleared after shut of R1 to R0 link\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
write_test_footer(tc_name)
@@ -3949,20 +4018,24 @@ def test_delete_RP_shut_noshut_RP_interface_p1(request):
iif = "r1-r2-eth1"
oif = "r1-r0-eth0"
result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r1: (*,G) mroutes are not cleared after shut of R1 to R2 and R3 link\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
step("r2: Verify (*, G) ip mroutes cleared")
dut = "r2"
iif = "lo"
oif = "r2-r1-eth0"
result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r2: (*,G) mroutes are not cleared after shut of R1 to R2 and R3 link\n Error: {}".format(
- tc_name, result
- ))
+ tc_name, result
+ )
+ )
write_test_footer(tc_name)
diff --git a/tests/topotests/nhrp-topo/r1/nhrp4_cache.json b/tests/topotests/nhrp-topo/r1/nhrp4_cache.json
new file mode 100644
index 0000000000..6426a939be
--- /dev/null
+++ b/tests/topotests/nhrp-topo/r1/nhrp4_cache.json
@@ -0,0 +1,29 @@
+{
+ "attr":{
+ "entriesCount":2
+ },
+ "table":[
+ {
+ "interface":"r1-gre0",
+ "type":"nhs",
+ "protocol":"10.255.255.2",
+ "nbma":"10.2.1.2",
+ "claimed_nbma":"10.2.1.2",
+ "used":false,
+ "timeout":true,
+ "auth":false,
+ "identity":""
+ },
+ {
+ "interface":"r1-gre0",
+ "type":"local",
+ "protocol":"10.255.255.1",
+ "nbma":"10.1.1.1",
+ "claimed_nbma":"10.1.1.1",
+ "used":false,
+ "timeout":false,
+ "auth":false,
+ "identity":"-"
+ }
+ ]
+}
diff --git a/tests/topotests/nhrp-topo/r1/nhrp_route4.json b/tests/topotests/nhrp-topo/r1/nhrp_route4.json
new file mode 100644
index 0000000000..68b5a6ece2
--- /dev/null
+++ b/tests/topotests/nhrp-topo/r1/nhrp_route4.json
@@ -0,0 +1,25 @@
+{
+ "10.255.255.2\/32":[
+ {
+ "prefix":"10.255.255.2\/32",
+ "protocol":"nhrp",
+ "vrfId":0,
+ "vrfName":"default",
+ "selected":true,
+ "destSelected":true,
+ "distance":10,
+ "metric":0,
+ "installed":true,
+ "internalNextHopNum":1,
+ "internalNextHopActiveNum":1,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"r1-gre0",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/nhrp-topo/r1/nhrpd.conf b/tests/topotests/nhrp-topo/r1/nhrpd.conf
new file mode 100644
index 0000000000..04114bdbe6
--- /dev/null
+++ b/tests/topotests/nhrp-topo/r1/nhrpd.conf
@@ -0,0 +1,10 @@
+log stdout debugging
+debug nhrp all
+interface r1-gre0
+ ip nhrp holdtime 500
+ ip nhrp shortcut
+ ip nhrp network-id 42
+ ip nhrp nhs dynamic nbma 10.2.1.2
+ ip nhrp registration no-unique
+ tunnel source r1-eth0
+exit
diff --git a/tests/topotests/nhrp-topo/r1/zebra.conf b/tests/topotests/nhrp-topo/r1/zebra.conf
new file mode 100644
index 0000000000..b45670fcb2
--- /dev/null
+++ b/tests/topotests/nhrp-topo/r1/zebra.conf
@@ -0,0 +1,12 @@
+interface r1-eth0
+ ip address 10.1.1.1/24
+!
+ip route 10.2.1.0/24 10.1.1.3
+interface r1-gre0
+ ip address 10.255.255.1/32
+ no link-detect
+ ipv6 nd suppress-ra
+exit
+interface r1-eth1
+ ip address 192.168.1.1/24
+!
diff --git a/tests/topotests/nhrp-topo/r2/nhrp4_cache.json b/tests/topotests/nhrp-topo/r2/nhrp4_cache.json
new file mode 100644
index 0000000000..34558e0c28
--- /dev/null
+++ b/tests/topotests/nhrp-topo/r2/nhrp4_cache.json
@@ -0,0 +1,29 @@
+{
+ "attr":{
+ "entriesCount":2
+ },
+ "table":[
+ {
+ "interface":"r2-gre0",
+ "type":"local",
+ "protocol":"10.255.255.2",
+ "nbma":"10.2.1.2",
+ "claimed_nbma":"10.2.1.2",
+ "used":false,
+ "timeout":false,
+ "auth":false,
+ "identity":"-"
+ },
+ {
+ "interface":"r2-gre0",
+ "type":"dynamic",
+ "protocol":"10.255.255.1",
+ "nbma":"10.1.1.1",
+ "claimed_nbma":"10.1.1.1",
+ "used":false,
+ "timeout":true,
+ "auth":false,
+ "identity":""
+ }
+ ]
+}
diff --git a/tests/topotests/nhrp-topo/r2/nhrp_route4.json b/tests/topotests/nhrp-topo/r2/nhrp_route4.json
new file mode 100644
index 0000000000..7393cba893
--- /dev/null
+++ b/tests/topotests/nhrp-topo/r2/nhrp_route4.json
@@ -0,0 +1,25 @@
+{
+ "10.255.255.1\/32":[
+ {
+ "prefix":"10.255.255.1\/32",
+ "protocol":"nhrp",
+ "vrfId":0,
+ "vrfName":"default",
+ "selected":true,
+ "destSelected":true,
+ "distance":10,
+ "metric":0,
+ "installed":true,
+ "internalNextHopNum":1,
+ "internalNextHopActiveNum":1,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"r2-gre0",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/nhrp-topo/r2/nhrpd.conf b/tests/topotests/nhrp-topo/r2/nhrpd.conf
new file mode 100644
index 0000000000..e4f6fb7445
--- /dev/null
+++ b/tests/topotests/nhrp-topo/r2/nhrpd.conf
@@ -0,0 +1,10 @@
+debug nhrp all
+log stdout debugging
+nhrp nflog-group 1
+interface r2-gre0
+ ip nhrp holdtime 500
+ ip nhrp redirect
+ ip nhrp network-id 42
+ ip nhrp registration no-unique
+ tunnel source r2-eth0
+exit
diff --git a/tests/topotests/nhrp-topo/r2/zebra.conf b/tests/topotests/nhrp-topo/r2/zebra.conf
new file mode 100644
index 0000000000..9f40d4d72e
--- /dev/null
+++ b/tests/topotests/nhrp-topo/r2/zebra.conf
@@ -0,0 +1,12 @@
+interface r2-eth0
+ ip address 10.2.1.2/24
+!
+ip route 10.1.1.0/24 10.2.1.3
+interface r2-gre0
+ ip address 10.255.255.2/32
+ no link-detect
+ ipv6 nd suppress-ra
+!
+interface r2-eth1
+ ip address 192.168.2.2/24
+!
diff --git a/tests/topotests/nhrp-topo/r3/zebra.conf b/tests/topotests/nhrp-topo/r3/zebra.conf
new file mode 100644
index 0000000000..6d3d267978
--- /dev/null
+++ b/tests/topotests/nhrp-topo/r3/zebra.conf
@@ -0,0 +1,11 @@
+debug zebra kernel
+debug zebra rib
+debug zebra events
+debug zebra packet
+ip forwarding
+interface r3-eth0
+ ip address 10.1.1.3/24
+!
+interface r3-eth1
+ ip address 10.2.1.3/24
+exit
diff --git a/tests/topotests/nhrp-topo/test_nhrp_topo.dot b/tests/topotests/nhrp-topo/test_nhrp_topo.dot
new file mode 100644
index 0000000000..6b68fb398f
--- /dev/null
+++ b/tests/topotests/nhrp-topo/test_nhrp_topo.dot
@@ -0,0 +1,73 @@
+## Color coding:
+#########################
+## Main FRR: #f08080 red
+## Switches: #d0e0d0 gray
+## RIP: #19e3d9 Cyan
+## RIPng: #fcb314 dark yellow
+## OSPFv2: #32b835 Green
+## OSPFv3: #19e3d9 Cyan
+## ISIS IPv4 #fcb314 dark yellow
+## ISIS IPv6 #9a81ec purple
+## BGP IPv4 #eee3d3 beige
+## BGP IPv6 #fdff00 yellow
+##### Colors (see http://www.color-hex.com/)
+
+graph template {
+ label="bfd-topo2";
+
+ # Routers
+ r1 [
+ shape=doubleoctagon,
+ label="r1",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+ r2 [
+ shape=doubleoctagon
+ label="r2",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+ r3 [
+ shape=doubleoctagon
+ label="r3",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+ r4 [
+ shape=doubleoctagon
+ label="r4",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+
+ # Switches
+ sw1 [
+ shape=oval,
+ label="sw1\n2001:db8:1::/64",
+ fillcolor="#d0e0d0",
+ style=filled,
+ ];
+ sw2 [
+ shape=oval,
+ label="sw2\n10.0.3.0/24",
+ fillcolor="#d0e0d0",
+ style=filled,
+ ];
+ sw3 [
+ shape=oval,
+ label="sw3\n2001:db8:4::/64",
+ fillcolor="#d0e0d0",
+ style=filled,
+ ];
+
+ # Connections
+ r1 -- sw1 [label="eth0"];
+ r2 -- sw1 [label="eth0"];
+
+ r2 -- sw2 [label="eth1"];
+ r3 -- sw2 [label="eth0"];
+
+ r2 -- sw3 [label="eth2"];
+ r4 -- sw3 [label="eth0"];
+}
diff --git a/tests/topotests/nhrp-topo/test_nhrp_topo.py b/tests/topotests/nhrp-topo/test_nhrp_topo.py
new file mode 100644
index 0000000000..1687961f34
--- /dev/null
+++ b/tests/topotests/nhrp-topo/test_nhrp_topo.py
@@ -0,0 +1,221 @@
+#!/usr/bin/env python
+
+#
+# test_nhrp_topo.py
+# Part of NetDEF Topology Tests
+#
+# Copyright (c) 2019 by
+# Network Device Education Foundation, Inc. ("NetDEF")
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+test_nhrp_topo.py: Test the FRR/Quagga NHRP daemon
+"""
+
+import os
+import sys
+import json
+from functools import partial
+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
+
+# Required to instantiate the topology builder class.
+from mininet.topo import Topo
+
+
+class NHRPTopo(Topo):
+ "Test topology builder"
+ def build(self, *_args, **_opts):
+ "Build function"
+ tgen = get_topogen(self)
+
+ # Create 3 routers.
+ for routern in range(1, 4):
+ tgen.add_router('r{}'.format(routern))
+
+ switch = tgen.add_switch('s1')
+ switch.add_link(tgen.gears['r1'])
+ switch.add_link(tgen.gears['r3'])
+ switch = tgen.add_switch('s2')
+ switch.add_link(tgen.gears['r2'])
+ switch.add_link(tgen.gears['r3'])
+ switch = tgen.add_switch('s3')
+ switch.add_link(tgen.gears['r2'])
+ switch = tgen.add_switch('s4')
+ switch.add_link(tgen.gears['r1'])
+
+
+def _populate_iface():
+ tgen = get_topogen()
+ cmds_tot_hub = ['ip tunnel add {0}-gre0 mode gre ttl 64 key 42 dev {0}-eth0 local 10.2.1.{1} remote 0.0.0.0',
+ 'ip link set dev {0}-gre0 up',
+ 'echo 0 > /proc/sys/net/ipv4/ip_forward_use_pmtu',
+ 'echo 1 > /proc/sys/net/ipv6/conf/{0}-eth0/disable_ipv6',
+ 'echo 1 > /proc/sys/net/ipv6/conf/{0}-gre0/disable_ipv6']
+
+ cmds_tot = ['ip tunnel add {0}-gre0 mode gre ttl 64 key 42 dev {0}-eth0 local 10.1.1.{1} remote 0.0.0.0',
+ 'ip link set dev {0}-gre0 up',
+ 'echo 0 > /proc/sys/net/ipv4/ip_forward_use_pmtu',
+ 'echo 1 > /proc/sys/net/ipv6/conf/{0}-eth0/disable_ipv6',
+ 'echo 1 > /proc/sys/net/ipv6/conf/{0}-gre0/disable_ipv6']
+
+ for cmd in cmds_tot_hub:
+ input = cmd.format('r2', '2')
+ logger.info('input: '+cmd)
+ output = tgen.net['r2'].cmd(cmd.format('r2', '2'))
+ logger.info('output: '+output);
+
+ for cmd in cmds_tot:
+ input = cmd.format('r1', '1')
+ logger.info('input: '+cmd)
+ output = tgen.net['r1'].cmd(cmd.format('r1', '1'))
+ logger.info('output: '+output);
+
+
+def setup_module(mod):
+ "Sets up the pytest environment"
+ tgen = Topogen(NHRPTopo, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+ _populate_iface()
+
+ for rname, router in router_list.iteritems():
+ router.load_config(
+ TopoRouter.RD_ZEBRA,
+ os.path.join(CWD, '{}/zebra.conf'.format(rname)),
+ )
+ if rname in ('r1', 'r2'):
+ router.load_config(
+ TopoRouter.RD_NHRP,
+ os.path.join(CWD, '{}/nhrpd.conf'.format(rname))
+ )
+
+ # Initialize all routers.
+ logger.info('Launching BGP, NHRP')
+ for name in router_list:
+ router = tgen.gears[name]
+ router.start()
+
+
+def teardown_module(_mod):
+ "Teardown the pytest environment"
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_protocols_convergence():
+ """
+ Assert that all protocols have converged before checking for the NHRP
+ statuses as they depend on it.
+ """
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Check IPv4 routing tables.
+ logger.info("Checking NHRP cache and IPv4 routes for convergence")
+ router_list = tgen.routers()
+
+ for rname, router in router_list.iteritems():
+ if rname == 'r3':
+ continue
+
+ json_file = '{}/{}/nhrp4_cache.json'.format(CWD, router.name)
+ if not os.path.isfile(json_file):
+ logger.info('skipping file {}'.format(json_file))
+ continue
+
+ expected = json.loads(open(json_file).read())
+ test_func = partial(topotest.router_json_cmp,
+ router, 'show ip nhrp cache json', expected)
+ _, result = topotest.run_and_expect(test_func, None, count=40,
+ wait=0.5)
+
+ output = router.vtysh_cmd('show ip nhrp cache')
+ logger.info(output)
+
+ assertmsg = '"{}" JSON output mismatches'.format(router.name)
+ assert result is None, assertmsg
+
+ for rname, router in router_list.iteritems():
+ if rname == 'r3':
+ continue
+
+ json_file = '{}/{}/nhrp_route4.json'.format(CWD, router.name)
+ if not os.path.isfile(json_file):
+ logger.info('skipping file {}'.format(json_file))
+ continue
+
+ expected = json.loads(open(json_file).read())
+ test_func = partial(topotest.router_json_cmp,
+ router, 'show ip route nhrp json', expected)
+ _, result = topotest.run_and_expect(test_func, None, count=40,
+ wait=0.5)
+
+ output = router.vtysh_cmd('show ip route nhrp')
+ logger.info(output)
+
+ assertmsg = '"{}" JSON output mismatches'.format(router.name)
+ assert result is None, assertmsg
+
+ for rname, router in router_list.iteritems():
+ if rname == 'r3':
+ continue
+ logger.info('Dump neighbor information on {}-gre0'.format(rname))
+ output = router.run('ip neigh show')
+ logger.info(output)
+
+
+def test_nhrp_connection():
+ "Assert that the NHRP peers can find themselves."
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ pingrouter = tgen.gears['r1']
+ logger.info('Check Ping IPv4 from R1 to R2 = 10.255.255.2)')
+ output = pingrouter.run('ping 10.255.255.2 -f -c 1000')
+ logger.info(output)
+ if '1000 packets transmitted, 1000 received' not in output:
+ assertmsg = 'expected ping IPv4 from R1 to R2 should be ok'
+ assert 0, assertmsg
+ else:
+ logger.info('Check Ping IPv4 from R1 to R2 OK')
+
+
+def test_memory_leak():
+ "Run the memory leak test and report results."
+ tgen = get_topogen()
+ if not tgen.is_memleak_enabled():
+ pytest.skip('Memory leak test/report is disabled')
+
+ tgen.report_memory_leaks()
+
+
+if __name__ == '__main__':
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/ospf-sr-topo1/test_ospf_sr_topo1.py b/tests/topotests/ospf-sr-topo1/test_ospf_sr_topo1.py
index 57b93c3fd5..b6e5e14830 100644
--- a/tests/topotests/ospf-sr-topo1/test_ospf_sr_topo1.py
+++ b/tests/topotests/ospf-sr-topo1/test_ospf_sr_topo1.py
@@ -86,6 +86,7 @@ from mininet.topo import Topo
pytestmark = [pytest.mark.ospfd]
+
class TemplateTopo(Topo):
"Test topology builder"
@@ -385,9 +386,7 @@ def test_rib_ipv4_step5():
pytest.skip(tgen.errors)
logger.info("Disabling SR on rt6")
- tgen.net["rt6"].cmd(
- 'vtysh -c "conf t" -c "router ospf" -c "no segment-routing on"'
- )
+ tgen.net["rt6"].cmd('vtysh -c "conf t" -c "router ospf" -c "no segment-routing on"')
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
@@ -652,7 +651,7 @@ def test_mpls_lib_step10():
# Expected changes:
# -All commands should be rejected
#
-#def test_ospf_invalid_config_step11():
+# def test_ospf_invalid_config_step11():
# logger.info("Test (step 11): check if invalid configuration is rejected")
# tgen = get_topogen()
#
diff --git a/tests/topotests/ospf-te-topo1/__init__.py b/tests/topotests/ospf-te-topo1/__init__.py
new file mode 100755
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/ospf-te-topo1/__init__.py
diff --git a/tests/topotests/ospf-te-topo1/r1/ospfd.conf b/tests/topotests/ospf-te-topo1/r1/ospfd.conf
new file mode 100644
index 0000000000..312dd2697e
--- /dev/null
+++ b/tests/topotests/ospf-te-topo1/r1/ospfd.conf
@@ -0,0 +1,23 @@
+!
+interface lo
+ ip ospf area 0.0.0.0
+!
+interface r1-eth0
+ ip ospf network point-to-point
+ ip ospf hello-interval 2
+ ip ospf dead-interval 10
+ ip ospf area 0.0.0.0
+!
+interface r1-eth1
+ ip ospf network point-to-point
+ ip ospf hello-interval 2
+ ip ospf dead-interval 10
+ ip ospf area 0.0.0.0
+!
+router ospf
+ ospf router-id 10.0.255.1
+ capability opaque
+ mpls-te on
+ mpls-te router-address 10.0.255.1
+!
+
diff --git a/tests/topotests/ospf-te-topo1/r1/zebra.conf b/tests/topotests/ospf-te-topo1/r1/zebra.conf
new file mode 100644
index 0000000000..7c5dc3ffe0
--- /dev/null
+++ b/tests/topotests/ospf-te-topo1/r1/zebra.conf
@@ -0,0 +1,21 @@
+!
+interface lo
+ ip address 10.0.255.1/32
+!
+interface r1-eth0
+ ip address 10.0.0.1/24
+ link-params
+ metric 20
+ delay 10000
+ ava-bw 1.25e+08
+ enable
+ exit-link-params
+!
+interface r1-eth1
+ ip address 10.0.1.1/24
+ link-params
+ enable
+ exit-link-params
+!
+ip forwarding
+!
diff --git a/tests/topotests/ospf-te-topo1/r2/ospfd.conf b/tests/topotests/ospf-te-topo1/r2/ospfd.conf
new file mode 100644
index 0000000000..e9c3f65bc2
--- /dev/null
+++ b/tests/topotests/ospf-te-topo1/r2/ospfd.conf
@@ -0,0 +1,34 @@
+!
+interface lo
+ ip ospf area 0.0.0.0
+!
+interface r2-eth0
+ ip ospf network point-to-point
+ ip ospf hello-interval 2
+ ip ospf dead-interval 10
+ ip ospf area 0.0.0.0
+!
+interface r2-eth1
+ ip ospf network point-to-point
+ ip ospf hello-interval 2
+ ip ospf dead-interval 10
+ ip ospf area 0.0.0.0
+!
+interface r2-eth2
+ ip ospf network point-to-point
+ ip ospf area 0.0.0.0
+ ip ospf hello-interval 2
+ ip ospf dead-interval 10
+!
+interface r2-eth3
+ ip ospf network point-to-point
+ ip ospf hello-interval 2
+ ip ospf dead-interval 10
+ ip ospf area 0.0.0.0
+!
+router ospf
+ ospf router-id 10.0.255.2
+ capability opaque
+ mpls-te on
+ mpls-te router-address 10.0.255.2
+!
diff --git a/tests/topotests/ospf-te-topo1/r2/zebra.conf b/tests/topotests/ospf-te-topo1/r2/zebra.conf
new file mode 100644
index 0000000000..69e10191f3
--- /dev/null
+++ b/tests/topotests/ospf-te-topo1/r2/zebra.conf
@@ -0,0 +1,33 @@
+!
+interface lo
+ ip address 10.0.255.2/32
+!
+interface r2-eth0
+ ip address 10.0.0.2/24
+ link-params
+ enable
+ exit-link-params
+!
+interface r2-eth1
+ ip address 10.0.1.2/24
+ link-params
+ enable
+ exit-link-params
+!
+interface r2-eth2
+ ip address 10.0.3.2/24
+ link-params
+ enable
+ exit-link-params
+!
+interface r2-eth3
+ ip address 10.0.4.2/24
+ link-params
+ metric 30
+ delay 25000
+ use-bw 1.25e+8
+ enable
+ exit-link-params
+!
+ip forwarding
+!
diff --git a/tests/topotests/ospf-te-topo1/r3/ospfd.conf b/tests/topotests/ospf-te-topo1/r3/ospfd.conf
new file mode 100644
index 0000000000..caa5f1e1eb
--- /dev/null
+++ b/tests/topotests/ospf-te-topo1/r3/ospfd.conf
@@ -0,0 +1,24 @@
+!
+interface lo
+ ip ospf area 0.0.0.0
+!
+interface r3-eth0
+ ip ospf network point-to-point
+ ip ospf area 0.0.0.0
+ ip ospf hello-interval 2
+ ip ospf dead-interval 10
+!
+interface r3-eth1
+ ip ospf network point-to-point
+ ip ospf area 0.0.0.0
+ ip ospf hello-interval 2
+ ip ospf dead-interval 10
+!
+!
+router ospf
+ ospf router-id 10.0.255.3
+ capability opaque
+ mpls-te on
+ mpls-te router-address 10.0.255.3
+ mpls-te inter-as as
+!
diff --git a/tests/topotests/ospf-te-topo1/r3/zebra.conf b/tests/topotests/ospf-te-topo1/r3/zebra.conf
new file mode 100644
index 0000000000..4cf9077085
--- /dev/null
+++ b/tests/topotests/ospf-te-topo1/r3/zebra.conf
@@ -0,0 +1,22 @@
+!
+interface lo
+ ip address 10.0.255.3/32
+!
+interface r3-eth0
+ ip address 10.0.3.1/24
+ link-params
+ enable
+ admin-grp 0x20
+ exit-link-params
+!
+interface r3-eth1
+ ip address 10.0.5.1/24
+ link-params
+ enable
+ metric 10
+ delay 50000
+ neighbor 10.0.255.5 as 65535
+ exit-link-params
+!
+ip forwarding
+!
diff --git a/tests/topotests/ospf-te-topo1/r4/ospfd.conf b/tests/topotests/ospf-te-topo1/r4/ospfd.conf
new file mode 100644
index 0000000000..e454673153
--- /dev/null
+++ b/tests/topotests/ospf-te-topo1/r4/ospfd.conf
@@ -0,0 +1,22 @@
+!
+interface lo
+ ip ospf area 0.0.0.0
+!
+interface r4-eth0
+ ip ospf network point-to-point
+ ip ospf hello-interval 2
+ ip ospf dead-interval 10
+ ip ospf area 0.0.0.0
+!
+!
+router ospf
+ ospf router-id 10.0.255.4
+ capability opaque
+ mpls-te on
+ mpls-te router-address 10.0.255.4
+ segment-routing on
+ segment-routing local-block 5000 5999
+ segment-routing global-block 10000 19999
+ segment-routing node-msd 12
+ segment-routing prefix 10.0.255.4/32 index 400 no-php-flag
+!
diff --git a/tests/topotests/ospf-te-topo1/r4/zebra.conf b/tests/topotests/ospf-te-topo1/r4/zebra.conf
new file mode 100644
index 0000000000..18c003b230
--- /dev/null
+++ b/tests/topotests/ospf-te-topo1/r4/zebra.conf
@@ -0,0 +1,12 @@
+!
+interface lo
+ ip address 10.0.255.4/32
+!
+interface r4-eth0
+ ip address 10.0.4.1/24
+ link-params
+ enable
+ exit-link-params
+!
+ip forwarding
+!
diff --git a/tests/topotests/ospf-te-topo1/reference/ted_step1.json b/tests/topotests/ospf-te-topo1/reference/ted_step1.json
new file mode 100644
index 0000000000..9624292ccd
--- /dev/null
+++ b/tests/topotests/ospf-te-topo1/reference/ted_step1.json
@@ -0,0 +1,577 @@
+{
+ "ted":{
+ "name":"OSPF",
+ "key":1,
+ "verticesCount":5,
+ "edgesCount":9,
+ "subnetsCount":14,
+ "vertices":[
+ {
+ "vertex-id":167837441,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "router-id":"10.0.255.1",
+ "vertex-type":"Standard"
+ },
+ {
+ "vertex-id":167837442,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "router-id":"10.0.255.2",
+ "vertex-type":"Standard"
+ },
+ {
+ "vertex-id":167837443,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "router-id":"10.0.255.3",
+ "vertex-type":"ASBR"
+ },
+ {
+ "vertex-id":167837444,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "router-id":"10.0.255.4",
+ "vertex-type":"Standard",
+ "segment-routing":{
+ "srgb-size":10000,
+ "srgb-lower":10000,
+ "algorithms":[
+ {
+ "0":"SPF"
+ }
+ ],
+ "srlb-size":1000,
+ "srlb-lower":5000,
+ "msd":12
+ }
+ },
+ {
+ "vertex-id":167837445,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "router-id":"10.0.255.5",
+ "vertex-type":"Remote ASBR",
+ "asn":65535
+ }
+ ],
+ "edges":[
+ {
+ "edge-id":167772161,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.1",
+ "local-vertex-id":167837441,
+ "remote-vertex-id":167837442,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":20,
+ "local-address":"10.0.0.1",
+ "remote-address":"10.0.0.2",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ],
+ "delay":10000,
+ "available-bandwidth":125000000.0
+ }
+ },
+ {
+ "edge-id":167772162,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "local-vertex-id":167837442,
+ "remote-vertex-id":167837441,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":0,
+ "local-address":"10.0.0.2",
+ "remote-address":"10.0.0.1",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ]
+ }
+ },
+ {
+ "edge-id":167772417,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.1",
+ "local-vertex-id":167837441,
+ "remote-vertex-id":167837442,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":0,
+ "local-address":"10.0.1.1",
+ "remote-address":"10.0.1.2",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ]
+ }
+ },
+ {
+ "edge-id":167772418,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "local-vertex-id":167837442,
+ "remote-vertex-id":167837441,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":0,
+ "local-address":"10.0.1.2",
+ "remote-address":"10.0.1.1",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ]
+ }
+ },
+ {
+ "edge-id":167772929,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.3",
+ "local-vertex-id":167837443,
+ "remote-vertex-id":167837442,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":0,
+ "admin-group":32,
+ "local-address":"10.0.3.1",
+ "remote-address":"10.0.3.2",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ]
+ }
+ },
+ {
+ "edge-id":167772930,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "local-vertex-id":167837442,
+ "remote-vertex-id":167837443,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":0,
+ "local-address":"10.0.3.2",
+ "remote-address":"10.0.3.1",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ]
+ }
+ },
+ {
+ "edge-id":167773185,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.4",
+ "local-vertex-id":167837444,
+ "remote-vertex-id":167837442,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":0,
+ "local-address":"10.0.4.1",
+ "remote-address":"10.0.4.2",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ]
+ },
+ "segment-routing":[
+ {
+ "adj-sid":5001,
+ "flags":"0x60",
+ "weight":0
+ },
+ {
+ "adj-sid":5000,
+ "flags":"0xe0",
+ "weight":0
+ }
+ ]
+ },
+ {
+ "edge-id":167773186,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "local-vertex-id":167837442,
+ "remote-vertex-id":167837444,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":30,
+ "local-address":"10.0.4.2",
+ "remote-address":"10.0.4.1",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ],
+ "delay":25000,
+ "utilized-bandwidth":125000000.0
+ }
+ },
+ {
+ "edge-id":167773441,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.3",
+ "local-vertex-id":167837443,
+ "remote-vertex-id":167837445,
+ "metric":0,
+ "edge-attributes":{
+ "te-metric":10,
+ "local-address":"10.0.5.1",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ],
+ "remote-asn":65535,
+ "remote-as-address":"10.0.255.5",
+ "delay":50000
+ }
+ }
+ ],
+ "subnets":[
+ {
+ "subnet-id":"10.0.0.1\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.1",
+ "vertex-id":167837441,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.0.2\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "vertex-id":167837442,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.1.1\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.1",
+ "vertex-id":167837441,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.1.2\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "vertex-id":167837442,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.3.1\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.3",
+ "vertex-id":167837443,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.3.2\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "vertex-id":167837442,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.4.1\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.4",
+ "vertex-id":167837444,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.4.2\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "vertex-id":167837442,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.5.1\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.3",
+ "vertex-id":167837443,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.255.1\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.1",
+ "vertex-id":167837441,
+ "metric":0
+ },
+ {
+ "subnet-id":"10.0.255.2\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "vertex-id":167837442,
+ "metric":0
+ },
+ {
+ "subnet-id":"10.0.255.3\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.3",
+ "vertex-id":167837443,
+ "metric":0
+ },
+ {
+ "subnet-id":"10.0.255.4\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.4",
+ "vertex-id":167837444,
+ "metric":0,
+ "segment-routing":{
+ "pref-sid":400,
+ "algo":0,
+ "flags":"0x40"
+ }
+ },
+ {
+ "subnet-id":"10.0.255.5\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.5",
+ "vertex-id":167837445,
+ "metric":10
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-te-topo1/reference/ted_step2.json b/tests/topotests/ospf-te-topo1/reference/ted_step2.json
new file mode 100644
index 0000000000..623d1dc7e0
--- /dev/null
+++ b/tests/topotests/ospf-te-topo1/reference/ted_step2.json
@@ -0,0 +1,477 @@
+{
+ "ted":{
+ "name":"OSPF",
+ "key":1,
+ "verticesCount":5,
+ "edgesCount":7,
+ "subnetsCount":12,
+ "vertices":[
+ {
+ "vertex-id":167837441,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "router-id":"10.0.255.1",
+ "vertex-type":"Standard"
+ },
+ {
+ "vertex-id":167837442,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "router-id":"10.0.255.2",
+ "vertex-type":"Standard"
+ },
+ {
+ "vertex-id":167837443,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "router-id":"10.0.255.3",
+ "vertex-type":"ASBR"
+ },
+ {
+ "vertex-id":167837444,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "router-id":"10.0.255.4",
+ "vertex-type":"Standard",
+ "segment-routing":{
+ "srgb-size":10000,
+ "srgb-lower":10000,
+ "algorithms":[
+ {
+ "0":"SPF"
+ }
+ ],
+ "srlb-size":1000,
+ "srlb-lower":5000,
+ "msd":12
+ }
+ },
+ {
+ "vertex-id":167837445,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "router-id":"10.0.255.5",
+ "vertex-type":"Remote ASBR",
+ "asn":65535
+ }
+ ],
+ "edges":[
+ {
+ "edge-id":167772161,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.1",
+ "local-vertex-id":167837441,
+ "remote-vertex-id":167837442,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":20,
+ "local-address":"10.0.0.1",
+ "remote-address":"10.0.0.2",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ],
+ "delay":10000,
+ "available-bandwidth":125000000.0
+ }
+ },
+ {
+ "edge-id":167772162,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "local-vertex-id":167837442,
+ "remote-vertex-id":167837441,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":0,
+ "local-address":"10.0.0.2",
+ "remote-address":"10.0.0.1",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ]
+ }
+ },
+ {
+ "edge-id":167772929,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.3",
+ "local-vertex-id":167837443,
+ "remote-vertex-id":167837442,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":0,
+ "admin-group":32,
+ "local-address":"10.0.3.1",
+ "remote-address":"10.0.3.2",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ]
+ }
+ },
+ {
+ "edge-id":167772930,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "local-vertex-id":167837442,
+ "remote-vertex-id":167837443,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":0,
+ "local-address":"10.0.3.2",
+ "remote-address":"10.0.3.1",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ]
+ }
+ },
+ {
+ "edge-id":167773185,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.4",
+ "local-vertex-id":167837444,
+ "remote-vertex-id":167837442,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":0,
+ "local-address":"10.0.4.1",
+ "remote-address":"10.0.4.2",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ]
+ },
+ "segment-routing":[
+ {
+ "adj-sid":5001,
+ "flags":"0x60",
+ "weight":0
+ },
+ {
+ "adj-sid":5000,
+ "flags":"0xe0",
+ "weight":0
+ }
+ ]
+ },
+ {
+ "edge-id":167773186,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "local-vertex-id":167837442,
+ "remote-vertex-id":167837444,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":30,
+ "local-address":"10.0.4.2",
+ "remote-address":"10.0.4.1",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ],
+ "delay":25000,
+ "utilized-bandwidth":125000000.0
+ }
+ },
+ {
+ "edge-id":167773441,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.3",
+ "local-vertex-id":167837443,
+ "remote-vertex-id":167837445,
+ "metric":0,
+ "edge-attributes":{
+ "te-metric":10,
+ "local-address":"10.0.5.1",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ],
+ "remote-asn":65535,
+ "remote-as-address":"10.0.255.5",
+ "delay":50000
+ }
+ }
+ ],
+ "subnets":[
+ {
+ "subnet-id":"10.0.0.1\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.1",
+ "vertex-id":167837441,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.0.2\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "vertex-id":167837442,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.3.1\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.3",
+ "vertex-id":167837443,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.3.2\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "vertex-id":167837442,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.4.1\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.4",
+ "vertex-id":167837444,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.4.2\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "vertex-id":167837442,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.5.1\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.3",
+ "vertex-id":167837443,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.255.1\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.1",
+ "vertex-id":167837441,
+ "metric":0
+ },
+ {
+ "subnet-id":"10.0.255.2\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "vertex-id":167837442,
+ "metric":0
+ },
+ {
+ "subnet-id":"10.0.255.3\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.3",
+ "vertex-id":167837443,
+ "metric":0
+ },
+ {
+ "subnet-id":"10.0.255.4\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.4",
+ "vertex-id":167837444,
+ "metric":0,
+ "segment-routing":{
+ "pref-sid":400,
+ "algo":0,
+ "flags":"0x40"
+ }
+ },
+ {
+ "subnet-id":"10.0.255.5\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.5",
+ "vertex-id":167837445,
+ "metric":10
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-te-topo1/reference/ted_step3.json b/tests/topotests/ospf-te-topo1/reference/ted_step3.json
new file mode 100644
index 0000000000..117011a43a
--- /dev/null
+++ b/tests/topotests/ospf-te-topo1/reference/ted_step3.json
@@ -0,0 +1,409 @@
+{
+ "ted":{
+ "name":"OSPF",
+ "key":1,
+ "verticesCount":4,
+ "edgesCount":6,
+ "subnetsCount":10,
+ "vertices":[
+ {
+ "vertex-id":167837441,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "router-id":"10.0.255.1",
+ "vertex-type":"Standard"
+ },
+ {
+ "vertex-id":167837442,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "router-id":"10.0.255.2",
+ "vertex-type":"Standard"
+ },
+ {
+ "vertex-id":167837443,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "router-id":"10.0.255.3",
+ "vertex-type":"ASBR"
+ },
+ {
+ "vertex-id":167837444,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "router-id":"10.0.255.4",
+ "vertex-type":"Standard",
+ "segment-routing":{
+ "srgb-size":10000,
+ "srgb-lower":10000,
+ "algorithms":[
+ {
+ "0":"SPF"
+ }
+ ],
+ "srlb-size":1000,
+ "srlb-lower":5000,
+ "msd":12
+ }
+ }
+ ],
+ "edges":[
+ {
+ "edge-id":167772161,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.1",
+ "local-vertex-id":167837441,
+ "remote-vertex-id":167837442,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":20,
+ "local-address":"10.0.0.1",
+ "remote-address":"10.0.0.2",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ],
+ "delay":10000,
+ "available-bandwidth":125000000.0
+ }
+ },
+ {
+ "edge-id":167772162,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "local-vertex-id":167837442,
+ "remote-vertex-id":167837441,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":0,
+ "local-address":"10.0.0.2",
+ "remote-address":"10.0.0.1",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ]
+ }
+ },
+ {
+ "edge-id":167772929,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.3",
+ "local-vertex-id":167837443,
+ "remote-vertex-id":167837442,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":0,
+ "admin-group":32,
+ "local-address":"10.0.3.1",
+ "remote-address":"10.0.3.2",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ]
+ }
+ },
+ {
+ "edge-id":167772930,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "local-vertex-id":167837442,
+ "remote-vertex-id":167837443,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":0,
+ "local-address":"10.0.3.2",
+ "remote-address":"10.0.3.1",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ]
+ }
+ },
+ {
+ "edge-id":167773185,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.4",
+ "local-vertex-id":167837444,
+ "remote-vertex-id":167837442,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":0,
+ "local-address":"10.0.4.1",
+ "remote-address":"10.0.4.2",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ]
+ },
+ "segment-routing":[
+ {
+ "adj-sid":5001,
+ "flags":"0x60",
+ "weight":0
+ },
+ {
+ "adj-sid":5000,
+ "flags":"0xe0",
+ "weight":0
+ }
+ ]
+ },
+ {
+ "edge-id":167773186,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "local-vertex-id":167837442,
+ "remote-vertex-id":167837444,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":30,
+ "local-address":"10.0.4.2",
+ "remote-address":"10.0.4.1",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ],
+ "delay":25000,
+ "utilized-bandwidth":125000000.0
+ }
+ }
+ ],
+ "subnets":[
+ {
+ "subnet-id":"10.0.0.1\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.1",
+ "vertex-id":167837441,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.0.2\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "vertex-id":167837442,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.3.1\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.3",
+ "vertex-id":167837443,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.3.2\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "vertex-id":167837442,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.4.1\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.4",
+ "vertex-id":167837444,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.4.2\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "vertex-id":167837442,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.255.1\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.1",
+ "vertex-id":167837441,
+ "metric":0
+ },
+ {
+ "subnet-id":"10.0.255.2\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "vertex-id":167837442,
+ "metric":0
+ },
+ {
+ "subnet-id":"10.0.255.3\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.3",
+ "vertex-id":167837443,
+ "metric":0
+ },
+ {
+ "subnet-id":"10.0.255.4\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.4",
+ "vertex-id":167837444,
+ "metric":0,
+ "segment-routing":{
+ "pref-sid":400,
+ "algo":0,
+ "flags":"0x40"
+ }
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-te-topo1/reference/ted_step4.json b/tests/topotests/ospf-te-topo1/reference/ted_step4.json
new file mode 100644
index 0000000000..5c2dee1e4b
--- /dev/null
+++ b/tests/topotests/ospf-te-topo1/reference/ted_step4.json
@@ -0,0 +1,490 @@
+{
+ "ted":{
+ "name":"OSPF",
+ "key":1,
+ "verticesCount":4,
+ "edgesCount":6,
+ "subnetsCount":10,
+ "vertices":[
+ {
+ "vertex-id":167837441,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "router-id":"10.0.255.1",
+ "vertex-type":"Standard",
+ "segment-routing":{
+ "srgb-size":4000,
+ "srgb-lower":20000,
+ "algorithms":[
+ {
+ "0":"SPF"
+ }
+ ],
+ "srlb-size":1000,
+ "srlb-lower":15000
+ }
+ },
+ {
+ "vertex-id":167837442,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "router-id":"10.0.255.2",
+ "vertex-type":"Standard",
+ "segment-routing":{
+ "srgb-size":8000,
+ "srgb-lower":16000,
+ "algorithms":[
+ {
+ "0":"SPF"
+ }
+ ],
+ "srlb-size":2000,
+ "srlb-lower":5000,
+ "msd":16
+ }
+ },
+ {
+ "vertex-id":167837443,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "router-id":"10.0.255.3",
+ "vertex-type":"ASBR"
+ },
+ {
+ "vertex-id":167837444,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "router-id":"10.0.255.4",
+ "vertex-type":"Standard",
+ "segment-routing":{
+ "srgb-size":10000,
+ "srgb-lower":10000,
+ "algorithms":[
+ {
+ "0":"SPF"
+ }
+ ],
+ "srlb-size":1000,
+ "srlb-lower":5000,
+ "msd":12
+ }
+ }
+ ],
+ "edges":[
+ {
+ "edge-id":167772161,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.1",
+ "local-vertex-id":167837441,
+ "remote-vertex-id":167837442,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":20,
+ "local-address":"10.0.0.1",
+ "remote-address":"10.0.0.2",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ],
+ "delay":10000,
+ "available-bandwidth":125000000.0
+ },
+ "segment-routing":[
+ {
+ "adj-sid":15001,
+ "flags":"0x60",
+ "weight":0
+ },
+ {
+ "adj-sid":15000,
+ "flags":"0xe0",
+ "weight":0
+ }
+ ]
+ },
+ {
+ "edge-id":167772162,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "local-vertex-id":167837442,
+ "remote-vertex-id":167837441,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":0,
+ "local-address":"10.0.0.2",
+ "remote-address":"10.0.0.1",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ]
+ },
+ "segment-routing":[
+ {
+ "adj-sid":5001,
+ "flags":"0x60",
+ "weight":0
+ },
+ {
+ "adj-sid":5000,
+ "flags":"0xe0",
+ "weight":0
+ }
+ ]
+ },
+ {
+ "edge-id":167772929,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.3",
+ "local-vertex-id":167837443,
+ "remote-vertex-id":167837442,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":0,
+ "admin-group":32,
+ "local-address":"10.0.3.1",
+ "remote-address":"10.0.3.2",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ]
+ }
+ },
+ {
+ "edge-id":167772930,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "local-vertex-id":167837442,
+ "remote-vertex-id":167837443,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":0,
+ "local-address":"10.0.3.2",
+ "remote-address":"10.0.3.1",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ]
+ },
+ "segment-routing":[
+ {
+ "adj-sid":5003,
+ "flags":"0x60",
+ "weight":0
+ },
+ {
+ "adj-sid":5002,
+ "flags":"0xe0",
+ "weight":0
+ }
+ ]
+ },
+ {
+ "edge-id":167773185,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.4",
+ "local-vertex-id":167837444,
+ "remote-vertex-id":167837442,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":0,
+ "local-address":"10.0.4.1",
+ "remote-address":"10.0.4.2",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ]
+ },
+ "segment-routing":[
+ {
+ "adj-sid":5001,
+ "flags":"0x60",
+ "weight":0
+ },
+ {
+ "adj-sid":5000,
+ "flags":"0xe0",
+ "weight":0
+ }
+ ]
+ },
+ {
+ "edge-id":167773186,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "local-vertex-id":167837442,
+ "remote-vertex-id":167837444,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":30,
+ "local-address":"10.0.4.2",
+ "remote-address":"10.0.4.1",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ],
+ "delay":25000,
+ "utilized-bandwidth":125000000.0
+ },
+ "segment-routing":[
+ {
+ "adj-sid":5005,
+ "flags":"0x60",
+ "weight":0
+ },
+ {
+ "adj-sid":5004,
+ "flags":"0xe0",
+ "weight":0
+ }
+ ]
+ }
+ ],
+ "subnets":[
+ {
+ "subnet-id":"10.0.0.1\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.1",
+ "vertex-id":167837441,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.0.2\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "vertex-id":167837442,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.3.1\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.3",
+ "vertex-id":167837443,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.3.2\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "vertex-id":167837442,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.4.1\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.4",
+ "vertex-id":167837444,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.4.2\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "vertex-id":167837442,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.255.1\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.1",
+ "vertex-id":167837441,
+ "metric":0,
+ "segment-routing":{
+ "pref-sid":10,
+ "algo":0,
+ "flags":"0x0"
+ }
+ },
+ {
+ "subnet-id":"10.0.255.2\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "vertex-id":167837442,
+ "metric":0,
+ "segment-routing":{
+ "pref-sid":20,
+ "algo":0,
+ "flags":"0x50"
+ }
+ },
+ {
+ "subnet-id":"10.0.255.3\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.3",
+ "vertex-id":167837443,
+ "metric":0
+ },
+ {
+ "subnet-id":"10.0.255.4\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.4",
+ "vertex-id":167837444,
+ "metric":0,
+ "segment-routing":{
+ "pref-sid":400,
+ "algo":0,
+ "flags":"0x40"
+ }
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-te-topo1/reference/ted_step5.json b/tests/topotests/ospf-te-topo1/reference/ted_step5.json
new file mode 100644
index 0000000000..47e747f3ca
--- /dev/null
+++ b/tests/topotests/ospf-te-topo1/reference/ted_step5.json
@@ -0,0 +1,614 @@
+{
+ "ted":{
+ "name":"OSPF",
+ "key":1,
+ "verticesCount":4,
+ "edgesCount":8,
+ "subnetsCount":12,
+ "vertices":[
+ {
+ "vertex-id":167837441,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "router-id":"10.0.255.1",
+ "vertex-type":"Standard",
+ "segment-routing":{
+ "srgb-size":4000,
+ "srgb-lower":20000,
+ "algorithms":[
+ {
+ "0":"SPF"
+ }
+ ],
+ "srlb-size":1000,
+ "srlb-lower":15000
+ }
+ },
+ {
+ "vertex-id":167837442,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "router-id":"10.0.255.2",
+ "vertex-type":"Standard",
+ "segment-routing":{
+ "srgb-size":8000,
+ "srgb-lower":16000,
+ "algorithms":[
+ {
+ "0":"SPF"
+ }
+ ],
+ "srlb-size":2000,
+ "srlb-lower":5000,
+ "msd":16
+ }
+ },
+ {
+ "vertex-id":167837443,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "router-id":"10.0.255.3",
+ "vertex-type":"ASBR"
+ },
+ {
+ "vertex-id":167837444,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "router-id":"10.0.255.4",
+ "vertex-type":"Standard",
+ "segment-routing":{
+ "srgb-size":10000,
+ "srgb-lower":10000,
+ "algorithms":[
+ {
+ "0":"SPF"
+ }
+ ],
+ "srlb-size":1000,
+ "srlb-lower":5000,
+ "msd":12
+ }
+ }
+ ],
+ "edges":[
+ {
+ "edge-id":167772161,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.1",
+ "local-vertex-id":167837441,
+ "remote-vertex-id":167837442,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":20,
+ "local-address":"10.0.0.1",
+ "remote-address":"10.0.0.2",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ],
+ "delay":10000,
+ "available-bandwidth":125000000.0
+ },
+ "segment-routing":[
+ {
+ "adj-sid":15001,
+ "flags":"0x60",
+ "weight":0
+ },
+ {
+ "adj-sid":15000,
+ "flags":"0xe0",
+ "weight":0
+ }
+ ]
+ },
+ {
+ "edge-id":167772162,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "local-vertex-id":167837442,
+ "remote-vertex-id":167837441,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":0,
+ "local-address":"10.0.0.2",
+ "remote-address":"10.0.0.1",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ]
+ },
+ "segment-routing":[
+ {
+ "adj-sid":5001,
+ "flags":"0x60",
+ "weight":0
+ },
+ {
+ "adj-sid":5000,
+ "flags":"0xe0",
+ "weight":0
+ }
+ ]
+ },
+ {
+ "edge-id":167772417,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.1",
+ "local-vertex-id":167837441,
+ "remote-vertex-id":167837442,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":0,
+ "local-address":"10.0.1.1",
+ "remote-address":"10.0.1.2",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ]
+ },
+ "segment-routing":[
+ {
+ "adj-sid":15003,
+ "flags":"0x60",
+ "weight":0
+ },
+ {
+ "adj-sid":15002,
+ "flags":"0xe0",
+ "weight":0
+ }
+ ]
+ },
+ {
+ "edge-id":167772418,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "local-vertex-id":167837442,
+ "remote-vertex-id":167837441,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":0,
+ "local-address":"10.0.1.2",
+ "remote-address":"10.0.1.1",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ]
+ },
+ "segment-routing":[
+ {
+ "adj-sid":5007,
+ "flags":"0x60",
+ "weight":0
+ },
+ {
+ "adj-sid":5006,
+ "flags":"0xe0",
+ "weight":0
+ }
+ ]
+ },
+ {
+ "edge-id":167772929,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.3",
+ "local-vertex-id":167837443,
+ "remote-vertex-id":167837442,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":0,
+ "admin-group":32,
+ "local-address":"10.0.3.1",
+ "remote-address":"10.0.3.2",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ]
+ }
+ },
+ {
+ "edge-id":167772930,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "local-vertex-id":167837442,
+ "remote-vertex-id":167837443,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":0,
+ "local-address":"10.0.3.2",
+ "remote-address":"10.0.3.1",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ]
+ },
+ "segment-routing":[
+ {
+ "adj-sid":5003,
+ "flags":"0x60",
+ "weight":0
+ },
+ {
+ "adj-sid":5002,
+ "flags":"0xe0",
+ "weight":0
+ }
+ ]
+ },
+ {
+ "edge-id":167773185,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.4",
+ "local-vertex-id":167837444,
+ "remote-vertex-id":167837442,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":0,
+ "local-address":"10.0.4.1",
+ "remote-address":"10.0.4.2",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ]
+ },
+ "segment-routing":[
+ {
+ "adj-sid":5001,
+ "flags":"0x60",
+ "weight":0
+ },
+ {
+ "adj-sid":5000,
+ "flags":"0xe0",
+ "weight":0
+ }
+ ]
+ },
+ {
+ "edge-id":167773186,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "local-vertex-id":167837442,
+ "remote-vertex-id":167837444,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":30,
+ "local-address":"10.0.4.2",
+ "remote-address":"10.0.4.1",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ],
+ "delay":25000,
+ "utilized-bandwidth":125000000.0
+ },
+ "segment-routing":[
+ {
+ "adj-sid":5005,
+ "flags":"0x60",
+ "weight":0
+ },
+ {
+ "adj-sid":5004,
+ "flags":"0xe0",
+ "weight":0
+ }
+ ]
+ }
+ ],
+ "subnets":[
+ {
+ "subnet-id":"10.0.0.1\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.1",
+ "vertex-id":167837441,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.0.2\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "vertex-id":167837442,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.1.1\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.1",
+ "vertex-id":167837441,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.1.2\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "vertex-id":167837442,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.3.1\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.3",
+ "vertex-id":167837443,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.3.2\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "vertex-id":167837442,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.4.1\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.4",
+ "vertex-id":167837444,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.4.2\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "vertex-id":167837442,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.255.1\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.1",
+ "vertex-id":167837441,
+ "metric":0,
+ "segment-routing":{
+ "pref-sid":10,
+ "algo":0,
+ "flags":"0x0"
+ }
+ },
+ {
+ "subnet-id":"10.0.255.2\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "vertex-id":167837442,
+ "metric":0,
+ "segment-routing":{
+ "pref-sid":20,
+ "algo":0,
+ "flags":"0x50"
+ }
+ },
+ {
+ "subnet-id":"10.0.255.3\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.3",
+ "vertex-id":167837443,
+ "metric":0
+ },
+ {
+ "subnet-id":"10.0.255.4\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.4",
+ "vertex-id":167837444,
+ "metric":0,
+ "segment-routing":{
+ "pref-sid":400,
+ "algo":0,
+ "flags":"0x40"
+ }
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-te-topo1/reference/ted_step6.json b/tests/topotests/ospf-te-topo1/reference/ted_step6.json
new file mode 100644
index 0000000000..74bd83fbdb
--- /dev/null
+++ b/tests/topotests/ospf-te-topo1/reference/ted_step6.json
@@ -0,0 +1,615 @@
+{
+ "ted":{
+ "name":"OSPF",
+ "key":1,
+ "verticesCount":4,
+ "edgesCount":8,
+ "subnetsCount":12,
+ "vertices":[
+ {
+ "vertex-id":167837441,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "router-id":"10.0.255.1",
+ "vertex-type":"Standard",
+ "segment-routing":{
+ "srgb-size":4000,
+ "srgb-lower":20000,
+ "algorithms":[
+ {
+ "0":"SPF"
+ }
+ ],
+ "srlb-size":1000,
+ "srlb-lower":15000
+ }
+ },
+ {
+ "vertex-id":167837442,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "router-id":"10.0.255.2",
+ "vertex-type":"Standard",
+ "segment-routing":{
+ "srgb-size":8000,
+ "srgb-lower":16000,
+ "algorithms":[
+ {
+ "0":"SPF"
+ }
+ ],
+ "srlb-size":2000,
+ "srlb-lower":5000,
+ "msd":16
+ }
+ },
+ {
+ "vertex-id":167837443,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "router-id":"10.0.255.3",
+ "vertex-type":"ASBR"
+ },
+ {
+ "vertex-id":167837444,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "router-id":"10.0.255.4",
+ "vertex-type":"Standard",
+ "segment-routing":{
+ "srgb-size":10000,
+ "srgb-lower":10000,
+ "algorithms":[
+ {
+ "0":"SPF"
+ }
+ ],
+ "srlb-size":1000,
+ "srlb-lower":5000,
+ "msd":12
+ }
+ }
+ ],
+ "edges":[
+ {
+ "edge-id":167772161,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.1",
+ "local-vertex-id":167837441,
+ "remote-vertex-id":167837442,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":20,
+ "local-address":"10.0.0.1",
+ "remote-address":"10.0.0.2",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ],
+ "delay":10000,
+ "available-bandwidth":125000000.0
+ },
+ "segment-routing":[
+ {
+ "adj-sid":15001,
+ "flags":"0x60",
+ "weight":0
+ },
+ {
+ "adj-sid":15000,
+ "flags":"0xe0",
+ "weight":0
+ }
+ ]
+ },
+ {
+ "edge-id":167772162,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "local-vertex-id":167837442,
+ "remote-vertex-id":167837441,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":0,
+ "local-address":"10.0.0.2",
+ "remote-address":"10.0.0.1",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ]
+ },
+ "segment-routing":[
+ {
+ "adj-sid":5001,
+ "flags":"0x60",
+ "weight":0
+ },
+ {
+ "adj-sid":5000,
+ "flags":"0xe0",
+ "weight":0
+ }
+ ]
+ },
+ {
+ "edge-id":167772417,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.1",
+ "local-vertex-id":167837441,
+ "remote-vertex-id":167837442,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":0,
+ "local-address":"10.0.1.1",
+ "remote-address":"10.0.1.2",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ]
+ },
+ "segment-routing":[
+ {
+ "adj-sid":15003,
+ "flags":"0x60",
+ "weight":0
+ },
+ {
+ "adj-sid":15002,
+ "flags":"0xe0",
+ "weight":0
+ }
+ ]
+ },
+ {
+ "edge-id":167772418,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "local-vertex-id":167837442,
+ "remote-vertex-id":167837441,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":0,
+ "local-address":"10.0.1.2",
+ "remote-address":"10.0.1.1",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ]
+ },
+ "segment-routing":[
+ {
+ "adj-sid":5007,
+ "flags":"0x60",
+ "weight":0
+ },
+ {
+ "adj-sid":5006,
+ "flags":"0xe0",
+ "weight":0
+ }
+ ]
+ },
+ {
+ "edge-id":167772929,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.3",
+ "local-vertex-id":167837443,
+ "remote-vertex-id":167837442,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":0,
+ "admin-group":32,
+ "local-address":"10.0.3.1",
+ "remote-address":"10.0.3.2",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ]
+ }
+ },
+ {
+ "edge-id":167772930,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "local-vertex-id":167837442,
+ "remote-vertex-id":167837443,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":0,
+ "local-address":"10.0.3.2",
+ "remote-address":"10.0.3.1",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ]
+ },
+ "segment-routing":[
+ {
+ "adj-sid":5003,
+ "flags":"0x60",
+ "weight":0
+ },
+ {
+ "adj-sid":5002,
+ "flags":"0xe0",
+ "weight":0
+ }
+ ]
+ },
+ {
+ "edge-id":167773185,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.4",
+ "local-vertex-id":167837444,
+ "remote-vertex-id":167837442,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":0,
+ "local-address":"10.0.4.1",
+ "remote-address":"10.0.4.2",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ],
+ "delay":20000,
+ "jitter":10000
+ },
+ "segment-routing":[
+ {
+ "adj-sid":5001,
+ "flags":"0x60",
+ "weight":0
+ },
+ {
+ "adj-sid":5000,
+ "flags":"0xe0",
+ "weight":0
+ }
+ ]
+ },
+ {
+ "edge-id":167773186,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "local-vertex-id":167837442,
+ "remote-vertex-id":167837444,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":30,
+ "local-address":"10.0.4.2",
+ "remote-address":"10.0.4.1",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ],
+ "delay":25000
+ },
+ "segment-routing":[
+ {
+ "adj-sid":5005,
+ "flags":"0x60",
+ "weight":0
+ },
+ {
+ "adj-sid":5004,
+ "flags":"0xe0",
+ "weight":0
+ }
+ ]
+ }
+ ],
+ "subnets":[
+ {
+ "subnet-id":"10.0.0.1\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.1",
+ "vertex-id":167837441,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.0.2\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "vertex-id":167837442,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.1.1\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.1",
+ "vertex-id":167837441,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.1.2\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "vertex-id":167837442,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.3.1\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.3",
+ "vertex-id":167837443,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.3.2\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "vertex-id":167837442,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.4.1\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.4",
+ "vertex-id":167837444,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.4.2\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "vertex-id":167837442,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.255.1\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.1",
+ "vertex-id":167837441,
+ "metric":0,
+ "segment-routing":{
+ "pref-sid":10,
+ "algo":0,
+ "flags":"0x0"
+ }
+ },
+ {
+ "subnet-id":"10.0.255.2\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "vertex-id":167837442,
+ "metric":0,
+ "segment-routing":{
+ "pref-sid":20,
+ "algo":0,
+ "flags":"0x50"
+ }
+ },
+ {
+ "subnet-id":"10.0.255.3\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.3",
+ "vertex-id":167837443,
+ "metric":0
+ },
+ {
+ "subnet-id":"10.0.255.4\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.4",
+ "vertex-id":167837444,
+ "metric":0,
+ "segment-routing":{
+ "pref-sid":400,
+ "algo":0,
+ "flags":"0x40"
+ }
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-te-topo1/reference/ted_step7.json b/tests/topotests/ospf-te-topo1/reference/ted_step7.json
new file mode 100644
index 0000000000..1cea9f0455
--- /dev/null
+++ b/tests/topotests/ospf-te-topo1/reference/ted_step7.json
@@ -0,0 +1,456 @@
+{
+ "ted":{
+ "name":"OSPF",
+ "key":1,
+ "verticesCount":3,
+ "edgesCount":6,
+ "subnetsCount":9,
+ "vertices":[
+ {
+ "vertex-id":167837441,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "router-id":"10.0.255.1",
+ "vertex-type":"Standard",
+ "segment-routing":{
+ "srgb-size":4000,
+ "srgb-lower":20000,
+ "algorithms":[
+ {
+ "0":"SPF"
+ }
+ ],
+ "srlb-size":1000,
+ "srlb-lower":15000
+ }
+ },
+ {
+ "vertex-id":167837442,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "router-id":"10.0.255.2",
+ "vertex-type":"Standard",
+ "segment-routing":{
+ "srgb-size":8000,
+ "srgb-lower":16000,
+ "algorithms":[
+ {
+ "0":"SPF"
+ }
+ ],
+ "srlb-size":2000,
+ "srlb-lower":5000,
+ "msd":16
+ }
+ },
+ {
+ "vertex-id":167837443,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "router-id":"10.0.255.3",
+ "vertex-type":"ASBR"
+ }
+ ],
+ "edges":[
+ {
+ "edge-id":167772161,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.1",
+ "local-vertex-id":167837441,
+ "remote-vertex-id":167837442,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":20,
+ "local-address":"10.0.0.1",
+ "remote-address":"10.0.0.2",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ],
+ "delay":10000,
+ "available-bandwidth":125000000.0
+ },
+ "segment-routing":[
+ {
+ "adj-sid":15001,
+ "flags":"0x60",
+ "weight":0
+ },
+ {
+ "adj-sid":15000,
+ "flags":"0xe0",
+ "weight":0
+ }
+ ]
+ },
+ {
+ "edge-id":167772162,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "local-vertex-id":167837442,
+ "remote-vertex-id":167837441,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":0,
+ "local-address":"10.0.0.2",
+ "remote-address":"10.0.0.1",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ]
+ },
+ "segment-routing":[
+ {
+ "adj-sid":5001,
+ "flags":"0x60",
+ "weight":0
+ },
+ {
+ "adj-sid":5000,
+ "flags":"0xe0",
+ "weight":0
+ }
+ ]
+ },
+ {
+ "edge-id":167772417,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.1",
+ "local-vertex-id":167837441,
+ "remote-vertex-id":167837442,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":0,
+ "local-address":"10.0.1.1",
+ "remote-address":"10.0.1.2",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ]
+ },
+ "segment-routing":[
+ {
+ "adj-sid":15003,
+ "flags":"0x60",
+ "weight":0
+ },
+ {
+ "adj-sid":15002,
+ "flags":"0xe0",
+ "weight":0
+ }
+ ]
+ },
+ {
+ "edge-id":167772418,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "local-vertex-id":167837442,
+ "remote-vertex-id":167837441,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":0,
+ "local-address":"10.0.1.2",
+ "remote-address":"10.0.1.1",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ]
+ },
+ "segment-routing":[
+ {
+ "adj-sid":5007,
+ "flags":"0x60",
+ "weight":0
+ },
+ {
+ "adj-sid":5006,
+ "flags":"0xe0",
+ "weight":0
+ }
+ ]
+ },
+ {
+ "edge-id":167772929,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.3",
+ "local-vertex-id":167837443,
+ "remote-vertex-id":167837442,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":0,
+ "admin-group":32,
+ "local-address":"10.0.3.1",
+ "remote-address":"10.0.3.2",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ]
+ }
+ },
+ {
+ "edge-id":167772930,
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "local-vertex-id":167837442,
+ "remote-vertex-id":167837443,
+ "metric":10,
+ "edge-attributes":{
+ "te-metric":0,
+ "local-address":"10.0.3.2",
+ "remote-address":"10.0.3.1",
+ "max-link-bandwidth":176258176.0,
+ "max-resv-link-bandwidth":176258176.0,
+ "unreserved-bandwidth":[
+ {
+ "class-type-0":176258176.0
+ },
+ {
+ "class-type-1":176258176.0
+ },
+ {
+ "class-type-2":176258176.0
+ },
+ {
+ "class-type-3":176258176.0
+ },
+ {
+ "class-type-4":176258176.0
+ },
+ {
+ "class-type-5":176258176.0
+ },
+ {
+ "class-type-6":176258176.0
+ },
+ {
+ "class-type-7":176258176.0
+ }
+ ]
+ },
+ "segment-routing":[
+ {
+ "adj-sid":5003,
+ "flags":"0x60",
+ "weight":0
+ },
+ {
+ "adj-sid":5002,
+ "flags":"0xe0",
+ "weight":0
+ }
+ ]
+ }
+ ],
+ "subnets":[
+ {
+ "subnet-id":"10.0.0.1\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.1",
+ "vertex-id":167837441,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.0.2\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "vertex-id":167837442,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.1.1\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.1",
+ "vertex-id":167837441,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.1.2\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "vertex-id":167837442,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.3.1\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.3",
+ "vertex-id":167837443,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.3.2\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "vertex-id":167837442,
+ "metric":10
+ },
+ {
+ "subnet-id":"10.0.255.1\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.1",
+ "vertex-id":167837441,
+ "metric":0,
+ "segment-routing":{
+ "pref-sid":10,
+ "algo":0,
+ "flags":"0x0"
+ }
+ },
+ {
+ "subnet-id":"10.0.255.2\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.2",
+ "vertex-id":167837442,
+ "metric":0,
+ "segment-routing":{
+ "pref-sid":20,
+ "algo":0,
+ "flags":"0x50"
+ }
+ },
+ {
+ "subnet-id":"10.0.255.3\/32",
+ "status":"Sync",
+ "origin":"OSPFv2",
+ "advertised-router":"10.0.255.3",
+ "vertex-id":167837443,
+ "metric":0
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-te-topo1/test_ospf_te_topo1.py b/tests/topotests/ospf-te-topo1/test_ospf_te_topo1.py
new file mode 100644
index 0000000000..32f9b3453e
--- /dev/null
+++ b/tests/topotests/ospf-te-topo1/test_ospf_te_topo1.py
@@ -0,0 +1,300 @@
+#!/usr/bin/env python
+
+#
+# test_ospf_te_topo1.py
+# Part of NetDEF Topology Tests
+#
+# Copyright (c) 2021 by Orange
+# Author: Olivier Dugeon <olivier.dugeon@orange.com>
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+test_ospf_te_topo1.py: Test the FRR OSPF with Traffic Engineering.
+
+ +------------+
+ | |
+ | R1 |
+ | 10.0.225.1 |
+ | |
+ +------------+
+ r1-eth0| |r1-eth1
+ | |
+ 10.0.0.0/24| |10.0.1.0/24
+ | |
+ r2-eth0| |r2-eth1
+ +------------+ +------------+
+ | | | |
+ | R2 |r2-eth2 r3-eth0| R3 |
+ | 10.0.255.2 +------------------+ 10.0.255.3 |
+ | | 10.0.3.0/24 | |
+ +------------+ +------+-----+
+ r2-eth3| r3-eth1|
+ | |
+ 10.0.4.0/24| 10.0.5.0/24|
+ | |
+ r4-eth0| V
+ +------------+ ASBR 10.0.255.5
+ | |
+ | R4 |
+ | 10.0.255.4 |
+ | |
+ +------------+
+
+"""
+
+import os
+import sys
+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
+# Required to instantiate the topology builder class.
+from mininet.topo import Topo
+
+# Import topogen and topotest helpers
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+
+# and Finally pytest
+import pytest
+
+pytestmark = [pytest.mark.ospfd]
+
+
+class OspfTeTopo(Topo):
+ "Test topology builder"
+
+ def build(self):
+ "Build function"
+ tgen = get_topogen(self)
+
+ # Create 4 routers
+ for routern in range(1, 5):
+ tgen.add_router("r{}".format(routern))
+
+ # Interconect router 1 and 2 with 2 links
+ switch = tgen.add_switch("s1")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r2"])
+ switch = tgen.add_switch("s2")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r2"])
+
+ # Interconect router 3 and 2
+ switch = tgen.add_switch("s3")
+ switch.add_link(tgen.gears["r3"])
+ switch.add_link(tgen.gears["r2"])
+
+ # Interconect router 4 and 2
+ switch = tgen.add_switch("s4")
+ switch.add_link(tgen.gears["r4"])
+ switch.add_link(tgen.gears["r2"])
+
+ # Interconnect router 3 with next AS
+ switch = tgen.add_switch("s5")
+ switch.add_link(tgen.gears["r3"])
+
+
+def setup_module(mod):
+ "Sets up the pytest environment"
+
+ logger.info("\n\n---- Starting OSPF TE tests ----\n")
+
+ tgen = Topogen(OspfTeTopo, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ for rname, router in router_list.items():
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_OSPF, os.path.join(CWD, "{}/ospfd.conf".format(rname))
+ )
+
+ # Initialize all routers.
+ tgen.start_router()
+
+
+def teardown_module():
+ "Teardown the pytest environment"
+
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+ logger.info("\n\n---- OSPF TE tests End ----\n")
+
+
+def compare_ted_json_output(tgen, rname, fileref):
+ "Compare TED JSON output"
+
+ logger.info('Comparing router "%s" TED output', rname)
+
+ filename = "{}/reference/{}".format(CWD, fileref)
+ expected = json.loads(open(filename).read())
+ command = "show ip ospf mpls-te database json"
+
+ # 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=60, wait=2)
+ assertmsg = '"{}" TED JSON output mismatches the expected result'.format(rname)
+ assert diff is None, assertmsg
+
+
+def setup_testcase(msg):
+ "Setup test case"
+
+ logger.info(msg)
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ return tgen
+
+
+# Note that all routers must discover the same Network Topology, so the same TED.
+
+
+def test_step1():
+ "Step1: Check initial topology"
+
+ tgen = setup_testcase("Step1: test initial OSPF TE Data Base")
+
+ for rname in ["r1", "r2", "r3", "r4"]:
+ compare_ted_json_output(tgen, rname, "ted_step1.json")
+
+
+def test_step2():
+ "Step2: Shutdown interface between r1 and r2 and verify that \
+ corresponding Edges are removed from the TED on all routers "
+
+ tgen = setup_testcase("Step2: Shutdown interface between r1 & r2")
+
+ tgen.net["r1"].cmd('vtysh -c "conf t" -c "interface r1-eth1" -c "shutdown"')
+ tgen.net["r2"].cmd('vtysh -c "conf t" -c "interface r2-eth1" -c "shutdown"')
+
+ for rname in ["r1", "r2", "r3", "r4"]:
+ compare_ted_json_output(tgen, rname, "ted_step2.json")
+
+
+def test_step3():
+ "Step3: Disable Inter-AS on r3 and verify that corresponding Edge and \
+ remote ASBR are removed from the TED on all routers"
+
+ tgen = setup_testcase("Step3: Disable Inter-AS on r3")
+
+ tgen.net["r3"].cmd('vtysh -c "conf t" -c "router ospf" -c "no mpls-te inter-as"')
+ for rname in ["r1", "r2", "r3", "r4"]:
+ compare_ted_json_output(tgen, rname, "ted_step3.json")
+
+
+def test_step4():
+ "Step4: Enable Segment Routing on r1 and r2 and verify that corresponding \
+ Edges are updated with Adjacency SID and Subnets with Prefix SID in the \
+ TED on all routers"
+
+ tgen = setup_testcase("Step4: Enable Segment Routing on r1 & r2")
+
+ tgen.net["r1"].cmd('vtysh -c "conf t" -c "router ospf" -c "segment-routing on"')
+ tgen.net["r1"].cmd(
+ 'vtysh -c "conf t" -c "router ospf" -c "segment-routing global-block 20000 23999"'
+ )
+ tgen.net["r1"].cmd(
+ 'vtysh -c "conf t" -c "router ospf" -c "segment-routing prefix 10.0.255.1/32 index 10"'
+ )
+ tgen.net["r2"].cmd('vtysh -c "conf t" -c "router ospf" -c "segment-routing on"')
+ tgen.net["r2"].cmd(
+ 'vtysh -c "conf t" -c "router ospf" -c "segment-routing node-msd 16"'
+ )
+ tgen.net["r2"].cmd(
+ 'vtysh -c "conf t" -c "router ospf" -c "segment-routing local-block 5000 6999"'
+ )
+ tgen.net["r2"].cmd(
+ 'vtysh -c "conf t" -c "router ospf" -c "segment-routing prefix 10.0.255.2/32 index 20 explicit-null"'
+ )
+
+ for rname in ["r1", "r2", "r3", "r4"]:
+ compare_ted_json_output(tgen, rname, "ted_step4.json")
+
+
+def test_step5():
+ "Step5: Re-enable interface between r1 & r2 and verify that corresponding \
+ Edges are added in the TED on all routers"
+
+ tgen = setup_testcase("Step5: Re-enable interface between r1 & r2")
+
+ tgen.net["r1"].cmd('vtysh -c "conf t" -c "interface r1-eth1" -c "no shutdown"')
+ tgen.net["r2"].cmd('vtysh -c "conf t" -c "interface r2-eth1" -c "no shutdown"')
+
+ for rname in ["r1", "r2", "r3", "r4"]:
+ compare_ted_json_output(tgen, rname, "ted_step5.json")
+
+
+def test_step6():
+ "Step6: Set delay and jitter for interface r4-eth0 on r4, remove use-bw \
+ for interface r2-eth3 on r2 and verify that corresponding Edges are \
+ updated in the TED on all routers"
+
+ tgen = setup_testcase("Step6: Modify link parameters on r2 & r4")
+
+ tgen.net["r2"].cmd(
+ 'vtysh -c "conf t" -c "interface r2-eth3" -c "link-params" -c "no use-bw"'
+ )
+ tgen.net["r4"].cmd(
+ 'vtysh -c "conf t" -c "interface r4-eth0" -c "link-params" -c "delay 20000"'
+ )
+ tgen.net["r4"].cmd(
+ 'vtysh -c "conf t" -c "interface r4-eth0" -c "link-params" -c "delay-variation 10000"'
+ )
+
+ for rname in ["r1", "r2", "r3", "r4"]:
+ compare_ted_json_output(tgen, rname, "ted_step6.json")
+
+
+def test_step7():
+ "Step7: Disable OSPF on r4 and verify that corresponding Vertex, Edges and \
+ Subnets are removed from the TED on all remaining routers"
+
+ tgen = setup_testcase("Step7: Disable OSPF on r4")
+
+ tgen.net["r4"].cmd('vtysh -c "conf t" -c "no router ospf"')
+
+ for rname in ["r1", "r2", "r3"]:
+ compare_ted_json_output(tgen, rname, "ted_step7.json")
+
+
+def test_memory_leak():
+ "Run the memory leak test and report results."
+
+ tgen = get_topogen()
+ if not tgen.is_memleak_enabled():
+ pytest.skip("Memory leak test/report is disabled")
+
+ tgen.report_memory_leaks()
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/ospf-topo1/r1/ospf6d.conf-pre-v4 b/tests/topotests/ospf-topo1/r1/ospf6d.conf-pre-v4
deleted file mode 100644
index 6a40f859db..0000000000
--- a/tests/topotests/ospf-topo1/r1/ospf6d.conf-pre-v4
+++ /dev/null
@@ -1,9 +0,0 @@
-!
-router ospf6
- router-id 10.0.255.1
- redistribute kernel
- redistribute connected
- redistribute static
- interface r1-eth0 area 0.0.0.0
- interface r1-eth1 area 0.0.0.0
-!
diff --git a/tests/topotests/ospf-topo1/r2/ospf6d.conf-pre-v4 b/tests/topotests/ospf-topo1/r2/ospf6d.conf-pre-v4
deleted file mode 100644
index 7448b25327..0000000000
--- a/tests/topotests/ospf-topo1/r2/ospf6d.conf-pre-v4
+++ /dev/null
@@ -1,9 +0,0 @@
-!
-router ospf6
- router-id 10.0.255.2
- redistribute kernel
- redistribute connected
- redistribute static
- interface r2-eth0 area 0.0.0.0
- interface r2-eth1 area 0.0.0.0
-!
diff --git a/tests/topotests/ospf-topo1/r3/ospf6d.conf-pre-v4 b/tests/topotests/ospf-topo1/r3/ospf6d.conf-pre-v4
deleted file mode 100644
index e853e0e2b2..0000000000
--- a/tests/topotests/ospf-topo1/r3/ospf6d.conf-pre-v4
+++ /dev/null
@@ -1,10 +0,0 @@
-!
-router ospf6
- router-id 10.0.255.3
- redistribute kernel
- redistribute connected
- redistribute static
- interface r3-eth0 area 0.0.0.0
- interface r3-eth1 area 0.0.0.0
- interface r3-eth2 area 0.0.0.1
-!
diff --git a/tests/topotests/ospf-topo1/r4/ospf6d.conf-pre-v4 b/tests/topotests/ospf-topo1/r4/ospf6d.conf-pre-v4
deleted file mode 100644
index dcc07a4fdc..0000000000
--- a/tests/topotests/ospf-topo1/r4/ospf6d.conf-pre-v4
+++ /dev/null
@@ -1,9 +0,0 @@
-!
-router ospf6
- router-id 10.0.255.4
- redistribute kernel
- redistribute connected
- redistribute static
- interface r4-eth0 area 0.0.0.1
- interface r4-eth1 area 0.0.0.1
-!
diff --git a/tests/topotests/ospf-topo1/test_ospf_topo1.py b/tests/topotests/ospf-topo1/test_ospf_topo1.py
index 5bb6c2c818..42634ce906 100644
--- a/tests/topotests/ospf-topo1/test_ospf_topo1.py
+++ b/tests/topotests/ospf-topo1/test_ospf_topo1.py
@@ -93,8 +93,6 @@ def setup_module(mod):
tgen.start_topology()
ospf6_config = "ospf6d.conf"
- if tgen.gears["r1"].has_version("<", "4.0"):
- ospf6_config = "ospf6d.conf-pre-v4"
router_list = tgen.routers()
for rname, router in router_list.items():
@@ -118,6 +116,88 @@ def teardown_module(mod):
tgen.stop_topology()
+def test_wait_protocol_convergence():
+ "Wait for OSPFv2/OSPFv3 to converge"
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("waiting for protocols to converge")
+
+ def expect_ospfv2_neighbor_full(router, neighbor):
+ "Wait until OSPFv2 convergence."
+ logger.info("waiting OSPFv2 router '{}'".format(router))
+
+ def run_command_and_expect():
+ """
+ Function that runs command and expect the following outcomes:
+ * Full/DR
+ * Full/DROther
+ * Full/Backup
+ """
+ result = tgen.gears[router].vtysh_cmd(
+ "show ip ospf neighbor json", isjson=True
+ )
+ if (
+ topotest.json_cmp(
+ result, {"neighbors": {neighbor: [{"state": "Full/DR"}]}}
+ )
+ is None
+ ):
+ return None
+
+ if (
+ topotest.json_cmp(
+ result, {"neighbors": {neighbor: [{"state": "Full/DROther"}]}}
+ )
+ is None
+ ):
+ return None
+
+ return topotest.json_cmp(
+ result, {"neighbors": {neighbor: [{"state": "Full/Backup"}]}}
+ )
+
+ _, result = topotest.run_and_expect(
+ run_command_and_expect, None, count=130, wait=1
+ )
+ assertmsg = '"{}" convergence failure'.format(router)
+ assert result is None, assertmsg
+
+ def expect_ospfv3_neighbor_full(router, neighbor):
+ "Wait until OSPFv3 convergence."
+ logger.info("waiting OSPFv3 router '{}'".format(router))
+ test_func = partial(
+ topotest.router_json_cmp,
+ tgen.gears[router],
+ "show ipv6 ospf6 neighbor json",
+ {"neighbors": [{"neighborId": neighbor, "state": "Full"}]},
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=130, wait=1)
+ assertmsg = '"{}" convergence failure'.format(router)
+ assert result is None, assertmsg
+
+ # Wait for OSPFv2 convergence
+ expect_ospfv2_neighbor_full("r1", "10.0.255.2")
+ expect_ospfv2_neighbor_full("r1", "10.0.255.3")
+ expect_ospfv2_neighbor_full("r2", "10.0.255.1")
+ expect_ospfv2_neighbor_full("r2", "10.0.255.3")
+ expect_ospfv2_neighbor_full("r3", "10.0.255.1")
+ expect_ospfv2_neighbor_full("r3", "10.0.255.2")
+ expect_ospfv2_neighbor_full("r3", "10.0.255.4")
+ expect_ospfv2_neighbor_full("r4", "10.0.255.3")
+
+ # Wait for OSPFv3 convergence
+ expect_ospfv3_neighbor_full("r1", "10.0.255.2")
+ expect_ospfv3_neighbor_full("r1", "10.0.255.3")
+ expect_ospfv3_neighbor_full("r2", "10.0.255.1")
+ expect_ospfv3_neighbor_full("r2", "10.0.255.3")
+ expect_ospfv3_neighbor_full("r3", "10.0.255.1")
+ expect_ospfv3_neighbor_full("r3", "10.0.255.2")
+ expect_ospfv3_neighbor_full("r3", "10.0.255.4")
+ expect_ospfv3_neighbor_full("r4", "10.0.255.3")
+
+
def compare_show_ipv6_ospf6(rname, expected):
"""
Calls 'show ipv6 ospf6 route' for router `rname` and compare the obtained
diff --git a/tests/topotests/ospf6-topo1/r1/ospf6d.conf b/tests/topotests/ospf6-topo1/r1/ospf6d.conf
index ab2c0c647e..9f7e058931 100644
--- a/tests/topotests/ospf6-topo1/r1/ospf6d.conf
+++ b/tests/topotests/ospf6-topo1/r1/ospf6d.conf
@@ -11,9 +11,13 @@ debug ospf6 flooding
!
interface r1-stubnet
ipv6 ospf6 network broadcast
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
!
interface r1-sw5
ipv6 ospf6 network broadcast
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
!
router ospf6
ospf6 router-id 10.0.0.1
diff --git a/tests/topotests/ospf6-topo1/r2/ospf6d.conf b/tests/topotests/ospf6-topo1/r2/ospf6d.conf
index 075e815ed8..26ebc2c0ea 100644
--- a/tests/topotests/ospf6-topo1/r2/ospf6d.conf
+++ b/tests/topotests/ospf6-topo1/r2/ospf6d.conf
@@ -11,9 +11,13 @@ debug ospf6 flooding
!
interface r2-stubnet
ipv6 ospf6 network broadcast
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
!
interface r2-sw5
ipv6 ospf6 network broadcast
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
!
router ospf6
ospf6 router-id 10.0.0.2
diff --git a/tests/topotests/ospf6-topo1/r3/ospf6d.conf b/tests/topotests/ospf6-topo1/r3/ospf6d.conf
index e9a07a7e28..e902496530 100644
--- a/tests/topotests/ospf6-topo1/r3/ospf6d.conf
+++ b/tests/topotests/ospf6-topo1/r3/ospf6d.conf
@@ -11,12 +11,18 @@ debug ospf6 flooding
!
interface r3-stubnet
ipv6 ospf6 network broadcast
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
!
interface r3-sw5
ipv6 ospf6 network broadcast
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
!
interface r3-sw6
ipv6 ospf6 network broadcast
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
!
router ospf6
ospf6 router-id 10.0.0.3
diff --git a/tests/topotests/ospf6-topo1/r4/ospf6d.conf b/tests/topotests/ospf6-topo1/r4/ospf6d.conf
index fa66645f5a..5607a789de 100644
--- a/tests/topotests/ospf6-topo1/r4/ospf6d.conf
+++ b/tests/topotests/ospf6-topo1/r4/ospf6d.conf
@@ -11,9 +11,13 @@ debug ospf6 flooding
!
interface r4-stubnet
ipv6 ospf6 network broadcast
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
!
interface r4-sw6
ipv6 ospf6 network broadcast
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
!
router ospf6
ospf6 router-id 10.0.0.4
diff --git a/tests/topotests/ospf6-topo1/test_ospf6_topo1.py b/tests/topotests/ospf6-topo1/test_ospf6_topo1.py
index 6ae886b76e..f8c3476e18 100644
--- a/tests/topotests/ospf6-topo1/test_ospf6_topo1.py
+++ b/tests/topotests/ospf6-topo1/test_ospf6_topo1.py
@@ -185,70 +185,38 @@ def teardown_module(mod):
tgen.stop_topology()
-def test_ospf6_converged():
-
+def test_wait_protocol_convergence():
+ "Wait for OSPFv3 to converge"
tgen = get_topogen()
-
- # Don't run this test if we have any failure.
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
- # For debugging, uncomment the next line
- # tgen.mininet_cli()
-
- # Wait for OSPF6 to converge (All Neighbors in either Full or TwoWay State)
- logger.info("Waiting for OSPF6 convergence")
-
- # Set up for regex
- pat1 = re.compile("^[0-9]")
- pat2 = re.compile("Full")
-
- timeout = 60
- while timeout > 0:
- logger.info("Timeout in %s: " % timeout),
- sys.stdout.flush()
-
- # Look for any node not yet converged
- for router, rnode in tgen.routers().items():
- resStr = rnode.vtysh_cmd("show ipv6 ospf neigh")
-
- isConverged = False
+ logger.info("waiting for protocols to converge")
- for line in resStr.splitlines():
- res1 = pat1.match(line)
- if res1:
- isConverged = True
- res2 = pat2.search(line)
-
- if res2 == None:
- isConverged = False
- break
-
- if isConverged == False:
- logger.info("Waiting for {}".format(router))
- sys.stdout.flush()
- break
-
- if isConverged:
- logger.info("Done")
- break
- else:
- sleep(5)
- timeout -= 5
+ def expect_neighbor_full(router, neighbor):
+ "Wait until OSPFv3 convergence."
+ logger.info("waiting OSPFv3 router '{}'".format(router))
+ test_func = partial(
+ topotest.router_json_cmp,
+ tgen.gears[router],
+ "show ipv6 ospf6 neighbor json",
+ {"neighbors": [{"neighborId": neighbor, "state": "Full"}]},
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=130, wait=1)
+ assertmsg = '"{}" convergence failure'.format(router)
+ assert result is None, assertmsg
- if timeout == 0:
- # Bail out with error if a router fails to converge
- ospfStatus = rnode.vtysh_cmd("show ipv6 ospf neigh")
- assert False, "OSPFv6 did not converge:\n{}".format(ospfStatus)
+ expect_neighbor_full("r1", "10.0.0.2")
+ expect_neighbor_full("r1", "10.0.0.3")
- logger.info("OSPFv3 converged.")
+ expect_neighbor_full("r2", "10.0.0.1")
+ expect_neighbor_full("r2", "10.0.0.3")
- # For debugging, uncomment the next line
- # tgen.mininet_cli()
+ expect_neighbor_full("r3", "10.0.0.1")
+ expect_neighbor_full("r3", "10.0.0.2")
+ expect_neighbor_full("r3", "10.0.0.4")
- # Make sure that all daemons are still running
- if tgen.routers_have_failure():
- assert tgen.errors == "", tgen.errors
+ expect_neighbor_full("r4", "10.0.0.3")
def compare_show_ipv6(rname, expected):
diff --git a/tests/topotests/ospf6-topo2/r1/ospf6d.conf b/tests/topotests/ospf6-topo2/r1/ospf6d.conf
new file mode 100644
index 0000000000..c403fcd8dc
--- /dev/null
+++ b/tests/topotests/ospf6-topo2/r1/ospf6d.conf
@@ -0,0 +1,9 @@
+interface r1-eth0
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
+!
+router ospf6
+ ospf6 router-id 10.254.254.1
+ area 0.0.0.1 stub
+ interface r1-eth0 area 0.0.0.1
+!
diff --git a/tests/topotests/ospf6-topo2/r1/zebra.conf b/tests/topotests/ospf6-topo2/r1/zebra.conf
new file mode 100644
index 0000000000..7fee2da8ba
--- /dev/null
+++ b/tests/topotests/ospf6-topo2/r1/zebra.conf
@@ -0,0 +1,5 @@
+ipv6 forwarding
+!
+interface r1-eth0
+ ipv6 address 2001:db8:1::2/64
+!
diff --git a/tests/topotests/ospf6-topo2/r2/ospf6d.conf b/tests/topotests/ospf6-topo2/r2/ospf6d.conf
new file mode 100644
index 0000000000..d4bb0e2a41
--- /dev/null
+++ b/tests/topotests/ospf6-topo2/r2/ospf6d.conf
@@ -0,0 +1,17 @@
+interface r2-eth0
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
+!
+interface r2-eth1
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
+!
+router ospf6
+ ospf6 router-id 10.254.254.2
+ redistribute connected
+ redistribute static
+ default-information originate always metric 123
+ area 0.0.0.1 stub
+ interface r2-eth0 area 0.0.0.1
+ interface r2-eth1 area 0.0.0.0
+!
diff --git a/tests/topotests/ospf6-topo2/r2/zebra.conf b/tests/topotests/ospf6-topo2/r2/zebra.conf
new file mode 100644
index 0000000000..891945a4e7
--- /dev/null
+++ b/tests/topotests/ospf6-topo2/r2/zebra.conf
@@ -0,0 +1,8 @@
+ipv6 forwarding
+!
+interface r2-eth0
+ ipv6 address 2001:db8:1::1/64
+!
+interface r2-eth1
+ ipv6 address 2001:db8:2::2/64
+!
diff --git a/tests/topotests/ospf6-topo2/r3/ospf6d.conf b/tests/topotests/ospf6-topo2/r3/ospf6d.conf
new file mode 100644
index 0000000000..aaef00d5bb
--- /dev/null
+++ b/tests/topotests/ospf6-topo2/r3/ospf6d.conf
@@ -0,0 +1,10 @@
+interface r3-eth0
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
+!
+router ospf6
+ ospf6 router-id 10.254.254.3
+ redistribute connected
+ redistribute static
+ interface r3-eth0 area 0.0.0.0
+!
diff --git a/tests/topotests/ospf6-topo2/r3/zebra.conf b/tests/topotests/ospf6-topo2/r3/zebra.conf
new file mode 100644
index 0000000000..dea2fe4778
--- /dev/null
+++ b/tests/topotests/ospf6-topo2/r3/zebra.conf
@@ -0,0 +1,8 @@
+ipv6 forwarding
+!
+interface r3-eth0
+ ipv6 address 2001:db8:2::1/64
+!
+ipv6 route fc00:1::/64 fc00:100::1234
+ipv6 route fc00:2::/64 fc00:100::1234
+ipv6 route fc00:3::/64 fc00:100::1234
diff --git a/tests/topotests/ospf6-topo2/test_ospf6_topo2.dot b/tests/topotests/ospf6-topo2/test_ospf6_topo2.dot
new file mode 100644
index 0000000000..ba7a36f2b5
--- /dev/null
+++ b/tests/topotests/ospf6-topo2/test_ospf6_topo2.dot
@@ -0,0 +1,71 @@
+## Color coding:
+#########################
+## Main FRR: #f08080 red
+## Switches: #d0e0d0 gray
+## RIP: #19e3d9 Cyan
+## RIPng: #fcb314 dark yellow
+## OSPFv2: #32b835 Green
+## OSPFv3: #19e3d9 Cyan
+## ISIS IPv4 #fcb314 dark yellow
+## ISIS IPv6 #9a81ec purple
+## BGP IPv4 #eee3d3 beige
+## BGP IPv6 #fdff00 yellow
+##### Colors (see http://www.color-hex.com/)
+
+graph template {
+ label="ospf6-topo2";
+
+ # Routers
+ r1 [
+ shape=doubleoctagon,
+ label="r1",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+ r2 [
+ shape=doubleoctagon
+ label="r2",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+ r3 [
+ shape=doubleoctagon
+ label="r3",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+
+ # Switches
+ sw1 [
+ shape=oval,
+ label="sw1\n2001:db8:1::/64",
+ fillcolor="#d0e0d0",
+ style=filled,
+ ];
+ sw2 [
+ shape=oval,
+ label="sw2\n2001:db8:2::/64",
+ fillcolor="#d0e0d0",
+ style=filled,
+ ];
+ sw3 [
+ shape=oval,
+ label="sw3\n2001:db8:3::/64",
+ fillcolor="#d0e0d0",
+ style=filled,
+ ];
+
+ # Connections
+ subgraph cluster0 {
+ label="area 0.0.0.1";
+ r1 -- sw1 [label="eth0\n.2"];
+ }
+
+ subgraph cluster1 {
+ label="area 0.0.0.0";
+ r2 -- sw1 [label="eth0\n.1"];
+ r2 -- sw2 [label="eth1\n.2"];
+ r3 -- sw2 [label="eth0\n.1"];
+ r3 -- sw3 [label="eth1\n.2"];
+ }
+}
diff --git a/tests/topotests/ospf6-topo2/test_ospf6_topo2.png b/tests/topotests/ospf6-topo2/test_ospf6_topo2.png
new file mode 100644
index 0000000000..ee1de60736
--- /dev/null
+++ b/tests/topotests/ospf6-topo2/test_ospf6_topo2.png
Binary files differ
diff --git a/tests/topotests/ospf6-topo2/test_ospf6_topo2.py b/tests/topotests/ospf6-topo2/test_ospf6_topo2.py
new file mode 100644
index 0000000000..efc8565bb3
--- /dev/null
+++ b/tests/topotests/ospf6-topo2/test_ospf6_topo2.py
@@ -0,0 +1,184 @@
+#!/usr/bin/env python
+
+#
+# test_ospf6_topo2.py
+# Part of NetDEF Topology Tests
+#
+# Copyright (c) 2021 by
+# Network Device Education Foundation, Inc. ("NetDEF")
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+test_ospf6_topo2.py: Test the FRR OSPFv3 daemon.
+"""
+
+import os
+import sys
+from functools import partial
+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
+
+# Required to instantiate the topology builder class.
+from mininet.topo import Topo
+
+pytestmark = [pytest.mark.ospf6d]
+
+
+class OSPFv3Topo2(Topo):
+ "Test topology builder"
+
+ def build(self, *_args, **_opts):
+ "Build function"
+ tgen = get_topogen(self)
+
+ # Create 3 routers
+ for routern in range(1, 4):
+ tgen.add_router("r{}".format(routern))
+
+ switch = tgen.add_switch("s1")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r2"])
+
+ switch = tgen.add_switch("s2")
+ switch.add_link(tgen.gears["r2"])
+ switch.add_link(tgen.gears["r3"])
+
+
+def setup_module(mod):
+ "Sets up the pytest environment"
+ tgen = Topogen(OSPFv3Topo2, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+ for rname, router in router_list.items():
+ daemon_file = "{}/{}/zebra.conf".format(CWD, rname)
+ if os.path.isfile(daemon_file):
+ router.load_config(TopoRouter.RD_ZEBRA, daemon_file)
+
+ daemon_file = "{}/{}/ospf6d.conf".format(CWD, rname)
+ if os.path.isfile(daemon_file):
+ router.load_config(TopoRouter.RD_OSPF6, daemon_file)
+
+ # Initialize all routers.
+ tgen.start_router()
+
+
+def test_wait_protocol_convergence():
+ "Wait for OSPFv3 to converge"
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("waiting for protocols to converge")
+
+ def expect_neighbor_full(router, neighbor):
+ "Wait until OSPFv3 convergence."
+ logger.info("waiting OSPFv3 router '{}'".format(router))
+ test_func = partial(
+ topotest.router_json_cmp,
+ tgen.gears[router],
+ "show ipv6 ospf6 neighbor json",
+ {"neighbors": [{"neighborId": neighbor, "state": "Full"}]},
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=130, wait=1)
+ assertmsg = '"{}" convergence failure'.format(router)
+ assert result is None, assertmsg
+
+ expect_neighbor_full("r1", "10.254.254.2")
+ expect_neighbor_full("r2", "10.254.254.1")
+ expect_neighbor_full("r2", "10.254.254.3")
+ expect_neighbor_full("r3", "10.254.254.2")
+
+
+def test_ospf6_default_route():
+ "Wait for OSPFv3 default route in stub area."
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("waiting for default route")
+
+ def expect_route(router, route, metric):
+ "Test OSPF6 route existence."
+ logger.info("waiting OSPFv3 router '{}' routes".format(router))
+ test_func = partial(
+ topotest.router_json_cmp,
+ tgen.gears[router],
+ "show ipv6 route json",
+ {route: [{"metric": metric}]},
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=4, wait=1)
+ assertmsg = '"{}" convergence failure'.format(router)
+ assert result is None, assertmsg
+
+ def expect_lsa(router, area, prefix, metric):
+ "Test OSPF6 LSA existence."
+ logger.info("waiting OSPFv3 router '{}' LSA".format(router))
+ test_func = partial(
+ topotest.router_json_cmp,
+ tgen.gears[router],
+ "show ipv6 ospf6 database inter-prefix detail json",
+ {
+ "areaScopedLinkStateDb": [
+ {
+ "areaId": area,
+ "lsa": [
+ {
+ "prefix": prefix,
+ "metric": metric,
+ }
+ ],
+ }
+ ]
+ },
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=4, wait=1)
+ assertmsg = '"{}" convergence failure'.format(router)
+ assert result is None, assertmsg
+
+ metric = 123
+ expect_lsa("r1", "0.0.0.1", "::/0", metric)
+ expect_route("r1", "::/0", metric + 10)
+
+
+def teardown_module(_mod):
+ "Teardown the pytest environment"
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_memory_leak():
+ "Run the memory leak test and report results."
+ tgen = get_topogen()
+ if not tgen.is_memleak_enabled():
+ pytest.skip("Memory leak test/report is disabled")
+
+ tgen.report_memory_leaks()
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_chaos.py b/tests/topotests/ospf_basic_functionality/test_ospf_chaos.py
index cebe55b39c..c117fc6a72 100644
--- a/tests/topotests/ospf_basic_functionality/test_ospf_chaos.py
+++ b/tests/topotests/ospf_basic_functionality/test_ospf_chaos.py
@@ -249,17 +249,20 @@ def test_ospf_chaos_tc31_p1(request):
dut = "r1"
protocol = "ospf"
result = verify_ospf_rib(tgen, dut, input_dict, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: OSPF routes are present \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: OSPF routes are present \n Error: {}".format(
tc_name, result
- ))
+ )
- result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol,
- expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: routes are still present \n Error: {}".format(
+ result = verify_rib(
+ tgen, "ipv4", dut, input_dict, protocol=protocol, expected=False
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: routes are still present \n Error: {}".format(
tc_name, result
- ))
+ )
step("Bring up OSPFd daemon on R0.")
start_router_daemons(tgen, "r0", ["ospfd"])
@@ -482,17 +485,20 @@ def test_ospf_chaos_tc34_p1(request):
dut = "r1"
protocol = "ospf"
result = verify_ospf_rib(tgen, dut, input_dict, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: OSPF routes are present \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: OSPF routes are present \n Error: {}".format(
tc_name, result
- ))
+ )
- result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol,
- expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: routes are still present \n Error: {}".format(
+ result = verify_rib(
+ tgen, "ipv4", dut, input_dict, protocol=protocol, expected=False
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: routes are still present \n Error: {}".format(
tc_name, result
- ))
+ )
step("Bring up staticd daemon on R0.")
start_router_daemons(tgen, "r0", ["staticd"])
diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_ecmp.py b/tests/topotests/ospf_basic_functionality/test_ospf_ecmp.py
index adf82a5e85..1aabc06db0 100644
--- a/tests/topotests/ospf_basic_functionality/test_ospf_ecmp.py
+++ b/tests/topotests/ospf_basic_functionality/test_ospf_ecmp.py
@@ -259,19 +259,21 @@ def test_ospf_ecmp_tc16_p0(request):
shutdown_bringup_interface(tgen, dut, intf, False)
result = verify_ospf_rib(tgen, dut, input_dict, next_hop=nh, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: OSPF routes are present \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: OSPF routes are present \n Error: {}".format(
tc_name, result
- ))
+ )
protocol = "ospf"
result = verify_rib(
tgen, "ipv4", dut, input_dict, protocol=protocol, next_hop=nh, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: routes are still present \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: routes are still present \n Error: {}".format(
tc_name, result
- ))
+ )
for intfr in range(1, 7):
intf = topo["routers"]["r1"]["links"]["r0-link{}".format(intfr)]["interface"]
@@ -326,10 +328,11 @@ def test_ospf_ecmp_tc16_p0(request):
result = verify_ospf_rib(
tgen, dut, input_dict, next_hop=nh, attempts=5, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: OSPF routes are present \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: OSPF routes are present \n Error: {}".format(
tc_name, result
- ))
+ )
protocol = "ospf"
result = verify_rib(
@@ -342,10 +345,11 @@ def test_ospf_ecmp_tc16_p0(request):
attempts=5,
expected=False,
)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: routes are still present \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: routes are still present \n Error: {}".format(
tc_name, result
- ))
+ )
step("Re configure the static route in R0.")
dut = "r0"
@@ -432,10 +436,11 @@ def test_ospf_ecmp_tc17_p0(request):
result = verify_ospf_rib(
tgen, dut, input_dict, next_hop=nh, attempts=5, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: OSPF routes are present \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: OSPF routes are present \n Error: {}".format(
tc_name, result
- ))
+ )
protocol = "ospf"
result = verify_rib(
@@ -448,10 +453,11 @@ def test_ospf_ecmp_tc17_p0(request):
attempts=5,
expected=False,
)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: routes are still present \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: routes are still present \n Error: {}".format(
tc_name, result
- ))
+ )
step("Reconfigure the static route in R0.Change ECMP value to 2.")
dut = "r0"
diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_ecmp_lan.py b/tests/topotests/ospf_basic_functionality/test_ospf_ecmp_lan.py
index c5230d6614..e6dc18a434 100644
--- a/tests/topotests/ospf_basic_functionality/test_ospf_ecmp_lan.py
+++ b/tests/topotests/ospf_basic_functionality/test_ospf_ecmp_lan.py
@@ -307,10 +307,11 @@ def test_ospf_lan_ecmp_tc18_p0(request):
result = verify_ospf_rib(
tgen, dut, input_dict, next_hop=nh, attempts=5, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: OSPF routes are present \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: OSPF routes are present \n Error: {}".format(
tc_name, result
- ))
+ )
protocol = "ospf"
result = verify_rib(
@@ -323,10 +324,11 @@ def test_ospf_lan_ecmp_tc18_p0(request):
attempts=5,
expected=False,
)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: routes are still present \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: routes are still present \n Error: {}".format(
tc_name, result
- ))
+ )
write_test_footer(tc_name)
diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_lan.py b/tests/topotests/ospf_basic_functionality/test_ospf_lan.py
index 2fbb27f4fc..d9b90a132a 100644
--- a/tests/topotests/ospf_basic_functionality/test_ospf_lan.py
+++ b/tests/topotests/ospf_basic_functionality/test_ospf_lan.py
@@ -397,10 +397,11 @@ def test_ospf_lan_tc1_p0(request):
shutdown_bringup_interface(tgen, dut, intf, False)
result = verify_ospf_neighbor(tgen, topo, dut, lan=True, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "r0: OSPF neighbors-hip is up \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r0: OSPF neighbors-hip is up \n Error: {}".format(
tc_name, result
- ))
+ )
step("No Shut interface on R0")
dut = "r0"
diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_routemaps.py b/tests/topotests/ospf_basic_functionality/test_ospf_routemaps.py
index b99ce6cfb8..7864d0307a 100644
--- a/tests/topotests/ospf_basic_functionality/test_ospf_routemaps.py
+++ b/tests/topotests/ospf_basic_functionality/test_ospf_routemaps.py
@@ -332,18 +332,20 @@ def test_ospf_routemaps_functionality_tc19_p0(request):
}
}
result = verify_ospf_rib(tgen, dut, input_dict, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: OSPF routes are present \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: OSPF routes are present \n Error: {}".format(
tc_name, result
- ))
+ )
result = verify_rib(
tgen, "ipv4", dut, input_dict, protocol=protocol, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: routes are present in fib \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: routes are present in fib \n Error: {}".format(
tc_name, result
- ))
+ )
step("Delete and reconfigure prefix list.")
# Create ip prefix list
@@ -383,18 +385,20 @@ def test_ospf_routemaps_functionality_tc19_p0(request):
}
}
result = verify_ospf_rib(tgen, dut, input_dict, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: OSPF routes are present \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: OSPF routes are present \n Error: {}".format(
tc_name, result
- ))
+ )
result = verify_rib(
tgen, "ipv4", dut, input_dict, protocol=protocol, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: OSPF routes are present \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: OSPF routes are present \n Error: {}".format(
tc_name, result
- ))
+ )
pfx_list = {
"r0": {
@@ -438,18 +442,20 @@ def test_ospf_routemaps_functionality_tc19_p0(request):
}
}
result = verify_ospf_rib(tgen, dut, input_dict, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: OSPF routes are present \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: OSPF routes are present \n Error: {}".format(
tc_name, result
- ))
+ )
result = verify_rib(
tgen, "ipv4", dut, input_dict, protocol=protocol, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: routes are still present \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: routes are still present \n Error: {}".format(
tc_name, result
- ))
+ )
write_test_footer(tc_name)
@@ -496,18 +502,20 @@ def test_ospf_routemaps_functionality_tc20_p0(request):
dut = "r1"
protocol = "ospf"
result = verify_ospf_rib(tgen, dut, input_dict, attempts=2, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: OSPF routes are present \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: OSPF routes are present \n Error: {}".format(
tc_name, result
- ))
+ )
result = verify_rib(
tgen, "ipv4", dut, input_dict, protocol=protocol, attempts=2, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: routes are still present \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: routes are still present \n Error: {}".format(
tc_name, result
- ))
+ )
step(
"configure the route map with the same name that is used "
@@ -523,18 +531,20 @@ def test_ospf_routemaps_functionality_tc20_p0(request):
dut = "r1"
protocol = "ospf"
result = verify_ospf_rib(tgen, dut, input_dict, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: OSPF routes are present \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: OSPF routes are present \n Error: {}".format(
tc_name, result
- ))
+ )
result = verify_rib(
tgen, "ipv4", dut, input_dict, protocol=protocol, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: routes are still present \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: routes are still present \n Error: {}".format(
tc_name, result
- ))
+ )
# Create route map
routemaps = {"r0": {"route_maps": {"rmap_ipv4": [{"action": "deny"}]}}}
@@ -545,18 +555,20 @@ def test_ospf_routemaps_functionality_tc20_p0(request):
dut = "r1"
protocol = "ospf"
result = verify_ospf_rib(tgen, dut, input_dict, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: OSPF routes are present \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: OSPF routes are present \n Error: {}".format(
tc_name, result
- ))
+ )
result = verify_rib(
tgen, "ipv4", dut, input_dict, protocol=protocol, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: routes are still present \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: routes are still present \n Error: {}".format(
tc_name, result
- ))
+ )
step("Delete the route map.")
# Create route map
@@ -573,18 +585,20 @@ def test_ospf_routemaps_functionality_tc20_p0(request):
dut = "r1"
protocol = "ospf"
result = verify_ospf_rib(tgen, dut, input_dict, expected=False)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: OSPF routes are present \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: OSPF routes are present \n Error: {}".format(
tc_name, result
- ))
+ )
result = verify_rib(
tgen, "ipv4", dut, input_dict, protocol=protocol, expected=False
)
- assert result is not True, ("Testcase {} : Failed \n "
- "r1: routes are still present \n Error: {}".format(
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: routes are still present \n Error: {}".format(
tc_name, result
- ))
+ )
write_test_footer(tc_name)
diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py b/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py
index fb6b28ce5b..1432a82b12 100644
--- a/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py
+++ b/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py
@@ -247,11 +247,11 @@ def test_ospf_redistribution_tc5_p0(request):
if result is not True:
break
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r1: OSPF routes are present after deleting ip address of newly "
- "configured interface of R0 \n Error: {}".format(
- tc_name, result
- ))
+ "configured interface of R0 \n Error: {}".format(tc_name, result)
+ )
protocol = "ospf"
result = verify_rib(
@@ -264,11 +264,11 @@ def test_ospf_redistribution_tc5_p0(request):
attempts=5,
expected=False,
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r1: OSPF routes are present in fib after deleting ip address of newly "
- "configured interface of R0 \n Error: {}".format(
- tc_name, result
- ))
+ "configured interface of R0 \n Error: {}".format(tc_name, result)
+ )
step("Add back the deleted ip address on newly configured interface of R0")
topo1 = {
@@ -370,11 +370,11 @@ def test_ospf_redistribution_tc6_p0(request):
result = verify_ospf_rib(tgen, dut, input_dict, next_hop=nh, expected=False)
if result is not True:
break
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r1: OSPF routes are present after deleting ip address of newly "
- "configured loopback of R0 \n Error: {}".format(
- tc_name, result
- ))
+ "configured loopback of R0 \n Error: {}".format(tc_name, result)
+ )
protocol = "ospf"
result = verify_rib(
@@ -386,11 +386,11 @@ def test_ospf_redistribution_tc6_p0(request):
next_hop=nh,
expected=False,
)
- assert result is not True, ("Testcase {} : Failed \n "
+ assert result is not True, (
+ "Testcase {} : Failed \n "
"r1: OSPF routes are present in fib after deleting ip address of newly "
- "configured loopback of R0 \n Error: {}".format(
- tc_name, result
- ))
+ "configured loopback of R0 \n Error: {}".format(tc_name, result)
+ )
step("Add back the deleted ip address on newly configured interface of R0")
topo1 = {
diff --git a/tests/topotests/ospf_suppress_fa/__init__.py b/tests/topotests/ospf_suppress_fa/__init__.py
new file mode 100755
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/ospf_suppress_fa/__init__.py
diff --git a/tests/topotests/ospf_suppress_fa/r1/ospfd.conf b/tests/topotests/ospf_suppress_fa/r1/ospfd.conf
new file mode 100644
index 0000000000..c02be35b14
--- /dev/null
+++ b/tests/topotests/ospf_suppress_fa/r1/ospfd.conf
@@ -0,0 +1,9 @@
+!
+interface r1-eth0
+ ip ospf network point-to-point
+ ip ospf hello-interval 2
+ ip ospf dead-interval 10
+!
+router ospf
+ network 10.0.12.0/24 area 0
+!
diff --git a/tests/topotests/ospf_suppress_fa/r1/zebra.conf b/tests/topotests/ospf_suppress_fa/r1/zebra.conf
new file mode 100644
index 0000000000..c1e31fb474
--- /dev/null
+++ b/tests/topotests/ospf_suppress_fa/r1/zebra.conf
@@ -0,0 +1,4 @@
+!
+interface r1-eth0
+ ip address 10.0.12.1/24
+!
diff --git a/tests/topotests/ospf_suppress_fa/r2/ospfd.conf b/tests/topotests/ospf_suppress_fa/r2/ospfd.conf
new file mode 100644
index 0000000000..ebc7d252fd
--- /dev/null
+++ b/tests/topotests/ospf_suppress_fa/r2/ospfd.conf
@@ -0,0 +1,16 @@
+!
+interface r2-eth0
+ ip ospf network point-to-point
+ ip ospf hello-interval 2
+ ip ospf dead-interval 10
+!
+interface r2-eth1
+ ip ospf network point-to-point
+ ip ospf hello-interval 2
+ ip ospf dead-interval 10
+!
+router ospf
+ network 10.0.12.0/24 area 0
+ network 10.0.23.0/24 area 1
+ area 1 nssa
+!
diff --git a/tests/topotests/ospf_suppress_fa/r2/zebra.conf b/tests/topotests/ospf_suppress_fa/r2/zebra.conf
new file mode 100644
index 0000000000..9f1a26349e
--- /dev/null
+++ b/tests/topotests/ospf_suppress_fa/r2/zebra.conf
@@ -0,0 +1,7 @@
+!
+interface r2-eth0
+ ip address 10.0.12.2/24
+!
+interface r2-eth1
+ ip address 10.0.23.2/24
+!
diff --git a/tests/topotests/ospf_suppress_fa/r3/ospfd.conf b/tests/topotests/ospf_suppress_fa/r3/ospfd.conf
new file mode 100644
index 0000000000..08be11a7b7
--- /dev/null
+++ b/tests/topotests/ospf_suppress_fa/r3/ospfd.conf
@@ -0,0 +1,11 @@
+!
+interface r3-eth0
+ ip ospf network point-to-point
+ ip ospf hello-interval 2
+ ip ospf dead-interval 10
+!
+router ospf
+ redistribute static
+ network 10.0.23.0/24 area 1
+ area 1 nssa
+!
diff --git a/tests/topotests/ospf_suppress_fa/r3/zebra.conf b/tests/topotests/ospf_suppress_fa/r3/zebra.conf
new file mode 100644
index 0000000000..f76cbf74d2
--- /dev/null
+++ b/tests/topotests/ospf_suppress_fa/r3/zebra.conf
@@ -0,0 +1,8 @@
+!
+ip route 3.3.1.1/32 Null0
+ip route 3.3.2.2/32 Null0
+ip route 3.3.3.3/32 Null0
+!
+interface r3-eth0
+ ip address 10.0.23.3/24
+!
diff --git a/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.dot b/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.dot
new file mode 100644
index 0000000000..1036658f1a
--- /dev/null
+++ b/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.dot
@@ -0,0 +1,66 @@
+## Color coding:
+#########################
+## Main FRR: #f08080 red
+## Switches: #d0e0d0 gray
+## RIP: #19e3d9 Cyan
+## RIPng: #fcb314 dark yellow
+## OSPFv2: #32b835 Green
+## OSPFv3: #19e3d9 Cyan
+## ISIS IPv4 #fcb314 dark yellow
+## ISIS IPv6 #9a81ec purple
+## BGP IPv4 #eee3d3 beige
+## BGP IPv6 #fdff00 yellow
+##### Colors (see http://www.color-hex.com/)
+
+graph ospf_topo1 {
+ label="ospf suppress-fa";
+
+ # Routers
+ r1 [
+ label="r1\nrtr-id 10.0.12.1",
+ shape=doubleoctagon,
+ fillcolor="#f08080",
+ style=filled,
+ ];
+ r2 [
+ label="r2 (ABR)\nrtr-id 10.0.23.2",
+ shape=doubleoctagon,
+ fillcolor="#f08080",
+ style=filled,
+ ];
+ r3 [
+ label="r3 (ASBR)\nrtr-id 10.0.23.3",
+ shape=doubleoctagon,
+ fillcolor="#f08080",
+ style=filled,
+ ];
+
+ # Switches
+ s1 [
+ label="s1\n10.0.12.0/24",
+ shape=oval,
+ fillcolor="#d0e0d0",
+ style=filled,
+ ];
+ s2 [
+ label="s2\n10.0.23.0/24",
+ shape=oval,
+ fillcolor="#d0e0d0",
+ style=filled,
+ ];
+
+ # Connections
+ subgraph cluster0 {
+ label="area 0"
+ r1 -- s1 [label="eth1\n.1"];
+ r2 -- s1 [label="eth1\n.2"];
+ }
+
+ subgraph cluster1 {
+ label="area 1\nNSSA"
+ r2 -- s2 [label="eth2\n.2"];
+ r3 -- s2 [label="eth1\n.3"];
+ }
+
+ { rank=same; r1; r2; r3; }
+}
diff --git a/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.dot.jpg b/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.dot.jpg
new file mode 100644
index 0000000000..2907d799f5
--- /dev/null
+++ b/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.dot.jpg
Binary files differ
diff --git a/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.py b/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.py
new file mode 100644
index 0000000000..76e50beb5c
--- /dev/null
+++ b/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.py
@@ -0,0 +1,192 @@
+#!/usr/bin/env python
+
+#
+# test_ospf_suppres_fa.py
+# Carles Kishimoto
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+test_ospf_suppres_fa.py: Test OSPF suppress-fa feature
+- Topology: r1 --- R2 (ABR) --- R3 (redistribute static)
+
+test_ospf_set_suppress_fa()
+ 1) R1: Get a dict[LSA_ID] = fwd_addr for all type 5 LSA
+ 2) R2: Configure: area 1 nssa suppress-fa
+ 3) R1: Get a dict[LSA_ID] and compare fwd_address with 0.0.0.0
+
+test_ospf_unset_suppress_fa()
+ 4) R2: Configure: no area 1 nssa suppress-fa
+ 5) R1: Get a dict[LSA_ID] = fwd_addr and compare it with the dict obtained in 1)
+"""
+
+import os
+import sys
+import re
+import pytest
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+
+# Required to instantiate the topology builder class.
+from mininet.topo import Topo
+
+
+class NetworkTopo(Topo):
+ "OSPF topology builder"
+
+ def build(self, *_args, **_opts):
+ "Build function"
+
+ tgen = get_topogen(self)
+
+ # Create routers
+ for router in range(1, 4):
+ tgen.add_router("r{}".format(router))
+
+ # R1-R2 backbone area
+ switch = tgen.add_switch("s1")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r2"])
+
+ # R2-R3 NSSA area
+ switch = tgen.add_switch("s2")
+ switch.add_link(tgen.gears["r2"])
+ switch.add_link(tgen.gears["r3"])
+
+
+def setup_module(mod):
+ "Sets up the pytest environment"
+
+ tgen = Topogen(NetworkTopo, mod.__name__)
+ tgen.start_topology()
+
+ # This is a sample of configuration loading.
+ router_list = tgen.routers()
+
+ # For all registred routers, load the zebra and ospf configuration file
+ for rname, router in router_list.items():
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_OSPF, os.path.join(CWD, "{}/ospfd.conf".format(rname))
+ )
+
+ tgen.start_router()
+
+
+def teardown_module(_mod):
+ "Teardown the pytest environment"
+
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_converge_protocols():
+ "Wait for protocol convergence"
+
+ tgen = get_topogen()
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ topotest.sleep(10, "Waiting for OSPF convergence")
+
+
+def ospf_configure_suppress_fa(router_name, area):
+ "Configure OSPF suppress-fa in router_name"
+
+ tgen = get_topogen()
+ router = tgen.gears[router_name]
+ router.vtysh_cmd(
+ "conf t\nrouter ospf\narea {} nssa suppress-fa\nexit\n".format(area)
+ )
+
+
+def ospf_unconfigure_suppress_fa(router_name, area):
+ "Remove OSPF suppress-fa in router_name"
+
+ tgen = get_topogen()
+ router = tgen.gears[router_name]
+ router.vtysh_cmd(
+ "conf t\nrouter ospf\nno area {} nssa suppress-fa\nexit\n".format(area)
+ )
+
+
+def ospf_get_lsa_type5(router_name):
+ "Return a dict with link state id as key and forwarding addresses as value"
+
+ result = dict()
+ tgen = get_topogen()
+ router = tgen.gears[router_name]
+ cmd = "show ip ospf database external\n"
+ output = topotest.normalize_text(router.vtysh_cmd(cmd))
+ for line in output.splitlines():
+ re0 = re.match(r"\s+Link State ID: (\S+) \(External Network Number\)", line)
+ if re0:
+ lsa = re0.group(1)
+ re1 = re.match(r"\s+Forward Address: (\S+)", line)
+ if re1:
+ result[lsa] = re1.group(1)
+ return result
+
+
+@pytest.fixture(scope="module", name="original")
+def test_ospf_set_suppress_fa():
+ "Test OSPF area [x] nssa suppress-fa"
+
+ # Get current forwarding address for each LSA type-5 in r1
+ initial = ospf_get_lsa_type5("r1")
+
+ # Configure suppres-fa in r2 area 1
+ ospf_configure_suppress_fa("r2", "1")
+ topotest.sleep(10, "Waiting for OSPF convergence")
+
+ # Check forwarding address on r1 for all statics is 0.0.0.0
+ assertmsg = "Forwarding address is not 0.0.0.0 after enabling OSPF suppress-fa"
+ suppress = ospf_get_lsa_type5("r1")
+ for prefix in suppress:
+ assert suppress[prefix] == "0.0.0.0", assertmsg
+
+ # Return the original forwarding addresses so we can compare them
+ # in the test_ospf_unset_supress_fa
+ return initial
+
+
+def test_ospf_unset_supress_fa(original):
+ "Test OSPF no area [x] nssa suppress-fa"
+
+ # Remove suppress-fa in r2 area 1
+ ospf_unconfigure_suppress_fa("r2", "1")
+ topotest.sleep(10, "Waiting for OSPF convergence")
+
+ # Check forwarding address is the original value on r1 for all statics
+ assertmsg = "Forwarding address is not correct after removing OSPF suppress-fa"
+ restore = ospf_get_lsa_type5("r1")
+ for prefix in restore:
+ assert restore[prefix] == original[prefix], assertmsg
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/static_routing_with_ebgp/test_static_routes_topo4_ebgp.py b/tests/topotests/static_routing_with_ebgp/test_static_routes_topo4_ebgp.py
index dc4e29ebde..5d4950a70e 100644
--- a/tests/topotests/static_routing_with_ebgp/test_static_routes_topo4_ebgp.py
+++ b/tests/topotests/static_routing_with_ebgp/test_static_routes_topo4_ebgp.py
@@ -949,10 +949,11 @@ def static_routes_rmap_pfxlist_p0_tc7_ebgp(request):
result4 = verify_rib(
tgen, addr_type, dut, input_dict, protocol=protocol, expected=False
)
- assert result4 is not True, ("Testcase {} : Failed \n"
- "routes are still present \n Error: {}".format(
+ assert (
+ result4 is not True
+ ), "Testcase {} : Failed \n" "routes are still present \n Error: {}".format(
tc_name, result4
- ))
+ )
step("vm4 should be present in FRR1")
dut = "r1"
diff --git a/tests/topotests/static_routing_with_ibgp/test_static_routes_topo4_ibgp.py b/tests/topotests/static_routing_with_ibgp/test_static_routes_topo4_ibgp.py
index 14db729195..09c437c3c4 100644
--- a/tests/topotests/static_routing_with_ibgp/test_static_routes_topo4_ibgp.py
+++ b/tests/topotests/static_routing_with_ibgp/test_static_routes_topo4_ibgp.py
@@ -947,10 +947,11 @@ def test_static_routes_rmap_pfxlist_p0_tc7_ibgp(request):
result4 = verify_rib(
tgen, addr_type, dut, input_dict, protocol=protocol, expected=False
)
- assert result4 is not True, ("Testcase {} : Failed \n"
- "routes are still present \n Error: {}".format(
+ assert (
+ result4 is not True
+ ), "Testcase {} : Failed \n" "routes are still present \n Error: {}".format(
tc_name, result4
- ))
+ )
step("vm4 should be present in FRR1")
dut = "r1"