diff options
Diffstat (limited to 'tests')
50 files changed, 1181 insertions, 206 deletions
diff --git a/tests/.gitignore b/tests/.gitignore index fb2edc939a..3fad1b0813 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -25,6 +25,8 @@ /lib/test_atomlist /lib/test_buffer /lib/test_checksum +/lib/test_frrscript +/lib/test_frrlua /lib/test_graph /lib/test_heavy /lib/test_heavy_thread diff --git a/tests/bgpd/test_peer_attr.c b/tests/bgpd/test_peer_attr.c index 44b55a2381..45e9912a31 100644 --- a/tests/bgpd/test_peer_attr.c +++ b/tests/bgpd/test_peer_attr.c @@ -31,6 +31,7 @@ #include "bgpd/bgp_zebra.h" #include "bgpd/bgp_network.h" #include "lib/routing_nb.h" +#include "lib/northbound_cli.h" #include "bgpd/bgp_nb.h" #ifdef ENABLE_BGP_VNC diff --git a/tests/lib/script1.lua b/tests/lib/script1.lua new file mode 100644 index 0000000000..e9ebc29bd9 --- /dev/null +++ b/tests/lib/script1.lua @@ -0,0 +1 @@ +a = a + b diff --git a/tests/lib/test_frrlua.c b/tests/lib/test_frrlua.c new file mode 100644 index 0000000000..a81446f9ca --- /dev/null +++ b/tests/lib/test_frrlua.c @@ -0,0 +1,111 @@ +/* + * frrlua unit tests + * Copyright (C) 2021 Donald Lee + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <zebra.h> +#include "string.h" +#include "stdio.h" +#include "lib/frrlua.h" + +static void test_encode_decode(void) +{ + lua_State *L = luaL_newstate(); + + long long a = 123; + long long b = a; + + lua_pushintegerp(L, &a); + lua_decode_integerp(L, -1, &a); + assert(a == b); + assert(lua_gettop(L) == 0); + + time_t time_a = 100; + time_t time_b = time_a; + + lua_pushtimet(L, &time_a); + lua_decode_timet(L, -1, &time_a); + assert(time_a == time_b); + assert(lua_gettop(L) == 0); + + char str_b[] = "Hello", str_a[6]; + + strlcpy(str_a, str_b, sizeof(str_b)); + lua_pushstring_wrapper(L, str_a); + lua_decode_stringp(L, -1, str_a); + assert(strncmp(str_a, str_b, sizeof(str_b)) == 0); + assert(lua_gettop(L) == 0); + + char p_b_str[] = "10.0.0.0/24", p_a_str[12]; + struct prefix p_a; + + strlcpy(p_a_str, p_b_str, sizeof(p_b_str)); + str2prefix(p_a_str, &p_a); + lua_pushprefix(L, &p_a); + lua_decode_prefix(L, -1, &p_a); + prefix2str(&p_a, p_a_str, sizeof(p_b_str)); + assert(strncmp(p_a_str, p_b_str, sizeof(p_b_str)) == 0); + assert(lua_gettop(L) == 0); + + struct interface ifp_a; + struct interface ifp_b = ifp_a; + + lua_pushinterface(L, &ifp_a); + lua_decode_interface(L, -1, &ifp_a); + assert(strncmp(ifp_a.name, ifp_b.name, sizeof(ifp_b.name)) == 0); + assert(ifp_a.ifindex == ifp_b.ifindex); + assert(ifp_a.status == ifp_b.status); + assert(ifp_a.flags == ifp_b.flags); + assert(ifp_a.metric == ifp_b.metric); + assert(ifp_a.speed == ifp_b.speed); + assert(ifp_a.mtu == ifp_b.mtu); + assert(ifp_a.mtu6 == ifp_b.mtu6); + assert(ifp_a.bandwidth == ifp_b.bandwidth); + assert(ifp_a.link_ifindex == ifp_b.link_ifindex); + assert(ifp_a.ll_type == ifp_b.ll_type); + assert(lua_gettop(L) == 0); + + struct in_addr addr_a; + struct in_addr addr_b = addr_a; + + lua_pushinaddr(L, &addr_a); + lua_decode_inaddr(L, -1, &addr_a); + assert(addr_a.s_addr == addr_b.s_addr); + assert(lua_gettop(L) == 0); + + struct in6_addr in6addr_a; + struct in6_addr in6addr_b = in6addr_a; + + lua_pushin6addr(L, &in6addr_a); + lua_decode_in6addr(L, -1, &in6addr_a); + assert(in6addr_cmp(&in6addr_a, &in6addr_b) == 0); + assert(lua_gettop(L) == 0); + + union sockunion su_a, su_b; + + memset(&su_a, 0, sizeof(union sockunion)); + memset(&su_b, 0, sizeof(union sockunion)); + lua_pushsockunion(L, &su_a); + lua_decode_sockunion(L, -1, &su_a); + assert(sockunion_cmp(&su_a, &su_b) == 0); + assert(lua_gettop(L) == 0); +} + +int main(int argc, char **argv) +{ + test_encode_decode(); +} diff --git a/tests/lib/test_frrlua.py b/tests/lib/test_frrlua.py new file mode 100644 index 0000000000..2f6ddc1c07 --- /dev/null +++ b/tests/lib/test_frrlua.py @@ -0,0 +1,14 @@ +import frrtest +import pytest + +if 'S["SCRIPTING_TRUE"]=""\n' not in open("../config.status").readlines(): + class TestFrrlua: + @pytest.mark.skipif(True, reason="Test unsupported") + def test_exit_cleanly(self): + pass +else: + + class TestFrrlua(frrtest.TestMultiOut): + program = "./test_frrlua" + + TestFrrlua.exit_cleanly() diff --git a/tests/lib/test_frrscript.c b/tests/lib/test_frrscript.c new file mode 100644 index 0000000000..bd75cc5552 --- /dev/null +++ b/tests/lib/test_frrscript.c @@ -0,0 +1,37 @@ +/* + * frrscript unit tests + * Copyright (C) 2021 Donald Lee + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <zebra.h> + +#include "lib/frrscript.h" + +int main(int argc, char **argv) +{ + frrscript_init("./lib"); + + struct frrscript *fs = frrscript_load("script1", NULL); + long long a = 100, b = 200; + int result = frrscript_call(fs, ("a", &a), ("b", &b)); + + assert(result == 0); + assert(a == 300); + assert(b == 200); + + return 0; +} diff --git a/tests/lib/test_frrscript.py b/tests/lib/test_frrscript.py new file mode 100644 index 0000000000..046d97b014 --- /dev/null +++ b/tests/lib/test_frrscript.py @@ -0,0 +1,14 @@ +import frrtest +import pytest + +if 'S["SCRIPTING_TRUE"]=""\n' not in open("../config.status").readlines(): + class TestFrrscript: + @pytest.mark.skipif(True, reason="Test unsupported") + def test_exit_cleanly(self): + pass +else: + + class TestFrrscript(frrtest.TestMultiOut): + program = "./test_frrscript" + + TestFrrscript.exit_cleanly() diff --git a/tests/subdir.am b/tests/subdir.am index ca477851e3..c2153140f5 100644 --- a/tests/subdir.am +++ b/tests/subdir.am @@ -59,6 +59,15 @@ TESTS_ZEBRA = IGNORE_ZEBRA = --ignore=zebra/ endif +if SCRIPTING +TESTS_SCRIPTING = \ + tests/lib/test_frrlua \ + tests/lib/test_frrscript \ + #end +else +TESTS_SCRIPTING = +endif + clippy_scan += \ tests/lib/cli/test_cli.c \ tests/ospf6d/test_lsdb.c \ @@ -104,6 +113,7 @@ check_PROGRAMS = \ $(TESTS_OSPFD) \ $(TESTS_OSPF6D) \ $(TESTS_ZEBRA) \ + $(TESTS_SCRIPTING) \ # end if GRPC @@ -289,6 +299,16 @@ tests_lib_test_checksum_CFLAGS = $(TESTS_CFLAGS) tests_lib_test_checksum_CPPFLAGS = $(TESTS_CPPFLAGS) tests_lib_test_checksum_LDADD = $(ALL_TESTS_LDADD) tests_lib_test_checksum_SOURCES = tests/lib/test_checksum.c +if SCRIPTING +tests_lib_test_frrlua_CFLAGS = $(TESTS_CFLAGS) +tests_lib_test_frrlua_CPPFLAGS = $(TESTS_CPPFLAGS) +tests_lib_test_frrlua_LDADD = $(ALL_TESTS_LDADD) +tests_lib_test_frrlua_SOURCES = tests/lib/test_frrlua.c +tests_lib_test_frrscript_CFLAGS = $(TESTS_CFLAGS) +tests_lib_test_frrscript_CPPFLAGS = $(TESTS_CPPFLAGS) +tests_lib_test_frrscript_LDADD = $(ALL_TESTS_LDADD) +tests_lib_test_frrscript_SOURCES = tests/lib/test_frrscript.c +endif tests_lib_test_graph_CFLAGS = $(TESTS_CFLAGS) tests_lib_test_graph_CPPFLAGS = $(TESTS_CPPFLAGS) tests_lib_test_graph_LDADD = $(ALL_TESTS_LDADD) @@ -464,6 +484,14 @@ EXTRA_DIST += \ tests/zebra/test_lm_plugin.refout \ # end + +if SCRIPTING +EXTRA_DIST += \ + tests/lib/test_frrscript.py \ + tests/lib/test_frrlua.py \ + #end +endif + .PHONY: tests/tests.xml tests/tests.xml: $(check_PROGRAMS) ( cd tests; $(PYTHON) ../$(srcdir)/tests/runtests.py --junitxml=tests.xml -v ../$(srcdir)/tests $(IGNORE_BGPD) $(IGNORE_ISISD) $(IGNORE_OSPF6D); ) diff --git a/tests/topotests/bgp_default_ipv4_ipv6_unicast/__init__.py b/tests/topotests/bgp_default_afi_safi/__init__.py index e69de29bb2..e69de29bb2 100644 --- a/tests/topotests/bgp_default_ipv4_ipv6_unicast/__init__.py +++ b/tests/topotests/bgp_default_afi_safi/__init__.py diff --git a/tests/topotests/bgp_default_ipv4_ipv6_unicast/r1/bgpd.conf b/tests/topotests/bgp_default_afi_safi/r1/bgpd.conf index bf39152ea8..bf39152ea8 100644 --- a/tests/topotests/bgp_default_ipv4_ipv6_unicast/r1/bgpd.conf +++ b/tests/topotests/bgp_default_afi_safi/r1/bgpd.conf diff --git a/tests/topotests/bgp_default_ipv4_ipv6_unicast/r1/zebra.conf b/tests/topotests/bgp_default_afi_safi/r1/zebra.conf index 697765168d..697765168d 100644 --- a/tests/topotests/bgp_default_ipv4_ipv6_unicast/r1/zebra.conf +++ b/tests/topotests/bgp_default_afi_safi/r1/zebra.conf diff --git a/tests/topotests/bgp_default_ipv4_ipv6_unicast/r2/bgpd.conf b/tests/topotests/bgp_default_afi_safi/r2/bgpd.conf index abbd1b86fa..abbd1b86fa 100644 --- a/tests/topotests/bgp_default_ipv4_ipv6_unicast/r2/bgpd.conf +++ b/tests/topotests/bgp_default_afi_safi/r2/bgpd.conf diff --git a/tests/topotests/bgp_default_ipv4_ipv6_unicast/r2/zebra.conf b/tests/topotests/bgp_default_afi_safi/r2/zebra.conf index 606c17bec9..606c17bec9 100644 --- a/tests/topotests/bgp_default_ipv4_ipv6_unicast/r2/zebra.conf +++ b/tests/topotests/bgp_default_afi_safi/r2/zebra.conf diff --git a/tests/topotests/bgp_default_afi_safi/r3/bgpd.conf b/tests/topotests/bgp_default_afi_safi/r3/bgpd.conf new file mode 100644 index 0000000000..f3ec3f06c5 --- /dev/null +++ b/tests/topotests/bgp_default_afi_safi/r3/bgpd.conf @@ -0,0 +1,5 @@ +! +router bgp 65001 + no bgp default ipv4-unicast + bgp default l2vpn-evpn +! diff --git a/tests/topotests/bgp_default_ipv4_ipv6_unicast/r3/zebra.conf b/tests/topotests/bgp_default_afi_safi/r3/zebra.conf index e9fdfb70c5..e9fdfb70c5 100644 --- a/tests/topotests/bgp_default_ipv4_ipv6_unicast/r3/zebra.conf +++ b/tests/topotests/bgp_default_afi_safi/r3/zebra.conf diff --git a/tests/topotests/bgp_default_ipv4_ipv6_unicast/r3/bgpd.conf b/tests/topotests/bgp_default_afi_safi/r4/bgpd.conf index a405c047ca..8a6af55ee7 100644 --- a/tests/topotests/bgp_default_ipv4_ipv6_unicast/r3/bgpd.conf +++ b/tests/topotests/bgp_default_afi_safi/r4/bgpd.conf @@ -1,4 +1,5 @@ ! router bgp 65001 bgp default ipv6-unicast + bgp default l2vpn-evpn ! diff --git a/tests/topotests/bgp_default_afi_safi/r4/zebra.conf b/tests/topotests/bgp_default_afi_safi/r4/zebra.conf new file mode 100644 index 0000000000..e9fdfb70c5 --- /dev/null +++ b/tests/topotests/bgp_default_afi_safi/r4/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_afi_safi/test_bgp-default-afi-safi.py index f9aa94fd14..28117b7fe4 100644 --- a/tests/topotests/bgp_default_ipv4_ipv6_unicast/test_bgp-default-ipv4-ipv6-unicast.py +++ b/tests/topotests/bgp_default_afi_safi/test_bgp-default-afi-safi.py @@ -20,12 +20,13 @@ # """ -Test if `bgp default ipv4-unicast` and `bgp default ipv6-unicast` -commands work as expected. +Test if `bgp default ipv4-unicast`, `bgp default ipv6-unicast` +and `bgp default l2vpn-evpn` 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' +STEP 3: 'Check if neighbor 192.168.255.254 is enabled for l2vpn evpn address-family only' +STEP 4: 'Check if neighbor 192.168.255.254 is enabled for ipv4/ipv6 unicast and l2vpn evpn address-families' """ import os @@ -98,7 +99,7 @@ def test_bgp_default_ipv4_ipv6_unicast(): output = json.loads(tgen.gears["r1"].vtysh_cmd("show bgp summary json")) - if "ipv4Unicast" in output and "ipv6Unicast" not in output: + if len(output.keys()) == 1 and "ipv4Unicast" in output: return True return False @@ -113,28 +114,48 @@ def test_bgp_default_ipv4_ipv6_unicast(): output = json.loads(tgen.gears["r2"].vtysh_cmd("show bgp summary json")) - if "ipv4Unicast" not in output and "ipv6Unicast" in output: + if len(output.keys()) == 1 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" - ) + step("Check if neighbor 192.168.255.254 is enabled for evpn address-family only") - def _bgp_neighbor_ipv4_and_ipv6_af(): + def _bgp_neighbor_evpn_af_only(): 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: + if len(output.keys()) == 1 and "l2VpnEvpn" in output: + return True + return False + + assert _bgp_neighbor_evpn_af_only() == True + + step( + "Check if neighbor 192.168.255.254 is enabled for ipv4/ipv6 unicast and evpn address-families" + ) + + def _bgp_neighbor_ipv4_ipv6_and_evpn_af(): + tgen.gears["r4"].vtysh_cmd( + "conf t\nrouter bgp\nneighbor 192.168.255.254 remote-as external" + ) + + output = json.loads(tgen.gears["r4"].vtysh_cmd("show bgp summary json")) + + if ( + len(output.keys()) == 3 + and "ipv4Unicast" in output + and "ipv6Unicast" in output + and "l2VpnEvpn" in output + ): return True return False - assert _bgp_neighbor_ipv4_and_ipv6_af() == True + assert _bgp_neighbor_ipv4_ipv6_and_evpn_af() == True if __name__ == "__main__": diff --git a/tests/topotests/lib/bgp.py b/tests/topotests/lib/bgp.py index db7b3586f1..a236a916b5 100644 --- a/tests/topotests/lib/bgp.py +++ b/tests/topotests/lib/bgp.py @@ -989,7 +989,7 @@ def modify_bgp_config_when_bgpd_down(tgen, topo, input_dict): ############################################# # Verification APIs ############################################# -@retry(attempts=4, wait=2, return_is_str=True) +@retry(retry_timeout=8) def verify_router_id(tgen, topo, input_dict, expected=True): """ Running command "show ip bgp json" for DUT and reading router-id @@ -1061,7 +1061,7 @@ def verify_router_id(tgen, topo, input_dict, expected=True): return True -@retry(attempts=50, wait=3, return_is_str=True) +@retry(retry_timeout=150) def verify_bgp_convergence(tgen, topo, dut=None, expected=True): """ API will verify if BGP is converged with in the given time frame. @@ -1266,7 +1266,7 @@ def verify_bgp_convergence(tgen, topo, dut=None, expected=True): return True -@retry(attempts=4, wait=4, return_is_str=True) +@retry(retry_timeout=16) def verify_bgp_community( tgen, addr_type, router, network, input_dict=None, vrf=None, bestpath=False, expected=True ): @@ -1427,7 +1427,7 @@ def modify_as_number(tgen, topo, input_dict): return True -@retry(attempts=4, wait=2, return_is_str=True) +@retry(retry_timeout=8) def verify_as_numbers(tgen, topo, input_dict, expected=True): """ This API is to verify AS numbers for given DUT by running @@ -1527,7 +1527,7 @@ def verify_as_numbers(tgen, topo, input_dict, expected=True): return True -@retry(attempts=50, wait=3, return_is_str=True) +@retry(retry_timeout=150) def verify_bgp_convergence_from_running_config(tgen, dut=None, expected=True): """ API to verify BGP convergence b/w loopback and physical interface. @@ -2083,7 +2083,7 @@ def verify_bgp_timers_and_functionality(tgen, topo, input_dict): return True -@retry(attempts=4, wait=4, return_is_str=True) +@retry(retry_timeout=16) def verify_bgp_attributes( tgen, addr_type, @@ -2223,7 +2223,7 @@ def verify_bgp_attributes( return True -@retry(attempts=4, wait=2, return_is_str=True) +@retry(retry_timeout=8) def verify_best_path_as_per_bgp_attribute( tgen, addr_type, router, input_dict, attribute, expected=True ): @@ -2429,7 +2429,7 @@ def verify_best_path_as_per_bgp_attribute( return True -@retry(attempts=5, wait=2, return_is_str=True) +@retry(retry_timeout=10) def verify_best_path_as_per_admin_distance( tgen, addr_type, router, input_dict, attribute, expected=True ): @@ -2543,7 +2543,7 @@ def verify_best_path_as_per_admin_distance( return True -@retry(attempts=5, wait=2, return_is_str=True, initial_wait=2) +@retry(retry_timeout=10, initial_wait=2) def verify_bgp_rib( tgen, addr_type, dut, input_dict, next_hop=None, aspath=None, multi_nh=None, expected=True ): @@ -2846,7 +2846,7 @@ def verify_bgp_rib( return True -@retry(attempts=5, wait=2, return_is_str=True) +@retry(retry_timeout=10) def verify_graceful_restart(tgen, topo, addr_type, input_dict, dut, peer, expected=True): """ This API is to verify verify_graceful_restart configuration of DUT and @@ -3096,7 +3096,7 @@ def verify_graceful_restart(tgen, topo, addr_type, input_dict, dut, peer, expect return True -@retry(attempts=5, wait=2, return_is_str=True) +@retry(retry_timeout=10) def verify_r_bit(tgen, topo, addr_type, input_dict, dut, peer, expected=True): """ This API is to verify r_bit in the BGP gr capability advertised @@ -3216,7 +3216,7 @@ def verify_r_bit(tgen, topo, addr_type, input_dict, dut, peer, expected=True): return True -@retry(attempts=5, wait=2, return_is_str=True) +@retry(retry_timeout=10) def verify_eor(tgen, topo, addr_type, input_dict, dut, peer, expected=True): """ This API is to verify EOR @@ -3379,7 +3379,7 @@ def verify_eor(tgen, topo, addr_type, input_dict, dut, peer, expected=True): return True -@retry(attempts=4, wait=2, return_is_str=True) +@retry(retry_timeout=8) def verify_f_bit(tgen, topo, addr_type, input_dict, dut, peer, expected=True): """ This API is to verify f_bit in the BGP gr capability advertised @@ -3520,7 +3520,7 @@ def verify_f_bit(tgen, topo, addr_type, input_dict, dut, peer, expected=True): return True -@retry(attempts=5, wait=2, return_is_str=True) +@retry(retry_timeout=10) def verify_graceful_restart_timers(tgen, topo, addr_type, input_dict, dut, peer): """ This API is to verify graceful restart timers, configured and recieved @@ -3648,7 +3648,7 @@ def verify_graceful_restart_timers(tgen, topo, addr_type, input_dict, dut, peer) return True -@retry(attempts=4, wait=2, return_is_str=True) +@retry(retry_timeout=8) def verify_gr_address_family(tgen, topo, addr_type, addr_family, dut, expected=True): """ This API is to verify gr_address_family in the BGP gr capability advertised @@ -3739,7 +3739,7 @@ def verify_gr_address_family(tgen, topo, addr_type, addr_family, dut, expected=T logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name)) -@retry(attempts=6, wait=2, return_is_str=True) +@retry(retry_timeout=12) def verify_attributes_for_evpn_routes( tgen, topo, @@ -4139,7 +4139,7 @@ def verify_attributes_for_evpn_routes( return False -@retry(attempts=5, wait=2, return_is_str=True) +@retry(retry_timeout=10) def verify_evpn_routes( tgen, topo, dut, input_dict, routeType=5, EthTag=0, next_hop=None, expected=True ): diff --git a/tests/topotests/lib/common_config.py b/tests/topotests/lib/common_config.py index 3f78f020bc..d659b8d52d 100644 --- a/tests/topotests/lib/common_config.py +++ b/tests/topotests/lib/common_config.py @@ -19,7 +19,7 @@ # from collections import OrderedDict -from datetime import datetime +from datetime import datetime, timedelta from time import sleep from copy import deepcopy from subprocess import call @@ -37,12 +37,14 @@ import socket import ipaddress import platform -if sys.version_info[0] > 2: - import io - import configparser -else: - import StringIO +try: + # Imports from python2 + from StringIO import StringIO import ConfigParser as configparser +except ImportError: + # Imports from python3 + from io import StringIO + import configparser from lib.topolog import logger, logger_config from lib.topogen import TopoRouter, get_topogen @@ -136,6 +138,12 @@ DEBUG_LOGS = { ], } +def is_string(value): + try: + return isinstance(value, basestring) + except NameError: + return isinstance(value, str) + if config.has_option("topogen", "verbosity"): loglevel = config.get("topogen", "verbosity") loglevel = loglevel.upper() @@ -448,16 +456,6 @@ def check_router_status(tgen): return True -def getStrIO(): - """ - Return a StringIO object appropriate for the current python version. - """ - if sys.version_info[0] > 2: - return io.StringIO() - else: - return StringIO.StringIO() - - def reset_config_on_routers(tgen, routerName=None): """ Resets configuration on routers to the snapshot created using input JSON @@ -529,7 +527,7 @@ def reset_config_on_routers(tgen, routerName=None): raise InvalidCLIError("Unknown error in %s", output) f = open(dname, "r") - delta = getStrIO() + delta = StringIO() delta.write("configure terminal\n") t_delta = f.read() @@ -563,7 +561,7 @@ def reset_config_on_routers(tgen, routerName=None): output = router.vtysh_multicmd(delta.getvalue(), pretty_output=False) delta.close() - delta = getStrIO() + delta = StringIO() cfg = router.run("vtysh -c 'show running'") for line in cfg.split("\n"): line = line.strip() @@ -714,20 +712,36 @@ def generate_support_bundle(): tgen = get_topogen() router_list = tgen.routers() - test_name = sys._getframe(2).f_code.co_name + test_name = os.environ.get('PYTEST_CURRENT_TEST').split(':')[-1].split(' ')[0] + TMPDIR = os.path.join(LOGDIR, tgen.modname) + bundle_procs = {} for rname, rnode in router_list.items(): - logger.info("Generating support bundle for {}".format(rname)) + logger.info("Spawn collection of support bundle for %s", rname) rnode.run("mkdir -p /var/log/frr") + bundle_procs[rname] = tgen.net[rname].popen( + "/usr/lib/frr/generate_support_bundle.py", + stdin=None, + stdout=SUB_PIPE, + stderr=SUB_PIPE, + ) - # Support only python3 going forward - bundle_log = rnode.run("env python3 /usr/lib/frr/generate_support_bundle.py") - - logger.info(bundle_log) - + for rname, rnode in router_list.items(): dst_bundle = "{}/{}/support_bundles/{}".format(TMPDIR, rname, test_name) src_bundle = "/var/log/frr" + + output, error = bundle_procs[rname].communicate() + + logger.info("Saving support bundle for %s", rname) + if output: + logger.info( + "Output from collecting support bundle for %s:\n%s", rname, output + ) + if error: + logger.warning( + "Error from collecting support bundle for %s:\n%s", rname, error + ) rnode.run("rm -rf {}".format(dst_bundle)) rnode.run("mkdir -p {}".format(dst_bundle)) rnode.run("mv -f {}/* {}".format(src_bundle, dst_bundle)) @@ -1619,60 +1633,99 @@ def interface_status(tgen, topo, input_dict): return True -def retry(attempts=3, wait=2, return_is_str=True, initial_wait=0, return_is_dict=False): +def retry(retry_timeout, initial_wait=0, expected=True, diag_pct=0.75): """ - Retries function execution, if return is an errormsg or exception - - * `attempts`: Number of attempts to make - * `wait`: Number of seconds to wait between each attempt - * `return_is_str`: Return val is an errormsg in case of failure - * `initial_wait`: Sleeps for this much seconds before executing function - + Fixture: Retries function while it's return value is an errormsg (str), False, or it raises an exception. + + * `retry_timeout`: Retry for at least this many seconds; after waiting initial_wait seconds + * `initial_wait`: Sleeps for this many seconds before first executing function + * `expected`: if False then the return logic is inverted, except for exceptions, + (i.e., a False or errmsg (str) function return ends the retry loop, + and returns that False or str value) + * `diag_pct`: Percentage of `retry_timeout` to keep testing after negative result would have + been returned in order to see if a positive result comes after. This is an + important diagnostic tool, and normally should not be disabled. Calls to wrapped + functions though, can override the `diag_pct` value to make it larger in case more + diagnostic retrying is appropriate. """ def _retry(func): @wraps(func) def func_retry(*args, **kwargs): - _wait = kwargs.pop("wait", wait) - _attempts = kwargs.pop("attempts", attempts) - _attempts = int(_attempts) - if _attempts < 0: - raise ValueError("attempts must be 0 or greater") + # We will continue to retry diag_pct of the timeout value to see if test would have passed with a + # longer retry timeout value. + saved_failure = None + + retry_sleep = 2 + + # Allow the wrapped function's args to override the fixtures + _retry_timeout = kwargs.pop("retry_timeout", retry_timeout) + _expected = kwargs.pop("expected", expected) + _initial_wait = kwargs.pop("initial_wait", initial_wait) + _diag_pct = kwargs.pop("diag_pct", diag_pct) + + start_time = datetime.now() + retry_until = datetime.now() + timedelta(seconds=_retry_timeout + _initial_wait) if initial_wait > 0: logger.info("Waiting for [%s]s as initial delay", initial_wait) sleep(initial_wait) - _return_is_str = kwargs.pop("return_is_str", return_is_str) - _return_is_dict = kwargs.pop("return_is_str", return_is_dict) - _expected = kwargs.setdefault("expected", True) - kwargs.pop("expected") - for i in range(1, _attempts + 1): + invert_logic = not _expected + while True: + seconds_left = (retry_until - datetime.now()).total_seconds() try: ret = func(*args, **kwargs) logger.debug("Function returned %s", ret) - if _return_is_str and isinstance(ret, bool) and _expected: - return ret - if ( - isinstance(ret, str) or isinstance(ret, unicode) - ) and _expected is False: - return ret - if _return_is_dict and isinstance(ret, dict): - return ret - - if _attempts == i: - generate_support_bundle() - return ret - except Exception as err: - if _attempts == i: - generate_support_bundle() - logger.info("Max number of attempts (%r) reached", _attempts) - raise - else: - logger.info("Function returned %s", err) - if i < _attempts: - logger.info("Retry [#%r] after sleeping for %ss" % (i, _wait)) - sleep(_wait) + + negative_result = ret is False or is_string(ret) + if negative_result == invert_logic: + # Simple case, successful result in time + if not saved_failure: + return ret + + # Positive result, but happened after timeout failure, very important to + # note for fixing tests. + logger.warning("RETRY DIAGNOSTIC: SUCCEED after FAILED with requested timeout of %.1fs; however, succeeded in %.1fs, investigate timeout timing", + _retry_timeout, (datetime.now() - start_time).total_seconds()) + if isinstance(saved_failure, Exception): + raise saved_failure # pylint: disable=E0702 + return saved_failure + + except Exception as error: + logger.info("Function raised exception: %s", str(error)) + ret = error + + if seconds_left < 0 and saved_failure: + logger.info("RETRY DIAGNOSTIC: Retry timeout reached, still failing") + if isinstance(saved_failure, Exception): + raise saved_failure # pylint: disable=E0702 + return saved_failure + + if seconds_left < 0: + logger.info("Retry timeout of %ds reached", _retry_timeout) + + saved_failure = ret + retry_extra_delta = timedelta(seconds=seconds_left + _retry_timeout * _diag_pct) + retry_until = datetime.now() + retry_extra_delta + seconds_left = retry_extra_delta.total_seconds() + + # Generate bundle after setting remaining diagnostic retry time + generate_support_bundle() + + # If user has disabled diagnostic retries return now + if not _diag_pct: + if isinstance(saved_failure, Exception): + raise saved_failure + return saved_failure + + if saved_failure: + logger.info("RETRY DIAG: [failure] Sleeping %ds until next retry with %.1f retry time left - too see if timeout was too short", + retry_sleep, seconds_left) + else: + logger.info("Sleeping %ds until next retry with %.1f retry time left", + retry_sleep, seconds_left) + sleep(retry_sleep) func_retry._original = func return func_retry @@ -2881,7 +2934,7 @@ def configure_interface_mac(tgen, input_dict): ############################################# # Verification APIs ############################################# -@retry(attempts=6, wait=2, return_is_str=True) +@retry(retry_timeout=12) def verify_rib( tgen, addr_type, @@ -3290,7 +3343,7 @@ def verify_rib( return True -@retry(attempts=6, wait=2, return_is_str=True) +@retry(retry_timeout=12) def verify_fib_routes(tgen, addr_type, dut, input_dict, next_hop=None): """ Data will be read from input_dict or input JSON file, API will generate @@ -3694,7 +3747,7 @@ def verify_prefix_lists(tgen, input_dict): return True -@retry(attempts=3, wait=4, return_is_str=True) +@retry(retry_timeout=12) def verify_route_maps(tgen, input_dict): """ Running "show route-map" command and verifying given route-map @@ -3746,7 +3799,7 @@ def verify_route_maps(tgen, input_dict): return True -@retry(attempts=4, wait=4, return_is_str=True) +@retry(retry_timeout=16) def verify_bgp_community(tgen, addr_type, router, network, input_dict=None): """ API to veiryf BGP large community is attached in route for any given @@ -3982,7 +4035,7 @@ def verify_cli_json(tgen, input_dict): return True -@retry(attempts=3, wait=4, return_is_str=True) +@retry(retry_timeout=12) def verify_evpn_vni(tgen, input_dict): """ API to verify evpn vni details using "show evpn vni detail json" @@ -4100,7 +4153,7 @@ def verify_evpn_vni(tgen, input_dict): return False -@retry(attempts=3, wait=4, return_is_str=True) +@retry(retry_timeout=12) def verify_vrf_vni(tgen, input_dict): """ API to verify vrf vni details using "show vrf vni json" diff --git a/tests/topotests/lib/ospf.py b/tests/topotests/lib/ospf.py index 3f39b93d8c..dc9fe0fcca 100644 --- a/tests/topotests/lib/ospf.py +++ b/tests/topotests/lib/ospf.py @@ -579,7 +579,7 @@ def redistribute_ospf(tgen, topo, dut, route_type, **kwargs): ################################ # Verification procs ################################ -@retry(attempts=40, wait=2, return_is_str=True) +@retry(retry_timeout=80) def verify_ospf_neighbor(tgen, topo, dut=None, input_dict=None, lan=False, expected=True): """ This API is to verify ospf neighborship by running @@ -774,7 +774,7 @@ def verify_ospf_neighbor(tgen, topo, dut=None, input_dict=None, lan=False, expec ################################ # Verification procs ################################ -@retry(attempts=10, wait=2, return_is_str=True) +@retry(retry_timeout=20) def verify_ospf6_neighbor(tgen, topo, dut=None, input_dict=None, lan=False): """ This API is to verify ospf neighborship by running @@ -959,7 +959,7 @@ def verify_ospf6_neighbor(tgen, topo, dut=None, input_dict=None, lan=False): return result -@retry(attempts=21, wait=2, return_is_str=True) +@retry(retry_timeout=40) def verify_ospf_rib( tgen, dut, input_dict, next_hop=None, tag=None, metric=None, fib=None, expected=True ): @@ -1236,7 +1236,7 @@ def verify_ospf_rib( return result -@retry(attempts=10, wait=2, return_is_str=True) +@retry(retry_timeout=20) def verify_ospf_interface(tgen, topo, dut=None, lan=False, input_dict=None, expected=True): """ This API is to verify ospf routes by running @@ -1326,7 +1326,7 @@ def verify_ospf_interface(tgen, topo, dut=None, lan=False, input_dict=None, expe return result -@retry(attempts=11, wait=2, return_is_str=True) +@retry(retry_timeout=20) def verify_ospf_database(tgen, topo, dut, input_dict, expected=True): """ This API is to verify ospf lsa's by running @@ -1490,7 +1490,7 @@ def verify_ospf_database(tgen, topo, dut, input_dict, expected=True): return result -@retry(attempts=10, wait=2, return_is_str=True) +@retry(retry_timeout=20) def verify_ospf_summary(tgen, topo, dut, input_dict, expected=True): """ This API is to verify ospf routes by running @@ -1571,7 +1571,7 @@ def verify_ospf_summary(tgen, topo, dut, input_dict, expected=True): -@retry(attempts=10, wait=3, return_is_str=True) +@retry(retry_timeout=30) def verify_ospf6_rib(tgen, dut, input_dict, next_hop=None, tag=None, metric=None, fib=None): """ @@ -1811,7 +1811,7 @@ def verify_ospf6_rib(tgen, dut, input_dict, next_hop=None, return result -@retry(attempts=3, wait=2, return_is_str=True) +@retry(retry_timeout=6) def verify_ospf6_interface(tgen, topo, dut=None,lan=False, input_dict=None): """ This API is to verify ospf routes by running @@ -1905,7 +1905,7 @@ def verify_ospf6_interface(tgen, topo, dut=None,lan=False, input_dict=None): return result -@retry(attempts=11, wait=2, return_is_str=True) +@retry(retry_timeout=20) def verify_ospf6_database(tgen, topo, dut, input_dict): """ This API is to verify ospf lsa's by running @@ -2176,9 +2176,9 @@ def config_ospf6_interface (tgen, topo, input_dict=None, build=False, config_data = [] for lnk in input_dict[router]['links'].keys(): if "ospf6" not in input_dict[router]['links'][lnk]: - logger.debug("Router %s: ospf6 configs is not present in" - "input_dict, passed input_dict", router, - input_dict) + logger.debug("Router %s: ospf6 config is not present in" + "input_dict, passed input_dict %s", router, + str(input_dict)) continue ospf_data = input_dict[router]['links'][lnk]['ospf6'] data_ospf_area = ospf_data.setdefault("area", None) diff --git a/tests/topotests/lib/pim.py b/tests/topotests/lib/pim.py index ce90717fa4..7de1c7a2f9 100644 --- a/tests/topotests/lib/pim.py +++ b/tests/topotests/lib/pim.py @@ -495,7 +495,7 @@ def configure_pim_force_expire(tgen, topo, input_dict, build=False): ############################################# # Verification APIs ############################################# -@retry(attempts=6, wait=2, return_is_str=True) +@retry(retry_timeout=12) def verify_pim_neighbors(tgen, topo, dut=None, iface=None, nbr_ip=None, expected=True): """ Verify all PIM neighbors are up and running, config is verified @@ -619,7 +619,7 @@ def verify_pim_neighbors(tgen, topo, dut=None, iface=None, nbr_ip=None, expected return True -@retry(attempts=21, wait=2, return_is_str=True) +@retry(retry_timeout=40) def verify_igmp_groups(tgen, dut, interface, group_addresses, expected=True): """ Verify IGMP groups are received from an intended interface @@ -693,7 +693,7 @@ def verify_igmp_groups(tgen, dut, interface, group_addresses, expected=True): return True -@retry(attempts=31, wait=2, return_is_str=True) +@retry(retry_timeout=60) def verify_upstream_iif( tgen, dut, iif, src_address, group_addresses, joinState=None, refCount=1, expected=True ): @@ -847,7 +847,7 @@ def verify_upstream_iif( return True -@retry(attempts=6, wait=2, return_is_str=True) +@retry(retry_timeout=12) def verify_join_state_and_timer(tgen, dut, iif, src_address, group_addresses, expected=True): """ Verify join state is updated correctly and join timer is @@ -966,7 +966,7 @@ def verify_join_state_and_timer(tgen, dut, iif, src_address, group_addresses, ex return True -@retry(attempts=41, wait=2, return_is_dict=True) +@retry(retry_timeout=80) def verify_ip_mroutes( tgen, dut, src_address, group_addresses, iif, oil, return_uptime=False, mwait=0, expected=True ): @@ -1163,7 +1163,7 @@ def verify_ip_mroutes( return True if return_uptime == False else uptime_dict -@retry(attempts=31, wait=2, return_is_str=True) +@retry(retry_timeout=60) def verify_pim_rp_info( tgen, topo, dut, group_addresses, oif=None, rp=None, source=None, iamrp=None, expected=True ): @@ -1320,7 +1320,7 @@ def verify_pim_rp_info( return True -@retry(attempts=31, wait=2, return_is_str=True) +@retry(retry_timeout=60) def verify_pim_state( tgen, dut, iif, oil, group_addresses, src_address=None, installed_fl=None, expected=True ): @@ -1490,7 +1490,7 @@ def verify_pim_interface_traffic(tgen, input_dict): return output_dict -@retry(attempts=21, wait=2, return_is_str=True) +@retry(retry_timeout=40) def verify_pim_interface(tgen, topo, dut, interface=None, interface_ip=None, expected=True): """ Verify all PIM interface are up and running, config is verified @@ -1797,7 +1797,7 @@ def clear_ip_igmp_interfaces(tgen, dut): return True -@retry(attempts=10, wait=2, return_is_str=True) +@retry(retry_timeout=20) def clear_ip_mroute_verify(tgen, dut, expected=True): """ Clear ip mroute by running "clear ip mroute" cli and verify @@ -2173,7 +2173,7 @@ def find_rp_from_bsrp_info(tgen, dut, bsr, grp=None): return rp_details -@retry(attempts=6, wait=2, return_is_str=True) +@retry(retry_timeout=12) def verify_pim_grp_rp_source(tgen, topo, dut, grp_addr, rp_source, rpadd=None, expected=True): """ Verify pim rp info by running "show ip pim rp-info" cli @@ -2276,7 +2276,7 @@ def verify_pim_grp_rp_source(tgen, topo, dut, grp_addr, rp_source, rpadd=None, e return errormsg -@retry(attempts=31, wait=2, return_is_str=True) +@retry(retry_timeout=60) def verify_pim_bsr(tgen, topo, dut, bsr_ip, expected=True): """ Verify all PIM interface are up and running, config is verified @@ -2332,7 +2332,7 @@ def verify_pim_bsr(tgen, topo, dut, bsr_ip, expected=True): return True -@retry(attempts=31, wait=2, return_is_str=True) +@retry(retry_timeout=60) def verify_ip_pim_upstream_rpf(tgen, topo, dut, interface, group_addresses, rp=None, expected=True): """ Verify IP PIM upstream rpf, config is verified @@ -2530,7 +2530,7 @@ def enable_disable_pim_bsm(tgen, router, intf, enable=True): return result -@retry(attempts=31, wait=2, return_is_str=True) +@retry(retry_timeout=60) def verify_ip_pim_join(tgen, topo, dut, interface, group_addresses, src_address=None, expected=True): """ Verify ip pim join by running "show ip pim join" cli @@ -2621,7 +2621,7 @@ def verify_ip_pim_join(tgen, topo, dut, interface, group_addresses, src_address= return True -@retry(attempts=31, wait=2, return_is_dict=True) +@retry(retry_timeout=60) def verify_igmp_config(tgen, input_dict, stats_return=False, expected=True): """ Verify igmp interface details, verifying following configs: @@ -2911,7 +2911,7 @@ def verify_igmp_config(tgen, input_dict, stats_return=False, expected=True): return True if stats_return == False else igmp_stats -@retry(attempts=31, wait=2, return_is_str=True) +@retry(retry_timeout=60) def verify_pim_config(tgen, input_dict, expected=True): """ Verify pim interface details, verifying following configs: @@ -3037,7 +3037,7 @@ def verify_pim_config(tgen, input_dict, expected=True): return True -@retry(attempts=21, wait=2, return_is_dict=True) +@retry(retry_timeout=40) def verify_multicast_traffic(tgen, input_dict, return_traffic=False, expected=True): """ Verify multicast traffic by running @@ -3280,7 +3280,7 @@ def get_refCount_for_mroute(tgen, dut, iif, src_address, group_addresses): return refCount -@retry(attempts=21, wait=2, return_is_str=True) +@retry(retry_timeout=40) def verify_multicast_flag_state(tgen, dut, src_address, group_addresses, flag, expected=True): """ Verify flag state for mroutes and make sure (*, G)/(S, G) are having @@ -3375,7 +3375,7 @@ def verify_multicast_flag_state(tgen, dut, src_address, group_addresses, flag, e return True -@retry(attempts=21, wait=2, return_is_str=True) +@retry(retry_timeout=40) def verify_igmp_interface(tgen, topo, dut, igmp_iface, interface_ip, expected=True): """ Verify all IGMP interface are up and running, config is verified diff --git a/tests/topotests/msdp_mesh_topo1/r1/pimd.conf b/tests/topotests/msdp_mesh_topo1/r1/pimd.conf index 49341efa57..30cecee9e1 100644 --- a/tests/topotests/msdp_mesh_topo1/r1/pimd.conf +++ b/tests/topotests/msdp_mesh_topo1/r1/pimd.conf @@ -10,6 +10,7 @@ interface r1-eth1 ip igmp ! ip pim rp 10.254.254.1 +ip msdp timers 10 20 3 ip msdp mesh-group mg-1 source 10.254.254.1 ip msdp mesh-group mg-1 member 10.254.254.2 ip msdp mesh-group mg-1 member 10.254.254.3 diff --git a/tests/topotests/msdp_mesh_topo1/r2/pimd.conf b/tests/topotests/msdp_mesh_topo1/r2/pimd.conf index 9005263ed7..a51c6d58c7 100644 --- a/tests/topotests/msdp_mesh_topo1/r2/pimd.conf +++ b/tests/topotests/msdp_mesh_topo1/r2/pimd.conf @@ -9,6 +9,7 @@ interface r2-eth1 ip pim ! ip pim rp 10.254.254.2 +ip msdp timers 10 20 3 ip msdp mesh-group mg-1 source 10.254.254.2 ip msdp mesh-group mg-1 member 10.254.254.1 ip msdp mesh-group mg-1 member 10.254.254.3 diff --git a/tests/topotests/msdp_mesh_topo1/r3/pimd.conf b/tests/topotests/msdp_mesh_topo1/r3/pimd.conf index 30e1148561..663f78620e 100644 --- a/tests/topotests/msdp_mesh_topo1/r3/pimd.conf +++ b/tests/topotests/msdp_mesh_topo1/r3/pimd.conf @@ -10,6 +10,7 @@ interface r3-eth1 ip igmp ! ip pim rp 10.254.254.3 +ip msdp timers 10 20 3 ip msdp mesh-group mg-1 source 10.254.254.3 ip msdp mesh-group mg-1 member 10.254.254.1 ip msdp mesh-group mg-1 member 10.254.254.2 diff --git a/tests/topotests/msdp_mesh_topo1/test_msdp_mesh_topo1.py b/tests/topotests/msdp_mesh_topo1/test_msdp_mesh_topo1.py index 719ead091c..222fb28ade 100644 --- a/tests/topotests/msdp_mesh_topo1/test_msdp_mesh_topo1.py +++ b/tests/topotests/msdp_mesh_topo1/test_msdp_mesh_topo1.py @@ -223,7 +223,7 @@ def test_wait_msdp_convergence(): "show ip msdp peer json", {peer: {"state": "established", "saCount": sa_count}} ) - _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) + _, result = topotest.run_and_expect(test_func, None, count=40, wait=2) assertmsg = '"{}" MSDP connection failure'.format(router) assert result is None, assertmsg diff --git a/tests/topotests/msdp_topo1/__init__.py b/tests/topotests/msdp_topo1/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/topotests/msdp_topo1/__init__.py diff --git a/tests/topotests/msdp_topo1/r1/bgpd.conf b/tests/topotests/msdp_topo1/r1/bgpd.conf new file mode 100644 index 0000000000..01d8ddbdfa --- /dev/null +++ b/tests/topotests/msdp_topo1/r1/bgpd.conf @@ -0,0 +1,8 @@ +router bgp 65001 + no bgp ebgp-requires-policy + neighbor 192.168.0.2 remote-as 65002 + neighbor 192.168.1.2 remote-as 65003 + address-family ipv4 unicast + redistribute connected + exit-address-family +! diff --git a/tests/topotests/msdp_topo1/r1/pimd.conf b/tests/topotests/msdp_topo1/r1/pimd.conf new file mode 100644 index 0000000000..fc289031f4 --- /dev/null +++ b/tests/topotests/msdp_topo1/r1/pimd.conf @@ -0,0 +1,21 @@ +debug pim +debug pim zebra +! +interface lo + ip pim + ip pim use-source 10.254.254.1 +! +interface r1-eth0 + ip pim +! +interface r1-eth1 + ip pim +! +interface r1-eth2 + ip pim + ip igmp +! +ip msdp timers 10 20 3 +ip msdp peer 192.168.0.2 source 192.168.0.1 +ip msdp peer 192.168.1.2 source 192.168.1.1 +ip pim rp 10.254.254.1 diff --git a/tests/topotests/msdp_topo1/r1/zebra.conf b/tests/topotests/msdp_topo1/r1/zebra.conf new file mode 100644 index 0000000000..fb6eabccdf --- /dev/null +++ b/tests/topotests/msdp_topo1/r1/zebra.conf @@ -0,0 +1,14 @@ +ip forwarding +! +interface r1-eth0 + ip address 192.168.0.1/24 +! +interface r1-eth1 + ip address 192.168.1.1/24 +! +interface r1-eth2 + ip address 192.168.10.1/24 +! +interface lo + ip address 10.254.254.1/32 +! diff --git a/tests/topotests/msdp_topo1/r2/bgpd.conf b/tests/topotests/msdp_topo1/r2/bgpd.conf new file mode 100644 index 0000000000..987bef40dd --- /dev/null +++ b/tests/topotests/msdp_topo1/r2/bgpd.conf @@ -0,0 +1,8 @@ +router bgp 65002 + no bgp ebgp-requires-policy + neighbor 192.168.0.1 remote-as 65001 + neighbor 192.168.2.2 remote-as 65004 + address-family ipv4 unicast + redistribute connected + exit-address-family +! diff --git a/tests/topotests/msdp_topo1/r2/pimd.conf b/tests/topotests/msdp_topo1/r2/pimd.conf new file mode 100644 index 0000000000..ffa80b12d3 --- /dev/null +++ b/tests/topotests/msdp_topo1/r2/pimd.conf @@ -0,0 +1,17 @@ +debug pim +debug pim zebra +! +interface lo + ip pim + ip pim use-source 10.254.254.2 +! +interface r2-eth0 + ip pim +! +interface r2-eth1 + ip pim +! +ip msdp timers 10 20 3 +ip msdp peer 192.168.0.1 source 192.168.0.2 +ip msdp peer 192.168.2.2 source 192.168.2.1 +ip pim rp 10.254.254.2 diff --git a/tests/topotests/msdp_topo1/r2/zebra.conf b/tests/topotests/msdp_topo1/r2/zebra.conf new file mode 100644 index 0000000000..527f7dd766 --- /dev/null +++ b/tests/topotests/msdp_topo1/r2/zebra.conf @@ -0,0 +1,11 @@ +ip forwarding +! +interface r2-eth0 + ip address 192.168.0.2/24 +! +interface r2-eth1 + ip address 192.168.2.1/24 +! +interface lo + ip address 10.254.254.2/32 +! diff --git a/tests/topotests/msdp_topo1/r3/bgpd.conf b/tests/topotests/msdp_topo1/r3/bgpd.conf new file mode 100644 index 0000000000..02d685b0e8 --- /dev/null +++ b/tests/topotests/msdp_topo1/r3/bgpd.conf @@ -0,0 +1,8 @@ +router bgp 65003 + no bgp ebgp-requires-policy + neighbor 192.168.1.1 remote-as 65001 + neighbor 192.168.3.2 remote-as 65004 + address-family ipv4 unicast + redistribute connected + exit-address-family +! diff --git a/tests/topotests/msdp_topo1/r3/pimd.conf b/tests/topotests/msdp_topo1/r3/pimd.conf new file mode 100644 index 0000000000..ab12f0573a --- /dev/null +++ b/tests/topotests/msdp_topo1/r3/pimd.conf @@ -0,0 +1,17 @@ +debug pim +debug pim zebra +! +interface lo + ip pim + ip pim use-source 10.254.254.3 +! +interface r3-eth0 + ip pim +! +interface r3-eth1 + ip pim +! +ip msdp timers 10 20 3 +ip msdp peer 192.168.1.1 source 192.168.1.2 +ip msdp peer 192.168.3.2 source 192.168.3.1 +ip pim rp 10.254.254.3 diff --git a/tests/topotests/msdp_topo1/r3/zebra.conf b/tests/topotests/msdp_topo1/r3/zebra.conf new file mode 100644 index 0000000000..688e752f42 --- /dev/null +++ b/tests/topotests/msdp_topo1/r3/zebra.conf @@ -0,0 +1,11 @@ +ip forwarding +! +interface r3-eth0 + ip address 192.168.1.2/24 +! +interface r3-eth1 + ip address 192.168.3.1/24 +! +interface lo + ip address 10.254.254.3/32 +! diff --git a/tests/topotests/msdp_topo1/r4/bgpd.conf b/tests/topotests/msdp_topo1/r4/bgpd.conf new file mode 100644 index 0000000000..633e8db245 --- /dev/null +++ b/tests/topotests/msdp_topo1/r4/bgpd.conf @@ -0,0 +1,9 @@ +router bgp 65004 + no bgp ebgp-requires-policy + neighbor 192.168.2.1 remote-as 65002 + neighbor 192.168.3.1 remote-as 65003 + address-family ipv4 unicast + redistribute connected + exit-address-family +! + diff --git a/tests/topotests/msdp_topo1/r4/pimd.conf b/tests/topotests/msdp_topo1/r4/pimd.conf new file mode 100644 index 0000000000..b2e05cb3cb --- /dev/null +++ b/tests/topotests/msdp_topo1/r4/pimd.conf @@ -0,0 +1,21 @@ +debug pim +debug pim zebra +! +interface lo + ip pim + ip pim use-source 10.254.254.4 +! +interface r4-eth0 + ip pim +! +interface r4-eth1 + ip pim +! +interface r4-eth2 + ip pim + ip igmp +! +ip msdp timers 10 20 3 +ip msdp peer 192.168.2.1 source 192.168.2.2 +ip msdp peer 192.168.3.1 source 192.168.3.2 +ip pim rp 10.254.254.4 diff --git a/tests/topotests/msdp_topo1/r4/zebra.conf b/tests/topotests/msdp_topo1/r4/zebra.conf new file mode 100644 index 0000000000..1db8132256 --- /dev/null +++ b/tests/topotests/msdp_topo1/r4/zebra.conf @@ -0,0 +1,14 @@ +ip forwarding +! +interface r4-eth0 + ip address 192.168.2.2/24 +! +interface r4-eth1 + ip address 192.168.3.2/24 +! +interface r4-eth2 + ip address 192.168.4.1/24 +! +interface lo + ip address 10.254.254.4/32 +! diff --git a/tests/topotests/msdp_topo1/test_msdp_topo1.py b/tests/topotests/msdp_topo1/test_msdp_topo1.py new file mode 100755 index 0000000000..d85e16086d --- /dev/null +++ b/tests/topotests/msdp_topo1/test_msdp_topo1.py @@ -0,0 +1,499 @@ +#!/usr/bin/env python + +# +# test_msdp_topo1.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_msdp_topo1.py: Test the FRR PIM MSDP peer. +""" + +import os +import sys +import json +import socket +import tempfile +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.bgpd, pytest.mark.pimd] + +# +# Test global variables: +# They are used to handle communicating with external application. +# +APP_SOCK_PATH = '/tmp/topotests/apps.sock' +HELPER_APP_PATH = os.path.join(CWD, "../lib/mcast-tester.py") +app_listener = None +app_clients = {} + + +def listen_to_applications(): + "Start listening socket to connect with applications." + # Remove old socket. + try: + os.unlink(APP_SOCK_PATH) + except OSError: + pass + + sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM, 0) + sock.bind(APP_SOCK_PATH) + sock.listen(10) + global app_listener + app_listener = sock + + +def accept_host(host): + "Accept connection from application running in hosts." + global app_listener, app_clients + conn = app_listener.accept() + app_clients[host] = { + 'fd': conn[0], + 'address': conn[1] + } + + +def close_applications(): + "Signal applications to stop and close all sockets." + global app_listener, app_clients + + # Close listening socket. + app_listener.close() + + # Remove old socket. + try: + os.unlink(APP_SOCK_PATH) + except OSError: + pass + + # Close all host connections. + for host in ["h1", "h2"]: + if app_clients.get(host) is None: + continue + app_clients[host]["fd"].close() + + +class MSDPTopo1(Topo): + "Test topology builder" + + def build(self, *_args, **_opts): + "Build function" + tgen = get_topogen(self) + + # Create 4 routers + 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 = tgen.add_switch("s2") + switch.add_link(tgen.gears["r1"]) + switch.add_link(tgen.gears["r3"]) + + switch = tgen.add_switch("s3") + switch.add_link(tgen.gears["r2"]) + switch.add_link(tgen.gears["r4"]) + + switch = tgen.add_switch("s4") + switch.add_link(tgen.gears["r3"]) + switch.add_link(tgen.gears["r4"]) + + switch = tgen.add_switch("s5") + switch.add_link(tgen.gears["r4"]) + + # Create a host connected and direct at r4: + tgen.add_host("h1", "192.168.4.100/24", "192.168.4.1") + switch.add_link(tgen.gears["h1"]) + + # Create a host connected and direct at r1: + switch = tgen.add_switch("s6") + tgen.add_host("h2", "192.168.10.100/24", "192.168.10.1") + switch.add_link(tgen.gears["r1"]) + switch.add_link(tgen.gears["h2"]) + + +def setup_module(mod): + "Sets up the pytest environment" + tgen = Topogen(MSDPTopo1, 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 = "{}/{}/bgpd.conf".format(CWD, rname) + if os.path.isfile(daemon_file): + router.load_config(TopoRouter.RD_BGP, daemon_file) + + daemon_file = "{}/{}/pimd.conf".format(CWD, rname) + if os.path.isfile(daemon_file): + router.load_config(TopoRouter.RD_PIM, daemon_file) + + # Initialize all routers. + tgen.start_router() + + # Start applications socket. + listen_to_applications() + + +def teardown_module(mod): + "Teardown the pytest environment" + tgen = get_topogen() + close_applications() + tgen.stop_topology() + + +def test_bgp_convergence(): + "Wait for BGP protocol convergence" + tgen = get_topogen() + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + logger.info("waiting for protocols to converge") + + def expect_loopback_route(router, iptype, route, proto): + "Wait until route is present on RIB for protocol." + logger.info("waiting route {} in {}".format(route, router)) + test_func = partial( + topotest.router_json_cmp, + tgen.gears[router], + "show {} route json".format(iptype), + {route: [{"protocol": proto}]}, + ) + _, result = topotest.run_and_expect(test_func, None, count=130, wait=1) + assertmsg = '"{}" convergence failure'.format(router) + assert result is None, assertmsg + + # Wait for R1 + expect_loopback_route("r1", "ip", "10.254.254.2/32", "bgp") + expect_loopback_route("r1", "ip", "10.254.254.3/32", "bgp") + expect_loopback_route("r1", "ip", "10.254.254.4/32", "bgp") + + # Wait for R2 + expect_loopback_route("r2", "ip", "10.254.254.1/32", "bgp") + expect_loopback_route("r2", "ip", "10.254.254.3/32", "bgp") + expect_loopback_route("r2", "ip", "10.254.254.4/32", "bgp") + + # Wait for R3 + expect_loopback_route("r3", "ip", "10.254.254.1/32", "bgp") + expect_loopback_route("r3", "ip", "10.254.254.2/32", "bgp") + expect_loopback_route("r3", "ip", "10.254.254.4/32", "bgp") + + # Wait for R4 + expect_loopback_route("r4", "ip", "10.254.254.1/32", "bgp") + expect_loopback_route("r4", "ip", "10.254.254.2/32", "bgp") + expect_loopback_route("r4", "ip", "10.254.254.3/32", "bgp") + + +def test_mroute_install(): + "Test that multicast routes propagated and installed" + tgen = get_topogen() + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + tgen.gears["h1"].run("{} '{}' '{}' '{}' &".format( + HELPER_APP_PATH, APP_SOCK_PATH, '229.1.2.3', 'h1-eth0')) + accept_host("h1") + + tgen.gears["h2"].run("{} --send='0.7' '{}' '{}' '{}' &".format( + HELPER_APP_PATH, APP_SOCK_PATH, '229.1.2.3', 'h2-eth0')) + accept_host("h2") + + # + # Test R1 mroute + # + expect_1 = { + '229.1.2.3': { + '192.168.10.100': { + 'iif': 'r1-eth2', + 'flags': 'SFT', + 'oil': { + 'r1-eth0': { + 'source': '192.168.10.100', + 'group': '229.1.2.3' + }, + 'r1-eth1': None + } + } + } + } + # Create a deep copy of `expect_1`. + expect_2 = json.loads(json.dumps(expect_1)) + # The route will be either via R2 or R3. + expect_2['229.1.2.3']['192.168.10.100']['oil']['r1-eth0'] = None + expect_2['229.1.2.3']['192.168.10.100']['oil']['r1-eth1'] = { + 'source': '192.168.10.100', + 'group': '229.1.2.3' + } + + def test_r1_mroute(): + "Test r1 multicast routing table function" + out = tgen.gears['r1'].vtysh_cmd('show ip mroute json', isjson=True) + if topotest.json_cmp(out, expect_1) is None: + return None + return topotest.json_cmp(out, expect_2) + + logger.info('Waiting for R1 multicast routes') + _, val = topotest.run_and_expect(test_r1_mroute, None, count=55, wait=2) + assert val is None, 'multicast route convergence failure' + + # + # Test routers 2 and 3. + # + # NOTE: only one of the paths will get the multicast route. + # + expect_r2 = { + "229.1.2.3": { + "192.168.10.100": { + "iif": "r2-eth0", + "flags": "S", + "oil": { + "r2-eth1": { + "source": "192.168.10.100", + "group": "229.1.2.3", + } + } + } + } + } + expect_r3 = { + "229.1.2.3": { + "192.168.10.100": { + "iif": "r3-eth0", + "flags": "S", + "oil": { + "r3-eth1": { + "source": "192.168.10.100", + "group": "229.1.2.3", + } + } + } + } + } + + def test_r2_r3_mroute(): + "Test r2/r3 multicast routing table function" + r2_out = tgen.gears['r2'].vtysh_cmd('show ip mroute json', isjson=True) + r3_out = tgen.gears['r3'].vtysh_cmd('show ip mroute json', isjson=True) + + if topotest.json_cmp(r2_out, expect_r2) is not None: + return topotest.json_cmp(r3_out, expect_r3) + + return topotest.json_cmp(r2_out, expect_r2) + + logger.info('Waiting for R2 and R3 multicast routes') + _, val = topotest.run_and_expect(test_r2_r3_mroute, None, count=55, wait=2) + assert val is None, 'multicast route convergence failure' + + # + # Test router 4 + # + expect_4 = { + "229.1.2.3": { + "*": { + "iif": "lo", + "flags": "SC", + "oil": { + "pimreg": { + "source": "*", + "group": "229.1.2.3", + "inboundInterface": "lo", + "outboundInterface": "pimreg" + }, + "r4-eth2": { + "source": "*", + "group": "229.1.2.3", + "inboundInterface": "lo", + "outboundInterface": "r4-eth2" + } + } + }, + "192.168.10.100": { + "iif": "r4-eth0", + "flags": "ST", + "oil": { + "r4-eth2": { + "source": "192.168.10.100", + "group": "229.1.2.3", + "inboundInterface": "r4-eth0", + "outboundInterface": "r4-eth2", + } + } + } + } + } + + test_func = partial( + topotest.router_json_cmp, + tgen.gears['r4'], "show ip mroute json", expect_4, + ) + logger.info('Waiting for R4 multicast routes') + _, val = topotest.run_and_expect(test_func, None, count=55, wait=2) + assert val is None, 'multicast route convergence failure' + + +def test_msdp(): + """ + Test MSDP convergence. + + MSDP non meshed groups must propagate the whole SA database (not just + their own) to all peers because not all peers talk with each other. + + This setup leads to a potential loop that can be prevented by checking + the route's first AS in AS path: it must match the remote eBGP AS number. + """ + tgen = get_topogen() + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + r1_expect = { + "192.168.0.2": { + "peer": "192.168.0.2", + "local": "192.168.0.1", + "state": "established" + }, + "192.168.1.2": { + "peer": "192.168.1.2", + "local": "192.168.1.1", + "state": "established" + } + } + r1_sa_expect = { + "229.1.2.3": { + "192.168.10.100": { + "source": "192.168.10.100", + "group": "229.1.2.3", + "rp": "-", + "local": "yes", + "sptSetup": "-" + } + } + } + r2_expect = { + "192.168.0.1": { + "peer": "192.168.0.1", + "local": "192.168.0.2", + "state": "established" + }, + "192.168.2.2": { + "peer": "192.168.2.2", + "local": "192.168.2.1", + "state": "established" + } + } + # Only R2 or R3 will get this SA. + r2_r3_sa_expect = { + "229.1.2.3": { + "192.168.10.100": { + "source": "192.168.10.100", + "group": "229.1.2.3", + "rp": "192.168.1.1", + "local": "no", + "sptSetup": "no", + } + } + } + r3_expect = { + "192.168.1.1": { + "peer": "192.168.1.1", + "local": "192.168.1.2", + "state": "established" + }, + "192.168.3.2": { + "peer": "192.168.3.2", + "local": "192.168.3.1", + "state": "established" + } + } + r4_expect = { + "192.168.2.1": { + "peer": "192.168.2.1", + "local": "192.168.2.2", + "state": "established" + }, + "192.168.3.1": { + "peer": "192.168.3.1", + "local": "192.168.3.2", + "state": "established" + } + } + r4_sa_expect = { + "229.1.2.3": { + "192.168.10.100": { + "source": "192.168.10.100", + "group": "229.1.2.3", + "rp": "192.168.1.1", + "local": "no", + "sptSetup": "yes" + } + } + } + + for router in [('r1', r1_expect, r1_sa_expect), + ('r2', r2_expect, r2_r3_sa_expect), + ('r3', r3_expect, r2_r3_sa_expect), + ('r4', r4_expect, r4_sa_expect)]: + test_func = partial( + topotest.router_json_cmp, + tgen.gears[router[0]], "show ip msdp peer json", router[1] + ) + logger.info('Waiting for {} msdp peer data'.format(router[0])) + _, val = topotest.run_and_expect(test_func, None, count=30, wait=1) + assert val is None, 'multicast route convergence failure' + + test_func = partial( + topotest.router_json_cmp, + tgen.gears[router[0]], "show ip msdp sa json", router[2] + ) + logger.info('Waiting for {} msdp SA data'.format(router[0])) + _, val = topotest.run_and_expect(test_func, None, count=30, wait=1) + assert val is None, 'multicast route convergence failure' + + +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/multicast_pim_bsm_topo2/test_mcast_pim_bsmp_02.py b/tests/topotests/multicast_pim_bsm_topo2/test_mcast_pim_bsmp_02.py index 199746d5f6..60bd6de35d 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 @@ -456,7 +456,7 @@ def test_starg_mroute_p0(request): # Verify mroute not installed step("Verify mroute not installed in l1") result = verify_ip_mroutes( - tgen, dut, src_addr, GROUP_ADDRESS, iif, oil, wait=20, expected=False + tgen, dut, src_addr, GROUP_ADDRESS, iif, oil, retry_timeout=20, expected=False ) assert ( result is not True @@ -705,6 +705,7 @@ def test_RP_priority_p0(request): ), "Testcase {} :Failed \n Error : rp expected {} rp received {}".format( tc_name, rp_add1, + rp2[group] if group in rp2 else None ) # Verify if that rp is installed diff --git a/tests/topotests/multicast_pim_sm_topo1/test_multicast_pim_sm_topo1.py b/tests/topotests/multicast_pim_sm_topo1/test_multicast_pim_sm_topo1.py index e55e30270d..b880e0e462 100755 --- a/tests/topotests/multicast_pim_sm_topo1/test_multicast_pim_sm_topo1.py +++ b/tests/topotests/multicast_pim_sm_topo1/test_multicast_pim_sm_topo1.py @@ -526,9 +526,14 @@ def test_multicast_data_traffic_static_RP_send_traffic_then_join_p0(request): {"dut": "r2", "src_address": source, "iif": "r2-f1-eth0", "oil": "r2-l1-eth2"}, {"dut": "f1", "src_address": source, "iif": "f1-i2-eth1", "oil": "f1-r2-eth3"}, ] + # On timeout change from default of 80 to 120: failures logs indicate times 90+ + # seconds for success on the 2nd entry in the above table. Using 100s here restores + # previous 80 retries with 2s wait if we assume .5s per vtysh/show ip mroute runtime + # (41 * (2 + .5)) == 102. for data in input_dict: result = verify_ip_mroutes( - tgen, data["dut"], data["src_address"], IGMP_JOIN, data["iif"], data["oil"] + tgen, data["dut"], data["src_address"], IGMP_JOIN, data["iif"], data["oil"], + retry_timeout=102 ) assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result) 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 7bef57b629..d73e8dc9e8 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 @@ -424,7 +424,7 @@ def test_add_delete_static_RP_p0(request): step("r1: Verify show ip igmp group without any IGMP join") dut = "r1" interface = "r1-r0-eth0" - result = verify_igmp_groups(tgen, dut, interface, GROUP_ADDRESS) + result = verify_igmp_groups(tgen, dut, interface, GROUP_ADDRESS, expected=False) assert result is not True, ( "Testcase {} : Failed \n " "r1: igmp group present without any IGMP join \n Error: {}".format( @@ -495,7 +495,7 @@ def test_add_delete_static_RP_p0(request): step("r1: Verify RP info") result = verify_pim_rp_info( - tgen, TOPO, dut, GROUP_RANGE_ALL, iif, rp_address, SOURCE + tgen, TOPO, dut, GROUP_RANGE_ALL, iif, rp_address, SOURCE, expected=False ) assert ( result is not True @@ -504,14 +504,14 @@ def test_add_delete_static_RP_p0(request): ) step("r1: Verify upstream IIF interface") - result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS) + 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) ) step("r1: Verify upstream join state and join timer") - result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS) + result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS, expected=False) assert result is not True, ( "Testcase {} : Failed \n " "r1: upstream join state is up and join timer is running \n Error: {}".format( @@ -519,14 +519,15 @@ def test_add_delete_static_RP_p0(request): ) ) + # 20 step("r1: Verify PIM state") - result = verify_pim_state(tgen, dut, iif, oif, GROUP_ADDRESS) + result = verify_pim_state(tgen, dut, iif, oif, GROUP_ADDRESS, expected=False) assert result is not True, "Testcase {} :Failed \n Error: {}".format( tc_name, result ) step("r1: Verify ip mroutes") - result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif) + 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( @@ -686,7 +687,9 @@ def test_SPT_RPT_path_same_p1(request): assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) step("r3: Verify (S, G) upstream join state and join timer") - result = verify_join_state_and_timer(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS) + result = verify_join_state_and_timer( + tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False + ) assert result is not True, ( "Testcase {} : Failed \n " "r3: (S, G) upstream join state is up and join timer is running\n Error: {}".format( @@ -819,7 +822,7 @@ def test_not_reachable_static_RP_p0(request): "r1 : OIL should be same and IIF should be cleared on R1 verify" "using show ip pim state" ) - result = verify_pim_state(tgen, dut, iif, oif, GROUP_ADDRESS) + result = verify_pim_state(tgen, dut, iif, oif, GROUP_ADDRESS, expected=False) assert result is not True, ( "Testcase {} : Failed \n " "OIL is not same and IIF is not cleared on R1 \n Error: {}".format( @@ -828,7 +831,7 @@ def test_not_reachable_static_RP_p0(request): ) step("r1: upstream IIF should be unknown , verify using show ip pim" "upstream") - result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS) + 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) @@ -838,7 +841,7 @@ def test_not_reachable_static_RP_p0(request): "r1: join state should not be joined and join timer should stop," "verify using show ip pim upstream" ) - result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS) + result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS, expected=False) assert result is not True, ( "Testcase {} : Failed \n " "r1: join state is joined and timer is not stopped \n Error: {}".format( @@ -861,7 +864,7 @@ def test_not_reachable_static_RP_p0(request): assert result is True, "Testcase{} : Failed Error: {}".format(tc_name, result) step("r1: (*, G) cleared from mroute table using show ip mroute") - result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif) + result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False) assert result is not True, ( "Testcase {} : Failed \n " "r1: (*, G) are not cleared from mroute table \n Error: {}".format( @@ -932,7 +935,7 @@ def test_add_RP_after_join_received_p1(request): rp_address = "1.0.2.17" iif = "r1-r2-eth1" result = verify_pim_rp_info( - tgen, TOPO, dut, GROUP_RANGE_ALL, iif, rp_address, SOURCE + tgen, TOPO, dut, GROUP_RANGE_ALL, iif, rp_address, SOURCE, expected=False ) assert ( result is not True @@ -959,7 +962,7 @@ def test_add_RP_after_join_received_p1(request): assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) step("r1: Verify upstream IIF interface") - result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS) + 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) @@ -967,7 +970,7 @@ def test_add_RP_after_join_received_p1(request): step("r1: Verify upstream join state and join timer") - result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS) + result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS, expected=False) assert result is not True, ( "Testcase {} : Failed \n " "r1: upstream join state is joined and timer is running \n Error: {}".format( @@ -976,7 +979,7 @@ def test_add_RP_after_join_received_p1(request): ) step("r1: Verify PIM state") - result = verify_pim_state(tgen, dut, iif, oif, GROUP_ADDRESS) + 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( @@ -984,7 +987,7 @@ def test_add_RP_after_join_received_p1(request): ) step("r1: Verify ip mroutes") - result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif) + 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( @@ -1114,14 +1117,14 @@ 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) + 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) ) step("r1 : Verify upstream join state and join timer") - result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS) + result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS, expected=False) assert result is not True, ( "Testcase {} : Failed \n " "r1: upstream join state is joined and timer is running\n Error: {}".format( @@ -1130,7 +1133,7 @@ def test_reachable_static_RP_after_join_p0(request): ) step("r1 : Verify PIM state") - result = verify_pim_state(tgen, dut, iif, oif, GROUP_ADDRESS) + 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( @@ -1138,7 +1141,7 @@ def test_reachable_static_RP_after_join_p0(request): ) step("r1 : Verify ip mroutes") - result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif) + 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( @@ -1385,7 +1388,9 @@ def test_send_join_on_higher_preffered_rp_p1(request): step("r1 : Verify rp-info for group 225.1.1.1") iif = "r1-r4-eth3" - result = verify_pim_rp_info(tgen, TOPO, dut, GROUP_RANGE, oif, rp_address_2, SOURCE) + 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 " "r1: rp-info is present for group 225.1.1.1 \n Error: {}".format( @@ -1643,7 +1648,9 @@ def test_RP_configured_as_LHR_1_p1(request): assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) step("r3: Verify (S, G) upstream join state and join timer") - result = verify_join_state_and_timer(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS) + result = verify_join_state_and_timer( + tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False + ) assert result is not True, ( "Testcase {} : Failed \n " "r3: (S, G) upstream join state is joined and join" @@ -1850,7 +1857,9 @@ def test_RP_configured_as_LHR_2_p1(request): assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) step("r3: Verify (S, G) upstream join state and join timer") - result = verify_join_state_and_timer(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS) + result = verify_join_state_and_timer( + tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False + ) assert result is not True, ( "Testcase {} : Failed \n " "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format( @@ -2058,7 +2067,9 @@ def test_RP_configured_as_FHR_1_p1(request): assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) step("r3: Verify (S, G) upstream join state and join timer") - result = verify_join_state_and_timer(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS) + result = verify_join_state_and_timer( + tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False + ) assert result is not True, ( "Testcase {} : Failed \n " "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format( @@ -2267,7 +2278,9 @@ def test_RP_configured_as_FHR_2_p2(request): assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) step("r3: Verify (S, G) upstream join state and join timer") - result = verify_join_state_and_timer(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS) + result = verify_join_state_and_timer( + tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False + ) assert result is not True, ( "Testcase {} : Failed \n " "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format( @@ -2394,7 +2407,9 @@ def test_SPT_RPT_path_different_p1(request): assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) step("r3: Verify (S, G) upstream join state and join timer") - result = verify_join_state_and_timer(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS) + result = verify_join_state_and_timer( + tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False + ) assert result is not True, ( "Testcase {} : Failed \n " "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format( @@ -2416,7 +2431,9 @@ def test_SPT_RPT_path_different_p1(request): assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) step("r2: Verify (S, G) upstream join state and join timer") - result = verify_join_state_and_timer(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS) + result = verify_join_state_and_timer( + tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False + ) assert result is not True, ( "Testcase {} : Failed \n " "r2: (S,G) upstream state is joined and join timer is running\n Error: {}".format( @@ -2645,7 +2662,8 @@ def test_restart_pimd_process_p2(request): assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) step("r3: Verify (S, G) upstream join state and join timer") - result = verify_join_state_and_timer(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS) + result = verify_join_state_and_timer( + tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False) assert result is not True, ( "Testcase {} : Failed \n " "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format( @@ -2663,6 +2681,7 @@ def test_restart_pimd_process_p2(request): oil = "r1-r0-eth0" logger.info("waiting for 10 sec to make sure old mroute time is higher") sleep(10) + # Why do we then wait 60 seconds below before checking the routes? uptime_before = verify_ip_mroutes( tgen, dut, STAR, GROUP_ADDRESS, iif, oil, return_uptime=True, mwait=60 ) @@ -2679,6 +2698,7 @@ def test_restart_pimd_process_p2(request): logger.info("Waiting for 5sec to get PIMd restarted and mroute" " re-learned..") sleep(5) + # Why do we then wait 10 seconds below before checking the routes? uptime_after = verify_ip_mroutes( tgen, dut, STAR, GROUP_ADDRESS, iif, oil, return_uptime=True, mwait=10 ) @@ -2814,7 +2834,7 @@ def test_multiple_groups_same_RP_address_p2(request): step("r3: Verify (S, G) upstream join state and join timer") result = verify_join_state_and_timer( - tgen, dut, iif, SOURCE_ADDRESS, group_address_list + tgen, dut, iif, SOURCE_ADDRESS, group_address_list, expected=False ) assert result is not True, ( "Testcase {} : Failed \n " @@ -2838,7 +2858,7 @@ def test_multiple_groups_same_RP_address_p2(request): step("r2: Verify (S, G) upstream join state and join timer") result = verify_join_state_and_timer( - tgen, dut, iif, SOURCE_ADDRESS, group_address_list + tgen, dut, iif, SOURCE_ADDRESS, group_address_list, expected=False ) assert result is not True, ( "Testcase {} : Failed \n " @@ -2959,7 +2979,7 @@ def test_multiple_groups_same_RP_address_p2(request): step("r2: Verify (S, G) upstream join state and join timer") result = verify_join_state_and_timer( - tgen, dut, iif, SOURCE_ADDRESS, group_address_list + tgen, dut, iif, SOURCE_ADDRESS, group_address_list, expected=False ) assert result is not True, ( "Testcase {} : Failed \n " @@ -2981,7 +3001,7 @@ def test_multiple_groups_same_RP_address_p2(request): step("r3: Verify (S, G) upstream join state and join timer") result = verify_join_state_and_timer( - tgen, dut, iif, SOURCE_ADDRESS, group_address_list + tgen, dut, iif, SOURCE_ADDRESS, group_address_list, expected=False ) assert result is not True, ( "Testcase {} : Failed \n " @@ -3163,7 +3183,7 @@ def test_multiple_groups_different_RP_address_p2(request): step("r2: Verify (S, G) upstream join state and join timer") result = verify_join_state_and_timer( - tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1 + tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1, expected=False ) assert result is not True, ( "Testcase {} : Failed \n " @@ -3187,7 +3207,7 @@ def test_multiple_groups_different_RP_address_p2(request): step("r3: Verify (S, G) upstream join state and join timer") result = verify_join_state_and_timer( - tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1 + tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1, expected=False ) assert result is not True, ( "Testcase {} : Failed \n " @@ -3259,7 +3279,7 @@ def test_multiple_groups_different_RP_address_p2(request): step("r4: Verify (S, G) upstream join state and join timer") result = verify_join_state_and_timer( - tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2 + tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2, expected=False ) assert result is not True, ( "Testcase {} : Failed \n " @@ -3283,7 +3303,7 @@ def test_multiple_groups_different_RP_address_p2(request): step("r3: Verify (S, G) upstream join state and join timer") result = verify_join_state_and_timer( - tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2 + tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2, expected=False ) assert result is not True, "Testcase {} :Failed \n Error: {}".format( tc_name, result @@ -3436,7 +3456,7 @@ def test_multiple_groups_different_RP_address_p2(request): step("r2: Verify (S, G) upstream join state and join timer") result = verify_join_state_and_timer( - tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1 + tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1, expected=False ) assert result is not True, ( "Testcase {} : Failed \n " @@ -3460,7 +3480,7 @@ def test_multiple_groups_different_RP_address_p2(request): step("r3: Verify (S, G) upstream join state and join timer") result = verify_join_state_and_timer( - tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1 + tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1, expected=False ) assert result is not True, ( "Testcase {} : Failed \n " @@ -3532,7 +3552,7 @@ def test_multiple_groups_different_RP_address_p2(request): step("r4: Verify (S, G) upstream join state and join timer") result = verify_join_state_and_timer( - tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2 + tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2, expected=False ) assert result is not True, ( "Testcase {} : Failed \n " @@ -3556,7 +3576,7 @@ def test_multiple_groups_different_RP_address_p2(request): step("r3: Verify (S, G) upstream join state and join timer") result = verify_join_state_and_timer( - tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2 + tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2, expected=False ) assert result is not True, ( "Testcase {} : Failed \n " @@ -3682,14 +3702,14 @@ def test_shutdown_primary_path_p1(request): step( "Verify after shut of R1 to R3 link , verify (*,G) entries got" - "cleared from all the node R1, R2, R3" + " cleared from all the node R1, R2, R3" ) step("r1: Verify (*, G) ip mroutes") dut = "r1" iif = "r1-r3-eth2" oif = "r1-r0-eth0" - result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif) + result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False) assert result is not True, ( "Testcase {} : Failed \n " "r1: (*,G) mroutes are not cleared after shut of R1 to R3 link\n Error: {}".format( @@ -3701,7 +3721,7 @@ def test_shutdown_primary_path_p1(request): dut = "r2" iif = "lo" oif = "r2-r3-eth1" - result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif) + result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False) assert result is not True, ( "Testcase {} : Failed \n " "r2: (*,G) mroutes are not cleared after shut of R1 to R3 link\n Error: {}".format( @@ -3713,7 +3733,7 @@ def test_shutdown_primary_path_p1(request): dut = "r3" iif = "r3-r2-eth1" oif = "r3-r1-eth0" - result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif) + result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False) assert result is not True, ( "Testcase {} : Failed \n " "r3: (*,G) mroutes are not cleared after shut of R1 to R3 link\n Error: {}".format( @@ -3878,7 +3898,7 @@ def test_delete_RP_shut_noshut_upstream_interface_p1(request): dut = "r1" iif = "r1-r2-eth1" oif = "r1-r0-eth0" - result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif) + result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False) assert result is not True, ( "Testcase {} : Failed \n " "r1: (*,G) mroutes are not cleared after shut of R1 to R0 link\n Error: {}".format( @@ -3890,7 +3910,7 @@ def test_delete_RP_shut_noshut_upstream_interface_p1(request): dut = "r2" iif = "lo" oif = "r2-r1-eth0" - result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif) + result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False) assert result is not True, ( "Testcase {} : Failed \n " "r2: (*,G) mroutes are not cleared after shut of R1 to R0 link\n Error: {}".format( @@ -4005,7 +4025,7 @@ def test_delete_RP_shut_noshut_RP_interface_p1(request): dut = "r1" iif = "r1-r2-eth1" oif = "r1-r0-eth0" - result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif) + result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False) 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( @@ -4017,7 +4037,7 @@ def test_delete_RP_shut_noshut_RP_interface_p1(request): dut = "r2" iif = "lo" oif = "r2-r1-eth0" - result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif) + result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False) 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( diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_authentication.py b/tests/topotests/ospf_basic_functionality/test_ospf_authentication.py index 9c3be58937..a7f2893eab 100644 --- a/tests/topotests/ospf_basic_functionality/test_ospf_authentication.py +++ b/tests/topotests/ospf_basic_functionality/test_ospf_authentication.py @@ -257,7 +257,7 @@ def test_ospf_authentication_simple_pass_tc28_p1(request): sleep(6) dut = "r2" ospf_covergence = verify_ospf_neighbor( - tgen, topo, dut=dut, expected=False, attempts=5 + tgen, topo, dut=dut, expected=False, retry_timeout=10 ) assert ospf_covergence is not True, "setup_module :Failed \n Error:" " {}".format( ospf_covergence @@ -395,7 +395,7 @@ def test_ospf_authentication_md5_tc29_p1(request): sleep(6) dut = "r1" ospf_covergence = verify_ospf_neighbor( - tgen, topo, dut=dut, expected=False, attempts=3 + tgen, topo, dut=dut, expected=False, retry_timeout=6 ) assert ospf_covergence is not True, "setup_module :Failed \n Error:" " {}".format( ospf_covergence @@ -460,7 +460,7 @@ def test_ospf_authentication_md5_tc29_p1(request): sleep(6) dut = "r2" ospf_covergence = verify_ospf_neighbor( - tgen, topo, dut=dut, expected=False, attempts=5 + tgen, topo, dut=dut, expected=False, retry_timeout=10 ) assert ospf_covergence is not True, "setup_module :Failed \n Error:" " {}".format( ospf_covergence @@ -610,7 +610,7 @@ def test_ospf_authentication_different_auths_tc30_p1(request): step("Verify that the neighbour is not FULL between R1 and R2.") dut = "r1" ospf_covergence = verify_ospf_neighbor( - tgen, topo, dut=dut, expected=False, attempts=5 + tgen, topo, dut=dut, expected=False, retry_timeout=10 ) assert ospf_covergence is not True, "setup_module :Failed \n Error:" " {}".format( ospf_covergence diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_ecmp.py b/tests/topotests/ospf_basic_functionality/test_ospf_ecmp.py index 1aabc06db0..49ecaac9f7 100644 --- a/tests/topotests/ospf_basic_functionality/test_ospf_ecmp.py +++ b/tests/topotests/ospf_basic_functionality/test_ospf_ecmp.py @@ -326,7 +326,7 @@ def test_ospf_ecmp_tc16_p0(request): step("Verify that route is withdrawn from R2.") dut = "r1" result = verify_ospf_rib( - tgen, dut, input_dict, next_hop=nh, attempts=5, expected=False + tgen, dut, input_dict, next_hop=nh, retry_timeout=10, expected=False ) assert ( result is not True @@ -342,7 +342,7 @@ def test_ospf_ecmp_tc16_p0(request): input_dict, protocol=protocol, next_hop=nh, - attempts=5, + retry_timeout=10, expected=False, ) assert ( @@ -434,7 +434,7 @@ def test_ospf_ecmp_tc17_p0(request): step("Verify that route is withdrawn from R2.") dut = "r1" result = verify_ospf_rib( - tgen, dut, input_dict, next_hop=nh, attempts=5, expected=False + tgen, dut, input_dict, next_hop=nh, retry_timeout=10, expected=False ) assert ( result is not True @@ -450,7 +450,7 @@ def test_ospf_ecmp_tc17_p0(request): input_dict, protocol=protocol, next_hop=nh, - attempts=5, + retry_timeout=10, expected=False, ) assert ( 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 e6dc18a434..47c6c45e39 100644 --- a/tests/topotests/ospf_basic_functionality/test_ospf_ecmp_lan.py +++ b/tests/topotests/ospf_basic_functionality/test_ospf_ecmp_lan.py @@ -305,7 +305,7 @@ def test_ospf_lan_ecmp_tc18_p0(request): step("Verify that all the routes are withdrawn from R0") dut = "r1" result = verify_ospf_rib( - tgen, dut, input_dict, next_hop=nh, attempts=5, expected=False + tgen, dut, input_dict, next_hop=nh, retry_timeout=10, expected=False ) assert ( result is not True @@ -321,7 +321,7 @@ def test_ospf_lan_ecmp_tc18_p0(request): input_dict, protocol=protocol, next_hop=nh, - attempts=5, + retry_timeout=10, expected=False, ) assert ( diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_routemaps.py b/tests/topotests/ospf_basic_functionality/test_ospf_routemaps.py index 7864d0307a..0848f6c94a 100644 --- a/tests/topotests/ospf_basic_functionality/test_ospf_routemaps.py +++ b/tests/topotests/ospf_basic_functionality/test_ospf_routemaps.py @@ -501,7 +501,7 @@ def test_ospf_routemaps_functionality_tc20_p0(request): dut = "r1" protocol = "ospf" - result = verify_ospf_rib(tgen, dut, input_dict, attempts=2, expected=False) + result = verify_ospf_rib(tgen, dut, input_dict, retry_timeout=4, expected=False) assert ( result is not True ), "Testcase {} : Failed \n " "r1: OSPF routes are present \n Error: {}".format( @@ -509,7 +509,7 @@ def test_ospf_routemaps_functionality_tc20_p0(request): ) result = verify_rib( - tgen, "ipv4", dut, input_dict, protocol=protocol, attempts=2, expected=False + tgen, "ipv4", dut, input_dict, protocol=protocol, retry_timeout=4, expected=False ) assert ( result is not True 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 9dfde325f6..f17346d5b1 100644 --- a/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py +++ b/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py @@ -263,7 +263,7 @@ def test_ospf_redistribution_tc5_p0(request): input_dict, protocol=protocol, next_hop=nh, - attempts=5, + retry_timeout=10, expected=False, ) assert result is not True, ( diff --git a/tests/topotests/static_routing_with_ebgp/test_static_routes_topo2_ebgp.py b/tests/topotests/static_routing_with_ebgp/test_static_routes_topo2_ebgp.py index bbb4370a93..2c44ec2351 100644 --- a/tests/topotests/static_routing_with_ebgp/test_static_routes_topo2_ebgp.py +++ b/tests/topotests/static_routing_with_ebgp/test_static_routes_topo2_ebgp.py @@ -690,9 +690,8 @@ def test_static_route_8nh_diff_AD_bgp_ecmp_p1_tc6_ebgp(request): next_hop=nh, protocol=protocol, fib=True, + retry_timeout=6, expected=False, - wait=2, - attempts=3, ) assert ( result is not True @@ -804,8 +803,7 @@ def test_static_route_8nh_diff_AD_bgp_ecmp_p1_tc6_ebgp(request): protocol=protocol, fib=True, expected=False, - wait=2, - attempts=3, + retry_timeout=6, ) assert ( result is not True @@ -1283,8 +1281,7 @@ def test_static_route_8nh_diff_AD_bgp_ecmp_p1_tc10_ebgp(request): protocol=protocol, fib=True, expected=False, - wait=2, - attempts=3, + retry_timeout=6, ) assert ( result is not True diff --git a/tests/topotests/static_routing_with_ibgp/test_static_routes_topo2_ibgp.py b/tests/topotests/static_routing_with_ibgp/test_static_routes_topo2_ibgp.py index ee0e01b411..85b9e8b543 100644 --- a/tests/topotests/static_routing_with_ibgp/test_static_routes_topo2_ibgp.py +++ b/tests/topotests/static_routing_with_ibgp/test_static_routes_topo2_ibgp.py @@ -695,12 +695,11 @@ def test_static_route_8nh_diff_AD_bgp_ecmp_p1_tc6_ibgp(request): protocol=protocol, fib=True, expected=False, - wait=2, - attempts=3, + retry_timeout=6, ) assert ( result is not True - ), "Testcase {} : Failed \nError: Routes " " are missing in RIB".format(tc_name) + ), "Testcase {} : Failed \nError: Routes " " are present in RIB".format(tc_name) step( "Remove the static route configured with nexthop N1 to N8, one" @@ -808,8 +807,7 @@ def test_static_route_8nh_diff_AD_bgp_ecmp_p1_tc6_ibgp(request): protocol=protocol, fib=True, expected=False, - wait=2, - attempts=3, + retry_timeout=6, ) assert ( result is not True @@ -1512,8 +1510,7 @@ def test_static_route_8nh_diff_AD_bgp_ecmp_p1_tc10_ibgp(request): protocol=protocol, fib=True, expected=False, - wait=2, - attempts=3, + retry_timeout=6, ) assert ( result is not True |
