summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/lib/test_resolver.c2
-rw-r--r--tests/topotests/bfd_topo3/r1/bfd-peers.json9
-rw-r--r--tests/topotests/bfd_topo3/r2/bfd-peers.json6
-rw-r--r--tests/topotests/bfd_topo3/r3/bfd-peers.json9
-rw-r--r--tests/topotests/bfd_topo3/r4/bfd-peers.json6
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer1/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer10/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer11/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer12/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer13/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer14/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer15/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer16/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer17/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer18/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer19/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer2/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer20/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer3/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer4/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer5/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer6/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer7/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer8/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer9/exa-send.py2
-rw-r--r--tests/topotests/bgp_ecmp_topo1/r1/summary.txt2
-rw-r--r--tests/topotests/bgp_ecmp_topo1/r1/summary20.txt2
-rw-r--r--tests/topotests/bgp_ecmp_topo1/test_bgp_ecmp_topo1.py8
-rw-r--r--tests/topotests/bgp_evpn_rt5/test_bgp_evpn.py2
-rw-r--r--tests/topotests/bgp_extended_optional_parameters_length/__init__.py0
-rw-r--r--tests/topotests/bgp_extended_optional_parameters_length/r1/bgpd.conf6
-rw-r--r--tests/topotests/bgp_extended_optional_parameters_length/r1/zebra.conf4
-rw-r--r--tests/topotests/bgp_extended_optional_parameters_length/r2/bgpd.conf8
-rw-r--r--tests/topotests/bgp_extended_optional_parameters_length/r2/zebra.conf7
-rw-r--r--tests/topotests/bgp_extended_optional_parameters_length/test_bgp_extended_optional_parameters_length.py106
-rw-r--r--tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-1.py1542
-rw-r--r--tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-2.py404
-rw-r--r--tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-3.py (renamed from tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1.py)2321
-rw-r--r--tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-4.py1686
-rw-r--r--tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-1.py1515
-rw-r--r--tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-2.py1216
-rw-r--r--tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-3.py1367
-rw-r--r--tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-4.py1024
-rw-r--r--tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2.py4358
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_routes.py56
-rwxr-xr-xtests/topotests/bgp_multiview_topo1/peer1/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_multiview_topo1/peer2/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_multiview_topo1/peer3/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_multiview_topo1/peer4/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_multiview_topo1/peer5/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_multiview_topo1/peer6/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_multiview_topo1/peer7/exa-send.py2
-rwxr-xr-xtests/topotests/bgp_multiview_topo1/peer8/exa-send.py2
-rw-r--r--tests/topotests/bgp_peer_type_multipath_relax/peer1/exa_readpipe.py2
-rw-r--r--tests/topotests/bgp_peer_type_multipath_relax/peer2/exa_readpipe.py2
-rw-r--r--tests/topotests/bgp_peer_type_multipath_relax/peer3/exa_readpipe.py2
-rw-r--r--tests/topotests/bgp_peer_type_multipath_relax/peer4/exa_readpipe.py2
-rw-r--r--tests/topotests/bgp_route_map_match_ipv6_nexthop/__init__.py0
-rw-r--r--tests/topotests/bgp_route_map_match_ipv6_nexthop/r1/bgpd.conf32
-rw-r--r--tests/topotests/bgp_route_map_match_ipv6_nexthop/r1/zebra.conf4
-rw-r--r--tests/topotests/bgp_route_map_match_ipv6_nexthop/r2/bgpd.conf33
-rw-r--r--tests/topotests/bgp_route_map_match_ipv6_nexthop/r2/zebra.conf11
-rw-r--r--tests/topotests/bgp_route_map_match_ipv6_nexthop/test_bgp_route_map_match_ipv6_nexthop.py121
-rw-r--r--tests/topotests/bgp_route_server_client/__init__.py0
-rw-r--r--tests/topotests/bgp_route_server_client/r1/bgpd.conf12
-rw-r--r--tests/topotests/bgp_route_server_client/r1/zebra.conf7
-rw-r--r--tests/topotests/bgp_route_server_client/r2/bgpd.conf17
-rw-r--r--tests/topotests/bgp_route_server_client/r2/zebra.conf7
-rw-r--r--tests/topotests/bgp_route_server_client/r3/bgpd.conf12
-rw-r--r--tests/topotests/bgp_route_server_client/r3/zebra.conf7
-rw-r--r--tests/topotests/bgp_route_server_client/test_bgp_route_server_client.py143
-rw-r--r--tests/topotests/bgp_vrf_lite_best_path_test/bgp_vrf_lite_best_path_topo1.json563
-rw-r--r--tests/topotests/bgp_vrf_lite_best_path_test/bgp_vrf_lite_best_path_topo2.json1088
-rw-r--r--tests/topotests/bgp_vrf_lite_best_path_test/test_bgp_vrf_lite_best_path_topo1.py916
-rw-r--r--tests/topotests/bgp_vrf_lite_best_path_test/test_bgp_vrf_lite_best_path_topo2.py539
-rwxr-xr-xtests/topotests/bgp_vrf_netns/peer1/exa-send.py2
-rwxr-xr-xtests/topotests/conftest.py5
-rw-r--r--tests/topotests/isis_topo1_vrf/test_isis_topo1_vrf.py34
-rw-r--r--tests/topotests/lib/bgp.py92
-rw-r--r--tests/topotests/lib/common_config.py39
-rw-r--r--tests/topotests/lib/ospf.py115
-rw-r--r--tests/topotests/lib/pim.py44
-rw-r--r--tests/topotests/lib/topojson.py15
-rw-r--r--tests/topotests/lib/topotest.py9
-rw-r--r--tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py4
-rwxr-xr-xtests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo4.py14
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_lan.py2
-rw-r--r--tests/topotests/ospf_dual_stack/test_ospf_dual_stack.json52
-rw-r--r--tests/topotests/ospfv3_basic_functionality/ospfv3_nssa.json86
-rw-r--r--tests/topotests/ospfv3_basic_functionality/test_ospfv3_nssa.py162
-rwxr-xr-xtests/topotests/pim_basic/mcast-rx.py2
-rwxr-xr-xtests/topotests/pim_basic/mcast-tx.py2
92 files changed, 12983 insertions, 6938 deletions
diff --git a/tests/lib/test_resolver.c b/tests/lib/test_resolver.c
index 0b3dccc820..6a582cceaf 100644
--- a/tests/lib/test_resolver.c
+++ b/tests/lib/test_resolver.c
@@ -63,7 +63,7 @@ DEFUN (test_resolve,
"DNS resolver\n"
"Name to resolve\n")
{
- resolver_resolve(&query, AF_UNSPEC, argv[1]->arg, resolver_result);
+ resolver_resolve(&query, AF_UNSPEC, 0, argv[1]->arg, resolver_result);
return CMD_SUCCESS;
}
diff --git a/tests/topotests/bfd_topo3/r1/bfd-peers.json b/tests/topotests/bfd_topo3/r1/bfd-peers.json
index f8a354fc20..3ce8d97f15 100644
--- a/tests/topotests/bfd_topo3/r1/bfd-peers.json
+++ b/tests/topotests/bfd_topo3/r1/bfd-peers.json
@@ -18,9 +18,8 @@
"remote-receive-interval": 2000,
"remote-transmit-interval": 2000,
"status": "up",
- "transmit-interval": 2000,
"uptime": "*",
- "vrf": "default"
+ "transmit-interval": 2000
},
{
"detect-multiplier": 3,
@@ -41,9 +40,8 @@
"remote-receive-interval": 600,
"remote-transmit-interval": 600,
"status": "up",
- "transmit-interval": 600,
"uptime": "*",
- "vrf": "default"
+ "transmit-interval": 600
},
{
"detect-multiplier": 3,
@@ -64,8 +62,7 @@
"remote-receive-interval": 2000,
"remote-transmit-interval": 2000,
"status": "up",
- "transmit-interval": 2000,
"uptime": "*",
- "vrf": "default"
+ "transmit-interval": 2000
}
]
diff --git a/tests/topotests/bfd_topo3/r2/bfd-peers.json b/tests/topotests/bfd_topo3/r2/bfd-peers.json
index 786d66dbe3..a40f7e46cf 100644
--- a/tests/topotests/bfd_topo3/r2/bfd-peers.json
+++ b/tests/topotests/bfd_topo3/r2/bfd-peers.json
@@ -18,9 +18,8 @@
"remote-receive-interval": 600,
"remote-transmit-interval": 600,
"status": "up",
- "transmit-interval": 600,
"uptime": "*",
- "vrf": "default"
+ "transmit-interval": 600
},
{
"detect-multiplier": 3,
@@ -41,8 +40,7 @@
"remote-receive-interval": 2000,
"remote-transmit-interval": 2000,
"status": "up",
- "transmit-interval": 2000,
"uptime": "*",
- "vrf": "default"
+ "transmit-interval": 2000
}
]
diff --git a/tests/topotests/bfd_topo3/r3/bfd-peers.json b/tests/topotests/bfd_topo3/r3/bfd-peers.json
index 1f58663a4e..2182b26ed3 100644
--- a/tests/topotests/bfd_topo3/r3/bfd-peers.json
+++ b/tests/topotests/bfd_topo3/r3/bfd-peers.json
@@ -18,9 +18,8 @@
"remote-receive-interval": 2000,
"remote-transmit-interval": 2000,
"status": "up",
- "transmit-interval": 2000,
"uptime": "*",
- "vrf": "default"
+ "transmit-interval": 2000
},
{
"detect-multiplier": 3,
@@ -41,9 +40,8 @@
"remote-receive-interval": 2000,
"remote-transmit-interval": 2000,
"status": "up",
- "transmit-interval": 2000,
"uptime": "*",
- "vrf": "default"
+ "transmit-interval": 2000
},
{
"detect-multiplier": 3,
@@ -64,8 +62,7 @@
"remote-receive-interval": 2000,
"remote-transmit-interval": 2000,
"status": "up",
- "transmit-interval": 2000,
"uptime": "*",
- "vrf": "default"
+ "transmit-interval": 2000
}
]
diff --git a/tests/topotests/bfd_topo3/r4/bfd-peers.json b/tests/topotests/bfd_topo3/r4/bfd-peers.json
index 5477f39120..2f41f25c58 100644
--- a/tests/topotests/bfd_topo3/r4/bfd-peers.json
+++ b/tests/topotests/bfd_topo3/r4/bfd-peers.json
@@ -18,9 +18,8 @@
"remote-receive-interval": 2000,
"remote-transmit-interval": 2000,
"status": "up",
- "transmit-interval": 2000,
"uptime": "*",
- "vrf": "default"
+ "transmit-interval": 2000
},
{
"detect-multiplier": 3,
@@ -41,8 +40,7 @@
"remote-receive-interval": 2000,
"remote-transmit-interval": 2000,
"status": "up",
- "transmit-interval": 2000,
"uptime": "*",
- "vrf": "default"
+ "transmit-interval": 2000
}
]
diff --git a/tests/topotests/bgp_ecmp_topo1/peer1/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer1/exa-send.py
index d9ae3d1906..6bef35508f 100755
--- a/tests/topotests/bgp_ecmp_topo1/peer1/exa-send.py
+++ b/tests/topotests/bgp_ecmp_topo1/peer1/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_ecmp_topo1/peer10/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer10/exa-send.py
index d9ae3d1906..6bef35508f 100755
--- a/tests/topotests/bgp_ecmp_topo1/peer10/exa-send.py
+++ b/tests/topotests/bgp_ecmp_topo1/peer10/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_ecmp_topo1/peer11/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer11/exa-send.py
index d9ae3d1906..6bef35508f 100755
--- a/tests/topotests/bgp_ecmp_topo1/peer11/exa-send.py
+++ b/tests/topotests/bgp_ecmp_topo1/peer11/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_ecmp_topo1/peer12/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer12/exa-send.py
index d9ae3d1906..6bef35508f 100755
--- a/tests/topotests/bgp_ecmp_topo1/peer12/exa-send.py
+++ b/tests/topotests/bgp_ecmp_topo1/peer12/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_ecmp_topo1/peer13/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer13/exa-send.py
index d9ae3d1906..6bef35508f 100755
--- a/tests/topotests/bgp_ecmp_topo1/peer13/exa-send.py
+++ b/tests/topotests/bgp_ecmp_topo1/peer13/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_ecmp_topo1/peer14/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer14/exa-send.py
index d9ae3d1906..6bef35508f 100755
--- a/tests/topotests/bgp_ecmp_topo1/peer14/exa-send.py
+++ b/tests/topotests/bgp_ecmp_topo1/peer14/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_ecmp_topo1/peer15/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer15/exa-send.py
index d9ae3d1906..6bef35508f 100755
--- a/tests/topotests/bgp_ecmp_topo1/peer15/exa-send.py
+++ b/tests/topotests/bgp_ecmp_topo1/peer15/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_ecmp_topo1/peer16/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer16/exa-send.py
index d9ae3d1906..6bef35508f 100755
--- a/tests/topotests/bgp_ecmp_topo1/peer16/exa-send.py
+++ b/tests/topotests/bgp_ecmp_topo1/peer16/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_ecmp_topo1/peer17/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer17/exa-send.py
index d9ae3d1906..6bef35508f 100755
--- a/tests/topotests/bgp_ecmp_topo1/peer17/exa-send.py
+++ b/tests/topotests/bgp_ecmp_topo1/peer17/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_ecmp_topo1/peer18/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer18/exa-send.py
index d9ae3d1906..6bef35508f 100755
--- a/tests/topotests/bgp_ecmp_topo1/peer18/exa-send.py
+++ b/tests/topotests/bgp_ecmp_topo1/peer18/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_ecmp_topo1/peer19/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer19/exa-send.py
index d9ae3d1906..6bef35508f 100755
--- a/tests/topotests/bgp_ecmp_topo1/peer19/exa-send.py
+++ b/tests/topotests/bgp_ecmp_topo1/peer19/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_ecmp_topo1/peer2/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer2/exa-send.py
index d9ae3d1906..6bef35508f 100755
--- a/tests/topotests/bgp_ecmp_topo1/peer2/exa-send.py
+++ b/tests/topotests/bgp_ecmp_topo1/peer2/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_ecmp_topo1/peer20/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer20/exa-send.py
index d9ae3d1906..6bef35508f 100755
--- a/tests/topotests/bgp_ecmp_topo1/peer20/exa-send.py
+++ b/tests/topotests/bgp_ecmp_topo1/peer20/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_ecmp_topo1/peer3/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer3/exa-send.py
index d9ae3d1906..6bef35508f 100755
--- a/tests/topotests/bgp_ecmp_topo1/peer3/exa-send.py
+++ b/tests/topotests/bgp_ecmp_topo1/peer3/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_ecmp_topo1/peer4/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer4/exa-send.py
index d9ae3d1906..6bef35508f 100755
--- a/tests/topotests/bgp_ecmp_topo1/peer4/exa-send.py
+++ b/tests/topotests/bgp_ecmp_topo1/peer4/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_ecmp_topo1/peer5/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer5/exa-send.py
index d9ae3d1906..6bef35508f 100755
--- a/tests/topotests/bgp_ecmp_topo1/peer5/exa-send.py
+++ b/tests/topotests/bgp_ecmp_topo1/peer5/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_ecmp_topo1/peer6/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer6/exa-send.py
index d9ae3d1906..6bef35508f 100755
--- a/tests/topotests/bgp_ecmp_topo1/peer6/exa-send.py
+++ b/tests/topotests/bgp_ecmp_topo1/peer6/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_ecmp_topo1/peer7/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer7/exa-send.py
index d9ae3d1906..6bef35508f 100755
--- a/tests/topotests/bgp_ecmp_topo1/peer7/exa-send.py
+++ b/tests/topotests/bgp_ecmp_topo1/peer7/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_ecmp_topo1/peer8/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer8/exa-send.py
index d9ae3d1906..6bef35508f 100755
--- a/tests/topotests/bgp_ecmp_topo1/peer8/exa-send.py
+++ b/tests/topotests/bgp_ecmp_topo1/peer8/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_ecmp_topo1/peer9/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer9/exa-send.py
index d9ae3d1906..6bef35508f 100755
--- a/tests/topotests/bgp_ecmp_topo1/peer9/exa-send.py
+++ b/tests/topotests/bgp_ecmp_topo1/peer9/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_ecmp_topo1/r1/summary.txt b/tests/topotests/bgp_ecmp_topo1/r1/summary.txt
index f0929536d3..68de28a35b 100644
--- a/tests/topotests/bgp_ecmp_topo1/r1/summary.txt
+++ b/tests/topotests/bgp_ecmp_topo1/r1/summary.txt
@@ -2,7 +2,7 @@
"ipv4Unicast":{
"routerId":"10.0.255.1",
"as":100,
- "vrfName":"Default",
+ "vrfName":"default",
"peerCount":20,
"peers":{
"10.0.1.101":{
diff --git a/tests/topotests/bgp_ecmp_topo1/r1/summary20.txt b/tests/topotests/bgp_ecmp_topo1/r1/summary20.txt
index 9015f485f8..4895cdbecf 100644
--- a/tests/topotests/bgp_ecmp_topo1/r1/summary20.txt
+++ b/tests/topotests/bgp_ecmp_topo1/r1/summary20.txt
@@ -1,7 +1,7 @@
{
"routerId":"10.0.255.1",
"as":100,
- "vrfName":"Default",
+ "vrfName":"default",
"peerCount":20,
"peers":{
"10.0.1.101":{
diff --git a/tests/topotests/bgp_ecmp_topo1/test_bgp_ecmp_topo1.py b/tests/topotests/bgp_ecmp_topo1/test_bgp_ecmp_topo1.py
index 7b9ef0a505..96e4bf6ed3 100644
--- a/tests/topotests/bgp_ecmp_topo1/test_bgp_ecmp_topo1.py
+++ b/tests/topotests/bgp_ecmp_topo1/test_bgp_ecmp_topo1.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
#
# test_bgp_ecmp_topo1.py
@@ -140,12 +140,6 @@ def test_bgp_convergence():
with 'json') and compare with `data` contents.
"""
output = router.vtysh_cmd(cmd, isjson=True)
- if "ipv4Unicast" in output:
- output["ipv4Unicast"]["vrfName"] = output["ipv4Unicast"]["vrfName"].replace(
- "default", "Default"
- )
- elif "vrfName" in output:
- output["vrfName"] = output["vrfName"].replace("default", "Default")
return topotest.json_cmp(output, data)
test_func = functools.partial(
diff --git a/tests/topotests/bgp_evpn_rt5/test_bgp_evpn.py b/tests/topotests/bgp_evpn_rt5/test_bgp_evpn.py
index 6ea281e6f0..3e2fb2b6e0 100644
--- a/tests/topotests/bgp_evpn_rt5/test_bgp_evpn.py
+++ b/tests/topotests/bgp_evpn_rt5/test_bgp_evpn.py
@@ -148,7 +148,7 @@ def setup_module(mod):
router.load_config(
TopoRouter.RD_ZEBRA,
os.path.join(CWD, "{}/zebra.conf".format(rname)),
- "--vrfwnetns -o vrf0",
+ "--vrfwnetns",
)
else:
router.load_config(
diff --git a/tests/topotests/bgp_extended_optional_parameters_length/__init__.py b/tests/topotests/bgp_extended_optional_parameters_length/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bgp_extended_optional_parameters_length/__init__.py
diff --git a/tests/topotests/bgp_extended_optional_parameters_length/r1/bgpd.conf b/tests/topotests/bgp_extended_optional_parameters_length/r1/bgpd.conf
new file mode 100644
index 0000000000..d83013ca99
--- /dev/null
+++ b/tests/topotests/bgp_extended_optional_parameters_length/r1/bgpd.conf
@@ -0,0 +1,6 @@
+!
+router bgp 65001
+ no bgp ebgp-requires-policy
+ neighbor 192.168.1.2 remote-as external
+ neighbor 192.168.1.2 extended-optional-parameters
+!
diff --git a/tests/topotests/bgp_extended_optional_parameters_length/r1/zebra.conf b/tests/topotests/bgp_extended_optional_parameters_length/r1/zebra.conf
new file mode 100644
index 0000000000..b29940f46a
--- /dev/null
+++ b/tests/topotests/bgp_extended_optional_parameters_length/r1/zebra.conf
@@ -0,0 +1,4 @@
+!
+int r1-eth0
+ ip address 192.168.1.1/24
+!
diff --git a/tests/topotests/bgp_extended_optional_parameters_length/r2/bgpd.conf b/tests/topotests/bgp_extended_optional_parameters_length/r2/bgpd.conf
new file mode 100644
index 0000000000..e390d6ed8d
--- /dev/null
+++ b/tests/topotests/bgp_extended_optional_parameters_length/r2/bgpd.conf
@@ -0,0 +1,8 @@
+router bgp 65002
+ no bgp ebgp-requires-policy
+ neighbor 192.168.1.1 remote-as external
+ neighbor 192.168.1.1 extended-optional-parameters
+ address-family ipv4 unicast
+ redistribute connected
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_extended_optional_parameters_length/r2/zebra.conf b/tests/topotests/bgp_extended_optional_parameters_length/r2/zebra.conf
new file mode 100644
index 0000000000..dc15cf756a
--- /dev/null
+++ b/tests/topotests/bgp_extended_optional_parameters_length/r2/zebra.conf
@@ -0,0 +1,7 @@
+!
+int lo
+ ip address 172.16.16.1/32
+!
+int r2-eth0
+ ip address 192.168.1.2/24
+!
diff --git a/tests/topotests/bgp_extended_optional_parameters_length/test_bgp_extended_optional_parameters_length.py b/tests/topotests/bgp_extended_optional_parameters_length/test_bgp_extended_optional_parameters_length.py
new file mode 100644
index 0000000000..e677dc6ff6
--- /dev/null
+++ b/tests/topotests/bgp_extended_optional_parameters_length/test_bgp_extended_optional_parameters_length.py
@@ -0,0 +1,106 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2021 by
+# Donatas Abraitis <donatas.abraitis@gmail.com>
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+Test if Extended Optional Parameters Length encoding format works
+if forced with a knob.
+https://datatracker.ietf.org/doc/html/rfc9072
+"""
+
+import os
+import sys
+import json
+import pytest
+import functools
+
+pytestmark = pytest.mark.bgpd
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+
+pytestmark = [pytest.mark.bgpd]
+
+
+def setup_module(mod):
+ topodef = {"s1": ("r1", "r2")}
+ tgen = Topogen(topodef, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ for i, (rname, router) in enumerate(router_list.items(), 1):
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
+ )
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_extended_optional_parameters_length():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router = tgen.gears["r1"]
+
+ def _bgp_converge(router):
+ output = json.loads(router.vtysh_cmd("show bgp ipv4 unicast summary json"))
+ expected = {
+ "peers": {
+ "192.168.1.2": {
+ "pfxRcd": 2,
+ "pfxSnt": 2,
+ "state": "Established",
+ "peerState": "OK",
+ }
+ }
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_converge, router)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Can't converge with extended-optional-parameters"
+
+ def _bgp_extended_optional_parameters_length(router):
+ output = json.loads(router.vtysh_cmd("show bgp neighbor 192.168.1.2 json"))
+ expected = {"192.168.1.2": {"extendedOptionalParametersLength": True}}
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_extended_optional_parameters_length, router)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Can't see Extended Optional Parameters Length to be used"
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-1.py b/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-1.py
new file mode 100644
index 0000000000..290bf16fea
--- /dev/null
+++ b/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-1.py
@@ -0,0 +1,1542 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2019 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 Gracefull Restart functionality.
+Basic Common Test steps for all the test case below :
+- Create topology (setup module)
+ Creating 2 routers topology, r1, r2 in IBGP
+- Bring up topology
+- Verify for bgp to converge
+- Configure BGP Garceful Restart on both the routers.
+
+1. Transition from Peer-level helper to Global Restarting
+2. Transition from Peer-level helper to Global inherit helper
+3. Transition from Peer-level restarting to Global inherit helper
+4. Default GR functional mode is Helper.
+5. Verify that the restarting node sets "R" bit while sending the
+ BGP open messages after the node restart, only if GR is enabled.
+6. Verify if restarting node resets R bit in BGP open message
+ during normal BGP session flaps as well, even when GR restarting
+ mode is enabled. Here link flap happen due to interface UP/DOWN.
+7. Verify if restarting node resets R bit in BGP
+ open message during normal BGP session flaps when GR is disabled.
+8. Verify that restarting nodes set "F" bit while sending
+ the BGP open messages after it restarts, only when BGP GR is enabled.
+9. Verify that only GR helper routers keep the stale
+ route entries, not any GR disabled router.
+10. Verify that GR helper routers keeps all the routes received
+ from restarting node if both the routers are configured as
+ GR restarting node.
+11. Verify that GR helper routers delete all the routes
+ received from a node if both the routers are configured as GR
+ helper node.
+12. After BGP neighborship is established and GR capability is exchanged,
+ transition restarting router to disabled state and vice versa.
+13. After BGP neighborship is established and GR capability is exchanged,
+ transition restarting router to disabled state and vice versa.
+14. Verify that restarting nodes reset "F" bit while sending
+ the BGP open messages after it's restarts, when BGP GR is **NOT** enabled.
+15. Verify that only GR helper routers keep the stale
+ route entries, not any GR disabled router.
+16. Transition from Global Restarting to Disable and then Global
+ Disable to Restarting.
+17. Transition from Global Helper to Disable and then Global
+ Disable to Helper.
+18. Transition from Global Restart to Helper and then Global
+ Helper to Restart, Global Mode : GR Restarting
+ PerPeer Mode : GR Helper
+ GR Mode effective : GR Helper
+19. Transition from Peer-level helper to Global Restarting,
+ Global Mode : GR Restarting
+ PerPeer Mode : GR Restarting
+ GR Mode effective : GR Restarting
+20. Transition from Peer-level restart to Global Restart
+ Global Mode : GR Restarting
+ PerPeer Mode : GR Restarting
+ GR Mode effective : GR Restarting
+21. Transition from Peer-level disabled to Global Restart
+ Global Mode : GR Restarting
+ PerPeer Mode : GR Disabled
+ GR Mode effective : GR Disabled
+22. Peer-level inherit from Global Restarting
+ Global Mode : GR Restart
+ PerPeer Mode : None
+ GR Mode effective : GR Restart
+23. Transition from Peer-level disbale to Global inherit helper
+ Global Mode : None
+ PerPeer Mode : GR Disable
+ GR Mode effective : GR Disable
+
+These tests have been broken up into 4 sub python scripts because
+the totality of this run was fairly significant.
+"""
+
+import os
+import sys
+import time
+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("../"))
+sys.path.append(os.path.join("../lib/"))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib.topogen import Topogen, get_topogen
+from lib.topolog import logger
+
+# Required to instantiate the topology builder class.
+
+# Import topoJson from lib, to create topology and initial configuration
+from lib.topojson import build_config_from_json
+from lib.bgp import (
+ clear_bgp,
+ verify_bgp_rib,
+ verify_graceful_restart,
+ create_router_bgp,
+ verify_r_bit,
+ verify_f_bit,
+ verify_bgp_convergence,
+ verify_bgp_convergence_from_running_config,
+)
+
+from lib.common_config import (
+ write_test_header,
+ reset_config_on_routers,
+ start_topology,
+ kill_router_daemons,
+ start_router_daemons,
+ verify_rib,
+ check_address_types,
+ write_test_footer,
+ check_router_status,
+ shutdown_bringup_interface,
+ step,
+ get_frr_ipv6_linklocal,
+ required_linux_kernel_version,
+)
+
+pytestmark = [pytest.mark.bgpd]
+
+
+# Global variables
+NEXT_HOP_IP = {"ipv4": "192.168.1.10", "ipv6": "fd00:0:0:1::10"}
+NEXT_HOP_IP_1 = {"ipv4": "192.168.0.1", "ipv6": "fd00::1"}
+NEXT_HOP_IP_2 = {"ipv4": "192.168.0.2", "ipv6": "fd00::2"}
+BGP_CONVERGENCE = False
+GR_RESTART_TIMER = 20
+PREFERRED_NEXT_HOP = "link_local"
+
+
+def setup_module(mod):
+ """
+ Sets up the pytest environment
+
+ * `mod`: module name
+ """
+
+ global ADDR_TYPES
+
+ # Required linux kernel version for this suite to run.
+ result = required_linux_kernel_version("4.16")
+ if result is not True:
+ pytest.skip("Kernel requirements are not met")
+
+ 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...
+ json_file = "{}/bgp_gr_topojson_topo1.json".format(CWD)
+ tgen = Topogen(json_file, mod.__name__)
+ global topo
+ topo = tgen.json_topo
+ # ... 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)
+
+ # 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
+ ADDR_TYPES = check_address_types()
+
+ 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)
+
+
+def configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut, peer):
+ """
+ This function groups the repetitive function calls into one function.
+ """
+
+ result = create_router_bgp(tgen, topo, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ neighbor = topo["routers"][peer]["links"]["r1-link1"][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, dut, neighbor=neighbor)
+
+ for addr_type in ADDR_TYPES:
+ neighbor = topo["routers"][dut]["links"]["r2-link1"][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, peer, neighbor=neighbor)
+
+ result = verify_bgp_convergence_from_running_config(tgen)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ return True
+
+
+def next_hop_per_address_family(
+ tgen, dut, peer, addr_type, next_hop_dict, preferred_next_hop=PREFERRED_NEXT_HOP
+):
+ """
+ This function returns link_local or global next_hop per address-family
+ """
+
+ intferface = topo["routers"][peer]["links"]["{}-link1".format(dut)]["interface"]
+ if addr_type == "ipv6" and "link_local" in preferred_next_hop:
+ next_hop = get_frr_ipv6_linklocal(tgen, peer, intf=intferface)
+ else:
+ next_hop = next_hop_dict[addr_type]
+
+ return next_hop
+
+
+def BGP_GR_TC_50_p1(request):
+ """
+ Test Objective : Transition from Peer-level helper to Global inherit helper
+ Global Mode : None
+ PerPeer Mode : Helper
+ GR Mode effective : GR Helper
+
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ step(
+ "Configure R1 as GR helper node at per Peer-level for R2"
+ " and configure R2 as global restarting node."
+ )
+
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ step("Verify on R2 that R1 advertises GR capabilities as a helper node")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ next_hop = next_hop_per_address_family(
+ tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Kill BGP on R2")
+
+ kill_router_daemons(tgen, "r2", ["bgpd"])
+
+ step(
+ "Verify that R2 keeps the stale entries in FIB & R1 keeps stale entries in RIB & FIB"
+ )
+
+ for addr_type in ADDR_TYPES:
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ next_hop = next_hop_per_address_family(
+ tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Bring up BGP on R2 and remove Peer-level GR config from R1 ")
+
+ start_router_daemons(tgen, "r2", ["bgpd"])
+
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-helper": False}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-helper": False}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ neighbor = topo["routers"]["r2"]["links"]["r1-link1"][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, "r1", neighbor=neighbor)
+
+ result = verify_bgp_convergence_from_running_config(tgen)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify on R2 that R1 still advertises GR capabilities as a helper node")
+
+ input_dict = {
+ "r1": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}},
+ "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
+ }
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ next_hop = next_hop_per_address_family(
+ tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Kill BGP on R2")
+
+ kill_router_daemons(tgen, "r2", ["bgpd"])
+
+ step(
+ "Verify that R2 keeps the stale entries in FIB & R1 keeps stale entries in RIB & FIB"
+ )
+
+ for addr_type in ADDR_TYPES:
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ next_hop = next_hop_per_address_family(
+ tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Start BGP on R2")
+
+ start_router_daemons(tgen, "r2", ["bgpd"])
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_TC_51_p1(request):
+ """
+ Test Objective : Transition from Peer-level restarting to Global inherit helper
+ Global Mode : None
+ PerPeer Mode : GR Restart
+ GR Mode effective : GR Restart
+
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ step("Configure R1 as GR restarting node at per Peer-level for R2")
+
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+ step("Verify on R2 that R1 advertises GR capabilities as a restarting node")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ next_hop = next_hop_per_address_family(
+ tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, "r2", input_topo, next_hop)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Kill BGP on R1")
+
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ step(
+ "Verify that R1 keeps the stale entries in FIB & R2 keeps stale entries in RIB & FIB"
+ )
+
+ for addr_type in ADDR_TYPES:
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ next_hop = next_hop_per_address_family(
+ tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, "r2", input_topo, next_hop)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Bring up BGP on R1 and remove Peer-level GR config")
+
+ start_router_daemons(tgen, "r1", ["bgpd"])
+
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart": False}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart": False}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ neighbor = topo["routers"]["r2"]["links"]["r1-link1"][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, "r1", neighbor=neighbor)
+
+ result = verify_bgp_convergence_from_running_config(tgen)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify on R2 that R1 advertises GR capabilities as a helper node")
+
+ input_dict = {
+ "r1": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}},
+ "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
+ }
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ next_hop = next_hop_per_address_family(
+ tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Kill BGPd on R2")
+
+ kill_router_daemons(tgen, "r2", ["bgpd"])
+
+ step(
+ "Verify that R2 keeps the stale entries in FIB & R1 keeps stale entries in RIB & FIB"
+ )
+
+ for addr_type in ADDR_TYPES:
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ next_hop = next_hop_per_address_family(
+ tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Start BGP on R2")
+
+ start_router_daemons(tgen, "r2", ["bgpd"])
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_TC_53_p1(request):
+ """
+ Test Objective : Default GR functional mode is Helper.
+ Global Mode : None
+ PerPeer Mode : None
+ GR Mode effective : GR Helper
+
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ step("configure R2 as global restarting node")
+
+ input_dict = {"r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}}}
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ step(
+ "Verify on R2 that R1 advertises GR capabilities as a helper node based on inherit"
+ )
+
+ input_dict = {
+ "r1": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}},
+ "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
+ }
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ next_hop = next_hop_per_address_family(
+ tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Kill BGPd on R2")
+
+ kill_router_daemons(tgen, "r2", ["bgpd"])
+
+ step(
+ "Verify that R2 keeps the stale entries in FIB & R1 keeps stale entries in RIB & FIB"
+ )
+
+ for addr_type in ADDR_TYPES:
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ next_hop = next_hop_per_address_family(
+ tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Start BGP on R2")
+
+ start_router_daemons(tgen, "r2", ["bgpd"])
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_TC_4_p0(request):
+ """
+ Test Objective : Verify that the restarting node sets "R" bit while sending the
+ BGP open messages after the node restart, only if GR is enabled.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ "[Phase 1] : Test Setup" " [Restart Mode]R1-----R2[Helper Mode] initialized "
+ )
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ "r2": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2-link1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2-link1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes
+ dut = "r1"
+ peer = "r2"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {key: topo["routers"][key] for key in ["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes
+ protocol = "bgp"
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info("[Phase 2] : R2 goes for reload ")
+
+ kill_router_daemons(tgen, "r2", ["bgpd"])
+
+ logger.info(
+ "[Phase 3] : R2 is still down, restart time {} sec."
+ "So time verify the routes are present in BGP RIB and ZEBRA ".format(
+ GR_RESTART_TIMER
+ )
+ )
+
+ for addr_type in ADDR_TYPES:
+ # Verifying BGP RIB routes
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {key: topo["routers"][key] for key in ["r2"]}
+ result = verify_bgp_rib(
+ tgen, addr_type, dut, input_topo, next_hop, expected=False
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r1: routes are still present in BGP RIB\n Error: {}".format(
+ tc_name, result
+ )
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ # Verifying RIB routes
+ result = verify_rib(
+ tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ logger.info("[Phase 5] : R2 is about to come up now ")
+ start_router_daemons(tgen, "r2", ["bgpd"])
+
+ logger.info("[Phase 4] : R2 is UP now, so time to collect GR stats ")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_r_bit(tgen, topo, addr_type, input_dict, dut="r1", peer="r2")
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {key: topo["routers"][key] for key in ["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_TC_5_1_2_p1(request):
+ """
+ Test Objective : Verify if restarting node resets R bit in BGP open message
+ during normal BGP session flaps as well, even when GR restarting mode is enabled.
+ Here link flap happen due to interface UP/DOWN.
+
+ """
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ "[Phase 1] : Test Setup" " [Restart Mode]R1-----R2[Restart Mode] initialized "
+ )
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ "r2": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2-link1": {"graceful-restart": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2-link1": {"graceful-restart": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes
+ dut = "r1"
+ peer = "r2"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {key: topo["routers"][key] for key in ["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes
+ protocol = "bgp"
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info("[Phase 2] : Now flap the link running the BGP session ")
+ # Shutdown interface
+ intf = "r2-r1-eth0"
+ shutdown_bringup_interface(tgen, "r2", intf)
+
+ # Bring up Interface
+ shutdown_bringup_interface(tgen, "r2", intf, ifaceaction=True)
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_r_bit(tgen, topo, addr_type, input_dict, dut="r1", peer="r2")
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info("[Phase 2] : Restart BGPd on router R2. ")
+ kill_router_daemons(tgen, "r2", ["bgpd"])
+
+ start_router_daemons(tgen, "r2", ["bgpd"])
+
+ logger.info("[Phase 4] : R2 is UP now, so time to collect GR stats ")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_r_bit(tgen, topo, addr_type, input_dict, dut="r1", peer="r2")
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {key: topo["routers"][key] for key in ["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_TC_6_1_2_p1(request):
+ """
+ Test Objective : Verify if restarting node resets R bit in BGP
+ open message during normal BGP session flaps when GR is disabled.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ "[Phase 1] : Test Setup" "[Restart Mode]R1-----R2[Helper Mode] initialized "
+ )
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ "r2": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2-link1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2-link1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes
+ dut = "r1"
+ peer = "r2"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {key: topo["routers"][key] for key in ["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes
+ protocol = "bgp"
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info("[Phase 1] : Changing mode" "[Disable Mode]R1-----R2[Helper Mode]")
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-disable": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-disable": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ neighbor = topo["routers"]["r2"]["links"]["r1-link1"][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, "r1", neighbor=neighbor)
+
+ result = verify_bgp_convergence_from_running_config(tgen)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ # Verify GR stats
+ input_dict = {
+ "r2": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2-link1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2-link1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-disable": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-disable": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ # here the verify_graceful_restart fro the neighbor would be
+ # "NotReceived" as the latest GR config is not yet applied.
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info("[Phase 2] : Now flap the link running the BGP session ")
+ # Shutdown interface
+ intf = "r2-r1-eth0"
+ shutdown_bringup_interface(tgen, "r2", intf)
+
+ # Bring up Interface
+ shutdown_bringup_interface(tgen, "r2", intf, ifaceaction=True)
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_r_bit(
+ tgen, topo, addr_type, input_dict, dut="r2", peer="r1", expected=False
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r2: R-bit is set to True\n Error: {}".format(
+ tc_name, result
+ )
+
+ logger.info("Restart BGPd on R2 ")
+ kill_router_daemons(tgen, "r2", ["bgpd"])
+
+ start_router_daemons(tgen, "r2", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_r_bit(
+ tgen, topo, addr_type, input_dict, dut="r2", peer="r1", expected=False
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r2: R-bit is set to True\n Error: {}".format(
+ 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_gr_functionality_topo1/test_bgp_gr_functionality_topo1-2.py b/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-2.py
new file mode 100644
index 0000000000..0647ad5d06
--- /dev/null
+++ b/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-2.py
@@ -0,0 +1,404 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2019 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 Gracefull Restart functionality.
+Basic Common Test steps for all the test case below :
+- Create topology (setup module)
+ Creating 2 routers topology, r1, r2 in IBGP
+- Bring up topology
+- Verify for bgp to converge
+- Configure BGP Garceful Restart on both the routers.
+
+1. Transition from Peer-level helper to Global Restarting
+2. Transition from Peer-level helper to Global inherit helper
+3. Transition from Peer-level restarting to Global inherit helper
+4. Default GR functional mode is Helper.
+5. Verify that the restarting node sets "R" bit while sending the
+ BGP open messages after the node restart, only if GR is enabled.
+6. Verify if restarting node resets R bit in BGP open message
+ during normal BGP session flaps as well, even when GR restarting
+ mode is enabled. Here link flap happen due to interface UP/DOWN.
+7. Verify if restarting node resets R bit in BGP
+ open message during normal BGP session flaps when GR is disabled.
+8. Verify that restarting nodes set "F" bit while sending
+ the BGP open messages after it restarts, only when BGP GR is enabled.
+9. Verify that only GR helper routers keep the stale
+ route entries, not any GR disabled router.
+10. Verify that GR helper routers keeps all the routes received
+ from restarting node if both the routers are configured as
+ GR restarting node.
+11. Verify that GR helper routers delete all the routes
+ received from a node if both the routers are configured as GR
+ helper node.
+12. After BGP neighborship is established and GR capability is exchanged,
+ transition restarting router to disabled state and vice versa.
+13. After BGP neighborship is established and GR capability is exchanged,
+ transition restarting router to disabled state and vice versa.
+14. Verify that restarting nodes reset "F" bit while sending
+ the BGP open messages after it's restarts, when BGP GR is **NOT** enabled.
+15. Verify that only GR helper routers keep the stale
+ route entries, not any GR disabled router.
+16. Transition from Global Restarting to Disable and then Global
+ Disable to Restarting.
+17. Transition from Global Helper to Disable and then Global
+ Disable to Helper.
+18. Transition from Global Restart to Helper and then Global
+ Helper to Restart, Global Mode : GR Restarting
+ PerPeer Mode : GR Helper
+ GR Mode effective : GR Helper
+19. Transition from Peer-level helper to Global Restarting,
+ Global Mode : GR Restarting
+ PerPeer Mode : GR Restarting
+ GR Mode effective : GR Restarting
+20. Transition from Peer-level restart to Global Restart
+ Global Mode : GR Restarting
+ PerPeer Mode : GR Restarting
+ GR Mode effective : GR Restarting
+21. Transition from Peer-level disabled to Global Restart
+ Global Mode : GR Restarting
+ PerPeer Mode : GR Disabled
+ GR Mode effective : GR Disabled
+22. Peer-level inherit from Global Restarting
+ Global Mode : GR Restart
+ PerPeer Mode : None
+ GR Mode effective : GR Restart
+23. Transition from Peer-level disbale to Global inherit helper
+ Global Mode : None
+ PerPeer Mode : GR Disable
+ GR Mode effective : GR Disable
+
+These tests have been broken up into 4 sub python scripts because
+the totality of this run was fairly significant.
+"""
+
+import os
+import sys
+import time
+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("../"))
+sys.path.append(os.path.join("../lib/"))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib.topogen import Topogen, get_topogen
+from lib.topolog import logger
+
+# Required to instantiate the topology builder class.
+
+# Import topoJson from lib, to create topology and initial configuration
+from lib.topojson import build_config_from_json
+from lib.bgp import (
+ clear_bgp,
+ verify_bgp_rib,
+ verify_graceful_restart,
+ create_router_bgp,
+ verify_r_bit,
+ verify_f_bit,
+ verify_bgp_convergence,
+ verify_bgp_convergence_from_running_config,
+)
+
+from lib.common_config import (
+ write_test_header,
+ reset_config_on_routers,
+ start_topology,
+ kill_router_daemons,
+ start_router_daemons,
+ verify_rib,
+ check_address_types,
+ write_test_footer,
+ check_router_status,
+ shutdown_bringup_interface,
+ step,
+ get_frr_ipv6_linklocal,
+ required_linux_kernel_version,
+)
+
+pytestmark = [pytest.mark.bgpd]
+
+
+# Global variables
+NEXT_HOP_IP = {"ipv4": "192.168.1.10", "ipv6": "fd00:0:0:1::10"}
+NEXT_HOP_IP_1 = {"ipv4": "192.168.0.1", "ipv6": "fd00::1"}
+NEXT_HOP_IP_2 = {"ipv4": "192.168.0.2", "ipv6": "fd00::2"}
+BGP_CONVERGENCE = False
+GR_RESTART_TIMER = 20
+PREFERRED_NEXT_HOP = "link_local"
+
+
+def setup_module(mod):
+ """
+ Sets up the pytest environment
+
+ * `mod`: module name
+ """
+
+ global ADDR_TYPES
+
+ # Required linux kernel version for this suite to run.
+ result = required_linux_kernel_version("4.16")
+ if result is not True:
+ pytest.skip("Kernel requirements are not met")
+
+ 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...
+ json_file = "{}/bgp_gr_topojson_topo1.json".format(CWD)
+ tgen = Topogen(json_file, mod.__name__)
+ global topo
+ topo = tgen.json_topo
+ # ... 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)
+
+ # 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
+ ADDR_TYPES = check_address_types()
+
+ 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)
+
+
+def configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut, peer):
+ """
+ This function groups the repetitive function calls into one function.
+ """
+
+ result = create_router_bgp(tgen, topo, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ neighbor = topo["routers"][peer]["links"]["r1-link1"][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, dut, neighbor=neighbor)
+
+ for addr_type in ADDR_TYPES:
+ neighbor = topo["routers"][dut]["links"]["r2-link1"][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, peer, neighbor=neighbor)
+
+ result = verify_bgp_convergence_from_running_config(tgen)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ return True
+
+
+def next_hop_per_address_family(
+ tgen, dut, peer, addr_type, next_hop_dict, preferred_next_hop=PREFERRED_NEXT_HOP
+):
+ """
+ This function returns link_local or global next_hop per address-family
+ """
+
+ intferface = topo["routers"][peer]["links"]["{}-link1".format(dut)]["interface"]
+ if addr_type == "ipv6" and "link_local" in preferred_next_hop:
+ next_hop = get_frr_ipv6_linklocal(tgen, peer, intf=intferface)
+ else:
+ next_hop = next_hop_dict[addr_type]
+
+ return next_hop
+
+
+def test_BGP_GR_TC_8_p1(request):
+ """
+ Test Objective : Verify that restarting nodes set "F" bit while sending
+ the BGP open messages after it restarts, only when BGP GR is enabled.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ "[Phase 1] : Test Setup" " [Restart Mode]R1-----R2[Restart Mode] initialized "
+ )
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "graceful-restart": {"preserve-fw-state": True},
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart": True}
+ }
+ }
+ }
+ }
+ },
+ },
+ }
+ },
+ "r2": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2-link1": {"graceful-restart": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2-link1": {"graceful-restart": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes
+ dut = "r1"
+ peer = "r2"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {key: topo["routers"][key] for key in ["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes
+ protocol = "bgp"
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info("[Phase 2] : R1 goes for reload ")
+
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ logger.info("[Phase 3] : R1 is about to come up now ")
+ start_router_daemons(tgen, "r1", ["bgpd"])
+
+ logger.info("[Phase 4] : R2 is UP now, so time to collect GR stats ")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_r_bit(tgen, topo, addr_type, input_dict, dut="r2", peer="r1")
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_f_bit(tgen, topo, addr_type, input_dict, dut="r2", peer="r1")
+ 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_gr_functionality_topo1/test_bgp_gr_functionality_topo1.py b/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-3.py
index 56f6e1a3be..0c3ff6451e 100644
--- a/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1.py
+++ b/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-3.py
@@ -85,6 +85,9 @@ Basic Common Test steps for all the test case below :
Global Mode : None
PerPeer Mode : GR Disable
GR Mode effective : GR Disable
+
+These tests have been broken up into 4 sub python scripts because
+the totality of this run was fairly significant.
"""
import os
@@ -519,1165 +522,6 @@ def BGP_GR_TC_50_p1(request):
write_test_footer(tc_name)
-def test_BGP_GR_TC_51_p1(request):
- """
- Test Objective : Transition from Peer-level restarting to Global inherit helper
- Global Mode : None
- PerPeer Mode : GR Restart
- GR Mode effective : GR Restart
-
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- step("Configure R1 as GR restarting node at per Peer-level for R2")
-
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart": True}
- }
- }
- }
- }
- },
- }
- }
- },
- "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
- step("Verify on R2 that R1 advertises GR capabilities as a restarting node")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- for addr_type in ADDR_TYPES:
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- for addr_type in ADDR_TYPES:
- next_hop = next_hop_per_address_family(
- tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_bgp_rib(tgen, addr_type, "r2", input_topo, next_hop)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- step("Kill BGP on R1")
-
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- step(
- "Verify that R1 keeps the stale entries in FIB & R2 keeps stale entries in RIB & FIB"
- )
-
- for addr_type in ADDR_TYPES:
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- for addr_type in ADDR_TYPES:
- next_hop = next_hop_per_address_family(
- tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_bgp_rib(tgen, addr_type, "r2", input_topo, next_hop)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- step("Bring up BGP on R1 and remove Peer-level GR config")
-
- start_router_daemons(tgen, "r1", ["bgpd"])
-
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart": False}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart": False}
- }
- }
- }
- }
- },
- }
- }
- }
- }
-
- result = create_router_bgp(tgen, topo, input_dict)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
-
- for addr_type in ADDR_TYPES:
- neighbor = topo["routers"]["r2"]["links"]["r1-link1"][addr_type].split("/")[0]
- clear_bgp(tgen, addr_type, "r1", neighbor=neighbor)
-
- result = verify_bgp_convergence_from_running_config(tgen)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
-
- step("Verify on R2 that R1 advertises GR capabilities as a helper node")
-
- input_dict = {
- "r1": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}},
- "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
- }
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- for addr_type in ADDR_TYPES:
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
- assert (
- result is True
- ), "Testcase {} : Failed \n Routes are still present \n Error {}".format(
- tc_name, result
- )
-
- for addr_type in ADDR_TYPES:
- next_hop = next_hop_per_address_family(
- tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
- assert (
- result is True
- ), "Testcase {} : Failed \n Routes are still present \n Error {}".format(
- tc_name, result
- )
-
- step("Kill BGPd on R2")
-
- kill_router_daemons(tgen, "r2", ["bgpd"])
-
- step(
- "Verify that R2 keeps the stale entries in FIB & R1 keeps stale entries in RIB & FIB"
- )
-
- for addr_type in ADDR_TYPES:
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
- assert (
- result is True
- ), "Testcase {} : Failed \n Routes are still present \n Error {}".format(
- tc_name, result
- )
-
- for addr_type in ADDR_TYPES:
- next_hop = next_hop_per_address_family(
- tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
- assert (
- result is True
- ), "Testcase {} : Failed \n Routes are still present \n Error {}".format(
- tc_name, result
- )
-
- step("Start BGP on R2")
-
- start_router_daemons(tgen, "r2", ["bgpd"])
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_TC_53_p1(request):
- """
- Test Objective : Default GR functional mode is Helper.
- Global Mode : None
- PerPeer Mode : None
- GR Mode effective : GR Helper
-
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- step("configure R2 as global restarting node")
-
- input_dict = {"r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}}}
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- step(
- "Verify on R2 that R1 advertises GR capabilities as a helper node based on inherit"
- )
-
- input_dict = {
- "r1": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}},
- "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
- }
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- for addr_type in ADDR_TYPES:
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- for addr_type in ADDR_TYPES:
- next_hop = next_hop_per_address_family(
- tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- step("Kill BGPd on R2")
-
- kill_router_daemons(tgen, "r2", ["bgpd"])
-
- step(
- "Verify that R2 keeps the stale entries in FIB & R1 keeps stale entries in RIB & FIB"
- )
-
- for addr_type in ADDR_TYPES:
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- for addr_type in ADDR_TYPES:
- next_hop = next_hop_per_address_family(
- tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- step("Start BGP on R2")
-
- start_router_daemons(tgen, "r2", ["bgpd"])
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_TC_4_p0(request):
- """
- Test Objective : Verify that the restarting node sets "R" bit while sending the
- BGP open messages after the node restart, only if GR is enabled.
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- "[Phase 1] : Test Setup" " [Restart Mode]R1-----R2[Helper Mode] initialized "
- )
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart": True}
- }
- }
- }
- }
- },
- }
- }
- },
- "r2": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r2-link1": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r2-link1": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes
- dut = "r1"
- peer = "r2"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes
- protocol = "bgp"
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info("[Phase 2] : R2 goes for reload ")
-
- kill_router_daemons(tgen, "r2", ["bgpd"])
-
- logger.info(
- "[Phase 3] : R2 is still down, restart time {} sec."
- "So time verify the routes are present in BGP RIB and ZEBRA ".format(
- GR_RESTART_TIMER
- )
- )
-
- for addr_type in ADDR_TYPES:
- # Verifying BGP RIB routes
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_bgp_rib(
- tgen, addr_type, dut, input_topo, next_hop, expected=False
- )
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r1: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
- )
- logger.info(" Expected behavior: {}".format(result))
-
- # Verifying RIB routes
- result = verify_rib(
- tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
- )
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
- )
- logger.info(" Expected behavior: {}".format(result))
-
- logger.info("[Phase 5] : R2 is about to come up now ")
- start_router_daemons(tgen, "r2", ["bgpd"])
-
- logger.info("[Phase 4] : R2 is UP now, so time to collect GR stats ")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_r_bit(tgen, topo, addr_type, input_dict, dut="r1", peer="r2")
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_TC_5_1_2_p1(request):
- """
- Test Objective : Verify if restarting node resets R bit in BGP open message
- during normal BGP session flaps as well, even when GR restarting mode is enabled.
- Here link flap happen due to interface UP/DOWN.
-
- """
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- "[Phase 1] : Test Setup" " [Restart Mode]R1-----R2[Restart Mode] initialized "
- )
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart": True}
- }
- }
- }
- }
- },
- }
- }
- },
- "r2": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r2-link1": {"graceful-restart": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r2-link1": {"graceful-restart": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes
- dut = "r1"
- peer = "r2"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes
- protocol = "bgp"
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info("[Phase 2] : Now flap the link running the BGP session ")
- # Shutdown interface
- intf = "r2-r1-eth0"
- shutdown_bringup_interface(tgen, "r2", intf)
-
- # Bring up Interface
- shutdown_bringup_interface(tgen, "r2", intf, ifaceaction=True)
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_r_bit(tgen, topo, addr_type, input_dict, dut="r1", peer="r2")
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info("[Phase 2] : Restart BGPd on router R2. ")
- kill_router_daemons(tgen, "r2", ["bgpd"])
-
- start_router_daemons(tgen, "r2", ["bgpd"])
-
- logger.info("[Phase 4] : R2 is UP now, so time to collect GR stats ")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_r_bit(tgen, topo, addr_type, input_dict, dut="r1", peer="r2")
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_TC_6_1_2_p1(request):
- """
- Test Objective : Verify if restarting node resets R bit in BGP
- open message during normal BGP session flaps when GR is disabled.
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- "[Phase 1] : Test Setup" "[Restart Mode]R1-----R2[Helper Mode] initialized "
- )
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart": True}
- }
- }
- }
- }
- },
- }
- }
- },
- "r2": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r2-link1": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r2-link1": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes
- dut = "r1"
- peer = "r2"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes
- protocol = "bgp"
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info("[Phase 1] : Changing mode" "[Disable Mode]R1-----R2[Helper Mode]")
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart-disable": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart-disable": True}
- }
- }
- }
- }
- },
- }
- }
- }
- }
-
- result = create_router_bgp(tgen, topo, input_dict)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
-
- for addr_type in ADDR_TYPES:
- neighbor = topo["routers"]["r2"]["links"]["r1-link1"][addr_type].split("/")[0]
- clear_bgp(tgen, addr_type, "r1", neighbor=neighbor)
-
- result = verify_bgp_convergence_from_running_config(tgen)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
-
- # Verify GR stats
- input_dict = {
- "r2": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r2-link1": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r2-link1": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart-disable": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart-disable": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- # here the verify_graceful_restart fro the neighbor would be
- # "NotReceived" as the latest GR config is not yet applied.
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info("[Phase 2] : Now flap the link running the BGP session ")
- # Shutdown interface
- intf = "r2-r1-eth0"
- shutdown_bringup_interface(tgen, "r2", intf)
-
- # Bring up Interface
- shutdown_bringup_interface(tgen, "r2", intf, ifaceaction=True)
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_r_bit(
- tgen, topo, addr_type, input_dict, dut="r2", peer="r1", expected=False
- )
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r2: R-bit is set to True\n Error: {}".format(
- tc_name, result
- )
-
- logger.info("Restart BGPd on R2 ")
- kill_router_daemons(tgen, "r2", ["bgpd"])
-
- start_router_daemons(tgen, "r2", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_r_bit(
- tgen, topo, addr_type, input_dict, dut="r2", peer="r1", expected=False
- )
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r2: R-bit is set to True\n Error: {}".format(
- tc_name, result
- )
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_TC_8_p1(request):
- """
- Test Objective : Verify that restarting nodes set "F" bit while sending
- the BGP open messages after it restarts, only when BGP GR is enabled.
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- "[Phase 1] : Test Setup" " [Restart Mode]R1-----R2[Restart Mode] initialized "
- )
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "graceful-restart": {"preserve-fw-state": True},
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart": True}
- }
- }
- }
- }
- },
- },
- }
- },
- "r2": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r2-link1": {"graceful-restart": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r2-link1": {"graceful-restart": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes
- dut = "r1"
- peer = "r2"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes
- protocol = "bgp"
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info("[Phase 2] : R1 goes for reload ")
-
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- logger.info("[Phase 3] : R1 is about to come up now ")
- start_router_daemons(tgen, "r1", ["bgpd"])
-
- logger.info("[Phase 4] : R2 is UP now, so time to collect GR stats ")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_r_bit(tgen, topo, addr_type, input_dict, dut="r2", peer="r1")
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_f_bit(tgen, topo, addr_type, input_dict, dut="r2", peer="r1")
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- write_test_footer(tc_name)
-
-
def test_BGP_GR_TC_19_p1(request):
"""
Test Objective : Verify that GR helper routers keeps all the routes received
@@ -3904,1165 +2748,6 @@ def test_BGP_GR_TC_45_p1(request):
write_test_footer(tc_name)
-def test_BGP_GR_TC_46_p1(request):
- """
- Test Objective : transition from Peer-level helper to Global Restarting
- Global Mode : GR Restarting
- PerPeer Mode : GR Helper
- GR Mode effective : GR Helper
-
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- step(
- "Configure R1 and R2 as GR restarting node in global"
- " and helper in per-Peer-level"
- )
-
- input_dict = {
- "r1": {
- "bgp": {
- "graceful-restart": {
- "graceful-restart": True,
- },
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- },
- }
- },
- "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- step("Verify on R2 that R1 advertises GR capabilities as a restarting node")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r2", peer="r1"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- for addr_type in ADDR_TYPES:
- dut = "r2"
- peer = "r1"
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- dut = "r1"
- peer = "r2"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- step("Kill BGP on R2")
-
- kill_router_daemons(tgen, "r2", ["bgpd"])
-
- step(
- "Verify that R1 keeps the stale entries in RIB & FIB and R2 keeps stale entries in FIB using"
- )
-
- for addr_type in ADDR_TYPES:
- dut = "r2"
- peer = "r1"
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- dut = "r1"
- peer = "r2"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- step(
- "Bring up BGP on R1 and remove Peer-level GR config"
- " from R1 following by a session reset"
- )
-
- start_router_daemons(tgen, "r2", ["bgpd"])
-
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart-helper": False}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart-helper": False}
- }
- }
- }
- }
- },
- }
- }
- }
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- step("Verify on R2 that R1 advertises GR capabilities as a restarting node")
-
- input_dict = {
- "r1": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
- "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
- }
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r2", peer="r1"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- for addr_type in ADDR_TYPES:
- dut = "r1"
- peer = "r2"
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert (
- result is True
- ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
- tc_name, result
- )
-
- dut = "r2"
- peer = "r1"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert (
- result is True
- ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
- tc_name, result
- )
-
- step("Kill BGP on R1")
-
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- step(
- "Verify that R1 keeps the stale entries in FIB command and R2 keeps stale entries in RIB & FIB"
- )
-
- for addr_type in ADDR_TYPES:
- dut = "r1"
- peer = "r2"
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert (
- result is True
- ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
- tc_name, result
- )
-
- dut = "r2"
- peer = "r1"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert (
- result is True
- ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
- tc_name, result
- )
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_TC_47_p1(request):
- """
- Test Objective : transition from Peer-level restart to Global Restart
- Global Mode : GR Restarting
- PerPeer Mode : GR Restarting
- GR Mode effective : GR Restarting
-
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- step("Configure R1 and R2 as GR restarting node in global and per-Peer-level")
-
- input_dict = {
- "r1": {
- "bgp": {
- "graceful-restart": {
- "graceful-restart": True,
- },
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart": True}
- }
- }
- }
- }
- },
- },
- }
- },
- "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- step("Verify on R2 that R1 advertises GR capabilities as a restarting node")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r2", peer="r1"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- for addr_type in ADDR_TYPES:
- dut = "r1"
- peer = "r2"
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- dut = "r2"
- peer = "r1"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- step("Kill BGP on R1")
-
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- step(
- "Verify that R1 keeps the stale entries in FIB and R2 keeps stale entries in RIB & FIB"
- )
-
- for addr_type in ADDR_TYPES:
- dut = "r1"
- peer = "r2"
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- dut = "r2"
- peer = "r1"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- step(
- "Bring up BGP on R1 and remove Peer-level GR"
- " config from R1 following by a session reset"
- )
-
- start_router_daemons(tgen, "r1", ["bgpd"])
-
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart": False}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart": False}
- }
- }
- }
- }
- },
- }
- }
- }
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- step("Verify on R2 that R1 still advertises GR capabilities as a restarting node")
-
- input_dict = {
- "r1": {
- "bgp": {
- "graceful-restart": {
- "graceful-restart": True,
- }
- }
- },
- "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
- }
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r2", peer="r1"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- for addr_type in ADDR_TYPES:
- dut = "r1"
- peer = "r2"
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert (
- result is True
- ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
- tc_name, result
- )
-
- dut = "r2"
- peer = "r1"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert (
- result is True
- ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
- tc_name, result
- )
-
- step("Kill BGP on R1")
-
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- step(
- "Verify that R1 keeps the stale entries in FIB and R2 keeps stale entries in RIB & FIB"
- )
-
- for addr_type in ADDR_TYPES:
- dut = "r1"
- peer = "r2"
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert (
- result is True
- ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
- tc_name, result
- )
-
- dut = "r2"
- peer = "r1"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert (
- result is True
- ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
- tc_name, result
- )
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_TC_48_p1(request):
- """
- Test Objective : transition from Peer-level disabled to Global Restart
- Global Mode : GR Restarting
- PerPeer Mode : GR Disabled
- GR Mode effective : GR Disabled
-
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- step(
- "Configure R1 as GR restarting node in global level and"
- " GR Disabled in per-Peer-level"
- )
-
- input_dict = {
- "r1": {
- "bgp": {
- "graceful-restart": {
- "graceful-restart": True,
- },
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart-disable": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart-disable": True}
- }
- }
- }
- }
- },
- },
- }
- },
- "r2": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}},
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- step("Verify on R2 that R1 does't advertise any GR capabilities")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r2", peer="r1"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- for addr_type in ADDR_TYPES:
- dut = "r1"
- peer = "r2"
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- dut = "r2"
- peer = "r1"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- step("Kill BGP on R1")
-
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- step("Verify on R2 and R1 that none of the routers keep stale entries")
-
- for addr_type in ADDR_TYPES:
- dut = "r1"
- peer = "r2"
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_rib(
- tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
- )
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
- )
-
- dut = "r2"
- peer = "r1"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_bgp_rib(
- tgen, addr_type, dut, input_topo, next_hop, expected=False
- )
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r2: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
- )
- result = verify_rib(
- tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
- )
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r2: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
- )
-
- step("Bring up BGP on R1 and remove Peer-level GR config from R1")
-
- start_router_daemons(tgen, "r1", ["bgpd"])
-
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart-disable": False}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart-disable": False}
- }
- }
- }
- }
- },
- }
- }
- }
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- step("Verify on R2 that R1 advertises GR capabilities as a restarting node")
-
- input_dict = {
- "r1": {
- "bgp": {
- "graceful-restart": {
- "graceful-restart": True,
- }
- }
- },
- "r2": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}},
- }
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r2", peer="r1"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- for addr_type in ADDR_TYPES:
- dut = "r1"
- peer = "r2"
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert (
- result is True
- ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
- tc_name, result
- )
-
- dut = "r2"
- peer = "r1"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert (
- result is True
- ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
- tc_name, result
- )
-
- step("Kill BGP on R1")
-
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- step(
- "Verify that R1 keeps the stale entries in FIB and R2 keeps stale entries in RIB & FIB"
- )
-
- for addr_type in ADDR_TYPES:
- dut = "r1"
- peer = "r2"
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert (
- result is True
- ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
- tc_name, result
- )
-
- dut = "r2"
- peer = "r1"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert (
- result is True
- ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
- tc_name, result
- )
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_TC_49_p1(request):
- """
- Test Objective : Peer-level inherit from Global Restarting
- Global Mode : GR Restart
- PerPeer Mode : None
- GR Mode effective : GR Restart
-
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- step("Configure R1 as GR restarting node in global level")
-
- input_dict = {
- "r1": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
- "r2": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}},
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- step(
- "Verify that R2 receives GR restarting capabilities"
- " from R1 based on inheritence"
- )
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r2", peer="r1"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- for addr_type in ADDR_TYPES:
- dut = "r1"
- peer = "r2"
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- dut = "r2"
- peer = "r1"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- step("Kill BGPd on router R1")
-
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- step(
- "Verify that R1 keeps the stale entries in FIB and R2 keeps stale entries in RIB & FIB"
- )
-
- for addr_type in ADDR_TYPES:
- dut = "r1"
- peer = "r2"
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- dut = "r2"
- peer = "r1"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- write_test_footer(tc_name)
-
-
-def BGP_GR_TC_52_p1(request):
- """
- Test Objective : Transition from Peer-level disbale to Global inherit helper
- Global Mode : None
- PerPeer Mode : GR Disable
- GR Mode effective : GR Disable
-
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- step(
- "Configure R1 as GR disabled node at per Peer-level for R2"
- " & R2 as GR restarting node"
- )
-
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart-disable": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart-disable": True}
- }
- }
- }
- }
- },
- }
- }
- },
- "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- step("Verify on R2 that R1 does't advertise any GR capabilities")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r2", peer="r1"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- for addr_type in ADDR_TYPES:
- dut = "r2"
- peer = "r1"
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- dut = "r1"
- peer = "r2"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- step("Kill BGP on R2")
-
- kill_router_daemons(tgen, "r2", ["bgpd"])
-
- step(
- "Verify that R2 keeps the stale entries in FIB & R1 doesn't keep RIB & FIB entries."
- )
-
- for addr_type in ADDR_TYPES:
- dut = "r2"
- peer = "r1"
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- dut = "r1"
- peer = "r2"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_bgp_rib(
- tgen, addr_type, dut, input_topo, next_hop, expected=False
- )
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r1: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
- )
- result = verify_rib(
- tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
- )
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
- )
-
- step("Bring up BGP on R2 and remove Peer-level GR config from R1")
-
- start_router_daemons(tgen, "r2", ["bgpd"])
-
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart-disable": False}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1-link1": {"graceful-restart-disable": False}
- }
- }
- }
- }
- },
- }
- }
- }
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- step(
- "Verify on R2 that R1 advertises GR capabilities as a helper node from global inherit"
- )
-
- input_dict = {
- "r1": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}},
- "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
- }
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r2", peer="r1"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- for addr_type in ADDR_TYPES:
- dut = "r2"
- peer = "r1"
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert (
- result is True
- ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
- tc_name, result
- )
-
- dut = "r1"
- peer = "r2"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert (
- result is True
- ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
- tc_name, result
- )
-
- step("Kill BGP on R2")
-
- kill_router_daemons(tgen, "r2", ["bgpd"])
-
- step(
- "Verify that R2 keeps the stale entries in FIB & R1 keeps stale entries in RIB & FIB"
- )
-
- for addr_type in ADDR_TYPES:
- dut = "r2"
- peer = "r1"
- protocol = "bgp"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_1
- )
- input_topo = {"r1": topo["routers"]["r1"]}
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert (
- result is True
- ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
- tc_name, result
- )
-
- dut = "r1"
- peer = "r2"
- next_hop = next_hop_per_address_family(
- tgen, dut, peer, addr_type, NEXT_HOP_IP_2
- )
- input_topo = {"r2": topo["routers"]["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
- result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
- assert (
- result is True
- ), "Testcase {} :Failed \n Routes are still present \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_gr_functionality_topo1/test_bgp_gr_functionality_topo1-4.py b/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-4.py
new file mode 100644
index 0000000000..791ca37eae
--- /dev/null
+++ b/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1-4.py
@@ -0,0 +1,1686 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2019 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 Gracefull Restart functionality.
+Basic Common Test steps for all the test case below :
+- Create topology (setup module)
+ Creating 2 routers topology, r1, r2 in IBGP
+- Bring up topology
+- Verify for bgp to converge
+- Configure BGP Garceful Restart on both the routers.
+
+1. Transition from Peer-level helper to Global Restarting
+2. Transition from Peer-level helper to Global inherit helper
+3. Transition from Peer-level restarting to Global inherit helper
+4. Default GR functional mode is Helper.
+5. Verify that the restarting node sets "R" bit while sending the
+ BGP open messages after the node restart, only if GR is enabled.
+6. Verify if restarting node resets R bit in BGP open message
+ during normal BGP session flaps as well, even when GR restarting
+ mode is enabled. Here link flap happen due to interface UP/DOWN.
+7. Verify if restarting node resets R bit in BGP
+ open message during normal BGP session flaps when GR is disabled.
+8. Verify that restarting nodes set "F" bit while sending
+ the BGP open messages after it restarts, only when BGP GR is enabled.
+9. Verify that only GR helper routers keep the stale
+ route entries, not any GR disabled router.
+10. Verify that GR helper routers keeps all the routes received
+ from restarting node if both the routers are configured as
+ GR restarting node.
+11. Verify that GR helper routers delete all the routes
+ received from a node if both the routers are configured as GR
+ helper node.
+12. After BGP neighborship is established and GR capability is exchanged,
+ transition restarting router to disabled state and vice versa.
+13. After BGP neighborship is established and GR capability is exchanged,
+ transition restarting router to disabled state and vice versa.
+14. Verify that restarting nodes reset "F" bit while sending
+ the BGP open messages after it's restarts, when BGP GR is **NOT** enabled.
+15. Verify that only GR helper routers keep the stale
+ route entries, not any GR disabled router.
+16. Transition from Global Restarting to Disable and then Global
+ Disable to Restarting.
+17. Transition from Global Helper to Disable and then Global
+ Disable to Helper.
+18. Transition from Global Restart to Helper and then Global
+ Helper to Restart, Global Mode : GR Restarting
+ PerPeer Mode : GR Helper
+ GR Mode effective : GR Helper
+19. Transition from Peer-level helper to Global Restarting,
+ Global Mode : GR Restarting
+ PerPeer Mode : GR Restarting
+ GR Mode effective : GR Restarting
+20. Transition from Peer-level restart to Global Restart
+ Global Mode : GR Restarting
+ PerPeer Mode : GR Restarting
+ GR Mode effective : GR Restarting
+21. Transition from Peer-level disabled to Global Restart
+ Global Mode : GR Restarting
+ PerPeer Mode : GR Disabled
+ GR Mode effective : GR Disabled
+22. Peer-level inherit from Global Restarting
+ Global Mode : GR Restart
+ PerPeer Mode : None
+ GR Mode effective : GR Restart
+23. Transition from Peer-level disbale to Global inherit helper
+ Global Mode : None
+ PerPeer Mode : GR Disable
+ GR Mode effective : GR Disable
+
+These tests have been broken up into 4 sub python scripts because
+the totality of this run was fairly significant.
+"""
+
+import os
+import sys
+import time
+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("../"))
+sys.path.append(os.path.join("../lib/"))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib.topogen import Topogen, get_topogen
+from lib.topolog import logger
+
+# Required to instantiate the topology builder class.
+
+# Import topoJson from lib, to create topology and initial configuration
+from lib.topojson import build_config_from_json
+from lib.bgp import (
+ clear_bgp,
+ verify_bgp_rib,
+ verify_graceful_restart,
+ create_router_bgp,
+ verify_r_bit,
+ verify_f_bit,
+ verify_bgp_convergence,
+ verify_bgp_convergence_from_running_config,
+)
+
+from lib.common_config import (
+ write_test_header,
+ reset_config_on_routers,
+ start_topology,
+ kill_router_daemons,
+ start_router_daemons,
+ verify_rib,
+ check_address_types,
+ write_test_footer,
+ check_router_status,
+ shutdown_bringup_interface,
+ step,
+ get_frr_ipv6_linklocal,
+ required_linux_kernel_version,
+)
+
+pytestmark = [pytest.mark.bgpd]
+
+
+# Global variables
+NEXT_HOP_IP = {"ipv4": "192.168.1.10", "ipv6": "fd00:0:0:1::10"}
+NEXT_HOP_IP_1 = {"ipv4": "192.168.0.1", "ipv6": "fd00::1"}
+NEXT_HOP_IP_2 = {"ipv4": "192.168.0.2", "ipv6": "fd00::2"}
+BGP_CONVERGENCE = False
+GR_RESTART_TIMER = 20
+PREFERRED_NEXT_HOP = "link_local"
+
+
+def setup_module(mod):
+ """
+ Sets up the pytest environment
+
+ * `mod`: module name
+ """
+
+ global ADDR_TYPES
+
+ # Required linux kernel version for this suite to run.
+ result = required_linux_kernel_version("4.16")
+ if result is not True:
+ pytest.skip("Kernel requirements are not met")
+
+ 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...
+ json_file = "{}/bgp_gr_topojson_topo1.json".format(CWD)
+ tgen = Topogen(json_file, mod.__name__)
+ global topo
+ topo = tgen.json_topo
+ # ... 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)
+
+ # 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
+ ADDR_TYPES = check_address_types()
+
+ 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)
+
+
+def configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut, peer):
+ """
+ This function groups the repetitive function calls into one function.
+ """
+
+ result = create_router_bgp(tgen, topo, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ neighbor = topo["routers"][peer]["links"]["r1-link1"][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, dut, neighbor=neighbor)
+
+ for addr_type in ADDR_TYPES:
+ neighbor = topo["routers"][dut]["links"]["r2-link1"][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, peer, neighbor=neighbor)
+
+ result = verify_bgp_convergence_from_running_config(tgen)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ return True
+
+
+def next_hop_per_address_family(
+ tgen, dut, peer, addr_type, next_hop_dict, preferred_next_hop=PREFERRED_NEXT_HOP
+):
+ """
+ This function returns link_local or global next_hop per address-family
+ """
+
+ intferface = topo["routers"][peer]["links"]["{}-link1".format(dut)]["interface"]
+ if addr_type == "ipv6" and "link_local" in preferred_next_hop:
+ next_hop = get_frr_ipv6_linklocal(tgen, peer, intf=intferface)
+ else:
+ next_hop = next_hop_dict[addr_type]
+
+ return next_hop
+
+
+def BGP_GR_TC_50_p1(request):
+ """
+ Test Objective : Transition from Peer-level helper to Global inherit helper
+ Global Mode : None
+ PerPeer Mode : Helper
+ GR Mode effective : GR Helper
+
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ step(
+ "Configure R1 as GR helper node at per Peer-level for R2"
+ " and configure R2 as global restarting node."
+ )
+
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ step("Verify on R2 that R1 advertises GR capabilities as a helper node")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ next_hop = next_hop_per_address_family(
+ tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Kill BGP on R2")
+
+ kill_router_daemons(tgen, "r2", ["bgpd"])
+
+ step(
+ "Verify that R2 keeps the stale entries in FIB & R1 keeps stale entries in RIB & FIB"
+ )
+
+ for addr_type in ADDR_TYPES:
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ next_hop = next_hop_per_address_family(
+ tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Bring up BGP on R2 and remove Peer-level GR config from R1 ")
+
+ start_router_daemons(tgen, "r2", ["bgpd"])
+
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-helper": False}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-helper": False}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ neighbor = topo["routers"]["r2"]["links"]["r1-link1"][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, "r1", neighbor=neighbor)
+
+ result = verify_bgp_convergence_from_running_config(tgen)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify on R2 that R1 still advertises GR capabilities as a helper node")
+
+ input_dict = {
+ "r1": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}},
+ "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
+ }
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ next_hop = next_hop_per_address_family(
+ tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Kill BGP on R2")
+
+ kill_router_daemons(tgen, "r2", ["bgpd"])
+
+ step(
+ "Verify that R2 keeps the stale entries in FIB & R1 keeps stale entries in RIB & FIB"
+ )
+
+ for addr_type in ADDR_TYPES:
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ next_hop = next_hop_per_address_family(
+ tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Start BGP on R2")
+
+ start_router_daemons(tgen, "r2", ["bgpd"])
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_TC_46_p1(request):
+ """
+ Test Objective : transition from Peer-level helper to Global Restarting
+ Global Mode : GR Restarting
+ PerPeer Mode : GR Helper
+ GR Mode effective : GR Helper
+
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ step(
+ "Configure R1 and R2 as GR restarting node in global"
+ " and helper in per-Peer-level"
+ )
+
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "graceful-restart": {
+ "graceful-restart": True,
+ },
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ },
+ }
+ },
+ "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ step("Verify on R2 that R1 advertises GR capabilities as a restarting node")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r2", peer="r1"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ dut = "r2"
+ peer = "r1"
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ dut = "r1"
+ peer = "r2"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ step("Kill BGP on R2")
+
+ kill_router_daemons(tgen, "r2", ["bgpd"])
+
+ step(
+ "Verify that R1 keeps the stale entries in RIB & FIB and R2 keeps stale entries in FIB using"
+ )
+
+ for addr_type in ADDR_TYPES:
+ dut = "r2"
+ peer = "r1"
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ dut = "r1"
+ peer = "r2"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ step(
+ "Bring up BGP on R1 and remove Peer-level GR config"
+ " from R1 following by a session reset"
+ )
+
+ start_router_daemons(tgen, "r2", ["bgpd"])
+
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-helper": False}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-helper": False}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ }
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ step("Verify on R2 that R1 advertises GR capabilities as a restarting node")
+
+ input_dict = {
+ "r1": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
+ "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
+ }
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r2", peer="r1"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ dut = "r1"
+ peer = "r2"
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ dut = "r2"
+ peer = "r1"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Kill BGP on R1")
+
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ step(
+ "Verify that R1 keeps the stale entries in FIB command and R2 keeps stale entries in RIB & FIB"
+ )
+
+ for addr_type in ADDR_TYPES:
+ dut = "r1"
+ peer = "r2"
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ dut = "r2"
+ peer = "r1"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_TC_47_p1(request):
+ """
+ Test Objective : transition from Peer-level restart to Global Restart
+ Global Mode : GR Restarting
+ PerPeer Mode : GR Restarting
+ GR Mode effective : GR Restarting
+
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ step("Configure R1 and R2 as GR restarting node in global and per-Peer-level")
+
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "graceful-restart": {
+ "graceful-restart": True,
+ },
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart": True}
+ }
+ }
+ }
+ }
+ },
+ },
+ }
+ },
+ "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ step("Verify on R2 that R1 advertises GR capabilities as a restarting node")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r2", peer="r1"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ dut = "r1"
+ peer = "r2"
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ dut = "r2"
+ peer = "r1"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ step("Kill BGP on R1")
+
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ step(
+ "Verify that R1 keeps the stale entries in FIB and R2 keeps stale entries in RIB & FIB"
+ )
+
+ for addr_type in ADDR_TYPES:
+ dut = "r1"
+ peer = "r2"
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ dut = "r2"
+ peer = "r1"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ step(
+ "Bring up BGP on R1 and remove Peer-level GR"
+ " config from R1 following by a session reset"
+ )
+
+ start_router_daemons(tgen, "r1", ["bgpd"])
+
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart": False}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart": False}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ }
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ step("Verify on R2 that R1 still advertises GR capabilities as a restarting node")
+
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "graceful-restart": {
+ "graceful-restart": True,
+ }
+ }
+ },
+ "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
+ }
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r2", peer="r1"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ dut = "r1"
+ peer = "r2"
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ dut = "r2"
+ peer = "r1"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Kill BGP on R1")
+
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ step(
+ "Verify that R1 keeps the stale entries in FIB and R2 keeps stale entries in RIB & FIB"
+ )
+
+ for addr_type in ADDR_TYPES:
+ dut = "r1"
+ peer = "r2"
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ dut = "r2"
+ peer = "r1"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_TC_48_p1(request):
+ """
+ Test Objective : transition from Peer-level disabled to Global Restart
+ Global Mode : GR Restarting
+ PerPeer Mode : GR Disabled
+ GR Mode effective : GR Disabled
+
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ step(
+ "Configure R1 as GR restarting node in global level and"
+ " GR Disabled in per-Peer-level"
+ )
+
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "graceful-restart": {
+ "graceful-restart": True,
+ },
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-disable": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-disable": True}
+ }
+ }
+ }
+ }
+ },
+ },
+ }
+ },
+ "r2": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}},
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ step("Verify on R2 that R1 does't advertise any GR capabilities")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r2", peer="r1"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ dut = "r1"
+ peer = "r2"
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ dut = "r2"
+ peer = "r1"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ step("Kill BGP on R1")
+
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ step("Verify on R2 and R1 that none of the routers keep stale entries")
+
+ for addr_type in ADDR_TYPES:
+ dut = "r1"
+ peer = "r2"
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_rib(
+ tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
+
+ dut = "r2"
+ peer = "r1"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_bgp_rib(
+ tgen, addr_type, dut, input_topo, next_hop, expected=False
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r2: routes are still present in BGP RIB\n Error: {}".format(
+ tc_name, result
+ )
+ )
+ result = verify_rib(
+ tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r2: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
+
+ step("Bring up BGP on R1 and remove Peer-level GR config from R1")
+
+ start_router_daemons(tgen, "r1", ["bgpd"])
+
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-disable": False}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-disable": False}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ }
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ step("Verify on R2 that R1 advertises GR capabilities as a restarting node")
+
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "graceful-restart": {
+ "graceful-restart": True,
+ }
+ }
+ },
+ "r2": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}},
+ }
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r2", peer="r1"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ dut = "r1"
+ peer = "r2"
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ dut = "r2"
+ peer = "r1"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Kill BGP on R1")
+
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ step(
+ "Verify that R1 keeps the stale entries in FIB and R2 keeps stale entries in RIB & FIB"
+ )
+
+ for addr_type in ADDR_TYPES:
+ dut = "r1"
+ peer = "r2"
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ dut = "r2"
+ peer = "r1"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_TC_49_p1(request):
+ """
+ Test Objective : Peer-level inherit from Global Restarting
+ Global Mode : GR Restart
+ PerPeer Mode : None
+ GR Mode effective : GR Restart
+
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ step("Configure R1 as GR restarting node in global level")
+
+ input_dict = {
+ "r1": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
+ "r2": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}},
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ step(
+ "Verify that R2 receives GR restarting capabilities"
+ " from R1 based on inheritence"
+ )
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r2", peer="r1"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ dut = "r1"
+ peer = "r2"
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ dut = "r2"
+ peer = "r1"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ step("Kill BGPd on router R1")
+
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ step(
+ "Verify that R1 keeps the stale entries in FIB and R2 keeps stale entries in RIB & FIB"
+ )
+
+ for addr_type in ADDR_TYPES:
+ dut = "r1"
+ peer = "r2"
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ dut = "r2"
+ peer = "r1"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ write_test_footer(tc_name)
+
+
+def BGP_GR_TC_52_p1(request):
+ """
+ Test Objective : Transition from Peer-level disbale to Global inherit helper
+ Global Mode : None
+ PerPeer Mode : GR Disable
+ GR Mode effective : GR Disable
+
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ step(
+ "Configure R1 as GR disabled node at per Peer-level for R2"
+ " & R2 as GR restarting node"
+ )
+
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-disable": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-disable": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ step("Verify on R2 that R1 does't advertise any GR capabilities")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r2", peer="r1"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ dut = "r2"
+ peer = "r1"
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ dut = "r1"
+ peer = "r2"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ step("Kill BGP on R2")
+
+ kill_router_daemons(tgen, "r2", ["bgpd"])
+
+ step(
+ "Verify that R2 keeps the stale entries in FIB & R1 doesn't keep RIB & FIB entries."
+ )
+
+ for addr_type in ADDR_TYPES:
+ dut = "r2"
+ peer = "r1"
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ dut = "r1"
+ peer = "r2"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_bgp_rib(
+ tgen, addr_type, dut, input_topo, next_hop, expected=False
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r1: routes are still present in BGP RIB\n Error: {}".format(
+ tc_name, result
+ )
+ )
+ result = verify_rib(
+ tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
+
+ step("Bring up BGP on R2 and remove Peer-level GR config from R1")
+
+ start_router_daemons(tgen, "r2", ["bgpd"])
+
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-disable": False}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {"graceful-restart-disable": False}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ }
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ step(
+ "Verify on R2 that R1 advertises GR capabilities as a helper node from global inherit"
+ )
+
+ input_dict = {
+ "r1": {"bgp": {"graceful-restart": {"graceful-restart-helper": True}}},
+ "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
+ }
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r2", peer="r1"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ dut = "r2"
+ peer = "r1"
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ dut = "r1"
+ peer = "r2"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Kill BGP on R2")
+
+ kill_router_daemons(tgen, "r2", ["bgpd"])
+
+ step(
+ "Verify that R2 keeps the stale entries in FIB & R1 keeps stale entries in RIB & FIB"
+ )
+
+ for addr_type in ADDR_TYPES:
+ dut = "r2"
+ peer = "r1"
+ protocol = "bgp"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_1
+ )
+ input_topo = {"r1": topo["routers"]["r1"]}
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} :Failed \n Routes are still present \n Error {}".format(
+ tc_name, result
+ )
+
+ dut = "r1"
+ peer = "r2"
+ next_hop = next_hop_per_address_family(
+ tgen, dut, peer, addr_type, NEXT_HOP_IP_2
+ )
+ input_topo = {"r2": topo["routers"]["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
+ assert (
+ result is True
+ ), "Testcase {} :Failed \n Routes are still present \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_gr_functionality_topo2/test_bgp_gr_functionality_topo2-1.py b/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-1.py
new file mode 100644
index 0000000000..064fde1633
--- /dev/null
+++ b/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-1.py
@@ -0,0 +1,1515 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2019 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 Graceful Restart functionality.
+Basic Common Test steps for all the test case below :
+- Create topology (setup module)
+ Creating 7 routers topology
+- Bring up topology
+- Verify for bgp to converge
+- Configure BGP Graceful Restart on both the routers.
+
+TC_1_2:
+ Verify that EOR message is sent out only after initial convergence
+ Verify whether EOR message is received from all the peers after restart
+TC_3:
+ Verify the selection deferral timer functionality when EOR is not sent
+ by the helper router
+TC_11:
+ Verify that selection-deferral timer sets the maximum time to
+ avoid deadlock during which the best-path
+TC_10:
+ Test Objective : Test GR scenarios on helper router by enabling
+ Graceful Restart for multiple address families.
+TC_15:
+ Test Objective : Test GR scenarios by enabling Graceful Restart
+ for multiple address families..
+TC_16:
+ Test Objective : Verify BGP-GR feature when restarting node
+ is a transit router for it's iBGP peers.
+TC_18:
+ Test Objective : Verify that GR helper router deletes stale routes
+ received from restarting node, if GR capability is not present in
+TC_19:
+ Test Objective : Verify that GR routers keeps all the routes
+ received from restarting node if both the routers are
+TC_26:
+ Test Objective : Test GR scenarios on helper router by enabling
+ Graceful Restart for multiple address families.
+TC_28:
+ Test Objective : Verify if helper node goes down before restarting
+ node comes up online, helper node sets the R-bit to avoid dead-lock
+TC_29:
+ Test Objective : Change timers on the fly, and
+ verify if it takes immediate effect.
+TC_33:
+ Test Objective : Helper router receives same prefixes from two
+ different routers (GR-restarting and GR-disabled). Keeps the
+TC_34_1:
+ Test Objective : Restarting node doesn't preserve forwarding
+ state, helper router should not keep the stale entries.
+TC_34_2:
+ Test Objective : Restarting node doesn't preserve the forwarding
+ state verify the behaviour on helper node, if it still keeps the
+TC_32:
+ Test Objective : Restarting node is connected to multiple helper
+ nodes, one of them doesn't send EOR to restarting router. Verify
+TC_37:
+ Test Objective : Verify if helper node restarts before sending the
+ EOR message, restarting node doesn't wait until stale path timer
+TC_30:
+ Test Objective : Restarting node removes stale routes from Zebra
+ after receiving an EOR from helper router.
+
+"""
+
+import os
+import sys
+import time
+import pytest
+from time import sleep
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join("../"))
+sys.path.append(os.path.join("../lib/"))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib.topogen import Topogen, get_topogen
+from lib.topolog import logger
+
+# Required to instantiate the topology builder class.
+
+# Import topoJson from lib, to create topology and initial configuration
+from lib.topojson import build_config_from_json
+from lib.bgp import (
+ clear_bgp,
+ verify_bgp_rib,
+ verify_graceful_restart,
+ create_router_bgp,
+ verify_r_bit,
+ verify_eor,
+ verify_f_bit,
+ verify_bgp_convergence,
+ verify_gr_address_family,
+ modify_bgp_config_when_bgpd_down,
+ verify_graceful_restart_timers,
+ verify_bgp_convergence_from_running_config,
+)
+
+from lib.common_config import (
+ write_test_header,
+ reset_config_on_routers,
+ start_topology,
+ kill_router_daemons,
+ start_router_daemons,
+ verify_rib,
+ check_address_types,
+ write_test_footer,
+ check_router_status,
+ step,
+ get_frr_ipv6_linklocal,
+ required_linux_kernel_version,
+)
+
+pytestmark = [pytest.mark.bgpd]
+
+
+# Global variables
+BGP_CONVERGENCE = False
+GR_RESTART_TIMER = 5
+GR_SELECT_DEFER_TIMER = 5
+GR_STALEPATH_TIMER = 5
+PREFERRED_NEXT_HOP = "link_local"
+NEXT_HOP_4 = ["192.168.1.1", "192.168.4.2"]
+NEXT_HOP_6 = ["fd00:0:0:1::1", "fd00:0:0:4::2"]
+
+
+def setup_module(mod):
+ """
+ Sets up the pytest environment
+
+ * `mod`: module name
+ """
+
+ # Required linux kernel version for this suite to run.
+ result = required_linux_kernel_version("4.16")
+ if result is not True:
+ pytest.skip("Kernel requirements are not met")
+
+ global ADDR_TYPES
+
+ 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...
+ json_file = "{}/bgp_gr_topojson_topo2.json".format(CWD)
+ tgen = Topogen(json_file, mod.__name__)
+ global topo
+ topo = tgen.json_topo
+ # ... 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)
+
+ # Api call verify whether BGP is converged
+ ADDR_TYPES = check_address_types()
+
+ for addr_type in ADDR_TYPES:
+ 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)
+
+
+def configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut, peer):
+ """
+ This function groups the repetitive function calls into one function.
+ """
+
+ logger.info("configure_gr_followed_by_clear: dut %s peer %s", dut, peer)
+
+ result = create_router_bgp(tgen, topo, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ neighbor = topo["routers"][peer]["links"][dut][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, dut, neighbor=neighbor)
+
+ for addr_type in ADDR_TYPES:
+ neighbor = topo["routers"][dut]["links"][peer][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, peer, neighbor=neighbor)
+
+ result = verify_bgp_convergence_from_running_config(tgen)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ return True
+
+
+def next_hop_per_address_family(tgen, dut, peer, addr_type, next_hop_dict):
+ """
+ This function returns link_local or global next_hop per address-family
+ """
+
+ intferface = topo["routers"][peer]["links"]["{}-link1".format(dut)]["interface"]
+ if addr_type == "ipv6" and "link_local" in PREFERRED_NEXT_HOP:
+ next_hop = get_frr_ipv6_linklocal(tgen, peer, intf=intferface)
+ else:
+ next_hop = next_hop_dict[addr_type]
+
+ return next_hop
+
+
+def test_BGP_GR_TC_1_2_p0(request):
+ """
+ Verify that EOR message is sent out only after initial convergence
+ Verify whether EOR message is received from all the peers after restart
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ "Verify EOR Sent and Received : BGP_GR_TC_1_2 >> "
+ "BGP GR [Helper Mode]R3-----R1[Restart Mode] "
+ )
+
+ # Configure graceful-restart
+ input_dict = {
+ "r3": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ "r1": {
+ "bgp": {
+ "graceful-restart": {
+ "graceful-restart": True,
+ "preserve-fw-state": True,
+ },
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ },
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes received from router R3
+ dut = "r1"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r3"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info("R1 goes for reload")
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ # Verifying RIB routes
+ input_dict_1 = {key: topo["routers"][key] for key in ["r3"]}
+ # Verifying RIB routes
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info("Starting bgpd process")
+ start_router_daemons(tgen, "r1", ["bgpd"])
+ logger.info("R1 is UP Now")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes received from router R3
+ input_dict_1 = {key: topo["routers"][key] for key in ["r3"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying EOR on restarting router
+ result = verify_eor(tgen, topo, addr_type, input_dict, dut="r3", peer="r1")
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_TC_3_p0(request):
+ """
+ Verify the selection deferral timer functionality when EOR is not sent
+ by the helper router
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ " Verify route download to RIB: BGP_GR_TC_3 >> "
+ "BGP GR [Helper Mode]R1-----R2[Restart Mode] "
+ )
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "graceful-restart": {
+ "disable-eor": True,
+ },
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ },
+ }
+ },
+ "r2": {
+ "bgp": {
+ "graceful-restart": {
+ "graceful-restart": True,
+ "preserve-fw-state": True,
+ "timer": {"select-defer-time": GR_SELECT_DEFER_TIMER},
+ },
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {"dest_link": {"r2": {"graceful-restart": True}}}
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {"dest_link": {"r2": {"graceful-restart": True}}}
+ }
+ }
+ },
+ },
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes received from router R1
+ dut = "r2"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info("R2 goes for reload ")
+ kill_router_daemons(tgen, "r2", ["bgpd"])
+
+ logger.info("R2 is about to come up now")
+ start_router_daemons(tgen, "r2", ["bgpd"])
+ logger.info("R2 is UP Now")
+
+ for addr_type in ADDR_TYPES:
+ # Verifying BGP RIB routes received from router R1
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verify EOR on restarting router
+ result = verify_eor(
+ tgen, topo, addr_type, input_dict, dut="r2", peer="r1", expected=False
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r2: EOR is set to True\n Error: {}".format(
+ tc_name, result
+ )
+
+ logger.info(
+ "Waiting for selection deferral timer({} sec)..".format(GR_SELECT_DEFER_TIMER)
+ )
+ sleep(GR_SELECT_DEFER_TIMER)
+
+ for addr_type in ADDR_TYPES:
+ # Verifying RIB routes
+ result = verify_rib(tgen, addr_type, "r2", input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_TC_11_p0(request):
+ """
+ Verify that selection-deferral timer sets the maximum time to
+ avoid deadlock during which the best-path
+ selection process is deferred, after a peer session was restarted
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info("Verify EOR Sent after deferral timeout : BGP_GR_TC_11")
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "graceful-restart": {
+ "graceful-restart": True,
+ "select-defer-time": GR_SELECT_DEFER_TIMER,
+ },
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {"dest_link": {"r1": {"graceful-restart": True}}},
+ "r3": {"dest_link": {"r1": {"graceful-restart": True}}},
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {"dest_link": {"r1": {"graceful-restart": True}}},
+ "r3": {"dest_link": {"r1": {"graceful-restart": True}}},
+ }
+ }
+ },
+ },
+ }
+ },
+ "r3": {
+ "bgp": {
+ "graceful-restart": {"disable-eor": True},
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ },
+ }
+ },
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ clear_bgp(tgen, addr_type, "r1")
+ clear_bgp(tgen, addr_type, "r3")
+
+ result = verify_bgp_convergence_from_running_config(tgen, topo)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes received from router R1
+ dut = "r1"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r3"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info("R1 goes for reload")
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ logger.info("Starting bgpd process")
+ start_router_daemons(tgen, "r1", ["bgpd"])
+ logger.info("R1 is UP Now")
+
+ for addr_type in ADDR_TYPES:
+ # Verify EOR on restarting router
+ result = verify_eor(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r3", expected=False
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: EOR is set to True\n Error: {}".format(
+ tc_name, result
+ )
+
+ logger.info(
+ "Waiting for selection deferral timer({} sec).. ".format(
+ GR_SELECT_DEFER_TIMER + 2
+ )
+ )
+ sleep(GR_SELECT_DEFER_TIMER + 2)
+
+ for addr_type in ADDR_TYPES:
+ # Verifying BGP RIB routes received from router R1
+ input_dict_1 = {key: topo["routers"][key] for key in ["r3"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying EOR on restarting router
+ result = verify_eor(
+ tgen, topo, addr_type, input_dict, dut="r3", peer="r1", expected=False
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r3: EOR is set to True\n Error: {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_10_p2(request):
+ """
+ Test Objective : Test GR scenarios on helper router by enabling
+ Graceful Restart for multiple address families.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ step("Test Setup: [Helper Mode]R3-----R1[Restart Mode] initialized")
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1": {
+ "next_hop_self": True,
+ "graceful-restart": True,
+ "activate": "ipv6",
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1": {
+ "next_hop_self": True,
+ "graceful-restart": True,
+ "activate": "ipv4",
+ }
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ "r3": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "graceful-restart-helper": True,
+ "activate": "ipv6",
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "graceful-restart-helper": True,
+ "activate": "ipv4",
+ }
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
+
+ for addr_type in ADDR_TYPES:
+ step(
+ "Verifying GR config and operational state for addr_type {}".format(
+ addr_type
+ )
+ )
+
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes
+ dut = "r3"
+ input_topo = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_topo)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # verify multi address family
+ result = verify_gr_address_family(
+ tgen,
+ topo,
+ addr_type,
+ "ipv4Unicast",
+ dut="r1",
+ peer="r3",
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # verify multi address family
+ result = verify_gr_address_family(
+ tgen,
+ topo,
+ addr_type,
+ "ipv6Unicast",
+ dut="r1",
+ peer="r3",
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # verify multi address family
+ result = verify_gr_address_family(
+ tgen,
+ topo,
+ addr_type,
+ "ipv4Unicast",
+ dut="r3",
+ peer="r1",
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # verify multi address family
+ result = verify_gr_address_family(
+ tgen,
+ topo,
+ addr_type,
+ "ipv6Unicast",
+ dut="r3",
+ peer="r1",
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Killing bgpd on r1")
+
+ # Kill BGPd daemon on R1
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ # Verifying BGP RIB routes
+ input_topo = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_topo)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Starting bgpd on r1")
+
+ # Start BGPd daemon on R1
+ start_router_daemons(tgen, "r1", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ # Verifying BGP RIB routes
+ input_topo = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_topo)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+def BGP_GR_16_p2(request):
+ """
+ Test Objective : Verify BGP-GR feature when restarting node
+ is a transit router for it's iBGP peers.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ "[Step 1] : Test Setup " "[Helper Mode]R3-----R1[Restart Mode] initialized"
+ )
+
+ # Configure graceful-restart and timers
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1": {
+ "graceful-restart": True,
+ "next_hop_self": True,
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1": {
+ "graceful-restart": True,
+ "next_hop_self": True,
+ }
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ "r3": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info(
+ "[Step 2] : Test Setup "
+ "[Helper Mode]R3-----R1[Restart Mode]"
+ "--------R6[Helper Mode] initialized"
+ )
+
+ # Configure graceful-restart and timers
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ }
+ }
+ },
+ "r2": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes
+ dut = "r3"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes
+ input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Kill BGPd daemon on R1
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ # Verifying BGP RIB routes
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes
+ input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Start BGPd daemon on R1
+ start_router_daemons(tgen, "r1", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ # Verifying BGP RIB routes
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes
+ input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_bgp_convergence_from_running_config(tgen, topo)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_18_p1(request):
+ """
+ Test Objective : Verify that GR helper router deletes stale routes
+ received from restarting node, if GR capability is not present in
+ restarting node's OPEN message.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ "[Step 1] : Test Setup " "[Helper Mode]R6-----R1[Restart Mode] initialized"
+ )
+
+ # Configure graceful-restart and timers
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r6": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r6": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ }
+ }
+ },
+ "r6": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r6": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r6": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r6")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r6"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info(
+ "[Step 2] : Test Setup "
+ "[Helper Mode]R6-----R1[Restart Mode]"
+ "--------R2[Helper Mode] initialized"
+ )
+
+ # Configure graceful-restart and timers
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ }
+ }
+ },
+ "r2": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes
+ dut = "r6"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes
+ dut = "r2"
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Kill BGPd daemon on R1
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ logger.info("[Step 3] : Configure R1 to prevent sending EOR")
+
+ # Modify graceful-restart config to prevent sending EOR
+ input_dict_3 = {"r1": {"bgp": {"graceful-restart": {"disable-eor": True}}}}
+
+ result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_3)
+
+ # Modify configuration to delete routes
+ network = {"ipv4": "101.0.20.1/32", "ipv6": "1::1/128"}
+ for addr_type in ADDR_TYPES:
+ input_dict_3 = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ addr_type: {
+ "unicast": {
+ "advertise_networks": [
+ {
+ "network": network[addr_type],
+ "no_of_network": 5,
+ "delete": True,
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+
+ result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_3)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Modify graceful-restart config
+ input_dict_3 = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1": {"graceful-restart-disable": True}
+ }
+ },
+ "r6": {
+ "dest_link": {
+ "r1": {"graceful-restart-disable": True}
+ }
+ },
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1": {"graceful-restart-disable": True}
+ }
+ },
+ "r6": {
+ "dest_link": {
+ "r1": {"graceful-restart-disable": True}
+ }
+ },
+ }
+ }
+ },
+ }
+ }
+ }
+ }
+
+ result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_3)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(tc_name, result)
+
+ logger.info("[Step 4] : Bring up the BGPd daemon on R1 for 30" " seconds..")
+
+ # Start BGPd daemon on R1
+ start_router_daemons(tgen, "r1", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ # Verifying BGP RIB routes
+ dut = "r6"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r6: routes are still present in BGP RIB\n Error: {}".format(
+ tc_name, result
+ )
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r6: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ # Verifying BGP RIB routes
+ dut = "r2"
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r2: routes are still present in BGP RIB\n Error: {}".format(
+ tc_name, result
+ )
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r6: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
+ logger.info(" Expected behavior: {}".format(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_gr_functionality_topo2/test_bgp_gr_functionality_topo2-2.py b/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-2.py
new file mode 100644
index 0000000000..4356c4d591
--- /dev/null
+++ b/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-2.py
@@ -0,0 +1,1216 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2019 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 Graceful Restart functionality.
+Basic Common Test steps for all the test case below :
+- Create topology (setup module)
+ Creating 7 routers topology
+- Bring up topology
+- Verify for bgp to converge
+- Configure BGP Graceful Restart on both the routers.
+
+TC_1_2:
+ Verify that EOR message is sent out only after initial convergence
+ Verify whether EOR message is received from all the peers after restart
+TC_3:
+ Verify the selection deferral timer functionality when EOR is not sent
+ by the helper router
+TC_11:
+ Verify that selection-deferral timer sets the maximum time to
+ avoid deadlock during which the best-path
+TC_10:
+ Test Objective : Test GR scenarios on helper router by enabling
+ Graceful Restart for multiple address families.
+TC_15:
+ Test Objective : Test GR scenarios by enabling Graceful Restart
+ for multiple address families..
+TC_16:
+ Test Objective : Verify BGP-GR feature when restarting node
+ is a transit router for it's iBGP peers.
+TC_18:
+ Test Objective : Verify that GR helper router deletes stale routes
+ received from restarting node, if GR capability is not present in
+TC_19:
+ Test Objective : Verify that GR routers keeps all the routes
+ received from restarting node if both the routers are
+TC_26:
+ Test Objective : Test GR scenarios on helper router by enabling
+ Graceful Restart for multiple address families.
+TC_28:
+ Test Objective : Verify if helper node goes down before restarting
+ node comes up online, helper node sets the R-bit to avoid dead-lock
+TC_29:
+ Test Objective : Change timers on the fly, and
+ verify if it takes immediate effect.
+TC_33:
+ Test Objective : Helper router receives same prefixes from two
+ different routers (GR-restarting and GR-disabled). Keeps the
+TC_34_1:
+ Test Objective : Restarting node doesn't preserve forwarding
+ state, helper router should not keep the stale entries.
+TC_34_2:
+ Test Objective : Restarting node doesn't preserve the forwarding
+ state verify the behaviour on helper node, if it still keeps the
+TC_32:
+ Test Objective : Restarting node is connected to multiple helper
+ nodes, one of them doesn't send EOR to restarting router. Verify
+TC_37:
+ Test Objective : Verify if helper node restarts before sending the
+ EOR message, restarting node doesn't wait until stale path timer
+TC_30:
+ Test Objective : Restarting node removes stale routes from Zebra
+ after receiving an EOR from helper router.
+
+"""
+
+import os
+import sys
+import time
+import pytest
+from time import sleep
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join("../"))
+sys.path.append(os.path.join("../lib/"))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib.topogen import Topogen, get_topogen
+from lib.topolog import logger
+
+# Required to instantiate the topology builder class.
+
+# Import topoJson from lib, to create topology and initial configuration
+from lib.topojson import build_config_from_json
+from lib.bgp import (
+ clear_bgp,
+ verify_bgp_rib,
+ verify_graceful_restart,
+ create_router_bgp,
+ verify_r_bit,
+ verify_eor,
+ verify_f_bit,
+ verify_bgp_convergence,
+ verify_gr_address_family,
+ modify_bgp_config_when_bgpd_down,
+ verify_graceful_restart_timers,
+ verify_bgp_convergence_from_running_config,
+)
+
+from lib.common_config import (
+ write_test_header,
+ reset_config_on_routers,
+ start_topology,
+ kill_router_daemons,
+ start_router_daemons,
+ verify_rib,
+ check_address_types,
+ write_test_footer,
+ check_router_status,
+ step,
+ get_frr_ipv6_linklocal,
+ required_linux_kernel_version,
+)
+
+pytestmark = [pytest.mark.bgpd]
+
+
+# Global variables
+BGP_CONVERGENCE = False
+GR_RESTART_TIMER = 5
+GR_SELECT_DEFER_TIMER = 5
+GR_STALEPATH_TIMER = 5
+PREFERRED_NEXT_HOP = "link_local"
+NEXT_HOP_4 = ["192.168.1.1", "192.168.4.2"]
+NEXT_HOP_6 = ["fd00:0:0:1::1", "fd00:0:0:4::2"]
+
+
+def setup_module(mod):
+ """
+ Sets up the pytest environment
+
+ * `mod`: module name
+ """
+
+ # Required linux kernel version for this suite to run.
+ result = required_linux_kernel_version("4.16")
+ if result is not True:
+ pytest.skip("Kernel requirements are not met")
+
+ global ADDR_TYPES
+
+ 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...
+ json_file = "{}/bgp_gr_topojson_topo2.json".format(CWD)
+ tgen = Topogen(json_file, mod.__name__)
+ global topo
+ topo = tgen.json_topo
+ # ... 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)
+
+ # Api call verify whether BGP is converged
+ ADDR_TYPES = check_address_types()
+
+ for addr_type in ADDR_TYPES:
+ 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)
+
+
+def configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut, peer):
+ """
+ This function groups the repetitive function calls into one function.
+ """
+
+ logger.info("configure_gr_followed_by_clear: dut %s peer %s", dut, peer)
+
+ result = create_router_bgp(tgen, topo, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ neighbor = topo["routers"][peer]["links"][dut][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, dut, neighbor=neighbor)
+
+ for addr_type in ADDR_TYPES:
+ neighbor = topo["routers"][dut]["links"][peer][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, peer, neighbor=neighbor)
+
+ result = verify_bgp_convergence_from_running_config(tgen)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ return True
+
+
+def next_hop_per_address_family(tgen, dut, peer, addr_type, next_hop_dict):
+ """
+ This function returns link_local or global next_hop per address-family
+ """
+
+ intferface = topo["routers"][peer]["links"]["{}-link1".format(dut)]["interface"]
+ if addr_type == "ipv6" and "link_local" in PREFERRED_NEXT_HOP:
+ next_hop = get_frr_ipv6_linklocal(tgen, peer, intf=intferface)
+ else:
+ next_hop = next_hop_dict[addr_type]
+
+ return next_hop
+
+
+def test_BGP_GR_26_p2(request):
+ """
+ Test Objective : Test GR scenarios on helper router by enabling
+ Graceful Restart for multiple address families.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ "[Step 1] : Test Setup " "[Helper Mode]R3-----R1[Restart Mode] initialized"
+ )
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1": {
+ "graceful-restart": True,
+ "next_hop_self": True,
+ "activate": "ipv6",
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1": {
+ "graceful-restart": True,
+ "next_hop_self": True,
+ "activate": "ipv4",
+ }
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ "r3": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "graceful-restart-helper": True,
+ "activate": "ipv6",
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "graceful-restart-helper": True,
+ "activate": "ipv4",
+ }
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r3", peer="r1"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes
+ dut = "r3"
+ input_topo = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_topo)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Kill BGPd daemon on R1
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ # Verifying BGP RIB routes
+ input_topo = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_topo)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Start BGPd daemon on R1
+ start_router_daemons(tgen, "r1", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ # Verifying BGP RIB routes
+ input_topo = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_topo)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_topo)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # verify multi address family
+ result = verify_gr_address_family(
+ tgen,
+ topo,
+ addr_type,
+ "ipv4Unicast",
+ dut="r1",
+ peer="r3",
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # verify multi address family
+ result = verify_gr_address_family(
+ tgen,
+ topo,
+ addr_type,
+ "ipv6Unicast",
+ dut="r1",
+ peer="r3",
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # verify multi address family
+ result = verify_gr_address_family(
+ tgen,
+ topo,
+ addr_type,
+ "ipv4Unicast",
+ dut="r3",
+ peer="r1",
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # verify multi address family
+ result = verify_gr_address_family(
+ tgen,
+ topo,
+ addr_type,
+ "ipv6Unicast",
+ dut="r3",
+ peer="r1",
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_chaos_28_p1(request):
+ """
+ Test Objective : Verify if helper node goes down before restarting
+ node comes up online, helper node sets the R-bit to avoid dead-lock
+ till SDT expiry.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ "Test Case: test_BGP_GR_chaos_28 :"
+ "[Helper Mode]R3-----R1[Restart Mode] initialized"
+ )
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ }
+ }
+ },
+ "r3": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info("[Step 1] : Kill BGPd daemon on R1..")
+
+ # Kill BGPd daemon on R1
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ logger.info("[Step 2] : Kill BGPd daemon on R3..")
+
+ # Kill BGPd daemon on R3
+ kill_router_daemons(tgen, "r3", ["bgpd"])
+
+ logger.info("[Step 3] : Start BGPd daemon on R1..")
+
+ # Start BGPd daemon on R1
+ start_router_daemons(tgen, "r1", ["bgpd"])
+
+ logger.info("[Step 4] : Start BGPd daemon on R3..")
+
+ # Start BGPd daemon on R3
+ start_router_daemons(tgen, "r3", ["bgpd"])
+
+ # Verify r_bit
+ for addr_type in ADDR_TYPES:
+ result = verify_r_bit(tgen, topo, addr_type, input_dict, dut="r3", peer="r1")
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_chaos_29_p1(request):
+ """
+ Test Objective : Change timers on the fly, and
+ verify if it takes immediate effect.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ " Test Case : test_BGP_GR_chaos_29"
+ " BGP GR [Helper Mode]R3-----R1[Restart Mode]"
+ " and [restart-time 150]R1 initialized"
+ )
+
+ # Configure graceful-restart and timers
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "graceful-restart": {"timer": {"restart-time": GR_RESTART_TIMER}},
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ },
+ }
+ },
+ "r3": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verify graceful-restart timers
+ input_dict_2 = {
+ "r1": {
+ "bgp": {
+ "graceful-restart": {"timer": {"restart-time": GR_RESTART_TIMER + 5}}
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ input_dict_2 = {
+ "r1": {
+ "bgp": {
+ "graceful-restart": {"timer": {"restart-time": GR_RESTART_TIMER}}
+ }
+ }
+ }
+
+ result = verify_graceful_restart_timers(
+ tgen, topo, addr_type, input_dict_2, dut="r3", peer="r1"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ # Verifying BGP RIB routes before shutting down BGPd daemon
+ dut = "r3"
+ input_dict = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info("[Step 2] : Kill BGPd daemon on R1..")
+
+ # Kill BGPd daemon on R1
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ logger.info("[Step 3] : Wait for {} seconds..".format(GR_RESTART_TIMER))
+
+ # Waiting for GR_RESTART_TIMER
+ sleep(GR_RESTART_TIMER)
+
+ for addr_type in ADDR_TYPES:
+ # Verifying BGP RIB routes before shutting down BGPd daemon
+ input_dict = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: routes are still present in BGP RIB\n Error: {}".format(
+ tc_name, result
+ )
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ logger.info("[Step 4] : Start BGPd daemon on R1..")
+
+ # Start BGPd daemon on R1
+ start_router_daemons(tgen, "r1", ["bgpd"])
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_chaos_33_p1(request):
+ """
+ Test Objective : Helper router receives same prefixes from two
+ different routers (GR-restarting and GR-disabled). Keeps the
+ stale entry only for GR-restarting node(next-hop is correct).
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ " Test Case : test_BGP_GR_chaos_33 "
+ "BGP GR "
+ "[Restart Mode]R1--R3[Helper Mode]--R4[Disabled Mode]"
+ )
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ }
+ }
+ },
+ "r3": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ "r4": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r4": {"graceful-restart-disable": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r4": {"graceful-restart-disable": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info("[Step 2] : Advertise same networks from R1 and R4..")
+
+ # Api call to delete advertised networks
+ input_dict_2 = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "advertise_networks": [
+ {
+ "network": "200.0.20.1/32",
+ "no_of_network": 2,
+ }
+ ]
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "advertise_networks": [
+ {"network": "2001::1/128", "no_of_network": 2}
+ ]
+ }
+ },
+ }
+ }
+ },
+ "r4": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "advertise_networks": [
+ {"network": "200.0.20.1/32", "no_of_network": 2}
+ ]
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "advertise_networks": [
+ {"network": "2001::1/128", "no_of_network": 2}
+ ]
+ }
+ },
+ }
+ }
+ },
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ # Verifying RIB routes
+ dut = "r3"
+ peer1 = "r1"
+ peer2 = "r4"
+ intf1 = topo["routers"][peer1]["links"][dut]["interface"]
+ intf2 = topo["routers"][peer2]["links"][dut]["interface"]
+
+ if addr_type == "ipv4":
+ next_hop_4 = NEXT_HOP_4
+ result = verify_rib(tgen, addr_type, dut, input_dict_2, next_hop_4)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ if addr_type == "ipv6":
+ if "link_local" in PREFERRED_NEXT_HOP:
+ next_hop1 = get_frr_ipv6_linklocal(tgen, peer1, intf=intf1)
+ next_hop2 = get_frr_ipv6_linklocal(tgen, peer2, intf=intf2)
+
+ next_hop_6 = [next_hop1, next_hop2]
+ else:
+ next_hop_6 = NEXT_HOP_6
+
+ result = verify_rib(tgen, addr_type, dut, input_dict_2, next_hop_6)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info("[Step 3] : Kill BGPd daemon on R1 and R4..")
+
+ # Kill BGPd daemon on R1
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ # Kill BGPd daemon on R4
+ kill_router_daemons(tgen, "r4", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ # Verifying RIB routes
+ next_hop_6 = ["fd00:0:0:1::1"]
+ if addr_type == "ipv4":
+ next_hop_4 = NEXT_HOP_4[0]
+
+ result = verify_rib(tgen, addr_type, dut, input_dict_2, next_hop_4)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ if addr_type == "ipv6":
+ if "link_local" in PREFERRED_NEXT_HOP:
+ next_hop_6 = get_frr_ipv6_linklocal(tgen, peer1, intf=intf1)
+ else:
+ next_hop_6 = NEXT_HOP_6[0]
+
+ result = verify_rib(tgen, addr_type, dut, input_dict_2, next_hop_6)
+
+ # Verifying RIB routes
+ if addr_type == "ipv4":
+ next_hop_4 = NEXT_HOP_4[1]
+ result = verify_rib(
+ tgen, addr_type, dut, input_dict_2, next_hop_4, expected=False
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: routes are still present in BGP RIB\n Error: {}".format(
+ tc_name, result
+ )
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ if addr_type == "ipv6":
+ if "link_local" in PREFERRED_NEXT_HOP:
+ next_hop_6 = get_frr_ipv6_linklocal(tgen, peer2, intf=intf2)
+ else:
+ next_hop_6 = NEXT_HOP_6[1]
+
+ result = verify_rib(
+ tgen, addr_type, dut, input_dict_2, next_hop_6, expected=False
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: routes are still present in ZEBRA\n Error: {}".format(
+ tc_name, result
+ )
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ logger.info("[Step 4] : Start BGPd daemon on R1 and R4..")
+
+ # Start BGPd daemon on R1
+ start_router_daemons(tgen, "r1", ["bgpd"])
+
+ # Start BGPd daemon on R4
+ start_router_daemons(tgen, "r4", ["bgpd"])
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_chaos_34_2_p1(request):
+ """
+ Test Objective : Restarting node doesn't preserve the forwarding
+ state verify the behaviour on helper node, if it still keeps the
+ stale routes.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ " Test Case : test_BGP_GR_chaos_34 "
+ "BGP GR "
+ "[Restart Mode]R1---R3[Helper Mode]"
+ )
+
+ logger.info("[Step 1] : Configure restarting" " router R1 to prevent ")
+ logger.info("[Step 2] : Reset the session" " between R1 and R3..")
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "graceful-restart": {"preserve-fw-state": True, "disable-eor": True},
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ },
+ }
+ },
+ "r3": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verify f-bit before killing BGPd daemon
+ result = verify_f_bit(tgen, topo, addr_type, input_dict, "r3", "r1")
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes after starting BGPd daemon
+ dut = "r3"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info("[Step 3] : Kill BGPd daemon on R1..")
+
+ # Kill BGPd daemon on R1
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ logger.info("[Step 4] : Withdraw/delete the prefixes " "originated from R1..")
+
+ # Api call to delete advertised networks
+ network = {"ipv4": "101.0.20.1/32", "ipv6": "1::1/128"}
+ for addr_type in ADDR_TYPES:
+ input_dict_2 = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ addr_type: {
+ "unicast": {
+ "advertise_networks": [
+ {
+ "network": network[addr_type],
+ "no_of_network": 5,
+ "delete": True,
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+
+ result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info("[Step 5] : Remove the CLI from R1's config to " "set the F-bit..")
+
+ # Modify graceful-restart config not to set f-bit
+ # and write to /etc/frr
+ input_dict_2 = {"r1": {"bgp": {"graceful-restart": {"preserve-fw-state": False}}}}
+
+ result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(tc_name, result)
+
+ logger.info("[Step 6] : Bring up the BGPd daemon on R1 again..")
+
+ # Start BGPd daemon on R1
+ start_router_daemons(tgen, "r1", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ # Verify f-bit after starting BGPd daemon
+ result = verify_f_bit(
+ tgen, topo, addr_type, input_dict, "r3", "r1", expected=False
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r3: F-bit is set to True\n Error: {}".format(
+ tc_name, result
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ # Verifying BGP RIB routes after starting BGPd daemon
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: routes are still present in BGP RIB\n Error: {}".format(
+ tc_name, result
+ )
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ # Verifying RIB routes
+ result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
+ logger.info(" Expected behavior: {}".format(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_gr_functionality_topo2/test_bgp_gr_functionality_topo2-3.py b/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-3.py
new file mode 100644
index 0000000000..86d676dd8b
--- /dev/null
+++ b/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-3.py
@@ -0,0 +1,1367 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2019 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 Graceful Restart functionality.
+Basic Common Test steps for all the test case below :
+- Create topology (setup module)
+ Creating 7 routers topology
+- Bring up topology
+- Verify for bgp to converge
+- Configure BGP Graceful Restart on both the routers.
+
+TC_1_2:
+ Verify that EOR message is sent out only after initial convergence
+ Verify whether EOR message is received from all the peers after restart
+TC_3:
+ Verify the selection deferral timer functionality when EOR is not sent
+ by the helper router
+TC_11:
+ Verify that selection-deferral timer sets the maximum time to
+ avoid deadlock during which the best-path
+TC_10:
+ Test Objective : Test GR scenarios on helper router by enabling
+ Graceful Restart for multiple address families.
+TC_15:
+ Test Objective : Test GR scenarios by enabling Graceful Restart
+ for multiple address families..
+TC_16:
+ Test Objective : Verify BGP-GR feature when restarting node
+ is a transit router for it's iBGP peers.
+TC_18:
+ Test Objective : Verify that GR helper router deletes stale routes
+ received from restarting node, if GR capability is not present in
+TC_19:
+ Test Objective : Verify that GR routers keeps all the routes
+ received from restarting node if both the routers are
+TC_26:
+ Test Objective : Test GR scenarios on helper router by enabling
+ Graceful Restart for multiple address families.
+TC_28:
+ Test Objective : Verify if helper node goes down before restarting
+ node comes up online, helper node sets the R-bit to avoid dead-lock
+TC_29:
+ Test Objective : Change timers on the fly, and
+ verify if it takes immediate effect.
+TC_33:
+ Test Objective : Helper router receives same prefixes from two
+ different routers (GR-restarting and GR-disabled). Keeps the
+TC_34_1:
+ Test Objective : Restarting node doesn't preserve forwarding
+ state, helper router should not keep the stale entries.
+TC_34_2:
+ Test Objective : Restarting node doesn't preserve the forwarding
+ state verify the behaviour on helper node, if it still keeps the
+TC_32:
+ Test Objective : Restarting node is connected to multiple helper
+ nodes, one of them doesn't send EOR to restarting router. Verify
+TC_37:
+ Test Objective : Verify if helper node restarts before sending the
+ EOR message, restarting node doesn't wait until stale path timer
+TC_30:
+ Test Objective : Restarting node removes stale routes from Zebra
+ after receiving an EOR from helper router.
+
+"""
+
+import os
+import sys
+import time
+import pytest
+from time import sleep
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join("../"))
+sys.path.append(os.path.join("../lib/"))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib.topogen import Topogen, get_topogen
+from lib.topolog import logger
+
+# Required to instantiate the topology builder class.
+
+# Import topoJson from lib, to create topology and initial configuration
+from lib.topojson import build_config_from_json
+from lib.bgp import (
+ clear_bgp,
+ verify_bgp_rib,
+ verify_graceful_restart,
+ create_router_bgp,
+ verify_r_bit,
+ verify_eor,
+ verify_f_bit,
+ verify_bgp_convergence,
+ verify_gr_address_family,
+ modify_bgp_config_when_bgpd_down,
+ verify_graceful_restart_timers,
+ verify_bgp_convergence_from_running_config,
+)
+
+from lib.common_config import (
+ write_test_header,
+ reset_config_on_routers,
+ start_topology,
+ kill_router_daemons,
+ start_router_daemons,
+ verify_rib,
+ check_address_types,
+ write_test_footer,
+ check_router_status,
+ step,
+ get_frr_ipv6_linklocal,
+ required_linux_kernel_version,
+)
+
+pytestmark = [pytest.mark.bgpd]
+
+
+# Global variables
+BGP_CONVERGENCE = False
+GR_RESTART_TIMER = 5
+GR_SELECT_DEFER_TIMER = 5
+GR_STALEPATH_TIMER = 5
+PREFERRED_NEXT_HOP = "link_local"
+NEXT_HOP_4 = ["192.168.1.1", "192.168.4.2"]
+NEXT_HOP_6 = ["fd00:0:0:1::1", "fd00:0:0:4::2"]
+
+
+def setup_module(mod):
+ """
+ Sets up the pytest environment
+
+ * `mod`: module name
+ """
+
+ # Required linux kernel version for this suite to run.
+ result = required_linux_kernel_version("4.16")
+ if result is not True:
+ pytest.skip("Kernel requirements are not met")
+
+ global ADDR_TYPES
+
+ 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...
+ json_file = "{}/bgp_gr_topojson_topo2.json".format(CWD)
+ tgen = Topogen(json_file, mod.__name__)
+ global topo
+ topo = tgen.json_topo
+ # ... 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)
+
+ # Api call verify whether BGP is converged
+ ADDR_TYPES = check_address_types()
+
+ for addr_type in ADDR_TYPES:
+ 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)
+
+
+def configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut, peer):
+ """
+ This function groups the repetitive function calls into one function.
+ """
+
+ logger.info("configure_gr_followed_by_clear: dut %s peer %s", dut, peer)
+
+ result = create_router_bgp(tgen, topo, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ neighbor = topo["routers"][peer]["links"][dut][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, dut, neighbor=neighbor)
+
+ for addr_type in ADDR_TYPES:
+ neighbor = topo["routers"][dut]["links"][peer][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, peer, neighbor=neighbor)
+
+ result = verify_bgp_convergence_from_running_config(tgen)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ return True
+
+
+def next_hop_per_address_family(tgen, dut, peer, addr_type, next_hop_dict):
+ """
+ This function returns link_local or global next_hop per address-family
+ """
+
+ intferface = topo["routers"][peer]["links"]["{}-link1".format(dut)]["interface"]
+ if addr_type == "ipv6" and "link_local" in PREFERRED_NEXT_HOP:
+ next_hop = get_frr_ipv6_linklocal(tgen, peer, intf=intferface)
+ else:
+ next_hop = next_hop_dict[addr_type]
+
+ return next_hop
+
+
+def test_BGP_GR_chaos_34_1_p1(request):
+ """
+ Test Objective : Restarting node doesn't preserve forwarding
+ state, helper router should not keep the stale entries.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ " Test Case : test_BGP_GR_chaos_31 "
+ "BGP GR "
+ "[Restart Mode]R1---R3[Helper Mode]"
+ )
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "graceful-restart": {
+ "preserve-fw-state": True,
+ "timer": {"restart-time": GR_RESTART_TIMER},
+ },
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ },
+ }
+ },
+ "r3": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes after starting BGPd daemon
+ dut = "r3"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info(
+ "[Step 1] : Remove the preserve-fw-state command"
+ " from restarting node R1's config"
+ )
+
+ # Configure graceful-restart to set f-bit as False
+ input_dict_2 = {"r1": {"bgp": {"graceful-restart": {"preserve-fw-state": False}}}}
+
+ result = create_router_bgp(tgen, topo, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ logger.info("[Step 2] : Reset the session between R1 and R3..")
+
+ # Reset sessions
+ for addr_type in ADDR_TYPES:
+ clear_bgp(tgen, addr_type, "r1")
+
+ result = verify_bgp_convergence_from_running_config(tgen, topo)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ # Verify f-bit after starting BGPd daemon
+ result = verify_f_bit(
+ tgen, topo, addr_type, input_dict_2, "r3", "r1", expected=False
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r3: F-bit is set to True\n Error: {}".format(
+ tc_name, result
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ logger.info("[Step 3] : Kill BGPd daemon on R1..")
+
+ # Kill BGPd daemon on R1
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ # Waiting for GR_RESTART_TIMER
+ logger.info("Waiting for {} sec..".format(GR_RESTART_TIMER))
+ sleep(GR_RESTART_TIMER)
+
+ for addr_type in ADDR_TYPES:
+ # Verifying BGP RIB routes
+ input_dict = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: routes are still present in BGP RIB\n Error: {}".format(
+ tc_name, result
+ )
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ # Verifying RIB routes
+ result = verify_rib(tgen, addr_type, dut, input_dict, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ # Start BGPd daemon on R1
+ start_router_daemons(tgen, "r1", ["bgpd"])
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_chaos_32_p1(request):
+ """
+ Test Objective : Restarting node is connected to multiple helper
+ nodes, one of them doesn't send EOR to restarting router. Verify
+ that only after SDT restarting node send EOR to all helper peers
+ excluding the prefixes originated by faulty router.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ " Test Case : test_BGP_GR_chaos_32 "
+ "BGP GR "
+ "[Restart Mode]R1---R3&R5[Helper Mode]"
+ )
+
+ logger.info(
+ "[Step 1] : Change the mode on R1 be a restarting" " node on global level"
+ )
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "graceful-restart": {"graceful-restart": True},
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r1": {"next_hop_self": True}}},
+ "r5": {"dest_link": {"r1": {"graceful-restart": True}}},
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r1": {"next_hop_self": True}}},
+ "r5": {"dest_link": {"r1": {"graceful-restart": True}}},
+ }
+ }
+ },
+ },
+ }
+ },
+ "r5": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r5": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r5": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r5")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r5"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes after starting BGPd daemon
+ dut = "r3"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r5"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info("[Step 2] : Kill BGPd daemon on R1..")
+ # Kill BGPd daemon on R1
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ logger.info("[Step 3] : Withdraw all the advertised prefixes from R5")
+
+ # Api call to delete advertised networks
+ network = {"ipv4": "105.0.20.1/32", "ipv6": "5::1/128"}
+ for addr_type in ADDR_TYPES:
+ input_dict_2 = {
+ "r5": {
+ "bgp": {
+ "address_family": {
+ addr_type: {
+ "unicast": {
+ "advertise_networks": [
+ {
+ "network": network[addr_type],
+ "no_of_network": 5,
+ "delete": True,
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ logger.info(
+ "[Step 4] : Stop the helper router R5 from sending EOR" " message using CLI"
+ )
+
+ # Modify graceful-restart config to prevent sending EOR
+ input_dict_3 = {"r5": {"bgp": {"graceful-restart": {"disable-eor": True}}}}
+
+ result = create_router_bgp(tgen, topo, input_dict_3)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ logger.info("[Step 5] : Bring up the BGPd daemon on R1..")
+
+ # Start BGPd daemon on R1
+ start_router_daemons(tgen, "r1", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ # Verify EOR is disabled
+ result = verify_eor(
+ tgen, topo, addr_type, input_dict_3, dut="r5", peer="r1", expected=False
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r5: EOR is set to TRUE\n Error: {}".format(
+ tc_name, result
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ # Verifying BGP RIB routes after starting BGPd daemon
+ input_dict_1 = {key: topo["routers"][key] for key in ["r5"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: routes are still present in BGP RIB\n Error: {}".format(
+ tc_name, result
+ )
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ # Verifying RIB routes
+ result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_chaos_37_p1(request):
+ """
+ Test Objective : Verify if helper node restarts before sending the
+ EOR message, restarting node doesn't wait until stale path timer
+ expiry to do the best path selection and sends an EOR
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ " Test Case : test_BGP_GR_chaos_37 "
+ "BGP GR "
+ "[Restart Mode]R1---R3[Helper Mode]"
+ )
+
+ logger.info(
+ "[Step 1] : Configure restarting router R3 to prevent " "sending an EOR.."
+ )
+
+ logger.info("[Step 2] : Reset the session between R3 and R1..")
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ }
+ }
+ },
+ "r3": {
+ "bgp": {
+ "graceful-restart": {"disable-eor": True},
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ },
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verify EOR is disabled
+ result = verify_eor(
+ tgen, topo, addr_type, input_dict, dut="r3", peer="r1", expected=False
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r3: EOR is set to True\n Error: {}".format(
+ tc_name, result
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ # Verifying BGP RIB routes after starting BGPd daemon
+ dut = "r1"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r3"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info("[Step 3] : Kill BGPd daemon on R1..")
+
+ # Kill BGPd daemon on R1
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ logger.info("[Step 4] : Start BGPd daemon on R1..")
+
+ # Start BGPd daemon on R1
+ start_router_daemons(tgen, "r1", ["bgpd"])
+
+ logger.info("[Step 5] : Kill BGPd daemon on R3..")
+
+ # Kill BGPd daemon on R3
+ kill_router_daemons(tgen, "r3", ["bgpd"])
+
+ # Modify graceful-restart config to prevent sending EOR
+ input_dict_2 = {"r3": {"bgp": {"graceful-restart": {"disable-eor": True}}}}
+
+ result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(tc_name, result)
+
+ logger.info("[Step 6] : Start BGPd daemon on R3..")
+
+ # Start BGPd daemon on R3
+ start_router_daemons(tgen, "r3", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ # Verify r_bit
+ result = verify_r_bit(tgen, topo, addr_type, input_dict, dut="r1", peer="r3")
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes
+ input_dict_1 = {key: topo["routers"][key] for key in ["r3"]}
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verify EOR is send from R1 to R3
+ input_dict_3 = {"r1": {"bgp": {"graceful-restart": {"disable-eor": True}}}}
+
+ result = verify_eor(
+ tgen, topo, addr_type, input_dict_3, dut="r1", peer="r3", expected=False
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: EOR is set to True\n Error: {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_chaos_30_p1(request):
+ """
+ Test Objective : Restarting node removes stale routes from Zebra
+ after receiving an EOR from helper router.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ " Test Case : test_BGP_GR_chaos_30 "
+ "BGP GR [Helper Mode]R3-----R1[Restart Mode] "
+ )
+
+ # Configure graceful-restart and timers
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "graceful-restart": {"preserve-fw-state": True},
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ },
+ }
+ },
+ "r3": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ # Verifying BGP RIB routes before shutting down BGPd daemon
+ dut = "r1"
+ input_dict = {key: topo["routers"][key] for key in ["r3"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ logger.info("[Step 2] : Kill BGPd daemon on R1..")
+
+ # Kill BGPd daemon on R1
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ logger.info("[Step 3] : Withdraw advertised prefixes from R3...")
+
+ # Api call to delete advertised networks
+ network = {"ipv4": "103.0.20.1/32", "ipv6": "3::1/128"}
+ for addr_type in ADDR_TYPES:
+ input_dict = {
+ "r3": {
+ "bgp": {
+ "address_family": {
+ addr_type: {
+ "unicast": {
+ "advertise_networks": [
+ {
+ "network": network[addr_type],
+ "no_of_network": 5,
+ "delete": True,
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ logger.info("[Step 4] : Start BGPd daemon on R1..")
+
+ # Start BGPd daemon on R1
+ start_router_daemons(tgen, "r1", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ # Verifying BGP RIB routes before shutting down BGPd daemon
+ input_dict = {key: topo["routers"][key] for key in ["r3"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r1: routes are still present in BGP RIB\n Error: {}".format(
+ tc_name, result
+ )
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_15_p2(request):
+ """
+ Test Objective : Test GR scenarios by enabling Graceful Restart
+ for multiple address families..
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r6": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r6": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ }
+ }
+ },
+ "r6": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r6": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r6": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r6")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r6"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ logger.info(
+ "[Step 2] : Test Setup "
+ "[Helper Mode]R6-----R1[Restart Mode]"
+ "--------R2[Helper Mode] Initilized"
+ )
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ }
+ }
+ },
+ "r2": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying BGP RIB routes
+ dut = "r6"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying BGP RIB routes
+ dut = "r6"
+ input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Kill BGPd daemon on R1
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ # Verifying BGP RIB routes
+ dut = "r6"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying BGP RIB routes
+ dut = "r6"
+ input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Start BGPd daemon on R1
+ start_router_daemons(tgen, "r1", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ result = verify_bgp_convergence(tgen, topo)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying BGP RIB routes
+ dut = "r6"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying BGP RIB routes
+ dut = "r6"
+ input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ write_test_footer(tc_name)
+
+
+def BGP_GR_TC_7_p1(request):
+ """
+ Verify that BGP restarting node deletes all the routes received from peer
+ if BGP Graceful capability is not present in BGP Open message from the
+ peer
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ " Verify route download to RIB: BGP_GR_TC_7 >> "
+ "BGP GR [Helper Mode]R3-----R1[Restart Mode] "
+ )
+
+ # Configure graceful-restart
+ input_dict = {
+ "r3": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ "r1": {
+ "bgp": {
+ "graceful-restart": {
+ "graceful-restart": True,
+ "preserve-fw-state": True,
+ },
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
+ }
+ }
+ },
+ },
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying BGP RIB routes received from router R1
+ dut = "r1"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r3"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ logger.info("R1 goes for reload")
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ # Change the configuration on router R1
+ input_dict_2 = {
+ "r3": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-disable": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-disable": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ # Change the configuration on R1
+ network = {"ipv4": "103.0.20.1/32", "ipv6": "3::1/128"}
+ for addr_type in ADDR_TYPES:
+ input_dict_2 = {
+ "r3": {
+ "bgp": {
+ "address_family": {
+ addr_type: {
+ "unicast": {
+ "advertise_networks": [
+ {
+ "network": network[addr_type],
+ "no_of_network": 5,
+ "delete": True,
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_2)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ logger.info("R1 is about to come up now")
+ start_router_daemons(tgen, "r1", ["bgpd"])
+ logger.info("R1 is UP Now")
+
+ # Wait for RIB stale timeout
+ logger.info("Verify routes are not present" "in restart router")
+
+ for addr_type in ADDR_TYPES:
+ # Verifying RIB routes
+ dut = "r1"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r3"]}
+ result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
+
+ write_test_footer(tc_name)
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-4.py b/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-4.py
new file mode 100644
index 0000000000..889f47f377
--- /dev/null
+++ b/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2-4.py
@@ -0,0 +1,1024 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2019 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 Graceful Restart functionality.
+Basic Common Test steps for all the test case below :
+- Create topology (setup module)
+ Creating 7 routers topology
+- Bring up topology
+- Verify for bgp to converge
+- Configure BGP Graceful Restart on both the routers.
+
+TC_1_2:
+ Verify that EOR message is sent out only after initial convergence
+ Verify whether EOR message is received from all the peers after restart
+TC_3:
+ Verify the selection deferral timer functionality when EOR is not sent
+ by the helper router
+TC_11:
+ Verify that selection-deferral timer sets the maximum time to
+ avoid deadlock during which the best-path
+TC_10:
+ Test Objective : Test GR scenarios on helper router by enabling
+ Graceful Restart for multiple address families.
+TC_15:
+ Test Objective : Test GR scenarios by enabling Graceful Restart
+ for multiple address families..
+TC_16:
+ Test Objective : Verify BGP-GR feature when restarting node
+ is a transit router for it's iBGP peers.
+TC_18:
+ Test Objective : Verify that GR helper router deletes stale routes
+ received from restarting node, if GR capability is not present in
+TC_19:
+ Test Objective : Verify that GR routers keeps all the routes
+ received from restarting node if both the routers are
+TC_26:
+ Test Objective : Test GR scenarios on helper router by enabling
+ Graceful Restart for multiple address families.
+TC_28:
+ Test Objective : Verify if helper node goes down before restarting
+ node comes up online, helper node sets the R-bit to avoid dead-lock
+TC_29:
+ Test Objective : Change timers on the fly, and
+ verify if it takes immediate effect.
+TC_33:
+ Test Objective : Helper router receives same prefixes from two
+ different routers (GR-restarting and GR-disabled). Keeps the
+TC_34_1:
+ Test Objective : Restarting node doesn't preserve forwarding
+ state, helper router should not keep the stale entries.
+TC_34_2:
+ Test Objective : Restarting node doesn't preserve the forwarding
+ state verify the behaviour on helper node, if it still keeps the
+TC_32:
+ Test Objective : Restarting node is connected to multiple helper
+ nodes, one of them doesn't send EOR to restarting router. Verify
+TC_37:
+ Test Objective : Verify if helper node restarts before sending the
+ EOR message, restarting node doesn't wait until stale path timer
+TC_30:
+ Test Objective : Restarting node removes stale routes from Zebra
+ after receiving an EOR from helper router.
+
+These tests have been broken up into 4 sub python scripts because
+the totality of run time for this script was greater than 10 minutes
+"""
+
+import os
+import sys
+import time
+import pytest
+from time import sleep
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join("../"))
+sys.path.append(os.path.join("../lib/"))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib.topogen import Topogen, get_topogen
+from lib.topolog import logger
+
+# Required to instantiate the topology builder class.
+
+# Import topoJson from lib, to create topology and initial configuration
+from lib.topojson import build_config_from_json
+from lib.bgp import (
+ clear_bgp,
+ verify_bgp_rib,
+ verify_graceful_restart,
+ create_router_bgp,
+ verify_r_bit,
+ verify_eor,
+ verify_f_bit,
+ verify_bgp_convergence,
+ verify_gr_address_family,
+ modify_bgp_config_when_bgpd_down,
+ verify_graceful_restart_timers,
+ verify_bgp_convergence_from_running_config,
+)
+
+from lib.common_config import (
+ write_test_header,
+ reset_config_on_routers,
+ start_topology,
+ kill_router_daemons,
+ start_router_daemons,
+ verify_rib,
+ check_address_types,
+ write_test_footer,
+ check_router_status,
+ step,
+ get_frr_ipv6_linklocal,
+ required_linux_kernel_version,
+)
+
+pytestmark = [pytest.mark.bgpd]
+
+
+# Global variables
+BGP_CONVERGENCE = False
+GR_RESTART_TIMER = 5
+GR_SELECT_DEFER_TIMER = 5
+GR_STALEPATH_TIMER = 5
+PREFERRED_NEXT_HOP = "link_local"
+NEXT_HOP_4 = ["192.168.1.1", "192.168.4.2"]
+NEXT_HOP_6 = ["fd00:0:0:1::1", "fd00:0:0:4::2"]
+
+
+def setup_module(mod):
+ """
+ Sets up the pytest environment
+
+ * `mod`: module name
+ """
+
+ # Required linux kernel version for this suite to run.
+ result = required_linux_kernel_version("4.16")
+ if result is not True:
+ pytest.skip("Kernel requirements are not met")
+
+ global ADDR_TYPES
+
+ 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...
+ json_file = "{}/bgp_gr_topojson_topo2.json".format(CWD)
+ tgen = Topogen(json_file, mod.__name__)
+ global topo
+ topo = tgen.json_topo
+ # ... 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)
+
+ # Api call verify whether BGP is converged
+ ADDR_TYPES = check_address_types()
+
+ for addr_type in ADDR_TYPES:
+ 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)
+
+
+def configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut, peer):
+ """
+ This function groups the repetitive function calls into one function.
+ """
+
+ logger.info("configure_gr_followed_by_clear: dut %s peer %s", dut, peer)
+
+ result = create_router_bgp(tgen, topo, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ neighbor = topo["routers"][peer]["links"][dut][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, dut, neighbor=neighbor)
+
+ for addr_type in ADDR_TYPES:
+ neighbor = topo["routers"][dut]["links"][peer][addr_type].split("/")[0]
+ clear_bgp(tgen, addr_type, peer, neighbor=neighbor)
+
+ result = verify_bgp_convergence_from_running_config(tgen)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ return True
+
+
+def next_hop_per_address_family(tgen, dut, peer, addr_type, next_hop_dict):
+ """
+ This function returns link_local or global next_hop per address-family
+ """
+
+ intferface = topo["routers"][peer]["links"]["{}-link1".format(dut)]["interface"]
+ if addr_type == "ipv6" and "link_local" in PREFERRED_NEXT_HOP:
+ next_hop = get_frr_ipv6_linklocal(tgen, peer, intf=intferface)
+ else:
+ next_hop = next_hop_dict[addr_type]
+
+ return next_hop
+
+
+def test_BGP_GR_TC_23_p1(request):
+ """
+ Verify that helper routers are deleting stale routes after stale route
+ timer's expiry. If all the routes are not received from restating node
+ after restart.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ "Verify Stale Routes are deleted on helper: BGP_GR_TC_23 >> "
+ "BGP GR [Helper Mode]R1-----R2[Restart Mode] "
+ )
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "graceful-restart": {"timer": {"stalepath-time": GR_STALEPATH_TIMER}},
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ },
+ }
+ },
+ "r2": {
+ "bgp": {
+ "graceful-restart": {
+ "graceful-restart": True,
+ "preserve-fw-state": True,
+ },
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {"dest_link": {"r2": {"graceful-restart": True}}}
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {"dest_link": {"r2": {"graceful-restart": True}}}
+ }
+ }
+ },
+ },
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying BGP RIB routes received from router R1
+ dut = "r1"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ logger.info("R2 goes for reload")
+ kill_router_daemons(tgen, "r2", ["bgpd"])
+
+ # Modify configuration to delete routes and include disable-eor
+ input_dict_3 = {"r2": {"bgp": {"graceful-restart": {"disable-eor": True}}}}
+
+ result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_3)
+
+ # Modify configuration to delete routes and include disable-eor
+ network = {"ipv4": "102.0.20.1/32", "ipv6": "2::1/128"}
+ for addr_type in ADDR_TYPES:
+ input_dict_3 = {
+ "r2": {
+ "bgp": {
+ "address_family": {
+ addr_type: {
+ "unicast": {
+ "advertise_networks": [
+ {
+ "network": network[addr_type],
+ "no_of_network": 3,
+ "delete": True,
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+
+ result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_3)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ logger.info("BGPd comes up for r2")
+ start_router_daemons(tgen, "r2", ["bgpd"])
+
+ # Wait for stalepath timer
+ logger.info("Waiting for stalepath timer({} sec..)".format(GR_STALEPATH_TIMER))
+ sleep(GR_STALEPATH_TIMER)
+
+ for addr_type in ADDR_TYPES:
+ clear_bgp(tgen, addr_type, "r2")
+
+ # Verifying RIB routes
+ dut = "r1"
+ network = {"ipv4": "102.0.20.4/32", "ipv6": "2::4/128"}
+ for addr_type in ADDR_TYPES:
+ input_dict_1 = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ addr_type: {
+ "unicast": {
+ "advertise_networks": [
+ {"network": network[addr_type], "no_of_network": 2}
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+
+ # Verify EOR on helper router
+ result = verify_eor(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2", expected=False
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "r1: EOR is set to True\n Error: {}".format(
+ tc_name, result
+ )
+
+ # Verifying BGP RIB routes received from router R1
+ dut = "r1"
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_20_p1(request):
+ """
+ Test Objective : Verify that GR routers delete all the routes
+ received from a node if both the routers are configured as GR
+ helper node
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ "[Step 1] : Test Setup " "[Restart Mode]R3-----R1[Restart Mode] Initilized"
+ )
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ "r3": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying BGP RIB routes
+ dut = "r3"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Kill BGPd daemon on R1
+ kill_router_daemons(tgen, "r1", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ # Verifying BGP RIB routes
+ dut = "r3"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: routes are still present in BGP RIB\n Error: {}".format(
+ tc_name, result
+ )
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ )
+ logger.info(" Expected behavior: {}".format(result))
+
+ # Start BGPd daemon on R1
+ start_router_daemons(tgen, "r1", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ result = verify_bgp_convergence(tgen, topo)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying BGP RIB routes
+ dut = "r3"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_21_p2(request):
+ """
+ Test Objective : VVerify BGP-GR feature when helper node is
+ a transit router for it's eBGP peers.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ "[Step 1] : Test Setup " "[Helper Mode]R6-----R1[Restart Mode] Initilized"
+ )
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r6": {
+ "dest_link": {
+ "r1": {"graceful-restart-disable": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r6": {
+ "dest_link": {
+ "r1": {"graceful-restart-disable": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ "r6": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r6": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r6": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r6")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r6"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ logger.info(
+ "[Step 2] : Test Setup "
+ "[Restart Mode]R2-----[Helper Mode]R1[Disable Mode]"
+ "--------R6[Helper Mode] Initilized"
+ )
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ "r2": {
+ "bgp": {
+ "graceful-restart": {
+ "graceful-restart": True,
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying BGP RIB routes
+ dut = "r6"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying BGP RIB routes
+ dut = "r6"
+ input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Kill BGPd daemon on R1
+ kill_router_daemons(tgen, "r2", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ # Verifying BGP RIB routes
+ dut = "r6"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying BGP RIB routes
+ dut = "r6"
+ input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Start BGPd daemon on R1
+ start_router_daemons(tgen, "r2", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ result = verify_bgp_convergence(tgen, topo)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying BGP RIB routes
+ dut = "r6"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes after bringing up BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying BGP RIB routes
+ dut = "r6"
+ input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ write_test_footer(tc_name)
+
+
+def test_BGP_GR_22_p2(request):
+ """
+ Test Objective : Verify BGP-GR feature when helper node
+ is a transit router for it's iBGP peers.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Check router status
+ check_router_status(tgen)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ logger.info(
+ "[Step 1] : Test Setup " "[Helper Mode]R3-----R1[Restart Mode] Initilized"
+ )
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1": {
+ "graceful-restart-disable": True,
+ "next_hop_self": True,
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1": {
+ "graceful-restart-disable": True,
+ "next_hop_self": True,
+ }
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ "r3": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ logger.info(
+ "[Step 2] : Test Setup "
+ "[Restart Mode]R2-----[Helper Mode]R1[Disable Mode]"
+ "--------R3[Helper Mode] Initilized"
+ )
+
+ # Configure graceful-restart
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1": {"graceful-restart-helper": True}
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ },
+ "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
+ }
+
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
+
+ for addr_type in ADDR_TYPES:
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying BGP RIB routes
+ dut = "r3"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying BGP RIB routes
+ dut = "r3"
+ input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Kill BGPd daemon on R1
+ kill_router_daemons(tgen, "r2", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ # Verifying BGP RIB routes
+ dut = "r3"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying BGP RIB routes
+ dut = "r3"
+ input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Start BGPd daemon on R1
+ start_router_daemons(tgen, "r2", ["bgpd"])
+
+ for addr_type in ADDR_TYPES:
+ result = verify_bgp_convergence(tgen, topo)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying BGP RIB routes
+ dut = "r3"
+ input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying BGP RIB routes
+ dut = "r3"
+ input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
+ result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ # Verifying RIB routes before shutting down BGPd daemon
+ result = verify_rib(tgen, addr_type, dut, input_dict_2)
+ 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_gr_functionality_topo2/test_bgp_gr_functionality_topo2.py b/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2.py
deleted file mode 100644
index 52ad7813c5..0000000000
--- a/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2.py
+++ /dev/null
@@ -1,4358 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (c) 2019 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 Graceful Restart functionality.
-Basic Common Test steps for all the test case below :
-- Create topology (setup module)
- Creating 7 routers topology
-- Bring up topology
-- Verify for bgp to converge
-- Configure BGP Graceful Restart on both the routers.
-
-TC_1_2:
- Verify that EOR message is sent out only after initial convergence
- Verify whether EOR message is received from all the peers after restart
-TC_3:
- Verify the selection deferral timer functionality when EOR is not sent
- by the helper router
-TC_11:
- Verify that selection-deferral timer sets the maximum time to
- avoid deadlock during which the best-path
-TC_10:
- Test Objective : Test GR scenarios on helper router by enabling
- Graceful Restart for multiple address families.
-TC_15:
- Test Objective : Test GR scenarios by enabling Graceful Restart
- for multiple address families..
-TC_16:
- Test Objective : Verify BGP-GR feature when restarting node
- is a transit router for it's iBGP peers.
-TC_18:
- Test Objective : Verify that GR helper router deletes stale routes
- received from restarting node, if GR capability is not present in
-TC_19:
- Test Objective : Verify that GR routers keeps all the routes
- received from restarting node if both the routers are
-TC_26:
- Test Objective : Test GR scenarios on helper router by enabling
- Graceful Restart for multiple address families.
-TC_28:
- Test Objective : Verify if helper node goes down before restarting
- node comes up online, helper node sets the R-bit to avoid dead-lock
-TC_29:
- Test Objective : Change timers on the fly, and
- verify if it takes immediate effect.
-TC_33:
- Test Objective : Helper router receives same prefixes from two
- different routers (GR-restarting and GR-disabled). Keeps the
-TC_34_1:
- Test Objective : Restarting node doesn't preserve forwarding
- state, helper router should not keep the stale entries.
-TC_34_2:
- Test Objective : Restarting node doesn't preserve the forwarding
- state verify the behaviour on helper node, if it still keeps the
-TC_32:
- Test Objective : Restarting node is connected to multiple helper
- nodes, one of them doesn't send EOR to restarting router. Verify
-TC_37:
- Test Objective : Verify if helper node restarts before sending the
- EOR message, restarting node doesn't wait until stale path timer
-TC_30:
- Test Objective : Restarting node removes stale routes from Zebra
- after receiving an EOR from helper router.
-
-"""
-
-import os
-import sys
-import time
-import pytest
-from time import sleep
-
-# Save the Current Working Directory to find configuration files.
-CWD = os.path.dirname(os.path.realpath(__file__))
-sys.path.append(os.path.join("../"))
-sys.path.append(os.path.join("../lib/"))
-
-# pylint: disable=C0413
-# Import topogen and topotest helpers
-from lib.topogen import Topogen, get_topogen
-from lib.topolog import logger
-
-# Required to instantiate the topology builder class.
-
-# Import topoJson from lib, to create topology and initial configuration
-from lib.topojson import build_config_from_json
-from lib.bgp import (
- clear_bgp,
- verify_bgp_rib,
- verify_graceful_restart,
- create_router_bgp,
- verify_r_bit,
- verify_eor,
- verify_f_bit,
- verify_bgp_convergence,
- verify_gr_address_family,
- modify_bgp_config_when_bgpd_down,
- verify_graceful_restart_timers,
- verify_bgp_convergence_from_running_config,
-)
-
-from lib.common_config import (
- write_test_header,
- reset_config_on_routers,
- start_topology,
- kill_router_daemons,
- start_router_daemons,
- verify_rib,
- check_address_types,
- write_test_footer,
- check_router_status,
- step,
- get_frr_ipv6_linklocal,
- required_linux_kernel_version,
-)
-
-pytestmark = [pytest.mark.bgpd]
-
-
-# Global variables
-BGP_CONVERGENCE = False
-GR_RESTART_TIMER = 5
-GR_SELECT_DEFER_TIMER = 5
-GR_STALEPATH_TIMER = 5
-PREFERRED_NEXT_HOP = "link_local"
-NEXT_HOP_4 = ["192.168.1.1", "192.168.4.2"]
-NEXT_HOP_6 = ["fd00:0:0:1::1", "fd00:0:0:4::2"]
-
-
-def setup_module(mod):
- """
- Sets up the pytest environment
-
- * `mod`: module name
- """
-
- # Required linux kernel version for this suite to run.
- result = required_linux_kernel_version("4.16")
- if result is not True:
- pytest.skip("Kernel requirements are not met")
-
- global ADDR_TYPES
-
- 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...
- json_file = "{}/bgp_gr_topojson_topo2.json".format(CWD)
- tgen = Topogen(json_file, mod.__name__)
- global topo
- topo = tgen.json_topo
- # ... 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)
-
- # Api call verify whether BGP is converged
- ADDR_TYPES = check_address_types()
-
- for addr_type in ADDR_TYPES:
- 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)
-
-
-def configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut, peer):
- """
- This function groups the repetitive function calls into one function.
- """
-
- logger.info("configure_gr_followed_by_clear: dut %s peer %s", dut, peer)
-
- result = create_router_bgp(tgen, topo, input_dict)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
-
- for addr_type in ADDR_TYPES:
- neighbor = topo["routers"][peer]["links"][dut][addr_type].split("/")[0]
- clear_bgp(tgen, addr_type, dut, neighbor=neighbor)
-
- for addr_type in ADDR_TYPES:
- neighbor = topo["routers"][dut]["links"][peer][addr_type].split("/")[0]
- clear_bgp(tgen, addr_type, peer, neighbor=neighbor)
-
- result = verify_bgp_convergence_from_running_config(tgen)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
-
- return True
-
-
-def next_hop_per_address_family(tgen, dut, peer, addr_type, next_hop_dict):
- """
- This function returns link_local or global next_hop per address-family
- """
-
- intferface = topo["routers"][peer]["links"]["{}-link1".format(dut)]["interface"]
- if addr_type == "ipv6" and "link_local" in PREFERRED_NEXT_HOP:
- next_hop = get_frr_ipv6_linklocal(tgen, peer, intf=intferface)
- else:
- next_hop = next_hop_dict[addr_type]
-
- return next_hop
-
-
-def test_BGP_GR_TC_1_2_p0(request):
- """
- Verify that EOR message is sent out only after initial convergence
- Verify whether EOR message is received from all the peers after restart
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- "Verify EOR Sent and Received : BGP_GR_TC_1_2 >> "
- "BGP GR [Helper Mode]R3-----R1[Restart Mode] "
- )
-
- # Configure graceful-restart
- input_dict = {
- "r3": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- "r1": {
- "bgp": {
- "graceful-restart": {
- "graceful-restart": True,
- "preserve-fw-state": True,
- },
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- },
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes received from router R3
- dut = "r1"
- input_dict_1 = {key: topo["routers"][key] for key in ["r3"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info("R1 goes for reload")
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- # Verifying RIB routes
- input_dict_1 = {key: topo["routers"][key] for key in ["r3"]}
- # Verifying RIB routes
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info("Starting bgpd process")
- start_router_daemons(tgen, "r1", ["bgpd"])
- logger.info("R1 is UP Now")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes received from router R3
- input_dict_1 = {key: topo["routers"][key] for key in ["r3"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying EOR on restarting router
- result = verify_eor(tgen, topo, addr_type, input_dict, dut="r3", peer="r1")
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_TC_3_p0(request):
- """
- Verify the selection deferral timer functionality when EOR is not sent
- by the helper router
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- " Verify route download to RIB: BGP_GR_TC_3 >> "
- "BGP GR [Helper Mode]R1-----R2[Restart Mode] "
- )
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "graceful-restart": {
- "disable-eor": True,
- },
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- },
- }
- },
- "r2": {
- "bgp": {
- "graceful-restart": {
- "graceful-restart": True,
- "preserve-fw-state": True,
- "timer": {"select-defer-time": GR_SELECT_DEFER_TIMER},
- },
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {"dest_link": {"r2": {"graceful-restart": True}}}
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {"dest_link": {"r2": {"graceful-restart": True}}}
- }
- }
- },
- },
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes received from router R1
- dut = "r2"
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info("R2 goes for reload ")
- kill_router_daemons(tgen, "r2", ["bgpd"])
-
- logger.info("R2 is about to come up now")
- start_router_daemons(tgen, "r2", ["bgpd"])
- logger.info("R2 is UP Now")
-
- for addr_type in ADDR_TYPES:
- # Verifying BGP RIB routes received from router R1
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verify EOR on restarting router
- result = verify_eor(
- tgen, topo, addr_type, input_dict, dut="r2", peer="r1", expected=False
- )
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r2: EOR is set to True\n Error: {}".format(
- tc_name, result
- )
-
- logger.info(
- "Waiting for selection deferral timer({} sec)..".format(GR_SELECT_DEFER_TIMER)
- )
- sleep(GR_SELECT_DEFER_TIMER)
-
- for addr_type in ADDR_TYPES:
- # Verifying RIB routes
- result = verify_rib(tgen, addr_type, "r2", input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_TC_11_p0(request):
- """
- Verify that selection-deferral timer sets the maximum time to
- avoid deadlock during which the best-path
- selection process is deferred, after a peer session was restarted
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info("Verify EOR Sent after deferral timeout : BGP_GR_TC_11")
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "graceful-restart": {
- "graceful-restart": True,
- "select-defer-time": GR_SELECT_DEFER_TIMER,
- },
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {"dest_link": {"r1": {"graceful-restart": True}}},
- "r3": {"dest_link": {"r1": {"graceful-restart": True}}},
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {"dest_link": {"r1": {"graceful-restart": True}}},
- "r3": {"dest_link": {"r1": {"graceful-restart": True}}},
- }
- }
- },
- },
- }
- },
- "r3": {
- "bgp": {
- "graceful-restart": {"disable-eor": True},
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- },
- }
- },
- }
-
- result = create_router_bgp(tgen, topo, input_dict)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
-
- for addr_type in ADDR_TYPES:
- clear_bgp(tgen, addr_type, "r1")
- clear_bgp(tgen, addr_type, "r3")
-
- result = verify_bgp_convergence_from_running_config(tgen, topo)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes received from router R1
- dut = "r1"
- input_dict_1 = {key: topo["routers"][key] for key in ["r3"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info("R1 goes for reload")
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- logger.info("Starting bgpd process")
- start_router_daemons(tgen, "r1", ["bgpd"])
- logger.info("R1 is UP Now")
-
- for addr_type in ADDR_TYPES:
- # Verify EOR on restarting router
- result = verify_eor(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r3", expected=False
- )
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r1: EOR is set to True\n Error: {}".format(
- tc_name, result
- )
-
- logger.info(
- "Waiting for selection deferral timer({} sec).. ".format(
- GR_SELECT_DEFER_TIMER + 2
- )
- )
- sleep(GR_SELECT_DEFER_TIMER + 2)
-
- for addr_type in ADDR_TYPES:
- # Verifying BGP RIB routes received from router R1
- input_dict_1 = {key: topo["routers"][key] for key in ["r3"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying EOR on restarting router
- result = verify_eor(
- tgen, topo, addr_type, input_dict, dut="r3", peer="r1", expected=False
- )
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r3: EOR is set to True\n Error: {}".format(
- tc_name, result
- )
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_10_p2(request):
- """
- Test Objective : Test GR scenarios on helper router by enabling
- Graceful Restart for multiple address families.
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- step("Test Setup: [Helper Mode]R3-----R1[Restart Mode] initialized")
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r3": {
- "dest_link": {
- "r1": {
- "next_hop_self": True,
- "graceful-restart": True,
- "activate": "ipv6",
- }
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r3": {
- "dest_link": {
- "r1": {
- "next_hop_self": True,
- "graceful-restart": True,
- "activate": "ipv4",
- }
- }
- }
- }
- }
- },
- }
- }
- },
- "r3": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {
- "graceful-restart-helper": True,
- "activate": "ipv6",
- }
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {
- "graceful-restart-helper": True,
- "activate": "ipv4",
- }
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
-
- for addr_type in ADDR_TYPES:
- step(
- "Verifying GR config and operational state for addr_type {}".format(
- addr_type
- )
- )
-
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes
- dut = "r3"
- input_topo = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_topo)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # verify multi address family
- result = verify_gr_address_family(
- tgen,
- topo,
- addr_type,
- "ipv4Unicast",
- dut="r1",
- peer="r3",
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # verify multi address family
- result = verify_gr_address_family(
- tgen,
- topo,
- addr_type,
- "ipv6Unicast",
- dut="r1",
- peer="r3",
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # verify multi address family
- result = verify_gr_address_family(
- tgen,
- topo,
- addr_type,
- "ipv4Unicast",
- dut="r3",
- peer="r1",
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # verify multi address family
- result = verify_gr_address_family(
- tgen,
- topo,
- addr_type,
- "ipv6Unicast",
- dut="r3",
- peer="r1",
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- step("Killing bgpd on r1")
-
- # Kill BGPd daemon on R1
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- # Verifying BGP RIB routes
- input_topo = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_topo)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- step("Starting bgpd on r1")
-
- # Start BGPd daemon on R1
- start_router_daemons(tgen, "r1", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- # Verifying BGP RIB routes
- input_topo = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_topo)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- write_test_footer(tc_name)
-
-
-def BGP_GR_16_p2(request):
- """
- Test Objective : Verify BGP-GR feature when restarting node
- is a transit router for it's iBGP peers.
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- "[Step 1] : Test Setup " "[Helper Mode]R3-----R1[Restart Mode] initialized"
- )
-
- # Configure graceful-restart and timers
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r3": {
- "dest_link": {
- "r1": {
- "graceful-restart": True,
- "next_hop_self": True,
- }
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r3": {
- "dest_link": {
- "r1": {
- "graceful-restart": True,
- "next_hop_self": True,
- }
- }
- }
- }
- }
- },
- }
- }
- },
- "r3": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info(
- "[Step 2] : Test Setup "
- "[Helper Mode]R3-----R1[Restart Mode]"
- "--------R6[Helper Mode] initialized"
- )
-
- # Configure graceful-restart and timers
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- }
- }
- },
- "r2": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r2": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r2": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes
- dut = "r3"
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes
- input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Kill BGPd daemon on R1
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- # Verifying BGP RIB routes
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes
- input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Start BGPd daemon on R1
- start_router_daemons(tgen, "r1", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- # Verifying BGP RIB routes
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes
- input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_bgp_convergence_from_running_config(tgen, topo)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_18_p1(request):
- """
- Test Objective : Verify that GR helper router deletes stale routes
- received from restarting node, if GR capability is not present in
- restarting node's OPEN message.
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- "[Step 1] : Test Setup " "[Helper Mode]R6-----R1[Restart Mode] initialized"
- )
-
- # Configure graceful-restart and timers
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r6": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r6": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- }
- }
- },
- "r6": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r6": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r6": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r6")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r6"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info(
- "[Step 2] : Test Setup "
- "[Helper Mode]R6-----R1[Restart Mode]"
- "--------R2[Helper Mode] initialized"
- )
-
- # Configure graceful-restart and timers
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- }
- }
- },
- "r2": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r2": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r2": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes
- dut = "r6"
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes
- dut = "r2"
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Kill BGPd daemon on R1
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- logger.info("[Step 3] : Configure R1 to prevent sending EOR")
-
- # Modify graceful-restart config to prevent sending EOR
- input_dict_3 = {"r1": {"bgp": {"graceful-restart": {"disable-eor": True}}}}
-
- result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_3)
-
- # Modify configuration to delete routes
- network = {"ipv4": "101.0.20.1/32", "ipv6": "1::1/128"}
- for addr_type in ADDR_TYPES:
- input_dict_3 = {
- "r1": {
- "bgp": {
- "address_family": {
- addr_type: {
- "unicast": {
- "advertise_networks": [
- {
- "network": network[addr_type],
- "no_of_network": 5,
- "delete": True,
- }
- ]
- }
- }
- }
- }
- }
- }
-
- result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_3)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Modify graceful-restart config
- input_dict_3 = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1": {"graceful-restart-disable": True}
- }
- },
- "r6": {
- "dest_link": {
- "r1": {"graceful-restart-disable": True}
- }
- },
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1": {"graceful-restart-disable": True}
- }
- },
- "r6": {
- "dest_link": {
- "r1": {"graceful-restart-disable": True}
- }
- },
- }
- }
- },
- }
- }
- }
- }
-
- result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_3)
- assert result is True, "Testcase {} : Failed \n Error {}".format(tc_name, result)
-
- logger.info("[Step 4] : Bring up the BGPd daemon on R1 for 30" " seconds..")
-
- # Start BGPd daemon on R1
- start_router_daemons(tgen, "r1", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- # Verifying BGP RIB routes
- dut = "r6"
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r6: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
- )
- logger.info(" Expected behavior: {}".format(result))
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r6: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
- )
- logger.info(" Expected behavior: {}".format(result))
-
- # Verifying BGP RIB routes
- dut = "r2"
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r2: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
- )
- logger.info(" Expected behavior: {}".format(result))
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r6: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
- )
- logger.info(" Expected behavior: {}".format(result))
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_26_p2(request):
- """
- Test Objective : Test GR scenarios on helper router by enabling
- Graceful Restart for multiple address families.
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- "[Step 1] : Test Setup " "[Helper Mode]R3-----R1[Restart Mode] initialized"
- )
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r3": {
- "dest_link": {
- "r1": {
- "graceful-restart": True,
- "next_hop_self": True,
- "activate": "ipv6",
- }
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r3": {
- "dest_link": {
- "r1": {
- "graceful-restart": True,
- "next_hop_self": True,
- "activate": "ipv4",
- }
- }
- }
- }
- }
- },
- }
- }
- },
- "r3": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {
- "graceful-restart-helper": True,
- "activate": "ipv6",
- }
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {
- "graceful-restart-helper": True,
- "activate": "ipv4",
- }
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r3", peer="r1"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes
- dut = "r3"
- input_topo = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_topo)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Kill BGPd daemon on R1
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- # Verifying BGP RIB routes
- input_topo = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_topo)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Start BGPd daemon on R1
- start_router_daemons(tgen, "r1", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- # Verifying BGP RIB routes
- input_topo = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_topo)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_topo)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # verify multi address family
- result = verify_gr_address_family(
- tgen,
- topo,
- addr_type,
- "ipv4Unicast",
- dut="r1",
- peer="r3",
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # verify multi address family
- result = verify_gr_address_family(
- tgen,
- topo,
- addr_type,
- "ipv6Unicast",
- dut="r1",
- peer="r3",
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # verify multi address family
- result = verify_gr_address_family(
- tgen,
- topo,
- addr_type,
- "ipv4Unicast",
- dut="r3",
- peer="r1",
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # verify multi address family
- result = verify_gr_address_family(
- tgen,
- topo,
- addr_type,
- "ipv6Unicast",
- dut="r3",
- peer="r1",
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_chaos_28_p1(request):
- """
- Test Objective : Verify if helper node goes down before restarting
- node comes up online, helper node sets the R-bit to avoid dead-lock
- till SDT expiry.
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- "Test Case: test_BGP_GR_chaos_28 :"
- "[Helper Mode]R3-----R1[Restart Mode] initialized"
- )
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- }
- }
- },
- "r3": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info("[Step 1] : Kill BGPd daemon on R1..")
-
- # Kill BGPd daemon on R1
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- logger.info("[Step 2] : Kill BGPd daemon on R3..")
-
- # Kill BGPd daemon on R3
- kill_router_daemons(tgen, "r3", ["bgpd"])
-
- logger.info("[Step 3] : Start BGPd daemon on R1..")
-
- # Start BGPd daemon on R1
- start_router_daemons(tgen, "r1", ["bgpd"])
-
- logger.info("[Step 4] : Start BGPd daemon on R3..")
-
- # Start BGPd daemon on R3
- start_router_daemons(tgen, "r3", ["bgpd"])
-
- # Verify r_bit
- for addr_type in ADDR_TYPES:
- result = verify_r_bit(tgen, topo, addr_type, input_dict, dut="r3", peer="r1")
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_chaos_29_p1(request):
- """
- Test Objective : Change timers on the fly, and
- verify if it takes immediate effect.
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- " Test Case : test_BGP_GR_chaos_29"
- " BGP GR [Helper Mode]R3-----R1[Restart Mode]"
- " and [restart-time 150]R1 initialized"
- )
-
- # Configure graceful-restart and timers
- input_dict = {
- "r1": {
- "bgp": {
- "graceful-restart": {"timer": {"restart-time": GR_RESTART_TIMER}},
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- },
- }
- },
- "r3": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verify graceful-restart timers
- input_dict_2 = {
- "r1": {
- "bgp": {
- "graceful-restart": {"timer": {"restart-time": GR_RESTART_TIMER + 5}}
- }
- }
- }
-
- result = create_router_bgp(tgen, topo, input_dict_2)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
-
- for addr_type in ADDR_TYPES:
- input_dict_2 = {
- "r1": {
- "bgp": {
- "graceful-restart": {"timer": {"restart-time": GR_RESTART_TIMER}}
- }
- }
- }
-
- result = verify_graceful_restart_timers(
- tgen, topo, addr_type, input_dict_2, dut="r3", peer="r1"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- for addr_type in ADDR_TYPES:
- # Verifying BGP RIB routes before shutting down BGPd daemon
- dut = "r3"
- input_dict = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info("[Step 2] : Kill BGPd daemon on R1..")
-
- # Kill BGPd daemon on R1
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- logger.info("[Step 3] : Wait for {} seconds..".format(GR_RESTART_TIMER))
-
- # Waiting for GR_RESTART_TIMER
- sleep(GR_RESTART_TIMER)
-
- for addr_type in ADDR_TYPES:
- # Verifying BGP RIB routes before shutting down BGPd daemon
- input_dict = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r3: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
- )
- logger.info(" Expected behavior: {}".format(result))
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
- )
- logger.info(" Expected behavior: {}".format(result))
-
- logger.info("[Step 4] : Start BGPd daemon on R1..")
-
- # Start BGPd daemon on R1
- start_router_daemons(tgen, "r1", ["bgpd"])
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_chaos_33_p1(request):
- """
- Test Objective : Helper router receives same prefixes from two
- different routers (GR-restarting and GR-disabled). Keeps the
- stale entry only for GR-restarting node(next-hop is correct).
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- " Test Case : test_BGP_GR_chaos_33 "
- "BGP GR "
- "[Restart Mode]R1--R3[Helper Mode]--R4[Disabled Mode]"
- )
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- }
- }
- },
- "r3": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- "r4": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r3": {
- "dest_link": {
- "r4": {"graceful-restart-disable": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r3": {
- "dest_link": {
- "r4": {"graceful-restart-disable": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info("[Step 2] : Advertise same networks from R1 and R4..")
-
- # Api call to delete advertised networks
- input_dict_2 = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "advertise_networks": [
- {
- "network": "200.0.20.1/32",
- "no_of_network": 2,
- }
- ]
- }
- },
- "ipv6": {
- "unicast": {
- "advertise_networks": [
- {"network": "2001::1/128", "no_of_network": 2}
- ]
- }
- },
- }
- }
- },
- "r4": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "advertise_networks": [
- {"network": "200.0.20.1/32", "no_of_network": 2}
- ]
- }
- },
- "ipv6": {
- "unicast": {
- "advertise_networks": [
- {"network": "2001::1/128", "no_of_network": 2}
- ]
- }
- },
- }
- }
- },
- }
-
- result = create_router_bgp(tgen, topo, input_dict_2)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
-
- for addr_type in ADDR_TYPES:
- # Verifying RIB routes
- dut = "r3"
- peer1 = "r1"
- peer2 = "r4"
- intf1 = topo["routers"][peer1]["links"][dut]["interface"]
- intf2 = topo["routers"][peer2]["links"][dut]["interface"]
-
- if addr_type == "ipv4":
- next_hop_4 = NEXT_HOP_4
- result = verify_rib(tgen, addr_type, dut, input_dict_2, next_hop_4)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- if addr_type == "ipv6":
- if "link_local" in PREFERRED_NEXT_HOP:
- next_hop1 = get_frr_ipv6_linklocal(tgen, peer1, intf=intf1)
- next_hop2 = get_frr_ipv6_linklocal(tgen, peer2, intf=intf2)
-
- next_hop_6 = [next_hop1, next_hop2]
- else:
- next_hop_6 = NEXT_HOP_6
-
- result = verify_rib(tgen, addr_type, dut, input_dict_2, next_hop_6)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info("[Step 3] : Kill BGPd daemon on R1 and R4..")
-
- # Kill BGPd daemon on R1
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- # Kill BGPd daemon on R4
- kill_router_daemons(tgen, "r4", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- # Verifying RIB routes
- next_hop_6 = ["fd00:0:0:1::1"]
- if addr_type == "ipv4":
- next_hop_4 = NEXT_HOP_4[0]
-
- result = verify_rib(tgen, addr_type, dut, input_dict_2, next_hop_4)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- if addr_type == "ipv6":
- if "link_local" in PREFERRED_NEXT_HOP:
- next_hop_6 = get_frr_ipv6_linklocal(tgen, peer1, intf=intf1)
- else:
- next_hop_6 = NEXT_HOP_6[0]
-
- result = verify_rib(tgen, addr_type, dut, input_dict_2, next_hop_6)
-
- # Verifying RIB routes
- if addr_type == "ipv4":
- next_hop_4 = NEXT_HOP_4[1]
- result = verify_rib(
- tgen, addr_type, dut, input_dict_2, next_hop_4, expected=False
- )
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r3: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
- )
- logger.info(" Expected behavior: {}".format(result))
-
- if addr_type == "ipv6":
- if "link_local" in PREFERRED_NEXT_HOP:
- next_hop_6 = get_frr_ipv6_linklocal(tgen, peer2, intf=intf2)
- else:
- next_hop_6 = NEXT_HOP_6[1]
-
- result = verify_rib(
- tgen, addr_type, dut, input_dict_2, next_hop_6, expected=False
- )
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r3: routes are still present in ZEBRA\n Error: {}".format(
- tc_name, result
- )
- )
- logger.info(" Expected behavior: {}".format(result))
-
- logger.info("[Step 4] : Start BGPd daemon on R1 and R4..")
-
- # Start BGPd daemon on R1
- start_router_daemons(tgen, "r1", ["bgpd"])
-
- # Start BGPd daemon on R4
- start_router_daemons(tgen, "r4", ["bgpd"])
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_chaos_34_2_p1(request):
- """
- Test Objective : Restarting node doesn't preserve the forwarding
- state verify the behaviour on helper node, if it still keeps the
- stale routes.
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- " Test Case : test_BGP_GR_chaos_34 "
- "BGP GR "
- "[Restart Mode]R1---R3[Helper Mode]"
- )
-
- logger.info("[Step 1] : Configure restarting" " router R1 to prevent ")
- logger.info("[Step 2] : Reset the session" " between R1 and R3..")
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "graceful-restart": {"preserve-fw-state": True, "disable-eor": True},
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- },
- }
- },
- "r3": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verify f-bit before killing BGPd daemon
- result = verify_f_bit(tgen, topo, addr_type, input_dict, "r3", "r1")
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes after starting BGPd daemon
- dut = "r3"
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info("[Step 3] : Kill BGPd daemon on R1..")
-
- # Kill BGPd daemon on R1
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- logger.info("[Step 4] : Withdraw/delete the prefixes " "originated from R1..")
-
- # Api call to delete advertised networks
- network = {"ipv4": "101.0.20.1/32", "ipv6": "1::1/128"}
- for addr_type in ADDR_TYPES:
- input_dict_2 = {
- "r1": {
- "bgp": {
- "address_family": {
- addr_type: {
- "unicast": {
- "advertise_networks": [
- {
- "network": network[addr_type],
- "no_of_network": 5,
- "delete": True,
- }
- ]
- }
- }
- }
- }
- }
- }
-
- result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_2)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info("[Step 5] : Remove the CLI from R1's config to " "set the F-bit..")
-
- # Modify graceful-restart config not to set f-bit
- # and write to /etc/frr
- input_dict_2 = {"r1": {"bgp": {"graceful-restart": {"preserve-fw-state": False}}}}
-
- result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_2)
- assert result is True, "Testcase {} : Failed \n Error {}".format(tc_name, result)
-
- logger.info("[Step 6] : Bring up the BGPd daemon on R1 again..")
-
- # Start BGPd daemon on R1
- start_router_daemons(tgen, "r1", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- # Verify f-bit after starting BGPd daemon
- result = verify_f_bit(
- tgen, topo, addr_type, input_dict, "r3", "r1", expected=False
- )
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r3: F-bit is set to True\n Error: {}".format(
- tc_name, result
- )
- logger.info(" Expected behavior: {}".format(result))
-
- # Verifying BGP RIB routes after starting BGPd daemon
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r3: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
- )
- logger.info(" Expected behavior: {}".format(result))
-
- # Verifying RIB routes
- result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
- )
- logger.info(" Expected behavior: {}".format(result))
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_chaos_34_1_p1(request):
- """
- Test Objective : Restarting node doesn't preserve forwarding
- state, helper router should not keep the stale entries.
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- " Test Case : test_BGP_GR_chaos_31 "
- "BGP GR "
- "[Restart Mode]R1---R3[Helper Mode]"
- )
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "graceful-restart": {
- "preserve-fw-state": True,
- "timer": {"restart-time": GR_RESTART_TIMER},
- },
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- },
- }
- },
- "r3": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes after starting BGPd daemon
- dut = "r3"
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info(
- "[Step 1] : Remove the preserve-fw-state command"
- " from restarting node R1's config"
- )
-
- # Configure graceful-restart to set f-bit as False
- input_dict_2 = {"r1": {"bgp": {"graceful-restart": {"preserve-fw-state": False}}}}
-
- result = create_router_bgp(tgen, topo, input_dict_2)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
-
- logger.info("[Step 2] : Reset the session between R1 and R3..")
-
- # Reset sessions
- for addr_type in ADDR_TYPES:
- clear_bgp(tgen, addr_type, "r1")
-
- result = verify_bgp_convergence_from_running_config(tgen, topo)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
-
- for addr_type in ADDR_TYPES:
- # Verify f-bit after starting BGPd daemon
- result = verify_f_bit(
- tgen, topo, addr_type, input_dict_2, "r3", "r1", expected=False
- )
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r3: F-bit is set to True\n Error: {}".format(
- tc_name, result
- )
- logger.info(" Expected behavior: {}".format(result))
-
- logger.info("[Step 3] : Kill BGPd daemon on R1..")
-
- # Kill BGPd daemon on R1
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- # Waiting for GR_RESTART_TIMER
- logger.info("Waiting for {} sec..".format(GR_RESTART_TIMER))
- sleep(GR_RESTART_TIMER)
-
- for addr_type in ADDR_TYPES:
- # Verifying BGP RIB routes
- input_dict = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r3: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
- )
- logger.info(" Expected behavior: {}".format(result))
-
- # Verifying RIB routes
- result = verify_rib(tgen, addr_type, dut, input_dict, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
- )
- logger.info(" Expected behavior: {}".format(result))
-
- # Start BGPd daemon on R1
- start_router_daemons(tgen, "r1", ["bgpd"])
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_chaos_32_p1(request):
- """
- Test Objective : Restarting node is connected to multiple helper
- nodes, one of them doesn't send EOR to restarting router. Verify
- that only after SDT restarting node send EOR to all helper peers
- excluding the prefixes originated by faulty router.
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- " Test Case : test_BGP_GR_chaos_32 "
- "BGP GR "
- "[Restart Mode]R1---R3&R5[Helper Mode]"
- )
-
- logger.info(
- "[Step 1] : Change the mode on R1 be a restarting" " node on global level"
- )
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "graceful-restart": {"graceful-restart": True},
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r1": {"next_hop_self": True}}},
- "r5": {"dest_link": {"r1": {"graceful-restart": True}}},
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r1": {"next_hop_self": True}}},
- "r5": {"dest_link": {"r1": {"graceful-restart": True}}},
- }
- }
- },
- },
- }
- },
- "r5": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r5": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r5": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r5")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r5"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes after starting BGPd daemon
- dut = "r3"
- input_dict_1 = {key: topo["routers"][key] for key in ["r5"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info("[Step 2] : Kill BGPd daemon on R1..")
- # Kill BGPd daemon on R1
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- logger.info("[Step 3] : Withdraw all the advertised prefixes from R5")
-
- # Api call to delete advertised networks
- network = {"ipv4": "105.0.20.1/32", "ipv6": "5::1/128"}
- for addr_type in ADDR_TYPES:
- input_dict_2 = {
- "r5": {
- "bgp": {
- "address_family": {
- addr_type: {
- "unicast": {
- "advertise_networks": [
- {
- "network": network[addr_type],
- "no_of_network": 5,
- "delete": True,
- }
- ]
- }
- }
- }
- }
- }
- }
-
- result = create_router_bgp(tgen, topo, input_dict_2)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(
- tc_name, result
- )
-
- logger.info(
- "[Step 4] : Stop the helper router R5 from sending EOR" " message using CLI"
- )
-
- # Modify graceful-restart config to prevent sending EOR
- input_dict_3 = {"r5": {"bgp": {"graceful-restart": {"disable-eor": True}}}}
-
- result = create_router_bgp(tgen, topo, input_dict_3)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
-
- logger.info("[Step 5] : Bring up the BGPd daemon on R1..")
-
- # Start BGPd daemon on R1
- start_router_daemons(tgen, "r1", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- # Verify EOR is disabled
- result = verify_eor(
- tgen, topo, addr_type, input_dict_3, dut="r5", peer="r1", expected=False
- )
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r5: EOR is set to TRUE\n Error: {}".format(
- tc_name, result
- )
- logger.info(" Expected behavior: {}".format(result))
-
- # Verifying BGP RIB routes after starting BGPd daemon
- input_dict_1 = {key: topo["routers"][key] for key in ["r5"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r3: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
- )
- logger.info(" Expected behavior: {}".format(result))
-
- # Verifying RIB routes
- result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
- )
- logger.info(" Expected behavior: {}".format(result))
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_chaos_37_p1(request):
- """
- Test Objective : Verify if helper node restarts before sending the
- EOR message, restarting node doesn't wait until stale path timer
- expiry to do the best path selection and sends an EOR
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- " Test Case : test_BGP_GR_chaos_37 "
- "BGP GR "
- "[Restart Mode]R1---R3[Helper Mode]"
- )
-
- logger.info(
- "[Step 1] : Configure restarting router R3 to prevent " "sending an EOR.."
- )
-
- logger.info("[Step 2] : Reset the session between R3 and R1..")
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- }
- }
- },
- "r3": {
- "bgp": {
- "graceful-restart": {"disable-eor": True},
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- },
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verify EOR is disabled
- result = verify_eor(
- tgen, topo, addr_type, input_dict, dut="r3", peer="r1", expected=False
- )
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r3: EOR is set to True\n Error: {}".format(
- tc_name, result
- )
- logger.info(" Expected behavior: {}".format(result))
-
- # Verifying BGP RIB routes after starting BGPd daemon
- dut = "r1"
- input_dict_1 = {key: topo["routers"][key] for key in ["r3"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info("[Step 3] : Kill BGPd daemon on R1..")
-
- # Kill BGPd daemon on R1
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- logger.info("[Step 4] : Start BGPd daemon on R1..")
-
- # Start BGPd daemon on R1
- start_router_daemons(tgen, "r1", ["bgpd"])
-
- logger.info("[Step 5] : Kill BGPd daemon on R3..")
-
- # Kill BGPd daemon on R3
- kill_router_daemons(tgen, "r3", ["bgpd"])
-
- # Modify graceful-restart config to prevent sending EOR
- input_dict_2 = {"r3": {"bgp": {"graceful-restart": {"disable-eor": True}}}}
-
- result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_2)
- assert result is True, "Testcase {} : Failed \n Error {}".format(tc_name, result)
-
- logger.info("[Step 6] : Start BGPd daemon on R3..")
-
- # Start BGPd daemon on R3
- start_router_daemons(tgen, "r3", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- # Verify r_bit
- result = verify_r_bit(tgen, topo, addr_type, input_dict, dut="r1", peer="r3")
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes
- input_dict_1 = {key: topo["routers"][key] for key in ["r3"]}
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verify EOR is send from R1 to R3
- input_dict_3 = {"r1": {"bgp": {"graceful-restart": {"disable-eor": True}}}}
-
- result = verify_eor(
- tgen, topo, addr_type, input_dict_3, dut="r1", peer="r3", expected=False
- )
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r1: EOR is set to True\n Error: {}".format(
- tc_name, result
- )
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_chaos_30_p1(request):
- """
- Test Objective : Restarting node removes stale routes from Zebra
- after receiving an EOR from helper router.
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- " Test Case : test_BGP_GR_chaos_30 "
- "BGP GR [Helper Mode]R3-----R1[Restart Mode] "
- )
-
- # Configure graceful-restart and timers
- input_dict = {
- "r1": {
- "bgp": {
- "graceful-restart": {"preserve-fw-state": True},
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- },
- }
- },
- "r3": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- for addr_type in ADDR_TYPES:
- # Verifying BGP RIB routes before shutting down BGPd daemon
- dut = "r1"
- input_dict = {key: topo["routers"][key] for key in ["r3"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- logger.info("[Step 2] : Kill BGPd daemon on R1..")
-
- # Kill BGPd daemon on R1
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- logger.info("[Step 3] : Withdraw advertised prefixes from R3...")
-
- # Api call to delete advertised networks
- network = {"ipv4": "103.0.20.1/32", "ipv6": "3::1/128"}
- for addr_type in ADDR_TYPES:
- input_dict = {
- "r3": {
- "bgp": {
- "address_family": {
- addr_type: {
- "unicast": {
- "advertise_networks": [
- {
- "network": network[addr_type],
- "no_of_network": 5,
- "delete": True,
- }
- ]
- }
- }
- }
- }
- }
- }
-
- result = create_router_bgp(tgen, topo, input_dict)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(
- tc_name, result
- )
-
- logger.info("[Step 4] : Start BGPd daemon on R1..")
-
- # Start BGPd daemon on R1
- start_router_daemons(tgen, "r1", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- # Verifying BGP RIB routes before shutting down BGPd daemon
- input_dict = {key: topo["routers"][key] for key in ["r3"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r1: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
- )
- logger.info(" Expected behavior: {}".format(result))
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
- )
- logger.info(" Expected behavior: {}".format(result))
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_15_p2(request):
- """
- Test Objective : Test GR scenarios by enabling Graceful Restart
- for multiple address families..
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r6": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r6": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- }
- }
- },
- "r6": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r6": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r6": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r6")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r6"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- logger.info(
- "[Step 2] : Test Setup "
- "[Helper Mode]R6-----R1[Restart Mode]"
- "--------R2[Helper Mode] Initilized"
- )
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- }
- }
- },
- "r2": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r2": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r2": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying BGP RIB routes
- dut = "r6"
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying BGP RIB routes
- dut = "r6"
- input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Kill BGPd daemon on R1
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- # Verifying BGP RIB routes
- dut = "r6"
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying BGP RIB routes
- dut = "r6"
- input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Start BGPd daemon on R1
- start_router_daemons(tgen, "r1", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- result = verify_bgp_convergence(tgen, topo)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying BGP RIB routes
- dut = "r6"
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying BGP RIB routes
- dut = "r6"
- input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- write_test_footer(tc_name)
-
-
-def BGP_GR_TC_7_p1(request):
- """
- Verify that BGP restarting node deletes all the routes received from peer
- if BGP Graceful capability is not present in BGP Open message from the
- peer
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- " Verify route download to RIB: BGP_GR_TC_7 >> "
- "BGP GR [Helper Mode]R3-----R1[Restart Mode] "
- )
-
- # Configure graceful-restart
- input_dict = {
- "r3": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- "r1": {
- "bgp": {
- "graceful-restart": {
- "graceful-restart": True,
- "preserve-fw-state": True,
- },
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r1": {"graceful-restart": True}}}
- }
- }
- },
- },
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying BGP RIB routes received from router R1
- dut = "r1"
- input_dict_1 = {key: topo["routers"][key] for key in ["r3"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- logger.info("R1 goes for reload")
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- # Change the configuration on router R1
- input_dict_2 = {
- "r3": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-disable": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-disable": True}
- }
- }
- }
- }
- },
- }
- }
- }
- }
-
- result = create_router_bgp(tgen, topo, input_dict_2)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
-
- # Change the configuration on R1
- network = {"ipv4": "103.0.20.1/32", "ipv6": "3::1/128"}
- for addr_type in ADDR_TYPES:
- input_dict_2 = {
- "r3": {
- "bgp": {
- "address_family": {
- addr_type: {
- "unicast": {
- "advertise_networks": [
- {
- "network": network[addr_type],
- "no_of_network": 5,
- "delete": True,
- }
- ]
- }
- }
- }
- }
- }
- }
-
- result = create_router_bgp(tgen, topo, input_dict_2)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- logger.info("R1 is about to come up now")
- start_router_daemons(tgen, "r1", ["bgpd"])
- logger.info("R1 is UP Now")
-
- # Wait for RIB stale timeout
- logger.info("Verify routes are not present" "in restart router")
-
- for addr_type in ADDR_TYPES:
- # Verifying RIB routes
- dut = "r1"
- input_dict_1 = {key: topo["routers"][key] for key in ["r3"]}
- result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
- )
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_TC_23_p1(request):
- """
- Verify that helper routers are deleting stale routes after stale route
- timer's expiry. If all the routes are not received from restating node
- after restart.
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- "Verify Stale Routes are deleted on helper: BGP_GR_TC_23 >> "
- "BGP GR [Helper Mode]R1-----R2[Restart Mode] "
- )
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "graceful-restart": {"timer": {"stalepath-time": GR_STALEPATH_TIMER}},
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- },
- }
- },
- "r2": {
- "bgp": {
- "graceful-restart": {
- "graceful-restart": True,
- "preserve-fw-state": True,
- },
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {"dest_link": {"r2": {"graceful-restart": True}}}
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {"dest_link": {"r2": {"graceful-restart": True}}}
- }
- }
- },
- },
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying BGP RIB routes received from router R1
- dut = "r1"
- input_dict_1 = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- logger.info("R2 goes for reload")
- kill_router_daemons(tgen, "r2", ["bgpd"])
-
- # Modify configuration to delete routes and include disable-eor
- input_dict_3 = {"r2": {"bgp": {"graceful-restart": {"disable-eor": True}}}}
-
- result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_3)
-
- # Modify configuration to delete routes and include disable-eor
- network = {"ipv4": "102.0.20.1/32", "ipv6": "2::1/128"}
- for addr_type in ADDR_TYPES:
- input_dict_3 = {
- "r2": {
- "bgp": {
- "address_family": {
- addr_type: {
- "unicast": {
- "advertise_networks": [
- {
- "network": network[addr_type],
- "no_of_network": 3,
- "delete": True,
- }
- ]
- }
- }
- }
- }
- }
- }
-
- result = modify_bgp_config_when_bgpd_down(tgen, topo, input_dict_3)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- logger.info("BGPd comes up for r2")
- start_router_daemons(tgen, "r2", ["bgpd"])
-
- # Wait for stalepath timer
- logger.info("Waiting for stalepath timer({} sec..)".format(GR_STALEPATH_TIMER))
- sleep(GR_STALEPATH_TIMER)
-
- for addr_type in ADDR_TYPES:
- clear_bgp(tgen, addr_type, "r2")
-
- # Verifying RIB routes
- dut = "r1"
- network = {"ipv4": "102.0.20.4/32", "ipv6": "2::4/128"}
- for addr_type in ADDR_TYPES:
- input_dict_1 = {
- "r1": {
- "bgp": {
- "address_family": {
- addr_type: {
- "unicast": {
- "advertise_networks": [
- {"network": network[addr_type], "no_of_network": 2}
- ]
- }
- }
- }
- }
- }
- }
-
- # Verify EOR on helper router
- result = verify_eor(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2", expected=False
- )
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r1: EOR is set to True\n Error: {}".format(
- tc_name, result
- )
-
- # Verifying BGP RIB routes received from router R1
- dut = "r1"
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_20_p1(request):
- """
- Test Objective : Verify that GR routers delete all the routes
- received from a node if both the routers are configured as GR
- helper node
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- "[Step 1] : Test Setup " "[Restart Mode]R3-----R1[Restart Mode] Initilized"
- )
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r3": {
- "dest_link": {
- "r1": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r3": {
- "dest_link": {
- "r1": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- "r3": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying BGP RIB routes
- dut = "r3"
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Kill BGPd daemon on R1
- kill_router_daemons(tgen, "r1", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- # Verifying BGP RIB routes
- dut = "r3"
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r3: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
- )
- logger.info(" Expected behavior: {}".format(result))
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
- )
- logger.info(" Expected behavior: {}".format(result))
-
- # Start BGPd daemon on R1
- start_router_daemons(tgen, "r1", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- result = verify_bgp_convergence(tgen, topo)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying BGP RIB routes
- dut = "r3"
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_21_p2(request):
- """
- Test Objective : VVerify BGP-GR feature when helper node is
- a transit router for it's eBGP peers.
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- "[Step 1] : Test Setup " "[Helper Mode]R6-----R1[Restart Mode] Initilized"
- )
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r6": {
- "dest_link": {
- "r1": {"graceful-restart-disable": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r6": {
- "dest_link": {
- "r1": {"graceful-restart-disable": True}
- }
- }
- }
- }
- },
- }
- }
- },
- "r6": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r6": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r6": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r6")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r6"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- logger.info(
- "[Step 2] : Test Setup "
- "[Restart Mode]R2-----[Helper Mode]R1[Disable Mode]"
- "--------R6[Helper Mode] Initilized"
- )
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- "r2": {
- "bgp": {
- "graceful-restart": {
- "graceful-restart": True,
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying BGP RIB routes
- dut = "r6"
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying BGP RIB routes
- dut = "r6"
- input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Kill BGPd daemon on R1
- kill_router_daemons(tgen, "r2", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- # Verifying BGP RIB routes
- dut = "r6"
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying BGP RIB routes
- dut = "r6"
- input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Start BGPd daemon on R1
- start_router_daemons(tgen, "r2", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- result = verify_bgp_convergence(tgen, topo)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying BGP RIB routes
- dut = "r6"
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes after bringing up BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying BGP RIB routes
- dut = "r6"
- input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- write_test_footer(tc_name)
-
-
-def test_BGP_GR_22_p2(request):
- """
- Test Objective : Verify BGP-GR feature when helper node
- is a transit router for it's iBGP peers.
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Check router status
- check_router_status(tgen)
-
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
-
- logger.info(
- "[Step 1] : Test Setup " "[Helper Mode]R3-----R1[Restart Mode] Initilized"
- )
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r3": {
- "dest_link": {
- "r1": {
- "graceful-restart-disable": True,
- "next_hop_self": True,
- }
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r3": {
- "dest_link": {
- "r1": {
- "graceful-restart-disable": True,
- "next_hop_self": True,
- }
- }
- }
- }
- }
- },
- }
- }
- },
- "r3": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {
- "r3": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r3")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r3"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- logger.info(
- "[Step 2] : Test Setup "
- "[Restart Mode]R2-----[Helper Mode]R1[Disable Mode]"
- "--------R3[Helper Mode] Initilized"
- )
-
- # Configure graceful-restart
- input_dict = {
- "r1": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- "ipv6": {
- "unicast": {
- "neighbor": {
- "r2": {
- "dest_link": {
- "r1": {"graceful-restart-helper": True}
- }
- }
- }
- }
- },
- }
- }
- },
- "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
- }
-
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
- for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(
- tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
- )
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying BGP RIB routes
- dut = "r3"
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying BGP RIB routes
- dut = "r3"
- input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Kill BGPd daemon on R1
- kill_router_daemons(tgen, "r2", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- # Verifying BGP RIB routes
- dut = "r3"
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying BGP RIB routes
- dut = "r3"
- input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Start BGPd daemon on R1
- start_router_daemons(tgen, "r2", ["bgpd"])
-
- for addr_type in ADDR_TYPES:
- result = verify_bgp_convergence(tgen, topo)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying BGP RIB routes
- dut = "r3"
- input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying BGP RIB routes
- dut = "r3"
- input_dict_2 = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
-
- # Verifying RIB routes before shutting down BGPd daemon
- result = verify_rib(tgen, addr_type, dut, input_dict_2)
- 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_l3vpn_to_bgp_vrf/scripts/check_routes.py b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_routes.py
index c1a9499cbe..25951281a7 100644
--- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_routes.py
+++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_routes.py
@@ -294,16 +294,16 @@ luCommand(
"1 available, best",
"wait",
"Ensure 99.0.0.4 shows up",
- 10
- )
+ 10,
+)
luCommand(
"r1",
'vtysh -c "show bgp vrf r1-cust1 ipv4 uni 5.1.0.0/24"',
"2 available, best",
"wait",
"Ensure 5.1.0.0 shows up",
- 10
- )
+ 10,
+)
want_r1_remote_cust1_routes = [
{"p": "5.1.0.0/24", "n": "3.3.3.3", "bp": False},
{"p": "5.1.0.0/24", "n": "99.0.0.1", "bp": True},
@@ -316,9 +316,9 @@ want_r1_remote_cust1_routes = [
{"p": "6.0.1.0/24", "n": "3.3.3.3", "bp": False},
{"p": "6.0.1.0/24", "n": "4.4.4.4", "bp": False},
{"p": "6.0.1.0/24", "n": "99.0.0.1", "bp": True},
- {"p": "6.0.2.0/24", "n": "3.3.3.3", "bp": False},
+ {"p": "6.0.2.0/24", "n": "3.3.3.3", "bp": True},
{"p": "6.0.2.0/24", "n": "4.4.4.4", "bp": False},
- {"p": "6.0.2.0/24", "n": "99.0.0.1", "bp": True},
+ {"p": "6.0.2.0/24", "n": "99.0.0.1", "bp": False},
{"p": "99.0.0.1/32", "n": "192.168.1.2", "bp": True},
{"p": "99.0.0.2/32", "n": "3.3.3.3"},
{"p": "99.0.0.3/32", "n": "4.4.4.4"},
@@ -338,16 +338,16 @@ luCommand(
"1 available, best",
"wait",
"Ensure 99.0.0.4 shows up",
- 10
- )
+ 10,
+)
luCommand(
"r3",
'vtysh -c "show bgp vrf r3-cust1 ipv4 uni 5.1.0.0/24"',
"2 available, best",
"wait",
"Ensure 5.1.0.0 shows up",
- 10
- )
+ 10,
+)
want_r3_remote_cust1_routes = [
{"p": "5.1.0.0/24", "n": "1.1.1.1", "bp": True},
{"p": "5.1.0.0/24", "n": "99.0.0.2", "bp": False},
@@ -360,9 +360,9 @@ want_r3_remote_cust1_routes = [
{"p": "6.0.1.0/24", "n": "1.1.1.1", "bp": True},
{"p": "6.0.1.0/24", "n": "4.4.4.4", "bp": False},
{"p": "6.0.1.0/24", "n": "99.0.0.2", "bp": False},
- {"p": "6.0.2.0/24", "n": "1.1.1.1", "bp": False},
+ {"p": "6.0.2.0/24", "n": "1.1.1.1", "bp": True},
{"p": "6.0.2.0/24", "n": "4.4.4.4", "bp": False},
- {"p": "6.0.2.0/24", "n": "99.0.0.2", "bp": True},
+ {"p": "6.0.2.0/24", "n": "99.0.0.2", "bp": False},
{"p": "99.0.0.1/32", "n": "1.1.1.1", "bp": True},
{"p": "99.0.0.3/32", "n": "4.4.4.4", "bp": True},
{"p": "99.0.0.4/32", "n": "4.4.4.4", "bp": True},
@@ -382,24 +382,24 @@ luCommand(
"1 available, best",
"wait",
"Ensure 99.0.0.4 shows up",
- 10
- )
+ 10,
+)
luCommand(
"r4",
'vtysh -c "show bgp vrf r4-cust1 ipv4 uni 5.1.0.0/24"',
"2 available, best",
"wait",
"Ensure 5.1.0.0 shows up",
- 10
- )
+ 10,
+)
luCommand(
"r4",
'vtysh -c "show bgp vrf r4-cust1 ipv4 uni 99.0.0.2/32"',
"1 available, best",
"wait",
"Ensure 99.0.0.2 shows up",
- 10
- )
+ 10,
+)
want_r4_remote_cust1_routes = [
{"p": "5.1.0.0/24", "n": "1.1.1.1", "bp": True},
{"p": "5.1.0.0/24", "n": "3.3.3.3", "bp": False},
@@ -409,10 +409,10 @@ want_r4_remote_cust1_routes = [
{"p": "6.0.1.0/24", "n": "3.3.3.3", "bp": False},
{"p": "6.0.1.0/24", "n": "99.0.0.3", "bp": False},
{"p": "6.0.1.0/24", "n": "99.0.0.4", "bp": False},
- {"p": "6.0.2.0/24", "n": "1.1.1.1", "bp": False},
+ {"p": "6.0.2.0/24", "n": "1.1.1.1", "bp": True},
{"p": "6.0.2.0/24", "n": "3.3.3.3", "bp": False},
{"p": "6.0.2.0/24", "n": "99.0.0.3", "bp": False},
- {"p": "6.0.2.0/24", "n": "99.0.0.4", "bp": True},
+ {"p": "6.0.2.0/24", "n": "99.0.0.4", "bp": False},
{"p": "99.0.0.1/32", "n": "1.1.1.1", "bp": True},
{"p": "99.0.0.2/32", "n": "3.3.3.3", "bp": True},
{"p": "99.0.0.3/32", "n": "192.168.1.2", "bp": True},
@@ -436,9 +436,9 @@ want_r4_remote_cust2_routes = [
{"p": "6.0.1.0/24", "n": "3.3.3.3", "bp": False},
{"p": "6.0.1.0/24", "n": "99.0.0.3", "bp": False},
{"p": "6.0.1.0/24", "n": "99.0.0.4", "bp": False},
- {"p": "6.0.2.0/24", "n": "1.1.1.1", "bp": False},
+ {"p": "6.0.2.0/24", "n": "1.1.1.1", "bp": True},
{"p": "6.0.2.0/24", "n": "3.3.3.3", "bp": False},
- {"p": "6.0.2.0/24", "n": "99.0.0.3", "bp": True},
+ {"p": "6.0.2.0/24", "n": "99.0.0.3", "bp": False},
{"p": "6.0.2.0/24", "n": "99.0.0.4", "bp": False},
{"p": "99.0.0.1/32", "n": "1.1.1.1", "bp": True},
{"p": "99.0.0.2/32", "n": "3.3.3.3", "bp": True},
@@ -632,8 +632,8 @@ luCommand(
luCommand(
"ce1",
'vtysh -c "show bgp ipv4 uni 6.0.2.0"',
- "1 available, best .*192.168.1.1.* Local.* 99.0.0.1 from 0.0.0.0 .99.0.0.1"
- + ".* Origin IGP, metric 100, localpref 100, weight 32768, valid, sourced, local, best .First path received"
+ "2 available, best .*192.168.1.1.* Local.* 99.0.0.1 from 0.0.0.0 .99.0.0.1"
+ + ".* Origin IGP, metric 100, localpref 100, weight 32768, valid, sourced, local, best .Weight"
+ ".* Community: 0:67.* Extended Community: RT:89:123.* Large Community: 12:34:11",
"pass",
"Redundant route 2 details",
@@ -641,8 +641,8 @@ luCommand(
luCommand(
"ce2",
'vtysh -c "show bgp ipv4 uni 6.0.2.0"',
- "1 available, best .*192.168.1.1.* Local.* 99.0.0.2 from 0.0.0.0 .99.0.0.2"
- + ".* Origin IGP, metric 100, localpref 100, weight 32768, valid, sourced, local, best .First path received"
+ "2 available, best .*192.168.1.1.* Local.* 99.0.0.2 from 0.0.0.0 .99.0.0.2"
+ + ".* Origin IGP, metric 100, localpref 100, weight 32768, valid, sourced, local, best .Weight"
+ ".* Community: 0:67.* Extended Community: RT:89:123.* Large Community: 12:34:12",
"pass",
"Redundant route 2 details",
@@ -661,7 +661,7 @@ luCommand(
'vtysh -c "show bgp ipv4 uni 6.0.2.0"',
"2 available, best .*192.168.1.1.* Local.* 192.168.1.1 from 192.168.1.1 .192.168.1.1"
+ ".* Origin IGP, metric 100, localpref 100, valid, internal"
- + ".* Community: 0:67.* Extended Community: RT:52:100 RT:89:123.* Large Community: 12:34:14",
+ + ".* Community: 0:67.* Extended Community: RT:52:100 RT:89:123.* Large Community: 12:34:11",
"pass",
"Redundant route 2 details",
)
@@ -670,7 +670,7 @@ luCommand(
'vtysh -c "show bgp vrf ce4-cust2 ipv4 6.0.2.0"',
"2 available, best .*192.168.2.1.* Local.* 192.168.2.1 from 192.168.2.1 .192.168.2.1"
+ ".* Origin IGP, metric 100, localpref 100, valid, internal"
- + ".* Community: 0:67.* Extended Community: RT:52:100 RT:89:123.* Large Community: 12:34:13",
+ + ".* Community: 0:67.* Extended Community: RT:52:100 RT:89:123.* Large Community: 12:34:11",
"pass",
"Redundant route 2 details",
)
diff --git a/tests/topotests/bgp_multiview_topo1/peer1/exa-send.py b/tests/topotests/bgp_multiview_topo1/peer1/exa-send.py
index fbb73f5b6a..09f6ea59e5 100755
--- a/tests/topotests/bgp_multiview_topo1/peer1/exa-send.py
+++ b/tests/topotests/bgp_multiview_topo1/peer1/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_multiview_topo1/peer2/exa-send.py b/tests/topotests/bgp_multiview_topo1/peer2/exa-send.py
index fbb73f5b6a..09f6ea59e5 100755
--- a/tests/topotests/bgp_multiview_topo1/peer2/exa-send.py
+++ b/tests/topotests/bgp_multiview_topo1/peer2/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_multiview_topo1/peer3/exa-send.py b/tests/topotests/bgp_multiview_topo1/peer3/exa-send.py
index fbb73f5b6a..09f6ea59e5 100755
--- a/tests/topotests/bgp_multiview_topo1/peer3/exa-send.py
+++ b/tests/topotests/bgp_multiview_topo1/peer3/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_multiview_topo1/peer4/exa-send.py b/tests/topotests/bgp_multiview_topo1/peer4/exa-send.py
index fbb73f5b6a..09f6ea59e5 100755
--- a/tests/topotests/bgp_multiview_topo1/peer4/exa-send.py
+++ b/tests/topotests/bgp_multiview_topo1/peer4/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_multiview_topo1/peer5/exa-send.py b/tests/topotests/bgp_multiview_topo1/peer5/exa-send.py
index fbb73f5b6a..09f6ea59e5 100755
--- a/tests/topotests/bgp_multiview_topo1/peer5/exa-send.py
+++ b/tests/topotests/bgp_multiview_topo1/peer5/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_multiview_topo1/peer6/exa-send.py b/tests/topotests/bgp_multiview_topo1/peer6/exa-send.py
index fbb73f5b6a..09f6ea59e5 100755
--- a/tests/topotests/bgp_multiview_topo1/peer6/exa-send.py
+++ b/tests/topotests/bgp_multiview_topo1/peer6/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_multiview_topo1/peer7/exa-send.py b/tests/topotests/bgp_multiview_topo1/peer7/exa-send.py
index fbb73f5b6a..09f6ea59e5 100755
--- a/tests/topotests/bgp_multiview_topo1/peer7/exa-send.py
+++ b/tests/topotests/bgp_multiview_topo1/peer7/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_multiview_topo1/peer8/exa-send.py b/tests/topotests/bgp_multiview_topo1/peer8/exa-send.py
index fbb73f5b6a..09f6ea59e5 100755
--- a/tests/topotests/bgp_multiview_topo1/peer8/exa-send.py
+++ b/tests/topotests/bgp_multiview_topo1/peer8/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/bgp_peer_type_multipath_relax/peer1/exa_readpipe.py b/tests/topotests/bgp_peer_type_multipath_relax/peer1/exa_readpipe.py
index 9e689a27e3..0f998c1613 100644
--- a/tests/topotests/bgp_peer_type_multipath_relax/peer1/exa_readpipe.py
+++ b/tests/topotests/bgp_peer_type_multipath_relax/peer1/exa_readpipe.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"Helper script to read api commands from a pipe and feed them to ExaBGP"
import sys
diff --git a/tests/topotests/bgp_peer_type_multipath_relax/peer2/exa_readpipe.py b/tests/topotests/bgp_peer_type_multipath_relax/peer2/exa_readpipe.py
index 9e689a27e3..0f998c1613 100644
--- a/tests/topotests/bgp_peer_type_multipath_relax/peer2/exa_readpipe.py
+++ b/tests/topotests/bgp_peer_type_multipath_relax/peer2/exa_readpipe.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"Helper script to read api commands from a pipe and feed them to ExaBGP"
import sys
diff --git a/tests/topotests/bgp_peer_type_multipath_relax/peer3/exa_readpipe.py b/tests/topotests/bgp_peer_type_multipath_relax/peer3/exa_readpipe.py
index 9e689a27e3..0f998c1613 100644
--- a/tests/topotests/bgp_peer_type_multipath_relax/peer3/exa_readpipe.py
+++ b/tests/topotests/bgp_peer_type_multipath_relax/peer3/exa_readpipe.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"Helper script to read api commands from a pipe and feed them to ExaBGP"
import sys
diff --git a/tests/topotests/bgp_peer_type_multipath_relax/peer4/exa_readpipe.py b/tests/topotests/bgp_peer_type_multipath_relax/peer4/exa_readpipe.py
index 9e689a27e3..0f998c1613 100644
--- a/tests/topotests/bgp_peer_type_multipath_relax/peer4/exa_readpipe.py
+++ b/tests/topotests/bgp_peer_type_multipath_relax/peer4/exa_readpipe.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"Helper script to read api commands from a pipe and feed them to ExaBGP"
import sys
diff --git a/tests/topotests/bgp_route_map_match_ipv6_nexthop/__init__.py b/tests/topotests/bgp_route_map_match_ipv6_nexthop/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bgp_route_map_match_ipv6_nexthop/__init__.py
diff --git a/tests/topotests/bgp_route_map_match_ipv6_nexthop/r1/bgpd.conf b/tests/topotests/bgp_route_map_match_ipv6_nexthop/r1/bgpd.conf
new file mode 100644
index 0000000000..c2a49252d6
--- /dev/null
+++ b/tests/topotests/bgp_route_map_match_ipv6_nexthop/r1/bgpd.conf
@@ -0,0 +1,32 @@
+!
+ipv6 access-list nh1 permit 2001:db8:1::/64
+ipv6 access-list nh2 permit 2001:db8:2::/64
+ipv6 access-list nh3 permit 2001:db8:3::/64
+!
+ipv6 prefix-list nh4 permit 2001:db8:5::/64 le 128
+!
+router bgp 65001
+ bgp router-id 10.10.10.1
+ no bgp ebgp-requires-policy
+ neighbor 2001:db8::2 remote-as external
+ address-family ipv6 unicast
+ neighbor 2001:db8::2 activate
+ neighbor 2001:db8::2 route-map r2 in
+ exit-address-family
+!
+route-map r2 permit 10
+ match ipv6 next-hop nh1
+ set community 65002:1
+route-map r2 permit 20
+ match ipv6 next-hop nh2
+ set community 65002:2
+route-map r2 permit 30
+ match ipv6 next-hop nh3
+ set community 65002:3
+route-map r2 permit 40
+ match ipv6 next-hop address 2001:db8:4::1
+ set community 65002:4
+route-map r2 permit 50
+ match ipv6 next-hop prefix-list nh4
+ set community 65002:5
+!
diff --git a/tests/topotests/bgp_route_map_match_ipv6_nexthop/r1/zebra.conf b/tests/topotests/bgp_route_map_match_ipv6_nexthop/r1/zebra.conf
new file mode 100644
index 0000000000..1d4374bd8f
--- /dev/null
+++ b/tests/topotests/bgp_route_map_match_ipv6_nexthop/r1/zebra.conf
@@ -0,0 +1,4 @@
+!
+int r1-eth0
+ ipv6 address 2001:db8::1/64
+!
diff --git a/tests/topotests/bgp_route_map_match_ipv6_nexthop/r2/bgpd.conf b/tests/topotests/bgp_route_map_match_ipv6_nexthop/r2/bgpd.conf
new file mode 100644
index 0000000000..19dcf3664b
--- /dev/null
+++ b/tests/topotests/bgp_route_map_match_ipv6_nexthop/r2/bgpd.conf
@@ -0,0 +1,33 @@
+!
+router bgp 65002
+ bgp router-id 10.10.10.2
+ no bgp ebgp-requires-policy
+ neighbor 2001:db8::1 remote-as external
+ address-family ipv6 unicast
+ redistribute connected
+ neighbor 2001:db8::1 activate
+ neighbor 2001:db8::1 route-map r1 out
+ exit-address-family
+!
+ipv6 prefix-list p1 permit 2001:db8:1::1/128
+ipv6 prefix-list p2 permit 2001:db8:2::1/128
+ipv6 prefix-list p3 permit 2001:db8:3::1/128
+ipv6 prefix-list p4 permit 2001:db8:4::1/128
+ipv6 prefix-list p5 permit 2001:db8:5::1/128
+!
+route-map r1 permit 10
+ match ipv6 address prefix-list p1
+ set ipv6 next-hop global 2001:db8:1::1
+route-map r1 permit 20
+ match ipv6 address prefix-list p2
+ set ipv6 next-hop global 2001:db8:2::1
+route-map r1 permit 30
+ match ipv6 address prefix-list p3
+ set ipv6 next-hop global 2001:db8:3::1
+route-map r1 permit 40
+ match ipv6 address prefix-list p4
+ set ipv6 next-hop global 2001:db8:4::1
+route-map r1 permit 50
+ match ipv6 address prefix-list p5
+ set ipv6 next-hop global 2001:db8:5::1
+!
diff --git a/tests/topotests/bgp_route_map_match_ipv6_nexthop/r2/zebra.conf b/tests/topotests/bgp_route_map_match_ipv6_nexthop/r2/zebra.conf
new file mode 100644
index 0000000000..e69345f4f6
--- /dev/null
+++ b/tests/topotests/bgp_route_map_match_ipv6_nexthop/r2/zebra.conf
@@ -0,0 +1,11 @@
+!
+int lo
+ ipv6 address 2001:db8:1::1/128
+ ipv6 address 2001:db8:2::1/128
+ ipv6 address 2001:db8:3::1/128
+ ipv6 address 2001:db8:4::1/128
+ ipv6 address 2001:db8:5::1/128
+!
+int r2-eth0
+ ip address 2001:db8::2/64
+!
diff --git a/tests/topotests/bgp_route_map_match_ipv6_nexthop/test_bgp_route_map_match_ipv6_nexthop.py b/tests/topotests/bgp_route_map_match_ipv6_nexthop/test_bgp_route_map_match_ipv6_nexthop.py
new file mode 100644
index 0000000000..8c86526bf1
--- /dev/null
+++ b/tests/topotests/bgp_route_map_match_ipv6_nexthop/test_bgp_route_map_match_ipv6_nexthop.py
@@ -0,0 +1,121 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2021 by
+# Donatas Abraitis <donatas.abraitis@gmail.com>
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+Test if we can match BGP prefixes by next-hop which is
+specified by an IPv6 Access-list, prefix-list or just an address.
+"""
+
+import os
+import sys
+import json
+import pytest
+import functools
+
+pytestmark = pytest.mark.bgpd
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+
+pytestmark = [pytest.mark.bgpd]
+
+
+def build_topo(tgen):
+ for routern in range(1, 3):
+ tgen.add_router("r{}".format(routern))
+
+ switch = tgen.add_switch("s1")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r2"])
+
+
+def setup_module(mod):
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ for i, (rname, router) in enumerate(router_list.items(), 1):
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
+ )
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_route_map_match_ipv6_next_hop_access_list():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router = tgen.gears["r1"]
+
+ def _bgp_converge(router):
+ output = json.loads(router.vtysh_cmd("show ipv6 route json"))
+ expected = {
+ "2001:db8:1::1/128": [
+ {
+ "communities": "65002:1",
+ }
+ ],
+ "2001:db8:2::1/128": [
+ {
+ "communities": "65002:2",
+ }
+ ],
+ "2001:db8:3::1/128": [
+ {
+ "communities": "65002:3",
+ }
+ ],
+ "2001:db8:4::1/128": [
+ {
+ "communities": "65002:4",
+ }
+ ],
+ "2001:db8:5::1/128": [
+ {
+ "communities": "65002:5",
+ }
+ ],
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_converge, router)
+ success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Can't match routes using ipv6 next-hop access-list"
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_route_server_client/__init__.py b/tests/topotests/bgp_route_server_client/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bgp_route_server_client/__init__.py
diff --git a/tests/topotests/bgp_route_server_client/r1/bgpd.conf b/tests/topotests/bgp_route_server_client/r1/bgpd.conf
new file mode 100644
index 0000000000..9826b671f9
--- /dev/null
+++ b/tests/topotests/bgp_route_server_client/r1/bgpd.conf
@@ -0,0 +1,12 @@
+!
+router bgp 65001
+ bgp router-id 10.10.10.1
+ no bgp ebgp-requires-policy
+ neighbor 2001:db8:1::1 remote-as external
+ neighbor 2001:db8:1::1 timers 3 10
+ neighbor 2001:db8:1::1 timers connect 5
+ address-family ipv6 unicast
+ redistribute connected
+ neighbor 2001:db8:1::1 activate
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_route_server_client/r1/zebra.conf b/tests/topotests/bgp_route_server_client/r1/zebra.conf
new file mode 100644
index 0000000000..08d0be6220
--- /dev/null
+++ b/tests/topotests/bgp_route_server_client/r1/zebra.conf
@@ -0,0 +1,7 @@
+!
+int lo
+ ipv6 address 2001:db8:f::1/128
+!
+int r1-eth0
+ ipv6 address 2001:db8:1::2/64
+!
diff --git a/tests/topotests/bgp_route_server_client/r2/bgpd.conf b/tests/topotests/bgp_route_server_client/r2/bgpd.conf
new file mode 100644
index 0000000000..3b0a24b8ba
--- /dev/null
+++ b/tests/topotests/bgp_route_server_client/r2/bgpd.conf
@@ -0,0 +1,17 @@
+router bgp 65000 view RS
+ bgp router-id 10.10.10.2
+ no bgp ebgp-requires-policy
+ neighbor 2001:db8:1::2 remote-as external
+ neighbor 2001:db8:1::2 timers 3 10
+ neighbor 2001:db8:1::2 timers connect 5
+ neighbor 2001:db8:3::2 remote-as external
+ neighbor 2001:db8:3::2 timers 3 10
+ neighbor 2001:db8:3::2 timers connect 5
+ address-family ipv6 unicast
+ redistribute connected
+ neighbor 2001:db8:1::2 activate
+ neighbor 2001:db8:3::2 activate
+ neighbor 2001:db8:1::2 route-server-client
+ neighbor 2001:db8:3::2 route-server-client
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_route_server_client/r2/zebra.conf b/tests/topotests/bgp_route_server_client/r2/zebra.conf
new file mode 100644
index 0000000000..806bc4fe32
--- /dev/null
+++ b/tests/topotests/bgp_route_server_client/r2/zebra.conf
@@ -0,0 +1,7 @@
+!
+int r2-eth0
+ ipv6 address 2001:db8:1::1/64
+!
+int r2-eth1
+ ipv6 address 2001:db8:3::1/64
+!
diff --git a/tests/topotests/bgp_route_server_client/r3/bgpd.conf b/tests/topotests/bgp_route_server_client/r3/bgpd.conf
new file mode 100644
index 0000000000..60a5ffc559
--- /dev/null
+++ b/tests/topotests/bgp_route_server_client/r3/bgpd.conf
@@ -0,0 +1,12 @@
+!
+router bgp 65003
+ bgp router-id 10.10.10.3
+ no bgp ebgp-requires-policy
+ neighbor 2001:db8:3::1 remote-as external
+ neighbor 2001:db8:3::1 timers 3 10
+ neighbor 2001:db8:3::1 timers connect 5
+ address-family ipv6 unicast
+ redistribute connected
+ neighbor 2001:db8:3::1 activate
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_route_server_client/r3/zebra.conf b/tests/topotests/bgp_route_server_client/r3/zebra.conf
new file mode 100644
index 0000000000..b5511a437c
--- /dev/null
+++ b/tests/topotests/bgp_route_server_client/r3/zebra.conf
@@ -0,0 +1,7 @@
+!
+int lo
+ ipv6 address 2001:db8:f::3/128
+!
+int r3-eth0
+ ipv6 address 2001:db8:3::2/64
+!
diff --git a/tests/topotests/bgp_route_server_client/test_bgp_route_server_client.py b/tests/topotests/bgp_route_server_client/test_bgp_route_server_client.py
new file mode 100644
index 0000000000..21088f7008
--- /dev/null
+++ b/tests/topotests/bgp_route_server_client/test_bgp_route_server_client.py
@@ -0,0 +1,143 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2021 by
+# Donatas Abraitis <donatas.abraitis@gmail.com>
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+Test if we send ONLY GUA address for route-server-client peers.
+"""
+
+import os
+import sys
+import json
+import pytest
+import functools
+
+pytestmark = pytest.mark.bgpd
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+
+pytestmark = [pytest.mark.bgpd]
+
+
+def build_topo(tgen):
+ for routern in range(1, 4):
+ tgen.add_router("r{}".format(routern))
+
+ switch = tgen.add_switch("s1")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r2"])
+
+ switch = tgen.add_switch("s2")
+ switch.add_link(tgen.gears["r2"])
+ switch.add_link(tgen.gears["r3"])
+
+
+def setup_module(mod):
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ for i, (rname, router) in enumerate(router_list.items(), 1):
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
+ )
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_route_server_client():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r1 = tgen.gears["r1"]
+ r2 = tgen.gears["r2"]
+
+ def _bgp_converge(router):
+ output = json.loads(router.vtysh_cmd("show bgp ipv6 unicast summary json"))
+ expected = {"peers": {"2001:db8:1::1": {"state": "Established", "pfxRcd": 2}}}
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_converge, r1)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Cannot see BGP sessions to be up"
+
+ def _bgp_prefix_received(router):
+ output = json.loads(router.vtysh_cmd("show bgp 2001:db8:f::3/128 json"))
+ expected = {
+ "prefix": "2001:db8:f::3/128",
+ "paths": [{"nexthops": [{"ip": "2001:db8:3::2"}]}],
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_prefix_received, r1)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Cannot see BGP GUA next hop from r3 in r1"
+
+ def _bgp_single_next_hop(router):
+ output = json.loads(router.vtysh_cmd("show bgp 2001:db8:f::3/128 json"))
+ return len(output["paths"][0]["nexthops"])
+
+ assert (
+ _bgp_single_next_hop(r1) == 1
+ ), "Not ONLY one Next Hop received for 2001:db8:f::3/128"
+
+ def _bgp_gua_lla_next_hop(router):
+ output = json.loads(router.vtysh_cmd("show bgp view RS 2001:db8:f::3/128 json"))
+ expected = {
+ "prefix": "2001:db8:f::3/128",
+ "paths": [
+ {
+ "nexthops": [
+ {
+ "ip": "2001:db8:3::2",
+ "hostname": "r3",
+ "afi": "ipv6",
+ "scope": "global",
+ },
+ {"hostname": "r3", "afi": "ipv6", "scope": "link-local"},
+ ]
+ }
+ ],
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_gua_lla_next_hop, r2)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Cannot see BGP LLA next hop from r3 in r2"
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_vrf_lite_best_path_test/bgp_vrf_lite_best_path_topo1.json b/tests/topotests/bgp_vrf_lite_best_path_test/bgp_vrf_lite_best_path_topo1.json
new file mode 100644
index 0000000000..b1d7d09db8
--- /dev/null
+++ b/tests/topotests/bgp_vrf_lite_best_path_test/bgp_vrf_lite_best_path_topo1.json
@@ -0,0 +1,563 @@
+{
+ "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": {
+ "r2-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "ISR"},
+ "r3-link1": {"ipv4": "auto", "ipv6": "auto"},
+ "r4-link1": {"ipv4": "auto", "ipv6": "auto"}
+ },
+ "vrfs":[
+ {
+ "name": "ISR",
+ "id": "1"
+ }
+ ],
+ "bgp":
+ [
+ {
+ "local_as": "100",
+ "vrf": "ISR",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "next_hop_self": true
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "next_hop_self": true,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "100",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "100",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r4": {
+ "dest_link": {
+ "r1-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r4": {
+ "dest_link": {
+ "r1-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "static_routes":[
+ {
+ "network": ["11.11.11.1/32", "11.11.11.11/32"],
+ "next_hop":"Null0",
+ "vrf": "ISR"
+ },
+ {
+ "network": ["11:11::1/128", "11:11::11/128"],
+ "next_hop":"Null0",
+ "vrf": "ISR"
+ },
+ {
+ "network": ["10.10.10.10/32", "10.10.10.100/32"],
+ "next_hop":"Null0"
+ },
+ {
+ "network": ["10:10::10/128", "10:10::100/128"],
+ "next_hop":"Null0"
+ }
+ ],
+ "route_maps": {
+ "rmap_global": [{
+ "action": "permit",
+ "set": {
+ "ipv6": {
+ "nexthop": "prefer-global"
+ }
+ }
+ }]
+ }
+ },
+ "r2": {
+ "links": {
+ "r1-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "ISR"},
+ "r3-link1": {"ipv4": "auto", "ipv6": "auto"},
+ "r4-link1": {"ipv4": "auto", "ipv6": "auto"}
+ },
+ "vrfs":[
+ {
+ "name": "ISR",
+ "id": "1"
+ }
+ ],
+ "bgp":
+ [
+ {
+ "local_as": "100",
+ "vrf": "ISR",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "next_hop_self": true
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "next_hop_self": true,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "100",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r2-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r2-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "100",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r4": {
+ "dest_link": {
+ "r2-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r4": {
+ "dest_link": {
+ "r2-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "static_routes":[
+ {
+ "network": ["22.22.22.2/32", "22.22.22.22/32"],
+ "next_hop":"Null0",
+ "vrf": "ISR"
+ },
+ {
+ "network": ["22:22::2/128", "22:22::22/128"],
+ "next_hop":"Null0",
+ "vrf": "ISR"
+ },
+ {
+ "network": ["20.20.20.20/32", "20.20.20.200/32"],
+ "next_hop":"Null0"
+ },
+ {
+ "network": ["20:20::20/128", "20:20::200/128"],
+ "next_hop":"Null0"
+ }
+ ],
+ "route_maps": {
+ "rmap_global": [{
+ "action": "permit",
+ "set": {
+ "ipv6": {
+ "nexthop": "prefer-global"
+ }
+ }
+ }]
+ }
+ },
+ "r3": {
+ "links": {
+ "r1-link1": {"ipv4": "auto", "ipv6": "auto"},
+ "r2-link1": {"ipv4": "auto", "ipv6": "auto"}
+ },
+ "bgp":
+ [
+ {
+ "local_as": "300",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "300",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r3-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r3-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "static_routes":[
+ {
+ "network": ["30.30.30.3/32", "30.30.30.30/32"],
+ "next_hop":"Null0"
+ },
+ {
+ "network": ["30:30::3/128", "30:30::30/128"],
+ "next_hop":"Null0"
+ },
+ {
+ "network": ["50.50.50.5/32", "50.50.50.50/32"],
+ "next_hop":"Null0"
+ },
+ {
+ "network": ["50:50::5/128", "50:50::50/128"],
+ "next_hop":"Null0"
+ }
+ ],
+ "route_maps": {
+ "rmap_global": [{
+ "action": "permit",
+ "set": {
+ "ipv6": {
+ "nexthop": "prefer-global"
+ }
+ }
+ }]
+ }
+ },
+ "r4": {
+ "links": {
+ "r1-link1": {"ipv4": "auto", "ipv6": "auto"},
+ "r2-link1": {"ipv4": "auto", "ipv6": "auto"}
+ },
+ "bgp":
+ [
+ {
+ "local_as": "400",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r4-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r4-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "400",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r4-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r4-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "static_routes":[
+ {
+ "network": ["40.40.40.4/32", "40.40.40.40/32"],
+ "next_hop":"Null0"
+ },
+ {
+ "network": ["40:40::4/128", "40:40::40/128"],
+ "next_hop":"Null0"
+ },
+ {
+ "network": ["50.50.50.5/32", "50.50.50.50/32"],
+ "next_hop":"Null0"
+ },
+ {
+ "network": ["50:50::5/128", "50:50::50/128"],
+ "next_hop":"Null0"
+ }
+ ],
+ "route_maps": {
+ "rmap_global": [{
+ "action": "permit",
+ "set": {
+ "ipv6": {
+ "nexthop": "prefer-global"
+ }
+ }
+ }]
+ }
+ }
+ }
+}
diff --git a/tests/topotests/bgp_vrf_lite_best_path_test/bgp_vrf_lite_best_path_topo2.json b/tests/topotests/bgp_vrf_lite_best_path_test/bgp_vrf_lite_best_path_topo2.json
new file mode 100644
index 0000000000..0b13882176
--- /dev/null
+++ b/tests/topotests/bgp_vrf_lite_best_path_test/bgp_vrf_lite_best_path_topo2.json
@@ -0,0 +1,1088 @@
+{
+ "address_types": ["ipv4","ipv6"],
+ "ipv4base": "10.0.0.0",
+ "ipv4mask": 24,
+ "ipv6base": "fd00::",
+ "ipv6mask": 64,
+ "link_ip_start": {
+ "ipv4": "10.0.0.0",
+ "v4mask": 24,
+ "ipv6": "fd00::",
+ "v6mask": 64
+ },
+ "lo_prefix": {
+ "ipv4": "1.0.",
+ "v4mask": 32,
+ "ipv6": "2001:db8:f::",
+ "v6mask": 128
+ },
+ "routers": {
+ "r1": {
+ "links": {
+ "r3-link1": {"ipv4": "192.168.1.1/24", "ipv6": "fd00:0:0:1::1/120", "vrf": "RED"},
+ "r3-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE"},
+ "r3-link3": {"ipv4": "192.168.1.1/24", "ipv6": "fd00:0:0:1::1/120", "vrf": "GREEN"},
+ "r3-link4": {"ipv4": "auto", "ipv6": "auto"}
+ },
+ "vrfs":[
+ {"name": "RED", "id": "1"},
+ {"name": "BLUE", "id": "2"},
+ {"name": "GREEN", "id": "3"}
+ ],
+ "bgp":
+ [
+ {
+ "local_as": "1",
+ "vrf": "RED",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "1",
+ "vrf": "BLUE",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1-link2": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1-link2": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "1",
+ "vrf": "GREEN",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1-link3": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1-link3": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "1",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1-link4": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1-link4": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "route_maps": {
+ "rmap_global": [{
+ "action": "permit",
+ "set": {
+ "ipv6": {
+ "nexthop": "prefer-global"
+ }
+ }
+ }]
+ }
+ },
+ "r2": {
+ "links": {
+ "r3-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED"},
+ "r3-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE"},
+ "r3-link3": {"ipv4": "auto", "ipv6": "auto", "vrf": "GREEN"},
+ "r3-link4": {"ipv4": "auto", "ipv6": "auto"}
+ },
+ "vrfs":[
+ {"name": "RED", "id": "1"},
+ {"name": "BLUE", "id": "2"},
+ {"name": "GREEN", "id": "3"}
+ ],
+ "bgp":
+ [
+ {
+ "local_as": "2",
+ "vrf": "RED",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r2-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r2-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "2",
+ "vrf": "BLUE",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r2-link2": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r2-link2": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "2",
+ "vrf": "GREEN",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r2-link3": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r2-link3": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "2",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r2-link4": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r2-link4": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "route_maps": {
+ "rmap_global": [{
+ "action": "permit",
+ "set": {
+ "ipv6": {
+ "nexthop": "prefer-global"
+ }
+ }
+ }]
+ }
+ },
+ "r3": {
+ "links": {
+ "r1-link1": {"ipv4": "192.168.1.2/24", "ipv6": "fd00:0:0:1::2/120", "vrf": "RED"},
+ "r1-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE"},
+ "r1-link3": {"ipv4": "192.168.1.2/24", "ipv6": "fd00:0:0:1::2/120", "vrf": "GREEN"},
+ "r1-link4": {"ipv4": "auto", "ipv6": "auto"},
+ "r2-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED"},
+ "r2-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE"},
+ "r2-link3": {"ipv4": "auto", "ipv6": "auto", "vrf": "GREEN"},
+ "r2-link4": {"ipv4": "auto", "ipv6": "auto"},
+ "r4-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED"},
+ "r4-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE"},
+ "r4-link3": {"ipv4": "auto", "ipv6": "auto", "vrf": "GREEN"},
+ "r4-link4": {"ipv4": "auto", "ipv6": "auto"},
+ "r5-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED"},
+ "r5-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE"},
+ "r5-link3": {"ipv4": "auto", "ipv6": "auto", "vrf": "GREEN"},
+ "r5-link4": {"ipv4": "auto", "ipv6": "auto"}
+ },
+ "vrfs":[
+ {"name": "RED", "id": "1"},
+ {"name": "BLUE", "id": "2"},
+ {"name": "GREEN", "id": "3"}
+ ],
+ "bgp":
+ [
+ {
+ "local_as": "3",
+ "vrf": "RED",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3-link1": {}
+ }
+ },
+ "r2": {
+ "dest_link": {
+ "r3-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ },
+ "r5": {
+ "dest_link": {
+ "r3-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ },
+ "r2": {
+ "dest_link": {
+ "r3-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3-link1": {
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ },
+ "r5": {
+ "dest_link": {
+ "r3-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "3",
+ "vrf": "BLUE",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3-link2": {}
+ }
+ },
+ "r2": {
+ "dest_link": {
+ "r3-link2": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3-link2": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ },
+ "r5": {
+ "dest_link": {
+ "r3-link2": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3-link2": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ },
+ "r2": {
+ "dest_link": {
+ "r3-link2": {
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3-link2": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ },
+ "r5": {
+ "dest_link": {
+ "r3-link2": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "3",
+ "vrf": "GREEN",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3-link3": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ },
+ "r2": {
+ "dest_link": {
+ "r3-link3": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3-link3": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ },
+ "r5": {
+ "dest_link": {
+ "r3-link3": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3-link3": {
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ },
+ "r2": {
+ "dest_link": {
+ "r3-link3": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3-link3": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ },
+ "r5": {
+ "dest_link": {
+ "r3-link3": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "3",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3-link4": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ },
+ "r2": {
+ "dest_link": {
+ "r3-link4": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3-link4": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ },
+ "r5": {
+ "dest_link": {
+ "r3-link4": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3-link4": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ },
+ "r2": {
+ "dest_link": {
+ "r3-link4": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3-link4": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ },
+ "r5": {
+ "dest_link": {
+ "r3-link4": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "route_maps": {
+ "rmap_global": [{
+ "action": "permit",
+ "set": {
+ "ipv6": {
+ "nexthop": "prefer-global"
+ }
+ }
+ }]
+ }
+ },
+ "r4": {
+ "links": {
+ "r3-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED"},
+ "r3-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE"},
+ "r3-link3": {"ipv4": "auto", "ipv6": "auto", "vrf": "GREEN"},
+ "r3-link4": {"ipv4": "auto", "ipv6": "auto"}
+ },
+ "vrfs":[
+ {"name": "RED", "id": "1"},
+ {"name": "BLUE", "id": "2"},
+ {"name": "GREEN", "id": "3"}
+ ],
+ "bgp":
+ [
+ {
+ "local_as": "4",
+ "vrf": "RED",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r4-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r4-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "4",
+ "vrf": "BLUE",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r4-link2": {}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r4-link2": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "4",
+ "vrf": "GREEN",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r4-link3": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r4-link3": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "4",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r4-link4": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r4-link4": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ]
+ },
+ "r5": {
+ "links": {
+ "r3-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED"},
+ "r3-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE"},
+ "r3-link3": {"ipv4": "auto", "ipv6": "auto", "vrf": "GREEN"},
+ "r3-link4": {"ipv4": "auto", "ipv6": "auto"}
+ },
+ "vrfs":[
+ {"name": "RED", "id": "1"},
+ {"name": "BLUE", "id": "2"},
+ {"name": "GREEN", "id": "3"}
+ ],
+ "bgp":
+ [
+ {
+ "local_as": "3",
+ "vrf": "RED",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r5-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r5-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "3",
+ "vrf": "BLUE",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r5-link2": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r5-link2": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "3",
+ "vrf": "GREEN",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r5-link3": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r5-link3": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "local_as": "3",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r5-link4": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r5-link4": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ]
+ }
+ }
+}
diff --git a/tests/topotests/bgp_vrf_lite_best_path_test/test_bgp_vrf_lite_best_path_topo1.py b/tests/topotests/bgp_vrf_lite_best_path_test/test_bgp_vrf_lite_best_path_topo1.py
new file mode 100644
index 0000000000..d9d4f4f8b2
--- /dev/null
+++ b/tests/topotests/bgp_vrf_lite_best_path_test/test_bgp_vrf_lite_best_path_topo1.py
@@ -0,0 +1,916 @@
+#!/usr/bin/env 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 VRF Lite:
+
+1. Verify BGP best path selection algorithm works fine when
+routes are imported from ISR to default vrf and vice versa.
+"""
+
+import os
+import sys
+import time
+import pytest
+import platform
+
+# 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/"))
+
+# Required to instantiate the topology builder class.
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib.topogen import Topogen, get_topogen
+from lib.topotest import version_cmp
+
+from lib.common_config import (
+ start_topology,
+ write_test_header,
+ check_address_types,
+ write_test_footer,
+ step,
+ create_route_maps,
+ create_prefix_lists,
+ check_router_status,
+ get_frr_ipv6_linklocal,
+ shutdown_bringup_interface,
+)
+
+from lib.topolog import logger
+from lib.bgp import (
+ verify_bgp_convergence,
+ create_router_bgp,
+ verify_bgp_community,
+ verify_bgp_rib,
+ clear_bgp,
+ verify_best_path_as_per_bgp_attribute
+)
+from lib.topojson import build_config_from_json
+
+
+pytestmark = [pytest.mark.bgpd, pytest.mark.staticd]
+
+# Global variables
+NETWORK1_1 = {"ipv4": "11.11.11.1/32", "ipv6": "11:11::1/128"}
+NETWORK1_2 = {"ipv4": "11.11.11.11/32", "ipv6": "11:11::11/128"}
+NETWORK1_3 = {"ipv4": "10.10.10.10/32", "ipv6": "10:10::10/128"}
+NETWORK1_4 = {"ipv4": "10.10.10.100/32", "ipv6": "10:10::100/128"}
+
+NETWORK2_1 = {"ipv4": "22.22.22.2/32", "ipv6": "22:22::2/128"}
+NETWORK2_2 = {"ipv4": "22.22.22.22/32", "ipv6": "22:22::22/128"}
+NETWORK2_3 = {"ipv4": "20.20.20.20/32", "ipv6": "20:20::20/128"}
+NETWORK2_4 = {"ipv4": "20.20.20.200/32", "ipv6": "20:20::200/128"}
+
+NETWORK3_1 = {"ipv4": "30.30.30.3/32", "ipv6": "30:30::3/128"}
+NETWORK3_2 = {"ipv4": "30.30.30.30/32", "ipv6": "30:30::30/128"}
+NETWORK3_3 = {"ipv4": "50.50.50.5/32", "ipv6": "50:50::5/128"}
+NETWORK3_4 = {"ipv4": "50.50.50.50/32", "ipv6": "50:50::50/128"}
+
+NETWORK4_1 = {"ipv4": "40.40.40.4/32", "ipv6": "40:40::4/128"}
+NETWORK4_2 = {"ipv4": "40.40.40.40/32", "ipv6": "40:40::40/128"}
+NETWORK4_3 = {"ipv4": "50.50.50.5/32", "ipv6": "50:50::5/128"}
+NETWORK4_4 = {"ipv4": "50.50.50.50/32", "ipv6": "50:50::50/128"}
+NEXT_HOP_IP = {"ipv4": "Null0", "ipv6": "Null0"}
+LOOPBACK_1 = {
+ "ipv4": "10.0.0.7/24",
+ "ipv6": "fd00:0:0:1::7/64",
+ "ipv4_mask": "255.255.255.0",
+ "ipv6_mask": None,
+}
+LOOPBACK_2 = {
+ "ipv4": "10.0.0.16/24",
+ "ipv6": "fd00:0:0:3::5/64",
+ "ipv4_mask": "255.255.255.0",
+ "ipv6_mask": None,
+}
+PREFERRED_NEXT_HOP = "global"
+
+
+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...
+ json_file = "{}/bgp_vrf_lite_best_path_topo1.json".format(CWD)
+ tgen = Topogen(json_file, mod.__name__)
+ global topo
+ topo = tgen.json_topo
+ # ... 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)
+
+ # Run these tests for kernel version 4.19 or above
+ if version_cmp(platform.release(), "4.19") < 0:
+ error_msg = (
+ "BGP vrf dynamic route leak tests will not run "
+ '(have kernel "{}", but it requires >= 4.19)'.format(platform.release())
+ )
+ pytest.skip(error_msg)
+
+ # Creating configuration from JSON
+ build_config_from_json(tgen, topo)
+
+ global BGP_CONVERGENCE
+ global ADDR_TYPES
+ ADDR_TYPES = check_address_types()
+
+ 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():
+ """Teardown the pytest environment"""
+
+ 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)
+
+
+#####################################################
+#
+# Testcases
+#
+#####################################################
+
+
+def disable_route_map_to_prefer_global_next_hop(tgen, topo):
+ """
+ This API is to remove prefer global route-map applied on neighbors
+
+ Parameter:
+ ----------
+ * `tgen` : Topogen object
+ * `topo` : Input JSON data
+
+ Returns:
+ --------
+ True/errormsg
+
+ """
+
+ logger.info("Remove prefer-global rmap applied on neighbors")
+ input_dict = {
+ "r1": {
+ "bgp": [
+ {
+ "local_as": "100",
+ "vrf": "ISR",
+ "address_family": {
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {
+ "route_maps": [
+ {
+ "name": "rmap_global",
+ "direction": "in",
+ "delete": True,
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "local_as": "100",
+ "address_family": {
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1-link1": {
+ "route_maps": [
+ {
+ "name": "rmap_global",
+ "direction": "in",
+ "delete": True,
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "local_as": "100",
+ "address_family": {
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r4": {
+ "dest_link": {
+ "r1-link1": {
+ "route_maps": [
+ {
+ "name": "rmap_global",
+ "direction": "in",
+ "delete": True,
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ },
+ ]
+ },
+ "r2": {
+ "bgp": [
+ {
+ "local_as": "100",
+ "vrf": "ISR",
+ "address_family": {
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2-link1": {
+ "route_maps": [
+ {
+ "name": "rmap_global",
+ "direction": "in",
+ "delete": True,
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "local_as": "100",
+ "address_family": {
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r2-link1": {
+ "route_maps": [
+ {
+ "name": "rmap_global",
+ "direction": "in",
+ "delete": True,
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "local_as": "100",
+ "address_family": {
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r4": {
+ "dest_link": {
+ "r2-link1": {
+ "route_maps": [
+ {
+ "name": "rmap_global",
+ "direction": "in",
+ "delete": True,
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ },
+ ]
+ },
+ "r3": {
+ "bgp": [
+ {
+ "local_as": "300",
+ "address_family": {
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3-link1": {
+ "route_maps": [
+ {
+ "name": "rmap_global",
+ "direction": "in",
+ "delete": True,
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "local_as": "300",
+ "address_family": {
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r3-link1": {
+ "route_maps": [
+ {
+ "name": "rmap_global",
+ "direction": "in",
+ "delete": True,
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ },
+ ]
+ },
+ "r4": {
+ "bgp": [
+ {
+ "local_as": "400",
+ "address_family": {
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r4-link1": {
+ "route_maps": [
+ {
+ "name": "rmap_global",
+ "direction": "in",
+ "delete": True,
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "local_as": "400",
+ "address_family": {
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r4-link1": {
+ "route_maps": [
+ {
+ "name": "rmap_global",
+ "direction": "in",
+ "delete": True,
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ },
+ ]
+ },
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict)
+ assert result is True, "Testcase :Failed \n Error: {}".format(result)
+
+ return True
+
+
+def test_bgp_best_path_with_dynamic_import_p0(request):
+ """
+ 1.5.6. Verify BGP best path selection algorithm works fine when
+ routes are imported from ISR to default vrf and vice versa.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+ build_config_from_json(tgen, topo)
+
+ if tgen.routers_have_failure():
+ check_router_status(tgen)
+
+ for addr_type in ADDR_TYPES:
+
+ step(
+ "Redistribute configured static routes into BGP process" " on R1/R2 and R3"
+ )
+
+ input_dict_1 = {}
+ DUT = ["r1", "r2", "r3", "r4"]
+ VRFS = ["ISR", "ISR", "default", "default"]
+ AS_NUM = [100, 100, 300, 400]
+
+ for dut, vrf, as_num in zip(DUT, VRFS, AS_NUM):
+ temp = {dut: {"bgp": []}}
+ input_dict_1.update(temp)
+
+ temp[dut]["bgp"].append(
+ {
+ "local_as": as_num,
+ "vrf": vrf,
+ "address_family": {
+ addr_type: {
+ "unicast": {"redistribute": [{"redist_type": "static"}]}
+ }
+ },
+ }
+ )
+
+ result = create_router_bgp(tgen, topo, input_dict_1)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+
+ step("Import from default vrf into vrf ISR on R1 and R2 as below")
+
+ input_dict_vrf = {}
+ DUT = ["r1", "r2"]
+ VRFS = ["ISR", "ISR"]
+ AS_NUM = [100, 100]
+
+ for dut, vrf, as_num in zip(DUT, VRFS, AS_NUM):
+ temp = {dut: {"bgp": []}}
+ input_dict_vrf.update(temp)
+
+ temp[dut]["bgp"].append(
+ {
+ "local_as": as_num,
+ "vrf": vrf,
+ "address_family": {
+ addr_type: {"unicast": {"import": {"vrf": "default"}}}
+ },
+ }
+ )
+
+ result = create_router_bgp(tgen, topo, input_dict_vrf)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ input_dict_default = {}
+ DUT = ["r1", "r2"]
+ VRFS = ["default", "default"]
+ AS_NUM = [100, 100]
+
+ for dut, vrf, as_num in zip(DUT, VRFS, AS_NUM):
+ temp = {dut: {"bgp": []}}
+ input_dict_default.update(temp)
+
+ temp[dut]["bgp"].append(
+ {
+ "local_as": as_num,
+ "vrf": vrf,
+ "address_family": {
+ addr_type: {"unicast": {"import": {"vrf": "ISR"}}}
+ },
+ }
+ )
+
+ result = create_router_bgp(tgen, topo, input_dict_default)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step(
+ "Verify ECMP/Next-hop/Imported routes Vs Locally originated "
+ "routes/eBGP routes vs iBGP routes --already covered in almost"
+ " all tests"
+ )
+
+ for addr_type in ADDR_TYPES:
+
+ step("Verify Pre-emption")
+
+ input_routes_r3 = {
+ "r3": {"static_routes": [{"network": [NETWORK3_3[addr_type]]}]}
+ }
+
+ intf_r3_r1 = topo["routers"]["r3"]["links"]["r1-link1"]["interface"]
+ intf_r4_r1 = topo["routers"]["r4"]["links"]["r1-link1"]["interface"]
+
+ if addr_type == "ipv6" and "link_local" in PREFERRED_NEXT_HOP:
+ nh_r3_r1 = get_frr_ipv6_linklocal(tgen, "r3", intf=intf_r3_r1)
+ nh_r4_r1 = get_frr_ipv6_linklocal(tgen, "r4", intf=intf_r4_r1)
+ else:
+ nh_r3_r1 = topo["routers"]["r3"]["links"]["r1-link1"][addr_type].split("/")[
+ 0
+ ]
+ nh_r4_r1 = topo["routers"]["r4"]["links"]["r1-link1"][addr_type].split("/")[
+ 0
+ ]
+
+ result = verify_bgp_rib(
+ tgen, addr_type, "r1", input_routes_r3, next_hop=[nh_r4_r1]
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Shutdown interface connected to r1 from r4:")
+ shutdown_bringup_interface(tgen, "r4", intf_r4_r1, False)
+
+ for addr_type in ADDR_TYPES:
+
+ input_routes_r3 = {
+ "r3": {"static_routes": [{"network": [NETWORK3_3[addr_type]]}]}
+ }
+
+ intf_r3_r1 = topo["routers"]["r3"]["links"]["r1-link1"]["interface"]
+ intf_r4_r1 = topo["routers"]["r4"]["links"]["r1-link1"]["interface"]
+
+ if addr_type == "ipv6" and "link_local" in PREFERRED_NEXT_HOP:
+ nh_r3_r1 = get_frr_ipv6_linklocal(tgen, "r3", intf=intf_r3_r1)
+ nh_r4_r1 = get_frr_ipv6_linklocal(tgen, "r4", intf=intf_r4_r1)
+ else:
+ nh_r3_r1 = topo["routers"]["r3"]["links"]["r1-link1"][addr_type].split("/")[
+ 0
+ ]
+ nh_r4_r1 = topo["routers"]["r4"]["links"]["r1-link1"][addr_type].split("/")[
+ 0
+ ]
+
+ step("Verify next-hop is changed")
+ result = verify_bgp_rib(
+ tgen, addr_type, "r1", input_routes_r3, next_hop=[nh_r3_r1]
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Bringup interface connected to r1 from r4:")
+ shutdown_bringup_interface(tgen, "r4", intf_r4_r1, True)
+
+ for addr_type in ADDR_TYPES:
+
+ input_routes_r3 = {
+ "r3": {"static_routes": [{"network": [NETWORK3_3[addr_type]]}]}
+ }
+
+ intf_r3_r1 = topo["routers"]["r3"]["links"]["r1-link1"]["interface"]
+ intf_r4_r1 = topo["routers"]["r4"]["links"]["r1-link1"]["interface"]
+
+ if addr_type == "ipv6" and "link_local" in PREFERRED_NEXT_HOP:
+ nh_r3_r1 = get_frr_ipv6_linklocal(tgen, "r3", intf=intf_r3_r1)
+ nh_r4_r1 = get_frr_ipv6_linklocal(tgen, "r4", intf=intf_r4_r1)
+ else:
+ nh_r3_r1 = topo["routers"]["r3"]["links"]["r1-link1"][addr_type].split("/")[
+ 0
+ ]
+ nh_r4_r1 = topo["routers"]["r4"]["links"]["r1-link1"][addr_type].split("/")[
+ 0
+ ]
+
+ step("Verify next-hop is not chnaged aftr shutdown:")
+ result = verify_bgp_rib(
+ tgen, addr_type, "r1", input_routes_r3, next_hop=[nh_r3_r1]
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Active-Standby scenario(as-path prepend and Local pref)")
+
+ for addr_type in ADDR_TYPES:
+
+ step("Create prefix-list")
+
+ input_dict_pf = {
+ "r1": {
+ "prefix_lists": {
+ addr_type: {
+ "pf_ls_{}".format(addr_type): [
+ {
+ "seqid": 10,
+ "network": NETWORK3_4[addr_type],
+ "action": "permit",
+ }
+ ]
+ }
+ }
+ }
+ }
+ result = create_prefix_lists(tgen, input_dict_pf)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+
+ step("Create route-map to match prefix-list and set localpref 500")
+
+ input_dict_rm = {
+ "r1": {
+ "route_maps": {
+ "rmap_PATH1_{}".format(addr_type): [
+ {
+ "action": "permit",
+ "seq_id": 10,
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_ls_{}".format(addr_type)
+ }
+ },
+ "set": {"locPrf": 500},
+ }
+ ]
+ }
+ }
+ }
+
+ result = create_route_maps(tgen, input_dict_rm)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Create route-map to match prefix-list and set localpref 600")
+
+ input_dict_rm = {
+ "r1": {
+ "route_maps": {
+ "rmap_PATH2_{}".format(addr_type): [
+ {
+ "action": "permit",
+ "seq_id": 20,
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_ls_{}".format(addr_type)
+ }
+ },
+ "set": {"locPrf": 600},
+ }
+ ]
+ }
+ }
+ }
+
+ result = create_route_maps(tgen, input_dict_rm)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ input_dict_rma = {
+ "r1": {
+ "bgp": [
+ {
+ "local_as": "100",
+ "address_family": {
+ addr_type: {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1-link1": {
+ "route_maps": [
+ {
+ "name": "rmap_PATH1_{}".format(
+ addr_type
+ ),
+ "direction": "in",
+ }
+ ]
+ }
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r1-link1": {
+ "route_maps": [
+ {
+ "name": "rmap_PATH2_{}".format(
+ addr_type
+ ),
+ "direction": "in",
+ }
+ ]
+ }
+ }
+ },
+ }
+ }
+ }
+ },
+ }
+ ]
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_rma)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ dut = "r1"
+ attribute = "locPrf"
+
+ for addr_type in ADDR_TYPES:
+
+ step("Verify bestpath is installed as per highest localpref")
+
+ input_routes_r3 = {
+ "r3": {
+ "static_routes": [
+ {"network": [NETWORK3_3[addr_type], NETWORK3_4[addr_type]]}
+ ]
+ }
+ }
+
+ result = verify_best_path_as_per_bgp_attribute(
+ tgen, addr_type, dut, input_routes_r3, attribute
+ )
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+
+ step("Create route-map to match prefix-list and set localpref 700")
+
+ input_dict_rm = {
+ "r1": {
+ "route_maps": {
+ "rmap_PATH1_{}".format(addr_type): [
+ {
+ "action": "permit",
+ "seq_id": 10,
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_ls_{}".format(addr_type)
+ }
+ },
+ "set": {"locPrf": 700},
+ }
+ ]
+ }
+ }
+ }
+
+ result = create_route_maps(tgen, input_dict_rm)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+
+ step("Verify bestpath is changed as per highest localpref")
+
+ input_routes_r3 = {
+ "r3": {
+ "static_routes": [
+ {"network": [NETWORK3_3[addr_type], NETWORK3_4[addr_type]]}
+ ]
+ }
+ }
+
+ result = verify_best_path_as_per_bgp_attribute(
+ tgen, addr_type, dut, input_routes_r3, attribute
+ )
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+
+ step("Create route-map to match prefix-list and set as-path prepend")
+
+ input_dict_rm = {
+ "r1": {
+ "route_maps": {
+ "rmap_PATH2_{}".format(addr_type): [
+ {
+ "action": "permit",
+ "seq_id": 20,
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_ls_{}".format(addr_type)
+ }
+ },
+ "set": {
+ "localpref": 700,
+ "path": {"as_num": "111", "as_action": "prepend"},
+ },
+ }
+ ]
+ }
+ }
+ }
+
+ result = create_route_maps(tgen, input_dict_rm)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ attribute = "path"
+
+ for addr_type in ADDR_TYPES:
+
+ step("Verify bestpath is changed as per shortest as-path")
+
+ input_routes_r3 = {
+ "r3": {
+ "static_routes": [
+ {"network": [NETWORK3_3[addr_type], NETWORK3_4[addr_type]]}
+ ]
+ }
+ }
+
+ result = verify_best_path_as_per_bgp_attribute(
+ tgen, addr_type, dut, input_routes_r3, attribute
+ )
+ 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_vrf_lite_best_path_test/test_bgp_vrf_lite_best_path_topo2.py b/tests/topotests/bgp_vrf_lite_best_path_test/test_bgp_vrf_lite_best_path_topo2.py
new file mode 100644
index 0000000000..e930b62706
--- /dev/null
+++ b/tests/topotests/bgp_vrf_lite_best_path_test/test_bgp_vrf_lite_best_path_topo2.py
@@ -0,0 +1,539 @@
+#!/usr/bin/env python
+
+#
+# Copyright (c) 2021 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 VRF Lite:
+1. Verify that locally imported routes are selected as best path over eBGP imported routes
+ peers.
+2. Verify ECMP for imported routes from different VRFs.
+"""
+
+import os
+import sys
+import time
+import pytest
+import platform
+from time import sleep
+
+# 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/"))
+
+# Required to instantiate the topology builder class.
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib.topogen import Topogen, get_topogen
+from lib.topotest import version_cmp
+
+from lib.common_config import (
+ start_topology,
+ write_test_header,
+ check_address_types,
+ write_test_footer,
+ reset_config_on_routers,
+ verify_rib,
+ step,
+ create_static_routes,
+ check_router_status,
+ apply_raw_config
+)
+
+from lib.topolog import logger
+from lib.bgp import (
+ verify_bgp_convergence,
+ create_router_bgp,
+ verify_bgp_rib,
+ verify_bgp_bestpath
+)
+from lib.topojson import build_config_from_json
+
+pytestmark = [pytest.mark.bgpd, pytest.mark.staticd]
+
+# Global variables
+NETWORK1_1 = {"ipv4": "11.11.11.1/32", "ipv6": "11:11::1/128"}
+NETWORK1_2 = {"ipv4": "11.11.11.11/32", "ipv6": "11:11::11/128"}
+NETWORK1_3 = {"ipv4": "10.10.10.1/32", "ipv6": "10:10::1/128"}
+NETWORK1_4 = {"ipv4": "10.10.10.100/32", "ipv6": "10:10::100/128"}
+NETWORK1_5 = {"ipv4": "110.110.110.1/32", "ipv6": "110:110::1/128"}
+NETWORK1_6 = {"ipv4": "110.110.110.100/32", "ipv6": "110:110::100/128"}
+
+NETWORK2_1 = {"ipv4": "22.22.22.2/32", "ipv6": "22:22::2/128"}
+NETWORK2_2 = {"ipv4": "22.22.22.22/32", "ipv6": "22:22::22/128"}
+NETWORK2_3 = {"ipv4": "20.20.20.20/32", "ipv6": "20:20::20/128"}
+NETWORK2_4 = {"ipv4": "20.20.20.200/32", "ipv6": "20:20::200/128"}
+NETWORK2_5 = {"ipv4": "220.220.220.20/32", "ipv6": "220:220::20/128"}
+NETWORK2_6 = {"ipv4": "220.220.220.200/32", "ipv6": "220:220::200/128"}
+
+NETWORK3_1 = {"ipv4": "30.30.30.3/32", "ipv6": "30:30::3/128"}
+NETWORK3_2 = {"ipv4": "30.30.30.30/32", "ipv6": "30:30::30/128"}
+
+PREFIX_LIST = {
+ "ipv4": ["11.11.11.1", "22.22.22.2", "22.22.22.22"],
+ "ipv6": ["11:11::1", "22:22::2", "22:22::22"],
+}
+PREFERRED_NEXT_HOP = "global"
+VRF_LIST = ["RED", "BLUE", "GREEN"]
+COMM_VAL_1 = "100:100"
+COMM_VAL_2 = "500:500"
+COMM_VAL_3 = "600:600"
+BESTPATH = {
+ "ipv4": "0.0.0.0",
+ "ipv6": "::"
+}
+
+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...
+ json_file = "{}/bgp_vrf_lite_best_path_topo2.json".format(CWD)
+ tgen = Topogen(json_file, mod.__name__)
+ global topo
+ topo = tgen.json_topo
+ # ... 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)
+
+ # Run these tests for kernel version 4.19 or above
+ if version_cmp(platform.release(), "4.19") < 0:
+ error_msg = (
+ "BGP vrf dynamic route leak tests will not run "
+ '(have kernel "{}", but it requires >= 4.19)'.format(platform.release())
+ )
+ pytest.skip(error_msg)
+
+ # Creating configuration from JSON
+ build_config_from_json(tgen, topo)
+
+ global BGP_CONVERGENCE
+ global ADDR_TYPES
+ ADDR_TYPES = check_address_types()
+
+ 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():
+ """Teardown the pytest environment"""
+
+ 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)
+
+
+#####################################################
+#
+# Testcases
+#
+#####################################################
+
+def test_dynamic_import_ecmp_imported_routed_diffrent_vrfs_p0(request):
+ """
+ Verify ECMP for imported routes from different VRFs.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+ if tgen.routers_have_failure():
+ check_router_status(tgen)
+ reset_config_on_routers(tgen)
+
+ step("Configure same static routes in tenant vrfs RED and GREEN on router "
+ "R3 and redistribute in respective BGP process")
+
+ for vrf_name in ["RED", "GREEN"]:
+ for addr_type in ADDR_TYPES:
+ if vrf_name == "GREEN":
+ next_hop_vrf = topo["routers"]["r1"]["links"][
+ "r3-link3"][addr_type].split("/")[0]
+ else:
+ next_hop_vrf = topo["routers"]["r2"]["links"][
+ "r3-link1"][addr_type].split("/")[0]
+ static_routes = {
+ "r3": {
+ "static_routes": [
+ {
+ "network": [NETWORK1_1[addr_type]],
+ "next_hop": next_hop_vrf,
+ "vrf": vrf_name
+ }
+ ]
+ }
+ }
+
+ result = create_static_routes(tgen, static_routes)
+ assert result is True, "Testcase {} :Failed \n Error: {}". \
+ format(tc_name, result)
+
+ step("Redistribute static route on BGP VRF : {}".format(vrf_name))
+ temp = {}
+ for addr_type in ADDR_TYPES:
+ temp.update({
+ addr_type: {
+ "unicast": {
+ "redistribute": [{
+ "redist_type": "static"
+ }]
+ }
+ }
+ })
+
+ redist_dict = {"r3": {"bgp": [{
+ "vrf": vrf_name, "local_as": 3, "address_family": temp
+ }]}}
+
+ result = create_router_bgp(tgen, topo, redist_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}". \
+ format(tc_name, result)
+
+ step("Verify that configured static routes are installed in respective "
+ "BGP table for vrf RED & GREEN")
+ for vrf_name in ["RED", "GREEN"]:
+ for addr_type in ADDR_TYPES:
+ if vrf_name == "GREEN":
+ next_hop_vrf = topo["routers"]["r1"]["links"][
+ "r3-link3"][addr_type].split("/")[0]
+ else:
+ next_hop_vrf = topo["routers"]["r2"]["links"][
+ "r3-link1"][addr_type].split("/")[0]
+ static_routes = {
+ "r3": {
+ "static_routes": [
+ {
+ "network": [NETWORK1_1[addr_type]],
+ "vrf": vrf_name
+ }
+ ]
+ }
+ }
+
+ result = verify_bgp_rib(tgen, addr_type, "r3", static_routes,
+ next_hop=next_hop_vrf)
+ assert result is True, "Testcase {} : Failed \n Error {}". \
+ format(tc_name, result)
+
+ result = verify_rib(tgen, addr_type, "r3", static_routes,
+ next_hop=next_hop_vrf)
+ assert result is True, "Testcase {} : Failed \n Error {}". \
+ format(tc_name, result)
+
+ step("Import vrf RED and GREEN into default vrf and Configure ECMP")
+ bgp_val = []
+ for vrf_name in ["RED", "GREEN"]:
+ temp = {}
+ for addr_type in ADDR_TYPES:
+ temp.update({
+ addr_type: {
+ "unicast": {
+ "import": {
+ "vrf": vrf_name
+ },
+ "maximum_paths": {
+ "ebgp": 2
+ }
+ }
+ }
+ })
+
+ bgp_val.append({
+ "local_as": 3, "address_family": temp
+ })
+
+ import_dict = {"r3": {"bgp": bgp_val}}
+
+ result = create_router_bgp(tgen, topo, import_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}". \
+ format(tc_name, result)
+
+ step("Configure bgp bestpath on router r3")
+ r3_raw_config = {
+ "r3": {
+ "raw_config": [
+ "router bgp 3",
+ "bgp bestpath as-path multipath-relax"
+ ]
+ }
+ }
+ result = apply_raw_config(tgen, r3_raw_config)
+ assert result is True, "Testcase {} :Failed \n Error: {}". \
+ format(tc_name, result)
+
+ step("Verify that routes are imported with two different next-hop vrfs "
+ "and IPs. Additionally R3 must do ECMP for both the routes.")
+
+ for addr_type in ADDR_TYPES:
+ next_hop_vrf = [
+ topo["routers"]["r2"]["links"]["r3-link1"][addr_type]. \
+ split("/")[0],
+ topo["routers"]["r1"]["links"]["r3-link3"][addr_type]. \
+ split("/")[0]
+ ]
+ static_routes = {
+ "r3": {
+ "static_routes": [
+ {
+ "network": [NETWORK1_1[addr_type]],
+ }
+ ]
+ }
+ }
+
+ result = verify_bgp_rib(tgen, addr_type, "r3", static_routes,
+ next_hop=next_hop_vrf)
+ assert result is True, "Testcase {} : Failed \n Error {}". \
+ format(tc_name, result)
+
+ result = verify_rib(tgen, addr_type, "r3", static_routes,
+ next_hop=next_hop_vrf)
+ assert result is True, "Testcase {} : Failed \n Error {}". \
+ format(tc_name, result)
+
+ step("Now change the next-hop of static routes in vrf RED and GREEN to "
+ "same IP address")
+ for addr_type in ADDR_TYPES:
+ next_hop_vrf = topo["routers"]["r1"]["links"][
+ "r3-link3"][addr_type].split("/")[0]
+ static_routes = {
+ "r3": {
+ "static_routes": [
+ {
+ "network": [NETWORK1_1[addr_type]],
+ "next_hop": next_hop_vrf,
+ "vrf": "RED"
+ },
+ {
+ "network": [NETWORK1_1[addr_type]],
+ "next_hop": topo["routers"]["r2"]["links"][
+ "r3-link1"][addr_type].split("/")[0],
+ "vrf": "RED",
+ "delete": True
+ }
+ ]
+ }
+ }
+
+ result = create_static_routes(tgen, static_routes)
+ assert result is True, "Testcase {} :Failed \n Error: {}". \
+ format(tc_name, result)
+
+ step("Verify that now routes are imported with two different next-hop "
+ "vrfs but same IPs. Additionally R3 must do ECMP for both the routes")
+
+ for addr_type in ADDR_TYPES:
+ next_hop_vrf = [
+ topo["routers"]["r1"]["links"]["r3-link3"][addr_type].\
+ split("/")[0],
+ topo["routers"]["r1"]["links"]["r3-link3"][addr_type]. \
+ split("/")[0]
+ ]
+ static_routes = {
+ "r3": {
+ "static_routes": [
+ {
+ "network": [NETWORK1_1[addr_type]],
+ }
+ ]
+ }
+ }
+
+ result = verify_bgp_rib(tgen, addr_type, "r3", static_routes,
+ next_hop=next_hop_vrf)
+ assert result is True, "Testcase {} : Failed \n Error {}". \
+ format(tc_name, result)
+
+ result = verify_rib(tgen, addr_type, "r3", static_routes,
+ next_hop=next_hop_vrf)
+ assert result is True, "Testcase {} : Failed \n Error {}". \
+ format(tc_name, result)
+
+ write_test_footer(tc_name)
+
+
+def test_locally_imported_routes_selected_as_bestpath_over_ebgp_imported_routes_p0(request):
+ """
+ Verify ECMP for imported routes from different VRFs.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+ if tgen.routers_have_failure():
+ check_router_status(tgen)
+ reset_config_on_routers(tgen)
+
+ step("Configure same static routes on R2 and R3 vrfs and redistribute in BGP "
+ "for GREEN and RED vrf instances")
+ for dut, network in zip(["r2", "r3"], [
+ [NETWORK1_1, NETWORK1_2], [NETWORK1_1, NETWORK1_2]]):
+ for vrf_name, network_vrf in zip(["RED", "GREEN"], network):
+ step("Configure static route for VRF : {} on {}".format(vrf_name,
+ dut))
+ for addr_type in ADDR_TYPES:
+ static_routes = {
+ dut: {
+ "static_routes": [
+ {
+ "network": [network_vrf[addr_type]],
+ "next_hop": "blackhole",
+ "vrf": vrf_name
+ }
+ ]
+ }
+ }
+
+ result = create_static_routes(tgen, static_routes)
+ assert result is True, "Testcase {} :Failed \n Error: {}". \
+ format(tc_name, result)
+
+ for dut, as_num in zip(["r2", "r3"], ["2", "3"]):
+ for vrf_name in ["RED", "GREEN"]:
+ step("Redistribute static route on BGP VRF : {}".format(vrf_name))
+ temp = {}
+ for addr_type in ADDR_TYPES:
+ temp.update({
+ addr_type: {
+ "unicast": {
+ "redistribute": [{
+ "redist_type": "static"
+ }]
+ }
+ }
+ })
+
+ redist_dict = {dut: {"bgp": [{
+ "vrf": vrf_name, "local_as": as_num, "address_family": temp
+ }]}}
+
+ result = create_router_bgp(tgen, topo, redist_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}". \
+ format(tc_name, result)
+
+ step("Verify that R2 and R3 has installed redistributed routes in default "
+ "and RED vrfs and GREEN respectively:")
+ for dut, network in zip(["r2", "r3"],
+ [[NETWORK1_1, NETWORK1_2],
+ [NETWORK1_1, NETWORK1_2]]):
+ for vrf_name, network_vrf in zip(["RED", "GREEN"], network):
+ for addr_type in ADDR_TYPES:
+ static_routes = {
+ dut: {
+ "static_routes": [
+ {
+ "network": [network_vrf[addr_type]],
+ "next_hop": "blackhole",
+ "vrf": vrf_name
+ }
+ ]
+ }
+ }
+ result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}". \
+ format(tc_name, result)
+
+ step("Import vrf RED's route in vrf GREEN on R3")
+ temp = {}
+ for addr_type in ADDR_TYPES:
+ temp.update({
+ addr_type: {
+ "unicast": {
+ "import": {
+ "vrf": "RED"
+ }
+ }
+ }
+ })
+
+ import_dict = {"r3": {"bgp": [{
+ "vrf": "GREEN", "local_as": 3, "address_family": temp
+ }]}}
+
+ result = create_router_bgp(tgen, topo, import_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}". \
+ format(tc_name, result)
+
+ step("Verify that locally imported routes are installed over eBGP imported"
+ " routes from VRF RED into VRF GREEN")
+ for addr_type in ADDR_TYPES:
+ static_routes = {
+ "r3": {
+ "static_routes": [
+ {
+ "network": [NETWORK1_2[addr_type]],
+ "next_hop": "blackhole",
+ "vrf": "GREEN"
+ }
+ ]
+ }
+ }
+
+ input_routes = {
+ "r3": {
+ addr_type: [
+ {
+ "network": NETWORK1_2[addr_type],
+ "bestpath": BESTPATH[addr_type],
+ "vrf": "GREEN"
+ }
+ ]
+ }
+ }
+
+ result = verify_bgp_bestpath(tgen, addr_type, input_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}". \
+ format(tc_name, result)
+
+ result = verify_rib(tgen, addr_type, "r3", static_routes)
+ 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_vrf_netns/peer1/exa-send.py b/tests/topotests/bgp_vrf_netns/peer1/exa-send.py
index 9279cc45ff..ab0eb8ce8f 100755
--- a/tests/topotests/bgp_vrf_netns/peer1/exa-send.py
+++ b/tests/topotests/bgp_vrf_netns/peer1/exa-send.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
exa-send.py: Send a few testroutes with ExaBGP
diff --git a/tests/topotests/conftest.py b/tests/topotests/conftest.py
index ce7878c240..3e1e6eb79b 100755
--- a/tests/topotests/conftest.py
+++ b/tests/topotests/conftest.py
@@ -9,6 +9,7 @@ import re
import subprocess
import sys
import time
+import resource
import pytest
import lib.fixtures
@@ -221,6 +222,9 @@ def pytest_configure(config):
is_xdist = True
is_worker = True
+ resource.setrlimit(
+ resource.RLIMIT_CORE, (resource.RLIM_INFINITY, resource.RLIM_INFINITY)
+ )
# -----------------------------------------------------
# Set some defaults for the pytest.ini [pytest] section
# ---------------------------------------------------
@@ -505,5 +509,6 @@ def pytest_runtest_makereport(item, call):
#
# Add common fixtures available to all tests as parameters
#
+
tgen = pytest.fixture(lib.fixtures.tgen)
topo = pytest.fixture(lib.fixtures.topo)
diff --git a/tests/topotests/isis_topo1_vrf/test_isis_topo1_vrf.py b/tests/topotests/isis_topo1_vrf/test_isis_topo1_vrf.py
index a0cae0a40b..ff9ad6150a 100644
--- a/tests/topotests/isis_topo1_vrf/test_isis_topo1_vrf.py
+++ b/tests/topotests/isis_topo1_vrf/test_isis_topo1_vrf.py
@@ -175,11 +175,19 @@ def test_isis_route_installation():
for rname, router in tgen.routers().items():
filename = "{0}/{1}/{1}_route.json".format(CWD, rname)
expected = json.loads(open(filename, "r").read())
- actual = router.vtysh_cmd(
- "show ip route vrf {0}-cust1 json".format(rname), isjson=True
- )
- assertmsg = "Router '{}' routes mismatch".format(rname)
- assert topotest.json_cmp(actual, expected) is None, assertmsg
+
+ def compare_routing_table(router, expected):
+ "Helper function to ensure zebra rib convergence"
+
+ actual = router.vtysh_cmd(
+ "show ip route vrf {0}-cust1 json".format(rname), isjson=True
+ )
+ return topotest.json_cmp(actual, expected)
+
+ test_func = functools.partial(compare_routing_table, router, expected)
+ (result, diff) = topotest.run_and_expect(test_func, None, count=20, wait=1)
+ assertmsg = "Router '{}' routes mismatch diff: {}".format(rname, diff)
+ assert result, assertmsg
def test_isis_linux_route_installation():
@@ -220,12 +228,18 @@ def test_isis_route6_installation():
for rname, router in tgen.routers().items():
filename = "{0}/{1}/{1}_route6.json".format(CWD, rname)
expected = json.loads(open(filename, "r").read())
- actual = router.vtysh_cmd(
- "show ipv6 route vrf {}-cust1 json".format(rname), isjson=True
- )
- assertmsg = "Router '{}' routes mismatch".format(rname)
- assert topotest.json_cmp(actual, expected) is None, assertmsg
+ def compare_routing_table(router, expected):
+ "Helper function to ensure zebra rib convergence"
+ actual = router.vtysh_cmd(
+ "show ipv6 route vrf {}-cust1 json".format(rname), isjson=True
+ )
+ return topotest.json_cmp(actual, expected)
+
+ test_func = functools.partial(compare_routing_table, router, expected)
+ (result, diff) = topotest.run_and_expect(test_func, None, count=20, wait=1)
+ assertmsg = "Router '{}' routes mismatch diff: ".format(rname, diff)
+ assert result, assertmsg
def test_isis_linux_route6_installation():
diff --git a/tests/topotests/lib/bgp.py b/tests/topotests/lib/bgp.py
index 458ae4b054..3253fe6900 100644
--- a/tests/topotests/lib/bgp.py
+++ b/tests/topotests/lib/bgp.py
@@ -989,6 +989,14 @@ def __create_bgp_unicast_address_family(
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 "shutdown" in peer:
+ shut_val = peer["shutdown"]
+ if shut_val is True:
+ config_data.append("{} shutdown".format(neigh_cxt))
+ elif shut_val is False:
+ config_data.append("no {} shutdown".format(neigh_cxt))
+
if prefix_lists:
for prefix_list in prefix_lists:
name = prefix_list.setdefault("name", {})
@@ -2221,6 +2229,7 @@ def verify_bgp_attributes(
rmap_name=None,
input_dict=None,
seq_id=None,
+ vrf=None,
nexthop=None,
expected=True,
):
@@ -2275,7 +2284,10 @@ def verify_bgp_attributes(
logger.info("Verifying BGP set attributes for dut {}:".format(router))
for static_route in static_routes:
- cmd = "show bgp {} {} json".format(addr_type, static_route)
+ if vrf:
+ cmd = "show bgp vrf {} {} {} json".format(vrf, addr_type, static_route)
+ else:
+ cmd = "show bgp {} {} json".format(addr_type, static_route)
show_bgp_json = run_frr_cmd(rnode, cmd, isjson=True)
dict_to_test = []
@@ -2821,7 +2833,6 @@ def verify_bgp_rib(
st_rt,
dut,
)
- return errormsg
else:
nh_found = True
@@ -4428,6 +4439,83 @@ def verify_evpn_routes(
logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
return False
+
+
+@retry(retry_timeout=10)
+def verify_bgp_bestpath(tgen, addr_type, input_dict):
+ """
+ Verifies bgp next hop values in best-path output
+
+ * `dut` : device under test
+ * `addr_type` : Address type ipv4/ipv6
+ * `input_dict`: having details like multipath and bestpath
+
+ Usage
+ -----
+ input_dict_1 = {
+ "r1": {
+ "ipv4" : {
+ "bestpath": "50.0.0.1",
+ "multipath": ["50.0.0.1", "50.0.0.2"],
+ "network": "100.0.0.0/24"
+ }
+ "ipv6" : {
+ "bestpath": "1000::1",
+ "multipath": ["1000::1", "1000::2"]
+ "network": "2000::1/128"
+ }
+ }
+ }
+
+ result = verify_bgp_bestpath(tgen, input_dict)
+
+ """
+
+ result = False
+ logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
+ for dut in input_dict.keys():
+ rnode = tgen.routers()[dut]
+
+ logger.info("[DUT: %s]: Verifying bgp bestpath and multipath " "routes:", dut)
+ result = False
+ for network_dict in input_dict[dut][addr_type]:
+ nw_addr = network_dict.setdefault("network", None)
+ vrf = network_dict.setdefault("vrf", None)
+ bestpath = network_dict.setdefault("bestpath", None)
+
+ if vrf:
+ cmd = "show bgp vrf {} {} {} bestpath json".format(
+ vrf, addr_type, nw_addr
+ )
+ else:
+ cmd = "show bgp {} {} bestpath json".format(addr_type, nw_addr)
+
+ data = run_frr_cmd(rnode, cmd, isjson=True)
+ route = data["paths"][0]
+
+ if "bestpath" in route:
+ if route["bestpath"]["overall"] is True:
+ _bestpath = route["nexthops"][0]["ip"]
+
+ if _bestpath != bestpath:
+ return (
+ "DUT:[{}] Bestpath do not match for"
+ " network: {}, Expected "
+ " {} as bgp bestpath found {}".format(
+ dut, nw_addr, bestpath, _bestpath
+ )
+ )
+
+ logger.info(
+ "DUT:[{}] Found expected bestpath: "
+ " {} for network: {}".format(dut, _bestpath, nw_addr)
+ )
+ result = True
+
+ logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
+ return result
+
+
def verify_tcp_mss(tgen, dut, neighbour, configured_tcp_mss, vrf=None):
"""
This api is used to verify the tcp-mss value assigned to a neigbour of DUT
diff --git a/tests/topotests/lib/common_config.py b/tests/topotests/lib/common_config.py
index cf8efdea16..c744e5bbbf 100644
--- a/tests/topotests/lib/common_config.py
+++ b/tests/topotests/lib/common_config.py
@@ -26,6 +26,7 @@ import socket
import subprocess
import sys
import traceback
+import functools
from collections import OrderedDict
from copy import deepcopy
from datetime import datetime, timedelta
@@ -2970,24 +2971,34 @@ def addKernelRoute(
logger.info("[DUT: {}]: Running command: [{}]".format(router, cmd))
output = rnode.run(cmd)
- # Verifying if ip route added to kernal
- result = rnode.run(verify_cmd)
- logger.debug("{}\n{}".format(verify_cmd, result))
- if "/" in grp_addr:
- ip, mask = grp_addr.split("/")
- if mask == "32" or mask == "128":
- grp_addr = ip
- else:
- mask = "32" if addr_type == "ipv4" else "128"
+ def check_in_kernel(rnode, verify_cmd, grp_addr, router):
+ # Verifying if ip route added to kernal
+ errormsg = None
+ result = rnode.run(verify_cmd)
+ logger.debug("{}\n{}".format(verify_cmd, result))
+ if "/" in grp_addr:
+ ip, mask = grp_addr.split("/")
+ if mask == "32" or mask == "128":
+ grp_addr = ip
+ else:
+ mask = "32" if addr_type == "ipv4" else "128"
- if not re_search(r"{}".format(grp_addr), result) and mask != "0":
- errormsg = (
- "[DUT: {}]: Kernal route is not added for group"
- " address {} Config output: {}".format(router, grp_addr, output)
- )
+ if not re_search(r"{}".format(grp_addr), result) and mask != "0":
+ errormsg = (
+ "[DUT: {}]: Kernal route is not added for group"
+ " address {} Config output: {}".format(
+ router, grp_addr, output
+ )
+ )
return errormsg
+ test_func = functools.partial(
+ check_in_kernel, rnode, verify_cmd, grp_addr, router
+ )
+ (result, out) = topotest.run_and_expect(test_func, None, count=20, wait=1)
+ assert result, out
+
logger.debug("Exiting lib API: addKernelRoute()")
return True
diff --git a/tests/topotests/lib/ospf.py b/tests/topotests/lib/ospf.py
index c425e121af..92d29ad1ab 100644
--- a/tests/topotests/lib/ospf.py
+++ b/tests/topotests/lib/ospf.py
@@ -265,35 +265,6 @@ def __create_ospf_global(tgen, input_dict, router, build, load_config, ospf):
cmd = "no {}".format(cmd)
config_data.append(cmd)
- # area interface information for ospf6d only
- if ospf == "ospf6":
- area_iface = ospf_data.setdefault("neighbors", {})
- if area_iface:
- for neighbor in area_iface:
- if "area" in area_iface[neighbor]:
- iface = input_dict[router]["links"][neighbor]["interface"]
- cmd = "interface {} area {}".format(
- iface, area_iface[neighbor]["area"]
- )
- if area_iface[neighbor].setdefault("delete", False):
- cmd = "no {}".format(cmd)
- config_data.append(cmd)
-
- try:
- if "area" in input_dict[router]["links"][neighbor]["ospf6"]:
- iface = input_dict[router]["links"][neighbor]["interface"]
- cmd = "interface {} area {}".format(
- iface,
- input_dict[router]["links"][neighbor]["ospf6"]["area"],
- )
- if input_dict[router]["links"][neighbor].setdefault(
- "delete", False
- ):
- cmd = "no {}".format(cmd)
- config_data.append(cmd)
- except KeyError:
- pass
-
# summary information
summary_data = ospf_data.setdefault("summary-address", {})
if summary_data:
@@ -363,69 +334,6 @@ def __create_ospf_global(tgen, input_dict, router, build, load_config, ospf):
return config_data
-def create_router_ospf6(
- tgen, topo=None, input_dict=None, build=False, load_config=True
-):
- """
- API to configure ospf on router
-
- Parameters
- ----------
- * `tgen` : Topogen object
- * `topo` : json file data
- * `input_dict` : Input dict data, required when configuring from testcase
- * `build` : Only for initial setup phase this is set as True.
-
- Usage
- -----
- input_dict = {
- "r1": {
- "ospf6": {
- "router_id": "22.22.22.22",
- }
- }
-
- Returns
- -------
- True or False
- """
- logger.debug("Entering lib API: create_router_ospf6()")
- result = False
-
- if topo is None:
- topo = tgen.json_topo
-
- if not input_dict:
- input_dict = deepcopy(topo)
- else:
- topo = topo["routers"]
- input_dict = deepcopy(input_dict)
-
- config_data_dict = {}
-
- for router in input_dict.keys():
- if "ospf6" not in input_dict[router]:
- logger.debug("Router %s: 'ospf6' not present in input_dict", router)
- continue
-
- config_data = __create_ospf_global(
- tgen, input_dict, router, build, load_config, "ospf6"
- )
- if config_data:
- config_data_dict[router] = config_data
-
- try:
- result = create_common_configurations(
- tgen, config_data_dict, "ospf6", build, load_config
- )
- except InvalidCLIError:
- logger.error("create_router_ospf6", exc_info=True)
- result = False
-
- logger.debug("Exiting lib API: create_router_ospf6()")
- return result
-
-
def config_ospf_interface(
tgen, topo=None, input_dict=None, build=False, load_config=True
):
@@ -874,6 +782,16 @@ def verify_ospf6_neighbor(tgen, topo=None, dut=None, input_dict=None, lan=False)
}
result = verify_ospf6_neighbor(tgen, topo, dut, input_dict, lan=True)
+ 3. To check there are no neighbors.
+ input_dict = {
+ "r0": {
+ "ospf6": {
+ "neighbors": []
+ }
+ }
+ }
+ result = verify_ospf6_neighbor(tgen, topo, dut, input_dict)
+
Returns
-------
True or False (Error Message)
@@ -904,6 +822,19 @@ def verify_ospf6_neighbor(tgen, topo=None, dut=None, input_dict=None, lan=False)
ospf_data_list = input_dict[router]["ospf6"]
ospf_nbr_list = ospf_data_list["neighbors"]
+ # Check if looking for no neighbors
+ if ospf_nbr_list == []:
+ if show_ospf_json["neighbors"] == []:
+ logger.info("[DUT: {}] OSPF6 no neighbors found".format(router))
+ return True
+ else:
+ errormsg = (
+ "[DUT: {}] OSPF6 active neighbors found, expected None".format(
+ router
+ )
+ )
+ return errormsg
+
for ospf_nbr, nbr_data in ospf_nbr_list.items():
try:
diff --git a/tests/topotests/lib/pim.py b/tests/topotests/lib/pim.py
index 944981add4..dd2f787014 100644
--- a/tests/topotests/lib/pim.py
+++ b/tests/topotests/lib/pim.py
@@ -21,8 +21,10 @@ import os
import re
import sys
import traceback
+import functools
from copy import deepcopy
from time import sleep
+from lib import topotest
# Import common_config to use commomnly used APIs
@@ -1481,24 +1483,34 @@ def verify_pim_interface_traffic(tgen, input_dict):
rnode = tgen.routers()[dut]
logger.info("[DUT: %s]: Verifying pim interface traffic", dut)
- show_pim_intf_traffic_json = run_frr_cmd(
- rnode, "show ip pim interface traffic json", isjson=True
- )
- output_dict[dut] = {}
- for intf, data in input_dict[dut].items():
- interface_json = show_pim_intf_traffic_json[intf]
- for state in data:
+ def show_pim_intf_traffic(rnode, dut, input_dict, output_dict):
+ show_pim_intf_traffic_json = run_frr_cmd(
+ rnode, "show ip pim interface traffic json", isjson=True
+ )
- # Verify Tx/Rx
- if state in interface_json:
- output_dict[dut][state] = interface_json[state]
- else:
- errormsg = (
- "[DUT %s]: %s is not present"
- "for interface %s [FAILED]!! " % (dut, state, intf)
- )
- return errormsg
+ output_dict[dut] = {}
+ for intf, data in input_dict[dut].items():
+ interface_json = show_pim_intf_traffic_json[intf]
+ for state in data:
+
+ # Verify Tx/Rx
+ if state in interface_json:
+ output_dict[dut][state] = interface_json[state]
+ else:
+ errormsg = (
+ "[DUT %s]: %s is not present"
+ "for interface %s [FAILED]!! " % (dut, state, intf)
+ )
+ return errormsg
+ return None
+
+ test_func = functools.partial(
+ show_pim_intf_traffic, rnode, dut, input_dict, output_dict
+ )
+ (result, out) = topotest.run_and_expect(test_func, None, count=20, wait=1)
+ if not result:
+ return out
logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
return output_dict
diff --git a/tests/topotests/lib/topojson.py b/tests/topotests/lib/topojson.py
index 4f23e1ace0..3ca3353ed3 100644
--- a/tests/topotests/lib/topojson.py
+++ b/tests/topotests/lib/topojson.py
@@ -40,7 +40,7 @@ from lib.common_config import (
topo_daemons,
number_to_column,
)
-from lib.ospf import create_router_ospf, create_router_ospf6
+from lib.ospf import create_router_ospf
from lib.pim import create_igmp_config, create_pim_config
from lib.topolog import logger
@@ -334,7 +334,6 @@ def build_config_from_json(tgen, topo=None, save_bkup=True):
("igmp", create_igmp_config),
("bgp", create_router_bgp),
("ospf", create_router_ospf),
- ("ospf6", create_router_ospf6),
]
)
@@ -353,6 +352,18 @@ def build_config_from_json(tgen, topo=None, save_bkup=True):
logger.info("build_config_from_json: failed to configure topology")
pytest.exit(1)
+ logger.info("Built config now clearing ospf neighbors as that router-id might not be what is used")
+ for ospf in ["ospf", "ospf6"]:
+ for router in data:
+ if ospf not in data[router]:
+ continue
+
+ r = tgen.gears[router]
+ if ospf == "ospf":
+ r.vtysh_cmd("clear ip ospf process")
+ else:
+ r.vtysh_cmd("clear ipv6 ospf6 process")
+
def create_tgen_from_json(testfile, json_file=None):
"""Create a topogen object given a testfile.
diff --git a/tests/topotests/lib/topotest.py b/tests/topotests/lib/topotest.py
index 6ee000b0f4..6be644ac00 100644
--- a/tests/topotests/lib/topotest.py
+++ b/tests/topotests/lib/topotest.py
@@ -1386,7 +1386,6 @@ class Router(Node):
if params.get("routertype") is not None:
self.routertype = params.get("routertype")
- self.cmd("ulimit -c unlimited")
# Set ownership of config files
self.cmd("chown {0}:{0}vty /etc/{0}".format(self.routertype))
@@ -1860,7 +1859,7 @@ class Router(Node):
self.cmd("kill -9 %s" % daemonpid)
if pid_exists(int(daemonpid)):
numRunning += 1
- if wait and numRunning > 0:
+ while wait and numRunning > 0:
sleep(
2,
"{}: waiting for {} daemon to be stopped".format(
@@ -1884,7 +1883,11 @@ class Router(Node):
)
)
self.cmd("kill -9 %s" % daemonpid)
- self.cmd("rm -- {}".format(d.rstrip()))
+ if daemonpid.isdigit() and not pid_exists(
+ int(daemonpid)
+ ):
+ numRunning -= 1
+ self.cmd("rm -- {}".format(d.rstrip()))
if wait:
errors = self.checkRouterCores(reportOnce=True)
if self.checkRouterVersion("<", minErrorVersion):
diff --git a/tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py b/tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py
index a94dcb505a..38560c06e4 100644
--- a/tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py
+++ b/tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py
@@ -848,6 +848,10 @@ def test_new_router_fwd_p0(request):
assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
do_countdown(5)
+ step("Verify again if BSR is installed from bsm forwarded by i1")
+ result = verify_pim_bsr(tgen, topo, "l1", bsr_ip)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
# Verify ip mroute populated again
step("Verify mroute again on l1 (lhr)")
result = verify_ip_mroutes(tgen, "l1", src_addr, GROUP_ADDRESS, iif, oil)
diff --git a/tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo4.py b/tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo4.py
index 5e29a1f1fd..2a8e29b1d4 100755
--- a/tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo4.py
+++ b/tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo4.py
@@ -954,11 +954,13 @@ def test_PIM_hello_tx_rx_p1(request):
tc_name, result
)
- step("verify stats not increamented on c1")
+ step("verify stats incremented on c1")
result = verify_state_incremented(c1_state_before, c1_state_after)
assert (
- result is not True
- ), "Testcase{} : Failed Error: {}" "stats incremented".format(tc_name, result)
+ result is True
+ ), "Testcase{} : Failed Error: {}" "stats is not incremented".format(
+ tc_name, result
+ )
step("verify before stats on l1")
l1_state_dict = {
@@ -991,7 +993,7 @@ def test_PIM_hello_tx_rx_p1(request):
tc_name, result
)
- step("verify stats not increamented on l1")
+ step("verify stats not incremented on l1")
result = verify_state_incremented(l1_state_before, l1_state_after)
assert (
result is not True
@@ -1041,10 +1043,10 @@ def test_PIM_hello_tx_rx_p1(request):
tc_name, result
)
- step("verify stats not increamented on c1")
+ step("verify stats incremented on c1")
result = verify_state_incremented(c1_state_before, c1_state_after)
assert (
- result is not True
+ result is True
), "Testcase{} : Failed Error: {}" "stats incremented".format(tc_name, result)
write_test_footer(tc_name)
diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_lan.py b/tests/topotests/ospf_basic_functionality/test_ospf_lan.py
index b80da41bec..fd17180051 100644
--- a/tests/topotests/ospf_basic_functionality/test_ospf_lan.py
+++ b/tests/topotests/ospf_basic_functionality/test_ospf_lan.py
@@ -408,7 +408,7 @@ def test_ospf_lan_tc1_p0(request):
topo_modify_change_ip = deepcopy(topo)
intf_ip = topo_modify_change_ip["routers"]["r0"]["links"]["s1"]["ipv4"]
topo_modify_change_ip["routers"]["r0"]["links"]["s1"]["ipv4"] = str(
- IPv4Address(frr_unicode(intf_ip.split("/")[0])) + 3
+ IPv4Address(frr_unicode(intf_ip.split("/")[0])) + 4
) + "/{}".format(intf_ip.split("/")[1])
build_config_from_json(tgen, topo_modify_change_ip, save_bkup=False)
diff --git a/tests/topotests/ospf_dual_stack/test_ospf_dual_stack.json b/tests/topotests/ospf_dual_stack/test_ospf_dual_stack.json
index c8a3ce783b..cdb8813b3d 100644
--- a/tests/topotests/ospf_dual_stack/test_ospf_dual_stack.json
+++ b/tests/topotests/ospf_dual_stack/test_ospf_dual_stack.json
@@ -23,7 +23,8 @@
},
"ospf6": {
"hello_interval": 1,
- "dead_interval": 4
+ "dead_interval": 4,
+ "area": "1.1.1.1"
}
}
},
@@ -36,9 +37,7 @@
"ospf6": {
"router_id": "1.1.1.1",
"neighbors": {
- "r3": {
- "area": "1.1.1.1"
- }
+ "r3": {}
}
}
},
@@ -56,7 +55,8 @@
"ospf6": {
"hello_interval": 1,
"dead_interval": 4,
- "network": "point-to-point"
+ "network": "point-to-point",
+ "area": "1.1.1.1"
}
},
"r4": {
@@ -71,7 +71,8 @@
"ospf6": {
"hello_interval": 1,
"dead_interval": 4,
- "network": "point-to-point"
+ "network": "point-to-point",
+ "area": "0.0.0.0"
}
}
},
@@ -85,8 +86,8 @@
"ospf6": {
"router_id": "2.2.2.2",
"neighbors": {
- "r3": { "area": "1.1.1.1" },
- "r4": { "area": "0.0.0.0" }
+ "r3": {},
+ "r4": {}
}
}
},
@@ -104,7 +105,8 @@
"ospf6": {
"hello_interval": 1,
"dead_interval": 4,
- "network": "point-to-point"
+ "network": "point-to-point",
+ "area": "1.1.1.1"
}
},
"r2": {
@@ -119,7 +121,8 @@
"ospf6": {
"hello_interval": 1,
"dead_interval": 4,
- "network": "point-to-point"
+ "network": "point-to-point",
+ "area": "1.1.1.1"
}
},
"r4": {
@@ -134,7 +137,8 @@
"ospf6": {
"hello_interval": 1,
"dead_interval": 4,
- "network": "point-to-point"
+ "network": "point-to-point",
+ "area": "0.0.0.0"
}
}
},
@@ -149,9 +153,9 @@
"ospf6": {
"router_id": "3.3.3.3",
"neighbors": {
- "r1": { "area": "1.1.1.1" },
- "r2": { "area": "1.1.1.1" },
- "r4": { "area": "0.0.0.0" }
+ "r1": {},
+ "r2": {},
+ "r4": {}
}
}
},
@@ -169,7 +173,8 @@
"ospf6": {
"hello_interval": 1,
"dead_interval": 4,
- "network": "point-to-point"
+ "network": "point-to-point",
+ "area": "0.0.0.0"
}
},
"r3": {
@@ -184,7 +189,8 @@
"ospf6": {
"hello_interval": 1,
"dead_interval": 4,
- "network": "point-to-point"
+ "network": "point-to-point",
+ "area": "0.0.0.0"
}
},
"r5": {
@@ -199,7 +205,8 @@
"ospf6": {
"hello_interval": 1,
"dead_interval": 4,
- "network": "point-to-point"
+ "network": "point-to-point",
+ "area": "2.2.2.2"
}
}
},
@@ -214,9 +221,9 @@
"ospf6": {
"router_id": "4.4.4.4",
"neighbors": {
- "r2": { "area": "0.0.0.0" },
- "r3": { "area": "0.0.0.0" },
- "r5": { "area": "2.2.2.2" }
+ "r2": {},
+ "r3": {},
+ "r5": {}
}
}
},
@@ -234,7 +241,8 @@
"ospf6": {
"hello_interval": 1,
"dead_interval": 4,
- "network": "point-to-point"
+ "network": "point-to-point",
+ "area": "2.2.2.2"
}
}
},
@@ -247,7 +255,7 @@
"ospf6": {
"router_id": "5.5.5.5",
"neighbors": {
- "r4": { "area": "2.2.2.2" }
+ "r4": {}
}
}
}
diff --git a/tests/topotests/ospfv3_basic_functionality/ospfv3_nssa.json b/tests/topotests/ospfv3_basic_functionality/ospfv3_nssa.json
new file mode 100644
index 0000000000..2b91abc9e3
--- /dev/null
+++ b/tests/topotests/ospfv3_basic_functionality/ospfv3_nssa.json
@@ -0,0 +1,86 @@
+{
+ "address_types": [
+ "ipv6"
+ ],
+ "lo_prefix": {
+ "ipv6": "2001::",
+ "v6mask": 128
+ },
+ "routers": {
+ "r1": {
+ "links": {
+ "lo": {
+ "ipv6": "auto",
+ "type": "loopback"
+ },
+ "r2": {
+ "ipv6": "12::1/64",
+ "ospf6": {
+ "area": "0.0.0.0",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ }
+ },
+ "ospf6": {
+ "router_id": "1.1.1.1",
+ "neighbors": {
+ "r2": {}
+ }
+ }
+ },
+ "r2": {
+ "links": {
+ "lo": {
+ "ipv6": "auto",
+ "type": "loopback"
+ },
+ "r1": {
+ "ipv6": "12::2/64",
+ "ospf6": {
+ "area": "0.0.0.0",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ },
+ "r3": {
+ "ipv6": "23::2/64",
+ "ospf6": {
+ "area": "1.1.1.1",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ }
+ },
+ "ospf6": {
+ "router_id": "2.2.2.2",
+ "neighbors": {
+ "r1": {},
+ "r3": {}
+ }
+ }
+ },
+ "r3": {
+ "links": {
+ "lo": {
+ "ipv6": "auto",
+ "type": "loopback"
+ },
+ "r2": {
+ "ipv6": "23::3/64",
+ "ospf6": {
+ "area": "1.1.1.1",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ }
+ },
+ "ospf6": {
+ "router_id": "3.3.3.3",
+ "neighbors": {
+ "r2": {}
+ }
+ }
+ }
+ }
+}
diff --git a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_nssa.py b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_nssa.py
new file mode 100644
index 0000000000..64a067cd1a
--- /dev/null
+++ b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_nssa.py
@@ -0,0 +1,162 @@
+#!/usr/bin/python
+
+from lib.topogen import Topogen, get_topogen
+from lib.common_config import (
+ start_topology,
+ write_test_header,
+ write_test_footer,
+ reset_config_on_routers,
+ step,
+ topo_daemons,
+)
+from lib.topolog import logger
+from lib.topojson import build_config_from_json
+from lib.ospf import create_router_ospf, verify_ospf6_neighbor
+import os
+import sys
+import time
+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
+
+pytestmark = [pytest.mark.ospfd]
+
+
+# Global variables
+topo = None
+
+"""
+TOPOOLOGY
+
+ +---+ 0.0.0.0 +---+ 1.1.1.1 +---+
+ +R1 +------------+R2 |------------+R3 |
+ +-+-+ +--++ +--++
+
+TESTCASES =
+1. OSPF Verify E-bit mismatch between R2 and R3
+2. OSPF Verify N-bit mismatch between R2 and R3
+"""
+
+
+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...
+ json_file = "{}/ospfv3_nssa.json".format(CWD)
+ tgen = Topogen(json_file, mod.__name__)
+ global topo
+ topo = tgen.json_topo
+ # ... and here it calls Mininet initialization functions.
+
+ # get list of daemons needs to be started for this suite.
+ daemons = topo_daemons(tgen, topo)
+
+ # Starting topology, create tmp files which are loaded to routers
+ # to start deamons and then start routers
+ start_topology(tgen, daemons)
+
+ # Creating configuration from JSON
+ build_config_from_json(tgen, topo)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ result = verify_ospf6_neighbor(tgen, topo)
+ assert result is True, "setup_module: Failed \n Error:" " {}".format(result)
+
+ 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)
+
+
+# ##################################
+# Test cases start here.
+# ##################################
+
+
+def test_ospfv3_bit_mismatch(request):
+ """OSPF verify E-bit and N-bit mismatch."""
+
+ tc_name = request.node.name
+ write_test_header(tc_name)
+ tgen = get_topogen()
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ global topo
+ step("Bring up the base config as per the topology")
+ reset_config_on_routers(tgen)
+
+ input_dict = {"r3": {"ospf6": {"neighbors": []}}}
+
+ step("Configure r3 as stub router")
+ stub = {"r3": {"ospf6": {"area": [{"id": "1.1.1.1", "type": "stub"}]}}}
+ result = create_router_ospf(tgen, topo, stub)
+ assert result is True, "Testcase {}: Failed \n Error: {}".format(tc_name, result)
+ # Verify r3 lost its adjacency with r2 due to E-bit mismatch
+ result = verify_ospf6_neighbor(tgen, topo, dut="r3", input_dict=input_dict)
+ assert result is True, "Testcase {}: Failed \n Error: {}".format(tc_name, result)
+
+ step("Configure r2 as stub router")
+ stub = {"r2": {"ospf6": {"area": [{"id": "1.1.1.1", "type": "stub"}]}}}
+ result = create_router_ospf(tgen, topo, stub)
+ assert result is True, "Testcase {}: Failed \n Error: {}".format(tc_name, result)
+ # Verify r3 has an adjacency up with r2 again
+ result = verify_ospf6_neighbor(tgen, topo, dut="r3")
+ assert result is True, "Testcase {}: Failed \n Error: {}".format(tc_name, result)
+
+ step("Configure r3 as NSSA router")
+ nssa = {"r3": {"ospf6": {"area": [{"id": "1.1.1.1", "type": "nssa"}]}}}
+ result = create_router_ospf(tgen, topo, nssa)
+ # Verify r3 lost its adjacency with r2 due to N-bit mismatch
+ result = verify_ospf6_neighbor(tgen, topo, dut="r3", input_dict=input_dict)
+ assert result is True, "Testcase {}: Failed \n Error: {}".format(tc_name, result)
+
+ step("Configure r2 as NSSA router")
+ nssa = {"r2": {"ospf6": {"area": [{"id": "1.1.1.1", "type": "nssa"}]}}}
+ result = create_router_ospf(tgen, topo, nssa)
+ # Verify r3 has an adjacency up with r2 again
+ result = verify_ospf6_neighbor(tgen, topo, dut="r3")
+ 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/pim_basic/mcast-rx.py b/tests/topotests/pim_basic/mcast-rx.py
index 862ad46af4..885337666a 100755
--- a/tests/topotests/pim_basic/mcast-rx.py
+++ b/tests/topotests/pim_basic/mcast-rx.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
#
# mcast-rx.py
#
diff --git a/tests/topotests/pim_basic/mcast-tx.py b/tests/topotests/pim_basic/mcast-tx.py
index 87038ad5cf..88c234573f 100755
--- a/tests/topotests/pim_basic/mcast-tx.py
+++ b/tests/topotests/pim_basic/mcast-tx.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
#
# mcast-tx.py
#