blob: 2acddb49ba9c478ae45db024f96a716447672776 [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("../")
34from drivers.common.cli.emulatordriver import Emulator
35from drivers.common.clidriver import CLI
36from time import time
37
38class RemoteMininetDriver(Emulator):
39 '''
adminaeedddd2013-08-02 15:14:15 -070040 RemoteMininetCliDriver is the basic driver which will handle the Mininet functions
41 The main different between this and the MininetCliDriver is that this one does not build the mininet.
42 It assumes that there is already a mininet running on the target.
adminbae64d82013-08-01 10:50:15 -070043 '''
44 def __init__(self):
45 super(Emulator, self).__init__()
46 self.handle = self
47 self.wrapped = sys.modules[__name__]
48 self.flag = 0
49
50 def connect(self, **connectargs):
51 #,user_name, ip_address, pwd,options):
52 # Here the main is the TestON instance after creating all the log handles.
53 for key in connectargs:
54 vars(self)[key] = connectargs[key]
55
56 self.name = self.options['name']
57 self.handle = super(RemoteMininetDriver, self).connect(user_name = self.user_name, ip_address = self.ip_address,port = None, pwd = self.pwd)
58
59 self.ssh_handle = self.handle
60
61 # Copying the readme file to process the
62 if self.handle :
63 return main.TRUE
64
65 else :
66 main.log.error("Connection failed to the host "+self.user_name+"@"+self.ip_address)
67 main.log.error("Failed to connect to the Mininet")
68 return main.FALSE
admin98ad0092014-07-23 16:51:07 -070069
70#*********************************************************************************************
71#*********************************************************************************************
72# checkForLoss will determine if any of the pings had any packets lost during the course of
73# the pingLong.
74#*********************************************************************************************
75#*********************************************************************************************
76
admin2580a0e2014-07-29 11:24:34 -070077 def checkForLoss(self, pingList):
Jon Hall6c794f32014-08-14 13:33:13 -070078 '''
79 Returns main.FALSE for 0% packet loss and
80 Returns main.ERROR if "found multiple mininet" is found and
81 Returns main.TRUE else
82 '''
admin98ad0092014-07-23 16:51:07 -070083 import os
admin2580a0e2014-07-29 11:24:34 -070084 self.handle.sendline("")
85 self.handle.expect("\$")
86 self.handle.sendline("cat " + pingList)
87 self.handle.expect(pingList)
88 self.handle.expect("\$")
89 outputs = self.handle.before + self.handle.after
90 if re.search(" 0% packet loss",outputs):
admin98ad0092014-07-23 16:51:07 -070091 return main.FALSE
admin2580a0e2014-07-29 11:24:34 -070092 elif re.search("found multiple mininet",outputs):
93 return main.ERROR
shahshreyaf4d4d0c2014-10-10 12:11:10 -070094 else:
95 print outputs
96 return main.TRUE
97
admin98ad0092014-07-23 16:51:07 -070098
99
adminbae64d82013-08-01 10:50:15 -0700100 def pingLong(self,**pingParams):
adminaeedddd2013-08-02 15:14:15 -0700101 '''
102 Starts a continuous ping on the mininet host outputing to a file in the /tmp dir.
103 '''
Jon Hall6c794f32014-08-14 13:33:13 -0700104 self.handle.sendline("")
105 self.handle.expect("\$")
admin98ad0092014-07-23 16:51:07 -0700106 args = utilities.parse_args(["SRC","TARGET","PINGTIME"],**pingParams)
Jon Hall6c794f32014-08-14 13:33:13 -0700107 precmd = "sudo rm /tmp/ping." + args["SRC"]
admin530b4c92013-08-14 16:54:35 -0700108 self.execute(cmd=precmd,prompt="(.*)",timeout=10)
Jon Hall6c794f32014-08-14 13:33:13 -0700109 command = "sudo mininet/util/m " + args["SRC"] + " ping "+args ["TARGET"]+" -i .2 -w " + str(args['PINGTIME']) + " > /tmp/ping." + args["SRC"] + " &"
adminbae64d82013-08-01 10:50:15 -0700110 main.log.info( command )
111 self.execute(cmd=command,prompt="(.*)",timeout=10)
Jon Hall6c794f32014-08-14 13:33:13 -0700112 self.handle.sendline("")
113 self.handle.expect("\$")
adminbae64d82013-08-01 10:50:15 -0700114 return main.TRUE
115
116 def pingstatus(self,**pingParams):
adminaeedddd2013-08-02 15:14:15 -0700117 '''
118 Tails the respective ping output file and check that there is a moving "64 bytes"
119 '''
Jon Hall6c794f32014-08-14 13:33:13 -0700120 self.handle.sendline("")
121 self.handle.expect("\$")
adminbae64d82013-08-01 10:50:15 -0700122 args = utilities.parse_args(["SRC"],**pingParams)
123 self.handle.sendline("tail /tmp/ping." + args["SRC"])
124 self.handle.expect("tail")
125 self.handle.expect("\$")
126 result = self.handle.before + self.handle.after
Jon Hall6c794f32014-08-14 13:33:13 -0700127 self.handle.sendline("")
128 self.handle.expect("\$")
adminbae64d82013-08-01 10:50:15 -0700129 if re.search('Unreachable', result ):
130 main.log.info("Unreachable found in ping logs...")
131 return main.FALSE
132 elif re.search('64\sbytes', result):
133 main.log.info("Pings look good")
134 return main.TRUE
135 else:
136 main.log.info("No, or faulty ping data...")
137 return main.FALSE
138
Jon Hall6c794f32014-08-14 13:33:13 -0700139 def pingKill(self, testONUser, testONIP):
adminaeedddd2013-08-02 15:14:15 -0700140 '''
141 Kills all continuous ping processes.
142 Then copies all the ping files to the TestStation.
143 '''
144 import time
Jon Hall6c794f32014-08-14 13:33:13 -0700145 self.handle.sendline("")
146 self.handle.expect("\$")
admin2580a0e2014-07-29 11:24:34 -0700147 command = "sudo kill -SIGINT `pgrep ping`"
adminbae64d82013-08-01 10:50:15 -0700148 main.log.info( command )
149 self.execute(cmd=command,prompt="(.*)",timeout=10)
Jon Hall6c794f32014-08-14 13:33:13 -0700150 #Commenting out in case TestON and MN are on the same machine. scp overrights the file anyways
151 #main.log.info( "Removing old ping data" )
152 #command = "rm /tmp/ping.*"
153 #os.popen(command)
154 #time.sleep(2)
adminbae64d82013-08-01 10:50:15 -0700155 main.log.info( "Transferring ping files to TestStation" )
Jon Hall6c794f32014-08-14 13:33:13 -0700156 command = "scp /tmp/ping.* "+ str(testONUser) + "@" + str(testONIP) + ":/tmp/"
adminbae64d82013-08-01 10:50:15 -0700157 self.execute(cmd=command,prompt="100%",timeout=20)
Jon Hall6c794f32014-08-14 13:33:13 -0700158 self.handle.sendline("")
159 self.handle.expect("\$")
admin2580a0e2014-07-29 11:24:34 -0700160 return main.TRUE
161
162 def pingLongKill(self):
163 import time
Jon Hall6c794f32014-08-14 13:33:13 -0700164 self.handle.sendline("")
165 self.handle.expect("\$")
admin2580a0e2014-07-29 11:24:34 -0700166 command = "sudo kill -SIGING `pgrep ping`"
167 main.log.info(command)
168 self.execute(cmd=command,prompt="(.*)",timeout=10)
Jon Hall6c794f32014-08-14 13:33:13 -0700169 self.handle.sendline("")
170 self.handle.expect("\$")
adminbae64d82013-08-01 10:50:15 -0700171 return main.TRUE
172
173 def pingHost(self,**pingParams):
adminaeedddd2013-08-02 15:14:15 -0700174 '''
175 Pings between two hosts on remote mininet
176 '''
Jon Hall6c794f32014-08-14 13:33:13 -0700177 self.handle.sendline("")
178 self.handle.expect("\$")
adminbae64d82013-08-01 10:50:15 -0700179 args = utilities.parse_args(["SRC","TARGET"],**pingParams)
180 command = "mininet/util/m " + args["SRC"] + " ping "+args ["TARGET"]+" -c 4 -W 1 -i .2"
181 main.log.info ( command )
182 response = self.execute(cmd=command,prompt="rtt",timeout=10 )
Jon Hall6c794f32014-08-14 13:33:13 -0700183 self.handle.sendline("")
184 self.handle.expect("\$")
adminbae64d82013-08-01 10:50:15 -0700185 if utilities.assert_matches(expect=',\s0\%\spacket\sloss',actual=response,onpass="No Packet loss",onfail="Host is not reachable"):
186 main.log.info("NO PACKET LOSS, HOST IS REACHABLE")
187 main.last_result = main.TRUE
188 return main.TRUE
189 else :
190 main.log.error("PACKET LOST, HOST IS NOT REACHABLE")
191 main.last_result = main.FALSE
192 return main.FALSE
193
194
195 def checknum(self,num):
196 '''
adminaeedddd2013-08-02 15:14:15 -0700197 Verifies the correct number of switches are running
adminbae64d82013-08-01 10:50:15 -0700198 '''
199 if self.handle :
200 self.handle.sendline("")
201 self.handle.expect("\$")
202 self.handle.sendline('ifconfig -a | grep "sw.. " | wc -l')
203 self.handle.expect("wc")
204 self.handle.expect("\$")
205 response = self.handle.before
206 self.handle.sendline('ps -ef | grep "bash -ms mininet:sw" | grep -v color | wc -l')
207 self.handle.expect("color")
208 self.handle.expect("\$")
209 response2 = self.handle.before
210
211 if re.search(num, response):
212 if re.search(num, response2):
213 return main.TRUE
214 else:
215 return main.FALSE
216 else:
217 return main.FALSE
218 else :
219 main.log.error("Connection failed to the host")
220
221 def ctrl_none(self):
adminaeedddd2013-08-02 15:14:15 -0700222 '''
223 Sets all the switches to no controllers.
224 '''
adminbae64d82013-08-01 10:50:15 -0700225 self.execute(cmd="~/ONOS/scripts/test-ctrl-none.sh", prompt="\$",timeout=10)
226
227 def ctrl_one(self, ip):
adminaeedddd2013-08-02 15:14:15 -0700228 '''
229 Sets all the switches to point to the supplied IP
230 '''
adminbae64d82013-08-01 10:50:15 -0700231 self.execute(cmd="~/ONOS/scripts/test-ctrl-one.sh "+ip, prompt="\$",timeout=10)
232
233 def ctrl_local(self):
adminaeedddd2013-08-02 15:14:15 -0700234 '''
235 Sets all the switches to point to the Controller on the same machine that they are running on.
236 '''
adminbae64d82013-08-01 10:50:15 -0700237 self.execute(cmd="~/ONOS/scripts/test-ctrl-local.sh ", prompt="\$",timeout=10)
238
239 # def verifySSH(self,**connectargs):
240 # response = self.execute(cmd="h1 /usr/sbin/sshd -D&",prompt="mininet>",timeout=10)
241 # response = self.execute(cmd="h4 /usr/sbin/sshd -D&",prompt="mininet>",timeout=10)
242 # for key in connectargs:
243 # vars(self)[key] = connectargs[key]
244 # response = self.execute(cmd="xterm h1 h4 ",prompt="mininet>",timeout=10)
245 # import time
246 # time.sleep(20)
247 # if self.flag == 0:
248 # self.flag = 1
249 # return main.FALSE
250 # else :
251 # return main.TRUE
252 #
253 # def getMacAddress(self,host):
254 # '''
255 # Verifies the host's ip configured or not.
256 # '''
257 # if self.handle :
258 # response = self.execute(cmd=host+" ifconfig",prompt="mininet>",timeout=10)
259
260 # pattern = "HWaddr\s(((\d|\w)+:)+(\d|\w))"
261 # mac_address_search = re.search(pattern, response)
262 # main.log.info("Mac-Address of Host "+host +" is "+mac_address_search.group(1))
263 # return mac_address_search.group(1)
264 # else :
265 # main.log.error("Connection failed to the host")
266 # def getIPAddress(self,host):
267 # '''
268 # Verifies the host's ip configured or not.
269 # '''
270 # if self.handle :
271 # response = self.execute(cmd=host+" ifconfig",prompt="mininet>",timeout=10)
272
273 # pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)"
274 # ip_address_search = re.search(pattern, response)
275 # main.log.info("IP-Address of Host "+host +" is "+ip_address_search.group(1))
276 # return ip_address_search.group(1)
277 # else :
278 # main.log.error("Connection failed to the host")
279 #
280 # def dump(self):
281 # main.log.info("Dump node info")
282 # self.execute(cmd = 'dump',prompt = 'mininet>',timeout = 10)
283 # return main.TRUE
284 #
285 # def intfs(self):
286 # main.log.info("List interfaces")
287 # self.execute(cmd = 'intfs',prompt = 'mininet>',timeout = 10)
288 # return main.TRUE
289 #
290 # def net(self):
291 # main.log.info("List network connections")
292 # self.execute(cmd = 'net',prompt = 'mininet>',timeout = 10)
293 # return main.TRUE
294 #
295 # def iperf(self):
296 # main.log.info("Simple iperf TCP test between two (optionally specified) hosts")
297 # self.execute(cmd = 'iperf',prompt = 'mininet>',timeout = 10)
298 # return main.TRUE
299 #
300 # def iperfudp(self):
301 # main.log.info("Simple iperf TCP test between two (optionally specified) hosts")
302 # self.execute(cmd = 'iperfudp',prompt = 'mininet>',timeout = 10)
303 # return main.TRUE
304 #
305 # def nodes(self):
306 # main.log.info("List all nodes.")
307 # self.execute(cmd = 'nodes',prompt = 'mininet>',timeout = 10)
308 # return main.TRUE
309 #
310 # def pingpair(self):
311 # main.log.infoe("Ping between first two hosts")
312 # self.execute(cmd = 'pingpair',prompt = 'mininet>',timeout = 20)
313 #
314 # if utilities.assert_matches(expect='0% packet loss',actual=response,onpass="No Packet loss",onfail="Hosts not reachable"):
315 # main.log.info("Ping between two hosts SUCCESS")
316 # main.last_result = main.TRUE
317 # return main.TRUE
318 # else :
319 # main.log.error("PACKET LOST, HOSTS NOT REACHABLE")
320 # main.last_result = main.FALSE
321 # return main.FALSE
322 #
323 # def link(self,**linkargs):
324 # '''
325 # Bring link(s) between two nodes up or down
326 # '''
327 # main.log.info('Bring link(s) between two nodes up or down')
328 # args = utilities.parse_args(["END1","END2","OPTION"],**linkargs)
329 # end1 = args["END1"] if args["END1"] != None else ""
330 # end2 = args["END2"] if args["END2"] != None else ""
331 # option = args["OPTION"] if args["OPTION"] != None else ""
332 # command = "link "+str(end1) + " " + str(end2)+ " " + str(option)
333 # response = self.execute(cmd=command,prompt="mininet>",timeout=10)
334 # return main.TRUE
335 #
336
337 # def dpctl(self,**dpctlargs):
338 # '''
339 # Run dpctl command on all switches.
340 # '''
341 # main.log.info('Run dpctl command on all switches')
342 # args = utilities.parse_args(["CMD","ARGS"],**dpctlargs)
343 # cmd = args["CMD"] if args["CMD"] != None else ""
344 # cmdargs = args["ARGS"] if args["ARGS"] != None else ""
345 # command = "dpctl "+cmd + " " + str(cmdargs)
346 # response = self.execute(cmd=command,prompt="mininet>",timeout=10)
347 # return main.TRUE
348 #
349 #
350 # def get_version(self):
351 # file_input = path+'/lib/Mininet/INSTALL'
352 # version = super(Mininet, self).get_version()
353 # pattern = 'Mininet\s\w\.\w\.\w\w*'
354 # for line in open(file_input,'r').readlines():
355 # result = re.match(pattern, line)
356 # if result:
357 # version = result.group(0)
358 #
359 #
360 # return version
admin2a9548d2014-06-17 14:08:07 -0700361 def start_tcpdump(self, filename, intf = "eth0", port = "port 6633"):
362 '''
363 Runs tpdump on an intferface and saves the file
364 intf can be specified, or the default eth0 is used
365 '''
366 try:
367 self.handle.sendline("")
368 self.handle.sendline("sudo tcpdump -n -i "+ intf + " " + port + " -w " + filename.strip() + " &")
369 self.handle.sendline("")
370 self.handle.sendline("")
371 i=self.handle.expect(['No\ssuch\device','listening\son',pexpect.TIMEOUT,"\$"],timeout=10)
372 main.log.warn(self.handle.before + self.handle.after)
373 if i == 0:
374 main.log.error(self.name + ": tcpdump - No such device exists. tcpdump attempted on: " + intf)
375 return main.FALSE
376 elif i == 1:
377 main.log.info(self.name + ": tcpdump started on " + intf)
378 return main.TRUE
379 elif i == 2:
380 main.log.error(self.name + ": tcpdump command timed out! Check interface name, given interface was: " + intf)
381 return main.FALSE
382 elif i ==3:
383 main.log.info(self.name +": " + self.handle.before)
384 return main.TRUE
385 else:
386 main.log.error(self.name + ": tcpdump - unexpected response")
387 return main.FALSE
388 except pexpect.EOF:
389 main.log.error(self.name + ": EOF exception found")
390 main.log.error(self.name + ": " + self.handle.before)
391 main.cleanup()
392 main.exit()
393 except:
394 main.log.info(self.name + ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
395 main.log.error( traceback.print_exc() )
396 main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
397 main.cleanup()
398 main.exit()
399
400 def stop_tcpdump(self):
401 "pkills tcpdump"
402 try:
403 self.handle.sendline("sudo pkill tcpdump")
404 self.handle.sendline("")
405 self.handle.sendline("")
406 self.handle.expect("\$")
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()
412 except:
413 main.log.info(self.name + ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
414 main.log.error( traceback.print_exc() )
415 main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
416 main.cleanup()
417 main.exit()
418
admin680b78c2014-08-08 11:46:45 -0700419 def del_switch(self,sw):
420 self.handle.sendline("")
421 self.handle.expect("\$")
422 self.handle.sendline("sudo ovs-vsctl del-br "+sw)
423 self.handle.expect("\$")
424 return main.TRUE
admin2a9548d2014-06-17 14:08:07 -0700425
admin680b78c2014-08-08 11:46:45 -0700426 def add_switch(self,sw):
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700427 #FIXME: Remove hardcoded number of ports
admin680b78c2014-08-08 11:46:45 -0700428 self.handle.sendline("")
429 self.handle.expect("\$")
430 self.handle.sendline("sudo ovs-vsctl add-br "+sw)
431 self.handle.expect("\$")
432 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth1")
433 self.handle.expect("\$")
434 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth2")
435 self.handle.expect("\$")
436 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth3")
437 self.handle.expect("\$")
438 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth4")
439 self.handle.expect("\$")
440 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth5")
441 self.handle.expect("\$")
442 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth6")
443 self.handle.expect("\$")
444 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth7")
445 self.handle.expect("\$")
446 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth8")
447 self.handle.expect("\$")
448 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth9")
449 self.handle.expect("\$")
450 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth10")
451 self.handle.expect("\$")
452 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth11")
453 self.handle.expect("\$")
454 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth12")
455 self.handle.expect("\$")
456 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth13")
457 self.handle.expect("\$")
458 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth14")
459 self.handle.expect("\$")
admin2a9548d2014-06-17 14:08:07 -0700460
adminbae64d82013-08-01 10:50:15 -0700461
462 def disconnect(self):
adminaeedddd2013-08-02 15:14:15 -0700463 '''
464 Called at the end of the test to disconnect the handle.
465 '''
adminbae64d82013-08-01 10:50:15 -0700466 response = ''
467 #print "Disconnecting Mininet"
468 if self.handle:
469 self.handle.sendline("exit")
470 self.handle.expect("exit")
471 self.handle.expect("(.*)")
472 response = self.handle.before
473
474 else :
475 main.log.error("Connection failed to the host")
476 response = main.FALSE
477 return response
478
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700479 def get_flowTable(self, protoVersion, sw):
santhosh9da93892014-07-28 14:11:19 -0700480 self.handle.sendline("cd")
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700481 #self.handle.expect(["\$",pexpect.EOF,pexpect.TIMEOUT])
482 print "cd expect status: "
483 print self.handle.expect(["\$",pexpect.EOF,pexpect.TIMEOUT])
Jon Hall6c794f32014-08-14 13:33:13 -0700484 #TODO: Write seperate versions of the function for this, possibly a string that tells it which switch is in use?
485 #For 1.0 version of OVS
486 #command = "sudo ovs-ofctl dump-flows " + sw + " | awk '{OFS=\",\" ; print $1 $6 $7 }' |sort -n -k1"
487 #for 1.3 version of OVS
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700488 #command = "sudo ovs-ofctl dump-flows " + sw + " | awk '{OFS=\",\" ; print $1 $3 $7 $8}' |sort -n -k1"
489 #NOTE: Use format to force consistent flow table output across versions
490 if protoVersion==1.0:
491 command = "sudo ovs-ofctl dump-flows " + sw + " -F OpenFlow10-table_id | awk '{OFS=\",\" ; print $1 $3 $6 $7 $8}' |sort -n -k1"
492 self.handle.sendline(command)
493 self.handle.expect(["sort -n -k1",pexpect.EOF,pexpect.TIMEOUT])
494 self.handle.expect(["OFPST_FLOW",pexpect.EOF,pexpect.TIMEOUT])
495 response = self.handle.before
496 #print "response=", response
497 return response
498 elif protoVersion==1.3:
499 command = "sudo ovs-ofctl dump-flows " + sw + " -O OpenFlow13 | awk '{OFS=\",\" ; print $1 $3 $6 $7}' |sort -n -k1"
500 self.handle.sendline(command)
501 #print "ovs-vsctl Command sent status."
502 #self.handle.expect(["sort -n -k1",pexpect.EOF,pexpect.TIMEOUT])
503 #print "sort return status: "
504 #print self.handle.expect(["sort -n -k1",pexpect.EOF,pexpect.TIMEOUT])
505 #print self.handle.before
506 self.handle.expect(["OFPST_FLOW",pexpect.EOF,pexpect.TIMEOUT])
507 #print "OFPST_FLOW expected status: "
508 #print self.handle.expect(["OFPST_FLOW",pexpect.EOF,pexpect.TIMEOUT])
509 #print self.handle.before
510 response = self.handle.before
511 #print "response=", response
512 return response
santhosh19fd8032014-07-29 11:56:17 -0700513
514
515 def flow_comp(self,flow1,flow2):
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700516 #print "Inside flow compare function"
517 #print "Flow1 Table:"
518 #for flow in flow1:
519 #print flow1
520 #print "Flow2 Table"
521 #for flow in flow2:
522 #print flow2
523
santhosh19fd8032014-07-29 11:56:17 -0700524 if flow1==flow2:
525 return main.TRUE
526 else:
Jon Hall6c794f32014-08-14 13:33:13 -0700527 main.log.info("Flow tables do not match, printing tables:")
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700528 #main.log.info("Flow Table 1:")
529 #main.log.info(flow1)
530 #main.log.info("Flow Table 2:")
531 #main.log.info(flow2)
santhosh19fd8032014-07-29 11:56:17 -0700532 return main.FALSE
533
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700534 def setIpTablesOUTPUT(self, dst_ip, dst_port, action='add', packet_type='tcp',rule='DROP'):
535 '''
536 Description:
537 add or remove iptables rule to DROP (default) packets from specific IP and PORT
538 Usage:
539 * specify action ('add' or 'remove')
540 when removing, pass in the same argument as you would add. It will
541 delete that specific rule.
542 * specify the destination ip to block with dst_ip
543 * specify destination port to block to dst_port
544 * optional packet type to block (default tcp)
545 * optional iptables rule (default DROP)
546 WARNING:
547 * This function uses root privilege iptables command which may result in
548 unwanted network errors. USE WITH CAUTION
549 '''
550 import re
551 import time
552
553 #NOTE*********
554 # The strict checking methods of this driver function is intentional
555 # to discourage any misuse or error of iptables, which can cause
556 # severe network errors
557 #*************
558
559 #NOTE: Sleep needed to give some time for rule to be added and registered
560 # to the instance
561 time.sleep(5)
562
563 action_type = action.lower()
564 if action_type != 'add' and action_type !='remove':
565 main.log.error("Invalid action type. 'add' or 'remove' table rule")
566 if rule != 'DROP' and rule != 'ACCEPT' and rule != 'LOG':
567 #NOTE: Currently only supports rules DROP, ACCEPT, and LOG
568 main.log.error("Invalid rule. 'DROP' or 'ACCEPT' or 'LOG' only.")
569 return
570 return
571 else:
572
573 #If there is no existing rule in the iptables, we will see an
574 #'iptables:'... message. We expect to see this message.
575 #Otherwise, if there IS an existing rule, we will get the prompt
576 # back, hence why we expect $ for remove type. We want to remove
577 # an already existing rule
578
579 if action_type == 'add':
580 #NOTE: "iptables:" expect is a result of return from the command
581 # iptables -C ...
582 # Any changes by the iptables command return string
583 # will result in failure of the function. (deemed unlikely
584 # at the time of writing this function)
585 #Check for existing rules on current input
586 self.handle.sendline("")
587 self.handle.expect("\$")
588 self.handle.sendline("sudo iptables -C OUTPUT -p "+str(packet_type)+
589 " -d "+ str(dst_ip)+" --dport "+str(dst_port)+" -j "+str(rule))
590 i = self.handle.expect(["iptables:", "\$"])
591 print i
592 print self.handle.before
593 print "after: "
594 print self.handle.after
595
596 elif action_type == 'remove':
597 #Check for existing rules on current input
598 self.handle.sendline("")
599 self.handle.expect("\$")
600 self.handle.sendline("sudo iptables -C OUTPUT -p "+str(packet_type)+
601 " -d "+ str(dst_ip)+" --dport "+str(dst_port)+" -j "+str(rule))
602 self.handle.expect("\$")
603 print "before: "
604 print self.handle.before
605 actual_string = self.handle.after
606 expect_string = "iptables:"
607 print "Actual String:"
608 print actual_string
609
610 if re.search(expect_string, actual_string):
611 match_result = main.TRUE
612 else:
613 match_result = main.FALSE
614 #If match_result is main.TRUE, it means there is no matching rule.
615
616 #If tables does not exist and expected prompt is returned, go ahead and
617 #add iptables rule
618 if match_result == main.TRUE:
619 #Ensure action type is add
620 if action_type == 'add':
621 #-A is the 'append' action of iptables
622 action_add = '-A'
623 try:
624 self.handle.sendline("")
625 self.handle.sendline("sudo iptables "+action_add+" OUTPUT -p "+str(packet_type)+
626 " -d "+ str(dst_ip)+" --dport "+str(dst_port)+" -j "+str(rule))
627
628 info_string = "Rules added to "+str(self.name)
629 info_string += "iptable rule added to block IP: "+str(dst_ip)
630 info_string += "Port: "+str(dst_port)+" Rule: "+str(rule)
631
632 main.log.info(info_string)
633
634 self.handle.expect(["\$",pexpect.EOF,pexpect.TIMEOUT])
635 except pexpect.TIMEOUT:
636 main.log.error(self.name + ": Timeout exception in setIpTables function")
637 except:
638 main.log.error( traceback.print_exc())
639 main.cleanup()
640 main.exit()
641 else:
642 main.log.error("Given rule already exists, but attempted to add it")
643 #If match_result is 0, it means there IS a matching rule provided
644 elif match_result == main.FALSE:
645 #Ensure action type is remove
646 if action_type == 'remove':
647 #-D is the 'delete' rule of iptables
648 action_remove = '-D'
649 try:
650 self.handle.sendline("")
651 #Delete a specific rule specified into the function
652 self.handle.sendline("sudo iptables "+action_remove+" OUTPUT -p "+str(packet_type)+
653 " -d "+ str(dst_ip)+" --dport "+str(dst_port)+" -j "+str(rule))
654
655 info_string = "Rules removed from "+str(self.name)
656 info_string += " iptables rule removed from blocking IP: "+str(dst_ip)
657 info_string += " Port: "+str(dst_port)+" Rule: "+str(rule)
658
659 main.log.info(info_string)
660
661 self.handle.expect(["\$",pexpect.EOF,pexpect.TIMEOUT])
662 except pexpect.TIMEOUT:
663 main.log.error(self.name + ": Timeout exception in setIpTables function")
664 except:
665 main.log.error( traceback.print_exc())
666 main.cleanup()
667 main.exit()
668 else:
669 main.log.error("Given rule does not exist, but attempted to remove it")
670 else:
671 #NOTE: If a bad usage of this function occurs, exit the entire test
672 main.log.error("Bad rule given for iptables. Exiting...")
673 main.cleanup()
674 main.exit()
675
676
adminbae64d82013-08-01 10:50:15 -0700677if __name__ != "__main__":
678 import sys
679 sys.modules[__name__] = RemoteMininetDriver()