]>
Commit | Line | Data |
---|---|---|
4ac1e79f LB |
1 | #!/usr/bin/env python |
2 | ||
3 | # | |
4 | # Part of NetDEF Topology Tests | |
5 | # | |
6 | # Copyright (c) 2017 by | |
7 | # Network Device Education Foundation, Inc. ("NetDEF") | |
8 | # | |
9 | # Permission to use, copy, modify, and/or distribute this software | |
10 | # for any purpose with or without fee is hereby granted, provided | |
11 | # that the above copyright notice and this permission notice appear | |
12 | # in all copies. | |
13 | # | |
14 | # THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES | |
15 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
16 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR | |
17 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY | |
18 | # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, | |
19 | # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS | |
20 | # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |
21 | # OF THIS SOFTWARE. | |
22 | # | |
23 | ||
24 | """ | |
25 | customize.py: Simple FRR/Quagga MPLS L3VPN test topology | |
26 | ||
27 | | | |
28 | +----+----+ | |
29 | | ce1 | | |
30 | | 99.0.0.1| CE Router | |
31 | +----+----+ | |
32 | 192.168.1. | .2 ce1-eth0 | |
33 | | .1 r1-eth4 | |
34 | +---------+ | |
35 | | r1 | | |
36 | | 1.1.1.1 | PE Router | |
37 | +----+----+ | |
38 | | .1 r1-eth0 | |
39 | | | |
40 | ~~~~~~~~~~~~~ | |
41 | ~~ sw0 ~~ | |
42 | ~~ 10.0.1.0/24 ~~ | |
43 | ~~~~~~~~~~~~~ | |
44 | |10.0.1.0/24 | |
45 | | | |
46 | | .2 r2-eth0 | |
47 | +----+----+ | |
48 | | r2 | | |
49 | | 2.2.2.2 | P router | |
50 | +--+---+--+ | |
51 | r2-eth2 .2 | | .2 r2-eth1 | |
52 | ______/ \______ | |
53 | / \ | |
54 | ~~~~~~~~~~~~~ ~~~~~~~~~~~~~ | |
55 | ~~ sw2 ~~ ~~ sw1 ~~ | |
56 | ~~ 10.0.3.0/24 ~~ ~~ 10.0.2.0/24 ~~ | |
57 | ~~~~~~~~~~~~~ ~~~~~~~~~~~~~ | |
58 | | / | | |
59 | \ _________/ | | |
60 | \ / \ | |
61 | r3-eth1 .3 | | .3 r3-eth0 | .4 r4-eth0 | |
62 | +----+--+---+ +----+----+ | |
856b9cce LB |
63 | | r3 | | r4 | r4-eth5 |
64 | | 3.3.3.3 | | 4.4.4.4 |-------+ PE Routers | |
65 | +-----------+ +---------+ | | |
66 | 192.168.1.1 |r3.eth4 192.168.1.1 | r4-eth4 |192.168.2.1 | |
67 | .2 | ceX-eth0 .2 | | .2 | |
68 | +-----+-----+ +----+-----+ +----+-----+ | |
69 | | ce2 | | ce3 | | ce4 | | |
70 | | 99.0.0.2 | | 99.0.0.3 | | 99.0.0.4 | CE Routers | |
71 | +-----+-----+ +----+-----+ +----+-----+ | |
72 | | | | | |
4ac1e79f LB |
73 | |
74 | """ | |
75 | ||
76 | import os | |
85c81f95 | 77 | import re |
4ac1e79f LB |
78 | import sys |
79 | import pytest | |
6dd81dbb | 80 | import platform |
4ac1e79f LB |
81 | |
82 | # pylint: disable=C0413 | |
83 | # Import topogen and topotest helpers | |
84 | from lib import topotest | |
85 | from lib.topogen import Topogen, TopoRouter, get_topogen | |
86 | from lib.topolog import logger | |
87 | ||
88 | # Required to instantiate the topology builder class. | |
89 | from mininet.topo import Topo | |
90 | ||
91 | import shutil | |
92 | CWD = os.path.dirname(os.path.realpath(__file__)) | |
93 | # test name based on directory | |
94 | TEST = os.path.basename(CWD) | |
95 | ||
96 | class ThisTestTopo(Topo): | |
97 | "Test topology builder" | |
98 | def build(self, *_args, **_opts): | |
99 | "Build function" | |
100 | tgen = get_topogen(self) | |
101 | ||
102 | # This function only purpose is to define allocation and relationship | |
103 | # between routers, switches and hosts. | |
104 | # | |
105 | # Create P/PE routers | |
1c507d27 | 106 | #check for mpls |
85c81f95 | 107 | tgen.add_router('r1') |
1c507d27 | 108 | if tgen.hasmpls != True: |
85c81f95 LB |
109 | logger.info('MPLS not available, tests will be skipped') |
110 | return | |
85c81f95 | 111 | for routern in range(2, 5): |
4ac1e79f LB |
112 | tgen.add_router('r{}'.format(routern)) |
113 | # Create CE routers | |
856b9cce | 114 | for routern in range(1, 5): |
4ac1e79f LB |
115 | tgen.add_router('ce{}'.format(routern)) |
116 | ||
117 | #CE/PE links | |
118 | tgen.add_link(tgen.gears['ce1'], tgen.gears['r1'], 'ce1-eth0', 'r1-eth4') | |
119 | tgen.add_link(tgen.gears['ce2'], tgen.gears['r3'], 'ce2-eth0', 'r3-eth4') | |
120 | tgen.add_link(tgen.gears['ce3'], tgen.gears['r4'], 'ce3-eth0', 'r4-eth4') | |
856b9cce | 121 | tgen.add_link(tgen.gears['ce4'], tgen.gears['r4'], 'ce4-eth0', 'r4-eth5') |
4ac1e79f LB |
122 | |
123 | # Create a switch with just one router connected to it to simulate a | |
124 | # empty network. | |
125 | switch = {} | |
126 | switch[0] = tgen.add_switch('sw0') | |
127 | switch[0].add_link(tgen.gears['r1'], nodeif='r1-eth0') | |
128 | switch[0].add_link(tgen.gears['r2'], nodeif='r2-eth0') | |
129 | ||
130 | switch[1] = tgen.add_switch('sw1') | |
131 | switch[1].add_link(tgen.gears['r2'], nodeif='r2-eth1') | |
132 | switch[1].add_link(tgen.gears['r3'], nodeif='r3-eth0') | |
133 | switch[1].add_link(tgen.gears['r4'], nodeif='r4-eth0') | |
134 | ||
135 | switch[1] = tgen.add_switch('sw2') | |
136 | switch[1].add_link(tgen.gears['r2'], nodeif='r2-eth2') | |
137 | switch[1].add_link(tgen.gears['r3'], nodeif='r3-eth1') | |
138 | ||
85c81f95 | 139 | def doCmd(tgen, rtr, cmd, checkstr = None): |
4ac1e79f LB |
140 | output = tgen.net[rtr].cmd(cmd).strip() |
141 | if len(output): | |
85c81f95 LB |
142 | if checkstr != None: |
143 | return re.search(checkstr, output) | |
4ac1e79f | 144 | logger.info('command output: ' + output) |
85c81f95 | 145 | return None |
4ac1e79f | 146 | |
c0ace6d8 | 147 | def ltemplatePreRouterStartHook(): |
6dd81dbb | 148 | krel = platform.release() |
4ac1e79f | 149 | tgen = get_topogen() |
6dd81dbb | 150 | logger.info('pre router-start hook, kernel=' + krel) |
85c81f95 | 151 | #check for mpls |
1c507d27 | 152 | if tgen.hasmpls != True: |
85c81f95 LB |
153 | logger.info('MPLS not available, skipping setup') |
154 | return | |
4ac1e79f LB |
155 | #configure r2 mpls interfaces |
156 | intfs = ['lo', 'r2-eth0', 'r2-eth1', 'r2-eth2'] | |
157 | for intf in intfs: | |
158 | doCmd(tgen, 'r2', 'echo 1 > /proc/sys/net/mpls/conf/{}/input'.format(intf)) | |
856b9cce | 159 | #configure cust1 VRFs & MPLS |
4ac1e79f | 160 | rtrs = ['r1', 'r3', 'r4'] |
c0ace6d8 LB |
161 | cmds = ['ip link add cust1 type vrf table 10', |
162 | 'ip ru add oif cust1 table 10', | |
163 | 'ip ru add iif cust1 table 10', | |
164 | 'ip link set dev cust1 up'] | |
4ac1e79f | 165 | for rtr in rtrs: |
85c81f95 | 166 | router = tgen.gears[rtr] |
4ac1e79f LB |
167 | for cmd in cmds: |
168 | doCmd(tgen, rtr, cmd) | |
c0ace6d8 | 169 | doCmd(tgen, rtr, 'ip link set dev {}-eth4 master cust1'.format(rtr)) |
856b9cce | 170 | intfs = ['cust1', 'lo', rtr+'-eth0', rtr+'-eth4'] |
4ac1e79f LB |
171 | for intf in intfs: |
172 | doCmd(tgen, rtr, 'echo 1 > /proc/sys/net/mpls/conf/{}/input'.format(intf)) | |
c0ace6d8 | 173 | logger.info('setup {0} vrf cust1, {0}-eth4. enabled mpls input.'.format(rtr)) |
856b9cce LB |
174 | #configure cust2 VRFs & MPLS |
175 | rtrs = ['r4'] | |
176 | cmds = ['ip link add cust2 type vrf table 20', | |
177 | 'ip ru add oif cust1 table 20', | |
178 | 'ip ru add iif cust1 table 20', | |
179 | 'ip link set dev cust2 up'] | |
180 | for rtr in rtrs: | |
181 | for cmd in cmds: | |
182 | doCmd(tgen, rtr, cmd) | |
183 | doCmd(tgen, rtr, 'ip link set dev {}-eth5 master cust2'.format(rtr)) | |
184 | intfs = ['cust2', rtr+'-eth5'] | |
185 | for intf in intfs: | |
186 | doCmd(tgen, rtr, 'echo 1 > /proc/sys/net/mpls/conf/{}/input'.format(intf)) | |
187 | logger.info('setup {0} vrf cust2, {0}-eth5. enabled mpls input.'.format(rtr)) | |
4ac1e79f LB |
188 | return; |
189 | ||
c0ace6d8 | 190 | def ltemplatePostRouterStartHook(): |
4ac1e79f LB |
191 | logger.info('post router-start hook') |
192 | return; | |
193 | ||
6dd81dbb | 194 | def versionCheck(vstr, rname='r1', compstr='<',cli=False, kernel='4.9'): |
4ac1e79f LB |
195 | tgen = get_topogen() |
196 | ||
197 | router = tgen.gears[rname] | |
2015a497 | 198 | |
1c507d27 | 199 | if tgen.hasmpls != True: |
85c81f95 | 200 | ret = 'MPLS not initialized' |
2015a497 LB |
201 | return ret |
202 | ||
4ac1e79f LB |
203 | ret = True |
204 | try: | |
205 | if router.has_version(compstr, vstr): | |
206 | ret = False | |
207 | logger.debug('version check failed, version {} {}'.format(compstr, vstr)) | |
208 | except: | |
209 | ret = True | |
210 | if ret == False: | |
6dd81dbb | 211 | ret = 'Skipping tests on old version ({}{})'.format(compstr, vstr) |
4ac1e79f | 212 | logger.info(ret) |
6dd81dbb LB |
213 | elif kernel != None: |
214 | krel = platform.release() | |
215 | if topotest.version_cmp(krel, kernel) < 0: | |
216 | ret = 'Skipping tests on old version ({} < {})'.format(krel, kernel) | |
217 | logger.info(ret) | |
4ac1e79f LB |
218 | if cli: |
219 | logger.info('calling mininet CLI') | |
220 | tgen.mininet_cli() | |
221 | logger.info('exited mininet CLI') | |
222 | return ret |