]>
Commit | Line | Data |
---|---|---|
85d47773 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 | ||
24 | """ | |
25 | Following tests are covered to test large-community/community functionality: | |
26 | 1. Verify if large community attribute can be configured only in correct | |
27 | canonical format. | |
28 | 2. Verify that the community attribute value, which we have advertised are | |
29 | received in correct format and values, at the receiving end. | |
30 | 3. Verify BGP Large Community attribute"s transitive property attribute. | |
31 | 4. Verify that BGP Large Communities attribute are malformed, if the length of | |
32 | the BGP Large Communities Attribute value, expressed in octets, | |
33 | is not a non-zero multiple of 12. | |
34 | 5. Verify if overriding large community values works fine. | |
35 | 6. Verify that large community values" aggregation works fine. | |
36 | 7. Standard community also work fine in conjunction with large-community. | |
37 | 8. Matching prefixes based on attributes other than prefix list and make use | |
38 | of set clause (IPV6). | |
39 | 9. Matching prefixes based on attributes other than prefix list and make use | |
40 | of set clause (IPV4). | |
41 | 10. Verify community and large-community list operations in route-map with all | |
42 | clause (exact, all, any, regex) works. | |
43 | 11. Verify that any value in BGP Large communities for boundary values. | |
44 | 12. Clear BGP neighbor-ship and check if large community and community | |
45 | attributes are getting re-populated. | |
46 | ||
47 | """ | |
48 | ||
49 | import pytest | |
50 | import time | |
51 | from os import path as os_path | |
52 | import sys | |
53 | from json import load as json_load | |
54 | ||
55 | # Required to instantiate the topology builder class. | |
56 | from lib.topogen import Topogen, get_topogen | |
57 | from mininet.topo import Topo | |
58 | ||
59 | from lib.common_config import ( | |
60 | start_topology, write_test_header, | |
61 | write_test_footer, reset_config_on_routers, | |
62 | create_route_maps, create_bgp_community_lists, | |
63 | create_prefix_lists, verify_bgp_community, step, | |
64 | check_address_types | |
65 | ) | |
66 | from lib.topolog import logger | |
67 | from lib.bgp import ( | |
68 | verify_bgp_convergence, create_router_bgp, | |
69 | clear_bgp_and_verify | |
70 | ) | |
71 | from lib.topojson import build_topo_from_json, build_config_from_json | |
72 | ||
73 | # Save the Current Working Directory to find configuration files. | |
74 | CWD = os_path.dirname(os_path.realpath(__file__)) | |
75 | sys.path.append(os_path.join(CWD, "../")) | |
76 | sys.path.append(os_path.join(CWD, "../lib/")) | |
77 | ||
78 | # Reading the data from JSON File for topology and configuration creation | |
79 | jsonFile = "{}/bgp_large_community_topo_1.json".format(CWD) | |
80 | try: | |
81 | with open(jsonFile, "r") as topoJson: | |
82 | topo = json_load(topoJson) | |
83 | except IOError: | |
84 | logger.info("Could not read file:", jsonFile) | |
85 | ||
86 | # Global variables | |
87 | bgp_convergence = False | |
88 | NETWORK = { | |
89 | "ipv4": ["200.50.2.0", "200.50.2.1", "200.50.2.0"], | |
90 | "ipv6": ["1::1", "1::2", "1::0"] | |
91 | } | |
92 | MASK = {"ipv4": "32", "ipv6": "128"} | |
93 | NET_MASK = {"ipv4": "24", "ipv6": "120"} | |
94 | IPV4_NET = ["200.50.2.0"] | |
95 | IPV6_NET = ["1::0"] | |
96 | CONFIG_ROUTER_R1 = False | |
97 | CONFIG_ROUTER_R2 = False | |
98 | CONFIG_ROUTER_ADDITIVE = False | |
99 | ADDR_TYPES = [] | |
100 | LARGE_COMM = { | |
101 | "r1": "1:1:1 1:2:1 1:3:1 1:4:1 1:5:1", | |
102 | "r2": "2:1:1 2:2:1 2:3:1 2:4:1 2:5:1", | |
103 | "mal_1": "1:1 1:2 1:3 1:4 1:5", | |
104 | "pf_list_1": "0:0:1 0:0:10 0:0:100", | |
105 | "pf_list_2": "0:0:2 0:0:20 0:0:200", | |
106 | "agg_1": "0:0:1 0:0:2 0:0:10 0:0:20 0:0:100 0:0:200 2:1:1 " | |
107 | "2:2:1 2:3:1 2:4:1 2:5:1", | |
108 | "agg_2": "0:0:2 0:0:20 0:0:200 2:1:1 " | |
109 | "2:2:1 2:3:1 2:4:1 2:5:1" | |
110 | } | |
111 | STANDARD_COMM = { | |
112 | "r1": "1:1 1:2 1:3 1:4 1:5", | |
113 | "r2": "2:1 2:2 2:3 2:4 2:5", | |
114 | "mal_1": "1 2 3 4 5", | |
115 | "pf_list_1": "0:1 0:10 0:100", | |
116 | "pf_list_2": "0:2 0:20 0:200", | |
117 | "agg_1": "0:1 0:2 0:10 0:20 0:100 0:200 2:1 2:2 2:3 2:4 2:5", | |
118 | "agg_2": "0:2 0:20 0:200 2:1 2:2 2:3 2:4 2:5" | |
119 | } | |
120 | ||
121 | ||
122 | class CreateTopo(Topo): | |
123 | """ | |
124 | Test topology builder | |
125 | ||
126 | ||
127 | * `Topo`: Topology object | |
128 | """ | |
129 | ||
130 | def build(self, *_args, **_opts): | |
131 | """Build function""" | |
132 | tgen = get_topogen(self) | |
133 | ||
134 | # Building topology from json file | |
135 | build_topo_from_json(tgen, topo) | |
136 | ||
137 | ||
138 | def setup_module(mod): | |
139 | """ | |
140 | Sets up the pytest environment | |
141 | ||
142 | * `mod`: module name | |
143 | """ | |
144 | global ADDR_TYPES | |
145 | testsuite_run_time = time.asctime(time.localtime(time.time())) | |
146 | logger.info("Testsuite start time: {}".format(testsuite_run_time)) | |
147 | logger.info("=" * 40) | |
148 | ||
149 | logger.info("Running setup_module to create topology") | |
150 | ||
151 | # This function initiates the topology build with Topogen... | |
152 | tgen = Topogen(CreateTopo, mod.__name__) | |
153 | # ... and here it calls Mininet initialization functions. | |
154 | ||
155 | # Starting topology, create tmp files which are loaded to routers | |
156 | # to start deamons and then start routers | |
157 | start_topology(tgen) | |
158 | ||
159 | # Creating configuration from JSON | |
160 | build_config_from_json(tgen, topo) | |
161 | ||
162 | # Checking BGP convergence | |
163 | global bgp_convergence | |
164 | ||
165 | # Don"t run this test if we have any failure. | |
166 | if tgen.routers_have_failure(): | |
167 | pytest.skip(tgen.errors) | |
168 | ||
169 | ##tgen.mininet_cli() | |
170 | # Api call verify whether BGP is converged | |
171 | bgp_convergence = verify_bgp_convergence(tgen, topo) | |
172 | assert bgp_convergence is True, ("setup_module :Failed \n Error:" | |
173 | " {}".format(bgp_convergence)) | |
174 | ||
175 | ADDR_TYPES = check_address_types() | |
176 | logger.info("Running setup_module() done") | |
177 | ||
178 | ||
179 | def teardown_module(): | |
180 | """ | |
181 | Teardown the pytest environment | |
182 | ||
183 | * `mod`: module name | |
184 | """ | |
185 | ||
186 | logger.info("Running teardown_module to delete topology") | |
187 | ||
188 | tgen = get_topogen() | |
189 | ||
190 | # Stop toplogy and Remove tmp files | |
191 | tgen.stop_topology() | |
192 | ||
193 | logger.info("Testsuite end time: {}". | |
194 | format(time.asctime(time.localtime(time.time())))) | |
195 | logger.info("=" * 40) | |
196 | ||
197 | ||
198 | def config_router_r1(tgen, topo, tc_name): | |
199 | global CONFIG_ROUTER_R1 | |
200 | ||
201 | input_dict_1 = { | |
202 | "r1": { | |
203 | "route_maps": { | |
204 | "LC1": [ | |
205 | { | |
206 | "action": "permit", | |
207 | "seq_id": "10", | |
208 | "set": { | |
209 | "large_community": { | |
210 | "num": LARGE_COMM["r1"] | |
211 | }, | |
212 | "community": { | |
213 | "num": STANDARD_COMM["r1"] | |
214 | } | |
215 | } | |
216 | } | |
217 | ] | |
218 | } | |
219 | } | |
220 | } | |
221 | ||
222 | step("Configuring LC1 on r1") | |
223 | result = create_route_maps(tgen, input_dict_1) | |
224 | assert result is True, "Test case {} : Failed \n Error: {}".format( | |
225 | tc_name, result) | |
226 | ||
227 | # Configure neighbor for route map | |
228 | input_dict_2 = { | |
229 | "r1": { | |
230 | "bgp": { | |
231 | "address_family": { | |
232 | "ipv4": { | |
233 | "unicast": { | |
234 | "advertise_networks": [ | |
235 | { | |
236 | "network": "%s/%s" % ( | |
237 | NETWORK["ipv4"][0], MASK["ipv4"]), | |
238 | "no_of_network": 4 | |
239 | } | |
240 | ], | |
241 | "neighbor": { | |
242 | "r2": { | |
243 | "dest_link": { | |
244 | "r1-link1": { | |
245 | "route_maps": [{ | |
246 | "name": "LC1", | |
247 | "direction": "out" | |
248 | }] | |
249 | } | |
250 | } | |
251 | }, | |
252 | "r3": { | |
253 | "dest_link": { | |
254 | "r1-link1": { | |
255 | "route_maps": [{ | |
256 | "name": "LC1", | |
257 | "direction": "out" | |
258 | }] | |
259 | } | |
260 | } | |
261 | } | |
262 | } | |
263 | } | |
264 | }, | |
265 | "ipv6": { | |
266 | "unicast": { | |
267 | "advertise_networks": [ | |
268 | { | |
269 | "network": "%s/%s" % ( | |
270 | NETWORK["ipv6"][0], MASK["ipv6"]), | |
271 | "no_of_network": 4 | |
272 | } | |
273 | ], | |
274 | "neighbor": { | |
275 | "r2": { | |
276 | "dest_link": { | |
277 | "r1-link1": { | |
278 | "route_maps": [{ | |
279 | "name": "LC1", | |
280 | "direction": "out" | |
281 | }] | |
282 | } | |
283 | } | |
284 | }, | |
285 | "r3": { | |
286 | "dest_link": { | |
287 | "r1-link1": { | |
288 | "route_maps": [{ | |
289 | "name": "LC1", | |
290 | "direction": "out" | |
291 | }] | |
292 | } | |
293 | } | |
294 | } | |
295 | } | |
296 | } | |
297 | } | |
298 | } | |
299 | } | |
300 | } | |
301 | } | |
302 | ||
303 | step("Applying LC1 on r1 neighbors and advertising networks") | |
304 | result = create_router_bgp(tgen, topo, input_dict_2) | |
305 | assert result is True, "Test case {} : Failed \n Error: {}".format( | |
306 | tc_name, result) | |
307 | ||
308 | CONFIG_ROUTER_R1 = True | |
309 | ||
310 | ||
311 | def config_router_r2(tgen, topo, tc_name): | |
312 | global CONFIG_ROUTER_R2 | |
313 | ||
314 | input_dict = { | |
315 | "r2": { | |
316 | "route_maps": { | |
317 | "LC2": [ | |
318 | { | |
319 | "action": "permit", | |
320 | "seq_id": "10", | |
321 | "set": { | |
322 | "large_community": { | |
323 | "num": LARGE_COMM["r2"] | |
324 | }, | |
325 | "community": { | |
326 | "num": STANDARD_COMM["r2"] | |
327 | } | |
328 | } | |
329 | } | |
330 | ] | |
331 | } | |
332 | } | |
333 | } | |
334 | ||
335 | step("Configuring route-maps LC2 on r2") | |
336 | result = create_route_maps(tgen, input_dict) | |
337 | assert result is True, "Test case {} : Failed \n Error: {}". \ | |
338 | format(tc_name, result) | |
339 | ||
340 | input_dict_1 = { | |
341 | "r2": { | |
342 | "bgp": { | |
343 | "address_family": { | |
344 | "ipv4": { | |
345 | "unicast": { | |
346 | "neighbor": { | |
347 | "r4": { | |
348 | "dest_link": { | |
349 | "r2-link1": { | |
350 | "route_maps": [{ | |
351 | "name": "LC2", | |
352 | "direction": "out" | |
353 | }] | |
354 | } | |
355 | } | |
356 | } | |
357 | } | |
358 | } | |
359 | }, | |
360 | "ipv6": { | |
361 | "unicast": { | |
362 | "neighbor": { | |
363 | "r4": { | |
364 | "dest_link": { | |
365 | "r2-link1": { | |
366 | "route_maps": [{ | |
367 | "name": "LC2", | |
368 | "direction": "out" | |
369 | }] | |
370 | } | |
371 | } | |
372 | } | |
373 | } | |
374 | } | |
375 | } | |
376 | } | |
377 | } | |
378 | } | |
379 | } | |
380 | ||
381 | step("Applying LC2 on r2 neighbors in out direction") | |
382 | result = create_router_bgp(tgen, topo, input_dict_1) | |
383 | assert result is True, "Test case {} : Failed \n Error: {}". \ | |
384 | format(tc_name, result) | |
385 | ||
386 | CONFIG_ROUTER_R2 = True | |
387 | ||
388 | ||
389 | def config_router_additive(tgen, topo, tc_name): | |
390 | global CONFIG_ROUTER_ADDITIVE | |
391 | ||
392 | input_dict = { | |
393 | "r2": { | |
394 | "route_maps": { | |
395 | "LC2": [ | |
396 | { | |
397 | "action": "permit", | |
398 | "seq_id": "10", | |
399 | "set": { | |
400 | "large_community": { | |
401 | "num": LARGE_COMM["r2"], | |
402 | "action": "additive" | |
403 | }, | |
404 | "community": { | |
405 | "num": STANDARD_COMM["r2"], | |
406 | "action": "additive" | |
407 | } | |
408 | } | |
409 | } | |
410 | ] | |
411 | } | |
412 | } | |
413 | } | |
414 | ||
415 | step("Configuring LC2 with community attributes as additive") | |
416 | result = create_route_maps(tgen, input_dict) | |
417 | assert result is True, "Test case {} : Failed \n Error: {}". \ | |
418 | format(tc_name, result) | |
419 | ||
420 | # tgen.mininet_cli() | |
421 | CONFIG_ROUTER_ADDITIVE = True | |
422 | ||
423 | ||
424 | def config_for_as_path(tgen, topo, tc_name): | |
425 | config_router_r1(tgen, topo, tc_name) | |
426 | ||
427 | config_router_r2(tgen, topo, tc_name) | |
428 | ||
429 | # Create ipv6 prefix list | |
430 | input_dict_1 = { | |
431 | "r1": { | |
432 | "prefix_lists": { | |
433 | "ipv4": { | |
434 | "pf_list_1": [ | |
435 | { | |
436 | "seqid": "10", | |
437 | "network": "%s/%s" % (NETWORK["ipv4"][0], | |
438 | MASK["ipv4"]), | |
439 | "action": "permit" | |
440 | } | |
441 | ], | |
442 | "pf_list_2": [ | |
443 | { | |
444 | "seqid": "10", | |
445 | "network": "%s/%s" % (NETWORK["ipv4"][1], | |
446 | MASK["ipv4"]), | |
447 | "action": "permit" | |
448 | } | |
449 | ] | |
450 | }, | |
451 | "ipv6": { | |
452 | "pf_list_3": [ | |
453 | { | |
454 | "seqid": "10", | |
455 | "network": "%s/%s" % (NETWORK["ipv6"][0], | |
456 | MASK["ipv6"]), | |
457 | "action": "permit" | |
458 | } | |
459 | ], | |
460 | "pf_list_4": [ | |
461 | { | |
462 | "seqid": "10", | |
463 | "network": "%s/%s" % (NETWORK["ipv6"][1], | |
464 | MASK["ipv6"]), | |
465 | "action": "permit" | |
466 | } | |
467 | ] | |
468 | } | |
469 | ||
470 | } | |
471 | } | |
472 | } | |
473 | ||
474 | step("Configuring prefix-lists on r1 to filter networks") | |
475 | result = create_prefix_lists(tgen, input_dict_1) | |
476 | assert result is True, "Test case {} : Failed \n Error: {}". \ | |
477 | format(tc_name, result) | |
478 | ||
479 | input_dict_2 = { | |
480 | "r1": { | |
481 | "route_maps": { | |
482 | "LC1": [ | |
483 | { | |
484 | "action": "permit", | |
485 | "seq_id": 10, | |
486 | "match": { | |
487 | "ipv4": { | |
488 | "prefix_lists": "pf_list_1" | |
489 | } | |
490 | }, | |
491 | "set": { | |
492 | "large_community": { | |
493 | "num": LARGE_COMM["pf_list_1"] | |
494 | }, | |
495 | "community": { | |
496 | "num": STANDARD_COMM["pf_list_1"] | |
497 | } | |
498 | } | |
499 | }, | |
500 | { | |
501 | "action": "permit", | |
502 | "seq_id": 20, | |
503 | "match": { | |
504 | "ipv6": { | |
505 | "prefix_lists": "pf_list_3" | |
506 | } | |
507 | }, | |
508 | "set": { | |
509 | "large_community": { | |
510 | "num": LARGE_COMM["pf_list_1"] | |
511 | }, | |
512 | "community": { | |
513 | "num": STANDARD_COMM["pf_list_1"] | |
514 | } | |
515 | } | |
516 | }, | |
517 | { | |
518 | "action": "permit", | |
519 | "seq_id": 30, | |
520 | "match": { | |
521 | "ipv4": { | |
522 | "prefix_lists": "pf_list_2" | |
523 | } | |
524 | }, | |
525 | "set": { | |
526 | "large_community": { | |
527 | "num": LARGE_COMM["pf_list_2"] | |
528 | }, | |
529 | "community": { | |
530 | "num": STANDARD_COMM["pf_list_2"] | |
531 | } | |
532 | } | |
533 | }, | |
534 | { | |
535 | "action": "permit", | |
536 | "seq_id": 40, | |
537 | "match": { | |
538 | "ipv6": { | |
539 | "prefix_lists": "pf_list_4" | |
540 | } | |
541 | }, | |
542 | "set": { | |
543 | "large_community": { | |
544 | "num": LARGE_COMM["pf_list_2"] | |
545 | }, | |
546 | "community": { | |
547 | "num": STANDARD_COMM["pf_list_2"] | |
548 | } | |
549 | } | |
550 | } | |
551 | ] | |
552 | } | |
553 | } | |
554 | } | |
555 | ||
556 | step("Applying prefix-lists match in route-map LC1 on r1. Setting" | |
557 | " community attritbute for filtered networks") | |
558 | result = create_route_maps(tgen, input_dict_2) | |
559 | assert result is True, "Test case {} : Failed \n Error: {}". \ | |
560 | format(tc_name, result) | |
561 | ||
562 | config_router_additive(tgen, topo, tc_name) | |
563 | ||
564 | input_dict_3 = { | |
565 | "r4": { | |
566 | "bgp_community_lists": [ | |
567 | { | |
568 | "community_type": "standard", | |
569 | "action": "permit", | |
570 | "name": "ANY", | |
571 | "value": LARGE_COMM["pf_list_1"], | |
572 | "large": True | |
573 | }, | |
574 | { | |
575 | "community_type": "standard", | |
576 | "action": "permit", | |
577 | "name": "ANY", | |
578 | "value": STANDARD_COMM["pf_list_1"], | |
579 | } | |
580 | ] | |
581 | } | |
582 | } | |
583 | ||
584 | step("Configuring bgp community lists on r4") | |
585 | result = create_bgp_community_lists(tgen, input_dict_3) | |
586 | assert result is True, "Test case {} : Failed \n Error: {}". \ | |
587 | format(tc_name, result) | |
588 | ||
589 | input_dict_4 = { | |
590 | "r4": { | |
591 | "route_maps": { | |
592 | "LC4": [ | |
593 | { | |
594 | "action": "permit", | |
595 | "seq_id": "10", | |
596 | "match": { | |
597 | "large_community_list": {"id": "ANY"}, | |
598 | "community_list": {"id": "ANY"} | |
599 | }, | |
600 | "set": { | |
0a9fe278 | 601 | "path": { |
85d47773 AP |
602 | "as_num": "4000000", |
603 | "as_action": "prepend" | |
604 | } | |
605 | } | |
606 | } | |
607 | ] | |
608 | } | |
609 | } | |
610 | } | |
611 | ||
612 | step("Applying community list on route-map on r4") | |
613 | result = create_route_maps(tgen, input_dict_4) | |
614 | assert result is True, "Test case {} : Failed \n Error: {}". \ | |
615 | format(tc_name, result) | |
616 | ||
617 | input_dict_5 = { | |
618 | "r4": { | |
619 | "bgp": { | |
620 | "address_family": { | |
621 | "ipv4": { | |
622 | "unicast": { | |
623 | "neighbor": { | |
624 | "r5": { | |
625 | "dest_link": { | |
626 | "r4-link1": { | |
627 | "route_maps": [{ | |
628 | "name": "LC4", | |
629 | "direction": "out" | |
630 | }] | |
631 | } | |
632 | } | |
633 | } | |
634 | } | |
635 | } | |
636 | }, | |
637 | "ipv6": { | |
638 | "unicast": { | |
639 | "neighbor": { | |
640 | "r5": { | |
641 | "dest_link": { | |
642 | "r4-link1": { | |
643 | "route_maps": [{ | |
644 | "name": "LC4", | |
645 | "direction": "out" | |
646 | }] | |
647 | } | |
648 | } | |
649 | } | |
650 | } | |
651 | } | |
652 | } | |
653 | } | |
654 | } | |
655 | } | |
656 | } | |
657 | ||
658 | step("Applying route-map LC4 out from r4 to r5 ") | |
659 | result = create_router_bgp(tgen, topo, input_dict_5) | |
660 | assert result is True, "Test case {} : Failed \n Error: {}". \ | |
661 | format(tc_name, result) | |
662 | ||
663 | ||
664 | ##################################################### | |
665 | # | |
666 | # Test cases | |
667 | # | |
668 | ##################################################### | |
669 | def test_large_community_set(request): | |
670 | """ | |
671 | Verify if large community attribute can be configured only in correct | |
672 | canonical format. | |
673 | """ | |
674 | tc_name = request.node.name | |
675 | write_test_header(tc_name) | |
676 | tgen = get_topogen() | |
677 | ||
678 | # Don"t run this test if we have any failure. | |
679 | if tgen.routers_have_failure(): | |
680 | pytest.skip(tgen.errors) | |
681 | ||
682 | # API call to modify router id | |
683 | # input_dict dictionary to be provided to configure route_map | |
684 | input_dict = { | |
685 | "r1": { | |
686 | "route_maps": { | |
687 | "LC1": [ | |
688 | { | |
689 | "action": "permit", | |
690 | "seq_id": "10", | |
691 | "set": { | |
692 | "large_community": {"num": LARGE_COMM["r1"]}, | |
693 | "community": {"num": STANDARD_COMM["r1"]} | |
694 | } | |
695 | } | |
696 | ] | |
697 | } | |
698 | } | |
699 | } | |
700 | ||
701 | step("Trying to set bgp communities") | |
702 | result = create_route_maps(tgen, input_dict) | |
703 | assert result is True, "Test case {} : Failed \n Error: {}".format( | |
704 | tc_name, result) | |
705 | ||
706 | write_test_footer(tc_name) | |
707 | ||
708 | ||
709 | def test_large_community_advertise(request): | |
710 | """ | |
711 | Verify that the community attribute value, which we have advertised are | |
712 | received in correct format and values, at the receiving end. | |
713 | """ | |
714 | tc_name = request.node.name | |
715 | write_test_header(tc_name) | |
716 | tgen = get_topogen() | |
717 | ||
718 | # Don"t run this test if we have any failure. | |
719 | if tgen.routers_have_failure(): | |
720 | pytest.skip(tgen.errors) | |
721 | ||
722 | reset_config_on_routers(tgen) | |
723 | config_router_r1(tgen, topo, tc_name) | |
724 | ||
725 | input_dict = { | |
726 | "largeCommunity": LARGE_COMM["r1"], | |
727 | "community": STANDARD_COMM["r1"], | |
728 | } | |
729 | ||
730 | for adt in ADDR_TYPES: | |
731 | result = verify_bgp_community(tgen, adt, "r2", [NETWORK[adt][0]], | |
732 | input_dict) | |
733 | assert result is True, "Test case {} : Failed \n Error: {}".format( | |
734 | tc_name, result) | |
735 | ||
736 | result = verify_bgp_community(tgen, adt, "r3", [NETWORK[adt][0]], | |
737 | input_dict) | |
738 | assert result is True, "Test case {} : Failed \n Error: {}".format( | |
739 | tc_name, result) | |
740 | ||
741 | write_test_footer(tc_name) | |
742 | ||
743 | ||
744 | def test_large_community_transitive(request): | |
745 | """ | |
746 | Verify BGP Large Community attribute"s transitive property attribute. | |
747 | """ | |
748 | tc_name = request.node.name | |
749 | write_test_header(tc_name) | |
750 | tgen = get_topogen() | |
751 | ||
752 | # Don"t run this test if we have any failure. | |
753 | if tgen.routers_have_failure(): | |
754 | pytest.skip(tgen.errors) | |
755 | ||
756 | reset_config_on_routers(tgen) | |
757 | ||
758 | config_router_r1(tgen, topo, tc_name) | |
759 | ||
760 | input_dict_1 = { | |
761 | "largeCommunity": LARGE_COMM["r1"], | |
762 | "community": STANDARD_COMM["r1"] | |
763 | } | |
764 | ||
765 | for adt in ADDR_TYPES: | |
766 | result = verify_bgp_community(tgen, adt, "r4", [NETWORK[adt][0]], | |
767 | input_dict_1) | |
768 | assert result is True, "Test case {} : Failed \n Error: {}".format( | |
769 | tc_name, result) | |
770 | ||
771 | write_test_footer(tc_name) | |
772 | ||
773 | ||
774 | def test_large_community_override(request): | |
775 | """ | |
776 | Verify if overriding large community values works fine. | |
777 | """ | |
778 | tc_name = request.node.name | |
779 | write_test_header(tc_name) | |
780 | tgen = get_topogen() | |
781 | ||
782 | # Don"t run this test if we have any failure. | |
783 | if tgen.routers_have_failure(): | |
784 | pytest.skip(tgen.errors) | |
785 | ||
786 | reset_config_on_routers(tgen) | |
787 | config_router_r1(tgen, topo, tc_name) | |
788 | ||
789 | config_router_r2(tgen, topo, tc_name) | |
790 | ||
791 | input_dict_3 = { | |
792 | "largeCommunity": LARGE_COMM["r2"], | |
793 | "community": STANDARD_COMM["r2"] | |
794 | } | |
795 | ||
796 | for adt in ADDR_TYPES: | |
797 | result = verify_bgp_community(tgen, adt, "r4", [NETWORK[adt][1]], | |
798 | input_dict_3) | |
799 | assert result is True, "Test case {} : Failed \n Error: {}". \ | |
800 | format(tc_name, result) | |
801 | ||
802 | write_test_footer(tc_name) | |
803 | ||
804 | ||
805 | def test_large_community_additive(request): | |
806 | """ | |
807 | Verify that large community values" aggregation works fine. | |
808 | """ | |
809 | tc_name = request.node.name | |
810 | write_test_header(tc_name) | |
811 | tgen = get_topogen() | |
812 | ||
813 | # Don"t run this test if we have any failure. | |
814 | if tgen.routers_have_failure(): | |
815 | pytest.skip(tgen.errors) | |
816 | ||
817 | reset_config_on_routers(tgen) | |
818 | config_router_r1(tgen, topo, tc_name) | |
819 | ||
820 | config_router_r2(tgen, topo, tc_name) | |
821 | ||
822 | config_router_additive(tgen, topo, tc_name) | |
823 | ||
824 | input_dict_1 = { | |
825 | "largeCommunity": "%s %s" % (LARGE_COMM["r1"], LARGE_COMM["r2"]), | |
826 | "community": "%s %s" % (STANDARD_COMM["r1"], STANDARD_COMM["r2"]) | |
827 | } | |
828 | ||
829 | for adt in ADDR_TYPES: | |
830 | result = verify_bgp_community(tgen, adt, "r4", [NETWORK[adt][0]], | |
831 | input_dict_1) | |
832 | assert result is True, "Test case {} : Failed \n Error: {}". \ | |
833 | format(tc_name, result) | |
834 | ||
835 | write_test_footer(tc_name) | |
836 | ||
837 | ||
838 | def test_large_community_match_as_path(request): | |
839 | """ | |
840 | Matching prefixes based on attributes other than prefix list and make use | |
841 | of set clause. | |
842 | """ | |
843 | ||
844 | tc_name = request.node.name | |
845 | write_test_header(tc_name) | |
846 | tgen = get_topogen() | |
847 | ||
848 | # Don"t run this test if we have any failure. | |
849 | if tgen.routers_have_failure(): | |
850 | pytest.skip(tgen.errors) | |
851 | ||
852 | reset_config_on_routers(tgen) | |
853 | config_for_as_path(tgen, topo, tc_name) | |
854 | ||
855 | input_dict = { | |
856 | "largeCommunity": "%s %s" % ( | |
857 | LARGE_COMM["pf_list_1"], LARGE_COMM["r2"]), | |
858 | "community": "%s %s" % ( | |
859 | STANDARD_COMM["pf_list_1"], STANDARD_COMM["r2"]), | |
860 | } | |
861 | ||
862 | input_dict_1 = { | |
863 | "largeCommunity": "%s %s" % ( | |
864 | LARGE_COMM["pf_list_2"], LARGE_COMM["r2"]), | |
865 | "community": "%s %s" % ( | |
866 | STANDARD_COMM["pf_list_2"], STANDARD_COMM["r2"]), | |
867 | } | |
868 | ||
869 | for adt in ADDR_TYPES: | |
870 | result = verify_bgp_community(tgen, adt, "r5", [NETWORK[adt][0]], | |
871 | input_dict) | |
872 | assert result is True, "Test case {} : Failed \n Error: {}". \ | |
873 | format(tc_name, result) | |
874 | ||
875 | result = verify_bgp_community(tgen, adt, "r5", [NETWORK[adt][1]], | |
876 | input_dict_1, expected=False) | |
877 | ||
878 | assert result is not True, "Test case {} : Should fail \n Error: {}". \ | |
879 | format(tc_name, result) | |
880 | ||
881 | write_test_footer(tc_name) | |
882 | ||
883 | ||
884 | def test_large_community_match_all(request): | |
885 | """ | |
886 | Verify community and large-community list operations in route-map with all | |
887 | clause (exact, all, any, regex) works. | |
888 | """ | |
889 | tc_name = request.node.name | |
890 | write_test_header(tc_name) | |
891 | tgen = get_topogen() | |
892 | ||
893 | # Don"t run this test if we have any failure. | |
894 | if tgen.routers_have_failure(): | |
895 | pytest.skip(tgen.errors) | |
896 | ||
897 | reset_config_on_routers(tgen) | |
898 | config_router_r1(tgen, topo, tc_name) | |
899 | ||
900 | config_router_r2(tgen, topo, tc_name) | |
901 | ||
902 | config_router_additive(tgen, topo, tc_name) | |
903 | ||
904 | input_dict_1 = { | |
905 | "r4": { | |
906 | "bgp_community_lists": [ | |
907 | { | |
908 | "community_type": "standard", | |
909 | "action": "permit", | |
910 | "name": "ANY", | |
911 | "value": "1:1:1", | |
912 | "large": True | |
913 | }, | |
914 | { | |
915 | "community_type": "standard", | |
916 | "action": "permit", | |
917 | "name": "ALL", | |
918 | "value": "1:1:1 1:2:1 1:3:1 1:4:1 1:5:1 2:1:1 2:2:1", | |
919 | "large": True | |
920 | }, | |
921 | { | |
922 | "community_type": "expanded", | |
923 | "action": "permit", | |
924 | "name": "EXP_ALL", | |
925 | "value": "1:1:1 1:2:1 1:3:1 1:4:1 1:5:1 2:[1-5]:1", | |
926 | "large": True | |
927 | } | |
928 | ] | |
929 | } | |
930 | } | |
931 | ||
932 | step("Create bgp community lists for ANY, EXACT and EXP_ALL match") | |
933 | ||
934 | result = create_bgp_community_lists(tgen, input_dict_1) | |
935 | assert result is True, "Test case {} : Failed \n Error: {}". \ | |
936 | format(tc_name, result) | |
937 | ||
938 | input_dict_2 = { | |
939 | "r4": { | |
940 | "route_maps": { | |
941 | "LC4": [ | |
942 | { | |
943 | "action": "permit", | |
944 | "seq_id": "10", | |
945 | "match": {"large-community-list": {"id": "ANY"}} | |
946 | }, | |
947 | { | |
948 | "action": "permit", | |
949 | "seq_id": "20", | |
950 | "match": {"large-community-list": {"id": "EXACT"}} | |
951 | }, | |
952 | { | |
953 | "action": "permit", | |
954 | "seq_id": "30", | |
955 | "match": {"large-community-list": {"id": "EXP_ALL"}} | |
956 | } | |
957 | ] | |
958 | } | |
959 | } | |
960 | } | |
961 | ||
962 | step("Applying bgp community lits on LC4 route-map") | |
963 | result = create_route_maps(tgen, input_dict_2) | |
964 | assert result is True, "Test case {} : Failed \n Error: {}". \ | |
965 | format(tc_name, result) | |
966 | ||
967 | input_dict_3 = { | |
968 | "r4": { | |
969 | "bgp": { | |
970 | "address_family": { | |
971 | "ipv4": { | |
972 | "unicast": { | |
973 | "neighbor": { | |
974 | "r5": { | |
975 | "dest_link": { | |
976 | "r4-link1": { | |
977 | "route_maps": [{ | |
978 | "name": "LC4", | |
979 | "direction": "in" | |
980 | }] | |
981 | } | |
982 | } | |
983 | } | |
984 | } | |
985 | } | |
986 | }, | |
987 | "ipv6": { | |
988 | "unicast": { | |
989 | "neighbor": { | |
990 | "r5": { | |
991 | "dest_link": { | |
992 | "r4-link1": { | |
993 | "route_maps": [{ | |
994 | "name": "LC4", | |
995 | "direction": "in" | |
996 | }] | |
997 | } | |
998 | } | |
999 | } | |
1000 | } | |
1001 | } | |
1002 | } | |
1003 | } | |
1004 | } | |
1005 | } | |
1006 | } | |
1007 | ||
1008 | step("Apply route-mpa LC4 on r4 for r2 neighbor, direction 'in'") | |
1009 | ||
1010 | result = create_router_bgp(tgen, topo, input_dict_3) | |
1011 | assert result is True, "Test case {} : Failed \n Error: {}". \ | |
1012 | format(tc_name, result) | |
1013 | ||
1014 | input_dict_4 = { | |
1015 | "largeCommunity": "1:1:1 1:2:1 1:3:1 1:4:1 1:5:1 2:1:1 2:2:1 2:3:1 " | |
1016 | "2:4:1 2:5:1" | |
1017 | } | |
1018 | ||
1019 | for adt in ADDR_TYPES: | |
1020 | result = verify_bgp_community(tgen, adt, "r4", [NETWORK[adt][0]], | |
1021 | input_dict_4) | |
1022 | assert result is True, "Test case {} : Should fail \n Error: {}". \ | |
1023 | format(tc_name, result) | |
1024 | ||
1025 | write_test_footer(tc_name) | |
1026 | ||
1027 | ||
1028 | #@pytest.mark.skip(reason="as-set not working for ipv6") | |
1029 | def test_large_community_aggregate_network(request): | |
1030 | """ | |
1031 | Restart router and check if large community and community | |
1032 | attributes are getting re-populated. | |
1033 | """ | |
1034 | ||
1035 | tc_name = request.node.name | |
1036 | write_test_header(tc_name) | |
1037 | ||
1038 | tgen = get_topogen() | |
1039 | ||
1040 | # Don"t run this test if we have any failure. | |
1041 | if tgen.routers_have_failure(): | |
1042 | pytest.skip(tgen.errors) | |
1043 | ||
1044 | reset_config_on_routers(tgen) | |
1045 | ||
1046 | config_for_as_path(tgen, topo, tc_name) | |
1047 | ||
1048 | input_dict = { | |
1049 | "community": STANDARD_COMM["agg_1"], | |
1050 | "largeCommunity": LARGE_COMM["agg_1"] | |
1051 | } | |
1052 | ||
1053 | input_dict_1 = { | |
1054 | "r2": { | |
1055 | "bgp": { | |
1056 | "address_family": { | |
1057 | "ipv4": { | |
1058 | "unicast": { | |
1059 | "aggregate_address": [ | |
1060 | { | |
1061 | "network": "%s/%s" % ( | |
1062 | NETWORK["ipv4"][2], NET_MASK["ipv4"]), | |
1063 | "as_set": True | |
1064 | } | |
1065 | ] | |
1066 | } | |
1067 | }, | |
1068 | "ipv6": { | |
1069 | "unicast": { | |
1070 | "aggregate_address": [ | |
1071 | { | |
1072 | "network": "%s/%s" % ( | |
1073 | NETWORK["ipv6"][2], NET_MASK["ipv6"]), | |
1074 | "as_set": True | |
1075 | } | |
1076 | ] | |
1077 | } | |
1078 | } | |
1079 | } | |
1080 | } | |
1081 | } | |
1082 | } | |
1083 | ||
1084 | step("Configuring aggregate address as-set on r2") | |
1085 | result = create_router_bgp(tgen, topo, input_dict_1) | |
1086 | assert result is True, "Test case {} : Failed \n Error: {}".format( | |
1087 | tc_name, result) | |
1088 | ||
1089 | for adt in ADDR_TYPES: | |
1090 | result = verify_bgp_community(tgen, adt, "r4", | |
1091 | ["%s/%s" % (NETWORK[adt][2], | |
1092 | NET_MASK[adt])], | |
1093 | input_dict) | |
1094 | assert result is True, "Test case {} : Failed \n Error: {}". \ | |
1095 | format(tc_name, result) | |
1096 | ||
1097 | input_dict_2 = { | |
1098 | "r1": { | |
1099 | "bgp": { | |
1100 | "address_family": { | |
1101 | "ipv4": { | |
1102 | "unicast": { | |
1103 | "advertise_networks": [ | |
1104 | { | |
1105 | "network": "%s/%s" % ( | |
1106 | NETWORK["ipv4"][0], MASK["ipv4"]), | |
1107 | "no_of_network": 1, | |
1108 | "delete": True | |
1109 | } | |
1110 | ] | |
1111 | } | |
1112 | }, | |
1113 | "ipv6": { | |
1114 | "unicast": { | |
1115 | "advertise_networks": [ | |
1116 | { | |
1117 | "network": "%s/%s" % ( | |
1118 | NETWORK["ipv6"][0], MASK["ipv6"]), | |
1119 | "no_of_network": 1, | |
1120 | "delete": True | |
1121 | } | |
1122 | ] | |
1123 | } | |
1124 | } | |
1125 | } | |
1126 | } | |
1127 | } | |
1128 | } | |
1129 | ||
1130 | step("Stop advertising one of the networks") | |
1131 | result = create_router_bgp(tgen, topo, input_dict_2) | |
1132 | assert result is True, "Test case {} : Failed \n Error: {}".format( | |
1133 | tc_name, result) | |
1134 | ||
1135 | input_dict_3 = { | |
1136 | "community": STANDARD_COMM["agg_2"], | |
1137 | "largeCommunity": LARGE_COMM["agg_2"] | |
1138 | } | |
1139 | ||
1140 | for adt in ADDR_TYPES: | |
1141 | step("Verifying bgp community values on r5 is also modified") | |
1142 | result = verify_bgp_community(tgen, adt, "r4", | |
1143 | ["%s/%s" % (NETWORK[adt][2], | |
1144 | NET_MASK[adt])], | |
1145 | input_dict_3) | |
1146 | assert result is True, "Test case {} : Failed \n Error: {}". \ | |
1147 | format(tc_name, result) | |
1148 | ||
1149 | write_test_footer(tc_name) | |
1150 | ||
1151 | ||
1152 | def test_large_community_boundary_values(request): | |
1153 | """ | |
1154 | Verify that any value in BGP Large communities for boundary values. | |
1155 | """ | |
1156 | tc_name = request.node.name | |
1157 | write_test_header(tc_name) | |
1158 | tgen = get_topogen() | |
1159 | ||
1160 | # Don"t run this test if we have any failure. | |
1161 | if tgen.routers_have_failure(): | |
1162 | pytest.skip(tgen.errors) | |
1163 | ||
1164 | input_dict = { | |
1165 | "r4": { | |
1166 | "bgp_community_lists": [ | |
1167 | { | |
1168 | "community_type": "standard", | |
1169 | "action": "permit", | |
1170 | "name": "ANY", | |
1171 | "value": "0:-1" | |
1172 | } | |
1173 | ] | |
1174 | } | |
1175 | } | |
1176 | ||
1177 | step("Checking boundary value for community 0:-1") | |
1178 | result = create_bgp_community_lists(tgen, input_dict) | |
1179 | assert result is not True, "Test case {} : Failed \n Error: {}". \ | |
1180 | format(tc_name, result) | |
1181 | ||
1182 | step("Checking community attribute 0:65536") | |
1183 | input_dict_2 = { | |
1184 | "r4": { | |
1185 | "bgp_community_lists": [ | |
1186 | { | |
1187 | "community_type": "standard", | |
1188 | "action": "permit", | |
1189 | "name": "ANY", | |
1190 | "value": "0:65536" | |
1191 | } | |
1192 | ] | |
1193 | } | |
1194 | } | |
1195 | ||
1196 | step("Checking boundary value for community 0:65536") | |
1197 | result = create_bgp_community_lists(tgen, input_dict_2) | |
1198 | assert result is not True, "Test case {} : Failed \n Error: {}". \ | |
1199 | format(tc_name, result) | |
1200 | ||
1201 | step("Checking boundary value for community 0:4294967296") | |
1202 | input_dict_3 = { | |
1203 | "r4": { | |
1204 | "bgp_community_lists": [ | |
1205 | { | |
1206 | "community_type": "standard", | |
1207 | "action": "permit", | |
1208 | "name": "ANY", | |
1209 | "value": "0:4294967296", | |
1210 | "large": True | |
1211 | } | |
1212 | ] | |
1213 | } | |
1214 | } | |
1215 | ||
1216 | result = create_bgp_community_lists(tgen, input_dict_3) | |
1217 | assert result is not True, "Test case {} : Failed \n Error: {}". \ | |
1218 | format(tc_name, result) | |
1219 | step("Checking boundary value for community 0:-1:1") | |
1220 | ||
1221 | input_dict_4 = { | |
1222 | "r4": { | |
1223 | "bgp_community_lists": [ | |
1224 | { | |
1225 | "community_type": "standard", | |
1226 | "action": "permit", | |
1227 | "name": "ANY", | |
1228 | "value": "0:-1:1", | |
1229 | "large": True | |
1230 | } | |
1231 | ] | |
1232 | } | |
1233 | } | |
1234 | ||
1235 | result = create_bgp_community_lists(tgen, input_dict_4) | |
1236 | assert result is not True, "Test case {} : Failed \n Error: {}". \ | |
1237 | format(tc_name, result) | |
1238 | ||
1239 | ||
1240 | def test_large_community_after_clear_bgp(request): | |
1241 | """ | |
1242 | Clear BGP neighbor-ship and check if large community and community | |
1243 | attributes are getting re-populated. | |
1244 | """ | |
1245 | tc_name = request.node.name | |
1246 | write_test_header(tc_name) | |
1247 | tgen = get_topogen() | |
1248 | ||
1249 | # Don"t run this test if we have any failure. | |
1250 | if tgen.routers_have_failure(): | |
1251 | pytest.skip(tgen.errors) | |
1252 | ||
1253 | reset_config_on_routers(tgen) | |
1254 | config_router_r1(tgen, topo, tc_name) | |
1255 | ||
1256 | input_dict = { | |
1257 | "largeCommunity": LARGE_COMM["r1"], | |
1258 | "community": STANDARD_COMM["r1"] | |
1259 | } | |
1260 | ||
1261 | for adt in ADDR_TYPES: | |
1262 | result = verify_bgp_community(tgen, adt, "r2", [NETWORK[adt][0]], | |
1263 | input_dict) | |
1264 | assert result is True, "Test case {} : Failed \n Error: {}". \ | |
1265 | format(tc_name, result) | |
1266 | ||
1267 | step("Clearing BGP on r1") | |
1268 | clear_bgp_and_verify(tgen, topo, "r1") | |
1269 | ||
1270 | for adt in ADDR_TYPES: | |
1271 | result = verify_bgp_community(tgen, adt, "r2", [NETWORK[adt][0]], | |
1272 | input_dict) | |
1273 | assert result is True, "Test case {} : Failed \n Error: {}". \ | |
1274 | format(tc_name, result) | |
1275 | ||
1276 | write_test_footer(tc_name) | |
1277 | ||
1278 | ||
1279 | if __name__ == "__main__": | |
1280 | args = ["-s"] + sys.argv[1:] | |
1281 | sys.exit(pytest.main(args)) |