blob: ccf3bafba101d6734cd2ba7e74ca892e1f5cf7f2 [file] [log] [blame]
adminbae64d82013-08-01 10:50:15 -07001#!/usr/bin/env python
2'''
3Created on 26-Oct-2012
4
5@author: Anil Kumar (anilkumar.s@paxterrasolutions.com)
6
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
22MininetCliDriver is the basic driver which will handle the Mininet functions
23'''
admin2a9548d2014-06-17 14:08:07 -070024import traceback
adminbae64d82013-08-01 10:50:15 -070025import pexpect
26import struct
27import fcntl
28import os
29import signal
30import re
31import sys
32import core.teston
33sys.path.append("../")
Jon Hall1ccf82c2014-10-15 14:55:16 -040034from math import pow
adminbae64d82013-08-01 10:50:15 -070035from drivers.common.cli.emulatordriver import Emulator
36from drivers.common.clidriver import CLI
37
38class MininetCliDriver(Emulator):
39 '''
Jon Hall41f40e82014-04-08 16:43:17 -070040 MininetCliDriver is the basic driver which will handle the Mininet functions
adminbae64d82013-08-01 10:50:15 -070041 '''
42 def __init__(self):
43 super(Emulator, self).__init__()
44 self.handle = self
45 self.wrapped = sys.modules[__name__]
46 self.flag = 0
47
48 def connect(self, **connectargs):
Jon Hall41f40e82014-04-08 16:43:17 -070049 '''
50 Here the main is the TestON instance after creating all the log handles.
51 '''
adminbae64d82013-08-01 10:50:15 -070052 for key in connectargs:
53 vars(self)[key] = connectargs[key]
54
55 self.name = self.options['name']
56 self.handle = super(MininetCliDriver, self).connect(user_name = self.user_name, ip_address = self.ip_address,port = None, pwd = self.pwd)
57
58 self.ssh_handle = self.handle
59
adminbae64d82013-08-01 10:50:15 -070060 if self.handle :
Jon Hallf2942ce2014-04-10 16:00:16 -070061 main.log.info(self.name+": Clearing any residual state or processes")
adminbae64d82013-08-01 10:50:15 -070062 self.handle.sendline("sudo mn -c")
adminf939f8b2014-04-03 17:22:56 -070063 i=self.handle.expect(['password\sfor\s','Cleanup\scomplete',pexpect.EOF,pexpect.TIMEOUT],120)
adminbae64d82013-08-01 10:50:15 -070064 if i==0:
Jon Hallf2942ce2014-04-10 16:00:16 -070065 main.log.info(self.name+": Sending sudo password")
adminf939f8b2014-04-03 17:22:56 -070066 self.handle.sendline(self.pwd)
67 i=self.handle.expect(['%s:'%(self.user),'\$',pexpect.EOF,pexpect.TIMEOUT],120)
adminbae64d82013-08-01 10:50:15 -070068 if i==1:
Jon Hallf2942ce2014-04-10 16:00:16 -070069 main.log.info(self.name+": Clean")
adminbae64d82013-08-01 10:50:15 -070070 elif i==2:
Jon Hallf2942ce2014-04-10 16:00:16 -070071 main.log.error(self.name+": Connection terminated")
adminbae64d82013-08-01 10:50:15 -070072 elif i==3: #timeout
Jon Hallf2942ce2014-04-10 16:00:16 -070073 main.log.error(self.name+": Something while cleaning MN took too long... " )
adminbae64d82013-08-01 10:50:15 -070074
Jon Hallf2942ce2014-04-10 16:00:16 -070075 main.log.info(self.name+": building fresh mininet")
adminbeea0032014-01-23 14:54:13 -080076 #### for reactive/PARP enabled tests
shahshreyaf4d4d0c2014-10-10 12:11:10 -070077 cmdString = "sudo mn " + self.options['arg1'] + " " + self.options['arg2'] + " --mac --controller " + self.options['controller'] + " " + self.options['arg3']
Jon Hall1ccf82c2014-10-15 14:55:16 -040078
79 argList = self.options['arg1'].split(",")
80 global topoArgList
81 topoArgList = argList[0].split(" ")
82 argList = map(int, argList[1:])
83 topoArgList = topoArgList[1:] + argList
84
85 #### for proactive flow with static ARP entries
shahshreyaf4d4d0c2014-10-10 12:11:10 -070086 #cmdString = "sudo mn " + self.options['arg1'] + " " + self.options['arg2'] + " --mac --arp --controller " + self.options['controller'] + " " + self.options['arg3']
adminbae64d82013-08-01 10:50:15 -070087 self.handle.sendline(cmdString)
Jon Hall333fa8c2014-04-11 11:24:58 -070088 self.handle.expect(["sudo mn",pexpect.EOF,pexpect.TIMEOUT])
adminbae64d82013-08-01 10:50:15 -070089 while 1:
90 i=self.handle.expect(['mininet>','\*\*\*','Exception',pexpect.EOF,pexpect.TIMEOUT],300)
91 if i==0:
Jon Hallf2942ce2014-04-10 16:00:16 -070092 main.log.info(self.name+": mininet built")
adminbae64d82013-08-01 10:50:15 -070093 return main.TRUE
94 if i==1:
Jon Hall333fa8c2014-04-11 11:24:58 -070095 self.handle.expect(["\n",pexpect.EOF,pexpect.TIMEOUT])
adminbae64d82013-08-01 10:50:15 -070096 main.log.info(self.handle.before)
97 elif i==2:
Jon Hallf2942ce2014-04-10 16:00:16 -070098 main.log.error(self.name+": Launching mininet failed...")
adminbae64d82013-08-01 10:50:15 -070099 return main.FALSE
100 elif i==3:
Jon Hallf2942ce2014-04-10 16:00:16 -0700101 main.log.error(self.name+": Connection timeout")
adminbae64d82013-08-01 10:50:15 -0700102 return main.FALSE
103 elif i==4: #timeout
Jon Hallf2942ce2014-04-10 16:00:16 -0700104 main.log.error(self.name+": Something took too long... " )
adminbae64d82013-08-01 10:50:15 -0700105 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700106 #if utilities.assert_matches(expect=patterns,actual=resultCommand,onpass="Network is being launched",onfail="Network launching is being failed "):
107 return main.TRUE
Jon Hallf2942ce2014-04-10 16:00:16 -0700108 else:#if no handle
109 main.log.error(self.name+": Connection failed to the host "+self.user_name+"@"+self.ip_address)
110 main.log.error(self.name+": Failed to connect to the Mininet")
adminbae64d82013-08-01 10:50:15 -0700111 return main.FALSE
Jon Hall1ccf82c2014-10-15 14:55:16 -0400112
113 def num_switches_n_links(self,topoType,depth,fanout):
114 if topoType == 'tree':
115 if fanout is None: #In tree topology, if fanout arg is not given, by default it is 2
116 fanout = 2
117 k = 0
118 sum = 0
119 while(k <= depth-1):
120 sum = sum + pow(fanout,k)
121 k = k+1
122 num_switches = sum
123 while(k <= depth-2):
124 '''depth-2 gives you only core links and not considering edge links as seen by ONOS
125 If all the links including edge links are required, do depth-1
126 '''
127 sum = sum + pow(fanout,k)
128 k = k+1
129 num_links = sum * fanout
130 #print "num_switches for %s(%d,%d) = %d and links=%d" %(topoType,depth,fanout,num_switches,num_links)
131
132 elif topoType =='linear':
133 if fanout is None: #In linear topology, if fanout or num_hosts_per_sw is not given, by default it is 1
134 fanout = 1
135 num_switches = depth
136 num_hosts_per_sw = fanout
137 total_num_hosts = num_switches * num_hosts_per_sw
138 num_links = total_num_hosts + (num_switches - 1)
139 print "num_switches for %s(%d,%d) = %d and links=%d" %(topoType,depth,fanout,num_switches,num_links)
140 topoDict = {}
141 topoDict = {"num_switches":int(num_switches), "num_corelinks":int(num_links)}
142 return topoDict
143
144
145 def calculate_sw_and_links(self):
146 topoDict = self.num_switches_n_links(*topoArgList)
147 return topoDict
148
adminbae64d82013-08-01 10:50:15 -0700149 def pingall(self):
150 '''
Jon Hall41f40e82014-04-08 16:43:17 -0700151 Verifies the reachability of the hosts using pingall command.
adminbae64d82013-08-01 10:50:15 -0700152 '''
153 if self.handle :
Jon Hallf2942ce2014-04-10 16:00:16 -0700154 main.log.info(self.name+": Checking reachabilty to the hosts using pingall")
Jon Hall6094a362014-04-11 14:46:56 -0700155 try:
Jon Hallefa4fa12014-04-14 11:40:21 -0700156 response = self.execute(cmd="pingall",prompt="mininet>",timeout=120)
Jon Hall77f53ce2014-10-13 18:02:06 -0400157 print "response: " + str(response)
Jon Hall6094a362014-04-11 14:46:56 -0700158 except pexpect.EOF:
159 main.log.error(self.name + ": EOF exception found")
160 main.log.error(self.name + ": " + self.handle.before)
161 main.cleanup()
162 main.exit()
Jon Hallf4c8d012014-10-09 19:35:08 -0400163 pattern = 'Results\:\s0\%\sdropped\s'
andrew@onlab.us59e8f692014-10-09 21:41:48 -0400164 #FIXME:Pending Mininet Pull Request #408
Jon Hallf4c8d012014-10-09 19:35:08 -0400165 #pattern = 'Results\:\s0\.00\%\sdropped\s'
Jon Hallf2942ce2014-04-10 16:00:16 -0700166 #if utilities.assert_matches(expect=pattern,actual=response,onpass="All hosts are reaching",onfail="Unable to reach all the hosts"):
167 if re.search(pattern,response):
168 main.log.info(self.name+": All hosts are reachable")
adminbae64d82013-08-01 10:50:15 -0700169 return main.TRUE
170 else:
Jon Hallf2942ce2014-04-10 16:00:16 -0700171 main.log.error(self.name+": Unable to reach all the hosts")
adminbae64d82013-08-01 10:50:15 -0700172 return main.FALSE
173 else :
Jon Hallf2942ce2014-04-10 16:00:16 -0700174 main.log.error(self.name+": Connection failed to the host")
adminbae64d82013-08-01 10:50:15 -0700175 return main.FALSE
adminaeedddd2013-08-02 15:14:15 -0700176
177 def fpingHost(self,**pingParams):
178 '''
179 Uses the fping package for faster pinging...
180 *requires fping to be installed on machine running mininet
181 '''
182 args = utilities.parse_args(["SRC","TARGET"],**pingParams)
admin530b4c92013-08-14 16:54:35 -0700183 command = args["SRC"] + " fping -i 100 -t 20 -C 1 -q "+args["TARGET"]
adminaeedddd2013-08-02 15:14:15 -0700184 self.handle.sendline(command)
Jon Hall333fa8c2014-04-11 11:24:58 -0700185 self.handle.expect([args["TARGET"],pexpect.EOF,pexpect.TIMEOUT])
186 self.handle.expect(["mininet",pexpect.EOF,pexpect.TIMEOUT])
adminaeedddd2013-08-02 15:14:15 -0700187 response = self.handle.before
188 if re.search(":\s-" ,response):
Jon Hallf2942ce2014-04-10 16:00:16 -0700189 main.log.info(self.name+": Ping fail")
adminaeedddd2013-08-02 15:14:15 -0700190 return main.FALSE
admin530b4c92013-08-14 16:54:35 -0700191 elif re.search(":\s\d{1,2}\.\d\d", response):
Jon Hallf2942ce2014-04-10 16:00:16 -0700192 main.log.info(self.name+": Ping good!")
adminaeedddd2013-08-02 15:14:15 -0700193 return main.TRUE
Jon Hallf2942ce2014-04-10 16:00:16 -0700194 main.log.info(self.name+": Install fping on mininet machine... ")
195 main.log.info(self.name+": \n---\n"+response)
adminaeedddd2013-08-02 15:14:15 -0700196 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700197
198 def pingHost(self,**pingParams):
Jon Hallf2942ce2014-04-10 16:00:16 -0700199 '''
200 Ping from one mininet host to another
201 Currently the only supported Params: SRC and TARGET
202 '''
adminbae64d82013-08-01 10:50:15 -0700203 args = utilities.parse_args(["SRC","TARGET"],**pingParams)
204 #command = args["SRC"] + " ping -" + args["CONTROLLER"] + " " +args ["TARGET"]
Jon Hall0819fd92014-05-23 12:08:13 -0700205 command = args["SRC"] + " ping "+args ["TARGET"]+" -c 1 -i 1 -W 8"
Jon Hall6094a362014-04-11 14:46:56 -0700206 try:
Jon Hall6e18c7b2014-04-23 16:26:33 -0700207 main.log.warn("Sending: " + command)
208 #response = self.execute(cmd=command,prompt="mininet",timeout=10 )
209 self.handle.sendline(command)
210 i = self.handle.expect([command,pexpect.TIMEOUT])
211 if i == 1:
212 main.log.error(self.name + ": timeout when waiting for response from mininet")
213 main.log.error("response: " + str(self.handle.before))
214 i = self.handle.expect(["mininet>",pexpect.TIMEOUT])
215 if i == 1:
216 main.log.error(self.name + ": timeout when waiting for response from mininet")
217 main.log.error("response: " + str(self.handle.before))
218 response = self.handle.before
Jon Hall6094a362014-04-11 14:46:56 -0700219 except pexpect.EOF:
220 main.log.error(self.name + ": EOF exception found")
221 main.log.error(self.name + ": " + self.handle.before)
222 main.cleanup()
223 main.exit()
Jon Hallf2942ce2014-04-10 16:00:16 -0700224 main.log.info(self.name+": Ping Response: "+ response )
225 #if utilities.assert_matches(expect=',\s0\%\spacket\sloss',actual=response,onpass="No Packet loss",onfail="Host is not reachable"):
226 if re.search(',\s0\%\spacket\sloss',response):
Jon Hall6e18c7b2014-04-23 16:26:33 -0700227 main.log.info(self.name+": no packets lost, host is reachable")
adminbae64d82013-08-01 10:50:15 -0700228 main.last_result = main.TRUE
229 return main.TRUE
230 else :
Jon Hallf2942ce2014-04-10 16:00:16 -0700231 main.log.error(self.name+": PACKET LOST, HOST IS NOT REACHABLE")
adminbae64d82013-08-01 10:50:15 -0700232 main.last_result = main.FALSE
233 return main.FALSE
adminbae64d82013-08-01 10:50:15 -0700234
235 def checkIP(self,host):
236 '''
Jon Hall41f40e82014-04-08 16:43:17 -0700237 Verifies the host's ip configured or not.
adminbae64d82013-08-01 10:50:15 -0700238 '''
239 if self.handle :
Jon Hall6094a362014-04-11 14:46:56 -0700240 try:
241 response = self.execute(cmd=host+" ifconfig",prompt="mininet>",timeout=10)
242 except pexpect.EOF:
243 main.log.error(self.name + ": EOF exception found")
244 main.log.error(self.name + ": " + self.handle.before)
245 main.cleanup()
246 main.exit()
adminbae64d82013-08-01 10:50:15 -0700247
248 pattern = "inet\s(addr|Mask):([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2}).([0-1]{1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]|[0-9]{1,2})"
admin2a9548d2014-06-17 14:08:07 -0700249 #pattern = "inet addr:10.0.0.6"
Jon Hallf2942ce2014-04-10 16:00:16 -0700250 #if utilities.assert_matches(expect=pattern,actual=response,onpass="Host Ip configured properly",onfail="Host IP not found") :
251 if re.search(pattern,response):
252 main.log.info(self.name+": Host Ip configured properly")
adminbae64d82013-08-01 10:50:15 -0700253 return main.TRUE
254 else:
Jon Hallf2942ce2014-04-10 16:00:16 -0700255 main.log.error(self.name+": Host IP not found")
adminbae64d82013-08-01 10:50:15 -0700256 return main.FALSE
257 else :
Jon Hallf2942ce2014-04-10 16:00:16 -0700258 main.log.error(self.name+": Connection failed to the host")
adminbae64d82013-08-01 10:50:15 -0700259
260 def verifySSH(self,**connectargs):
Jon Hall6094a362014-04-11 14:46:56 -0700261 try:
262 response = self.execute(cmd="h1 /usr/sbin/sshd -D&",prompt="mininet>",timeout=10)
263 response = self.execute(cmd="h4 /usr/sbin/sshd -D&",prompt="mininet>",timeout=10)
264 for key in connectargs:
265 vars(self)[key] = connectargs[key]
266 response = self.execute(cmd="xterm h1 h4 ",prompt="mininet>",timeout=10)
267 except pexpect.EOF:
268 main.log.error(self.name + ": EOF exception found")
269 main.log.error(self.name + ": " + self.handle.before)
270 main.cleanup()
271 main.exit()
adminbae64d82013-08-01 10:50:15 -0700272 import time
273 time.sleep(20)
274 if self.flag == 0:
275 self.flag = 1
276 return main.FALSE
277 else :
278 return main.TRUE
279
280 def getMacAddress(self,host):
281 '''
Jon Hall41f40e82014-04-08 16:43:17 -0700282 Verifies the host's ip configured or not.
adminbae64d82013-08-01 10:50:15 -0700283 '''
284 if self.handle :
Jon Hall6094a362014-04-11 14:46:56 -0700285 try:
286 response = self.execute(cmd=host+" ifconfig",prompt="mininet>",timeout=10)
287 except pexpect.EOF:
288 main.log.error(self.name + ": EOF exception found")
289 main.log.error(self.name + ": " + self.handle.before)
290 main.cleanup()
291 main.exit()
adminbae64d82013-08-01 10:50:15 -0700292
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -0700293 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
294 mac_address_search = re.search(pattern, response, re.I)
295 mac_address = mac_address_search.group().split(" ")[1]
Jon Hallf2942ce2014-04-10 16:00:16 -0700296 main.log.info(self.name+": Mac-Address of Host "+ host + " is " + mac_address)
Ahmed El-Hassanyf720e202014-04-04 16:11:36 -0700297 return mac_address
adminbae64d82013-08-01 10:50:15 -0700298 else :
Jon Hallf2942ce2014-04-10 16:00:16 -0700299 main.log.error(self.name+": Connection failed to the host")
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700300
301 def getInterfaceMACAddress(self,host, interface):
302 '''
303 Return the IP address of the interface on the given host
304 '''
305 if self.handle :
Jon Hall6094a362014-04-11 14:46:56 -0700306 try:
307 response = self.execute(cmd=host+" ifconfig " + interface,
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700308 prompt="mininet>",timeout=10)
Jon Hall6094a362014-04-11 14:46:56 -0700309 except pexpect.EOF:
310 main.log.error(self.name + ": EOF exception found")
311 main.log.error(self.name + ": " + self.handle.before)
312 main.cleanup()
313 main.exit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700314
315 pattern = r'HWaddr\s([0-9A-F]{2}[:-]){5}([0-9A-F]{2})'
316 mac_address_search = re.search(pattern, response, re.I)
317 if mac_address_search is None:
318 main.log.info("No mac address found in %s" % response)
319 return main.FALSE
320 mac_address = mac_address_search.group().split(" ")[1]
321 main.log.info("Mac-Address of "+ host + ":"+ interface + " is " + mac_address)
322 return mac_address
323 else:
324 main.log.error("Connection failed to the host")
325
adminbae64d82013-08-01 10:50:15 -0700326 def getIPAddress(self,host):
327 '''
Jon Hall41f40e82014-04-08 16:43:17 -0700328 Verifies the host's ip configured or not.
adminbae64d82013-08-01 10:50:15 -0700329 '''
330 if self.handle :
Jon Hall6094a362014-04-11 14:46:56 -0700331 try:
332 response = self.execute(cmd=host+" ifconfig",prompt="mininet>",timeout=10)
333 except pexpect.EOF:
334 main.log.error(self.name + ": EOF exception found")
335 main.log.error(self.name + ": " + self.handle.before)
336 main.cleanup()
337 main.exit()
adminbae64d82013-08-01 10:50:15 -0700338
339 pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)"
340 ip_address_search = re.search(pattern, response)
Jon Hallf2942ce2014-04-10 16:00:16 -0700341 main.log.info(self.name+": IP-Address of Host "+host +" is "+ip_address_search.group(1))
adminbae64d82013-08-01 10:50:15 -0700342 return ip_address_search.group(1)
343 else :
Jon Hallf2942ce2014-04-10 16:00:16 -0700344 main.log.error(self.name+": Connection failed to the host")
adminbae64d82013-08-01 10:50:15 -0700345
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700346 def getSwitchDPID(self,switch):
347 '''
348 return the datapath ID of the switch
349 '''
350 if self.handle :
351 cmd = "py %s.dpid" % switch
Jon Hall6094a362014-04-11 14:46:56 -0700352 try:
353 response = self.execute(cmd=cmd,prompt="mininet>",timeout=10)
354 except pexpect.EOF:
355 main.log.error(self.name + ": EOF exception found")
356 main.log.error(self.name + ": " + self.handle.before)
357 main.cleanup()
358 main.exit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700359 pattern = r'^(?P<dpid>\d)+'
360 result = re.search(pattern, response, re.MULTILINE)
361 if result is None:
362 main.log.info("Couldn't find DPID for switch '', found: %s" % (switch, response))
363 return main.FALSE
Jon Hallc1a1d242014-07-21 16:03:33 -0700364 return str(result.group(0))
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700365 else:
366 main.log.error("Connection failed to the host")
367
admin2580a0e2014-07-29 11:24:34 -0700368 def getDPID(self, switch):
369 if self.handle:
370 self.handle.sendline("")
371 self.expect("mininet>")
372 cmd = "py %s.dpid" %switch
373 try:
374 response = self.execute(cmd=cmd,prompt="mininet>",timeout=10)
375 self.handle.expect("mininet>")
376 response = self.handle.before
377 return response
378 except pexpect.EOF:
379 main.log.error(self.name + ": EOF exception found")
380 main.log.error(self.name + ": " + self.handle.before)
381 main.cleanup()
382 main.exit()
383
384
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700385 def getInterfaces(self, node):
386 '''
387 return information dict about interfaces connected to the node
388 '''
389 if self.handle :
390 cmd = 'py "\\n".join(["name=%s,mac=%s,ip=%s,isUp=%s" % (i.name, i.MAC(), i.IP(), i.isUp())'
391 cmd += ' for i in %s.intfs.values()])' % node
Jon Hall6094a362014-04-11 14:46:56 -0700392 try:
393 response = self.execute(cmd=cmd,prompt="mininet>",timeout=10)
394 except pexpect.EOF:
395 main.log.error(self.name + ": EOF exception found")
396 main.log.error(self.name + ": " + self.handle.before)
397 main.cleanup()
398 main.exit()
Ahmed El-Hassanyfd329182014-04-10 11:38:16 -0700399 return response
400 else:
401 main.log.error("Connection failed to the node")
402
adminbae64d82013-08-01 10:50:15 -0700403 def dump(self):
Jon Hallf2942ce2014-04-10 16:00:16 -0700404 main.log.info(self.name+": Dump node info")
Jon Hall6094a362014-04-11 14:46:56 -0700405 try:
406 response = self.execute(cmd = 'dump',prompt = 'mininet>',timeout = 10)
407 except pexpect.EOF:
408 main.log.error(self.name + ": EOF exception found")
409 main.log.error(self.name + ": " + self.handle.before)
410 main.cleanup()
411 main.exit()
Ahmed El-Hassanyd1f71702014-04-04 16:12:45 -0700412 return response
adminbae64d82013-08-01 10:50:15 -0700413
414 def intfs(self):
Jon Hallf2942ce2014-04-10 16:00:16 -0700415 main.log.info(self.name+": List interfaces")
Jon Hall6094a362014-04-11 14:46:56 -0700416 try:
417 response = self.execute(cmd = 'intfs',prompt = 'mininet>',timeout = 10)
418 except pexpect.EOF:
419 main.log.error(self.name + ": EOF exception found")
420 main.log.error(self.name + ": " + self.handle.before)
421 main.cleanup()
422 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700423 return response
adminbae64d82013-08-01 10:50:15 -0700424
425 def net(self):
Jon Hallf2942ce2014-04-10 16:00:16 -0700426 main.log.info(self.name+": List network connections")
Jon Hall6094a362014-04-11 14:46:56 -0700427 try:
428 response = self.execute(cmd = 'net',prompt = 'mininet>',timeout = 10)
429 except pexpect.EOF:
430 main.log.error(self.name + ": EOF exception found")
431 main.log.error(self.name + ": " + self.handle.before)
432 main.cleanup()
433 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700434 return response
adminbae64d82013-08-01 10:50:15 -0700435
436 def iperf(self):
Jon Hallf2942ce2014-04-10 16:00:16 -0700437 main.log.info(self.name+": Simple iperf TCP test between two (optionally specified) hosts")
Jon Hall6094a362014-04-11 14:46:56 -0700438 try:
439 response = self.execute(cmd = 'iperf',prompt = 'mininet>',timeout = 10)
440 except pexpect.EOF:
441 main.log.error(self.name + ": EOF exception found")
442 main.log.error(self.name + ": " + self.handle.before)
443 main.cleanup()
444 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700445 return response
adminbae64d82013-08-01 10:50:15 -0700446
447 def iperfudp(self):
Jon Hallf2942ce2014-04-10 16:00:16 -0700448 main.log.info(self.name+": Simple iperf TCP test between two (optionally specified) hosts")
Jon Hall6094a362014-04-11 14:46:56 -0700449 try:
450 response = self.execute(cmd = 'iperfudp',prompt = 'mininet>',timeout = 10)
451 except pexpect.EOF:
452 main.log.error(self.name + ": EOF exception found")
453 main.log.error(self.name + ": " + self.handle.before)
454 main.cleanup()
455 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700456 return response
adminbae64d82013-08-01 10:50:15 -0700457
458 def nodes(self):
Jon Hallf2942ce2014-04-10 16:00:16 -0700459 main.log.info(self.name+": List all nodes.")
Jon Hall6094a362014-04-11 14:46:56 -0700460 try:
461 response = self.execute(cmd = 'nodes',prompt = 'mininet>',timeout = 10)
462 except pexpect.EOF:
463 main.log.error(self.name + ": EOF exception found")
464 main.log.error(self.name + ": " + self.handle.before)
465 main.cleanup()
466 main.exit()
Jon Hall668ed802014-04-08 17:17:59 -0700467 return response
adminbae64d82013-08-01 10:50:15 -0700468
469 def pingpair(self):
Jon Hallf2942ce2014-04-10 16:00:16 -0700470 main.log.info(self.name+": Ping between first two hosts")
Jon Hall6094a362014-04-11 14:46:56 -0700471 try:
472 response = self.execute(cmd = 'pingpair',prompt = 'mininet>',timeout = 20)
473 except pexpect.EOF:
474 main.log.error(self.name + ": EOF exception found")
475 main.log.error(self.name + ": " + self.handle.before)
476 main.cleanup()
477 main.exit()
adminbae64d82013-08-01 10:50:15 -0700478
Jon Hallf2942ce2014-04-10 16:00:16 -0700479 #if utilities.assert_matches(expect='0% packet loss',actual=response,onpass="No Packet loss",onfail="Hosts not reachable"):
480 if re.search(',\s0\%\spacket\sloss',response):
481 main.log.info(self.name+": Ping between two hosts SUCCESSFUL")
adminbae64d82013-08-01 10:50:15 -0700482 main.last_result = main.TRUE
483 return main.TRUE
484 else :
Jon Hallf2942ce2014-04-10 16:00:16 -0700485 main.log.error(self.name+": PACKET LOST, HOSTS NOT REACHABLE")
adminbae64d82013-08-01 10:50:15 -0700486 main.last_result = main.FALSE
487 return main.FALSE
488
489 def link(self,**linkargs):
490 '''
491 Bring link(s) between two nodes up or down
492 '''
493 main.log.info('Bring link(s) between two nodes up or down')
494 args = utilities.parse_args(["END1","END2","OPTION"],**linkargs)
495 end1 = args["END1"] if args["END1"] != None else ""
496 end2 = args["END2"] if args["END2"] != None else ""
497 option = args["OPTION"] if args["OPTION"] != None else ""
498 command = "link "+str(end1) + " " + str(end2)+ " " + str(option)
Jon Hall6094a362014-04-11 14:46:56 -0700499 try:
Jon Halle80ef8c2014-04-29 15:29:13 -0700500 #response = self.execute(cmd=command,prompt="mininet>",timeout=10)
501 self.handle.sendline(command)
502 self.handle.expect("mininet>")
Jon Hall6094a362014-04-11 14:46:56 -0700503 except pexpect.EOF:
504 main.log.error(self.name + ": EOF exception found")
505 main.log.error(self.name + ": " + self.handle.before)
506 main.cleanup()
507 main.exit()
adminbae64d82013-08-01 10:50:15 -0700508 return main.TRUE
509
510
admin530b4c92013-08-14 16:54:35 -0700511 def yank(self,**yankargs):
adminaeedddd2013-08-02 15:14:15 -0700512 '''
admin530b4c92013-08-14 16:54:35 -0700513 yank a mininet switch interface to a host
adminaeedddd2013-08-02 15:14:15 -0700514 '''
admin530b4c92013-08-14 16:54:35 -0700515 main.log.info('Yank the switch interface attached to a host')
516 args = utilities.parse_args(["SW","INTF"],**yankargs)
adminaeedddd2013-08-02 15:14:15 -0700517 sw = args["SW"] if args["SW"] !=None else ""
518 intf = args["INTF"] if args["INTF"] != None else ""
519 command = "py "+ str(sw) + '.detach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -0700520 try:
521 response = self.execute(cmd=command,prompt="mininet>",timeout=10)
522 except pexpect.EOF:
523 main.log.error(self.name + ": EOF exception found")
524 main.log.error(self.name + ": " + self.handle.before)
525 main.cleanup()
526 main.exit()
adminaeedddd2013-08-02 15:14:15 -0700527 return main.TRUE
528
529 def plug(self, **plugargs):
530 '''
531 plug the yanked mininet switch interface to a switch
532 '''
533 main.log.info('Plug the switch interface attached to a switch')
admin530b4c92013-08-14 16:54:35 -0700534 args = utilities.parse_args(["SW","INTF"],**plugargs)
adminaeedddd2013-08-02 15:14:15 -0700535 sw = args["SW"] if args["SW"] !=None else ""
536 intf = args["INTF"] if args["INTF"] != None else ""
537 command = "py "+ str(sw) + '.attach("' + str(intf) + '")'
Jon Hall6094a362014-04-11 14:46:56 -0700538 try:
539 response = self.execute(cmd=command,prompt="mininet>",timeout=10)
540 except pexpect.EOF:
541 main.log.error(self.name + ": EOF exception found")
542 main.log.error(self.name + ": " + self.handle.before)
543 main.cleanup()
544 main.exit()
adminaeedddd2013-08-02 15:14:15 -0700545 return main.TRUE
546
547
548
adminbae64d82013-08-01 10:50:15 -0700549 def dpctl(self,**dpctlargs):
550 '''
Jon Hall41f40e82014-04-08 16:43:17 -0700551 Run dpctl command on all switches.
adminbae64d82013-08-01 10:50:15 -0700552 '''
553 main.log.info('Run dpctl command on all switches')
554 args = utilities.parse_args(["CMD","ARGS"],**dpctlargs)
555 cmd = args["CMD"] if args["CMD"] != None else ""
556 cmdargs = args["ARGS"] if args["ARGS"] != None else ""
557 command = "dpctl "+cmd + " " + str(cmdargs)
Jon Hall6094a362014-04-11 14:46:56 -0700558 try:
559 response = self.execute(cmd=command,prompt="mininet>",timeout=10)
560 except pexpect.EOF:
561 main.log.error(self.name + ": EOF exception found")
562 main.log.error(self.name + ": " + self.handle.before)
563 main.cleanup()
564 main.exit()
adminbae64d82013-08-01 10:50:15 -0700565 return main.TRUE
566
567
568 def get_version(self):
569 file_input = path+'/lib/Mininet/INSTALL'
570 version = super(Mininet, self).get_version()
571 pattern = 'Mininet\s\w\.\w\.\w\w*'
572 for line in open(file_input,'r').readlines():
573 result = re.match(pattern, line)
574 if result:
575 version = result.group(0)
576 return version
577
admin2a9548d2014-06-17 14:08:07 -0700578 def get_sw_controller_sanity(self, sw):
579 command = "sh ovs-vsctl get-controller "+str(sw)
580 try:
581 response = self.execute(cmd=command,prompt="mininet>",timeout=10)
582 if response:
583 return main.TRUE
584 else:
585 return main.FALSE
586 except pexpect.EOF:
587 main.log.error(self.name + ": EOF exception found")
588 main.log.error(self.name + ": " + self.handle.before)
589 main.cleanup()
590 main.exit()
591 else:
592 main.log.info(response)
593
adminbae64d82013-08-01 10:50:15 -0700594 def get_sw_controller(self,sw):
595 command = "sh ovs-vsctl get-controller "+str(sw)
Jon Hall6094a362014-04-11 14:46:56 -0700596 try:
597 response = self.execute(cmd=command,prompt="mininet>",timeout=10)
admin2a9548d2014-06-17 14:08:07 -0700598 print(response)
599 if response:
admindc1c5072014-06-24 15:57:19 -0700600 print("**********************")
admin2a9548d2014-06-17 14:08:07 -0700601 return response
602 else:
603 return main.FALSE
Jon Hall6094a362014-04-11 14:46:56 -0700604 except pexpect.EOF:
605 main.log.error(self.name + ": EOF exception found")
606 main.log.error(self.name + ": " + self.handle.before)
607 main.cleanup()
608 main.exit()
609 else:
610 main.log.info(response)
adminbae64d82013-08-01 10:50:15 -0700611
612 def assign_sw_controller(self,**kwargs):
Jon Hallf89c8552014-04-02 13:14:06 -0700613 '''
614 count is only needed if there is more than 1 controller
615 '''
616 args = utilities.parse_args(["COUNT"],**kwargs)
617 count = args["COUNT"] if args!={} else 1
618
619 argstring = "SW"
620 for j in range(count):
621 argstring = argstring + ",IP" + str(j+1) + ",PORT" + str(j+1)
622 args = utilities.parse_args(argstring.split(","),**kwargs)
623
adminbae64d82013-08-01 10:50:15 -0700624 sw = args["SW"] if args["SW"] != None else ""
admin530b4c92013-08-14 16:54:35 -0700625 ptcpA = int(args["PORT1"])+int(sw) if args["PORT1"] != None else ""
Jon Hallf89c8552014-04-02 13:14:06 -0700626 ptcpB = "ptcp:"+str(ptcpA) if ptcpA != "" else ""
627
628 command = "sh ovs-vsctl set-controller s" + str(sw) + " " + ptcpB + " "
629 for j in range(count):
630 i=j+1
631 args = utilities.parse_args(["IP"+str(i),"PORT"+str(i)],**kwargs)
632 ip = args["IP"+str(i)] if args["IP"+str(i)] != None else ""
633 port = args["PORT" + str(i)] if args["PORT" + str(i)] != None else ""
634 tcp = "tcp:" + str(ip) + ":" + str(port) + " " if ip != "" else ""
635 command = command + tcp
Jon Hall6094a362014-04-11 14:46:56 -0700636 try:
637 self.execute(cmd=command,prompt="mininet>",timeout=5)
638 except pexpect.EOF:
639 main.log.error(self.name + ": EOF exception found")
640 main.log.error(self.name + ": " + self.handle.before)
641 main.cleanup()
642 main.exit()
643 except:
644 main.log.info(self.name + ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
645 main.log.error( traceback.print_exc() )
646 main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
647 main.cleanup()
648 main.exit()
adminbae64d82013-08-01 10:50:15 -0700649
Jon Hall0819fd92014-05-23 12:08:13 -0700650 def delete_sw_controller(self,sw):
651 '''
652 Removes the controller target from sw
653 '''
654
655 command = "sh ovs-vsctl del-controller "+str(sw)
656 try:
657 response = self.execute(cmd=command,prompt="mininet>",timeout=10)
658 except pexpect.EOF:
659 main.log.error(self.name + ": EOF exception found")
660 main.log.error(self.name + ": " + self.handle.before)
661 main.cleanup()
662 main.exit()
663 else:
664 main.log.info(response)
665
666
adminbae64d82013-08-01 10:50:15 -0700667 def disconnect(self):
Jon Hallf2942ce2014-04-10 16:00:16 -0700668 main.log.info(self.name+": Disconnecting mininet...")
adminbae64d82013-08-01 10:50:15 -0700669 response = ''
670 if self.handle:
Jon Hall6094a362014-04-11 14:46:56 -0700671 try:
672 response = self.execute(cmd="exit",prompt="(.*)",timeout=120)
673 response = self.execute(cmd="exit",prompt="(.*)",timeout=120)
Jon Halle80ef8c2014-04-29 15:29:13 -0700674 self.handle.sendline("sudo mn -c")
Jon Hall6094a362014-04-11 14:46:56 -0700675 except pexpect.EOF:
676 main.log.error(self.name + ": EOF exception found")
677 main.log.error(self.name + ": " + self.handle.before)
678 main.cleanup()
679 main.exit()
adminbae64d82013-08-01 10:50:15 -0700680 else :
Jon Hallf2942ce2014-04-10 16:00:16 -0700681 main.log.error(self.name+": Connection failed to the host")
adminbae64d82013-08-01 10:50:15 -0700682 response = main.FALSE
683 return response
admin07529932013-11-22 14:58:28 -0800684
685 def arping(self, src, dest, destmac):
686 self.handle.sendline('')
Jon Hall333fa8c2014-04-11 11:24:58 -0700687 self.handle.expect(["mininet",pexpect.EOF,pexpect.TIMEOUT])
admin07529932013-11-22 14:58:28 -0800688
689 self.handle.sendline(src + ' arping ' + dest)
690 try:
Jon Hall333fa8c2014-04-11 11:24:58 -0700691 self.handle.expect([destmac,pexpect.EOF,pexpect.TIMEOUT])
Jon Hallf2942ce2014-04-10 16:00:16 -0700692 main.log.info(self.name+": ARP successful")
Jon Hall333fa8c2014-04-11 11:24:58 -0700693 self.handle.expect(["mininet",pexpect.EOF,pexpect.TIMEOUT])
admin07529932013-11-22 14:58:28 -0800694 return main.TRUE
695 except:
Jon Hallf2942ce2014-04-10 16:00:16 -0700696 main.log.warn(self.name+": ARP FAILURE")
Jon Hall333fa8c2014-04-11 11:24:58 -0700697 self.handle.expect(["mininet",pexpect.EOF,pexpect.TIMEOUT])
admin07529932013-11-22 14:58:28 -0800698 return main.FALSE
699
700 def decToHex(num):
701 return hex(num).split('x')[1]
admin2a9548d2014-06-17 14:08:07 -0700702
703 def getSwitchFlowCount(self, switch):
704 '''
705 return the Flow Count of the switch
706 '''
707 if self.handle:
708 cmd = "sh ovs-ofctl dump-aggregate %s" % switch
709 try:
710 response = self.execute(cmd=cmd, prompt="mininet>", timeout=10)
711 except pexpect.EOF:
712 main.log.error(self.name + ": EOF exception found")
713 main.log.error(self.name + " " + self.handle.before)
714 main.cleanup()
715 main.exit()
716 pattern = "flow_count=(\d+)"
717 result = re.search(pattern, response, re.MULTILINE)
718 if result is None:
719 print "no flow on switch print test"
720 main.log.info("Couldn't find flows on switch '', found: %s" % (switch, response))
721 return main.FALSE
722 return result.group(1)
723 else:
724 main.log.error("Connection failed to the Mininet host")
725
Ahmed El-Hassanyb6545eb2014-08-01 11:32:10 -0700726 def check_flows(self, sw, dump_format=None):
727 if dump_format:
728 command = "sh ovs-ofctl -F " + dump_format + " dump-flows " + str(sw)
729 else:
730 command = "sh ovs-ofctl dump-flows "+str(sw)
admin2a9548d2014-06-17 14:08:07 -0700731 try:
732 response=self.execute(cmd=command,prompt="mininet>",timeout=10)
733 return response
734 except pexpect.EOF:
735 main.log.error(self.name + ": EOF exception found")
736 main.log.error(self.name + ": " + self.handle.before)
737 main.cleanup()
738 main.exit()
739 else:
740 main.log.info(response)
741
742 def start_tcpdump(self, filename, intf = "eth0", port = "port 6633"):
743 '''
744 Runs tpdump on an intferface and saves the file
745 intf can be specified, or the default eth0 is used
746 '''
747 try:
748 self.handle.sendline("")
749 self.handle.expect("mininet>")
750 self.handle.sendline("sh sudo tcpdump -n -i "+ intf + " " + port + " -w " + filename.strip() + " &")
751 self.handle.sendline("")
752 self.handle.sendline("")
753 i=self.handle.expect(['No\ssuch\device','listening\son',pexpect.TIMEOUT,"mininet>"],timeout=10)
754 main.log.warn(self.handle.before + self.handle.after)
755 if i == 0:
756 main.log.error(self.name + ": tcpdump - No such device exists. tcpdump attempted on: " + intf)
757 return main.FALSE
758 elif i == 1:
759 main.log.info(self.name + ": tcpdump started on " + intf)
760 return main.TRUE
761 elif i == 2:
762 main.log.error(self.name + ": tcpdump command timed out! Check interface name, given interface was: " + intf)
763 return main.FALSE
764 elif i ==3:
765 main.log.info(self.name +": " + self.handle.before)
766 return main.TRUE
767 else:
768 main.log.error(self.name + ": tcpdump - unexpected response")
769 return main.FALSE
770 except pexpect.EOF:
771 main.log.error(self.name + ": EOF exception found")
772 main.log.error(self.name + ": " + self.handle.before)
773 main.cleanup()
774 main.exit()
775 except:
776 main.log.info(self.name + ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
777 main.log.error( traceback.print_exc() )
778 main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
779 main.cleanup()
780 main.exit()
781
782 def stop_tcpdump(self):
783 "pkills tcpdump"
784 try:
785 self.handle.sendline("sh sudo pkill tcpdump")
786 self.handle.sendline("")
787 self.handle.sendline("")
788 self.handle.expect("mininet>")
789 except pexpect.EOF:
790 main.log.error(self.name + ": EOF exception found")
791 main.log.error(self.name + ": " + self.handle.before)
792 main.cleanup()
793 main.exit()
794 except:
795 main.log.info(self.name + ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
796 main.log.error( traceback.print_exc() )
797 main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
798 main.cleanup()
799 main.exit()
800
Jon Hall3d87d502014-10-17 18:37:42 -0400801 def compare_switches(self, topo, switches_json):
802 '''
803 Compare mn and onos switches
804 topo: sts TestONTopology object
805 switches_json: parsed json object from the onos devices api
806
807 This uses the sts TestONTopology object
808
809 '''
810 import json
Jon Hall3d87d502014-10-17 18:37:42 -0400811 output = {"switches":[]}
812 for switch in topo.graph.switches: #iterate through the MN topology and pull out switches and and port info
813 #print vars(switch)
814 ports = []
815 for port in switch.ports.values():
816 #print port.hw_addr.toStr(separator = '')
817 ports.append({'of_port': port.port_no, 'mac': str(port.hw_addr).replace('\'',''), 'name': port.name})
818 output['switches'].append({"name": switch.name, "dpid": str(switch.dpid).zfill(16), "ports": ports })
819 #print output
820
821 #print json.dumps(output, sort_keys=True,indent=4,separators=(',', ': '))
822
823
824 # created sorted list of dpid's in MN and ONOS for comparison
825 mnDPIDs=[]
826 for switch in output['switches']:
827 mnDPIDs.append(switch['dpid'])
828 mnDPIDs.sort()
829 #print mnDPIDs
830 if switches_json == "":#if rest call fails
831 main.log.error(self.name + ".compare_topo(): Empty JSON object given from ONOS")
832 return main.FALSE
833 onos=switches_json
834 onosDPIDs=[]
835 for switch in onos:
836 onosDPIDs.append(switch['id'].replace(":",'').replace("of",''))
837 #print switch
838 onosDPIDs.sort()
839 #print onosDPIDs
840
841 if mnDPIDs!=onosDPIDs:
842 switch_results = main.FALSE
843 main.log.report( "Switches in MN but not in ONOS:")
844 main.log.report( str([switch for switch in mnDPIDs if switch not in onosDPIDs]))
845 main.log.report( "Switches in ONOS but not in MN:")
846 main.log.report( str([switch for switch in onosDPIDs if switch not in mnDPIDs]))
847 else:#list of dpid's match in onos and mn
848 #main.log.report("DEBUG: The dpid's of the switches in Mininet and ONOS match")
849 switch_results = main.TRUE
850 return switch_results
851
852
853
Jon Hall72cf1dc2014-10-20 21:04:50 -0400854 def compare_ports(self, topo, ports_json):
855 '''
856 Compare mn and onos ports
857 topo: sts TestONTopology object
858 ports_json: parsed json object from the onos ports api
859
860 Dependencies:
861 1. This uses the sts TestONTopology object
862 2. numpy - "sudo pip install numpy"
863
864 '''
865 import json
866 from numpy import uint64
867 port_results = main.TRUE
868 output = {"switches":[]}
869 for switch in topo.graph.switches: #iterate through the MN topology and pull out switches and and port info
870 #print vars(switch)
871 ports = []
872 for port in switch.ports.values():
873 #print port.hw_addr.toStr(separator = '')
874 ports.append({'of_port': port.port_no, 'mac': str(port.hw_addr).replace('\'',''), 'name': port.name})
875 output['switches'].append({"name": switch.name, "dpid": str(switch.dpid).zfill(16), "ports": ports })
876 #print "compare_ports 'output' variable:"
877 #print output
878
879
880 ################ports#############
881 for switch in output['switches']:
882 mn_ports = []
883 onos_ports = []
884 for port in switch['ports']:
885 mn_ports.append(port['of_port'])
886 for onos_switch in ports_json:
887 if onos_switch['device'].replace(':','').replace("of", '') == switch['dpid']:
888 for port in onos_switch['ports']:
889 onos_ports.append(int(port['port']))
890 mn_ports.sort(key=float)
891 onos_ports.sort(key=float)
892 #print "\nPorts for Switch %s:" % (switch['name'])
893 #print "\tmn_ports[] = ", mn_ports
894 #print "\tonos_ports[] = ", onos_ports
895
896 #if mn_ports == onos_ports:
897 #pass #don't set results to true here as this is just one of many checks and it might override a failure
898
899 #For OF1.3, the OFP_local port number is 0xfffffffe or 4294967294 instead of 0xfffe or 65534 in OF1.0, ONOS topology
900 #sees the correct port number, however MN topology as read from line 151 of https://github.com/ucb-sts/sts/blob/
901 #topology_refactoring2/sts/entities/teston_entities.py is 0xfffe which doesn't work correctly with OF1.3 switches.
902 #So a short term fix is to ignore the case when mn_port == 65534 and onos_port ==4294967294.
903
904 #ONOS-Next is abstracting port numbers to 64bit unsigned number. So we will be converting the OF reserved ports to these numbers
905 #TODO: handle other reserved port numbers besides LOCAL
906 for mn_port,onos_port in zip(mn_ports,onos_ports):
907 if mn_port == onos_port or (mn_port == 65534 and onos_port ==int(uint64(-2))):
908 continue
909 #don't set results to true here as this is just one of many checks and it might override a failure
910 else: #the ports of this switch don't match
911 port_results = main.FALSE
912 break
913 if port_results == main.FALSE:
914 main.log.report("The list of ports for switch %s(%s) does not match:" % (switch['name'], switch['dpid']) )
915 main.log.report("mn_ports[] = " + str(mn_ports))
916 main.log.report("onos_ports[] = " + str(onos_ports))
917 return port_results
918
919
920
921
922 def compare_links(self, topo, links_json):
923 '''
924 Compare mn and onos links
925 topo: sts TestONTopology object
926 links_json: parsed json object from the onos links api
927
928 This uses the sts TestONTopology object
929
930 '''
931 import json
932 link_results = main.TRUE
933 output = {"switches":[]}
934 onos = links_json
935 for switch in topo.graph.switches: #iterate through the MN topology and pull out switches and and port info
936 #print vars(switch)
937 ports = []
938 for port in switch.ports.values():
939 #print port.hw_addr.toStr(separator = '')
940 ports.append({'of_port': port.port_no, 'mac': str(port.hw_addr).replace('\'',''), 'name': port.name})
941 output['switches'].append({"name": switch.name, "dpid": str(switch.dpid).zfill(16), "ports": ports })
942 #######Links########
943
944 if 2*len(topo.patch_panel.network_links) == len(onos):
945 link_results = main.TRUE
946 else:
947 link_results = main.FALSE
948 main.log.report("Mininet has %i bidirectional links and ONOS has %i unidirectional links" % (len(topo.patch_panel.network_links), len(onos) ))
949
950
951 # iterate through MN links and check if an ONOS link exists in both directions
952 # NOTE: Will currently only show mn links as down if they are cut through STS.
953 # We can either do everything through STS or wait for up_network_links
954 # and down_network_links to be fully implemented.
955 for link in topo.patch_panel.network_links:
956 #print "\n"
957 #print "Link: %s" % link
958 #TODO: Find a more efficient search method
959 node1 = None
960 port1 = None
961 node2 = None
962 port2 = None
963 first_dir = main.FALSE
964 second_dir = main.FALSE
965 for switch in output['switches']:
966 #print "Switch: %s" % switch['name']
967 if switch['name'] == link.node1.name:
968 node1 = switch['dpid']
969 for port in switch['ports']:
970 if str(port['name']) == str(link.port1):
971 port1 = port['of_port']
972 if node1 is not None and node2 is not None:
973 break
974 if switch['name'] == link.node2.name:
975 node2 = switch['dpid']
976 for port in switch['ports']:
977 if str(port['name']) == str(link.port2):
978 port2 = port['of_port']
979 if node1 is not None and node2 is not None:
980 break
981
982
983 for onos_link in onos:
984 onos_node1 = onos_link['src']['device'].replace(":",'').replace("of", '')
985 onos_node2 = onos_link['dst']['device'].replace(":",'').replace("of", '')
986 onos_port1 = onos_link['src']['port']
987 onos_port2 = onos_link['dst']['port']
988
989 #print "Checking ONOS for link %s/%s -> %s/%s and" % (node1, port1, node2, port2)
990 #print "Checking ONOS for link %s/%s -> %s/%s" % (node2, port2, node1, port1)
991 # check onos link from node1 to node2
992 if str(onos_node1) == str(node1) and str(onos_node2) == str(node2):
993 if int(onos_port1) == int(port1) and int(onos_port2) == int(port2):
994 first_dir = main.TRUE
995 else:
996 main.log.report('The port numbers do not match for ' +str(link) +\
997 ' between ONOS and MN. When cheking ONOS for link '+\
998 '%s/%s -> %s/%s' % (node1, port1, node2, port2)+\
999 ' ONOS has the values %s/%s -> %s/%s' %\
1000 (onos_node1, onos_port1, onos_node2, onos_port2))
1001
1002 # check onos link from node2 to node1
1003 elif ( str(onos_node1) == str(node2) and str(onos_node2) == str(node1) ):
1004 if ( int(onos_port1) == int(port2) and int(onos_port2) == int(port1) ):
1005 second_dir = main.TRUE
1006 else:
1007 main.log.report('The port numbers do not match for ' +str(link) +\
1008 ' between ONOS and MN. When cheking ONOS for link '+\
1009 '%s/%s -> %s/%s' % (node2, port2, node1, port1)+\
1010 ' ONOS has the values %s/%s -> %s/%s' %\
1011 (onos_node2, onos_port2, onos_node1, onos_port1))
1012 else:#this is not the link you're looking for
1013 pass
1014 if not first_dir:
1015 main.log.report('ONOS does not have the link %s/%s -> %s/%s' % (node1, port1, node2, port2))
1016 if not second_dir:
1017 main.log.report('ONOS does not have the link %s/%s -> %s/%s' % (node2, port2, node1, port1))
1018 link_results = link_results and first_dir and second_dir
Jon Hall62df9242014-10-22 12:20:17 -04001019 return link_results
Jon Hall72cf1dc2014-10-20 21:04:50 -04001020
1021
Jon Hall3d87d502014-10-17 18:37:42 -04001022
1023
Jon Hall7c3d1092014-08-11 15:08:31 -07001024 def compare_topo(self, topo, onos_json):
Jon Hall8412ed12014-07-24 16:33:58 -07001025 '''
1026 compares mn topology with ONOS topology
1027 onos_list is a list of ONOS controllers, each element of the list should be (handle, name, ip, port)
1028 onos_json is the output of the onos get_json function calling the /wm/onos/topology REST API
Jon Halle3a74502014-07-25 11:13:16 -07001029 Returns: True if MN and ONOS topology match and False if the differ.
1030 Differences between ONOS and MN topology will be printed to the log.
1031
1032 Dependency: Requires STS to be installed on the TestON machine. STS can be pulled
1033 from https://github.com/ucb-sts/sts.git . Currently the required functions from STS are located in the
1034 topology_refactoring2 branch, but may be merged into the master branch soon. You may need to install some
1035 python modules such as networkx to use the STS functions.
1036
Jon Hall38f50122014-08-05 13:16:52 -07001037 To install sts:
1038 $ git clone git://github.com/ucb-sts/sts.git
1039 $ cd sts
1040 $ git clone -b debugger git://github.com/ucb-sts/pox.git
1041 $ sudo apt-get install python-dev
1042 $ ./tools/install_hassel_python.sh
1043 $ sudo pip install networkx
1044
1045 Include sts in your PYTHONPATH. it should looks comething like:
1046 PYTHONPATH=/home/admin/TestON:/home/admin/sts
1047
Jon Hall8412ed12014-07-24 16:33:58 -07001048 '''
admin680b78c2014-08-08 11:46:45 -07001049 import sys
1050 sys.path.append("~/sts")
Jon Halle9341332014-08-07 10:09:36 -07001051 #NOTE: Create this once per Test and pass the TestONTopology object around. It takes too long to create this object.
1052 # This will make it easier to use the sts methods for severing links and solve that issue
Jon Hall0d88a252014-07-25 11:22:40 -07001053 import json
admin2a9548d2014-06-17 14:08:07 -07001054
Jon Hall8412ed12014-07-24 16:33:58 -07001055 link_results = main.TRUE
1056 switch_results = main.TRUE
1057 port_results = main.TRUE
1058
1059 ########Switches#######
1060 output = {"switches":[]}
Jon Hall0d88a252014-07-25 11:22:40 -07001061 for switch in topo.graph.switches: #iterate through the MN topology and pull out switches and and port info
Jon Hall8412ed12014-07-24 16:33:58 -07001062 ports = []
1063 for port in switch.ports.values():
Jon Hall38f50122014-08-05 13:16:52 -07001064 #print port.hw_addr.toStr(separator = '')
1065 ports.append({'of_port': port.port_no, 'mac': str(port.hw_addr).replace('\'',''), 'name': port.name})
1066 output['switches'].append({"name": switch.name, "dpid": str(switch.dpid).zfill(16), "ports": ports })
Jon Hall8412ed12014-07-24 16:33:58 -07001067 #print output
1068
Jon Hall8412ed12014-07-24 16:33:58 -07001069 #print json.dumps(output, sort_keys=True,indent=4,separators=(',', ': '))
1070
1071
Jon Hall0d88a252014-07-25 11:22:40 -07001072 # created sorted list of dpid's in MN and ONOS for comparison
Jon Hall8412ed12014-07-24 16:33:58 -07001073 mnDPIDs=[]
1074 for switch in output['switches']:
1075 mnDPIDs.append(switch['dpid'])
1076 mnDPIDs.sort()
Jon Halle9341332014-08-07 10:09:36 -07001077 #print mnDPIDs
Jon Hall0d88a252014-07-25 11:22:40 -07001078 if onos_json == "":#if rest call fails
Jon Hall8412ed12014-07-24 16:33:58 -07001079 main.log.error(self.name + ".compare_topo(): Empty JSON object given from ONOS rest call")
1080 return main.FALSE
1081 onos=onos_json
1082 onosDPIDs=[]
1083 for switch in onos['switches']:
1084 onosDPIDs.append(switch['dpid'].replace(":",''))
1085 onosDPIDs.sort()
Jon Halle9341332014-08-07 10:09:36 -07001086 #print onosDPIDs
Jon Hall8412ed12014-07-24 16:33:58 -07001087
1088 if mnDPIDs!=onosDPIDs:
1089 switch_results = main.FALSE
1090 main.log.report( "Switches in MN but not in ONOS:")
1091 main.log.report( str([switch for switch in mnDPIDs if switch not in onosDPIDs]))
1092 main.log.report( "Switches in ONOS but not in MN:")
1093 main.log.report( str([switch for switch in onosDPIDs if switch not in mnDPIDs]))
1094 else:#list of dpid's match in onos and mn
1095 switch_results = main.TRUE
1096
1097 ################ports#############
1098 for switch in output['switches']:
1099 mn_ports = []
1100 onos_ports = []
1101 for port in switch['ports']:
1102 mn_ports.append(port['of_port'])
1103 for onos_switch in onos['switches']:
1104 if onos_switch['dpid'].replace(':','') == switch['dpid']:
1105 for port in onos_switch['ports']:
1106 onos_ports.append(port['portNumber'])
1107 mn_ports.sort()
1108 onos_ports.sort()
shahshreyaf4d4d0c2014-10-10 12:11:10 -07001109 #print "mn_ports[] = ", mn_ports
1110 #print "onos_ports90 = ", onos_ports
1111
1112 #if mn_ports == onos_ports:
1113 #pass #don't set results to true here as this is just one of many checks and it might override a failure
1114
1115 #For OF1.3, the OFP_local port number is 0xfffffffe or 4294967294 instead of 0xfffe or 65534 in OF1.0, ONOS topology
Jon Hall72cf1dc2014-10-20 21:04:50 -04001116 #sees the correct port number, however MN topology as read from line 151 of https://github.com/ucb-sts/sts/blob/
shahshreyaf4d4d0c2014-10-10 12:11:10 -07001117 #topology_refactoring2/sts/entities/teston_entities.py is 0xfffe which doesn't work correctly with OF1.3 switches.
1118 #So a short term fix is to ignore the case when mn_port == 65534 and onos_port ==4294967294.
1119 for mn_port,onos_port in zip(mn_ports,onos_ports):
1120 if mn_port == onos_port or (mn_port == 65534 and onos_port ==4294967294):
1121 continue
1122 else:
1123 port_results = main.FALSE
1124 break
shahshreyaf4d4d0c2014-10-10 12:11:10 -07001125 '''
Jon Hall8412ed12014-07-24 16:33:58 -07001126 else: #the ports of this switch don't match
1127 port_results = main.FALSE
1128 main.log.report("ports in MN switch %s(%s) but not in ONOS:" % (switch['name'],switch['dpid']))
1129 main.log.report( str([port for port in mn_ports if port not in onos_ports]))
1130 main.log.report("ports in ONOS switch %s(%s) but not in MN:" % (switch['name'],switch['dpid']))
1131 main.log.report( str([port for port in onos_ports if port not in mn_ports]))
shahshreyaf4d4d0c2014-10-10 12:11:10 -07001132 '''
1133 if port_results == main.FALSE:
1134 main.log.report("ports in MN switch %s(%s) but not in ONOS:" % (switch['name'],switch['dpid']))
1135 main.log.report( str([port for port in mn_ports if port not in onos_ports]))
1136 main.log.report("ports in ONOS switch %s(%s) but not in MN:" % (switch['name'],switch['dpid']))
1137 main.log.report( str([port for port in onos_ports if port not in mn_ports]))
Jon Hall8412ed12014-07-24 16:33:58 -07001138
1139 #######Links########
Jon Hall0d88a252014-07-25 11:22:40 -07001140 # iterate through MN links and check if and ONOS link exists in both directions
Jon Halle9341332014-08-07 10:09:36 -07001141 # NOTE: Will currently only show mn links as down if they are cut through STS.
1142 # We can either do everything through STS or wait for up_network_links
1143 # and down_network_links to be fully implemented.
Jon Hall8412ed12014-07-24 16:33:58 -07001144 for link in topo.patch_panel.network_links:
1145 #print "Link: %s" % link
1146 #TODO: Find a more efficient search method
1147 node1 = None
1148 port1 = None
1149 node2 = None
1150 port2 = None
1151 first_dir = main.FALSE
1152 second_dir = main.FALSE
1153 for switch in output['switches']:
1154 if switch['name'] == link.node1.name:
1155 node1 = switch['dpid']
1156 for port in switch['ports']:
1157 if str(port['name']) == str(link.port1):
1158 port1 = port['of_port']
1159 if node1 is not None and node2 is not None:
1160 break
1161 if switch['name'] == link.node2.name:
1162 node2 = switch['dpid']
1163 for port in switch['ports']:
1164 if str(port['name']) == str(link.port2):
1165 port2 = port['of_port']
1166 if node1 is not None and node2 is not None:
1167 break
1168 # check onos link from node1 to node2
1169 for onos_link in onos['links']:
1170 if onos_link['src']['dpid'].replace(":",'') == node1 and onos_link['dst']['dpid'].replace(":",'') == node2:
1171 if onos_link['src']['portNumber'] == port1 and onos_link['dst']['portNumber'] == port2:
1172 first_dir = main.TRUE
1173 else:
1174 main.log.report('the port numbers do not match for ' +str(link) + ' between ONOS and MN')
1175 #print node1, ' to ', node2
1176 elif onos_link['src']['dpid'].replace(":",'') == node2 and onos_link['dst']['dpid'].replace(":",'') == node1:
1177 if onos_link['src']['portNumber'] == port2 and onos_link['dst']['portNumber'] == port1:
1178 second_dir = main.TRUE
1179 else:
1180 main.log.report('the port numbers do not match for ' +str(link) + ' between ONOS and MN')
1181 #print node2, ' to ', node1
1182 else:#this is not the link you're looking for
1183 pass
1184 if not first_dir:
1185 main.log.report('ONOS has issues with the link from '+str(link.node1.name) +"(dpid: "+ str(node1)+"):"+str(link.port1)+"(portNumber: "+str(port1)+")"+ ' to ' + str(link.node2.name) +"(dpid: "+ str(node2)+"):"+str(link.port2)+"(portNumber: "+str(port2)+")")
1186 if not second_dir:
1187 main.log.report('ONOS has issues with the link from '+str(link.node2.name) +"(dpid: "+ str(node2)+"):"+str(link.port2)+"(portNumber: "+str(port2)+")"+ ' to ' + str(link.node1.name) +"(dpid: "+ str(node1)+"):"+str(link.port1)+"(portNumber: "+str(port1)+")")
1188 link_results = link_results and first_dir and second_dir
1189
1190
1191 results = switch_results and port_results and link_results
Jon Halle9341332014-08-07 10:09:36 -07001192# if not results: #To print out both topologies
1193# main.log.error("Topology comparison failed, printing json objects, MN then ONOS")
1194# main.log.error(str(json.dumps(output, sort_keys=True,indent=4,separators=(',', ': '))))
1195# main.log.error('MN Links:')
1196# for link in topo.patch_panel.network_links: main.log.error(str("\tLink: %s" % link))
1197# main.log.error(str(json.dumps(onos, sort_keys=True,indent=4,separators=(',', ': '))))
Jon Hall8412ed12014-07-24 16:33:58 -07001198 return results
admin2a9548d2014-06-17 14:08:07 -07001199
andrewonlab3f0a4af2014-10-17 12:25:14 -04001200 def get_hosts(self):
1201 '''
1202 Returns a list of all hosts
1203 Don't ask questions just use it
1204 '''
1205 self.handle.sendline("")
1206 self.handle.expect("mininet>")
1207
1208 self.handle.sendline("py [ host.name for host in net.hosts ]")
1209 self.handle.expect("mininet>")
admin2a9548d2014-06-17 14:08:07 -07001210
andrewonlab3f0a4af2014-10-17 12:25:14 -04001211 handle_py = self.handle.before
1212 handle_py = handle_py.split("]\r\n",1)[1]
1213 handle_py = handle_py.rstrip()
admin2a9548d2014-06-17 14:08:07 -07001214
andrewonlab3f0a4af2014-10-17 12:25:14 -04001215 self.handle.sendline("")
1216 self.handle.expect("mininet>")
admin2a9548d2014-06-17 14:08:07 -07001217
andrewonlab3f0a4af2014-10-17 12:25:14 -04001218 host_str = handle_py.replace("]", "")
1219 host_str = host_str.replace("'", "")
1220 host_str = host_str.replace("[", "")
1221 host_list = host_str.split(",")
1222
1223 return host_list
adminbae64d82013-08-01 10:50:15 -07001224
1225if __name__ != "__main__":
1226 import sys
1227 sys.modules[__name__] = MininetCliDriver()
admin2a9548d2014-06-17 14:08:07 -07001228