]> git.proxmox.com Git - mirror_frr.git/blame - tests/topotests/bgp-basic-functionality-topo1/test_bgp_basic_functionality.py
Merge pull request #7017 from xThaid/netlink_fix
[mirror_frr.git] / tests / topotests / bgp-basic-functionality-topo1 / test_bgp_basic_functionality.py
CommitLineData
7fa2079a
AP
1#!/usr/bin/env python
2
3#
4# Copyright (c) 2019 by VMware, Inc. ("VMware")
5# Used Copyright (c) 2018 by Network Device Education Foundation,
6# Inc. ("NetDEF") in this file.
7#
8# Permission to use, copy, modify, and/or distribute this software
9# for any purpose with or without fee is hereby granted, provided
10# that the above copyright notice and this permission notice appear
11# in all copies.
12#
13# THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES
14# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR
16# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
17# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
19# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20# OF THIS SOFTWARE.
21#
22
23"""
24Following tests are covered to test BGP basic functionality:
25
26Test steps
27- Create topology (setup module)
28 Creating 4 routers topology, r1, r2, r3 are in IBGP and
29 r3, r4 are in EBGP
30- Bring up topology
31- Verify for bgp to converge
32- Modify/Delete and verify router-id
81e3d609
AP
33- Modify and verify bgp timers
34- Create and verify static routes
35- Modify and verify admin distance for existing static routes
36- Test advertise network using network command
37- Verify clear bgp
38- Test bgp convergence with loopback interface
39- Test advertise network using network command
7fa2079a
AP
40"""
41
42import os
43import sys
44import json
45import time
46import pytest
47from copy import deepcopy
48
49# Save the Current Working Directory to find configuration files.
50CWD = os.path.dirname(os.path.realpath(__file__))
787e7624 51sys.path.append(os.path.join(CWD, "../"))
52sys.path.append(os.path.join(CWD, "../lib/"))
7fa2079a
AP
53
54# Required to instantiate the topology builder class.
55
56# pylint: disable=C0413
57# Import topogen and topotest helpers
58from lib.topogen import Topogen, get_topogen
59from mininet.topo import Topo
60
61from lib.common_config import (
787e7624 62 start_topology,
63 write_test_header,
64 write_test_footer,
65 reset_config_on_routers,
66 create_static_routes,
67 verify_rib,
68 verify_admin_distance_for_static_routes,
7fa2079a
AP
69)
70from lib.topolog import logger
71from lib.bgp import (
787e7624 72 verify_bgp_convergence,
73 create_router_bgp,
74 verify_router_id,
75 modify_as_number,
76 verify_as_numbers,
77 clear_bgp_and_verify,
78 verify_bgp_timers_and_functionality,
7fa2079a
AP
79)
80from lib.topojson import build_topo_from_json, build_config_from_json
81
82# Reading the data from JSON File for topology creation
83jsonFile = "{}/bgp_basic_functionality.json".format(CWD)
84try:
787e7624 85 with open(jsonFile, "r") as topoJson:
7fa2079a
AP
86 topo = json.load(topoJson)
87except IOError:
88 assert False, "Could not read file {}".format(jsonFile)
89
787e7624 90# Global Variable
af9c65d4
KK
91KEEPALIVETIMER = 2
92HOLDDOWNTIMER = 6
7fa2079a 93
787e7624 94
7fa2079a
AP
95class CreateTopo(Topo):
96 """
97 Test BasicTopo - topology 1
98
99 * `Topo`: Topology object
100 """
101
102 def build(self, *_args, **_opts):
103 """Build function"""
104 tgen = get_topogen(self)
105
106 # Building topology from json file
107 build_topo_from_json(tgen, topo)
108
109
110def setup_module(mod):
111 """
112 Sets up the pytest environment
113
114 * `mod`: module name
115 """
116
117 testsuite_run_time = time.asctime(time.localtime(time.time()))
118 logger.info("Testsuite start time: {}".format(testsuite_run_time))
119 logger.info("=" * 40)
120
121 logger.info("Running setup_module to create topology")
122
123 # This function initiates the topology build with Topogen...
124 tgen = Topogen(CreateTopo, mod.__name__)
125 # ... and here it calls Mininet initialization functions.
126
127 # Starting topology, create tmp files which are loaded to routers
128 # to start deamons and then start routers
129 start_topology(tgen)
130
131 # Creating configuration from JSON
132 build_config_from_json(tgen, topo)
133
134 global BGP_CONVERGENCE
135 BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo)
787e7624 136 assert BGP_CONVERGENCE is True, "setup_module :Failed \n Error: {}".format(
137 BGP_CONVERGENCE
138 )
7fa2079a
AP
139
140 logger.info("Running setup_module() done")
141
142
143def teardown_module():
144 """Teardown the pytest environment"""
145
146 logger.info("Running teardown_module to delete topology")
147
148 tgen = get_topogen()
149
150 # Stop toplogy and Remove tmp files
6bb29e5e 151 tgen.stop_topology()
7fa2079a 152
787e7624 153 logger.info(
154 "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
155 )
7fa2079a
AP
156 logger.info("=" * 40)
157
158
159#####################################################
160#
161# Testcases
162#
163#####################################################
164
165
166def test_modify_and_delete_router_id(request):
167 """ Test to modify, delete and verify router-id. """
168
169 tgen = get_topogen()
170 if BGP_CONVERGENCE is not True:
787e7624 171 pytest.skip("skipped because of BGP Convergence failure")
7fa2079a
AP
172
173 # test case name
174 tc_name = request.node.name
175 write_test_header(tc_name)
176
177 # Modify router id
178 input_dict = {
787e7624 179 "r1": {"bgp": {"router_id": "12.12.12.12"}},
180 "r2": {"bgp": {"router_id": "22.22.22.22"}},
181 "r3": {"bgp": {"router_id": "33.33.33.33"}},
7fa2079a
AP
182 }
183 result = create_router_bgp(tgen, topo, input_dict)
787e7624 184 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
7fa2079a
AP
185
186 # Verifying router id once modified
187 result = verify_router_id(tgen, topo, input_dict)
787e7624 188 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
7fa2079a
AP
189
190 # Delete router id
191 input_dict = {
787e7624 192 "r1": {"bgp": {"del_router_id": True}},
193 "r2": {"bgp": {"del_router_id": True}},
194 "r3": {"bgp": {"del_router_id": True}},
7fa2079a
AP
195 }
196 result = create_router_bgp(tgen, topo, input_dict)
787e7624 197 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
7fa2079a
AP
198
199 # Verifying router id once deleted
200 # Once router-id is deleted, highest interface ip should become
201 # router-id
202 result = verify_router_id(tgen, topo, input_dict)
787e7624 203 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
7fa2079a
AP
204
205 write_test_footer(tc_name)
206
207
77ef1af6
AP
208def test_bgp_config_with_4byte_as_number(request):
209 """
210 Configure BGP with 4 byte ASN and verify it works fine
211 """
212
213 tgen = get_topogen()
214 if BGP_CONVERGENCE is not True:
787e7624 215 pytest.skip("skipped because of BGP Convergence failure")
77ef1af6
AP
216
217 # test case name
218 tc_name = request.node.name
219 write_test_header(tc_name)
220
221 input_dict = {
787e7624 222 "r1": {"bgp": {"local_as": 131079}},
223 "r2": {"bgp": {"local_as": 131079}},
224 "r3": {"bgp": {"local_as": 131079}},
225 "r4": {"bgp": {"local_as": 131080}},
77ef1af6
AP
226 }
227 result = modify_as_number(tgen, topo, input_dict)
787e7624 228 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
77ef1af6
AP
229
230 result = verify_as_numbers(tgen, topo, input_dict)
787e7624 231 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
77ef1af6
AP
232
233 write_test_footer(tc_name)
234
235
b7250ecf
KK
236def test_BGP_config_with_invalid_ASN_p2(request):
237 """
238 Configure BGP with invalid ASN(ex - 0, reserved ASN) and verify test case
239 ended up with error
240 """
241
242 tgen = get_topogen()
243 global BGP_CONVERGENCE
244
245 if BGP_CONVERGENCE != True:
afee014e 246 pytest.skip("skipped because of BGP Convergence failure")
b7250ecf
KK
247
248 # test case name
249 tc_name = request.node.name
250 write_test_header(tc_name)
251
252 # Api call to modify AS number
253 input_dict = {
afee014e
KK
254 "r1": {"bgp": {"local_as": 0,}},
255 "r2": {"bgp": {"local_as": 0,}},
256 "r3": {"bgp": {"local_as": 0,}},
257 "r4": {"bgp": {"local_as": 64000,}},
b7250ecf
KK
258 }
259 result = modify_as_number(tgen, topo, input_dict)
260 try:
261 assert result is True
262 except AssertionError:
263 logger.info("Expected behaviour: {}".format(result))
264 logger.info("BGP config is not created because of invalid ASNs")
265
266 write_test_footer(tc_name)
267
268
269def test_BGP_config_with_2byteAS_and_4byteAS_number_p1(request):
270 """
271 Configure BGP with 4 byte and 2 byte ASN and verify BGP is converged
272 """
273
274 tgen = get_topogen()
275 global BGP_CONVERGENCE
276
277 if BGP_CONVERGENCE != True:
afee014e 278 pytest.skip("skipped because of BGP Convergence failure")
b7250ecf
KK
279
280 # test case name
281 tc_name = request.node.name
282 write_test_header(tc_name)
283
284 # Api call to modify AS number
285 input_dict = {
afee014e
KK
286 "r1": {"bgp": {"local_as": 131079}},
287 "r2": {"bgp": {"local_as": 131079}},
288 "r3": {"bgp": {"local_as": 131079}},
289 "r4": {"bgp": {"local_as": 111}},
b7250ecf
KK
290 }
291 result = modify_as_number(tgen, topo, input_dict)
292 if result != True:
afee014e 293 assert False, "Testcase " + tc_name + " :Failed \n Error: {}".format(result)
b7250ecf
KK
294
295 result = verify_as_numbers(tgen, topo, input_dict)
296 if result != True:
afee014e 297 assert False, "Testcase " + tc_name + " :Failed \n Error: {}".format(result)
b7250ecf
KK
298
299 # Api call verify whether BGP is converged
300 result = verify_bgp_convergence(tgen, topo)
301 if result != True:
afee014e 302 assert False, "Testcase " + tc_name + " :Failed \n Error: {}".format(result)
b7250ecf
KK
303
304 write_test_footer(tc_name)
305
306
77ef1af6
AP
307def test_bgp_timers_functionality(request):
308 """
309 Test to modify bgp timers and verify timers functionality.
310 """
311
312 tgen = get_topogen()
313 if BGP_CONVERGENCE is not True:
787e7624 314 pytest.skip("skipped because of BGP Convergence failure")
77ef1af6
AP
315
316 # test case name
317 tc_name = request.node.name
318 write_test_header(tc_name)
319
320 # Creating configuration from JSON
321 reset_config_on_routers(tgen)
322
323 # Api call to modfiy BGP timerse
324 input_dict = {
325 "r1": {
326 "bgp": {
327 "address_family": {
328 "ipv4": {
329 "unicast": {
330 "neighbor": {
331 "r2": {
787e7624 332 "dest_link": {
77ef1af6 333 "r1": {
af9c65d4 334 "keepalivetimer": KEEPALIVETIMER,
787e7624 335 "holddowntimer": HOLDDOWNTIMER,
77ef1af6
AP
336 }
337 }
338 }
339 }
340 }
341 }
342 }
343 }
344 }
345 }
346 result = create_router_bgp(tgen, topo, deepcopy(input_dict))
787e7624 347 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
77ef1af6
AP
348
349 # Api call to clear bgp, so timer modification would take place
787e7624 350 clear_bgp_and_verify(tgen, topo, "r1")
77ef1af6
AP
351
352 # Verifying bgp timers functionality
353 result = verify_bgp_timers_and_functionality(tgen, topo, input_dict)
787e7624 354 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
77ef1af6
AP
355
356 write_test_footer(tc_name)
357
358
cb6b1d90
AP
359def test_static_routes(request):
360 """ Test to create and verify static routes. """
361
362 tgen = get_topogen()
363 if BGP_CONVERGENCE is not True:
787e7624 364 pytest.skip("skipped because of BGP Convergence failure")
cb6b1d90
AP
365
366 # test case name
367 tc_name = request.node.name
368 write_test_header(tc_name)
369
370 # Creating configuration from JSON
371 reset_config_on_routers(tgen)
372
373 # Api call to create static routes
374 input_dict = {
375 "r1": {
787e7624 376 "static_routes": [
377 {
378 "network": "10.0.20.1/32",
379 "no_of_ip": 9,
380 "admin_distance": 100,
381 "next_hop": "10.0.0.2",
382 }
383 ]
cb6b1d90
AP
384 }
385 }
386 result = create_static_routes(tgen, input_dict)
787e7624 387 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
cb6b1d90
AP
388
389 # Api call to redistribute static routes
390 input_dict_1 = {
391 "r1": {
392 "bgp": {
393 "address_family": {
394 "ipv4": {
395 "unicast": {
396 "redistribute": [
397 {"redist_type": "static"},
787e7624 398 {"redist_type": "connected"},
cb6b1d90
AP
399 ]
400 }
401 }
402 }
403 }
404 }
405 }
406
407 result = create_router_bgp(tgen, topo, input_dict_1)
787e7624 408 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
cb6b1d90
AP
409
410 # Verifying RIB routes
787e7624 411 dut = "r3"
412 protocol = "bgp"
413 next_hop = ["10.0.0.2", "10.0.0.5"]
414 result = verify_rib(
415 tgen, "ipv4", dut, input_dict, next_hop=next_hop, protocol=protocol
416 )
417 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
cb6b1d90
AP
418
419 write_test_footer(tc_name)
420
421
422def test_admin_distance_for_existing_static_routes(request):
423 """ Test to modify and verify admin distance for existing static routes."""
424
425 tgen = get_topogen()
426 if BGP_CONVERGENCE is not True:
787e7624 427 pytest.skip("skipped because of BGP Convergence failure")
cb6b1d90
AP
428
429 # test case name
430 tc_name = request.node.name
431 write_test_header(tc_name)
432
433 # Creating configuration from JSON
434 reset_config_on_routers(tgen)
435
436 input_dict = {
437 "r1": {
787e7624 438 "static_routes": [
439 {
440 "network": "10.0.20.1/32",
441 "admin_distance": 10,
442 "next_hop": "10.0.0.2",
443 }
444 ]
cb6b1d90
AP
445 }
446 }
447 result = create_static_routes(tgen, input_dict)
787e7624 448 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
cb6b1d90
AP
449
450 # Verifying admin distance once modified
451 result = verify_admin_distance_for_static_routes(tgen, input_dict)
787e7624 452 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
cb6b1d90
AP
453
454 write_test_footer(tc_name)
455
456
457def test_advertise_network_using_network_command(request):
458 """ Test advertise networks using network command."""
459
460 tgen = get_topogen()
461 if BGP_CONVERGENCE is not True:
787e7624 462 pytest.skip("skipped because of BGP Convergence failure")
cb6b1d90
AP
463
464 # test case name
465 tc_name = request.node.name
466 write_test_header(tc_name)
467
468 # Creating configuration from JSON
469 reset_config_on_routers(tgen)
470
471 # Api call to advertise networks
472 input_dict = {
473 "r1": {
474 "bgp": {
475 "address_family": {
476 "ipv4": {
477 "unicast": {
478 "advertise_networks": [
787e7624 479 {"network": "20.0.0.0/32", "no_of_network": 10},
480 {"network": "30.0.0.0/32", "no_of_network": 10},
cb6b1d90
AP
481 ]
482 }
483 }
484 }
485 }
486 }
487 }
488
489 result = create_router_bgp(tgen, topo, input_dict)
787e7624 490 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
cb6b1d90
AP
491
492 # Verifying RIB routes
787e7624 493 dut = "r2"
cb6b1d90 494 protocol = "bgp"
787e7624 495 result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol)
496 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
cb6b1d90
AP
497
498 write_test_footer(tc_name)
499
500
501def test_clear_bgp_and_verify(request):
502 """
503 Created few static routes and verified all routes are learned via BGP
504 cleared BGP and verified all routes are intact
505 """
506
507 tgen = get_topogen()
508 if BGP_CONVERGENCE is not True:
787e7624 509 pytest.skip("skipped because of BGP Convergence failure")
cb6b1d90
AP
510
511 # test case name
512 tc_name = request.node.name
513 write_test_header(tc_name)
514
515 # Creating configuration from JSON
516 reset_config_on_routers(tgen)
517
518 # clear ip bgp
787e7624 519 result = clear_bgp_and_verify(tgen, topo, "r1")
520 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
cb6b1d90
AP
521
522 write_test_footer(tc_name)
523
524
525def test_bgp_with_loopback_interface(request):
526 """
527 Test BGP with loopback interface
528
529 Adding keys:value pair "dest_link": "lo" and "source_link": "lo"
530 peer dict of input json file for all router's creating config using
531 loopback interface. Once BGP neighboship is up then verifying BGP
532 convergence
533 """
534
535 tgen = get_topogen()
536 if BGP_CONVERGENCE is not True:
787e7624 537 pytest.skip("skipped because of BGP Convergence failure")
cb6b1d90
AP
538
539 # test case name
540 tc_name = request.node.name
541 write_test_header(tc_name)
542
543 # Creating configuration from JSON
544 reset_config_on_routers(tgen)
545
787e7624 546 for routerN in sorted(topo["routers"].keys()):
547 for bgp_neighbor in topo["routers"][routerN]["bgp"]["address_family"]["ipv4"][
548 "unicast"
549 ]["neighbor"].keys():
cb6b1d90
AP
550
551 # Adding ['source_link'] = 'lo' key:value pair
787e7624 552 topo["routers"][routerN]["bgp"]["address_family"]["ipv4"]["unicast"][
553 "neighbor"
554 ][bgp_neighbor]["dest_link"] = {"lo": {"source_link": "lo",}}
cb6b1d90
AP
555
556 # Creating configuration from JSON
557 build_config_from_json(tgen, topo)
558
559 input_dict = {
560 "r1": {
787e7624 561 "static_routes": [
562 {"network": "1.0.2.17/32", "next_hop": "10.0.0.2"},
563 {"network": "1.0.3.17/32", "next_hop": "10.0.0.6"},
cb6b1d90
AP
564 ]
565 },
566 "r2": {
787e7624 567 "static_routes": [
568 {"network": "1.0.1.17/32", "next_hop": "10.0.0.1"},
569 {"network": "1.0.3.17/32", "next_hop": "10.0.0.10"},
cb6b1d90
AP
570 ]
571 },
572 "r3": {
787e7624 573 "static_routes": [
574 {"network": "1.0.1.17/32", "next_hop": "10.0.0.5"},
575 {"network": "1.0.2.17/32", "next_hop": "10.0.0.9"},
576 {"network": "1.0.4.17/32", "next_hop": "10.0.0.14"},
cb6b1d90
AP
577 ]
578 },
787e7624 579 "r4": {"static_routes": [{"network": "1.0.3.17/32", "next_hop": "10.0.0.13"}]},
cb6b1d90
AP
580 }
581 result = create_static_routes(tgen, input_dict)
787e7624 582 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
cb6b1d90
AP
583
584 # Api call verify whether BGP is converged
585 result = verify_bgp_convergence(tgen, topo)
787e7624 586 assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
cb6b1d90
AP
587
588 write_test_footer(tc_name)
589
590
787e7624 591if __name__ == "__main__":
7fa2079a
AP
592 args = ["-s"] + sys.argv[1:]
593 sys.exit(pytest.main(args))