]> git.proxmox.com Git - mirror_frr.git/blob - tests/topotests/bgp_l3vpn_to_bgp_vrf/customize.py
bgp_l3vpn_to_bgp_vrf: required 4.11 kernel on arm processors
[mirror_frr.git] / tests / topotests / bgp_l3vpn_to_bgp_vrf / customize.py
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 +----+--+---+ +----+----+
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 | | |
73
74 """
75
76 import os
77 import re
78 import sys
79 import pytest
80 import platform
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 InitSuccess = False
97
98 class ThisTestTopo(Topo):
99 "Test topology builder"
100 def build(self, *_args, **_opts):
101 "Build function"
102 tgen = get_topogen(self)
103
104 # This function only purpose is to define allocation and relationship
105 # between routers, switches and hosts.
106 #
107 # Create P/PE routers
108 #check for mpls
109 tgen.add_router('r1')
110 if tgen.hasmpls != True:
111 logger.info('MPLS not available, tests will be skipped')
112 return
113 mach = platform.machine()
114 krel = platform.release()
115 if mach[:1] == 'a' and topotest.version_cmp(krel, '4.11') < 0:
116 logger.info('Need Kernel version 4.11 to run on arm processor')
117 return
118 for routern in range(2, 5):
119 tgen.add_router('r{}'.format(routern))
120 # Create CE routers
121 for routern in range(1, 5):
122 tgen.add_router('ce{}'.format(routern))
123
124 #CE/PE links
125 tgen.add_link(tgen.gears['ce1'], tgen.gears['r1'], 'ce1-eth0', 'r1-eth4')
126 tgen.add_link(tgen.gears['ce2'], tgen.gears['r3'], 'ce2-eth0', 'r3-eth4')
127 tgen.add_link(tgen.gears['ce3'], tgen.gears['r4'], 'ce3-eth0', 'r4-eth4')
128 tgen.add_link(tgen.gears['ce4'], tgen.gears['r4'], 'ce4-eth0', 'r4-eth5')
129
130 # Create a switch with just one router connected to it to simulate a
131 # empty network.
132 switch = {}
133 switch[0] = tgen.add_switch('sw0')
134 switch[0].add_link(tgen.gears['r1'], nodeif='r1-eth0')
135 switch[0].add_link(tgen.gears['r2'], nodeif='r2-eth0')
136
137 switch[1] = tgen.add_switch('sw1')
138 switch[1].add_link(tgen.gears['r2'], nodeif='r2-eth1')
139 switch[1].add_link(tgen.gears['r3'], nodeif='r3-eth0')
140 switch[1].add_link(tgen.gears['r4'], nodeif='r4-eth0')
141
142 switch[1] = tgen.add_switch('sw2')
143 switch[1].add_link(tgen.gears['r2'], nodeif='r2-eth2')
144 switch[1].add_link(tgen.gears['r3'], nodeif='r3-eth1')
145
146 class CustCmd():
147 def __init__(self):
148 self.resetCounts()
149
150 def doCmd(self, tgen, rtr, cmd, checkstr = None):
151 output = tgen.net[rtr].cmd(cmd).strip()
152 if len(output):
153 self.output += 1
154 if checkstr != None:
155 ret = re.search(checkstr, output)
156 if ret == None:
157 self.nomatch += 1
158 else:
159 self.match += 1
160 return ret
161 logger.info('command: {} {}'.format(rtr, cmd))
162 logger.info('output: ' + output)
163 self.none += 1
164 return None
165
166 def resetCounts(self):
167 self.match = 0
168 self.nomatch = 0
169 self.output = 0
170 self.none = 0
171
172 def getMatch(self):
173 return self.match
174
175 def getNoMatch(self):
176 return self.nomatch
177
178 def getOutput(self):
179 return self.output
180
181 def getNone(self):
182 return self.none
183
184 cc = CustCmd()
185
186 def ltemplatePreRouterStartHook():
187 krel = platform.release()
188 tgen = get_topogen()
189 logger.info('pre router-start hook, kernel=' + krel)
190 #check for mpls
191 if tgen.hasmpls != True:
192 logger.info('MPLS not available, skipping setup')
193 return
194 #check for normal init
195 if len(tgen.net) == 1:
196 logger.info('Topology not configured, skipping setup')
197 return
198 #collect/log info on iproute2
199 cc.doCmd(tgen, 'r2', 'apt-cache policy iproute2')
200 cc.doCmd(tgen, 'r2', 'yum info iproute2')
201 cc.doCmd(tgen, 'r2', 'yum info iproute')
202
203 cc.resetCounts()
204 #configure r2 mpls interfaces
205 intfs = ['lo', 'r2-eth0', 'r2-eth1', 'r2-eth2']
206 for intf in intfs:
207 cc.doCmd(tgen, 'r2', 'echo 1 > /proc/sys/net/mpls/conf/{}/input'.format(intf))
208
209 #configure cust1 VRFs & MPLS
210 rtrs = ['r1', 'r3', 'r4']
211 cmds = ['ip link add {0}-cust1 type vrf table 10',
212 'ip ru add oif {0}-cust1 table 10',
213 'ip ru add iif {0}-cust1 table 10',
214 'ip link set dev {0}-cust1 up']
215 for rtr in rtrs:
216 router = tgen.gears[rtr]
217 for cmd in cmds:
218 cc.doCmd(tgen, rtr, cmd.format(rtr))
219 cc.doCmd(tgen, rtr, 'ip link set dev {0}-eth4 master {0}-cust1'.format(rtr))
220 intfs = [rtr+'-cust1', 'lo', rtr+'-eth0', rtr+'-eth4']
221 for intf in intfs:
222 cc.doCmd(tgen, rtr, 'echo 1 > /proc/sys/net/mpls/conf/{}/input'.format(intf))
223 logger.info('setup {0} vrf {0}-cust1, {0}-eth4. enabled mpls input.'.format(rtr))
224 #configure cust2 VRFs & MPLS
225 rtrs = ['r4']
226 cmds = ['ip link add {0}-cust2 type vrf table 20',
227 'ip ru add oif {0}-cust1 table 20',
228 'ip ru add iif {0}-cust1 table 20',
229 'ip link set dev {0}-cust2 up']
230 for rtr in rtrs:
231 for cmd in cmds:
232 cc.doCmd(tgen, rtr, cmd.format(rtr))
233 cc.doCmd(tgen, rtr, 'ip link set dev {0}-eth5 master {0}-cust2'.format(rtr))
234 intfs = [rtr+'-cust2', rtr+'-eth5']
235 for intf in intfs:
236 cc.doCmd(tgen, rtr, 'echo 1 > /proc/sys/net/mpls/conf/{}/input'.format(intf))
237 logger.info('setup {0} vrf {0}-cust2, {0}-eth5. enabled mpls input.'.format(rtr))
238 global InitSuccess
239 if cc.getOutput():
240 InitSuccess = False
241 logger.info('VRF config failed ({}), tests will be skipped'.format(cc.getOutput()))
242 else:
243 InitSuccess = True
244 logger.info('VRF config successful!')
245 return;
246
247 def ltemplatePostRouterStartHook():
248 logger.info('post router-start hook')
249 return;
250
251 def versionCheck(vstr, rname='r1', compstr='<',cli=False, kernel='4.9'):
252 tgen = get_topogen()
253
254 router = tgen.gears[rname]
255
256 if tgen.hasmpls != True:
257 ret = 'MPLS not initialized'
258 return ret
259
260 if InitSuccess != True:
261 ret = 'Test not successfully initialized'
262 return ret
263
264 ret = True
265 try:
266 if router.has_version(compstr, vstr):
267 ret = False
268 logger.debug('version check failed, version {} {}'.format(compstr, vstr))
269 except:
270 ret = True
271 if ret == False:
272 ret = 'Skipping tests on old version ({}{})'.format(compstr, vstr)
273 logger.info(ret)
274 elif kernel != None:
275 krel = platform.release()
276 if topotest.version_cmp(krel, kernel) < 0:
277 ret = 'Skipping tests on old version ({} < {})'.format(krel, kernel)
278 logger.info(ret)
279 if cli:
280 logger.info('calling mininet CLI')
281 tgen.mininet_cli()
282 logger.info('exited mininet CLI')
283 return ret