blob: a959e7143ae8f6176dcb563519e562755440375d [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 '''
Jonghwan Hyun812c70f2018-02-16 16:33:16 -080041 try:
Jon Hall9b0de1f2020-08-24 15:38:04 -070042 topo = dict()
43 # (number of spine switch, number of leaf switch, dual-homed, description, port number of h1)
44 topo[ '0x1' ] = ( 0, 1, False, 'single ToR', 1 )
45 topo[ '0x2' ] = ( 0, 2, True, 'dual-homed ToR', 2 )
46 topo[ '2x2' ] = ( 2, 2, False, '2x2 leaf-spine topology', 3 )
47 topo[ '2x4' ] = ( 2, 4, True, '2x4 dual-homed leaf-spine topology', 6 )
48 fanout = 4
49 switchNames = {}
50 switchNames[ '2x2' ] = [ "leaf1", "leaf2", "spine101", "spine102" ]
51
52 TAG = 'CASE%d' % testIndex
53 skipPackage = False
54 init = False
55 dualHomed = topo[ topology ][ 2 ]
56 portNum = topo[ topology ][ 4 ]
57 defaultIntf = 'bond0' if dualHomed else 'eth0'
58
59 from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as run
60 if not hasattr( main, 'apps' ):
61 init = True
62 run.initTest( main )
63 # Skip onos packaging if the clusrer size stays the same
64 if not init and onosNodes == main.Cluster.numCtrls:
65 skipPackage = True
66
67 main.case( '%s, with %s and %d ONOS instance%s' %
68 ( description, topo[ topology ][ 3 ], onosNodes, 's' if onosNodes > 1 else '' ) )
69 main.cfgName = topology
70 main.Cluster.setRunningNode( onosNodes )
71 run.installOnos( main, skipPackage=skipPackage, cliSleep=5 )
72
73 # Provide common configuration
74 # TODO: Generate json and chart dynamically, according to topologies and scenarios
You Wang68568b12019-03-04 11:49:57 -080075 if main.useBmv2:
76 # Translate configuration file from OVS-OFDPA to BMv2 driver
Jon Hall9b0de1f2020-08-24 15:38:04 -070077 translator.bmv2ToOfdpa( main ) # Try to cleanup if switching between switch types
Jon Hall43060f62020-06-23 13:13:33 -070078 switchPrefix = main.params[ 'DEPENDENCY' ].get( 'switchPrefix', "bmv2" )
Jon Hall9b0de1f2020-08-24 15:38:04 -070079 translator.ofdpaToBmv2( main, switchPrefix=switchPrefix )
You Wang68568b12019-03-04 11:49:57 -080080 else:
Jon Hall9b0de1f2020-08-24 15:38:04 -070081 translator.bmv2ToOfdpa( main )
82 run.loadJson( main )
83 run.loadChart( main )
84
85 # Provide topology-specific interface configuration
86 import json
87 try:
88 intfCfg = "%s%s%s.json" % ( main.configPath, main.forJson, TAG )
89 if main.useBmv2:
90 # Translate configuration file from OVS-OFDPA to BMv2 driver
91 translator.bmv2ToOfdpa( main ) # Try to cleanup if switching between switch types
92 switchPrefix = main.params[ 'DEPENDENCY' ].get( 'switchPrefix', "bmv2" )
93 translator.ofdpaToBmv2( main, switchPrefix=switchPrefix, cfgFile=intfCfg )
94 else:
95 translator.bmv2ToOfdpa( main, intfCfg )
96 with open( intfCfg ) as cfg:
97 main.Cluster.active( 0 ).REST.setNetCfg( json.load( cfg ) )
98 except IOError:
99 # Load default interface configuration
100 defaultIntfCfg = "%s%s%s_ports.json" % ( main.configPath, main.forJson, topology )
101 if main.useBmv2:
102 # Translate configuration file from OVS-OFDPA to BMv2 driver
103 translator.bmv2ToOfdpa( main ) # Try to cleanup if switching between switch types
104 switchPrefix = main.params[ 'DEPENDENCY' ].get( 'switchPrefix', "bmv2" )
105 translator.ofdpaToBmv2( main, switchPrefix=switchPrefix, cfgFile=defaultIntfCfg )
106 else:
107 translator.bmv2ToOfdpa( main, defaultIntfCfg )
108 with open( defaultIntfCfg ) as cfg:
109 main.Cluster.active( 0 ).REST.setNetCfg( json.load( cfg ) )
110
111 try:
112 with open( "%s%sCASE%d.chart" % (main.configPath, main.forChart, testIndex / 10 * 10) ) as chart:
113 main.pingChart = json.load( chart )
114 except IOError:
115 # Load default chart
116 with open( "%s%sdefault.chart" % (main.configPath, main.forChart) ) as chart:
117 main.pingChart = json.load( chart )
118
119 # Set up topology
120 if hasattr( main, 'Mininet1' ):
121 # Run the test with mininet topology
122 mininet_args = ' --spine=%d --leaf=%d --fanout=%d' \
123 % ( topo[ topology ][ 0 ], topo[ topology ][ 1 ], fanout )
124 if len( vlan ) > 0 :
125 mininet_args += ' --vlan=%s' % ( ','.join( [ '%d' % vlanId for vlanId in vlan ] ) )
126 if topo[ topology ][ 0 ] > 0:
127 mininet_args += ',0,0,0,0'
128 if dualHomed:
129 mininet_args += ' --dual-homed'
130 if main.useBmv2:
131 mininet_args += ' --switch bmv2'
132 main.log.info( "Using BMv2 switch" )
133
134 run.startMininet( main, 'trellis_fabric.py', args=mininet_args )
135 else:
136 # Run the test with physical devices
137 run.connectToPhysicalNetwork( main, switchNames[ topology ] )
138
139 # minFlowCountPerLeaf = 13 + [# of ports] * 5 + [# of hosts] * 2 + [# of vlan ids]
140 minFlowCountPerLeaf = 13 + ( fanout + topo[ topology ][ 0 ]) * 5 + fanout * 2 + len( set( vlan ) )
141 run.checkFlows( main, minFlowCount=minFlowCountPerLeaf * topo[ topology ][ 1 ], sleep=5, dumpflows=False )
142 # Check connectivity before changing interface configuration
143 run.pingAll( main, '%s_Before' % TAG, retryAttempts=2 )
144
You Wang68568b12019-03-04 11:49:57 -0800145 if main.useBmv2:
Jon Hall9b0de1f2020-08-24 15:38:04 -0700146 leaf_dpid = [ "device:bmv2:leaf%d" % ( ls + 1 ) for ls in range( topo[ topology ][ 1 ] ) ]
You Wang68568b12019-03-04 11:49:57 -0800147 else:
Jon Hall9b0de1f2020-08-24 15:38:04 -0700148 leaf_dpid = [ "of:%016d" % ( ls + 1 ) for ls in range( topo[ topology ][ 1 ] ) ]
149 for dpid in leaf_dpid:
150 run.checkFlowsByDpid( main, dpid, minFlowCountPerLeaf, sleep=5 )
Jonghwan Hyun812c70f2018-02-16 16:33:16 -0800151
Jon Hall9b0de1f2020-08-24 15:38:04 -0700152 # Testcase-specific interface configuration change
153 if testIndex / 10 == 1:
154 # CASE11-14
155 if hasattr( main, 'Mininet1' ):
156 # Assign vlan tag 10 to host h1
157 main.Mininet1.assignVLAN( 'h1', 'h1-%s' % defaultIntf, '10' )
158 # Update port configuration of port 1
159 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
160 [ '10.0.2.254/24', ], tagged=[ 10, ] )
161 else:
162 # TODO: update physical device configuration, same for all test cases
163 pass
164 elif testIndex / 10 == 2:
165 # CASE21-24
166 if hasattr( main, 'Mininet1' ):
167 # Update port configuration of port 1
168 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
169 [ '10.0.2.254/24', ], untagged=20 )
170 elif testIndex / 10 == 3:
171 # CASE31-34
172 if hasattr( main, 'Mininet1' ):
173 # Update port configuration of port 1
174 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
175 [ '10.0.2.254/24', ], untagged=110 )
176 # Update port configuration of port 2
177 SRDynamicConfTest.updateIntfCfg( main, portNum + 1, dualHomed,
178 [ '10.0.2.254/24', ], untagged=110 )
179 elif testIndex / 10 == 4:
180 # CASE41-44
181 if hasattr( main, 'Mininet1' ):
182 # Assign vlan tag 20 to host h1
183 main.Mininet1.assignVLAN( 'h1', 'h1-%s' % defaultIntf, '20')
184 # Update port configuration of port 1
185 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
186 [ '10.0.2.254/24', ], tagged=[ 20, ] )
187 elif testIndex / 10 == 5:
188 # CASE51-54
189 if hasattr( main, 'Mininet1' ):
190 # Update port configuration of port 1
191 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
192 [ '10.0.2.254/24', ], tagged=[ 20, ], native=10 )
193 elif testIndex / 10 == 6:
194 # CASE61-64
195 if hasattr( main, 'Mininet1' ):
196 # Update port configuration of port 1
197 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
198 [ '10.0.2.254/24', ], tagged=[ 120, ], native=110 )
199 # Update port configuration of port 2
200 SRDynamicConfTest.updateIntfCfg( main, portNum + 1, dualHomed,
201 [ '10.0.2.254/24', ], tagged=[ 120, ], native=110 )
202 elif testIndex / 10 == 7:
203 # CASE71-74
204 if hasattr( main, 'Mininet1' ):
205 # Update host configuration of h1
206 main.Mininet1.removeVLAN( 'h1', 'h1-%s.10' % defaultIntf )
207 # Update port configuration of port 1
208 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
209 [ '10.0.2.254/24', ], untagged=10 )
210 elif testIndex / 10 == 8:
211 # CASE81-84
212 if hasattr( main, 'Mininet1' ):
213 # Update port configuration of port 1
214 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
215 [ '10.0.2.254/24', ], tagged=[ 20, ], native=10 )
216 elif testIndex / 10 == 9:
217 # CASE91-94
218 if hasattr( main, 'Mininet1' ):
219 # Update host configuration
220 main.Mininet1.removeVLAN( 'h1', 'h1-%s.10' % defaultIntf )
221 main.Mininet1.removeVLAN( 'h2', 'h2-%s.10' % defaultIntf )
Jonghwan Hyun812c70f2018-02-16 16:33:16 -0800222
Jon Hall9b0de1f2020-08-24 15:38:04 -0700223 # Update port configuration
224 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
225 [ '10.0.2.254/24', ], tagged=[ 120, ], native=110 )
226 SRDynamicConfTest.updateIntfCfg( main, portNum + 1, dualHomed,
227 [ '10.0.2.254/24', ], tagged=[ 120, ], native=110 )
228 elif testIndex / 10 == 10:
229 # CASE101-104
230 if hasattr( main, 'Mininet1' ):
231 # Update port configuration
232 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
233 [ '10.0.2.254/24', ], untagged=20 )
234 elif testIndex / 10 == 11:
235 # CASE111-114
236 if hasattr( main, 'Mininet1' ):
237 # Update port configuration
238 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
239 [ '10.0.2.254/24', ], tagged=[ 20, ] )
240 elif testIndex / 10 == 12:
241 # CASE121-124
242 if hasattr( main, 'Mininet1' ):
243 # Update port configuration
244 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
245 [ '10.0.2.254/24', ], tagged=[ 20, ], native=110 )
246 SRDynamicConfTest.updateIntfCfg( main, portNum + 1, dualHomed,
247 [ '10.0.2.254/24', ], tagged=[ 20, ], native=110 )
248 elif testIndex / 10 == 13:
249 # CASE131-134
250 if hasattr( main, 'Mininet1' ):
251 # Update port configuration
252 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
253 [ '10.0.2.254/24', ], tagged=[ 120, ], native=10 )
254 elif testIndex / 10 == 14:
255 # CASE141-144
256 if hasattr( main, 'Mininet1' ):
257 # Update port configuration
258 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
259 [ '10.0.2.254/24', ], tagged=[ 20, ] )
260 elif testIndex / 10 == 15:
261 # CASE151-154
262 if hasattr( main, 'Mininet1' ):
263 # Update port configuration
264 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
265 [ '10.0.2.254/24', ], tagged=[ 120, ] )
266 elif testIndex / 10 == 16:
267 # CASE161-164
268 if hasattr( main, 'Mininet1' ):
269 # Update port configuration
270 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
271 [ '10.0.2.254/24', ], tagged=[ 20, ], native=10 )
272 elif testIndex / 10 == 17:
273 # CASE171-174
274 if hasattr( main, 'Mininet1' ):
275 # Update port configuration
276 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
277 [ '10.0.2.254/24', ], tagged=[ 120, ] )
278 elif testIndex / 10 == 18:
279 # CASE181-184
280 if hasattr( main, 'Mininet1' ):
281 # Update port configuration
282 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
283 [ '10.0.2.254/24', ], tagged=[ 20, ], native=10 )
284 elif testIndex / 10 == 19:
285 # CASE191-194
286 if hasattr( main, 'Mininet1' ):
287 # Update port configuration
288 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
289 [ '10.0.2.254/24', ], untagged=20 )
290 elif testIndex / 10 == 20:
291 # CASE201-204
292 if hasattr( main, 'Mininet1' ):
293 # Update port configuration
294 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
295 [ '10.0.2.254/24', ], tagged=[ 20 ] )
296 elif testIndex / 10 == 21:
297 # CASE211-214
298 if hasattr( main, 'Mininet1' ):
299 # Update port configuration
300 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
301 [ '10.0.2.254/24', ], tagged=[ 20 ], native=110 )
302 elif testIndex / 10 == 22:
303 # CASE221-224
304 if hasattr( main, 'Mininet1' ):
305 # Update port configuration
306 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
307 [ '10.0.2.254/24', ], tagged=[ 120 ], native=10 )
308 elif testIndex / 10 == 23:
309 # CASE231-234
310 if hasattr( main, "Mininet1" ):
311 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
312 [ '10.0.2.254/24', ], tagged=[ 10, ] )
313 for dpid in leaf_dpid:
314 run.checkFlowsByDpid( main, dpid, minFlowCountPerLeaf, sleep=5 )
315 main.pingChart[ 'leaf1' ][ 'expect' ] = False
316 run.pingAll( main, '%s_1' % TAG, retryAttempts=2 )
Jonghwan Hyun812c70f2018-02-16 16:33:16 -0800317
Jon Hall9b0de1f2020-08-24 15:38:04 -0700318 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
319 [ '10.0.2.254/24', ], untagged=50 )
320 for dpid in leaf_dpid:
321 run.checkFlowsByDpid( main, dpid, minFlowCountPerLeaf, sleep=5 )
322 run.pingAll( main, '%s_2' % TAG, retryAttempts=2 )
Jonghwan Hyun812c70f2018-02-16 16:33:16 -0800323
Jon Hall9b0de1f2020-08-24 15:38:04 -0700324 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
325 [ '10.0.2.254/24', ], tagged=[ 20, ] )
326 for dpid in leaf_dpid:
327 run.checkFlowsByDpid( main, dpid, minFlowCountPerLeaf, sleep=5 )
328 run.pingAll( main, '%s_3' % TAG, retryAttempts=2 )
Jonghwan Hyun812c70f2018-02-16 16:33:16 -0800329
Jon Hall9b0de1f2020-08-24 15:38:04 -0700330 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
331 [ '10.0.2.254/24', ], tagged=[ 40, ], native=10 )
332 for dpid in leaf_dpid:
333 run.checkFlowsByDpid( main, dpid, minFlowCountPerLeaf, sleep=5 )
334 main.pingChart[ 'leaf1' ][ 'expect' ] = True
335 run.pingAll( main, '%s_4' % TAG, retryAttempts=2 )
Jonghwan Hyun812c70f2018-02-16 16:33:16 -0800336
Jon Hall9b0de1f2020-08-24 15:38:04 -0700337 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
338 [ '10.0.2.254/24', ], tagged=[ 20, ] )
339 for dpid in leaf_dpid:
340 run.checkFlowsByDpid( main, dpid, minFlowCountPerLeaf, sleep=5 )
341 main.pingChart[ 'leaf1' ][ 'expect' ] = False
342 run.pingAll( main, '%s_5' % TAG, retryAttempts=2 )
Jonghwan Hyun812c70f2018-02-16 16:33:16 -0800343
Jon Hall9b0de1f2020-08-24 15:38:04 -0700344 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
345 [ '10.0.2.254/24', ], untagged= 20 )
346 for dpid in leaf_dpid:
347 run.checkFlowsByDpid( main, dpid, minFlowCountPerLeaf, sleep=5 )
348 run.pingAll( main, '%s_6' % TAG, retryAttempts=2 )
Jonghwan Hyun812c70f2018-02-16 16:33:16 -0800349
Jon Hall9b0de1f2020-08-24 15:38:04 -0700350 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
351 [ '10.0.2.254/24', ], untagged= 10 )
352 for dpid in leaf_dpid:
353 run.checkFlowsByDpid( main, dpid, minFlowCountPerLeaf, sleep=5 )
354 main.pingChart[ 'leaf1' ][ 'expect' ] = True
355 elif testIndex / 10 == 24:
356 # CASE243-244
357 # Only for 2x2 and 2x4 topology, to test reachability from other leaf
358 if hasattr( main, "Mininet1" ):
359 # Update host IP and default GW
360 main.Mininet1.changeIP( 'h1', 'h1-%s' % defaultIntf, '10.0.6.1', '255.255.255.0' )
361 main.Mininet1.changeDefaultGateway( 'h1', '10.0.6.254' )
362 # Update port configuration
363 SRDynamicConfTest.updateIntfCfg( main, portNum, dualHomed,
364 [ '10.0.6.254/24', ], untagged=60 )
Jonghwan Hyun812c70f2018-02-16 16:33:16 -0800365
Jon Hall9b0de1f2020-08-24 15:38:04 -0700366 # Update ping chart in case it is changed
367 try:
368 with open( "%s%sCASE%d_after.chart" % (main.configPath, main.forChart, testIndex / 10 * 10 ) ) as chart:
369 main.pingChart = json.load(chart)
370 except IOError:
371 main.log.debug( "Ping chart is not changed" )
Jonghwan Hyun812c70f2018-02-16 16:33:16 -0800372
Jon Hall9b0de1f2020-08-24 15:38:04 -0700373 # Check connectivity after changing interface configuration
374 run.checkFlows( main, minFlowCount=minFlowCountPerLeaf * topo[ topology ][ 1 ], sleep=5, dumpflows=False )
375 run.pingAll( main, '%s_After' % TAG, retryAttempts=2 )
Jonghwan Hyun812c70f2018-02-16 16:33:16 -0800376
Jon Hall9b0de1f2020-08-24 15:38:04 -0700377 run.cleanup( main )
378 except Exception as e:
379 main.log.exception( "Error in runTest" )
380 main.skipCase( result="FAIL", msg=e )
Jonghwan Hyun812c70f2018-02-16 16:33:16 -0800381
382 @staticmethod
383 def updateIntfCfg( main, portNum, dualHomed, ips=[], untagged=0, tagged=[], native=0 ):
384 from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as run
You Wang68568b12019-03-04 11:49:57 -0800385 if main.useBmv2:
386 run.updateIntfCfg( main, "device:bmv2:leaf1/%d" % portNum,
Jonghwan Hyun812c70f2018-02-16 16:33:16 -0800387 ips=ips, untagged=untagged, tagged=tagged, native=native )
You Wang68568b12019-03-04 11:49:57 -0800388 else:
389 run.updateIntfCfg( main, "of:0000000000000001/%d" % portNum,
390 ips=ips, untagged=untagged, tagged=tagged, native=native )
391 if dualHomed:
392 if main.useBmv2:
393 run.updateIntfCfg( main, "device:bmv2:leaf2/%d" % portNum,
394 ips=ips, untagged=untagged, tagged=tagged, native=native )
395 else:
396 run.updateIntfCfg( main, "of:0000000000000002/%d" % portNum,
397 ips=ips, untagged=untagged, tagged=tagged, native=native )