blob: ffb5151ea32574785c010b40aaf41cae42e7f3a6 [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
shahshreya4d79aab2014-11-07 15:20:41 -0800419 def run_optical_mn_script(self):
420 self.handle.sendline("")
421 self.handle.expect("\$")
422 self.handle.sendline("cd ~")
423 self.handle.expect("\$")
424 self.handle.sendline("sudo python optical.py")
425 self.handle.expect("\$")
426
427
admin680b78c2014-08-08 11:46:45 -0700428 def del_switch(self,sw):
429 self.handle.sendline("")
430 self.handle.expect("\$")
431 self.handle.sendline("sudo ovs-vsctl del-br "+sw)
432 self.handle.expect("\$")
433 return main.TRUE
admin2a9548d2014-06-17 14:08:07 -0700434
admin680b78c2014-08-08 11:46:45 -0700435 def add_switch(self,sw):
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700436 #FIXME: Remove hardcoded number of ports
admin680b78c2014-08-08 11:46:45 -0700437 self.handle.sendline("")
438 self.handle.expect("\$")
439 self.handle.sendline("sudo ovs-vsctl add-br "+sw)
440 self.handle.expect("\$")
441 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth1")
442 self.handle.expect("\$")
443 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth2")
444 self.handle.expect("\$")
445 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth3")
446 self.handle.expect("\$")
447 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth4")
448 self.handle.expect("\$")
449 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth5")
450 self.handle.expect("\$")
451 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth6")
452 self.handle.expect("\$")
453 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth7")
454 self.handle.expect("\$")
455 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth8")
456 self.handle.expect("\$")
457 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth9")
458 self.handle.expect("\$")
459 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth10")
460 self.handle.expect("\$")
461 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth11")
462 self.handle.expect("\$")
463 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth12")
464 self.handle.expect("\$")
465 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth13")
466 self.handle.expect("\$")
467 self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth14")
468 self.handle.expect("\$")
admin2a9548d2014-06-17 14:08:07 -0700469
adminbae64d82013-08-01 10:50:15 -0700470
471 def disconnect(self):
adminaeedddd2013-08-02 15:14:15 -0700472 '''
473 Called at the end of the test to disconnect the handle.
474 '''
adminbae64d82013-08-01 10:50:15 -0700475 response = ''
476 #print "Disconnecting Mininet"
477 if self.handle:
478 self.handle.sendline("exit")
479 self.handle.expect("exit")
480 self.handle.expect("(.*)")
481 response = self.handle.before
482
483 else :
484 main.log.error("Connection failed to the host")
485 response = main.FALSE
486 return response
487
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700488 def get_flowTable(self, protoVersion, sw):
santhosh9da93892014-07-28 14:11:19 -0700489 self.handle.sendline("cd")
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700490 #self.handle.expect(["\$",pexpect.EOF,pexpect.TIMEOUT])
491 print "cd expect status: "
492 print self.handle.expect(["\$",pexpect.EOF,pexpect.TIMEOUT])
Jon Hall6c794f32014-08-14 13:33:13 -0700493 #TODO: Write seperate versions of the function for this, possibly a string that tells it which switch is in use?
494 #For 1.0 version of OVS
495 #command = "sudo ovs-ofctl dump-flows " + sw + " | awk '{OFS=\",\" ; print $1 $6 $7 }' |sort -n -k1"
496 #for 1.3 version of OVS
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700497 #command = "sudo ovs-ofctl dump-flows " + sw + " | awk '{OFS=\",\" ; print $1 $3 $7 $8}' |sort -n -k1"
498 #NOTE: Use format to force consistent flow table output across versions
499 if protoVersion==1.0:
500 command = "sudo ovs-ofctl dump-flows " + sw + " -F OpenFlow10-table_id | awk '{OFS=\",\" ; print $1 $3 $6 $7 $8}' |sort -n -k1"
501 self.handle.sendline(command)
502 self.handle.expect(["sort -n -k1",pexpect.EOF,pexpect.TIMEOUT])
503 self.handle.expect(["OFPST_FLOW",pexpect.EOF,pexpect.TIMEOUT])
504 response = self.handle.before
505 #print "response=", response
506 return response
507 elif protoVersion==1.3:
508 command = "sudo ovs-ofctl dump-flows " + sw + " -O OpenFlow13 | awk '{OFS=\",\" ; print $1 $3 $6 $7}' |sort -n -k1"
509 self.handle.sendline(command)
510 #print "ovs-vsctl Command sent status."
511 #self.handle.expect(["sort -n -k1",pexpect.EOF,pexpect.TIMEOUT])
512 #print "sort return status: "
513 #print self.handle.expect(["sort -n -k1",pexpect.EOF,pexpect.TIMEOUT])
514 #print self.handle.before
515 self.handle.expect(["OFPST_FLOW",pexpect.EOF,pexpect.TIMEOUT])
516 #print "OFPST_FLOW expected status: "
517 #print self.handle.expect(["OFPST_FLOW",pexpect.EOF,pexpect.TIMEOUT])
518 #print self.handle.before
519 response = self.handle.before
520 #print "response=", response
521 return response
santhosh19fd8032014-07-29 11:56:17 -0700522
523
524 def flow_comp(self,flow1,flow2):
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700525 #print "Inside flow compare function"
526 #print "Flow1 Table:"
527 #for flow in flow1:
528 #print flow1
529 #print "Flow2 Table"
530 #for flow in flow2:
531 #print flow2
532
santhosh19fd8032014-07-29 11:56:17 -0700533 if flow1==flow2:
534 return main.TRUE
535 else:
Jon Hall6c794f32014-08-14 13:33:13 -0700536 main.log.info("Flow tables do not match, printing tables:")
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700537 #main.log.info("Flow Table 1:")
538 #main.log.info(flow1)
539 #main.log.info("Flow Table 2:")
540 #main.log.info(flow2)
santhosh19fd8032014-07-29 11:56:17 -0700541 return main.FALSE
542
shahshreyaf4d4d0c2014-10-10 12:11:10 -0700543 def setIpTablesOUTPUT(self, dst_ip, dst_port, action='add', packet_type='tcp',rule='DROP'):
544 '''
545 Description:
546 add or remove iptables rule to DROP (default) packets from specific IP and PORT
547 Usage:
548 * specify action ('add' or 'remove')
549 when removing, pass in the same argument as you would add. It will
550 delete that specific rule.
551 * specify the destination ip to block with dst_ip
552 * specify destination port to block to dst_port
553 * optional packet type to block (default tcp)
554 * optional iptables rule (default DROP)
555 WARNING:
556 * This function uses root privilege iptables command which may result in
557 unwanted network errors. USE WITH CAUTION
558 '''
559 import re
560 import time
561
562 #NOTE*********
563 # The strict checking methods of this driver function is intentional
564 # to discourage any misuse or error of iptables, which can cause
565 # severe network errors
566 #*************
567
568 #NOTE: Sleep needed to give some time for rule to be added and registered
569 # to the instance
570 time.sleep(5)
571
572 action_type = action.lower()
573 if action_type != 'add' and action_type !='remove':
574 main.log.error("Invalid action type. 'add' or 'remove' table rule")
575 if rule != 'DROP' and rule != 'ACCEPT' and rule != 'LOG':
576 #NOTE: Currently only supports rules DROP, ACCEPT, and LOG
577 main.log.error("Invalid rule. 'DROP' or 'ACCEPT' or 'LOG' only.")
578 return
579 return
580 else:
581
582 #If there is no existing rule in the iptables, we will see an
583 #'iptables:'... message. We expect to see this message.
584 #Otherwise, if there IS an existing rule, we will get the prompt
585 # back, hence why we expect $ for remove type. We want to remove
586 # an already existing rule
587
588 if action_type == 'add':
589 #NOTE: "iptables:" expect is a result of return from the command
590 # iptables -C ...
591 # Any changes by the iptables command return string
592 # will result in failure of the function. (deemed unlikely
593 # at the time of writing this function)
594 #Check for existing rules on current input
595 self.handle.sendline("")
596 self.handle.expect("\$")
597 self.handle.sendline("sudo iptables -C OUTPUT -p "+str(packet_type)+
598 " -d "+ str(dst_ip)+" --dport "+str(dst_port)+" -j "+str(rule))
599 i = self.handle.expect(["iptables:", "\$"])
600 print i
601 print self.handle.before
602 print "after: "
603 print self.handle.after
604
605 elif action_type == 'remove':
606 #Check for existing rules on current input
607 self.handle.sendline("")
608 self.handle.expect("\$")
609 self.handle.sendline("sudo iptables -C OUTPUT -p "+str(packet_type)+
610 " -d "+ str(dst_ip)+" --dport "+str(dst_port)+" -j "+str(rule))
611 self.handle.expect("\$")
612 print "before: "
613 print self.handle.before
614 actual_string = self.handle.after
615 expect_string = "iptables:"
616 print "Actual String:"
617 print actual_string
618
619 if re.search(expect_string, actual_string):
620 match_result = main.TRUE
621 else:
622 match_result = main.FALSE
623 #If match_result is main.TRUE, it means there is no matching rule.
624
625 #If tables does not exist and expected prompt is returned, go ahead and
626 #add iptables rule
627 if match_result == main.TRUE:
628 #Ensure action type is add
629 if action_type == 'add':
630 #-A is the 'append' action of iptables
631 action_add = '-A'
632 try:
633 self.handle.sendline("")
634 self.handle.sendline("sudo iptables "+action_add+" OUTPUT -p "+str(packet_type)+
635 " -d "+ str(dst_ip)+" --dport "+str(dst_port)+" -j "+str(rule))
636
637 info_string = "Rules added to "+str(self.name)
638 info_string += "iptable rule added to block IP: "+str(dst_ip)
639 info_string += "Port: "+str(dst_port)+" Rule: "+str(rule)
640
641 main.log.info(info_string)
642
643 self.handle.expect(["\$",pexpect.EOF,pexpect.TIMEOUT])
644 except pexpect.TIMEOUT:
645 main.log.error(self.name + ": Timeout exception in setIpTables function")
646 except:
647 main.log.error( traceback.print_exc())
648 main.cleanup()
649 main.exit()
650 else:
651 main.log.error("Given rule already exists, but attempted to add it")
652 #If match_result is 0, it means there IS a matching rule provided
653 elif match_result == main.FALSE:
654 #Ensure action type is remove
655 if action_type == 'remove':
656 #-D is the 'delete' rule of iptables
657 action_remove = '-D'
658 try:
659 self.handle.sendline("")
660 #Delete a specific rule specified into the function
661 self.handle.sendline("sudo iptables "+action_remove+" OUTPUT -p "+str(packet_type)+
662 " -d "+ str(dst_ip)+" --dport "+str(dst_port)+" -j "+str(rule))
663
664 info_string = "Rules removed from "+str(self.name)
665 info_string += " iptables rule removed from blocking IP: "+str(dst_ip)
666 info_string += " Port: "+str(dst_port)+" Rule: "+str(rule)
667
668 main.log.info(info_string)
669
670 self.handle.expect(["\$",pexpect.EOF,pexpect.TIMEOUT])
671 except pexpect.TIMEOUT:
672 main.log.error(self.name + ": Timeout exception in setIpTables function")
673 except:
674 main.log.error( traceback.print_exc())
675 main.cleanup()
676 main.exit()
677 else:
678 main.log.error("Given rule does not exist, but attempted to remove it")
679 else:
680 #NOTE: If a bad usage of this function occurs, exit the entire test
681 main.log.error("Bad rule given for iptables. Exiting...")
682 main.cleanup()
683 main.exit()
684
685
adminbae64d82013-08-01 10:50:15 -0700686if __name__ != "__main__":
687 import sys
688 sys.modules[__name__] = RemoteMininetDriver()