Skip to content

Commit a6de6cf

Browse files
committed
topotest: add bgp ip-transparent test
r1 is a legacy bgp setting r2 is configured using IP transparent 2 steps: - when IP transparent is not set, TCP session should not establish - when IP transparent is set, TCP session should establish Signed-off-by: Vincent Jardin <[email protected]>
1 parent d5d2609 commit a6de6cf

File tree

2 files changed

+279
-0
lines changed

2 files changed

+279
-0
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"routers": {
3+
"r1": {
4+
"links": {
5+
"lo": { "type": "loopback" },
6+
"r2": { "ipv4": "10.20.100.1/24"}
7+
},
8+
"static_routes": [
9+
{"network": "0.0.0.0/0", "next_hop": "10.20.100.2"}
10+
],
11+
"bgp": { "local_as": "20101" }
12+
},
13+
"r2": {
14+
"links": {
15+
"lo": { "type": "loopback" },
16+
"r1": { "ipv4": "10.20.100.2/24"}
17+
},
18+
"bgp": { "local_as": "20102" }
19+
}
20+
}
21+
}
Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
#!/usr/bin/env python
2+
# SPDX-License-Identifier: ISC
3+
4+
#
5+
# Copyright (c) 2025 by Free Mobile, Vincent Jardin
6+
7+
"""
8+
test_bgp_tcp_ip_transparent.py: Test TCP BGP connectiong using ip-transparent
9+
"""
10+
11+
import os
12+
import sys
13+
import time
14+
import json
15+
import pytest
16+
17+
# Save the Current Working Directory to find configuration files.
18+
CWD = os.path.dirname(os.path.realpath(__file__))
19+
sys.path.append(os.path.join(CWD, "../"))
20+
sys.path.append(os.path.join(CWD, "../../"))
21+
22+
# pylint: disable=C0413
23+
# Import topogen and topotest helpers
24+
# Required to instantiate the topology builder class.
25+
26+
from lib.topogen import Topogen, get_topogen
27+
from lib.topolog import logger
28+
from lib.topojson import build_topo_from_json, build_config_from_json
29+
from lib.common_config import retry, run_frr_cmd
30+
31+
# Import topoJson from lib, to create topology and initial configuration
32+
from lib.common_config import (
33+
start_topology,
34+
write_test_header,
35+
write_test_footer,
36+
)
37+
#from lib.bgp import (
38+
# verify_bgp_convergence
39+
#)
40+
41+
# pytest, bgp only
42+
pytestmark = pytest.mark.bgpd
43+
44+
def build_topo(tgen):
45+
"""Build function"""
46+
47+
# Create topology acording to topogen input json file.
48+
build_topo_from_json(tgen, TOPO)
49+
50+
51+
def setup_module(mod):
52+
"""
53+
Sets up the pytest environment
54+
55+
* `mod`: module name
56+
"""
57+
58+
testsuite_run_time = time.asctime(time.localtime(time.time()))
59+
logger.info("Testsuite start time: %s", testsuite_run_time)
60+
logger.info("=" * 40)
61+
62+
topology = """
63+
r1-----r2
64+
"""
65+
logger.info("Master Topology: \n %s", topology)
66+
67+
logger.info("Running setup_module to create topology")
68+
69+
json_file = "{}/test_bgp_tcp_ip_transparent.json".format(CWD)
70+
tgen = Topogen(json_file, mod.__name__)
71+
global TOPO
72+
TOPO = tgen.json_topo
73+
74+
r1 = tgen.gears["r1"]
75+
r2 = tgen.gears["r2"]
76+
77+
# Starting topology, create tmp files which are loaded to routers
78+
# to start daemons and then start routers
79+
start_topology(tgen)
80+
81+
# Don't run this test if we have any failure.
82+
if tgen.routers_have_failure():
83+
pytest.skip(tgen.errors)
84+
85+
# Create configuration as defined in input json file.
86+
build_config_from_json(tgen, TOPO)
87+
88+
# uncomment the following for debug
89+
#r1.vtysh_cmd(f"""
90+
#configure terminal
91+
#debug bgp neighbor-events
92+
#debug bgp nht
93+
#""")
94+
r1.vtysh_cmd(f"""
95+
configure terminal
96+
router bgp 20101
97+
bgp disable-ebgp-connected-route-check
98+
neighbor 15.20.100.2 remote-as 20102
99+
""")
100+
101+
# needed to enforce socket() receive for a transparent IP socket
102+
# up to the users to use any other method
103+
r2.run("iptables -t mangle -A PREROUTING -p tcp -j MARK --set-mark 0x100")
104+
r2.run("ip route add local default dev lo table 100")
105+
r2.run("ip rule add fwmark 0x100 lookup 100")
106+
107+
# uncomment the following for debug
108+
#r2.vtysh_cmd(f"""
109+
#configure terminal
110+
#debug bgp neighbor-events
111+
#debug bgp nht
112+
#""")
113+
r2.vtysh_cmd(f"""
114+
configure terminal
115+
router bgp 20102
116+
bgp disable-ebgp-connected-route-check
117+
neighbor 10.20.100.1 remote-as 20101
118+
neighbor 10.20.100.1 update-source 15.20.100.2
119+
""")
120+
121+
logger.info("Running setup_module() done")
122+
123+
124+
def teardown_module(mod):
125+
"""
126+
Teardown the pytest environment
127+
128+
* `mod`: module name
129+
"""
130+
131+
logger.info("Running teardown_module to delete topology")
132+
133+
tgen = get_topogen()
134+
135+
# Stop toplogy and Remove tmp files
136+
tgen.stop_topology()
137+
138+
logger.info("Testsuite end time: %s", time.asctime(time.localtime(time.time())))
139+
logger.info("=" * 40)
140+
141+
142+
@retry(retry_timeout=8)
143+
def verify_bgp_transparent(tgen, topo=None, dut=None):
144+
145+
if topo is None:
146+
topo = tgen.json_topo
147+
148+
result = False
149+
logger.info("Entering tool API: {}".format(sys._getframe().f_code.co_name))
150+
tgen = get_topogen()
151+
152+
no_of_peer = 0
153+
total_peer = 0
154+
for router, rnode in tgen.routers().items():
155+
if "bgp" not in topo["routers"][router]:
156+
continue
157+
158+
if dut is not None and dut != router:
159+
continue
160+
logger.info("Verifying BGP Convergence on router %s:", router)
161+
show_bgp_json = run_frr_cmd(rnode, "show bgp vrf all summary json", isjson=True)
162+
163+
# Verifying output dictionary show_bgp_json is empty or not
164+
if not bool(show_bgp_json):
165+
return f"[{router}] BGP is not running"
166+
167+
for vrf, vrf_blob in show_bgp_json.items():
168+
peers = vrf_blob.get("ipv4Unicast", {}).get("peers", {})
169+
for peer_ip, pdata in peers.items():
170+
nh_state = pdata.get("state")
171+
logger.debug(" VRF %s peer %s state %s", vrf, peer_ip, nh_state)
172+
total_peer += 1
173+
if nh_state == "Established":
174+
no_of_peer += 1
175+
176+
if no_of_peer == total_peer and no_of_peer > 0:
177+
errormsg = "[DUT: %s] VRF: %s, BGP is Converged" % (router, vrf)
178+
result = True
179+
else:
180+
errormsg = "[DUT: %s] VRF: %s, BGP is not Converged" % (router, vrf)
181+
result = False
182+
183+
logger.info("Exiting API: {}, {}".format(sys._getframe().f_code.co_name, errormsg))
184+
return result
185+
186+
187+
#####################################################
188+
#
189+
# Testcases
190+
#
191+
#####################################################
192+
193+
def test_bgp_session_not_established(request):
194+
"""Test that the BGP session is not established."""
195+
196+
tgen = get_topogen()
197+
198+
# test case name
199+
tc_name = request.node.name
200+
write_test_header(tc_name)
201+
202+
# Don't run this test if we have any failure.
203+
if tgen.routers_have_failure():
204+
pytest.skip(tgen.errors)
205+
206+
# Uncomment below to debug
207+
#tgen.mininet_cli()
208+
209+
# Api call verify whether BGP is converged
210+
logger.info("Checking BGP is not connecting\n")
211+
converged = verify_bgp_transparent(tgen, retry_timeout=9, expected=False)
212+
213+
assert (
214+
converged is False
215+
), "BGP session did not establish as expected"
216+
217+
logger.info("BGP TCP did not connect\n")
218+
write_test_footer(tc_name)
219+
220+
221+
def test_bgp_session_established(request):
222+
"""Test that the BGP session is established."""
223+
224+
tgen = get_topogen()
225+
226+
# test case name
227+
tc_name = request.node.name
228+
write_test_header(tc_name)
229+
230+
# Don't run this test if we have any failure.
231+
if tgen.routers_have_failure():
232+
pytest.skip(tgen.errors)
233+
234+
r2 = tgen.gears["r2"]
235+
r2.vtysh_cmd(f"""
236+
configure terminal
237+
router bgp 20102
238+
neighbor 10.20.100.1 ip-transparent
239+
""")
240+
241+
# Uncomment below to debug
242+
#tgen.mininet_cli()
243+
244+
# Api call verify whether BGP is converged
245+
logger.info("Checking BGP is connecting\n")
246+
converged = verify_bgp_transparent(tgen, retry_timeout=9, expected=True)
247+
248+
assert (
249+
converged is True
250+
), "test_bgp_convergence failed.. \n" " Error: {}".format(converged)
251+
252+
logger.info("BGP TCP did connect\n")
253+
write_test_footer(tc_name)
254+
255+
256+
if __name__ == "__main__":
257+
args = ["-s"] + sys.argv[1:]
258+
sys.exit(pytest.main(args))

0 commit comments

Comments
 (0)