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()