3 # Copyright (c) 2022, University of Rome Tor Vergata
4 # Authored by Carmine Scarpitta <carmine.scarpitta@uniroma2.it>
6 # Permission to use, copy, modify, and/or distribute this software
7 # for any purpose with or without fee is hereby granted, provided
8 # that the above copyright notice and this permission notice appear
11 # THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
12 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
14 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
15 # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
16 # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
17 # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
28 CWD
= os
.path
.dirname(os
.path
.realpath(__file__
))
29 sys
.path
.append(os
.path
.join(CWD
, "../"))
31 # pylint: disable=C0413
32 # Import topogen and topotest helpers
33 from lib
import topotest
34 from lib
.topogen
import Topogen
, TopoRouter
, get_topogen
35 from lib
.topolog
import logger
36 from lib
.common_config
import required_linux_kernel_version
38 pytestmark
= [pytest
.mark
.bgpd
]
44 tgen
.add_router("ce1")
45 tgen
.add_router("ce2")
46 tgen
.add_router("ce3")
47 tgen
.add_router("ce4")
48 tgen
.add_router("ce5")
49 tgen
.add_router("ce6")
51 tgen
.add_link(tgen
.gears
["r1"], tgen
.gears
["r2"], "eth0", "eth0")
52 tgen
.add_link(tgen
.gears
["ce1"], tgen
.gears
["r1"], "eth0", "eth1")
53 tgen
.add_link(tgen
.gears
["ce2"], tgen
.gears
["r2"], "eth0", "eth1")
54 tgen
.add_link(tgen
.gears
["ce3"], tgen
.gears
["r1"], "eth0", "eth2")
55 tgen
.add_link(tgen
.gears
["ce4"], tgen
.gears
["r2"], "eth0", "eth2")
56 tgen
.add_link(tgen
.gears
["ce5"], tgen
.gears
["r1"], "eth0", "eth3")
57 tgen
.add_link(tgen
.gears
["ce6"], tgen
.gears
["r2"], "eth0", "eth3")
60 def setup_module(mod
):
61 result
= required_linux_kernel_version("5.14")
62 if result
is not True:
63 pytest
.skip("Kernel requirements are not met")
65 tgen
= Topogen(build_topo
, mod
.__name
__)
67 for rname
, router
in tgen
.routers().items():
68 router
.run("/bin/bash {}/{}/setup.sh".format(CWD
, rname
))
70 TopoRouter
.RD_ZEBRA
, os
.path
.join(CWD
, "{}/zebra.conf".format(rname
))
73 TopoRouter
.RD_BGP
, os
.path
.join(CWD
, "{}/bgpd.conf".format(rname
))
76 tgen
.gears
["r1"].run("sysctl net.vrf.strict_mode=1")
77 tgen
.gears
["r1"].run("ip link add vrf10 type vrf table 10")
78 tgen
.gears
["r1"].run("ip link set vrf10 up")
79 tgen
.gears
["r1"].run("ip link add vrf20 type vrf table 20")
80 tgen
.gears
["r1"].run("ip link set vrf20 up")
81 tgen
.gears
["r1"].run("ip link set eth1 master vrf10")
82 tgen
.gears
["r1"].run("ip link set eth2 master vrf10")
83 tgen
.gears
["r1"].run("ip link set eth3 master vrf20")
85 tgen
.gears
["r2"].run("sysctl net.vrf.strict_mode=1")
86 tgen
.gears
["r2"].run("ip link add vrf10 type vrf table 10")
87 tgen
.gears
["r2"].run("ip link set vrf10 up")
88 tgen
.gears
["r2"].run("ip link add vrf20 type vrf table 20")
89 tgen
.gears
["r2"].run("ip link set vrf20 up")
90 tgen
.gears
["r2"].run("ip link set eth1 master vrf10")
91 tgen
.gears
["r2"].run("ip link set eth2 master vrf20")
92 tgen
.gears
["r2"].run("ip link set eth3 master vrf20")
96 def teardown_module(mod
):
101 def open_json_file(filename
):
103 with
open(filename
, "r") as f
:
106 assert False, "Could not read file {}".format(filename
)
109 def check_ping4(name
, dest_addr
, expect_connected
):
110 def _check(name
, dest_addr
, match
):
112 output
= tgen
.gears
[name
].run("ping {} -c 1 -w 1".format(dest_addr
))
114 assert match
in output
, "ping fail"
116 match
= ", {} packet loss".format("0%" if expect_connected
else "100%")
117 logger
.info("[+] check {} {} {}".format(name
, dest_addr
, match
))
119 func
= functools
.partial(_check
, name
, dest_addr
, match
)
120 success
, result
= topotest
.run_and_expect(func
, None, count
=10, wait
=0.5)
121 assert result
is None, "Failed"
124 def check_ping6(name
, dest_addr
, expect_connected
):
125 def _check(name
, dest_addr
, match
):
127 output
= tgen
.gears
[name
].run("ping6 {} -c 1 -w 1".format(dest_addr
))
129 if match
not in output
:
132 match
= "{} packet loss".format("0%" if expect_connected
else "100%")
133 logger
.info("[+] check {} {} {}".format(name
, dest_addr
, match
))
135 func
= functools
.partial(_check
, name
, dest_addr
, match
)
136 success
, result
= topotest
.run_and_expect(func
, None, count
=10, wait
=1)
137 assert result
is None, "Failed"
140 def check_rib(name
, cmd
, expected_file
):
141 def _check(name
, dest_addr
, match
):
142 logger
.info("polling")
144 router
= tgen
.gears
[name
]
145 output
= json
.loads(router
.vtysh_cmd(cmd
))
146 expected
= open_json_file("{}/{}".format(CWD
, expected_file
))
147 return topotest
.json_cmp(output
, expected
)
149 logger
.info('[+] check {} "{}" {}'.format(name
, cmd
, expected_file
))
151 func
= functools
.partial(_check
, name
, cmd
, expected_file
)
152 success
, result
= topotest
.run_and_expect(func
, None, count
=10, wait
=0.5)
153 assert result
is None, "Failed"
157 check_rib("r1", "show bgp ipv4 vpn json", "r1/vpnv4_rib.json")
158 check_rib("r2", "show bgp ipv4 vpn json", "r2/vpnv4_rib.json")
159 check_rib("r1", "show ip route vrf vrf10 json", "r1/vrf10v4_rib.json")
160 check_rib("r1", "show ip route vrf vrf20 json", "r1/vrf20v4_rib.json")
161 check_rib("r2", "show ip route vrf vrf10 json", "r2/vrf10v4_rib.json")
162 check_rib("r2", "show ip route vrf vrf20 json", "r2/vrf20v4_rib.json")
163 check_rib("ce1", "show ip route json", "ce1/ip_rib.json")
164 check_rib("ce2", "show ip route json", "ce2/ip_rib.json")
165 check_rib("ce3", "show ip route json", "ce3/ip_rib.json")
166 check_rib("ce4", "show ip route json", "ce4/ip_rib.json")
167 check_rib("ce5", "show ip route json", "ce5/ip_rib.json")
168 check_rib("ce6", "show ip route json", "ce6/ip_rib.json")
170 check_rib("r1", "show bgp ipv6 vpn json", "r1/vpnv6_rib.json")
171 check_rib("r2", "show bgp ipv6 vpn json", "r2/vpnv6_rib.json")
172 check_rib("r1", "show ipv6 route vrf vrf10 json", "r1/vrf10v6_rib.json")
173 check_rib("r1", "show ipv6 route vrf vrf20 json", "r1/vrf20v6_rib.json")
174 check_rib("r2", "show ipv6 route vrf vrf10 json", "r2/vrf10v6_rib.json")
175 check_rib("r2", "show ipv6 route vrf vrf20 json", "r2/vrf20v6_rib.json")
176 check_rib("ce1", "show ipv6 route json", "ce1/ipv6_rib.json")
177 check_rib("ce2", "show ipv6 route json", "ce2/ipv6_rib.json")
178 check_rib("ce3", "show ipv6 route json", "ce3/ipv6_rib.json")
179 check_rib("ce4", "show ipv6 route json", "ce4/ipv6_rib.json")
180 check_rib("ce5", "show ipv6 route json", "ce5/ipv6_rib.json")
181 check_rib("ce6", "show ipv6 route json", "ce6/ipv6_rib.json")
185 check_ping4("ce1", "192.168.2.2", True)
186 check_ping4("ce1", "192.168.3.2", True)
187 check_ping4("ce1", "192.168.4.2", False)
188 check_ping4("ce1", "192.168.5.2", False)
189 check_ping4("ce1", "192.168.6.2", False)
190 check_ping4("ce4", "192.168.1.2", False)
191 check_ping4("ce4", "192.168.2.2", False)
192 check_ping4("ce4", "192.168.3.2", False)
193 check_ping4("ce4", "192.168.5.2", True)
194 check_ping4("ce4", "192.168.6.2", True)
196 check_ping6("ce1", "2001:2::2", True)
197 check_ping6("ce1", "2001:3::2", True)
198 check_ping6("ce1", "2001:4::2", False)
199 check_ping6("ce1", "2001:5::2", False)
200 check_ping6("ce1", "2001:6::2", False)
201 check_ping6("ce4", "2001:1::2", False)
202 check_ping6("ce4", "2001:2::2", False)
203 check_ping6("ce4", "2001:3::2", False)
204 check_ping6("ce4", "2001:5::2", True)
205 check_ping6("ce4", "2001:6::2", True)
208 def test_bgp_sid_vpn_export_disable():
209 check_ping4("ce1", "192.168.2.2", True)
210 check_ping6("ce1", "2001:2::2", True)
211 get_topogen().gears
["r1"].vtysh_cmd(
214 router bgp 1 vrf vrf10
216 no sid vpn per-vrf export
220 "r1", "show bgp ipv4 vpn json", "r1/vpnv4_rib_sid_vpn_export_disabled.json"
223 "r2", "show bgp ipv4 vpn json", "r2/vpnv4_rib_sid_vpn_export_disabled.json"
226 "r1", "show bgp ipv6 vpn json", "r1/vpnv6_rib_sid_vpn_export_disabled.json"
229 "r2", "show bgp ipv6 vpn json", "r2/vpnv6_rib_sid_vpn_export_disabled.json"
231 check_ping4("ce1", "192.168.2.2", False)
232 check_ping6("ce1", "2001:2::2", False)
235 def test_bgp_sid_vpn_export_reenable():
236 check_ping4("ce1", "192.168.2.2", False)
237 check_ping6("ce1", "2001:2::2", False)
238 get_topogen().gears
["r1"].vtysh_cmd(
241 router bgp 1 vrf vrf10
243 sid vpn per-vrf export auto
247 "r1", "show bgp ipv4 vpn json", "r1/vpnv4_rib_sid_vpn_export_reenabled.json"
250 "r2", "show bgp ipv4 vpn json", "r2/vpnv4_rib_sid_vpn_export_reenabled.json"
253 "r1", "show bgp ipv6 vpn json", "r1/vpnv6_rib_sid_vpn_export_reenabled.json"
256 "r2", "show bgp ipv6 vpn json", "r2/vpnv6_rib_sid_vpn_export_reenabled.json"
258 check_ping4("ce1", "192.168.2.2", True)
259 check_ping6("ce1", "2001:2::2", True)
262 def test_locator_delete():
263 check_ping4("ce1", "192.168.2.2", True)
264 check_ping6("ce1", "2001:2::2", True)
265 get_topogen().gears
["r1"].vtysh_cmd(
274 check_rib("r1", "show bgp ipv4 vpn json", "r1/vpnv4_rib_locator_deleted.json")
275 check_rib("r2", "show bgp ipv4 vpn json", "r2/vpnv4_rib_locator_deleted.json")
276 check_rib("r1", "show bgp ipv6 vpn json", "r1/vpnv6_rib_locator_deleted.json")
277 check_rib("r2", "show bgp ipv6 vpn json", "r2/vpnv6_rib_locator_deleted.json")
278 check_ping4("ce1", "192.168.2.2", False)
279 check_ping6("ce1", "2001:2::2", False)
282 def test_locator_recreate():
283 check_ping4("ce1", "192.168.2.2", False)
284 check_ping6("ce1", "2001:2::2", False)
285 get_topogen().gears
["r1"].vtysh_cmd(
292 prefix 2001:db8:1:1::/64
295 check_rib("r1", "show bgp ipv4 vpn json", "r1/vpnv4_rib_locator_recreated.json")
296 check_rib("r2", "show bgp ipv4 vpn json", "r2/vpnv4_rib_locator_recreated.json")
297 check_rib("r1", "show bgp ipv6 vpn json", "r1/vpnv6_rib_locator_recreated.json")
298 check_rib("r2", "show bgp ipv6 vpn json", "r2/vpnv6_rib_locator_recreated.json")
299 check_ping4("ce1", "192.168.2.2", True)
300 check_ping6("ce1", "2001:2::2", True)
303 def test_bgp_locator_unset():
304 check_ping4("ce1", "192.168.2.2", True)
305 check_ping6("ce1", "2001:2::2", True)
306 get_topogen().gears
["r1"].vtysh_cmd(
314 check_rib("r1", "show bgp ipv4 vpn json", "r1/vpnv4_rib_locator_deleted.json")
315 check_rib("r2", "show bgp ipv4 vpn json", "r2/vpnv4_rib_locator_deleted.json")
316 check_rib("r1", "show bgp ipv6 vpn json", "r1/vpnv6_rib_locator_deleted.json")
317 check_rib("r2", "show bgp ipv6 vpn json", "r2/vpnv6_rib_locator_deleted.json")
318 check_ping4("ce1", "192.168.2.2", False)
319 check_ping6("ce1", "2001:2::2", False)
322 def test_bgp_locator_reset():
323 check_ping4("ce1", "192.168.2.2", False)
324 check_ping6("ce1", "2001:2::2", False)
325 get_topogen().gears
["r1"].vtysh_cmd(
333 check_rib("r1", "show bgp ipv4 vpn json", "r1/vpnv4_rib_locator_recreated.json")
334 check_rib("r2", "show bgp ipv4 vpn json", "r2/vpnv4_rib_locator_recreated.json")
335 check_rib("r1", "show bgp ipv6 vpn json", "r1/vpnv6_rib_locator_recreated.json")
336 check_rib("r2", "show bgp ipv6 vpn json", "r2/vpnv6_rib_locator_recreated.json")
337 check_ping4("ce1", "192.168.2.2", True)
338 check_ping6("ce1", "2001:2::2", True)
341 def test_bgp_srv6_unset():
342 check_ping4("ce1", "192.168.2.2", True)
343 check_ping6("ce1", "2001:2::2", True)
344 get_topogen().gears
["r1"].vtysh_cmd(
348 no segment-routing srv6
351 check_rib("r1", "show bgp ipv4 vpn json", "r1/vpnv4_rib_locator_deleted.json")
352 check_rib("r2", "show bgp ipv4 vpn json", "r2/vpnv4_rib_locator_deleted.json")
353 check_rib("r1", "show bgp ipv6 vpn json", "r1/vpnv6_rib_locator_deleted.json")
354 check_rib("r2", "show bgp ipv6 vpn json", "r2/vpnv6_rib_locator_deleted.json")
355 check_ping4("ce1", "192.168.2.2", False)
356 check_ping6("ce1", "2001:2::2", False)
359 def test_bgp_srv6_reset():
360 check_ping4("ce1", "192.168.2.2", False)
361 check_ping6("ce1", "2001:2::2", False)
362 get_topogen().gears
["r1"].vtysh_cmd(
370 check_rib("r1", "show bgp ipv4 vpn json", "r1/vpnv4_rib_locator_recreated.json")
371 check_rib("r2", "show bgp ipv4 vpn json", "r2/vpnv4_rib_locator_recreated.json")
372 check_rib("r1", "show bgp ipv6 vpn json", "r1/vpnv6_rib_locator_recreated.json")
373 check_rib("r2", "show bgp ipv6 vpn json", "r2/vpnv6_rib_locator_recreated.json")
374 check_ping4("ce1", "192.168.2.2", True)
375 check_ping6("ce1", "2001:2::2", True)
378 if __name__
== "__main__":
379 args
= ["-s"] + sys
.argv
[1:]
380 sys
.exit(pytest
.main(args
))