Initial oftest skeleton with wrapper generators and pylibopenflow
diff --git a/tools/pylibopenflow/bin/cstruct2py-get-struct.py b/tools/pylibopenflow/bin/cstruct2py-get-struct.py
new file mode 100755
index 0000000..4b8a350
--- /dev/null
+++ b/tools/pylibopenflow/bin/cstruct2py-get-struct.py
@@ -0,0 +1,76 @@
+#!/usr/bin/env python2.5
+"""This script reads struct from C/C++ header file and output query
+
+Author ykk
+Date June 2009
+"""
+import sys
+import getopt
+import cheader
+import c2py
+
+
+def usage():
+ """Display usage
+ """
+ print "Usage "+sys.argv[0]+" <options> header_files... struct_name\n"+\
+ "Options:\n"+\
+ "-h/--help\n\tPrint this usage guide\n"+\
+ "-c/--cstruct\n\tPrint C struct\n"+\
+ "-n/--name\n\tPrint names of struct\n"+\
+ "-s/--size\n\tPrint size of struct\n"+\
+ ""
+
+#Parse options and arguments
+try:
+ opts, args = getopt.getopt(sys.argv[1:], "hcsn",
+ ["help","cstruct","size","names"])
+except getopt.GetoptError:
+ usage()
+ sys.exit(2)
+
+#Check there is at least 1 input file and struct name
+if (len(args) < 2):
+ usage()
+ sys.exit(2)
+
+#Parse options
+##Print C struct
+printc = False
+##Print names
+printname = False
+##Print size
+printsize = False
+for opt,arg in opts:
+ if (opt in ("-h","--help")):
+ usage()
+ sys.exit(0)
+ elif (opt in ("-s","--size")):
+ printsize = True
+ elif (opt in ("-c","--cstruct")):
+ printc = True
+ elif (opt in ("-n","--names")):
+ printname = True
+ else:
+ print "Unhandled option :"+opt
+ sys.exit(1)
+
+headerfile = cheader.cheaderfile(args[:-1])
+cstruct = headerfile.structs[args[-1].strip()]
+cs2p = c2py.cstruct2py()
+pattern = cs2p.get_pattern(cstruct)
+
+#Print C struct
+if (printc):
+ print cstruct
+
+#Print pattern
+print "Python pattern = "+pattern
+
+#Print name
+if (printname):
+ print cstruct.get_names()
+
+#Print size
+if (printsize):
+ print "Size = "+str(cs2p.get_size(pattern))
diff --git a/tools/pylibopenflow/bin/cstruct2py-pythonize.py b/tools/pylibopenflow/bin/cstruct2py-pythonize.py
new file mode 100755
index 0000000..47cbffb
--- /dev/null
+++ b/tools/pylibopenflow/bin/cstruct2py-pythonize.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python2.5
+"""This script reads struct
+
+Author ykk
+Date Jan 2010
+"""
+import sys
+import getopt
+import cpythonize
+import cheader
+
+def usage():
+ """Display usage
+ """
+ print "Usage "+sys.argv[0]+" <options> header_files... output_file\n"+\
+ "Options:\n"+\
+ "-h/--help\n\tPrint this usage guide\n"+\
+ ""
+
+#Parse options and arguments
+try:
+ opts, args = getopt.getopt(sys.argv[1:], "h",
+ ["help"])
+except getopt.GetoptError:
+ usage()
+ sys.exit(2)
+
+#Parse options
+for opt,arg in opts:
+ if (opt in ("-h","--help")):
+ usage()
+ sys.exit(0)
+ else:
+ print "Unhandled option :"+opt
+ sys.exit(2)
+
+#Check there is at least 1 input file with 1 output file
+if (len(args) < 2):
+ usage()
+ sys.exit(2)
+
+ch = cheader.cheaderfile(args[:-1])
+py = cpythonize.pythonizer(ch)
+fileRef = open(args[len(args)-1], "w")
+for l in py.pycode():
+ fileRef.write(l+"\n")
+fileRef.close()
+
diff --git a/tools/pylibopenflow/bin/cstruct2py-query-cheader.py b/tools/pylibopenflow/bin/cstruct2py-query-cheader.py
new file mode 100755
index 0000000..3d23ef0
--- /dev/null
+++ b/tools/pylibopenflow/bin/cstruct2py-query-cheader.py
@@ -0,0 +1,138 @@
+#!/usr/bin/env python2.5
+"""This script reads C/C++ header file and output query
+
+Author ykk
+Date June 2009
+"""
+import sys
+import getopt
+import cheader
+
+def usage():
+ """Display usage
+ """
+ print "Usage "+sys.argv[0]+" <options> header_file_1 header_file_2 ...\n"+\
+ "Options:\n"+\
+ "-h/--help\n\tPrint this usage guide\n"+\
+ "-E/--enums\n\tPrint all enumerations\n"+\
+ "-e/--enum\n\tPrint specified enumeration\n"+\
+ "-M/--macros\n\tPrint all macros\n"+\
+ "-m/--macro\n\tPrint value of macro\n"+\
+ "-S/--structs\n\tPrint all structs\n"+\
+ "-s/--struct\n\tPrint struct\n"+\
+ "-n/--name-only\n\tPrint names only\n"+\
+ "-P/--print-no-comment\n\tPrint with comment removed only\n"+\
+ ""
+
+#Parse options and arguments
+try:
+ opts, args = getopt.getopt(sys.argv[1:], "hMm:Ee:Ss:nP",
+ ["help","macros","macro=","enums","enum=",
+ "structs","struct="
+ "name-only","print-no-comment"])
+except getopt.GetoptError:
+ usage()
+ sys.exit(2)
+
+#Check there is at least input file
+if (len(args) < 1):
+ usage()
+ sys.exit(2)
+
+#Parse options
+##Print names only
+nameOnly = False
+##Print all structs?
+allStructs = False
+##Query specific struct
+struct=""
+##Print all enums?
+allEnums = False
+##Query specific enum
+enum=""
+##Print all macros?
+allMacros = False
+##Query specific macro
+macro=""
+##Print without comment
+printNoComment=False
+for opt,arg in opts:
+ if (opt in ("-h","--help")):
+ usage()
+ sys.exit(0)
+ elif (opt in ("-S","--structs")):
+ allStructs = True
+ elif (opt in ("-s","--struct")):
+ struct = arg
+ elif (opt in ("-M","--macros")):
+ allMacros = True
+ elif (opt in ("-m","--macro")):
+ macro=arg
+ elif (opt in ("-E","--enums")):
+ allEnums = True
+ elif (opt in ("-e","--enum")):
+ enum = arg
+ elif (opt in ("-n","--name-only")):
+ nameOnly = True
+ elif (opt in ("-P","--print-no-comment")):
+ printNoComment = True
+ else:
+ assert (False,"Unhandled option :"+opt)
+
+headerfile = cheader.cheaderfile(args)
+if (printNoComment):
+ for line in headerfile.content:
+ print line
+ sys.exit(0)
+
+#Print all macros
+if (allMacros):
+ for (macroname, value) in headerfile.macros.items():
+ if (nameOnly):
+ print macroname
+ else:
+ print macroname+"\t=\t"+str(value)
+#Print specified macro
+if (macro != ""):
+ try:
+ print macro+"="+headerfile.macros[macro]
+ except KeyError:
+ print "Macro "+macro+" not found!"
+
+#Print all structs
+if (allStructs):
+ for (structname, value) in headerfile.structs.items():
+ if (nameOnly):
+ print structname
+ else:
+ print str(value)+"\n"
+
+#Print specified struct
+if (struct != ""):
+ try:
+ print str(headerfile.structs[struct])
+ except KeyError:
+ print "Struct "+struct+" not found!"
+
+#Print all enumerations
+if (allEnums):
+ for (enumname, values) in headerfile.enums.items():
+ print enumname
+ if (not nameOnly):
+ for enumval in values:
+ try:
+ print "\t"+enumval+"="+\
+ str(headerfile.enum_values[enumval])
+ except KeyError:
+ print enumval+" not found in enum!";
+
+#Print specifed enum
+if (enum != ""):
+ try:
+ for enumval in headerfile.enums[enum]:
+ try:
+ print enumval+"="+str(headerfile.enum_values[enumval])
+ except KeyError:
+ print enumval+" not found in enum!";
+ except KeyError:
+ print "Enumeration "+enum+" not found!"
diff --git a/tools/pylibopenflow/bin/pyopenflow-get-struct.py b/tools/pylibopenflow/bin/pyopenflow-get-struct.py
new file mode 100755
index 0000000..78297c5
--- /dev/null
+++ b/tools/pylibopenflow/bin/pyopenflow-get-struct.py
@@ -0,0 +1,74 @@
+#!/usr/bin/env python2.5
+"""This script reads struct from OpenFlow header file and output query
+
+(C) Copyright Stanford University
+Author ykk
+Date October 2009
+"""
+import sys
+import getopt
+import openflow
+
+def usage():
+ """Display usage
+ """
+ print "Usage "+sys.argv[0]+" <options> struct_name\n"+\
+ "Options:\n"+\
+ "-h/--help\n\tPrint this usage guide\n"+\
+ "-c/--cstruct\n\tPrint C struct\n"+\
+ "-n/--name\n\tPrint names of struct\n"+\
+ "-s/--size\n\tPrint size of struct\n"+\
+ ""
+
+#Parse options and arguments
+try:
+ opts, args = getopt.getopt(sys.argv[1:], "hcsn",
+ ["help","cstruct","size","names"])
+except getopt.GetoptError:
+ usage()
+ sys.exit(2)
+
+#Check there is only struct name
+if not (len(args) == 1):
+ usage()
+ sys.exit(2)
+
+#Parse options
+##Print C struct
+printc = False
+##Print names
+printname = False
+##Print size
+printsize = False
+for opt,arg in opts:
+ if (opt in ("-h","--help")):
+ usage()
+ sys.exit(0)
+ elif (opt in ("-s","--size")):
+ printsize = True
+ elif (opt in ("-c","--cstruct")):
+ printc = True
+ elif (opt in ("-n","--names")):
+ printname = True
+ else:
+ assert (False,"Unhandled option :"+opt)
+
+pyopenflow = openflow.messages()
+cstruct = pyopenflow.structs[args[0].strip()]
+pattern = pyopenflow.get_pattern(cstruct)
+
+#Print C struct
+if (printc):
+ print cstruct
+
+#Print pattern
+print "Python pattern = "+str(pattern)
+
+#Print name
+if (printname):
+ print cstruct.get_names()
+
+#Print size
+if (printsize):
+ print "Size = "+str(pyopenflow.get_size(pattern))
+
diff --git a/tools/pylibopenflow/bin/pyopenflow-lavi-pythonize.py b/tools/pylibopenflow/bin/pyopenflow-lavi-pythonize.py
new file mode 100755
index 0000000..bb8c180
--- /dev/null
+++ b/tools/pylibopenflow/bin/pyopenflow-lavi-pythonize.py
@@ -0,0 +1,89 @@
+#!/usr/bin/env python2.5
+"""This script generate class files for messenger and lavi in NOX,
+specifically it creates a Python class for each data structure.
+
+(C) Copyright Stanford University
+Author ykk
+Date January 2010
+"""
+import sys
+import os.path
+import getopt
+import cheader
+import lavi.pythonize
+
+def usage():
+ """Display usage
+ """
+ print "Usage "+sys.argv[0]+" <options> nox_dir\n"+\
+ "Options:\n"+\
+ "-i/--input-dir\n\tSpecify input directory (nox src directory)\n"+\
+ "-t/--template\n\tSpecify (non-default) template file\n"+\
+ "-n/--no-lavi\n\tSpecify that LAVI's file will not be created\n"+\
+ "-h/--help\n\tPrint this usage guide\n"+\
+ ""
+
+#Parse options and arguments
+try:
+ opts, args = getopt.getopt(sys.argv[1:], "hm:n",
+ ["help","messenger-template","no-lavi"])
+except getopt.GetoptError:
+ usage()
+ sys.exit(2)
+
+#Check there is only NOX directory given
+if not (len(args) == 1):
+ usage()
+ sys.exit(2)
+
+#Parse options
+##Output LAVI
+outputlavi=True
+##Template file
+templatefile="include/messenger.template.py"
+for opt,arg in opts:
+ if (opt in ("-h","--help")):
+ usage()
+ sys.exit(0)
+ elif (opt in ("-t","--template")):
+ templatefile=arg
+ elif (opt in ("-n","--no-lavi")):
+ outputlavi=False
+ else:
+ print "Unhandled option:"+opt
+ sys.exit(2)
+
+#Check for header file in NOX directory
+if not (os.path.isfile(args[0]+"/src/nox/coreapps/messenger/message.hh")):
+ print "Messenger header file not found!"
+ sys.exit(2)
+if (outputlavi):
+ if not (os.path.isfile(args[0]+"/src/nox/netapps/lavi/lavi-message.hh")):
+ print "LAVI message header file not found!"
+ sys.exit(2)
+
+#Get headerfile and pythonizer
+msgheader = cheader.cheaderfile(args[0]+"/src/nox/coreapps/messenger/message.hh")
+mpynizer = lavi.pythonize.msgpythonizer(msgheader)
+if (outputlavi):
+ laviheader = cheader.cheaderfile([args[0]+"/src/nox/coreapps/messenger/message.hh",
+ args[0]+"/src/nox/netapps/lavi/lavi-message.hh"])
+ lpynizer = lavi.pythonize.lavipythonizer(laviheader)
+
+#Generate Python code for messenger
+fileRef = open(args[0]+"/src/nox/coreapps/messenger/messenger.py", "w")
+for x in mpynizer.pycode(templatefile):
+ fileRef.write(x+"\n")
+fileRef.write("\n")
+fileRef.close()
+
+if (outputlavi):
+ fileRef = open(args[0]+"/src/nox/netapps/lavi/lavi.py", "w")
+ for x in lpynizer.pycode(templatefile):
+ fileRef.write(x.replace("def __init__(self,ipAddr,portNo=2603,debug=False):",
+ "def __init__(self,ipAddr,portNo=2503,debug=False):").\
+ replace("def __init__(self, ipAddr, portNo=1304,debug=False):",
+ "def __init__(self, ipAddr, portNo=1305,debug=False):")+\
+ "\n")
+ fileRef.write("\n")
+ fileRef.close()
diff --git a/tools/pylibopenflow/bin/pyopenflow-load-controller.py b/tools/pylibopenflow/bin/pyopenflow-load-controller.py
new file mode 100755
index 0000000..aef34f7
--- /dev/null
+++ b/tools/pylibopenflow/bin/pyopenflow-load-controller.py
@@ -0,0 +1,131 @@
+#!/usr/bin/env python2.5
+"""This script fakes as n OpenFlow switch and
+load the controller with k packets per second.
+
+(C) Copyright Stanford University
+Author ykk
+Date January 2010
+"""
+import sys
+import getopt
+import struct
+import openflow
+import time
+import output
+import of.msg
+import of.simu
+import of.network
+import dpkt.ethernet
+
+def usage():
+ """Display usage
+ """
+ print "Usage "+sys.argv[0]+" <options> controller\n"+\
+ "Options:\n"+\
+ "-p/--port\n\tSpecify port number\n"+\
+ "-v/--verbose\n\tPrint message exchange\n"+\
+ "-r/--rate\n\tSpecify rate per switch to send packets (default=1)\n"+\
+ "-d/--duration\n\tSpecify duration of load test in seconds (default=5)\n"+\
+ "-s/--switch\n\tSpecify number of switches (default=1)\n"+\
+ "-h/--help\n\tPrint this usage guide\n"+\
+ ""
+
+#Parse options and arguments
+try:
+ opts, args = getopt.getopt(sys.argv[1:], "hvp:s:d:r:",
+ ["help","verbose","port=",
+ "switch=","duration=","rate="])
+except getopt.GetoptError:
+ usage()
+ sys.exit(2)
+
+#Check there is only controller
+if not (len(args) == 1):
+ usage()
+ sys.exit(2)
+
+#Parse options
+##Duration
+duration = 5
+##Rate
+rate = 1.0
+##Switch number
+swno = 1
+##Port to connect to
+port = 6633
+##Set output mode
+output.set_mode("INFO")
+for opt,arg in opts:
+ if (opt in ("-h","--help")):
+ usage()
+ sys.exit(0)
+ elif (opt in ("-v","--verbose")):
+ output.set_mode("DBG")
+ elif (opt in ("-p","--port")):
+ port=int(arg)
+ elif (opt in ("-s","--switch")):
+ swno=int(arg)
+ elif (opt in ("-d","--duration")):
+ duration=int(arg)
+ elif (opt in ("-r","--rate")):
+ rate=float(arg)
+ else:
+ print "Unhandled option :"+opt
+ sys.exit(2)
+
+#Form packet
+pkt = dpkt.ethernet.Ethernet()
+pkt.type = dpkt.ethernet.ETH_MIN
+pkt.dst = '\xFF\xFF\xFF\xFF\xFF\xFF'
+
+#Connect to controller
+ofmsg = openflow.messages()
+parser = of.msg.parser(ofmsg)
+ofnet = of.simu.network()
+for i in range(1,swno+1):
+ ofsw = of.simu.switch(ofmsg, args[0], port,
+ dpid=i,
+ parser=parser)
+ ofnet.add_switch(ofsw)
+ ofsw.send_hello()
+
+output.info("Running "+str(swno)+" switches at "+str(rate)+\
+ " packets per seconds for "+str(duration)+" s")
+
+starttime = time.time()
+running = True
+interval = 1.0/(rate*swno)
+ntime=time.time()+(interval/10.0)
+swindex = 0
+pcount = 0
+rcount = 0
+while running:
+ ctime = time.time()
+ time.sleep(max(0,min(ntime-ctime,interval/10.0)))
+
+ if ((ctime-starttime) <= duration):
+ #Send packet if time's up
+ if (ctime >= ntime):
+ ntime += interval
+ pkt.src = struct.pack("Q",pcount)[:6]
+ ofnet.switches[swindex].send_packet(1,10,pkt.pack()+'A'*3)
+ pcount += 1
+ swno += 1
+ if (swno >= len(ofnet.switches)):
+ swno=0
+
+ #Process any received message
+ (ofsw, msg) = ofnet.connections.msgreceive()
+ while (msg != None):
+ dic = ofmsg.peek_from_front("ofp_header", msg)
+ if (dic["type"][0] == ofmsg.get_value("OFPT_FLOW_MOD")):
+ output.dbg("Received flow mod")
+ rcount += 1
+ ofsw.receive_openflow(msg)
+ (ofsw, msg) = ofnet.connections.msgreceive()
+ else:
+ running = False
+
+output.info("Sent "+str(pcount)+" packets at rate "+\
+ str(float(pcount)/float(duration))+" and received "+\
+ str(rcount)+" back")
diff --git a/tools/pylibopenflow/bin/pyopenflow-ping-controller.py b/tools/pylibopenflow/bin/pyopenflow-ping-controller.py
new file mode 100755
index 0000000..e5aa030
--- /dev/null
+++ b/tools/pylibopenflow/bin/pyopenflow-ping-controller.py
@@ -0,0 +1,78 @@
+#!/usr/bin/env python2.5
+"""This script fakes as an OpenFlow switch to the controller
+
+(C) Copyright Stanford University
+Author ykk
+Date October 2009
+"""
+import sys
+import getopt
+import openflow
+import time
+import output
+import of.msg
+import of.simu
+
+def usage():
+ """Display usage
+ """
+ print "Usage "+sys.argv[0]+" <options> controller\n"+\
+ "Options:\n"+\
+ "-p/--port\n\tSpecify port number\n"+\
+ "-v/--verbose\n\tPrint message exchange\n"+\
+ "-h/--help\n\tPrint this usage guide\n"+\
+ ""
+
+#Parse options and arguments
+try:
+ opts, args = getopt.getopt(sys.argv[1:], "hvp:",
+ ["help","verbose","port="])
+except getopt.GetoptError:
+ usage()
+ sys.exit(2)
+
+#Check there is only controller
+if not (len(args) == 1):
+ usage()
+ sys.exit(2)
+
+#Parse options
+##Port to connect to
+port = 6633
+##Set output mode
+output.set_mode("INFO")
+for opt,arg in opts:
+ if (opt in ("-h","--help")):
+ usage()
+ sys.exit(0)
+ elif (opt in ("-v","--verbose")):
+ output.set_mode("DBG")
+ elif (opt in ("-p","--port")):
+ port=int(arg)
+ else:
+ assert (False,"Unhandled option :"+opt)
+
+#Connect to controller
+ofmsg = openflow.messages()
+parser = of.msg.parser(ofmsg)
+ofsw = of.simu.switch(ofmsg, args[0], port,
+ dpid=int("0xcafecafe",16),
+ parser=parser)
+ofsw.send_hello()
+#Send echo and wait
+xid = 22092009
+running = True
+ofsw.send_echo(xid)
+starttime = time.time()
+while running:
+ msg = ofsw.connection.msgreceive(True, 0.00001)
+ pkttime = time.time()
+ dic = ofmsg.peek_from_front("ofp_header", msg)
+ if (dic["type"][0] == ofmsg.get_value("OFPT_ECHO_REPLY") and
+ dic["xid"][0] == xid):
+ #Check reply for echo request
+ output.info("Received echo reply after "+\
+ str((pkttime-starttime)*1000)+" ms", "ping-controller")
+ running = False
+ else:
+ ofsw.receive_openflow(msg)
diff --git a/tools/pylibopenflow/bin/pyopenflow-pythonize.py b/tools/pylibopenflow/bin/pyopenflow-pythonize.py
new file mode 100755
index 0000000..466c35d
--- /dev/null
+++ b/tools/pylibopenflow/bin/pyopenflow-pythonize.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python2.5
+"""This script generate openflow-packets.py which
+creates Python class for each data structure in openflow.h.
+
+(C) Copyright Stanford University
+Author ykk
+Date December 2009
+"""
+import sys
+sys.path.append('./bin')
+sys.path.append('./pylib')
+import getopt
+import openflow
+import time
+import output
+import of.pythonize
+
+def usage():
+ """Display usage
+ """
+ print "Usage "+sys.argv[0]+" <options> output_file\n"+\
+ "Options:\n"+\
+ "-i/--input\n\tSpecify (non-default) OpenFlow header\n"+\
+ "-t/--template\n\tSpecify (non-default) template file\n"+\
+ "-h/--help\n\tPrint this usage guide\n"+\
+ ""
+
+#Parse options and arguments
+try:
+ opts, args = getopt.getopt(sys.argv[1:], "hi:t:",
+ ["help","input","template"])
+except getopt.GetoptError:
+ usage()
+ sys.exit(2)
+
+#Check there is only output file
+if not (len(args) == 1):
+ usage()
+ sys.exit(2)
+
+#Parse options
+##Input
+headerfile=None
+##Template file
+templatefile=None
+for opt,arg in opts:
+ if (opt in ("-h","--help")):
+ usage()
+ sys.exit(0)
+ elif (opt in ("-i","--input")):
+ headerfile=arg
+ elif (opt in ("-t","--template")):
+ templatefile=arg
+ else:
+ print "Unhandled option:"+opt
+ sys.exit(2)
+
+#Generate Python code
+ofmsg = openflow.messages(headerfile)
+pynizer = of.pythonize.pythonizer(ofmsg)
+
+fileRef = open(args[0], "w")
+for x in pynizer.pycode(templatefile):
+ fileRef.write(x+"\n")
+fileRef.write("\n")
+fileRef.close()