]>
Commit | Line | Data |
---|---|---|
b1ab2bd2 DS |
1 | #!/usr/bin/env python |
2 | ||
3 | # | |
4 | # test_pbr_topo1.py | |
5 | # | |
6 | # Copyright (c) 2020 by | |
7 | # Cumulus Networks, Inc. | |
8 | # Donald Sharp | |
9 | # | |
10 | # Permission to use, copy, modify, and/or distribute this software | |
11 | # for any purpose with or without fee is hereby granted, provided | |
12 | # that the above copyright notice and this permission notice appear | |
13 | # in all copies. | |
14 | # | |
15 | # THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES | |
16 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
17 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR | |
18 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY | |
19 | # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, | |
20 | # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS | |
21 | # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |
22 | # OF THIS SOFTWARE. | |
23 | # | |
24 | ||
25 | """ | |
26 | test_pbr_topo1.py: Testing PBR | |
27 | ||
28 | """ | |
29 | ||
30 | import os | |
31 | import re | |
32 | import sys | |
33 | import pytest | |
34 | import json | |
36952a82 | 35 | from functools import partial |
b1ab2bd2 DS |
36 | |
37 | # Save the Current Working Directory to find configuration files. | |
38 | CWD = os.path.dirname(os.path.realpath(__file__)) | |
39 | sys.path.append(os.path.join(CWD, "../")) | |
40 | ||
41 | # pylint: disable=C0413 | |
42 | # Import topogen and topotest helpers | |
43 | from lib import topotest | |
44 | from lib.topogen import Topogen, TopoRouter, get_topogen | |
45 | from lib.topolog import logger | |
b046dc87 | 46 | from lib.common_config import shutdown_bringup_interface |
b1ab2bd2 DS |
47 | |
48 | # Required to instantiate the topology builder class. | |
49 | from mininet.topo import Topo | |
50 | ||
51 | ##################################################### | |
52 | ## | |
53 | ## Network Topology Definition | |
54 | ## | |
55 | ##################################################### | |
56 | ||
57 | ||
58 | class NetworkTopo(Topo): | |
59 | "PBR Topology 1" | |
60 | ||
61 | def build(self, **_opts): | |
62 | "Build function" | |
63 | ||
64 | tgen = get_topogen(self) | |
65 | ||
38b5ed4b | 66 | # Populate routers |
b1ab2bd2 DS |
67 | for routern in range(1, 2): |
68 | tgen.add_router("r{}".format(routern)) | |
69 | ||
38b5ed4b WC |
70 | # Populate switches |
71 | for switchn in range(1, 6): | |
72 | switch = tgen.add_switch("sw{}".format(switchn)) | |
73 | switch.add_link(tgen.gears["r1"]) | |
b1ab2bd2 DS |
74 | |
75 | ||
76 | ##################################################### | |
77 | ## | |
78 | ## Tests starting | |
79 | ## | |
80 | ##################################################### | |
81 | ||
82 | ||
83 | def setup_module(module): | |
84 | "Setup topology" | |
85 | tgen = Topogen(NetworkTopo, module.__name__) | |
86 | tgen.start_topology() | |
87 | ||
b1ab2bd2 DS |
88 | router_list = tgen.routers() |
89 | for rname, router in router_list.iteritems(): | |
11e33e00 WC |
90 | # Install vrf into the kernel and slave eth3 |
91 | router.run("ip link add vrf-chiyoda type vrf table 1000") | |
92 | router.run("ip link set dev {}-eth3 master vrf-chiyoda".format(rname)) | |
93 | router.run("ip link set vrf-chiyoda up") | |
94 | ||
b1ab2bd2 DS |
95 | router.load_config( |
96 | TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) | |
97 | ) | |
98 | router.load_config( | |
99 | TopoRouter.RD_PBRD, os.path.join(CWD, "{}/pbrd.conf".format(rname)) | |
100 | ) | |
101 | ||
102 | tgen.start_router() | |
38b5ed4b | 103 | |
b1ab2bd2 DS |
104 | |
105 | def teardown_module(_mod): | |
106 | "Teardown the pytest environment" | |
107 | tgen = get_topogen() | |
108 | ||
109 | # This function tears down the whole topology. | |
110 | tgen.stop_topology() | |
111 | ||
112 | ||
113 | def test_converge_protocols(): | |
114 | "Wait for protocol convergence" | |
115 | ||
116 | tgen = get_topogen() | |
117 | # Don't run this test if we have any failure. | |
118 | if tgen.routers_have_failure(): | |
119 | pytest.skip(tgen.errors) | |
120 | ||
121 | topotest.sleep(5, "Waiting for PBR convergence") | |
122 | ||
123 | ||
124 | def test_pbr_data(): | |
125 | "Test PBR 'show ip eigrp'" | |
126 | ||
127 | tgen = get_topogen() | |
128 | # Don't run this test if we have any failure. | |
129 | if tgen.routers_have_failure(): | |
130 | pytest.skip(tgen.errors) | |
131 | ||
132 | # Verify PBR Status | |
133 | logger.info("Verifying PBR routes") | |
134 | ||
135 | router_list = tgen.routers().values() | |
136 | for router in router_list: | |
137 | intf_file = "{}/{}/pbr-interface.json".format(CWD, router.name) | |
b1ab2bd2 | 138 | logger.info(intf_file) |
38b5ed4b | 139 | |
b1ab2bd2 DS |
140 | # Read expected result from file |
141 | expected = json.loads(open(intf_file).read()) | |
142 | ||
143 | # Actual output from router | |
36952a82 DS |
144 | test_func = partial(topotest.router_json_cmp, router, "show pbr interface json", expected) |
145 | _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) | |
b1ab2bd2 | 146 | assertmsg = '"show pbr interface" mismatches on {}'.format(router.name) |
36952a82 | 147 | assert result is None, assertmsg |
b1ab2bd2 DS |
148 | |
149 | map_file = "{}/{}/pbr-map.json".format(CWD, router.name) | |
150 | logger.info(map_file) | |
38b5ed4b | 151 | |
b1ab2bd2 DS |
152 | # Read expected result from file |
153 | expected = json.loads(open(map_file).read()) | |
154 | ||
155 | # Actual output from router | |
36952a82 DS |
156 | test_func = partial(topotest.router_json_cmp, router, "show pbr map json", expected) |
157 | _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) | |
b1ab2bd2 | 158 | assertmsg = '"show pbr map" mismatches on {}'.format(router.name) |
36952a82 | 159 | assert result is None, assertmsg |
b1ab2bd2 DS |
160 | |
161 | nexthop_file = "{}/{}/pbr-nexthop-groups.json".format(CWD, router.name) | |
38b5ed4b WC |
162 | logger.info(nexthop_file) |
163 | ||
b1ab2bd2 DS |
164 | # Read expected result from file |
165 | expected = json.loads(open(nexthop_file).read()) | |
166 | ||
167 | # Actual output from router | |
36952a82 DS |
168 | test_func = partial(topotest.router_json_cmp, router, "show pbr nexthop-groups json", expected) |
169 | _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) | |
b1ab2bd2 | 170 | assertmsg = '"show pbr nexthop-groups" mismatches on {}'.format(router.name) |
36952a82 | 171 | assert result is None, assertmsg |
38b5ed4b | 172 | |
b046dc87 WC |
173 | def test_pbr_flap(): |
174 | "Test PBR interface flapping" | |
175 | ||
176 | tgen = get_topogen() | |
177 | # Don't run this test if we have any failure. | |
178 | if tgen.routers_have_failure(): | |
179 | pytest.skip(tgen.errors) | |
180 | ||
181 | # Verify PBR Status | |
182 | logger.info("Flapping PBR Interfaces") | |
183 | ||
184 | router_list = tgen.routers().values() | |
185 | for router in router_list: | |
186 | # Flap interface to see if route-map properties are intact | |
187 | # Shutdown interface | |
11e33e00 | 188 | |
b046dc87 WC |
189 | for i in range(5): |
190 | intf = "r1-eth{}".format(i) | |
191 | ||
192 | # Down and back again | |
11e33e00 WC |
193 | shutdown_bringup_interface(tgen, router.name, intf, False) |
194 | shutdown_bringup_interface(tgen, router.name, intf, True) | |
b046dc87 WC |
195 | |
196 | intf_file = "{}/{}/pbr-interface.json".format(CWD, router.name) | |
197 | logger.info(intf_file) | |
198 | ||
199 | # Read expected result from file | |
200 | expected = json.loads(open(intf_file).read()) | |
201 | ||
202 | # Actual output from router | |
36952a82 DS |
203 | test_func = partial(topotest.router_json_cmp, router, "show pbr interface json", expected) |
204 | _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) | |
b046dc87 | 205 | assertmsg = '"show pbr interface" mismatches on {}'.format(router.name) |
36952a82 | 206 | assert result is None, assertmsg |
9b7decf2 JU |
207 | |
208 | ||
209 | def test_rule_linux_installation(): | |
210 | "Ensure that rule is installed in the kernel" | |
211 | ||
212 | tgen = get_topogen() | |
213 | # Don't run this test if we have any failure. | |
214 | if tgen.routers_have_failure(): | |
215 | pytest.skip(tgen.errors) | |
216 | ||
217 | logger.info("Checking for installed PBR rules in OS") | |
218 | ||
219 | router_list = tgen.routers().values() | |
220 | for router in router_list: | |
221 | rules_file = "{}/{}/linux-rules.json".format(CWD, router.name) | |
222 | ||
223 | actual = topotest.ip_rules(router) | |
224 | expected = json.loads(open(rules_file).read()) | |
225 | ||
226 | assertmsg = "Router {} OS rules mismatch".format(router.name) | |
b046dc87 WC |
227 | assert topotest.json_cmp(actual, expected) is None, assertmsg |
228 | ||
229 | ||
b1ab2bd2 DS |
230 | if __name__ == "__main__": |
231 | args = ["-s"] + sys.argv[1:] | |
232 | sys.exit(pytest.main(args)) |