blob: 78f3e6ad87cfb5c465546f8f66d0bc8a13ab1df2 [file] [log] [blame]
Jonghwan Hyun812c70f2018-02-16 16:33:16 -08001"""
2Copyright 2017 Open Networking Foundation ( ONF )
3
4Please refer questions to either the onos test mailing list at <onos-test@onosproject.org>,
5the System Testing Plans and Results wiki page at <https://wiki.onosproject.org/x/voMg>,
6or the System Testing Guide page at <https://wiki.onosproject.org/x/WYQg>
7
8 TestON is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 2 of the License, or
11 ( at your option ) any later version.
12
13 TestON is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with TestON. If not, see <http://www.gnu.org/licenses/>.
20"""
21
You Wang68568b12019-03-04 11:49:57 -080022import tests.USECASE.SegmentRouting.dependencies.cfgtranslator as translator
23
Jonghwan Hyun812c70f2018-02-16 16:33:16 -080024class SRDynamicConfTest:
25 def __init__( self ):
26 self.default = ''
27
28 @staticmethod
29 def runTest( main, testIndex, topology, onosNodes, description, vlan=( 0, 0, 0, 0 ) ):
30 '''
31 Tests connectivity for each test case.
32 Configuration files:
33 - (0x1, 0x2, 2x2, 2x4).json: device configuration, fed to ONOS before configuration change
34 - CASE*.json: interface configuration, fed to ONOS before configuration change
35 - CASE*0.chart: ping chart, used to check connectivity before configuration change.
36 Shared among same test scenario with different topology.
37 - CASE*0_after.chart: ping chart, used to check connectivity after configuration change.
38 Shared among same test scenario with different topology.
39 Only used when ping chart is updated.
40 '''
41 topo = dict()
42 # (number of spine switch, number of leaf switch, dual-homed, description, port number of h1)
43 topo[ '0x1' ] = ( 0, 1, False, 'single ToR', 1 )
44 topo[ '0x2' ] = ( 0, 2, True, 'dual-homed ToR', 2 )
45 topo[ '2x2' ] = ( 2, 2, False, '2x2 leaf-spine topology', 3 )
46 topo[ '2x4' ] = ( 2, 4, True, '2x4 dual-homed leaf-spine topology', 6 )
47 fanout = 4
48 switchNames = {}
49 switchNames[ '2x2' ] = [ "leaf1", "leaf2", "spine101", "spine102" ]
50
51 TAG = 'CASE%d' % testIndex
52 skipPackage = False
53 init = False
54 dualHomed = topo[ topology ][ 2 ]
55 portNum = topo[ topology ][ 4 ]
56 defaultIntf = 'bond0' if dualHomed else 'eth0'
57
58 from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as run
59 if not hasattr( main, 'apps' ):
60 init = True
61 run.initTest( main )
62 # Skip onos packaging if the clusrer size stays the same
63 if not init and onosNodes == main.Cluster.numCtrls:
64 skipPackage = True
65
66 main.case( '%s, with %s and %d ONOS instance%s' %
67 ( description, topo[ topology ][ 3 ], onosNodes, 's' if onosNodes > 1 else '' ) )
68 main.cfgName = topology
69 main.Cluster.setRunningNode( onosNodes )
70 run.installOnos( main, skipPackage=skipPackage, cliSleep=5 )
71
72 # Provide common configuration
73 # TODO: Generate json and chart dynamically, according to topologies and scenarios
You Wang68568b12019-03-04 11:49:57 -080074 if main.useBmv2:
75 # Translate configuration file from OVS-OFDPA to BMv2 driver
Jon Hall43060f62020-06-23 13:13:33 -070076 translator.bmv2ToOfdpa( main ) # Try to cleanup if switching between switch types
77 switchPrefix = main.params[ 'DEPENDENCY' ].get( 'switchPrefix', "bmv2" )
78 translator.ofdpaToBmv2( main, switchPrefix=switchPrefix )
You Wang68568b12019-03-04 11:49:57 -080079 else:
80 translator.bmv2ToOfdpa( main )
Jonghwan Hyun812c70f2018-02-16 16:33:16 -080081 run.loadJson( main )
82 run.loadChart( main )
83
84 # Provide topology-specific interface configuration
85 import json
86 try:
You Wang68568b12019-03-04 11:49:57 -080087 intfCfg = "%s%s%s.json" % ( main.configPath, main.forJson, TAG )
88 if main.useBmv2:
89 # Translate configuration file from OVS-OFDPA to BMv2 driver
Jon Hall43060f62020-06-23 13:13:33 -070090 translator.bmv2ToOfdpa( main ) # Try to cleanup if switching between switch types
91 switchPrefix = main.params[ 'DEPENDENCY' ].get( 'switchPrefix', "bmv2" )
92 translator.ofdpaToBmv2( main, switchPrefix=switchPrefix, cfgFile=intfCfg )
You Wang68568b12019-03-04 11:49:57 -080093 else:
94 translator.bmv2ToOfdpa( main, intfCfg )
95 with open( intfCfg ) as cfg:
Jonghwan Hyun812c70f2018-02-16 16:33:16 -080096 main.Cluster.active( 0 ).REST.setNetCfg( json.load( cfg ) )
97 except IOError:
98 # Load default interface configuration
You Wang68568b12019-03-04 11:49:57 -080099 defaultIntfCfg = "%s%s%s_ports.json" % ( main.configPath, main.forJson, topology )
100 if main.useBmv2:
101 # Translate configuration file from OVS-OFDPA to BMv2 driver
Jon Hall43060f62020-06-23 13:13:33 -0700102 translator.bmv2ToOfdpa( main ) # Try to cleanup if switching between switch types
103 switchPrefix = main.params[ 'DEPENDENCY' ].get( 'switchPrefix', "bmv2" )
104 translator.ofdpaToBmv2( main, switchPrefix=switchPrefix, cfgFile=defaultIntfCfg )
You Wang68568b12019-03-04 11:49:57 -0800105 else:
106 translator.bmv2ToOfdpa( main, defaultIntfCfg )
107 with open( defaultIntfCfg ) as cfg:
Jonghwan Hyun812c70f2018-02-16 16:33:16 -0800108 main.Cluster.active( 0 ).REST.setNetCfg( json.load( cfg ) )
109
110 try:
111 with open( "%s%sCASE%d.chart" % (main.configPath, main.forChart, testIndex / 10 * 10) ) as chart:
112 main.pingChart = json.load( chart )
113 except IOError:
114 # Load default chart
115 with open( "%s%sdefault.chart" % (main.configPath, main.forChart) ) as chart:
116 main.pingChart = json.load( chart )
117
118 # Set up topology
119 if hasattr( main, 'Mininet1' ):
120 # Run the test with mininet topology
121 mininet_args = ' --spine=%d --leaf=%d --fanout=%d' \
122 % ( topo[ topology ][ 0 ], topo[ topology ][ 1 ], fanout )
123 if len( vlan ) > 0 :
124 mininet_args += ' --vlan=%s' % ( ','.join( [ '%d' % vlanId for vlanId in vlan ] ) )
125 if topo[ topology ][ 0 ] > 0:
126 mininet_args += ',0,0,0,0'
127 if dualHomed:
128 mininet_args += ' --dual-homed'
You Wang68568b12019-03-04 11:49:57 -0800129 if main.useBmv2:
130 mininet_args += ' --switch bmv2'
131 main.log.info( "Using BMv2 switch" )
Jonghwan Hyun812c70f2018-02-16 16:33:16 -0800132
133 run.startMininet( main, 'trellis_fabric.py', args=mininet_args )
134 else:
135 # Run the test with physical devices
136 run.connectToPhysicalNetwork( main, switchNames[ topology ] )
137
138 # minFlowCountPerLeaf = 13 + [# of ports] * 5 + [# of hosts] * 2 + [# of vlan ids]
139 minFlowCountPerLeaf = 13 + ( fanout + topo[ topology ][ 0 ]) * 5 + fanout * 2 + len( set( vlan ) )
140 run.checkFlows( main, minFlowCount=minFlowCountPerLeaf * topo[ topology ][ 1 ], sleep=5, dumpflows=False )
141 # Check connectivity before changing interface configuration
142 run.pingAll( main, '%s_Before' % TAG, retryAttempts=2 )
143
You Wang68568b12019-03-04 11:49:57 -0800144 if main.useBmv2:
145 leaf_dpid = [ "device:bmv2:leaf%d" % ( ls + 1 ) for ls in range( topo[ topology ][ 1 ] ) ]
146 else:
147 leaf_dpid = [ "of:%016d" % ( ls + 1 ) for ls in range( topo[ topology ][ 1 ] ) ]
Jonghwan Hyun812c70f2018-02-16 16:33:16 -0800148 for dpid in leaf_dpid:
149 run.checkFlowsByDpid( main, dpid, minFlowCountPerLeaf, sleep=5 )
150
151 # Testcase-specific interface configuration change
152 if testIndex / 10 == 1:
153 # CASE11-14
154 if hasattr( main, 'Mininet1' ):
155 # Assign vlan tag 10 to host h1
156 main.Mininet1.assignVLAN( 'h1', 'h1-%s' % defaultIntf, '10' )
157 # Update port configuration of port 1
158 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
159 [ '10.0.2.254/24', ], tagged=[ 10, ] )
160 else:
161 # TODO: update physical device configuration, same for all test cases
162 pass
163 elif testIndex / 10 == 2:
164 # CASE21-24
165 if hasattr( main, 'Mininet1' ):
166 # Update port configuration of port 1
167 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
168 [ '10.0.2.254/24', ], untagged=20 )
169 elif testIndex / 10 == 3:
170 # CASE31-34
171 if hasattr( main, 'Mininet1' ):
172 # Update port configuration of port 1
173 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
174 [ '10.0.2.254/24', ], untagged=110 )
175 # Update port configuration of port 2
176 SRDynamicConfTest.updateIntfCfg( main, portNum + 1, dualHomed,
177 [ '10.0.2.254/24', ], untagged=110 )
178 elif testIndex / 10 == 4:
179 # CASE41-44
180 if hasattr( main, 'Mininet1' ):
181 # Assign vlan tag 20 to host h1
182 main.Mininet1.assignVLAN( 'h1', 'h1-%s' % defaultIntf, '20')
183 # Update port configuration of port 1
184 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
185 [ '10.0.2.254/24', ], tagged=[ 20, ] )
186 elif testIndex / 10 == 5:
187 # CASE51-54
188 if hasattr( main, 'Mininet1' ):
189 # Update port configuration of port 1
190 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
191 [ '10.0.2.254/24', ], tagged=[ 20, ], native=10 )
192 elif testIndex / 10 == 6:
193 # CASE61-64
194 if hasattr( main, 'Mininet1' ):
195 # Update port configuration of port 1
196 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
197 [ '10.0.2.254/24', ], tagged=[ 120, ], native=110 )
198 # Update port configuration of port 2
199 SRDynamicConfTest.updateIntfCfg( main, portNum + 1, dualHomed,
200 [ '10.0.2.254/24', ], tagged=[ 120, ], native=110 )
201 elif testIndex / 10 == 7:
202 # CASE71-74
203 if hasattr( main, 'Mininet1' ):
204 # Update host configuration of h1
205 main.Mininet1.removeVLAN( 'h1', 'h1-%s.10' % defaultIntf )
206 # Update port configuration of port 1
207 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
208 [ '10.0.2.254/24', ], untagged=10 )
209 elif testIndex / 10 == 8:
210 # CASE81-84
211 if hasattr( main, 'Mininet1' ):
212 # Update port configuration of port 1
213 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
214 [ '10.0.2.254/24', ], tagged=[ 20, ], native=10 )
215 elif testIndex / 10 == 9:
216 # CASE91-94
217 if hasattr( main, 'Mininet1' ):
218 # Update host configuration
219 main.Mininet1.removeVLAN( 'h1', 'h1-%s.10' % defaultIntf )
220 main.Mininet1.removeVLAN( 'h2', 'h2-%s.10' % defaultIntf )
221
222 # Update port configuration
223 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
224 [ '10.0.2.254/24', ], tagged=[ 120, ], native=110 )
225 SRDynamicConfTest.updateIntfCfg( main, portNum + 1, dualHomed,
226 [ '10.0.2.254/24', ], tagged=[ 120, ], native=110 )
227 elif testIndex / 10 == 10:
228 # CASE101-104
229 if hasattr( main, 'Mininet1' ):
230 # Update port configuration
231 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
232 [ '10.0.2.254/24', ], untagged=20 )
233 elif testIndex / 10 == 11:
234 # CASE111-114
235 if hasattr( main, 'Mininet1' ):
236 # Update port configuration
237 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
238 [ '10.0.2.254/24', ], tagged=[ 20, ] )
239 elif testIndex / 10 == 12:
240 # CASE121-124
241 if hasattr( main, 'Mininet1' ):
242 # Update port configuration
243 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
244 [ '10.0.2.254/24', ], tagged=[ 20, ], native=110 )
245 SRDynamicConfTest.updateIntfCfg( main, portNum + 1, dualHomed,
246 [ '10.0.2.254/24', ], tagged=[ 20, ], native=110 )
247 elif testIndex / 10 == 13:
248 # CASE131-134
249 if hasattr( main, 'Mininet1' ):
250 # Update port configuration
251 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
252 [ '10.0.2.254/24', ], tagged=[ 120, ], native=10 )
253 elif testIndex / 10 == 14:
254 # CASE141-144
255 if hasattr( main, 'Mininet1' ):
256 # Update port configuration
257 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
258 [ '10.0.2.254/24', ], tagged=[ 20, ] )
259 elif testIndex / 10 == 15:
260 # CASE151-154
261 if hasattr( main, 'Mininet1' ):
262 # Update port configuration
263 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
264 [ '10.0.2.254/24', ], tagged=[ 120, ] )
265 elif testIndex / 10 == 16:
266 # CASE161-164
267 if hasattr( main, 'Mininet1' ):
268 # Update port configuration
269 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
270 [ '10.0.2.254/24', ], tagged=[ 20, ], native=10 )
271 elif testIndex / 10 == 17:
272 # CASE171-174
273 if hasattr( main, 'Mininet1' ):
274 # Update port configuration
275 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
276 [ '10.0.2.254/24', ], tagged=[ 120, ] )
277 elif testIndex / 10 == 18:
278 # CASE181-184
279 if hasattr( main, 'Mininet1' ):
280 # Update port configuration
281 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
282 [ '10.0.2.254/24', ], tagged=[ 20, ], native=10 )
283 elif testIndex / 10 == 19:
284 # CASE191-194
285 if hasattr( main, 'Mininet1' ):
286 # Update port configuration
287 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
288 [ '10.0.2.254/24', ], untagged=20 )
289 elif testIndex / 10 == 20:
290 # CASE201-204
291 if hasattr( main, 'Mininet1' ):
292 # Update port configuration
293 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
294 [ '10.0.2.254/24', ], tagged=[ 20 ] )
295 elif testIndex / 10 == 21:
296 # CASE211-214
297 if hasattr( main, 'Mininet1' ):
298 # Update port configuration
299 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
300 [ '10.0.2.254/24', ], tagged=[ 20 ], native=110 )
301 elif testIndex / 10 == 22:
302 # CASE221-224
303 if hasattr( main, 'Mininet1' ):
304 # Update port configuration
305 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
306 [ '10.0.2.254/24', ], tagged=[ 120 ], native=10 )
307 elif testIndex / 10 == 23:
308 # CASE231-234
309 if hasattr( main, "Mininet1" ):
310 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
311 [ '10.0.2.254/24', ], tagged=[ 10, ] )
312 for dpid in leaf_dpid:
313 run.checkFlowsByDpid( main, dpid, minFlowCountPerLeaf, sleep=5 )
314 main.pingChart[ 'leaf1' ][ 'expect' ] = False
315 run.pingAll( main, '%s_1' % TAG, retryAttempts=2 )
316
317 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
318 [ '10.0.2.254/24', ], untagged=50 )
319 for dpid in leaf_dpid:
320 run.checkFlowsByDpid( main, dpid, minFlowCountPerLeaf, sleep=5 )
321 run.pingAll( main, '%s_2' % TAG, retryAttempts=2 )
322
323 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
324 [ '10.0.2.254/24', ], tagged=[ 20, ] )
325 for dpid in leaf_dpid:
326 run.checkFlowsByDpid( main, dpid, minFlowCountPerLeaf, sleep=5 )
327 run.pingAll( main, '%s_3' % TAG, retryAttempts=2 )
328
329 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
330 [ '10.0.2.254/24', ], tagged=[ 40, ], native=10 )
331 for dpid in leaf_dpid:
332 run.checkFlowsByDpid( main, dpid, minFlowCountPerLeaf, sleep=5 )
333 main.pingChart[ 'leaf1' ][ 'expect' ] = True
334 run.pingAll( main, '%s_4' % TAG, retryAttempts=2 )
335
336 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
337 [ '10.0.2.254/24', ], tagged=[ 20, ] )
338 for dpid in leaf_dpid:
339 run.checkFlowsByDpid( main, dpid, minFlowCountPerLeaf, sleep=5 )
340 main.pingChart[ 'leaf1' ][ 'expect' ] = False
341 run.pingAll( main, '%s_5' % TAG, retryAttempts=2 )
342
343 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
344 [ '10.0.2.254/24', ], untagged= 20 )
345 for dpid in leaf_dpid:
346 run.checkFlowsByDpid( main, dpid, minFlowCountPerLeaf, sleep=5 )
347 run.pingAll( main, '%s_6' % TAG, retryAttempts=2 )
348
349 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
350 [ '10.0.2.254/24', ], untagged= 10 )
351 for dpid in leaf_dpid:
352 run.checkFlowsByDpid( main, dpid, minFlowCountPerLeaf, sleep=5 )
353 main.pingChart[ 'leaf1' ][ 'expect' ] = True
354 elif testIndex / 10 == 24:
355 # CASE243-244
356 # Only for 2x2 and 2x4 topology, to test reachability from other leaf
357 if hasattr( main, "Mininet1" ):
358 # Update host IP and default GW
359 main.Mininet1.changeIP( 'h1', 'h1-%s' % defaultIntf, '10.0.6.1', '255.255.255.0' )
360 main.Mininet1.changeDefaultGateway( 'h1', '10.0.6.254' )
361 # Update port configuration
362 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
363 [ '10.0.6.254/24', ], untagged=60 )
364
365 # Update ping chart in case it is changed
366 try:
367 with open( "%s%sCASE%d_after.chart" % (main.configPath, main.forChart, testIndex / 10 * 10 ) ) as chart:
368 main.pingChart = json.load(chart)
369 except IOError:
370 main.log.debug( "Ping chart is not changed" )
371
372 # Check connectivity after changing interface configuration
373 run.checkFlows( main, minFlowCount=minFlowCountPerLeaf * topo[ topology ][ 1 ], sleep=5, dumpflows=False )
374 run.pingAll( main, '%s_After' % TAG, retryAttempts=2 )
375
You Wang5df1c6d2018-04-06 18:02:02 -0700376 run.cleanup( main )
Jonghwan Hyun812c70f2018-02-16 16:33:16 -0800377
378 @staticmethod
379 def updateIntfCfg( main, portNum, dualHomed, ips=[], untagged=0, tagged=[], native=0 ):
380 from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as run
You Wang68568b12019-03-04 11:49:57 -0800381 if main.useBmv2:
382 run.updateIntfCfg( main, "device:bmv2:leaf1/%d" % portNum,
Jonghwan Hyun812c70f2018-02-16 16:33:16 -0800383 ips=ips, untagged=untagged, tagged=tagged, native=native )
You Wang68568b12019-03-04 11:49:57 -0800384 else:
385 run.updateIntfCfg( main, "of:0000000000000001/%d" % portNum,
386 ips=ips, untagged=untagged, tagged=tagged, native=native )
387 if dualHomed:
388 if main.useBmv2:
389 run.updateIntfCfg( main, "device:bmv2:leaf2/%d" % portNum,
390 ips=ips, untagged=untagged, tagged=tagged, native=native )
391 else:
392 run.updateIntfCfg( main, "of:0000000000000002/%d" % portNum,
393 ips=ips, untagged=untagged, tagged=tagged, native=native )