summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/lib/test_srcdest_table.c3
-rw-r--r--tests/subdir.am2
-rw-r--r--tests/topotests/all-protocol-startup/r1/ipv4_routes.ref3
-rw-r--r--tests/topotests/all-protocol-startup/r1/zebra.conf11
-rwxr-xr-xtests/topotests/bgp-basic-functionality-topo1/test_bgp_basic_functionality.py71
-rwxr-xr-xtests/topotests/bgp-ecmp-topo2/test_ebgp_ecmp_topo2.py21
-rwxr-xr-xtests/topotests/bgp-ecmp-topo2/test_ibgp_ecmp_topo2.py12
-rw-r--r--tests/topotests/bgp_as_allow_in/bgp_as_allow_in.json266
-rwxr-xr-xtests/topotests/bgp_as_allow_in/test_bgp_as_allow_in.py975
-rw-r--r--tests/topotests/bgp_communities_topo1/bgp_communities.json175
-rw-r--r--tests/topotests/bgp_communities_topo1/test_bgp_communities.py635
-rw-r--r--tests/topotests/lib/bgp.py527
-rw-r--r--tests/topotests/rip-topo1/r1/rip_status.ref6
-rw-r--r--tests/topotests/rip-topo1/r1/ripd.conf3
-rw-r--r--tests/topotests/rip-topo1/r1/show_ip_rip.ref2
-rw-r--r--tests/topotests/rip-topo1/r1/zebra.conf7
-rw-r--r--tests/topotests/rip-topo1/r2/rip_status.ref1
-rw-r--r--tests/topotests/rip-topo1/r2/show_ip_rip.ref2
-rw-r--r--tests/topotests/rip-topo1/r2/show_ip_route.ref2
-rw-r--r--tests/topotests/rip-topo1/r3/show_ip_rip.ref2
-rw-r--r--tests/topotests/rip-topo1/r3/show_ip_route.ref2
-rwxr-xr-xtests/topotests/rip-topo1/test_rip_topo1.py6
-rw-r--r--tests/topotests/ripng-topo1/r1/ripng_status.ref4
-rw-r--r--tests/topotests/ripng-topo1/r1/ripngd.conf3
-rw-r--r--tests/topotests/ripng-topo1/r1/show_ipv6_ripng.ref4
-rw-r--r--tests/topotests/ripng-topo1/r1/zebra.conf6
-rw-r--r--tests/topotests/ripng-topo1/r2/show_ipv6_ripng.ref4
-rw-r--r--tests/topotests/ripng-topo1/r2/show_ipv6_route.ref2
-rw-r--r--tests/topotests/ripng-topo1/r3/show_ipv6_ripng.ref4
-rw-r--r--tests/topotests/ripng-topo1/r3/show_ipv6_route.ref2
-rwxr-xr-xtests/topotests/ripng-topo1/test_ripng_topo1.py5
31 files changed, 2746 insertions, 22 deletions
diff --git a/tests/lib/test_srcdest_table.c b/tests/lib/test_srcdest_table.c
index 935ee500a3..9d395bee89 100644
--- a/tests/lib/test_srcdest_table.c
+++ b/tests/lib/test_srcdest_table.c
@@ -391,8 +391,7 @@ static void test_state_del_one_route(struct test_state *test, struct prng *prng)
}
assert(rn);
- srcdest_rnode_prefixes(rn, (const struct prefix **)&dst_p,
- (const struct prefix **)&src_p);
+ srcdest_rnode_prefixes(rn, &dst_p, &src_p);
memcpy(&dst6_p, dst_p, sizeof(dst6_p));
if (src_p)
memcpy(&src6_p, src_p, sizeof(src6_p));
diff --git a/tests/subdir.am b/tests/subdir.am
index bce08c4034..5efdcbbd4c 100644
--- a/tests/subdir.am
+++ b/tests/subdir.am
@@ -90,6 +90,7 @@ check_PROGRAMS += \
endif
tests/lib/cli/test_commands_defun.c: vtysh/vtysh_cmd.c
+ mkdir -p tests/lib/cli
sed \
-e 's%"vtysh/vtysh\.h"%"tests/helpers/c/tests.h"%' \
-e 's/vtysh_init_cmd/test_init_cmd/' \
@@ -99,6 +100,7 @@ tests/lib/cli/test_commands_defun.c: vtysh/vtysh_cmd.c
CLEANFILES += tests/lib/cli/test_commands_defun.c
tests/isisd/test_fuzz_isis_tlv_tests.h: $(top_srcdir)/tests/isisd/test_fuzz_isis_tlv_tests.h.gz
+ mkdir -p tests/isisd
gzip -d < $(top_srcdir)/tests/isisd/test_fuzz_isis_tlv_tests.h.gz > "$@"
CLEANFILES += tests/isisd/test_fuzz_isis_tlv_tests.h
diff --git a/tests/topotests/all-protocol-startup/r1/ipv4_routes.ref b/tests/topotests/all-protocol-startup/r1/ipv4_routes.ref
index e13912f109..993b4df6a2 100644
--- a/tests/topotests/all-protocol-startup/r1/ipv4_routes.ref
+++ b/tests/topotests/all-protocol-startup/r1/ipv4_routes.ref
@@ -18,6 +18,9 @@ S>* 4.5.6.12/32 [1/0] is directly connected, r1-eth0, weight 1, XX:XX:XX
S>* 4.5.6.13/32 [1/0] unreachable (blackhole), weight 1, XX:XX:XX
S>* 4.5.6.14/32 [1/0] unreachable (blackhole), weight 1, XX:XX:XX
S 4.5.6.15/32 [255/0] via 192.168.0.2, r1-eth0, weight 1, XX:XX:XX
+S 4.5.6.16/32 [10/0] via 192.168.0.4, r1-eth0, weight 1, XX:XX:XX
+S>* 4.5.6.16/32 [5/0] via 192.168.0.2, r1-eth0, weight 1, XX:XX:XX
+S>* 4.5.6.17/32 [1/0] via 192.168.0.2, r1-eth0, weight 1, XX:XX:XX
S>* 4.5.6.7/32 [1/0] unreachable (blackhole), weight 1, XX:XX:XX
S>* 4.5.6.8/32 [1/0] unreachable (blackhole), weight 1, XX:XX:XX
S>* 4.5.6.9/32 [1/0] unreachable (ICMP unreachable), weight 1, XX:XX:XX
diff --git a/tests/topotests/all-protocol-startup/r1/zebra.conf b/tests/topotests/all-protocol-startup/r1/zebra.conf
index fbf827604f..f283590ddf 100644
--- a/tests/topotests/all-protocol-startup/r1/zebra.conf
+++ b/tests/topotests/all-protocol-startup/r1/zebra.conf
@@ -26,11 +26,20 @@ ipv6 route 4:5::6:12/128 r1-eth0
# by zebra but not installed.
ip route 4.5.6.15/32 192.168.0.2 255
ipv6 route 4:5::6:15/128 fc00:0:0:0::2 255
-
# Routes to put into a nexthop-group
ip route 1.1.1.1/32 r1-eth0
ip route 1.1.1.2/32 r1-eth1
+# Create a route that has overlapping distance
+# so we have backups
+ip route 4.5.6.16/32 192.168.0.2 5
+ip route 4.5.6.16/32 192.168.0.4 10
+
+# Create routes that have different tags
+# and how we handle it
+ip route 4.5.6.17/32 192.168.0.2 tag 9000
+ip route 4.5.6.17/32 192.168.0.2 tag 10000
+
!
interface r1-eth0
description to sw0 - no routing protocol
diff --git a/tests/topotests/bgp-basic-functionality-topo1/test_bgp_basic_functionality.py b/tests/topotests/bgp-basic-functionality-topo1/test_bgp_basic_functionality.py
index 7a74b62980..3441d68731 100755
--- a/tests/topotests/bgp-basic-functionality-topo1/test_bgp_basic_functionality.py
+++ b/tests/topotests/bgp-basic-functionality-topo1/test_bgp_basic_functionality.py
@@ -233,6 +233,77 @@ def test_bgp_config_with_4byte_as_number(request):
write_test_footer(tc_name)
+def test_BGP_config_with_invalid_ASN_p2(request):
+ """
+ Configure BGP with invalid ASN(ex - 0, reserved ASN) and verify test case
+ ended up with error
+ """
+
+ tgen = get_topogen()
+ global BGP_CONVERGENCE
+
+ if BGP_CONVERGENCE != True:
+ pytest.skip("skipped because of BGP Convergence failure")
+
+ # test case name
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Api call to modify AS number
+ input_dict = {
+ "r1": {"bgp": {"local_as": 0,}},
+ "r2": {"bgp": {"local_as": 0,}},
+ "r3": {"bgp": {"local_as": 0,}},
+ "r4": {"bgp": {"local_as": 64000,}},
+ }
+ result = modify_as_number(tgen, topo, input_dict)
+ try:
+ assert result is True
+ except AssertionError:
+ logger.info("Expected behaviour: {}".format(result))
+ logger.info("BGP config is not created because of invalid ASNs")
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_config_with_2byteAS_and_4byteAS_number_p1(request):
+ """
+ Configure BGP with 4 byte and 2 byte ASN and verify BGP is converged
+ """
+
+ tgen = get_topogen()
+ global BGP_CONVERGENCE
+
+ if BGP_CONVERGENCE != True:
+ pytest.skip("skipped because of BGP Convergence failure")
+
+ # test case name
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Api call to modify AS number
+ input_dict = {
+ "r1": {"bgp": {"local_as": 131079}},
+ "r2": {"bgp": {"local_as": 131079}},
+ "r3": {"bgp": {"local_as": 131079}},
+ "r4": {"bgp": {"local_as": 111}},
+ }
+ result = modify_as_number(tgen, topo, input_dict)
+ if result != True:
+ assert False, "Testcase " + tc_name + " :Failed \n Error: {}".format(result)
+
+ result = verify_as_numbers(tgen, topo, input_dict)
+ if result != True:
+ assert False, "Testcase " + tc_name + " :Failed \n Error: {}".format(result)
+
+ # Api call verify whether BGP is converged
+ result = verify_bgp_convergence(tgen, topo)
+ if result != True:
+ assert False, "Testcase " + tc_name + " :Failed \n Error: {}".format(result)
+
+ write_test_footer(tc_name)
+
+
def test_bgp_timers_functionality(request):
"""
Test to modify bgp timers and verify timers functionality.
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 bad421768c..fd3e7fd7d3 100755
--- a/tests/topotests/bgp-ecmp-topo2/test_ebgp_ecmp_topo2.py
+++ b/tests/topotests/bgp-ecmp-topo2/test_ebgp_ecmp_topo2.py
@@ -305,7 +305,8 @@ def test_modify_ecmp_max_paths(request, ecmp_num, test_type):
write_test_footer(tc_name)
-def test_ecmp_after_clear_bgp(request):
+@pytest.mark.parametrize("test_type", ["redist_static", "advertise_nw"])
+def test_ecmp_after_clear_bgp(request, test_type):
""" Verify BGP table and RIB in DUT after clear BGP routes and neighbors"""
tc_name = request.node.name
@@ -318,7 +319,7 @@ def test_ecmp_after_clear_bgp(request):
dut = "r3"
protocol = "bgp"
- static_or_nw(tgen, topo, tc_name, "redist_static", "r2")
+ static_or_nw(tgen, topo, tc_name, test_type, "r2")
for addr_type in ADDR_TYPES:
input_dict_1 = {"r3": {"static_routes": [{"network": NETWORK[addr_type]}]}}
@@ -466,14 +467,10 @@ def test_ecmp_remove_redistribute_static(request):
write_test_footer(tc_name)
-def test_ecmp_shut_bgp_neighbor(request):
- """
- Disable/Shut selected paths nexthops and verify other next are installed in
- the RIB of DUT. Enable interfaces and verify RIB count.
-
- Shut BGP neigbors one by one and verify BGP and routing table updated
- accordingly in DUT
- """
+@pytest.mark.parametrize("test_type", ["redist_static", "advertise_nw"])
+def test_ecmp_shut_bgp_neighbor(request, test_type):
+ """ Shut BGP neigbors one by one and verify BGP and routing table updated
+ accordingly in DUT """
tc_name = request.node.name
write_test_header(tc_name)
@@ -485,7 +482,7 @@ def test_ecmp_shut_bgp_neighbor(request):
protocol = "bgp"
reset_config_on_routers(tgen)
- static_or_nw(tgen, topo, tc_name, "redist_static", "r2")
+ static_or_nw(tgen, topo, tc_name, test_type, "r2")
for addr_type in ADDR_TYPES:
input_dict = {"r3": {"static_routes": [{"network": NETWORK[addr_type]}]}}
@@ -534,7 +531,7 @@ def test_ecmp_shut_bgp_neighbor(request):
result = interface_status(tgen, topo, input_dict_1)
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
- static_or_nw(tgen, topo, tc_name, "redist_static", "r2")
+ static_or_nw(tgen, topo, tc_name, test_type, "r2")
for addr_type in ADDR_TYPES:
input_dict = {"r3": {"static_routes": [{"network": NETWORK[addr_type]}]}}
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 9271a780bf..94ffc71ef6 100755
--- a/tests/topotests/bgp-ecmp-topo2/test_ibgp_ecmp_topo2.py
+++ b/tests/topotests/bgp-ecmp-topo2/test_ibgp_ecmp_topo2.py
@@ -306,7 +306,8 @@ def test_modify_ecmp_max_paths(request, ecmp_num, test_type):
write_test_footer(tc_name)
-def test_ecmp_after_clear_bgp(request):
+@pytest.mark.parametrize("test_type", ["redist_static", "advertise_nw"])
+def test_ecmp_after_clear_bgp(request, test_type):
""" Verify BGP table and RIB in DUT after clear BGP routes and neighbors"""
tc_name = request.node.name
@@ -319,7 +320,7 @@ def test_ecmp_after_clear_bgp(request):
dut = "r3"
protocol = "bgp"
- static_or_nw(tgen, topo, tc_name, "redist_static", "r2")
+ static_or_nw(tgen, topo, tc_name, test_type, "r2")
for addr_type in ADDR_TYPES:
input_dict_1 = {"r3": {"static_routes": [{"network": NETWORK[addr_type]}]}}
@@ -467,7 +468,8 @@ def test_ecmp_remove_redistribute_static(request):
write_test_footer(tc_name)
-def test_ecmp_shut_bgp_neighbor(request):
+@pytest.mark.parametrize("test_type", ["redist_static", "advertise_nw"])
+def test_ecmp_shut_bgp_neighbor(request, test_type):
""" Shut BGP neigbors one by one and verify BGP and routing table updated
accordingly in DUT """
@@ -481,7 +483,7 @@ def test_ecmp_shut_bgp_neighbor(request):
protocol = "bgp"
reset_config_on_routers(tgen)
- static_or_nw(tgen, topo, tc_name, "redist_static", "r2")
+ static_or_nw(tgen, topo, tc_name, test_type, "r2")
for addr_type in ADDR_TYPES:
input_dict = {"r3": {"static_routes": [{"network": NETWORK[addr_type]}]}}
@@ -530,7 +532,7 @@ def test_ecmp_shut_bgp_neighbor(request):
result = interface_status(tgen, topo, input_dict_1)
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
- static_or_nw(tgen, topo, tc_name, "redist_static", "r2")
+ static_or_nw(tgen, topo, tc_name, test_type, "r2")
for addr_type in ADDR_TYPES:
input_dict = {"r3": {"static_routes": [{"network": NETWORK[addr_type]}]}}
diff --git a/tests/topotests/bgp_as_allow_in/bgp_as_allow_in.json b/tests/topotests/bgp_as_allow_in/bgp_as_allow_in.json
new file mode 100644
index 0000000000..943876cdac
--- /dev/null
+++ b/tests/topotests/bgp_as_allow_in/bgp_as_allow_in.json
@@ -0,0 +1,266 @@
+{
+ "address_types": [
+ "ipv4",
+ "ipv6"
+ ],
+ "ipv4base": "10.0.0.0",
+ "ipv4mask": 30,
+ "ipv6base": "fd00::",
+ "ipv6mask": 64,
+ "link_ip_start": {
+ "ipv4": "10.0.0.0",
+ "v4mask": 30,
+ "ipv6": "fd00::",
+ "v6mask": 64
+ },
+ "lo_prefix": {
+ "ipv4": "1.0.",
+ "v4mask": 32,
+ "ipv6": "2001:db8:f::",
+ "v6mask": 128
+ },
+ "routers": {
+ "r1": {
+ "links": {
+ "lo": {
+ "ipv4": "auto",
+ "ipv6": "auto",
+ "type": "loopback"
+ },
+ "r2": {
+ "ipv4": "auto",
+ "ipv6": "auto"
+ }
+ },
+ "bgp": {
+ "local_as": "200",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1": {}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "r2": {
+ "links": {
+ "lo": {
+ "ipv4": "auto",
+ "ipv6": "auto",
+ "type": "loopback"
+ },
+ "r1": {
+ "ipv4": "auto",
+ "ipv6": "auto"
+ },
+ "r3": {
+ "ipv4": "auto",
+ "ipv6": "auto"
+ }
+ },
+ "bgp": {
+ "local_as": "100",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2": {}
+ }
+ },
+ "r3": {
+ "dest_link": {
+ "r2": {}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2": {}
+ }
+ },
+ "r3": {
+ "dest_link": {
+ "r2": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "r3": {
+ "links": {
+ "lo": {
+ "ipv4": "auto",
+ "ipv6": "auto",
+ "type": "loopback"
+ },
+ "r2": {
+ "ipv4": "auto",
+ "ipv6": "auto"
+ },
+ "r4": {
+ "ipv4": "auto",
+ "ipv6": "auto"
+ },
+ "r5": {
+ "ipv4": "auto",
+ "ipv6": "auto"
+ }
+ },
+ "bgp": {
+ "local_as": "200",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r5": {
+ "dest_link": {
+ "r3": {}
+ }
+ },
+ "r2": {
+ "dest_link": {
+ "r3": {}
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3": {}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r5": {
+ "dest_link": {
+ "r3": {}
+ }
+ },
+ "r2": {
+ "dest_link": {
+ "r3": {}
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "r4": {
+ "links": {
+ "lo": {
+ "ipv4": "auto",
+ "ipv6": "auto",
+ "type": "loopback"
+ },
+ "r3": {
+ "ipv4": "auto",
+ "ipv6": "auto"
+ }
+ },
+ "bgp": {
+ "local_as": "200",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r4": {}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r4": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "r5": {
+ "links": {
+ "lo": {
+ "ipv4": "auto",
+ "ipv6": "auto",
+ "type": "loopback"
+ },
+ "r3": {
+ "ipv4": "auto",
+ "ipv6": "auto"
+ }
+ },
+ "bgp": {
+ "local_as": "500",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r5": {}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r5": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/tests/topotests/bgp_as_allow_in/test_bgp_as_allow_in.py b/tests/topotests/bgp_as_allow_in/test_bgp_as_allow_in.py
new file mode 100755
index 0000000000..89b15c46d3
--- /dev/null
+++ b/tests/topotests/bgp_as_allow_in/test_bgp_as_allow_in.py
@@ -0,0 +1,975 @@
+#!/usr/bin/python
+
+#
+# Copyright (c) 2020 by VMware, Inc. ("VMware")
+# Used Copyright (c) 2018 by Network Device Education Foundation,
+# Inc. ("NetDEF") in this file.
+#
+# 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 VMWARE DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE 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.
+#
+
+"""
+Following tests are covered to test bgp allowas-in functionality:
+
+- Verify that routes coming from same AS are accepted only when
+ '"allowas-in" is configuerd.
+- Verify that "allowas-in" feature works per address-family/VRF
+ 'basis and doesn't impact the other AFIs.
+- Verify that the if number of occurrences of AS number in path is
+ 'more than the configured allowas-in value then we do not accept
+ 'the route.
+- Verify that when we advertise a network, learned from the same AS
+ 'via allowas-in command, to an iBGP neighbor we see multiple
+ 'occurrences.
+- Verify that when we advertise a network, learned from the same AS
+ 'via allowas-in command, to an eBGP neighbor we see multiple
+ 'occurrences of our own AS based on configured value+1.
+"""
+
+import os
+import sys
+import time
+import json
+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, "../"))
+sys.path.append(os.path.join(CWD, "../lib/"))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from mininet.topo import Topo
+from lib.topogen import Topogen, get_topogen
+
+# Import topoJson from lib, to create topology and initial configuration
+from lib.common_config import (
+ start_topology,
+ write_test_header,
+ write_test_footer,
+ reset_config_on_routers,
+ verify_rib,
+ create_static_routes,
+ create_route_maps,
+ check_address_types,
+ step,
+)
+from lib.topolog import logger
+from lib.bgp import (
+ verify_bgp_convergence,
+ create_router_bgp,
+ clear_bgp_and_verify,
+ verify_bgp_rib,
+)
+from lib.topojson import build_topo_from_json, build_config_from_json
+
+# Reading the data from JSON File for topology creation
+jsonFile = "{}/bgp_as_allow_in.json".format(CWD)
+try:
+ with open(jsonFile, "r") as topoJson:
+ topo = json.load(topoJson)
+except IOError:
+ assert False, "Could not read file {}".format(jsonFile)
+
+# Global variables
+BGP_CONVERGENCE = False
+ADDR_TYPES = check_address_types()
+NETWORK = {"ipv4": "2.2.2.2/32", "ipv6": "22:22::2/128"}
+NEXT_HOP_IP = {"ipv4": "Null0", "ipv6": "Null0"}
+
+
+class BGPALLOWASIN(Topo):
+ """
+ Test BGPALLOWASIN - topology 1
+
+ * `Topo`: Topology object
+ """
+
+ def build(self, *_args, **_opts):
+ """Build function"""
+ tgen = get_topogen(self)
+
+ # Building topology from json file
+ build_topo_from_json(tgen, topo)
+
+
+def setup_module(mod):
+ """
+ Sets up the pytest environment
+
+ * `mod`: module name
+ """
+
+ testsuite_run_time = time.asctime(time.localtime(time.time()))
+ logger.info("Testsuite start time: {}".format(testsuite_run_time))
+ logger.info("=" * 40)
+
+ logger.info("Running setup_module to create topology")
+
+ # This function initiates the topology build with Topogen...
+ tgen = Topogen(BGPALLOWASIN, mod.__name__)
+ # ... and here it calls Mininet initialization functions.
+
+ # Starting topology, create tmp files which are loaded to routers
+ # to start deamons and then start routers
+ start_topology(tgen)
+
+ # Creating configuration from JSON
+ build_config_from_json(tgen, topo)
+
+ # Checking BGP convergence
+ global BGP_CONVERGENCE
+ global ADDR_TYPES
+
+ # Api call verify whether BGP is converged
+ BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo)
+ assert BGP_CONVERGENCE is True, "setup_module :Failed \n Error:" " {}".format(
+ BGP_CONVERGENCE
+ )
+
+ logger.info("Running setup_module() done")
+
+
+def teardown_module(mod):
+ """
+ Teardown the pytest environment
+
+ * `mod`: module name
+ """
+
+ logger.info("Running teardown_module to delete topology")
+
+ tgen = get_topogen()
+
+ # Stop toplogy and Remove tmp files
+ tgen.stop_topology()
+
+ logger.info(
+ "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
+ )
+ logger.info("=" * 40)
+
+
+#####################################################
+#
+# Tests starting
+#
+#####################################################
+
+
+def test_bgp_allowas_in_p0(request):
+ """
+ Verify that routes coming from same AS are accepted only when
+ "allowas-in" is configuerd.
+
+ """
+
+ tc_name = request.node.name
+ write_test_header(tc_name)
+ tgen = get_topogen()
+ reset_config_on_routers(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ step("Advertise prefix 2.2.2.2/32 from Router-1(AS-200).")
+ step("Advertise an ipv6 prefix 22:22::2/128 from Router-1(AS-200).")
+ # configure static routes
+ dut = "r3"
+ protocol = "bgp"
+
+ for addr_type in ADDR_TYPES:
+ # Enable static routes
+ input_dict_4 = {
+ "r1": {
+ "static_routes": [
+ {"network": NETWORK[addr_type], "next_hop": NEXT_HOP_IP[addr_type]}
+ ]
+ }
+ }
+
+ logger.info("Configure static routes")
+ result = create_static_routes(tgen, input_dict_4)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("configure redistribute static in Router BGP in R1")
+
+ input_dict_2 = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ addr_type: {
+ "unicast": {"redistribute": [{"redist_type": "static"}]}
+ }
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+ step(
+ 'Check BGP table of router R3 using "sh bgp ipv4" and "sh bgp '
+ 'ipv6" command.'
+ )
+ step(
+ "We should not see prefix advertised from R1 in R3's BGP "
+ "table without allowas-in."
+ )
+ logger.info("Verifying %s routes on r3, route should not be present", addr_type)
+ result = verify_rib(
+ tgen,
+ addr_type,
+ dut,
+ input_dict_4,
+ next_hop=NEXT_HOP_IP[addr_type],
+ protocol=protocol,
+ expected=False,
+ )
+ assert result is not True, "Testcase {} : Failed \n"
+ "Expected behavior: routes should not present in rib \n"
+ "Error: {}".format(tc_name, result)
+
+ step("Configure allowas-in on R3 for R2.")
+ step("We should see the prefix advertised from R1 in R3's BGP table.")
+ # Api call to enable allowas-in in bgp process.
+ input_dict_1 = {
+ "r3": {
+ "bgp": {
+ "address_family": {
+ addr_type: {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r3": {
+ "allowas-in": {"number_occurences": 1}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+ result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+def test_bgp_allowas_in_per_addr_family_p0(request):
+ """
+ Verify that "allowas-in" feature works per address-family/VRF
+ basis and doesn't impact the other AFIs.
+
+ """
+
+ # This test is applicable only for dual stack.
+ if "ipv4" not in ADDR_TYPES or "ipv6" not in ADDR_TYPES:
+ pytest.skip("NOT APPLICABLE")
+
+ tc_name = request.node.name
+ write_test_header(tc_name)
+ tgen = get_topogen()
+ reset_config_on_routers(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ step("Advertise prefix 2.2.2.2/32 from Router-1(AS-200).")
+ step("Advertise an ipv6 prefix 22:22::2/128 from Router-1(AS-200).")
+ # configure static routes routes
+ dut = "r3"
+ protocol = "bgp"
+
+ for addr_type in ADDR_TYPES:
+ # Enable static routes
+ input_dict_4 = {
+ "r1": {
+ "static_routes": [
+ {"network": NETWORK[addr_type], "next_hop": NEXT_HOP_IP[addr_type]}
+ ]
+ }
+ }
+
+ logger.info("Configure static routes")
+ result = create_static_routes(tgen, input_dict_4)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("configure redistribute static in Router BGP in R1")
+
+ input_dict_2 = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ addr_type: {
+ "unicast": {"redistribute": [{"redist_type": "static"}]}
+ }
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Configure allowas-in on R3 for R2 under IPv4 addr-family only")
+ # Api call to enable allowas-in in bgp process.
+ input_dict_1 = {
+ "r3": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r3": {"allowas-in": {"number_occurences": 1}}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ static_route_ipv4 = {
+ "r1": {
+ "static_routes": [
+ {"network": NETWORK["ipv4"], "next_hop": NEXT_HOP_IP["ipv4"]}
+ ]
+ }
+ }
+
+ static_route_ipv6 = {
+ "r1": {
+ "static_routes": [
+ {"network": NETWORK["ipv6"], "next_hop": NEXT_HOP_IP["ipv6"]}
+ ]
+ }
+ }
+ step("We should see R1 advertised prefix only in IPv4 AFI " "not in IPv6 AFI.")
+ result = verify_rib(tgen, "ipv4", dut, static_route_ipv4, protocol=protocol)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+ result = verify_rib(
+ tgen, "ipv6", dut, static_route_ipv6, protocol=protocol, expected=False
+ )
+ assert result is not True, "Testcase {} : Failed \n"
+ "Expected behavior: routes are should not be present in ipv6 rib\n"
+ " Error: {}".format(tc_name, result)
+
+ step("Repeat the same test for IPv6 AFI.")
+ step("Configure allowas-in on R3 for R2 under IPv6 addr-family only")
+ # Api call to enable allowas-in in bgp process.
+ input_dict_1 = {
+ "r3": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r3": {
+ "allowas-in": {
+ "number_occurences": 2,
+ "delete": True,
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r3": {"allowas-in": {"number_occurences": 2}}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+ step("We should see R1 advertised prefix only in IPv6 AFI " "not in IPv4 AFI.")
+ result = verify_rib(
+ tgen, "ipv4", dut, static_route_ipv4, protocol=protocol, expected=False
+ )
+ assert result is not True, "Testcase {} : Failed \n"
+ "Expected behavior: routes should not be present in ipv4 rib\n"
+ " Error: {}".format(tc_name, result)
+ result = verify_rib(tgen, "ipv6", dut, static_route_ipv6, protocol=protocol)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ write_test_footer(tc_name)
+
+
+def test_bgp_allowas_in_no_of_occurrences_p0(request):
+ """
+ Verify that the if number of occurrences of AS number in path is
+ more than the configured allowas-in value then we do not accept
+ the route.
+
+ """
+
+ tc_name = request.node.name
+ write_test_header(tc_name)
+ tgen = get_topogen()
+ reset_config_on_routers(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ dut = "r3"
+ protocol = "bgp"
+
+ for addr_type in ADDR_TYPES:
+ # Enable static routes
+ static_routes = {
+ "r1": {
+ "static_routes": [
+ {"network": NETWORK[addr_type], "next_hop": NEXT_HOP_IP[addr_type]}
+ ]
+ }
+ }
+
+ logger.info("Configure static routes")
+ result = create_static_routes(tgen, static_routes)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("configure redistribute static in Router BGP in R1")
+
+ input_dict_2 = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ addr_type: {
+ "unicast": {"redistribute": [{"redist_type": "static"}]}
+ }
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Configure a route-map on R1 to prepend AS 4 times.")
+ for addr_type in ADDR_TYPES:
+ input_dict_4 = {
+ "r1": {
+ "route_maps": {
+ "ASP_{}".format(addr_type): [
+ {
+ "action": "permit",
+ "set": {
+ "path": {
+ "as_num": "200 200 200 200",
+ "as_action": "prepend",
+ }
+ },
+ }
+ ]
+ }
+ }
+ }
+ result = create_route_maps(tgen, input_dict_4)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("configure route map in out direction on R1")
+ # Configure neighbor for route map
+ input_dict_7 = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ addr_type: {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1": {
+ "route_maps": [
+ {
+ "name": "ASP_{}".format(
+ addr_type
+ ),
+ "direction": "out",
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_7)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ step('Configure "allowas-in 4" on R3 for R2.')
+ # Api call to enable allowas-in in bgp process.
+ input_dict_1 = {
+ "r3": {
+ "bgp": {
+ "address_family": {
+ addr_type: {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r3": {
+ "allowas-in": {"number_occurences": 4}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+ result = verify_rib(
+ tgen, addr_type, dut, static_routes, protocol=protocol, expected=False
+ )
+ assert result is not True, "Testcase {} : Failed \n "
+ "Expected behavior: routes are should not be present in rib\n"
+ "Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ step('Configure "allowas-in 5" on R3 for R2.')
+ input_dict_1 = {
+ "r3": {
+ "bgp": {
+ "address_family": {
+ addr_type: {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r3": {
+ "allowas-in": {"number_occurences": 5}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+ static_routes = {
+ "r1": {
+ "static_routes": [
+ {"network": NETWORK[addr_type], "next_hop": NEXT_HOP_IP[addr_type]}
+ ]
+ }
+ }
+ result = verify_rib(tgen, addr_type, dut, static_routes, protocol=protocol)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+def test_bgp_allowas_in_sameastoibgp_p1(request):
+ """
+ Verify that when we advertise a network, learned from the same AS
+ via allowas-in command, to an iBGP neighbor we see multiple
+ occurrences.
+
+ """
+
+ tc_name = request.node.name
+ write_test_header(tc_name)
+ tgen = get_topogen()
+ reset_config_on_routers(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ dut = "r3"
+ protocol = "bgp"
+
+ for addr_type in ADDR_TYPES:
+ # Enable static routes
+ static_routes = {
+ "r1": {
+ "static_routes": [
+ {"network": NETWORK[addr_type], "next_hop": NEXT_HOP_IP[addr_type]}
+ ]
+ }
+ }
+
+ logger.info("Configure static routes")
+ result = create_static_routes(tgen, static_routes)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("configure redistribute static in Router BGP in R1")
+
+ input_dict_2 = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ addr_type: {
+ "unicast": {"redistribute": [{"redist_type": "static"}]}
+ }
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Configure a route-map on R2 to prepend AS 2 times.")
+ for addr_type in ADDR_TYPES:
+ input_dict_4 = {
+ "r2": {
+ "route_maps": {
+ "ASP_{}".format(addr_type): [
+ {
+ "action": "permit",
+ "set": {
+ "path": {"as_num": "200 200", "as_action": "prepend"}
+ },
+ }
+ ]
+ }
+ }
+ }
+ result = create_route_maps(tgen, input_dict_4)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("configure route map in out direction on R2")
+ # Configure neighbor for route map
+ input_dict_7 = {
+ "r2": {
+ "bgp": {
+ "address_family": {
+ addr_type: {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r2": {
+ "route_maps": [
+ {
+ "name": "ASP_{}".format(
+ addr_type
+ ),
+ "direction": "out",
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_7)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step('Configure "allowas-in 3" on R3 for R1.')
+ input_dict_1 = {
+ "r3": {
+ "bgp": {
+ "address_family": {
+ addr_type: {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r3": {
+ "allowas-in": {"number_occurences": 3}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ input_dict_1 = {
+ "r4": {
+ "bgp": {
+ "address_family": {
+ addr_type: {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r4": {
+ "allowas-in": {"number_occurences": 3}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ static_routes = {
+ "r1": {
+ "static_routes": [
+ {"network": NETWORK[addr_type], "next_hop": NEXT_HOP_IP[addr_type]}
+ ]
+ }
+ }
+ dut = "r4"
+ path = "100 200 200 200"
+ result = verify_bgp_rib(tgen, addr_type, dut, static_routes, aspath=path)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+def test_bgp_allowas_in_sameastoebgp_p1(request):
+ """
+ Verify that when we advertise a network, learned from the same AS
+ via allowas-in command, to an eBGP neighbor we see multiple
+ occurrences of our own AS based on configured value+1.
+
+ """
+
+ tc_name = request.node.name
+ write_test_header(tc_name)
+ tgen = get_topogen()
+ reset_config_on_routers(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ dut = "r3"
+ protocol = "bgp"
+
+ for addr_type in ADDR_TYPES:
+ # Enable static routes
+ static_routes = {
+ "r1": {
+ "static_routes": [
+ {"network": NETWORK[addr_type], "next_hop": NEXT_HOP_IP[addr_type]}
+ ]
+ }
+ }
+
+ logger.info("Configure static routes")
+ result = create_static_routes(tgen, static_routes)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("configure redistribute static in Router BGP in R1")
+
+ input_dict_2 = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ addr_type: {
+ "unicast": {"redistribute": [{"redist_type": "static"}]}
+ }
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Configure a route-map on R2 to prepend AS 2 times.")
+ for addr_type in ADDR_TYPES:
+ input_dict_4 = {
+ "r2": {
+ "route_maps": {
+ "ASP_{}".format(addr_type): [
+ {
+ "action": "permit",
+ "set": {
+ "path": {"as_num": "200 200", "as_action": "prepend"}
+ },
+ }
+ ]
+ }
+ }
+ }
+ result = create_route_maps(tgen, input_dict_4)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("configure route map in out direction on R2")
+ # Configure neighbor for route map
+ input_dict_7 = {
+ "r2": {
+ "bgp": {
+ "address_family": {
+ addr_type: {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r2": {
+ "route_maps": [
+ {
+ "name": "ASP_{}".format(
+ addr_type
+ ),
+ "direction": "out",
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_7)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ step('Configure "allowas-in 3" on R3 for R1.')
+ input_dict_1 = {
+ "r3": {
+ "bgp": {
+ "address_family": {
+ addr_type: {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r3": {
+ "allowas-in": {"number_occurences": 3}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+ static_routes = {
+ "r1": {
+ "static_routes": [
+ {"network": NETWORK[addr_type], "next_hop": NEXT_HOP_IP[addr_type]}
+ ]
+ }
+ }
+ dut = "r5"
+ path = "200 100 200 200 200"
+ result = verify_bgp_rib(tgen, addr_type, dut, static_routes, aspath=path)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+ write_test_footer(tc_name)
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_communities_topo1/bgp_communities.json b/tests/topotests/bgp_communities_topo1/bgp_communities.json
new file mode 100644
index 0000000000..da6aec239f
--- /dev/null
+++ b/tests/topotests/bgp_communities_topo1/bgp_communities.json
@@ -0,0 +1,175 @@
+{
+ "address_types": [
+ "ipv4",
+ "ipv6"
+ ],
+ "ipv4base": "10.0.0.0",
+ "ipv4mask": 30,
+ "ipv6base": "fd00::",
+ "ipv6mask": 64,
+ "link_ip_start": {
+ "ipv4": "10.0.0.0",
+ "v4mask": 30,
+ "ipv6": "fd00::",
+ "v6mask": 64
+ },
+ "lo_prefix": {
+ "ipv4": "1.0.",
+ "v4mask": 32,
+ "ipv6": "2001:db8:f::",
+ "v6mask": 128
+ },
+ "routers": {
+ "r1": {
+ "links": {
+ "lo": {
+ "ipv4": "auto",
+ "ipv6": "auto",
+ "type": "loopback"
+ },
+ "r2": {
+ "ipv4": "auto",
+ "ipv6": "auto"
+ },
+ "r0": {
+ "ipv4": "auto",
+ "ipv6": "auto"
+ }
+ },
+ "bgp": {
+ "local_as": "100",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1": {}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "r2": {
+ "links": {
+ "lo": {
+ "ipv4": "auto",
+ "ipv6": "auto",
+ "type": "loopback"
+ },
+ "r1": {
+ "ipv4": "auto",
+ "ipv6": "auto"
+ },
+ "r3": {
+ "ipv4": "auto",
+ "ipv6": "auto"
+ }
+ },
+ "bgp": {
+ "local_as": "200",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2": {}
+ }
+ },
+ "r3": {
+ "dest_link": {
+ "r2": {}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2": {}
+ }
+ },
+ "r3": {
+ "dest_link": {
+ "r2": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "r3": {
+ "links": {
+ "lo": {
+ "ipv4": "auto",
+ "ipv6": "auto",
+ "type": "loopback"
+ },
+ "r2": {
+ "ipv4": "auto",
+ "ipv6": "auto"
+ }
+ },
+ "bgp": {
+ "local_as": "300",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r3": {}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r3": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "r0": {
+ "links": {
+ "lo": {
+ "ipv4": "auto",
+ "ipv6": "auto",
+ "type": "loopback"
+ },
+ "r1": {
+ "ipv4": "auto",
+ "ipv6": "auto"
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/tests/topotests/bgp_communities_topo1/test_bgp_communities.py b/tests/topotests/bgp_communities_topo1/test_bgp_communities.py
new file mode 100644
index 0000000000..7d960d6916
--- /dev/null
+++ b/tests/topotests/bgp_communities_topo1/test_bgp_communities.py
@@ -0,0 +1,635 @@
+#!/usr/bin/python
+
+#
+# Copyright (c) 2020 by VMware, Inc. ("VMware")
+# Used Copyright (c) 2018 by Network Device Education Foundation,
+# Inc. ("NetDEF") in this file.
+#
+# 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 VMWARE DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE 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.
+#
+
+"""
+Following tests are covered to test bgp community functionality:
+- Verify routes are not advertised when NO-ADVERTISE Community is applied
+
+"""
+
+import os
+import sys
+import time
+import json
+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 mininet.topo import Topo
+from lib.topogen import Topogen, get_topogen
+
+# Import topoJson from lib, to create topology and initial configuration
+from lib.common_config import (
+ start_topology,
+ write_test_header,
+ write_test_footer,
+ reset_config_on_routers,
+ verify_rib,
+ create_static_routes,
+ check_address_types,
+ step,
+ create_route_maps,
+ create_prefix_lists,
+ create_route_maps,
+)
+from lib.topolog import logger
+from lib.bgp import (
+ verify_bgp_convergence,
+ create_router_bgp,
+ clear_bgp_and_verify,
+ verify_bgp_rib,
+)
+from lib.topojson import build_topo_from_json, build_config_from_json
+from copy import deepcopy
+
+# Reading the data from JSON File for topology creation
+jsonFile = "{}/bgp_communities.json".format(CWD)
+try:
+ with open(jsonFile, "r") as topoJson:
+ topo = json.load(topoJson)
+except IOError:
+ assert False, "Could not read file {}".format(jsonFile)
+
+# Global variables
+BGP_CONVERGENCE = False
+ADDR_TYPES = check_address_types()
+NETWORK = {"ipv4": "2.2.2.2/32", "ipv6": "22:22::2/128"}
+NEXT_HOP_IP = {}
+
+
+class BGPCOMMUNITIES(Topo):
+ """
+ Test BGPCOMMUNITIES - topology 1
+
+ * `Topo`: Topology object
+ """
+
+ def build(self, *_args, **_opts):
+ """Build function"""
+ tgen = get_topogen(self)
+
+ # Building topology from json file
+ build_topo_from_json(tgen, topo)
+
+
+def setup_module(mod):
+ """
+ Sets up the pytest environment
+
+ * `mod`: module name
+ """
+
+ testsuite_run_time = time.asctime(time.localtime(time.time()))
+ logger.info("Testsuite start time: {}".format(testsuite_run_time))
+ logger.info("=" * 40)
+
+ logger.info("Running setup_module to create topology")
+
+ # This function initiates the topology build with Topogen...
+ tgen = Topogen(BGPCOMMUNITIES, mod.__name__)
+ # ... and here it calls Mininet initialization functions.
+
+ # Starting topology, create tmp files which are loaded to routers
+ # to start deamons and then start routers
+ start_topology(tgen)
+
+ # Creating configuration from JSON
+ build_config_from_json(tgen, topo)
+
+ # Checking BGP convergence
+ global BGP_CONVERGENCE
+ global ADDR_TYPES
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Api call verify whether BGP is converged
+ BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo)
+ assert BGP_CONVERGENCE is True, "setup_module :Failed \n Error:" " {}".format(
+ BGP_CONVERGENCE
+ )
+
+ logger.info("Running setup_module() done")
+
+
+def teardown_module(mod):
+ """
+ Teardown the pytest environment
+
+ * `mod`: module name
+ """
+
+ logger.info("Running teardown_module to delete topology")
+
+ tgen = get_topogen()
+
+ # Stop toplogy and Remove tmp files
+ tgen.stop_topology()
+
+ logger.info(
+ "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
+ )
+ logger.info("=" * 40)
+
+
+#####################################################
+#
+# Tests starting
+#
+#####################################################
+
+
+def test_bgp_no_advertise_community_p0(request):
+ """
+ Verify routes are not advertised when NO-ADVERTISE Community is applied
+
+ """
+
+ tc_name = request.node.name
+ write_test_header(tc_name)
+ tgen = get_topogen()
+ reset_config_on_routers(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ NEXT_HOP_IP = {
+ "ipv4": topo["routers"]["r0"]["links"]["r1"]["ipv4"].split("/")[0],
+ "ipv6": topo["routers"]["r0"]["links"]["r1"]["ipv6"].split("/")[0],
+ }
+
+ # configure static routes
+ dut = "r3"
+ protocol = "bgp"
+
+ for addr_type in ADDR_TYPES:
+ # Enable static routes
+ input_dict = {
+ "r1": {
+ "static_routes": [
+ {"network": NETWORK[addr_type], "next_hop": NEXT_HOP_IP[addr_type]}
+ ]
+ }
+ }
+
+ logger.info("Configure static routes")
+ result = create_static_routes(tgen, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("configure redistribute static and connected in Router BGP " "in R1")
+
+ input_dict_2 = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ addr_type: {
+ "unicast": {
+ "redistribute": [
+ {"redist_type": "static"},
+ {"redist_type": "connected"},
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step(
+ "BGP neighbors are up, static and connected route advertised from"
+ " R1 are present on R2 BGP table and RIB using show ip bgp and "
+ " show ip route"
+ )
+ step(
+ "Static and connected route advertised from R1 are present on R3"
+ " BGP table and RIB using show ip bgp and show ip route"
+ )
+
+ dut = "r3"
+ protocol = "bgp"
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Configure prefix list P1 on R2 to permit route coming from R1")
+ # Create ip prefix list
+ input_dict_2 = {
+ "r2": {
+ "prefix_lists": {
+ addr_type: {
+ "pf_list_1_{}".format(addr_type): [
+ {"seqid": 10, "network": "any", "action": "permit"}
+ ]
+ }
+ }
+ }
+ }
+ result = create_prefix_lists(tgen, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ # Create route map
+ input_dict_3 = {
+ "r2": {
+ "route_maps": {
+ "rmap_match_pf_1_{}".format(addr_type): [
+ {
+ "action": "permit",
+ "seq_id": "5",
+ "match": {
+ addr_type: {"prefix_lists": "pf_list_1_" + addr_type}
+ },
+ "set": {"community": {"num": "no-advertise"}},
+ }
+ ]
+ }
+ }
+ }
+ result = create_route_maps(tgen, input_dict_3)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+ step(
+ "Apply route-map RM1 on R2, R2 to R3 BGP neighbor with no"
+ " advertise community"
+ )
+ # Configure neighbor for route map
+ input_dict_4 = {
+ "r2": {
+ "bgp": {
+ "address_family": {
+ addr_type: {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2": {
+ "route_maps": [
+ {
+ "name": "rmap_match_pf_1_"
+ + addr_type,
+ "direction": "in",
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_4)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step(
+ "After advertising no advertise community to BGP neighbor "
+ "static and connected router got removed from R3 verify using "
+ "show ip bgp & show ip route"
+ )
+
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict, expected=False)
+ assert result is not True, "Testcase {} : Failed \n "
+ " Routes still present in R3 router. Error: {}".format(tc_name, result)
+
+ result = verify_rib(
+ tgen, addr_type, dut, input_dict, protocol=protocol, expected=False
+ )
+ assert result is not True, "Testcase {} : Failed \n "
+ " Routes still present in R3 router. Error: {}".format(tc_name, result)
+
+ step("Remove and Add no advertise community")
+ # Configure neighbor for route map
+ input_dict_4 = {
+ "r2": {
+ "bgp": {
+ "address_family": {
+ addr_type: {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2": {
+ "route_maps": [
+ {
+ "name": "rmap_match_pf_1_"
+ + addr_type,
+ "direction": "in",
+ "delete": True,
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_4)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step(
+ "After removing no advertise community from BGP neighbor "
+ "static and connected router got advertised to R3 and "
+ "removing route-map, verify route using show ip bgp"
+ " and show ip route"
+ )
+
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict)
+ assert result is True, "Testcase {} : Failed \n "
+ " Routes still present in R3 router. Error: {}".format(tc_name, result)
+
+ result = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+ assert result is True, "Testcase {} : Failed \n "
+ " Routes still present in R3 router. Error: {}".format(tc_name, result)
+
+ step("Repeat above steps when IBGP nbr configured between R1, R2 & R2, R3")
+ topo1 = deepcopy(topo)
+
+ topo1["routers"]["r1"]["bgp"]["local_as"] = "100"
+ topo1["routers"]["r2"]["bgp"]["local_as"] = "100"
+ topo1["routers"]["r3"]["bgp"]["local_as"] = "100"
+
+ for rtr in ["r1", "r2", "r3"]:
+ if "bgp" in topo1["routers"][rtr].keys():
+ delete_bgp = {rtr: {"bgp": {"delete": True}}}
+ result = create_router_bgp(tgen, topo1, delete_bgp)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+ config_bgp = {
+ rtr: {"bgp": {"local_as": topo1["routers"][rtr]["bgp"]["local_as"]}}
+ }
+ result = create_router_bgp(tgen, topo1, config_bgp)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ build_config_from_json(tgen, topo1, save_bkup=False)
+
+ step("verify bgp convergence before starting test case")
+
+ bgp_convergence = verify_bgp_convergence(tgen, topo1)
+ assert bgp_convergence is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, bgp_convergence
+ )
+
+ # configure static routes
+ dut = "r3"
+ protocol = "bgp"
+
+ for addr_type in ADDR_TYPES:
+ # Enable static routes
+ input_dict = {
+ "r1": {
+ "static_routes": [
+ {"network": NETWORK[addr_type], "next_hop": NEXT_HOP_IP[addr_type]}
+ ]
+ }
+ }
+
+ logger.info("Configure static routes")
+ result = create_static_routes(tgen, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("configure redistribute static and connected in Router " "BGP in R1")
+
+ input_dict_2 = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ addr_type: {
+ "unicast": {
+ "redistribute": [
+ {"redist_type": "static"},
+ {"redist_type": "connected"},
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step(
+ "BGP neighbors are up, static and connected route advertised from"
+ " R1 are present on R2 BGP table and RIB using show ip bgp and "
+ " show ip route"
+ )
+ step(
+ "Static and connected route advertised from R1 are present on R3"
+ " BGP table and RIB using show ip bgp and show ip route"
+ )
+
+ dut = "r2"
+ protocol = "bgp"
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Configure prefix list P1 on R2 to permit route coming from R1")
+ # Create ip prefix list
+ input_dict_2 = {
+ "r2": {
+ "prefix_lists": {
+ addr_type: {
+ "pf_list_1_{}".format(addr_type): [
+ {"seqid": 10, "network": "any", "action": "permit"}
+ ]
+ }
+ }
+ }
+ }
+ result = create_prefix_lists(tgen, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ # Create route map
+ input_dict_3 = {
+ "r2": {
+ "route_maps": {
+ "rmap_match_pf_1_{}".format(addr_type): [
+ {
+ "action": "permit",
+ "seq_id": "5",
+ "match": {
+ addr_type: {"prefix_lists": "pf_list_1_" + addr_type}
+ },
+ "set": {"community": {"num": "no-advertise"}},
+ }
+ ]
+ }
+ }
+ }
+ result = create_route_maps(tgen, input_dict_3)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+ step(
+ "Apply route-map RM1 on R2, R2 to R3 BGP neighbor with no"
+ " advertise community"
+ )
+
+ # Configure neighbor for route map
+ input_dict_4 = {
+ "r2": {
+ "bgp": {
+ "address_family": {
+ addr_type: {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2": {
+ "route_maps": [
+ {
+ "name": "rmap_match_pf_1_"
+ + addr_type,
+ "direction": "in",
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_4)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step(
+ "After advertising no advertise community to BGP neighbor "
+ "static and connected router got removed from R3 verify using "
+ "show ip bgp & show ip route"
+ )
+
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict)
+ assert result is True, "Testcase {} : Failed \n "
+ " Routes still present in R3 router. Error: {}".format(tc_name, result)
+
+ result = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+ assert result is True, "Testcase {} : Failed \n "
+ " Routes still present in R3 router. Error: {}".format(tc_name, result)
+
+ step("Remove and Add no advertise community")
+ # Configure neighbor for route map
+ input_dict_4 = {
+ "r2": {
+ "bgp": {
+ "address_family": {
+ addr_type: {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2": {
+ "route_maps": [
+ {
+ "name": "rmap_match_pf_1_"
+ + addr_type,
+ "direction": "in",
+ "delete": True,
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_4)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step(
+ "After removing no advertise community from BGP neighbor "
+ "static and connected router got advertised to R3 and "
+ "removing route verify using show ip bgp and "
+ " show ip route"
+ )
+
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict)
+ assert result is True, "Testcase {} : Failed \n "
+ " Routes still present in R3 router. Error: {}".format(tc_name, result)
+
+ result = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+ assert result is True, "Testcase {} : Failed \n "
+ " Routes still present in R3 router. Error: {}".format(tc_name, result)
+
+ write_test_footer(tc_name)
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/lib/bgp.py b/tests/topotests/lib/bgp.py
index d183fb9f60..b2cd2d284d 100644
--- a/tests/topotests/lib/bgp.py
+++ b/tests/topotests/lib/bgp.py
@@ -33,6 +33,7 @@ from lib.common_config import (
load_config_to_router,
check_address_types,
generate_ips,
+ validate_ip_address,
find_interface_with_greater_ip,
run_frr_cmd,
retry,
@@ -82,6 +83,9 @@ def create_router_bgp(tgen, topo, input_dict=None, build=False):
"holddowntimer": 180,
"dest_link": {
"r4": {
+ "allowas-in": {
+ "number_occurences":2
+ },
"prefix_lists": [
{
"name": "pf_list_1",
@@ -469,6 +473,7 @@ def __create_bgp_unicast_address_family(
prefix_lists = peer.setdefault("prefix_lists", {})
route_maps = peer.setdefault("route_maps", {})
no_send_community = peer.setdefault("no_send_community", None)
+ allowas_in = peer.setdefault("allowas-in", None)
# next-hop-self
if next_hop_self:
@@ -483,6 +488,13 @@ def __create_bgp_unicast_address_family(
"no {} send-community {}".format(neigh_cxt, no_send_community)
)
+ if "allowas_in" in peer:
+ allow_as_in = peer["allowas_in"]
+ config_data.append("{} allowas-in {}".format(neigh_cxt, allow_as_in))
+
+ if "no_allowas_in" in peer:
+ allow_as_in = peer["no_allowas_in"]
+ config_data.append("no {} allowas-in {}".format(neigh_cxt, allow_as_in))
if prefix_lists:
for prefix_list in prefix_lists:
name = prefix_list.setdefault("name", {})
@@ -517,6 +529,17 @@ def __create_bgp_unicast_address_family(
cmd = "no {}".format(cmd)
config_data.append(cmd)
+ if allowas_in:
+ number_occurences = allowas_in.setdefault("number_occurences", {})
+ del_action = allowas_in.setdefault("delete", False)
+
+ cmd = "{} allowas-in {}".format(neigh_cxt, number_occurences)
+
+ if del_action:
+ cmd = "no {}".format(cmd)
+
+ config_data.append(cmd)
+
return config_data
@@ -616,6 +639,9 @@ def verify_bgp_convergence(tgen, topo):
logger.debug("Entering lib API: verify_bgp_convergence()")
for router, rnode in tgen.routers().iteritems():
+ if "bgp" not in topo["routers"][router]:
+ continue
+
logger.info("Verifying BGP Convergence on router %s", router)
show_bgp_json = run_frr_cmd(rnode, "show bgp summary json", isjson=True)
# Verifying output dictionary show_bgp_json is empty or not
@@ -929,7 +955,6 @@ def clear_bgp_and_verify(tgen, topo, router):
)
return errormsg
- logger.info(peer_uptime_before_clear_bgp)
# Clearing BGP
logger.info("Clearing BGP neighborship for router %s..", router)
for addr_type in bgp_addr_type.keys():
@@ -1008,7 +1033,7 @@ def clear_bgp_and_verify(tgen, topo, router):
" router {}".format(router)
)
return errormsg
- logger.info(peer_uptime_after_clear_bgp)
+
# Comparing peerUptimeEstablishedEpoch dictionaries
if peer_uptime_before_clear_bgp != peer_uptime_after_clear_bgp:
logger.info("BGP neighborship is reset after clear BGP on router %s", router)
@@ -1679,3 +1704,501 @@ def verify_best_path_as_per_admin_distance(
logger.info("Exiting lib API: verify_best_path_as_per_admin_distance()")
return True
+
+
+@retry(attempts=5, wait=2, return_is_str=True, initial_wait=2)
+def verify_bgp_rib(tgen, addr_type, dut, input_dict, next_hop=None, aspath=None):
+ """
+ This API is to verify whether bgp rib has any
+ matching route for a nexthop.
+
+ Parameters
+ ----------
+ * `tgen`: topogen object
+ * `dut`: input dut router name
+ * `addr_type` : ip type ipv4/ipv6
+ * `input_dict` : input dict, has details of static routes
+ * `next_hop`[optional]: next_hop which needs to be verified,
+ default = static
+ * 'aspath'[optional]: aspath which needs to be verified
+
+ Usage
+ -----
+ dut = 'r1'
+ next_hop = "192.168.1.10"
+ input_dict = topo['routers']
+ aspath = "100 200 300"
+ result = verify_bgp_rib(tgen, addr_type, dut, tgen, input_dict,
+ next_hop, aspath)
+
+ Returns
+ -------
+ errormsg(str) or True
+ """
+
+ logger.debug("Entering lib API: verify_bgp_rib()")
+
+ router_list = tgen.routers()
+ additional_nexthops_in_required_nhs = []
+ list1 = []
+ list2 = []
+ for routerInput in input_dict.keys():
+ for router, rnode in router_list.iteritems():
+ if router != dut:
+ continue
+
+ # Verifying RIB routes
+ command = "show bgp"
+
+ # Static routes
+ sleep(2)
+ logger.info("Checking router {} BGP RIB:".format(dut))
+
+ if "static_routes" in input_dict[routerInput]:
+ static_routes = input_dict[routerInput]["static_routes"]
+
+ for static_route in static_routes:
+ found_routes = []
+ missing_routes = []
+ st_found = False
+ nh_found = False
+ vrf = static_route.setdefault("vrf", None)
+ if vrf:
+ cmd = "{} vrf {} {}".format(command, vrf, addr_type)
+
+ else:
+ cmd = "{} {}".format(command, addr_type)
+
+ cmd = "{} json".format(cmd)
+
+ rib_routes_json = run_frr_cmd(rnode, cmd, isjson=True)
+
+ # Verifying output dictionary rib_routes_json is not empty
+ if bool(rib_routes_json) == False:
+ errormsg = "No route found in rib of router {}..".format(router)
+ return errormsg
+
+ network = static_route["network"]
+
+ if "no_of_ip" in static_route:
+ no_of_ip = static_route["no_of_ip"]
+ else:
+ no_of_ip = 1
+
+ # Generating IPs for verification
+ ip_list = generate_ips(network, no_of_ip)
+
+ for st_rt in ip_list:
+ st_rt = str(ipaddr.IPNetwork(unicode(st_rt)))
+
+ _addr_type = validate_ip_address(st_rt)
+ if _addr_type != addr_type:
+ continue
+
+ if st_rt in rib_routes_json["routes"]:
+ st_found = True
+ found_routes.append(st_rt)
+
+ if next_hop:
+ if not isinstance(next_hop, list):
+ next_hop = [next_hop]
+ list1 = next_hop
+ found_hops = [
+ rib_r["ip"]
+ for rib_r in rib_routes_json["routes"][st_rt][0][
+ "nexthops"
+ ]
+ ]
+ list2 = found_hops
+ missing_list_of_nexthops = set(list2).difference(list1)
+ additional_nexthops_in_required_nhs = set(
+ list1
+ ).difference(list2)
+
+ if list2:
+ if additional_nexthops_in_required_nhs:
+ logger.info(
+ "Missing nexthop %s for route"
+ " %s in RIB of router %s\n",
+ additional_nexthops_in_required_nhs,
+ st_rt,
+ dut,
+ )
+ errormsg = (
+ "Nexthop {} is Missing for "
+ "route {} in RIB of router {}\n".format(
+ additional_nexthops_in_required_nhs,
+ st_rt,
+ dut,
+ )
+ )
+ return errormsg
+ else:
+ nh_found = True
+ if aspath:
+ found_paths = rib_routes_json["routes"][st_rt][0][
+ "path"
+ ]
+ if aspath == found_paths:
+ aspath_found = True
+ logger.info(
+ "Found AS path {} for route"
+ " {} in RIB of router "
+ "{}\n".format(aspath, st_rt, dut)
+ )
+ else:
+ errormsg = (
+ "AS Path {} is missing for route"
+ "for route {} in RIB of router {}\n".format(
+ aspath, st_rt, dut
+ )
+ )
+ return errormsg
+
+ else:
+ missing_routes.append(st_rt)
+
+ if nh_found:
+ logger.info(
+ "Found next_hop {} for all bgp"
+ " routes in RIB of"
+ " router {}\n".format(next_hop, router)
+ )
+
+ if len(missing_routes) > 0:
+ errormsg = (
+ "Missing route in RIB of router {}, "
+ "routes: {}\n".format(dut, missing_routes)
+ )
+ return errormsg
+
+ if found_routes:
+ logger.info(
+ "Verified routes in router {} BGP RIB, "
+ "found routes are: {} \n".format(dut, found_routes)
+ )
+ continue
+
+ if "bgp" not in input_dict[routerInput]:
+ continue
+
+ # Advertise networks
+ bgp_data_list = input_dict[routerInput]["bgp"]
+
+ if type(bgp_data_list) is not list:
+ bgp_data_list = [bgp_data_list]
+
+ for bgp_data in bgp_data_list:
+ vrf_id = bgp_data.setdefault("vrf", None)
+ if vrf_id:
+ cmd = "{} vrf {} {}".format(command, vrf_id, addr_type)
+ else:
+ cmd = "{} {}".format(command, addr_type)
+
+ cmd = "{} json".format(cmd)
+
+ rib_routes_json = run_frr_cmd(rnode, cmd, isjson=True)
+
+ # Verifying output dictionary rib_routes_json is not empty
+ if bool(rib_routes_json) == False:
+ errormsg = "No route found in rib of router {}..".format(router)
+ return errormsg
+
+ bgp_net_advertise = bgp_data["address_family"][addr_type]["unicast"]
+ advertise_network = bgp_net_advertise.setdefault(
+ "advertise_networks", []
+ )
+
+ for advertise_network_dict in advertise_network:
+ found_routes = []
+ missing_routes = []
+ found = False
+
+ network = advertise_network_dict["network"]
+
+ if "no_of_network" in advertise_network_dict:
+ no_of_network = advertise_network_dict["no_of_network"]
+ else:
+ no_of_network = 1
+
+ # Generating IPs for verification
+ ip_list = generate_ips(network, no_of_network)
+
+ for st_rt in ip_list:
+ st_rt = str(ipaddr.IPNetwork(unicode(st_rt)))
+
+ _addr_type = validate_ip_address(st_rt)
+ if _addr_type != addr_type:
+ continue
+
+ if st_rt in rib_routes_json["routes"]:
+ found = True
+ found_routes.append(st_rt)
+ else:
+ found = False
+ missing_routes.append(st_rt)
+
+ if len(missing_routes) > 0:
+ errormsg = (
+ "Missing route in BGP RIB of router {},"
+ " are: {}\n".format(dut, missing_routes)
+ )
+ return errormsg
+
+ if found_routes:
+ logger.info(
+ "Verified routes in router {} BGP RIB, found "
+ "routes are: {}\n".format(dut, found_routes)
+ )
+
+ logger.debug("Exiting lib API: verify_bgp_rib()")
+ return True
+
+
+@retry(attempts=5, wait=2, return_is_str=True, initial_wait=2)
+def verify_bgp_rib(tgen, addr_type, dut, input_dict, next_hop=None, aspath=None):
+ """
+ This API is to verify whether bgp rib has any
+ matching route for a nexthop.
+
+ Parameters
+ ----------
+ * `tgen`: topogen object
+ * `dut`: input dut router name
+ * `addr_type` : ip type ipv4/ipv6
+ * `input_dict` : input dict, has details of static routes
+ * `next_hop`[optional]: next_hop which needs to be verified,
+ default = static
+ * 'aspath'[optional]: aspath which needs to be verified
+
+ Usage
+ -----
+ dut = 'r1'
+ next_hop = "192.168.1.10"
+ input_dict = topo['routers']
+ aspath = "100 200 300"
+ result = verify_bgp_rib(tgen, addr_type, dut, tgen, input_dict,
+ next_hop, aspath)
+
+ Returns
+ -------
+ errormsg(str) or True
+ """
+
+ logger.debug("Entering lib API: verify_bgp_rib()")
+
+ router_list = tgen.routers()
+ additional_nexthops_in_required_nhs = []
+ list1 = []
+ list2 = []
+ for routerInput in input_dict.keys():
+ for router, rnode in router_list.iteritems():
+ if router != dut:
+ continue
+
+ # Verifying RIB routes
+ command = "show bgp"
+
+ # Static routes
+ sleep(2)
+ logger.info("Checking router {} BGP RIB:".format(dut))
+
+ if "static_routes" in input_dict[routerInput]:
+ static_routes = input_dict[routerInput]["static_routes"]
+
+ for static_route in static_routes:
+ found_routes = []
+ missing_routes = []
+ st_found = False
+ nh_found = False
+ vrf = static_route.setdefault("vrf", None)
+ if vrf:
+ cmd = "{} vrf {} {}".format(command, vrf, addr_type)
+
+ else:
+ cmd = "{} {}".format(command, addr_type)
+
+ cmd = "{} json".format(cmd)
+
+ rib_routes_json = run_frr_cmd(rnode, cmd, isjson=True)
+
+ # Verifying output dictionary rib_routes_json is not empty
+ if bool(rib_routes_json) == False:
+ errormsg = "No route found in rib of router {}..".format(router)
+ return errormsg
+
+ network = static_route["network"]
+
+ if "no_of_ip" in static_route:
+ no_of_ip = static_route["no_of_ip"]
+ else:
+ no_of_ip = 1
+
+ # Generating IPs for verification
+ ip_list = generate_ips(network, no_of_ip)
+
+ for st_rt in ip_list:
+ st_rt = str(ipaddr.IPNetwork(unicode(st_rt)))
+
+ _addr_type = validate_ip_address(st_rt)
+ if _addr_type != addr_type:
+ continue
+
+ if st_rt in rib_routes_json["routes"]:
+ st_found = True
+ found_routes.append(st_rt)
+
+ if next_hop:
+ if not isinstance(next_hop, list):
+ next_hop = [next_hop]
+ list1 = next_hop
+ found_hops = [
+ rib_r["ip"]
+ for rib_r in rib_routes_json["routes"][st_rt][0][
+ "nexthops"
+ ]
+ ]
+ list2 = found_hops
+ missing_list_of_nexthops = set(list2).difference(list1)
+ additional_nexthops_in_required_nhs = set(
+ list1
+ ).difference(list2)
+
+ if list2:
+ if additional_nexthops_in_required_nhs:
+ logger.info(
+ "Missing nexthop %s for route"
+ " %s in RIB of router %s\n",
+ additional_nexthops_in_required_nhs,
+ st_rt,
+ dut,
+ )
+ errormsg = (
+ "Nexthop {} is Missing for "
+ "route {} in RIB of router {}\n".format(
+ additional_nexthops_in_required_nhs,
+ st_rt,
+ dut,
+ )
+ )
+ return errormsg
+ else:
+ nh_found = True
+ if aspath:
+ found_paths = rib_routes_json["routes"][st_rt][0][
+ "path"
+ ]
+ if aspath == found_paths:
+ aspath_found = True
+ logger.info(
+ "Found AS path {} for route"
+ " {} in RIB of router "
+ "{}\n".format(aspath, st_rt, dut)
+ )
+ else:
+ errormsg = (
+ "AS Path {} is missing for route"
+ "for route {} in RIB of router {}\n".format(
+ aspath, st_rt, dut
+ )
+ )
+ return errormsg
+
+ else:
+ missing_routes.append(st_rt)
+
+ if nh_found:
+ logger.info(
+ "Found next_hop {} for all bgp"
+ " routes in RIB of"
+ " router {}\n".format(next_hop, router)
+ )
+
+ if len(missing_routes) > 0:
+ errormsg = (
+ "Missing route in RIB of router {}, "
+ "routes: {}\n".format(dut, missing_routes)
+ )
+ return errormsg
+
+ if found_routes:
+ logger.info(
+ "Verified routes in router {} BGP RIB, "
+ "found routes are: {} \n".format(dut, found_routes)
+ )
+ continue
+
+ if "bgp" not in input_dict[routerInput]:
+ continue
+
+ # Advertise networks
+ bgp_data_list = input_dict[routerInput]["bgp"]
+
+ if type(bgp_data_list) is not list:
+ bgp_data_list = [bgp_data_list]
+
+ for bgp_data in bgp_data_list:
+ vrf_id = bgp_data.setdefault("vrf", None)
+ if vrf_id:
+ cmd = "{} vrf {} {}".format(command, vrf_id, addr_type)
+ else:
+ cmd = "{} {}".format(command, addr_type)
+
+ cmd = "{} json".format(cmd)
+
+ rib_routes_json = run_frr_cmd(rnode, cmd, isjson=True)
+
+ # Verifying output dictionary rib_routes_json is not empty
+ if bool(rib_routes_json) == False:
+ errormsg = "No route found in rib of router {}..".format(router)
+ return errormsg
+
+ bgp_net_advertise = bgp_data["address_family"][addr_type]["unicast"]
+ advertise_network = bgp_net_advertise.setdefault(
+ "advertise_networks", []
+ )
+
+ for advertise_network_dict in advertise_network:
+ found_routes = []
+ missing_routes = []
+ found = False
+
+ network = advertise_network_dict["network"]
+
+ if "no_of_network" in advertise_network_dict:
+ no_of_network = advertise_network_dict["no_of_network"]
+ else:
+ no_of_network = 1
+
+ # Generating IPs for verification
+ ip_list = generate_ips(network, no_of_network)
+
+ for st_rt in ip_list:
+ st_rt = str(ipaddr.IPNetwork(unicode(st_rt)))
+
+ _addr_type = validate_ip_address(st_rt)
+ if _addr_type != addr_type:
+ continue
+
+ if st_rt in rib_routes_json["routes"]:
+ found = True
+ found_routes.append(st_rt)
+ else:
+ found = False
+ missing_routes.append(st_rt)
+
+ if len(missing_routes) > 0:
+ errormsg = (
+ "Missing route in BGP RIB of router {},"
+ " are: {}\n".format(dut, missing_routes)
+ )
+ return errormsg
+
+ if found_routes:
+ logger.info(
+ "Verified routes in router {} BGP RIB, found "
+ "routes are: {}\n".format(dut, found_routes)
+ )
+
+ logger.debug("Exiting lib API: verify_bgp_rib()")
+ return True
diff --git a/tests/topotests/rip-topo1/r1/rip_status.ref b/tests/topotests/rip-topo1/r1/rip_status.ref
index d75fbe85bb..31ad46ab2e 100644
--- a/tests/topotests/rip-topo1/r1/rip_status.ref
+++ b/tests/topotests/rip-topo1/r1/rip_status.ref
@@ -8,8 +8,14 @@ Routing Protocol is "rip"
Default version control: send version 2, receive version 2
Interface Send Recv Key-chain
r1-eth1 2 2
+ r1-eth2 2 2
+ r1-eth3 2 2
Routing for Networks:
193.1.1.0/26
+ r1-eth2
+ r1-eth3
+ Passive Interface(s):
+ r1-eth3
Routing Information Sources:
Gateway BadPackets BadRoutes Distance Last Update
193.1.1.2 0 0 120 XX:XX:XX
diff --git a/tests/topotests/rip-topo1/r1/ripd.conf b/tests/topotests/rip-topo1/r1/ripd.conf
index 935ec312e5..54f1774214 100644
--- a/tests/topotests/rip-topo1/r1/ripd.conf
+++ b/tests/topotests/rip-topo1/r1/ripd.conf
@@ -4,6 +4,9 @@ router rip
timers basic 5 180 5
version 2
network 193.1.1.0/26
+ network r1-eth2
+ network r1-eth3
+ passive-interface r1-eth3
!
line vty
!
diff --git a/tests/topotests/rip-topo1/r1/show_ip_rip.ref b/tests/topotests/rip-topo1/r1/show_ip_rip.ref
index 561560f230..a0b77c886e 100644
--- a/tests/topotests/rip-topo1/r1/show_ip_rip.ref
+++ b/tests/topotests/rip-topo1/r1/show_ip_rip.ref
@@ -6,5 +6,7 @@ Sub-codes:
Network Next Hop Metric From Tag Time
R(n) 192.168.2.0/24 193.1.1.2 3 193.1.1.2 0 XX:XX
R(n) 192.168.3.0/24 193.1.1.2 3 193.1.1.2 0 XX:XX
+C(i) 192.168.98.0/24 0.0.0.0 1 self 0
+C(i) 192.168.99.0/24 0.0.0.0 1 self 0
C(i) 193.1.1.0/26 0.0.0.0 1 self 0
R(n) 193.1.2.0/24 193.1.1.2 2 193.1.1.2 0 XX:XX
diff --git a/tests/topotests/rip-topo1/r1/zebra.conf b/tests/topotests/rip-topo1/r1/zebra.conf
index 8537f6dd80..7c8f2c502b 100644
--- a/tests/topotests/rip-topo1/r1/zebra.conf
+++ b/tests/topotests/rip-topo1/r1/zebra.conf
@@ -5,6 +5,13 @@ hostname r1
interface r1-eth0
ip address 192.168.1.1/24
!
+interface r1-eth2
+ ip address 192.168.99.1/24
+!
+interface r1-eth3
+ ip address 192.168.98.1/24
+!
+
interface r1-eth1
description to sw2 - RIPv2 interface
ip address 193.1.1.1/26
diff --git a/tests/topotests/rip-topo1/r2/rip_status.ref b/tests/topotests/rip-topo1/r2/rip_status.ref
index da1abd041a..99841a62b0 100644
--- a/tests/topotests/rip-topo1/r2/rip_status.ref
+++ b/tests/topotests/rip-topo1/r2/rip_status.ref
@@ -14,5 +14,6 @@ Routing Protocol is "rip"
193.1.2.0/24
Routing Information Sources:
Gateway BadPackets BadRoutes Distance Last Update
+ 193.1.1.1 0 0 120 XX:XX:XX
193.1.2.2 0 0 120 XX:XX:XX
Distance: (default is 120)
diff --git a/tests/topotests/rip-topo1/r2/show_ip_rip.ref b/tests/topotests/rip-topo1/r2/show_ip_rip.ref
index 58ab052160..b61fb45eac 100644
--- a/tests/topotests/rip-topo1/r2/show_ip_rip.ref
+++ b/tests/topotests/rip-topo1/r2/show_ip_rip.ref
@@ -6,5 +6,7 @@ Sub-codes:
Network Next Hop Metric From Tag Time
R(n) 192.168.2.0/24 193.1.2.2 2 193.1.2.2 0 XX:XX
R(n) 192.168.3.0/24 193.1.2.2 2 193.1.2.2 0 XX:XX
+R(n) 192.168.98.0/24 193.1.1.1 2 193.1.1.1 0 XX:XX
+R(n) 192.168.99.0/24 193.1.1.1 2 193.1.1.1 0 XX:XX
C(i) 193.1.1.0/26 0.0.0.0 1 self 0
C(i) 193.1.2.0/24 0.0.0.0 1 self 0
diff --git a/tests/topotests/rip-topo1/r2/show_ip_route.ref b/tests/topotests/rip-topo1/r2/show_ip_route.ref
index 22afbee385..80f51a92c7 100644
--- a/tests/topotests/rip-topo1/r2/show_ip_route.ref
+++ b/tests/topotests/rip-topo1/r2/show_ip_route.ref
@@ -1,2 +1,4 @@
R>* 192.168.2.0/24 [120/2] via 193.1.2.2, r2-eth1, weight 1
R>* 192.168.3.0/24 [120/2] via 193.1.2.2, r2-eth1, weight 1
+R>* 192.168.98.0/24 [120/2] via 193.1.1.1, r2-eth0, weight 1
+R>* 192.168.99.0/24 [120/2] via 193.1.1.1, r2-eth0, weight 1
diff --git a/tests/topotests/rip-topo1/r3/show_ip_rip.ref b/tests/topotests/rip-topo1/r3/show_ip_rip.ref
index cf672712a8..1df299b5e6 100644
--- a/tests/topotests/rip-topo1/r3/show_ip_rip.ref
+++ b/tests/topotests/rip-topo1/r3/show_ip_rip.ref
@@ -6,5 +6,7 @@ Sub-codes:
Network Next Hop Metric From Tag Time
S(r) 192.168.2.0/24 192.168.3.10 1 self 0
C(r) 192.168.3.0/24 0.0.0.0 1 self 0
+R(n) 192.168.98.0/24 193.1.2.1 3 193.1.2.1 0 XX:XX
+R(n) 192.168.99.0/24 193.1.2.1 3 193.1.2.1 0 XX:XX
R(n) 193.1.1.0/26 193.1.2.1 2 193.1.2.1 0 XX:XX
C(i) 193.1.2.0/24 0.0.0.0 1 self 0
diff --git a/tests/topotests/rip-topo1/r3/show_ip_route.ref b/tests/topotests/rip-topo1/r3/show_ip_route.ref
index 995b6d7da9..2b739f0489 100644
--- a/tests/topotests/rip-topo1/r3/show_ip_route.ref
+++ b/tests/topotests/rip-topo1/r3/show_ip_route.ref
@@ -1 +1,3 @@
+R>* 192.168.98.0/24 [120/3] via 193.1.2.1, r3-eth1, weight 1
+R>* 192.168.99.0/24 [120/3] via 193.1.2.1, r3-eth1, weight 1
R>* 193.1.1.0/26 [120/2] via 193.1.2.1, r3-eth1, weight 1
diff --git a/tests/topotests/rip-topo1/test_rip_topo1.py b/tests/topotests/rip-topo1/test_rip_topo1.py
index 132d38c2e5..3098812a24 100755
--- a/tests/topotests/rip-topo1/test_rip_topo1.py
+++ b/tests/topotests/rip-topo1/test_rip_topo1.py
@@ -91,6 +91,12 @@ class NetworkTopo(Topo):
switch[4] = self.addSwitch("sw4", cls=topotest.LegacySwitch)
self.addLink(switch[4], router[3], intfName2="r3-eth0")
+ switch[5] = self.addSwitch("sw5", cls=topotest.LegacySwitch)
+ self.addLink(switch[5], router[1], intfName2="r1-eth2")
+
+ switch[6] = self.addSwitch("sw6", cls=topotest.LegacySwitch)
+ self.addLink(switch[6], router[1], intfName2="r1-eth3")
+
#####################################################
##
diff --git a/tests/topotests/ripng-topo1/r1/ripng_status.ref b/tests/topotests/ripng-topo1/r1/ripng_status.ref
index e6197f179b..b02cc69d0e 100644
--- a/tests/topotests/ripng-topo1/r1/ripng_status.ref
+++ b/tests/topotests/ripng-topo1/r1/ripng_status.ref
@@ -8,8 +8,12 @@ Routing Protocol is "RIPng"
Default version control: send version 1, receive version 1
Interface Send Recv
r1-eth1 1 1
+ r1-eth2 1 1
+ r1-eth3 1 1
Routing for Networks:
fc00:5::/64
+ r1-eth2
+ r1-eth3
Routing Information Sources:
Gateway BadPackets BadRoutes Distance Last Update
fe80::XXXX:XXXX:XXXX:XXXX
diff --git a/tests/topotests/ripng-topo1/r1/ripngd.conf b/tests/topotests/ripng-topo1/r1/ripngd.conf
index dd54c43557..07ed7296d9 100644
--- a/tests/topotests/ripng-topo1/r1/ripngd.conf
+++ b/tests/topotests/ripng-topo1/r1/ripngd.conf
@@ -7,6 +7,9 @@ debug ripng zebra
router ripng
timers basic 5 180 5
network fc00:5::/64
+ network r1-eth2
+ network r1-eth3
+ passive-interface r1-eth3
!
line vty
!
diff --git a/tests/topotests/ripng-topo1/r1/show_ipv6_ripng.ref b/tests/topotests/ripng-topo1/r1/show_ipv6_ripng.ref
index 18d026a8fd..30d0f31e18 100644
--- a/tests/topotests/ripng-topo1/r1/show_ipv6_ripng.ref
+++ b/tests/topotests/ripng-topo1/r1/show_ipv6_ripng.ref
@@ -12,3 +12,7 @@ R(n) fc00:7::/64
fe80::XXXX:XXXX:XXXX:XXXX r1-eth1 3 0 XX:XX
R(n) fc00:7:1111::/64
fe80::XXXX:XXXX:XXXX:XXXX r1-eth1 3 0 XX:XX
+C(i) fc00:98:0:1::/64
+ :: self 1 0
+C(i) fc00:99:0:1::/64
+ :: self 1 0
diff --git a/tests/topotests/ripng-topo1/r1/zebra.conf b/tests/topotests/ripng-topo1/r1/zebra.conf
index 1a10343044..11c1cdc5b9 100644
--- a/tests/topotests/ripng-topo1/r1/zebra.conf
+++ b/tests/topotests/ripng-topo1/r1/zebra.conf
@@ -10,6 +10,12 @@ interface r1-eth1
ipv6 address fc00:5::1/64
no link-detect
!
+interface r1-eth2
+ ipv6 address fc00:99:0:1::1/64
+!
+interface r1-eth3
+ ipv6 address fc00:98:0:1::1/64
+!
ip forwarding
ipv6 forwarding
!
diff --git a/tests/topotests/ripng-topo1/r2/show_ipv6_ripng.ref b/tests/topotests/ripng-topo1/r2/show_ipv6_ripng.ref
index 765efd07a2..fe5bcc8b31 100644
--- a/tests/topotests/ripng-topo1/r2/show_ipv6_ripng.ref
+++ b/tests/topotests/ripng-topo1/r2/show_ipv6_ripng.ref
@@ -12,3 +12,7 @@ R(n) fc00:7::/64
fe80::XXXX:XXXX:XXXX:XXXX r2-eth1 2 0 XX:XX
R(n) fc00:7:1111::/64
fe80::XXXX:XXXX:XXXX:XXXX r2-eth1 2 0 XX:XX
+R(n) fc00:98:0:1::/64
+ fe80::XXXX:XXXX:XXXX:XXXX r2-eth0 2 0 XX:XX
+R(n) fc00:99:0:1::/64
+ fe80::XXXX:XXXX:XXXX:XXXX r2-eth0 2 0 XX:XX
diff --git a/tests/topotests/ripng-topo1/r2/show_ipv6_route.ref b/tests/topotests/ripng-topo1/r2/show_ipv6_route.ref
index 8c98b7a67b..72e1f926a2 100644
--- a/tests/topotests/ripng-topo1/r2/show_ipv6_route.ref
+++ b/tests/topotests/ripng-topo1/r2/show_ipv6_route.ref
@@ -1,2 +1,4 @@
R>* fc00:7::/64 [120/2] via fe80::XXXX:XXXX:XXXX:XXXX, r2-eth1, weight 1
R>* fc00:7:1111::/64 [120/2] via fe80::XXXX:XXXX:XXXX:XXXX, r2-eth1, weight 1
+R>* fc00:98:0:1::/64 [120/2] via fe80::XXXX:XXXX:XXXX:XXXX, r2-eth0, weight 1
+R>* fc00:99:0:1::/64 [120/2] via fe80::XXXX:XXXX:XXXX:XXXX, r2-eth0, weight 1
diff --git a/tests/topotests/ripng-topo1/r3/show_ipv6_ripng.ref b/tests/topotests/ripng-topo1/r3/show_ipv6_ripng.ref
index 81e76b97a6..909ad663ba 100644
--- a/tests/topotests/ripng-topo1/r3/show_ipv6_ripng.ref
+++ b/tests/topotests/ripng-topo1/r3/show_ipv6_ripng.ref
@@ -12,3 +12,7 @@ C(r) fc00:7::/64
:: self 1 0
S(r) fc00:7:1111::/64
:: self 1 0
+R(n) fc00:98:0:1::/64
+ fe80::XXXX:XXXX:XXXX:XXXX r3-eth1 3 0 XX:XX
+R(n) fc00:99:0:1::/64
+ fe80::XXXX:XXXX:XXXX:XXXX r3-eth1 3 0 XX:XX
diff --git a/tests/topotests/ripng-topo1/r3/show_ipv6_route.ref b/tests/topotests/ripng-topo1/r3/show_ipv6_route.ref
index 2e9de88db5..25a7440111 100644
--- a/tests/topotests/ripng-topo1/r3/show_ipv6_route.ref
+++ b/tests/topotests/ripng-topo1/r3/show_ipv6_route.ref
@@ -1 +1,3 @@
R>* fc00:5::/64 [120/2] via fe80::XXXX:XXXX:XXXX:XXXX, r3-eth1, weight 1
+R>* fc00:98:0:1::/64 [120/3] via fe80::XXXX:XXXX:XXXX:XXXX, r3-eth1, weight 1
+R>* fc00:99:0:1::/64 [120/3] via fe80::XXXX:XXXX:XXXX:XXXX, r3-eth1, weight 1
diff --git a/tests/topotests/ripng-topo1/test_ripng_topo1.py b/tests/topotests/ripng-topo1/test_ripng_topo1.py
index 51f7fb6fb1..23e689235c 100755
--- a/tests/topotests/ripng-topo1/test_ripng_topo1.py
+++ b/tests/topotests/ripng-topo1/test_ripng_topo1.py
@@ -92,6 +92,11 @@ class NetworkTopo(Topo):
switch[4] = self.addSwitch("sw4", cls=topotest.LegacySwitch)
self.addLink(switch[4], router[3], intfName2="r3-eth0")
+ switch[5] = self.addSwitch("sw5", cls=topotest.LegacySwitch)
+ self.addLink(switch[5], router[1], intfName2="r1-eth2")
+ switch[6] = self.addSwitch("sw6", cls=topotest.LegacySwitch)
+ self.addLink(switch[6], router[1], intfName2="r1-eth3")
+
#####################################################
##