Initial oftest skeleton with wrapper generators and pylibopenflow
diff --git a/tools/pylibopenflow/pylib/c2py.py b/tools/pylibopenflow/pylib/c2py.py
new file mode 100644
index 0000000..b699c5e
--- /dev/null
+++ b/tools/pylibopenflow/pylib/c2py.py
@@ -0,0 +1,154 @@
+"""This module converts C types to Python struct pattern string.
+
+Date June 2009
+Created by ykk
+"""
+import cheader
+import struct
+
+class cstruct2py:
+    """Class converts C struct to Python struct pattern string
+
+    Date October 2009
+    Created by ykk
+    """
+    def __init__(self):
+        """Initialize
+        """
+        ##Mapping
+        self.structmap = {}
+        self.structmap["char"] = "c"
+        self.structmap["signed char"] = "b"
+        self.structmap["uint8_t"]=\
+            self.structmap["unsigned char"] = "B"
+        self.structmap["short"] = "h"
+        self.structmap["uint16_t"] =\
+            self.structmap["unsigned short"] = "H"
+        self.structmap["int"] = "i"
+        self.structmap["unsigned int"] = "I"
+        self.structmap["long"] = "l"
+        self.structmap["uint32_t"] =\
+            self.structmap["unsigned long"] = "L"
+        self.structmap["long long"] = "q"
+        self.structmap["uint64_t"] =\
+            self.structmap["unsigned long long"] = "Q"
+        self.structmap["float"] = "f"
+        self.structmap["double"] = "d"
+
+    def get_pattern(self,ctype):
+        """Get pattern string for ctype.
+        Return None if ctype is not expanded.
+        """
+        if (ctype.expanded):
+            if (isinstance(ctype, cheader.cprimitive)):
+                return self.structmap[ctype.typename]
+            elif (isinstance(ctype, cheader.cstruct)):
+                string=""
+                for member in ctype.members:
+                    string += self.get_pattern(member)
+                return string
+            elif (isinstance(ctype, cheader.carray)):
+                if (ctype.size == 0):
+                    return ""
+                else:
+                    string = self.get_pattern(ctype.object)
+                    return string * ctype.size
+        return None
+        
+    def get_size(self, ctype, prefix="!"):
+        """Return size of struct or pattern specified
+        """
+        if (isinstance(ctype, str)):
+            return struct.calcsize(ctype)
+        elif (isinstance(ctype, cheader.ctype)):
+            return struct.calcsize(prefix + self.get_pattern(ctype))
+        else:
+            return 0
+
+class structpacker:
+    """Pack/unpack packets with ctype.
+    
+    Date October 2009
+    Created by ykk
+    """
+    def __init__(self, prefix=""):
+        """Initialize with prefix to struct
+        """
+        ##Reference to prefix
+        self.prefix = prefix
+        
+    def pack(self, ctype, *arg):
+        """Pack packet accordingly ctype or pattern provided.
+        Return struct packed.
+        """
+        if (isinstance(ctype, str)):
+            return struct.pack(self.prefix+ctype, *arg)
+        elif (isinstance(ctype, cheader.ctype)):
+            return struct.pack(self.prefix+cstruct2py.get_pattern(ctype),
+                               *arg)
+        else:
+            return None
+
+    def unpack_from_front(self, ctype, binaryString, returnDictionary=True):
+        """Unpack packet using front of packet,
+        accordingly ctype or pattern provided.
+
+        Return (dictionary of values indexed by arg name, 
+        remaining binary string) if ctype is cheader.ctype
+        and returnDictionary is True, 
+        else return (array of data unpacked, remaining binary string).
+        """
+        pattern = ""
+        if (isinstance(ctype, str)):
+            pattern = ctype
+        elif (isinstance(ctype, cheader.ctype)):
+            pattern = cstruct2py.get_pattern(ctype)
+        else:
+            return None
+        dsize = struct.calcsize(pattern)
+
+        if (dsize > len(binaryString)):
+            return None
+
+        return (structpacker.peek_from_front(self, pattern, binaryString, returnDictionary),
+                binaryString[dsize:])
+
+    def peek_from_front(self, ctype, binaryString, returnDictionary=True):
+        """Unpack packet using front of packet,
+        accordingly ctype or pattern provided.
+
+        Return dictionary of values indexed by arg name,
+        if ctype is cheader.ctype and returnDictionary is True, 
+        else return array of data unpacked.
+        """
+        pattern = self.prefix
+        if (isinstance(ctype, str)):
+            pattern += ctype
+        elif (isinstance(ctype, cheader.ctype)):
+            pattern += cstruct2py.get_pattern(ctype)
+        else:
+            return None
+        dsize = struct.calcsize(pattern)
+        if (dsize > len(binaryString)):
+            return None
+        data = struct.unpack(pattern, binaryString[0:dsize])
+        
+        #Return values
+        if (isinstance(ctype, str) or
+            (not returnDictionary)):
+            return data
+        else:
+            return self.data2dic(data, ctype)
+
+    def data2dic(self,ctype,data):
+        """Convert data to dictionary
+        """
+        valDic = {}
+        names = ctype.get_names()
+        for name in names:
+            valDic[name] = []
+        for d in data:
+            name = names.pop(0)
+            valDic[name].append(d)
+        return valDic
+
diff --git a/tools/pylibopenflow/pylib/cheader.py b/tools/pylibopenflow/pylib/cheader.py
new file mode 100644
index 0000000..a23e1eb
--- /dev/null
+++ b/tools/pylibopenflow/pylib/cheader.py
@@ -0,0 +1,434 @@
+"""This module parse and store a C/C++ header file.
+
+Date June 2009
+Created by ykk
+"""
+import re
+from config import *
+
+class textfile:
+    """Class to handle text file.
+    
+    Date June 2009
+    Created by ykk
+    """
+    def __init__(self, filename):
+        """Initialize filename with no content.
+        """
+        ##Filename
+        if (isinstance(filename, str)):
+            self.filename = []
+            self.filename.append(filename)
+        else:
+            self.filename = filename
+        ##Content
+        self.content = []
+
+    def read(self):
+        """Read file
+        """
+        for filename in self.filename:
+            fileRef = open(filename, "r")
+            for line in fileRef:
+                self.content.append(line)
+            fileRef.close()        
+
+class ctype:
+    """Class to represent types in C
+    """
+    def __init__(self,typename, name=None, expanded=False):
+        """Initialize
+        """
+        ##Name
+        self.name = name
+        ##Type of primitive
+        self.typename = typename
+        ##Expanded
+        self.expanded = expanded
+
+    def expand(self, cheader):
+        """Expand type if applicable
+        """
+        raise NotImplementedError()
+
+    def get_names(self):
+        """Return name of variables
+        """
+        raise NotImplementedError()
+
+class cprimitive(ctype):
+    """Class to represent C primitive
+
+    Date October 2009
+    Created by ykk
+    """
+    def __init__(self,typename, name=None):
+        """Initialize and store primitive
+        """
+        ctype.__init__(self, typename, name, True)
+
+    def __str__(self):
+        """Return string representation
+        """
+        if (self.name == None):
+            return self.typename
+        else:
+            return self.typename+" "+str(self.name)
+
+    def expand(self, cheader):
+        """Expand type if applicable
+        """
+        pass
+    
+    def get_names(self):
+        """Return name of variables
+        """
+        namelist = []
+        namelist.append(self.name)
+        return namelist
+
+class cstruct(ctype):
+    """Class to represent C struct
+
+    Date October 2009
+    Created by ykk
+    """
+    def __init__(self, typename, name=None):
+        """Initialize struct
+        """
+        ctype.__init__(self, typename, name)
+        ##List of members in struct
+        self.members = []
+    
+    def __str__(self):
+        """Return string representation
+        """
+        string = "struct "+self.typename
+        if (self.name != None):
+            string += " "+self.name
+        if (len(self.members) == 0):
+            return string
+        #Add members
+        string +=" {\n"
+        for member in self.members:
+            string += "\t"+str(member)
+            if (not isinstance(member, cstruct)):
+                string += ";"
+            string += "\n"
+        string +="};"
+        return string
+
+    def expand(self, cheader):
+        """Expand struct
+        """
+        self.expanded = True
+        #Expanded each member
+        for member in self.members:
+            if (isinstance(member, cstruct) and 
+                (not member.expanded)):
+                try:
+                    if (not cheader.structs[member.typename].expanded):
+                        cheader.structs[member.typename].expand(cheader)
+                    member.members=cheader.structs[member.typename].members[:]
+                    member.expanded = True
+                except KeyError:
+                    self.expanded=False
+            else:
+                member.expand(cheader)
+
+    def get_names(self):
+        """Return name of variables
+        """
+        namelist = []
+        for member in self.members:
+            if (isinstance(member, cstruct)):
+                tmplist = member.get_names()
+                for item in tmplist:
+                    namelist.append(member.name+"."+item)
+            else:
+                namelist.extend(member.get_names())
+        return namelist
+
+
+class carray(ctype):
+    """Class to represent C array
+
+    Date October 2009
+    Created by ykk
+    """
+    def __init__(self, typename, name, isPrimitive, size):
+        """Initialize array of object.
+        """
+        ctype.__init__(self, typename, name,
+                       (isinstance(size, int) and isPrimitive))
+        ##Object reference
+        if (isPrimitive):
+            self.object = cprimitive(typename, name)
+        else:
+            self.object = cstruct(typename, name)
+        ##Size of array
+        self.size = size
+        
+    def __str__(self):
+        """Return string representation
+        """
+        return str(self.object)+"["+str(self.size)+"]"
+
+    def expand(self, cheader):
+        """Expand array
+        """
+        self.expanded = True
+        if (not self.object.expanded):
+            if (isinstance(self.object, cstruct)):
+                cheader.structs[self.object.typename].expand(cheader)
+                self.object.members=cheader.structs[self.object.typename].members[:]    
+            else:
+                self.object.expand(cheader)
+
+        if (not isinstance(self.size, int)):
+            val = cheader.get_value(self.size)
+            if (val == None):
+                self.expanded = False
+            else:
+                try:
+                    self.size = int(val)
+                except ValueError:
+                    self.size = val
+                    self.expanded = False
+
+    def get_names(self):
+        """Return name of variables
+        """
+        namelist = []
+        for i in range(0,self.size):
+            namelist.append(self.object.name)
+        return namelist
+
+class ctype_parser:
+    """Class to check c types
+
+    Date October 2009
+    Created by ykk
+    """
+    def __init__(self):
+        """Initialize
+        """
+        self.CPrimitives = ["char","signed char","unsigned char",
+                            "short","unsigned short",
+                            "int","unsigned int",
+                            "long","unsigned long",
+                            "long long","unsigned long long",
+                            "float","double",
+                            "uint8_t","uint16_t","uint32_t","uint64_t"]
+
+    def is_primitive(self,type):
+        """Check type given is primitive.
+
+        Return true if valid, and false otherwise
+        """
+        if (type in self.CPrimitives):
+            return True
+        else:
+            return False
+
+    def is_array(self, string):
+        """Check if string declares an array
+        """
+        parts=string.strip().split()
+        if (len(parts) <= 1):
+            return False
+        else:
+            pattern = re.compile("\[.*?\]", re.MULTILINE)
+            values = pattern.findall(string)
+            if (len(values) == 1):
+                return True
+            else:
+                return False
+
+    def parse_array(self, string):
+        """Parse array from string.
+        Return occurrence and name.
+        """
+        pattern = re.compile("\[.*?\]", re.MULTILINE)
+        namepattern = re.compile(".*?\[", re.MULTILINE)
+        values = pattern.findall(string)
+        if (len(values) != 1):
+            return (1,string)
+        else:
+            val = values[0][1:-1]
+            try:
+                sizeval = int(val)
+            except ValueError:
+                if (val==""):
+                    sizeval = 0
+                else:
+                    sizeval = val
+            return (sizeval,
+                    namepattern.findall(string)[0].strip()[0:-1])
+
+    def parse_type(self, string):
+        """Parse string and return cstruct or cprimitive.
+        Else return None
+        """
+        parts=string.strip().split()
+        if (len(parts) >= 2):
+            if (parts[0].strip() == "struct"):
+                typename = " ".join(parts[1:-1])
+            else:
+                typename = " ".join(parts[:-1])
+            (size, name) = self.parse_array(parts[-1])
+            if IGNORE_ZERO_ARRAYS and size == 0:
+                return None
+            #Create appropriate type
+            if (size != 1):
+                #Array
+                return carray(typename, name, 
+                              self.is_primitive(typename),size)
+            else:
+                #Not array
+                if IGNORE_OFP_HEADER and typename == "ofp_header":
+                    return None
+                if (self.is_primitive(typename)):
+                    return cprimitive(typename, name)
+                else:
+                    return cstruct(typename, name)
+        else:
+            return None
+
+class cheaderfile(textfile):
+    """Class to handle C header file.
+    
+    Date June 2009
+    Created by ykk
+    """
+    def __init__(self, filename):
+        """Initialize filename and read from file
+        """
+        textfile.__init__(self,filename)
+        self.read()
+        self.__remove_comments()
+        ##Dictionary of macros
+        self.macros = {}
+        self.__get_macros()
+        ##Dictionary of enumerations
+        self.enums = {}
+        self.enum_values = {}
+        self.__get_enum()
+        self.__get_enum_values()
+        ##Dictionary of structs
+        self.structs = {}
+        self.__get_struct()
+
+    def get_enum_name(self, enum, value):
+        """Return name of variable in enum
+        """
+        for e in self.enums[enum]:
+            if (self.enum_values[e] == value):
+                return e
+
+    def eval_value(self, value):
+        """Evaluate value string
+        """
+        try:
+            return eval(value, self.enum_values)
+        except:
+            return value.strip()
+
+    def get_value(self, name):
+        """Get value for variable name,
+        searching through enum and macros.
+        Else return None
+        """
+        try:
+            return self.enum_values[name]
+        except KeyError:
+            try:
+                return self.macros[name]
+            except KeyError:
+                return None
+
+    def __remove_comments(self):
+        """Remove all comments
+        """
+        fileStr = "".join(self.content)
+        pattern = re.compile("\\\.*?\n", re.MULTILINE)
+        fileStr = pattern.sub("",fileStr)
+        pattern = re.compile(r"/\*.*?\*/", re.MULTILINE|re.DOTALL)
+        fileStr = pattern.sub("",fileStr)
+        pattern = re.compile("//.*$", re.MULTILINE)
+        fileStr = pattern.sub("",fileStr)
+        self.content = fileStr.split('\n')
+
+    def __get_struct(self):
+        """Get all structs
+        """
+        typeparser = ctype_parser()
+        fileStr = "".join(self.content)
+        #Remove attribute
+        attrpattern = re.compile("} __attribute__ \(\((.+?)\)\);", re.MULTILINE)
+        attrmatches = attrpattern.findall(fileStr)
+        for amatch in attrmatches:
+            fileStr=fileStr.replace(" __attribute__ (("+amatch+"));",";")
+        #Find all structs
+        pattern = re.compile("struct[\w\s]*?{.*?};", re.MULTILINE)
+        matches = pattern.findall(fileStr)
+        #Process each struct
+        namepattern = re.compile("struct(.+?)[ {]", re.MULTILINE)
+        pattern = re.compile("{(.+?)};", re.MULTILINE)
+        for match in matches:
+            structname = namepattern.findall(match)[0].strip()
+            if (len(structname) != 0):
+                values = pattern.findall(match)[0].strip().split(";")
+                cstru = cstruct(structname)
+                for val in values:
+                    presult = typeparser.parse_type(val)
+                    if (presult != None):
+                        cstru.members.append(presult)
+                self.structs[structname] = cstru
+        #Expand all structs
+        for (structname, struct) in self.structs.items():
+            struct.expand(self)
+
+    def __get_enum(self):
+        """Get all enumeration
+        """
+        fileStr = "".join(self.content)
+        #Find all enumerations
+        pattern = re.compile("enum[\w\s]*?{.*?}", re.MULTILINE)
+        matches = pattern.findall(fileStr)
+        #Process each enumeration
+        namepattern = re.compile("enum(.+?){", re.MULTILINE)
+        pattern = re.compile("{(.+?)}", re.MULTILINE)
+        for match in matches:
+            values = pattern.findall(match)[0].strip().split(",")
+            #Process each value in enumeration
+            enumList = []
+            value = 0
+            for val in values:
+                if not (val.strip() == ""):
+                    valList=val.strip().split("=")
+                    enumList.append(valList[0].strip())
+                    if (len(valList) == 1):
+                        self.enum_values[valList[0].strip()] = value
+                        value += 1
+                    else:
+                        self.enum_values[valList[0].strip()] = self.eval_value(valList[1].strip())
+                    self.enums[namepattern.findall(match)[0].strip()] = enumList
+
+    def __get_enum_values(self):
+        """Patch unresolved enum values
+        """
+        for name,enumval in self.enum_values.items():
+            if isinstance(enumval,str):
+                self.enum_values[name] = self.eval_value(enumval)
+        
+    def __get_macros(self):
+        """Extract macros
+        """
+        for line in self.content:
+            if (line[0:8] == "#define "):
+                lineList = line[8:].split()
+                if (len(lineList) >= 2):
+                    self.macros[lineList[0]] = self.eval_value("".join(lineList[1:]))
+                else:
+                    self.macros[lineList[0]] = ""
diff --git a/tools/pylibopenflow/pylib/config.py b/tools/pylibopenflow/pylib/config.py
new file mode 100644
index 0000000..bbf1528
--- /dev/null
+++ b/tools/pylibopenflow/pylib/config.py
@@ -0,0 +1,24 @@
+
+# of_message specific controls
+
+# Do not include any arrays marked [0]
+IGNORE_ZERO_ARRAYS = 1
+
+# Do not include the ofp_header as a member in any structure
+# This allows messages to be consistently generated as:
+#   explicit header declaration
+#   core member declaration
+#   variable length data
+IGNORE_OFP_HEADER = 1
+
+# Generate object equality functions
+GEN_OBJ_EQUALITY = 1
+
+# Generate object show functions
+GEN_OBJ_SHOW = 1
+
+# Generate lists of enum values
+GEN_ENUM_VALUES_LIST = 0
+
+# Generate dictionary of enum strings to values
+GEN_ENUM_DICTIONARY = 1
diff --git a/tools/pylibopenflow/pylib/cpythonize.py b/tools/pylibopenflow/pylib/cpythonize.py
new file mode 100644
index 0000000..6a66d7c
--- /dev/null
+++ b/tools/pylibopenflow/pylib/cpythonize.py
@@ -0,0 +1,533 @@
+"""This module generate Python code for C structs.
+
+Date January 2010
+Created by ykk
+"""
+import cheader
+import c2py
+import datetime
+import struct
+import re
+from config import *
+
+def _space_to(n, str):
+    """
+    Generate a string of spaces to achieve width n given string str
+    If length of str >= n, return one space
+    """
+    spaces = n - len(str)
+    if spaces > 0:
+        return " " * spaces
+    return " "
+
+class rules:
+    """Class that specify rules for pythonization
+
+    Date January 2010
+    Created by ykk
+    """
+    def __init__(self):
+        """Initialize rules
+        """
+        ##Default values for members
+        self.default_values = {}
+        #Default values for struct
+        self.struct_default = {}
+        ##What is a tab
+        self.tab = "    "
+        ##Macros to exclude
+        self.excluded_macros = []
+        ##Enforce mapping
+        self.enforced_maps = {}
+
+    def get_enforced_map(self, structname):
+        """Get code to enforce mapping
+        """
+        code = []
+        try:
+            mapping = self.enforced_maps[structname]
+        except KeyError:
+            return None
+        for (x,xlist) in mapping:
+            code.append("if (not (self."+x+" in "+xlist+")):")
+            code.append(self.tab+"return (False, \""+x+" must have values from "+xlist+"\")")
+        return code
+        
+
+    def get_struct_default(self, structname, fieldname):
+        """Get code to set defaults for member struct
+        """
+        try:
+            return "."+fieldname+self.struct_default[(structname, fieldname)]
+        except KeyError:
+            return None
+        
+    def get_default_value(self, structname, fieldname):
+        """Get default value for struct's field
+        """
+        try:
+            return self.default_values[(structname, fieldname)]
+        except KeyError:
+            return 0
+
+    def include_macro(self, name):
+        """Check if macro should be included
+        """
+        return not (name in self.excluded_macros)
+
+class pythonizer:
+    """Class that pythonize C structures
+
+    Date January 2010
+    Created by ykk
+    """
+    def __init__(self, cheaderfile, pyrules = None, tab="    "):
+        """Initialize
+        """
+        ##Rules
+        if (pyrules == None):
+            self.rules = rules()
+        else:
+            self.rules = pyrules
+        ##What is a tab (same as rules)
+        self.tab = str(tab)
+        self.rules.tab = self.tab
+        ##Reference to C header file
+        self.cheader = cheaderfile
+        ##Reference to cstruct2py
+        self.__c2py = c2py.cstruct2py()
+        ##Code for assertion
+        self.__assertcode = []
+
+    def pycode(self,preamble=None):
+        """Return pythonized code
+        """
+        code = []
+        code.append("import struct")
+        code.append("")
+        if (preamble != None):
+            fileRef = open(preamble,"r")
+            for l in fileRef:
+                code.append(l[:-1])
+            fileRef.close()
+        code.append("# Structure definitions")
+        for name,struct in self.cheader.structs.items():
+            code.extend(self.pycode_struct(struct))
+            code.append("")
+        code.append("# Enumerated type definitions")
+        for name,enum in self.cheader.enums.items():
+            code.extend(self.pycode_enum(name,enum))
+            if GEN_ENUM_DICTIONARY:
+                code.extend(self.pycode_enum_map(name,enum))
+            code.append("")
+        code.append("# Values from macro definitions")
+        for name,macro in self.cheader.macros.items():
+            code.extend(self.pycode_macro(name))
+        code.append("")
+        code.append("# Basic structure size definitions.")
+        if IGNORE_OFP_HEADER:
+            code.append("# Does not include ofp_header members.")
+        if IGNORE_ZERO_ARRAYS:
+            code.append("# Does not include variable length arrays.")
+        struct_keys = self.cheader.structs.keys()
+        struct_keys.sort()
+        for name in struct_keys:
+            struct = self.cheader.structs[name]
+            code.append(self.pycode_struct_size(name, struct))
+
+        return code
+
+    def pycode_enum(self, name, enum):
+        """Return Python array for enum
+        """
+        code=[]
+        code.append(name+" = "+str(enum))
+        ev = []
+        for e in enum:
+            v = self.cheader.get_value(e)
+            ev.append(v)
+            code.append(e+"%s= "%_space_to(36,e)+str(v))
+        if GEN_ENUM_VALUES_LIST:
+            code.append(name+"_values = "+str(ev))
+        return code
+
+    def pycode_enum_map(self, name, enum):
+        """Return Python dictionary for enum
+        """
+        code = []
+        code.append(name+"_map = {")
+        first = 1
+        for e in enum:
+            v = self.cheader.get_value(e)
+            if first:
+                prev_e = e
+                prev_v = v
+                first = 0
+            else:
+                code.append(self.tab + "'%s'%s: %s," %
+                            (prev_e, _space_to(30, prev_e), prev_v))
+                prev_e = e
+                prev_v = v
+        code.append(self.tab + "'%s'%s: %s" %
+                            (prev_e, _space_to(30, prev_e), prev_v))
+        code.append("}")
+        return code
+
+    def pycode_macro(self,name):
+        """Return Python dict for macro
+        """
+        code = []
+        if (self.rules.include_macro(name)):
+            code.append(name+" = "+str(self.cheader.get_value(name)))
+        return code
+
+    def pycode_struct_size(self, name, struct):
+        """Return one liner giving the structure size in bytes
+        """
+        pattern = '!' + self.__c2py.get_pattern(struct)
+        bytes = self.__c2py.get_size(pattern)
+        code = name.upper() + "_BYTES = " + str(bytes)
+        return code
+
+    def pycode_struct(self, struct_in):
+        """Return Python class code given C struct.
+
+        Returns None if struct_in is not cheader.cstruct.
+        Else return list of strings that codes Python class.
+        """
+        if (not isinstance(struct_in, cheader.cstruct)):
+            return None
+
+        code=[]
+        self.__assertcode = []
+        code.extend(self.codeheader(struct_in))
+        code.extend(self.codeinit(struct_in))
+        code.append("")
+        code.extend(self.codeassert(struct_in))
+        code.append("")
+        code.extend(self.codepack(struct_in))
+        code.append("")
+        code.extend(self.codeunpack(struct_in))
+        code.append("")
+        code.extend(self.codelen(struct_in))
+        code.append("")
+        if GEN_OBJ_EQUALITY:
+            code.extend(self.codeeq(struct_in))
+            code.append("")
+        if GEN_OBJ_SHOW:
+            code.extend(self.codeshow(struct_in))
+            code.append("")
+        return code
+
+    def codeheader(self, struct_in):
+        """Return Python code for header
+        """
+        code=[]
+        code.append("class "+struct_in.typename+":")
+        code.append(self.tab+"\"\"\"Automatically generated Python class for "+struct_in.typename)
+        code.append("")
+        code.append(self.tab+"Date "+str(datetime.date.today()))
+        code.append(self.tab+"Created by "+self.__module__+"."+self.__class__.__name__)
+        if IGNORE_OFP_HEADER:
+            code.append(self.tab+"Core structure: Messages do not include ofp_header")
+        if IGNORE_ZERO_ARRAYS:
+            code.append(self.tab+"Does not include var-length arrays")
+        code.append(self.tab+"\"\"\"")
+        return code
+
+    def codeinit(self, struct_in):
+        """Return Python code for init function
+        """
+        code = []
+        code.append(self.tab+"def __init__(self):")
+        code.append(self.tab*2+"\"\"\"Initialize")
+        code.append(self.tab*2+"Declare members and default values")
+        code.append(self.tab*2+"\"\"\"")
+        code.extend(self.codemembers(struct_in,self.tab*2+"self"))
+        return code
+
+    def codemembers(self, struct_in, prepend=""):
+        """Return members of class
+        """
+        code = []
+        for member in struct_in.members:
+            if (isinstance(member, cheader.cstruct)):
+                code.append(prepend+"."+member.name+" = "+member.typename+"()")
+                struct_default = self.rules.get_struct_default(struct_in.typename, member.name)
+                if (struct_default != None):
+                    code.append(prepend+struct_default)
+                self.__structassert(member, (prepend+"."+member.name).strip())
+            elif (isinstance(member, cheader.carray)):
+                if (member.typename == "char"):
+                    initvalue = "\"\""
+                    self.__stringassert(member, (prepend+"."+member.name).strip())
+                else:
+                    if (isinstance(member.object, cheader.cprimitive)):
+                        initvalue="0"
+                    else:
+                        initvalue="None"
+                    initvalue=(initvalue+",")*member.size
+                    initvalue="["+initvalue[:-1]+"]"
+                    self.__arrayassert(member, (prepend+"."+member.name).strip())
+                code.append(prepend+"."+member.name+"= "+initvalue)
+            else:
+                code.append(prepend+"."+member.name+" = "+
+                            str(self.rules.get_default_value(struct_in.typename, member.name)))
+        return code
+
+    def __structassert(self, cstruct, cstructname):
+        """Return code to check for C array
+        """
+        self.__assertcode.append(self.tab*2+"if(not isinstance("+cstructname+", "+cstruct.typename+")):")
+        self.__assertcode.append(self.tab*3+"return (False, \""+cstructname+" is not class "+cstruct.typename+" as expected.\")")        
+
+    def __addassert(self, prefix):
+        code = []
+        code.append(prefix+"if(not self.__assert()[0]):")
+        code.append(prefix+self.tab+"return None")        
+        return code
+
+    def __stringassert(self, carray, carrayname):
+        """Return code to check for C array
+        """
+        self.__assertcode.append(self.tab*2+"if(not isinstance("+carrayname+", str)):")
+        self.__assertcode.append(self.tab*3+"return (False, \""+carrayname+" is not string as expected.\")")        
+        self.__assertcode.append(self.tab*2+"if(len("+carrayname+") > "+str(carray.size)+"):")      
+        self.__assertcode.append(self.tab*3+"return (False, \""+carrayname+" is not of size "+str(carray.size)+" as expected.\")")
+
+    def __arrayassert(self, carray, carrayname):
+        """Return code to check for C array
+        """
+        if (carray.size == 0):
+            return
+        self.__assertcode.append(self.tab*2+"if(not isinstance("+carrayname+", list)):")
+        self.__assertcode.append(self.tab*3+"return (False, \""+carrayname+" is not list as expected.\")")
+        self.__assertcode.append(self.tab*2+"if(len("+carrayname+") != "+str(carray.size)+"):")
+        self.__assertcode.append(self.tab*3+"return (False, \""+carrayname+" is not of size "+str(carray.size)+" as expected.\")") 
+
+    def codeassert(self, struct_in):
+        """Return code for sanity checking
+        """
+        code = []
+        code.append(self.tab+"def __assert(self):")
+        code.append(self.tab*2+"\"\"\"Sanity check")
+        code.append(self.tab*2+"\"\"\"")
+        enforce = self.rules.get_enforced_map(struct_in.typename)
+        if (enforce != None):
+            for line in enforce:
+                code.append(self.tab*2+line)
+        code.extend(self.__assertcode)
+        code.append(self.tab*2+"return (True, None)")
+        return code
+
+    def codepack(self, struct_in, prefix="!"):
+        """Return code that pack struct
+        """
+        code = []
+        code.append(self.tab+"def pack(self, assertstruct=True):")
+        code.append(self.tab*2+"\"\"\"Pack message")
+        code.append(self.tab*2+"Packs empty array used as placeholder")
+        code.append(self.tab*2+"\"\"\"")
+        code.append(self.tab*2+"if(assertstruct):")
+        code.extend(self.__addassert(self.tab*3))
+        code.append(self.tab*2+"packed = \"\"")
+        primPattern = ""
+        primMemberNames = []
+        for member in struct_in.members:
+            if (isinstance(member, cheader.cprimitive)):
+                #Primitives
+                primPattern += self.__c2py.structmap[member.typename]
+                primMemberNames.append("self."+member.name)
+            else:
+                (primPattern, primMemberNames) = \
+                              self.__codepackprimitive(code, primPattern,
+                                                       primMemberNames, prefix)
+                if (isinstance(member, cheader.cstruct)):
+                    #Struct
+                    code.append(self.tab*2+"packed += self."+member.name+".pack()")
+                elif (isinstance(member, cheader.carray) and member.typename == "char"):
+                    #String
+                    code.append(self.tab*2+"packed += self."+member.name+".ljust("+\
+                                str(member.size)+",'\\0')")
+                elif (isinstance(member, cheader.carray) and \
+                      isinstance(member.object, cheader.cprimitive)):
+                    #Array of Primitives
+                    expandedarr = ""
+                    if (member.size != 0):
+                        for x in range(0, member.size):
+                            expandedarr += ", self."+member.name+"["+\
+                                           str(x).strip()+"]"
+                        code.append(self.tab*2+"packed += struct.pack(\""+prefix+\
+                                    self.__c2py.structmap[member.object.typename]*member.size+\
+                                    "\""+expandedarr+")")
+                    else:
+                        code.append(self.tab*2+"for i in self."+member.name+":")
+                        code.append(self.tab*3+"packed += struct.pack(\""+\
+                                    prefix+self.__c2py.get_pattern(member.object)+\
+                                    "\",i)")
+                elif (isinstance(member, cheader.carray) and \
+                      isinstance(member.object, cheader.cstruct)):
+                    #Array of struct
+                    if (member.size != 0):
+                        for x in range(0, member.size):
+                            code.append(self.tab*2+"packed += self."+member.name+"["+\
+                                        str(x).strip()+"].pack()")
+                    else:
+                        code.append(self.tab*2+"for i in self."+member.name+":")
+                        code.append(self.tab*3+"packed += i.pack(assertstruct)")
+        #Clear remaining fields
+        (primPattern, primMemberNames) = \
+                      self.__codepackprimitive(code, primPattern,
+                                               primMemberNames, prefix)
+        code.append(self.tab*2+"return packed")
+        return code
+
+    def __codepackprimitive(self, code, primPattern, primMemberNames, prefix):
+        """Return code for packing primitives
+        """
+        if (primPattern != ""):
+            #Clear prior primitives
+            code.append(self.tab*2+"packed += struct.pack(\""+\
+                        prefix+primPattern+"\", "+\
+                        str(primMemberNames).replace("'","")[1:-1]+")")
+        return ("",[])
+
+    def codelen(self, struct_in):
+        """Return code to return length
+        """
+        pattern = "!" + self.__c2py.get_pattern(struct_in)
+        code = []
+        code.append(self.tab+"def __len__(self):")
+        code.append(self.tab*2+"\"\"\"Return length of message")
+        code.append(self.tab*2+"\"\"\"")
+        code.append(self.tab*2+"l = "+str(self.__c2py.get_size(pattern)))
+        for member in struct_in.members:
+            if (isinstance(member, cheader.carray) and member.size == 0):
+                if (isinstance(member.object, cheader.cstruct)):
+                    code.append(self.tab*2+"for i in self."+member.name+":")
+                    code.append(self.tab*3+"l += i.length()")
+                else:
+                    pattern="!"+self.__c2py.get_pattern(member.object)
+                    size=self.__c2py.get_size(pattern)
+                    code.append(self.tab*2+"l += len(self."+member.name+")*"+str(size))
+        code.append(self.tab*2+"return l")
+        return code
+
+    def codeeq(self, struct_in):
+        """Return code to return equality comparisons
+        """
+        code = []
+        code.append(self.tab+"def __eq__(self, other):")
+        code.append(self.tab*2+"\"\"\"Return True if self and other have same values")
+        code.append(self.tab*2+"\"\"\"")
+        code.append(self.tab*2+"if type(self) != type(other): return False")
+        for member in struct_in.members:
+            code.append(self.tab*2 + "if self." + member.name + " !=  other." +
+                        member.name + ": return False")
+        code.append(self.tab*2+"return True")
+        code.append("")
+        code.append(self.tab+"def __ne__(self, other): return not self.__eq__(other)")
+        return code
+
+    def codeshow(self, struct_in):
+        """Return code to print basic members of structure
+        """
+        code = []
+        code.append(self.tab+"def show(self, prefix=''):")
+        code.append(self.tab*2+"\"\"\"" + "Print basic members of structure")
+        code.append(self.tab*2+"\"\"\"")
+        for member in struct_in.members:
+            if re.search('pad', member.name):
+                continue
+            elif (isinstance(member, cheader.cstruct)):
+                code.append(self.tab*2 + "print prefix + '" + 
+                            member.name + ": ' ")
+                code.append(self.tab*2 + "self." + member.name + 
+                            ".show(prefix + '  ')")
+            elif (isinstance(member, cheader.carray) and
+                  not isinstance(member.object, cheader.cprimitive)):
+                code.append(self.tab*2 + "print prefix + '" + member.name +
+                            ": ' ")
+                code.append(self.tab*2 + "for obj in self." + member.name + ":")
+                code.append(self.tab*3 + "obj.show(prefix + '  ')")
+            else:
+                code.append(self.tab*2 + "print prefix + '" + member.name +
+                            ": ' + str(self." + member.name + ")")
+        return code
+
+    def codeunpack(self, struct_in, prefix="!"):
+        """Return code that unpack struct
+        """
+        pattern = self.__c2py.get_pattern(struct_in)
+        structlen = self.__c2py.get_size(prefix + pattern)
+        code = []
+        code.append(self.tab+"def unpack(self, binaryString):")
+        code.append(self.tab*2+"\"\"\"Unpack message")
+        code.append(self.tab*2+"Do not unpack empty array used as placeholder")
+        code.append(self.tab*2+"since they can contain heterogeneous type")
+        code.append(self.tab*2+"\"\"\"")
+        code.append(self.tab*2+"if (len(binaryString) < "+str(structlen)+"):")
+        code.append(self.tab*3+"return binaryString")
+        offset = 0
+        primPattern = ""
+        primMemberNames = []
+        for member in struct_in.members:
+            if (isinstance(member, cheader.cprimitive)):
+                #Primitives
+                primPattern += self.__c2py.structmap[member.typename]
+                primMemberNames.append("self."+member.name)
+            else:
+                (primPattern, primMemberNames, offset) = \
+                              self.__codeunpackprimitive(code, offset, primPattern,
+                                                         primMemberNames, prefix)
+                if (isinstance(member, cheader.cstruct)):
+                    #Struct
+                    code.append(self.tab*2+"self."+member.name+\
+                                ".unpack(binaryString["+str(offset)+":])")
+                    pattern = self.__c2py.get_pattern(member)
+                    offset += self.__c2py.get_size(prefix+pattern)
+                elif (isinstance(member, cheader.carray) and member.typename == "char"):
+                    #String
+                    code.append(self.tab*2+"self."+member.name+\
+                                " = binaryString["+str(offset)+":"+\
+                                str(offset+member.size)+"].replace(\"\\0\",\"\")")
+                    offset += member.size
+                elif (isinstance(member, cheader.carray) and \
+                      isinstance(member.object, cheader.cprimitive)):
+                    #Array of Primitives
+                    expandedarr = ""
+                    if (member.size != 0):
+                        arrpattern = self.__c2py.structmap[member.object.typename]*member.size
+                        for x in range(0, member.size):
+                            expandedarr += "self."+member.name+"["+\
+                                           str(x).strip()+"], "
+                        code.append(self.tab*2+"("+expandedarr[:-2]+") = struct.unpack_from(\""+\
+                                    prefix+arrpattern+\
+                                    "\", binaryString, "+str(offset)+")")
+                        offset += struct.calcsize(prefix + arrpattern)
+                elif (isinstance(member, cheader.carray) and \
+                      isinstance(member.object, cheader.cstruct)):
+                    #Array of struct
+                    astructlen = self.__c2py.get_size("!"+self.__c2py.get_pattern(member.object))
+                    for x in range(0, member.size):
+                        code.append(self.tab*2+"self."+member.name+"["+str(x)+"]"+\
+                                ".unpack(binaryString["+str(offset)+":])")
+                        offset += astructlen
+        #Clear remaining fields
+        (primPattern, primMemberNames, offset) = \
+                      self.__codeunpackprimitive(code, offset, primPattern,
+                                                 primMemberNames, prefix)
+        code.append(self.tab*2+"return binaryString["+str(structlen)+":]");
+        return code
+
+    def __codeunpackprimitive(self, code, offset, primPattern,
+                              primMemberNames, prefix):
+        """Return code for unpacking primitives
+        """
+        if (primPattern != ""):
+            #Clear prior primitives
+            code.append(self.tab*2+"("+str(primMemberNames).replace("'","")[1:-1]+\
+                        ") = struct.unpack_from(\""+\
+                        prefix+primPattern+"\", binaryString, "+str(offset)+")")
+        return ("",[], offset+struct.calcsize(prefix+primPattern))
+
diff --git a/tools/pylibopenflow/pylib/lavi/__init__.py b/tools/pylibopenflow/pylib/lavi/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tools/pylibopenflow/pylib/lavi/__init__.py
diff --git a/tools/pylibopenflow/pylib/lavi/pythonize.py b/tools/pylibopenflow/pylib/lavi/pythonize.py
new file mode 100644
index 0000000..3c150aa
--- /dev/null
+++ b/tools/pylibopenflow/pylib/lavi/pythonize.py
@@ -0,0 +1,74 @@
+"""This module generate Python code for LAVI and messenger
+
+(C) Copyright Stanford University
+Date January 2010
+Created by ykk
+"""
+import cpythonize
+
+class msgrules(cpythonize.rules):
+    """Class that specify rules for pythonization of messenger
+
+    (C) Copyright Stanford University
+    Date January 2010
+    Created by ykk
+    """
+    def __init__(self):
+        """Initialize rules
+        """
+        cpythonize.rules.__init__(self)
+        ##Default values for members
+        #Default values for struct
+        ##Macros to exclude
+        self.excluded_macros = ['MESSAGE_HH__']
+        ##Enforce mapping
+        self.enforced_maps['messenger_msg'] = [ ('type','msg_type') ]
+
+class lavirules(msgrules):
+    """Class that specify rules for pythonization of LAVI messages
+
+    (C) Copyright Stanford University
+    Date January 2010
+    Created by ykk
+    """
+    def __init__(self, laviheader):
+        """Initialize rules
+        """
+        msgrules.__init__(self)
+        ##Default values for members
+        
+        #Default values for struct
+        self.struct_default[('lavi_poll_message',
+                             'header')] = ".type = "+str(laviheader.get_value('LAVIT_POLL'))
+        self.struct_default[('lavi_poll_stop_message',
+                             'header')] = ".type = "+str(laviheader.get_value('LAVIT_POLL_STOP'))
+        ##Macros to exclude
+        self.excluded_macros = ['LAVI_MSG_HH']
+        ##Enforce mapping
+        self.enforced_maps['lavi_header'] = [ ('type','lavi_type') ]
+
+class msgpythonizer(cpythonize.pythonizer):
+    """Class that pythonize C messenger messages
+
+    (C) Copyright Stanford University
+    Date January 2010
+    Created by ykk
+    """
+    def __init__(self, msgheader):
+        """Initialize
+        """
+        rules =  msgrules()
+        cpythonize.pythonizer.__init__(self, msgheader, rules)
+        
+class lavipythonizer(cpythonize.pythonizer):
+    """Class that pythonize C messenger messages
+
+    (C) Copyright Stanford University
+    Date December 2009
+    Created by ykk
+    """
+    def __init__(self, msgheader):
+        """Initialize
+        """
+        rules =  lavirules(msgheader)
+        cpythonize.pythonizer.__init__(self, msgheader, rules)
diff --git a/tools/pylibopenflow/pylib/of/__init__.py b/tools/pylibopenflow/pylib/of/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tools/pylibopenflow/pylib/of/__init__.py
diff --git a/tools/pylibopenflow/pylib/of/msg.py b/tools/pylibopenflow/pylib/of/msg.py
new file mode 100644
index 0000000..8617f56
--- /dev/null
+++ b/tools/pylibopenflow/pylib/of/msg.py
@@ -0,0 +1,117 @@
+"""This module parses OpenFlow packets.
+
+Unfortunately, this has to be updated manually for each OpenFlow version
+and packet type.  Ugly.
+
+(C) Copyright Stanford University
+Date October 2009
+Created by ykk
+"""
+class parser:
+    """Parser for  OpenFlow packets
+    
+    (C) Copyright Stanford University
+    Date October 2009
+    Created by ykk
+    """
+    def __init__(self, messages):
+        """Initialize
+        """
+        ##Internal reference to OpenFlow messages
+        self.__messages = messages
+
+    def describe(self, packet):
+        """Parse OpenFlow packet and return string description
+        """
+        dic = self.__messages.peek_from_front("ofp_header", packet)
+        desc = self.header_describe(dic)
+        if (dic["type"][0] == self.__messages.get_value("OFPT_HELLO")):
+            pass
+        elif (dic["type"][0] == self.__messages.get_value("OFPT_SET_CONFIG")):
+            desc += "\n\t"+self.switch_config_describe(packet)
+        elif (dic["type"][0] == self.__messages.get_value("OFPT_FLOW_MOD")):
+            (fmdic, remaining) = self.__messages.unpack_from_front("ofp_flow_mod", packet)
+            desc += self.flow_mod_describe(fmdic, "\n\t")
+            desc += "\n\twith remaining "+str(len(remaining))+" bytes"
+        else:
+            desc += "\n\tUnparsed..."
+        return desc
+
+    def flow_mod_describe(self, packet, prefix=""):
+        """Parse flow mod and return description
+        """
+        dic = self.__assert_dic(packet, "ofp_flow_mod")
+        if (dic == None):
+            return ""
+        return prefix+\
+               "Flow_mod of command "+self.__messages.get_enum_name("ofp_flow_mod_command", dic["command"][0])+\
+               " idle/hard timeout:"+str(dic["idle_timeout"][0])+"/"+str(dic["hard_timeout"][0])+\
+               self.match_describe(dic, "match.", "\n\t")+\
+               prefix+\
+               "(priority:"+str(dic["priority"][0])+\
+               "/buffer id:"+str(dic["buffer_id"][0])+\
+               "/out port:"+str(dic["out_port"][0])+")"
+
+    def match_describe(self, dic, nameprefix="", prefix=""):
+        """Return description for ofp match
+        """
+        return prefix+"match wildcards:%x" % dic[nameprefix+"wildcards"][0]+\
+               " inport="+str(dic[nameprefix+"in_port"][0])+\
+               prefix+"     "+\
+               " ethertype="+str(dic[nameprefix+"dl_type"][0])+\
+               " vlan="+str(dic[nameprefix+"dl_vlan"][0])+\
+               " "+self.eth_describe(dic[nameprefix+"dl_src"])+"->"+\
+               self.eth_describe(dic[nameprefix+"dl_dst"])+\
+               prefix+"     "+\
+               " ipproto="+str(dic[nameprefix+"nw_proto"][0])+\
+               " "+self.ip_describe(dic[nameprefix+"nw_src"][0])+\
+               "->"+self.ip_describe(dic[nameprefix+"nw_src"][0])+\
+               prefix+"     "+\
+               " transport "+str(dic[nameprefix+"tp_src"][0])+\
+               "->"+str(dic[nameprefix+"tp_dst"][0])
+               
+    def switch_config_describe(self, packet):
+        """Parse OpenFlow switch config and return description
+        """
+        dic = self.__assert_dic(packet, "ofp_switch_config")
+        if (dic == None):
+            return ""
+        return "with flag "+str(self.__messages.get_enum_name("ofp_config_flags", dic["flags"][0]))+\
+               " and miss send length "+str(dic["miss_send_len"][0])
+        
+    def header_describe(self, packet):
+        """Parse OpenFlow header and return string description
+        """
+        dic = self.__assert_dic(packet, "ofp_header")
+        if (dic == None):
+            return ""
+        return self.__messages.get_enum_name("ofp_type", dic["type"][0])+" packet "+\
+               "(length:"+str(dic["length"][0])+\
+               "/xid:"+str(dic["xid"][0])+")"
+
+    def ip_describe(self, value):
+        """Return string for ip address
+        """
+        desc = ""
+        for i in range(0,4):
+            (value, cv) = divmod(value, 256)
+            desc = str(cv).strip() +"." + desc
+        return desc
+    
+    def eth_describe(self, etheraddr):
+        """Return string for ethernet address
+        """
+        desc = ""
+        for value in etheraddr:
+            desc += ":"+("%x" % value).zfill(2)
+        return desc[1:]
+
+    def __assert_dic(self, packet, typename):
+        """Assert and ensure dictionary is given
+        """
+        dic = None
+        if (isinstance(packet, str)):
+            dic = self.__messages.peek_from_front(typename, packet)
+        elif (isinstance(packet, dict)):
+            dic = packet
+        return dic
diff --git a/tools/pylibopenflow/pylib/of/network.py b/tools/pylibopenflow/pylib/of/network.py
new file mode 100644
index 0000000..6765a12
--- /dev/null
+++ b/tools/pylibopenflow/pylib/of/network.py
@@ -0,0 +1,191 @@
+"""This module holds the network.
+
+Copyright(C) 2009, Stanford University
+Date October 2009
+Created by ykk
+"""
+import random
+import openflow
+
+class network:
+    """Class holding information about OpenFlow network
+    """
+    def __init__(self):
+        """Initialize
+        """
+        ##List of switches
+        self.switches = []
+        ##Dictionary of links
+        self.links = {}
+        ##Reference to connections
+        self.connections = openflow.connections()
+
+    def add_switch(self, sw):
+        """Add switch to network
+        """
+        self.switches.append(sw)
+        self.connections.add_connection(sw, sw.connection)
+
+    def add_link(self, link):
+        """Add link to network
+        """
+        try:
+            self.links[link.switch1,link.switch2].append(link)
+        except KeyError:
+            self.links[link.switch1,link.switch2] = []
+            self.links[link.switch1,link.switch2].append(link)
+
+class link:
+    """Class to hold information about link
+
+    Copyright(C) 2009, Stanford University
+    Date November 2009
+    Created by ykk
+    """
+    def __init__(self, switch1, switch2):
+        """Initialize link between specified switches
+        """
+        ##Reference to first switch
+        self.switch1 = switch1
+        ##Reference to second switch
+        self.switch2 = switch2
+
+class switch:
+    """Class holding information about OpenFlow switch
+
+    Copyright(C) 2009, Stanford University
+    Date October 2009
+    Created by ykk
+    """
+    def __init__(self, miss_send_len=128,
+                 sock=None, dpid=None, n_buffers=100, n_tables=1,
+                 capability=None):
+        """Initialize switch
+        """
+        ##Socket to controller
+        self.sock = sock
+        ##Datapath id of switch
+        if (dpid != None):
+            self.datapath_id = dpid
+        else:
+            self.datapath_id = random.randrange(1, pow(2,64))
+        ##Number of buffers
+        self.n_buffers = n_buffers
+        ##Number of tables
+        self.n_tables= n_tables
+        ##Capabilities
+        if (isinstance(capability, switch_capabilities)):
+            self.capability = capability
+        else:
+            self.capability = switch_capabilities(miss_send_len)
+        ##Valid Actions
+        self.valid_actions = 0
+        ##List of port
+        self.port = []
+
+class switch_capabilities:
+    """Class to hold switch capabilities
+    """
+    def __init__(self, miss_send_len=128):
+        """Initialize
+
+        Copyright(C) 2009, Stanford University
+        Date October 2009
+        Created by ykk
+        """
+        ##Capabilities support by datapath
+        self.flow_stats = True
+        self.table_stats = True
+        self.port_stats = True
+        self.stp = True
+        self.multi_phy_tx = True
+        self.ip_resam = False
+        ##Switch config
+        self.send_exp = None
+        self.ip_frag = 0
+        self.miss_send_len = miss_send_len
+        ##Valid actions
+        self.act_output = True
+        self.act_set_vlan_vid = True
+        self.act_set_vlan_pcp = True
+        self.act_strip_vlan = True
+        self.act_set_dl_src = True
+        self.act_set_dl_dst = True
+        self.act_set_nw_src = True
+        self.act_set_nw_dst = True
+        self.act_set_tp_src = True
+        self.act_set_tp_dst = True
+        self.act_vendor = False
+
+    def get_capability(self, ofmsg):
+        """Return value for uint32_t capability field
+        """
+        value = 0
+        if (self.flow_stats):
+            value += ofmsg.get_value("OFPC_FLOW_STATS")
+        if (self.table_stats):
+            value += ofmsg.get_value("OFPC_TABLE_STATS")
+        if (self.port_stats):
+            value += ofmsg.get_value("OFPC_PORT_STATS")
+        if (self.stp):
+            value += ofmsg.get_value("OFPC_STP")
+        if (self.multi_phy_tx):
+            value += ofmsg.get_value("OFPC_MULTI_PHY_TX")
+        if (self.ip_resam):
+            value += ofmsg.get_value("OFPC_IP_REASM")
+        return value
+
+    def get_actions(self, ofmsg):
+        """Return value for uint32_t action field
+        """
+        value = 0
+        if (self.act_output):
+            value += (1 << (ofmsg.get_value("OFPAT_OUTPUT")+1))
+        if (self.act_set_vlan_vid):
+            value += (1 << (ofmsg.get_value("OFPAT_SET_VLAN_VID")+1))
+        if (self.act_set_vlan_pcp):
+            value += (1 << (ofmsg.get_value("OFPAT_SET_VLAN_PCP")+1))
+        if (self.act_strip_vlan):
+            value += (1 << (ofmsg.get_value("OFPAT_STRIP_VLAN")+1))
+        if (self.act_set_dl_src):
+            value += (1 << (ofmsg.get_value("OFPAT_SET_DL_SRC")+1))
+        if (self.act_set_dl_dst):
+            value += (1 << (ofmsg.get_value("OFPAT_SET_DL_DST")+1))
+        if (self.act_set_nw_src):
+            value += (1 << (ofmsg.get_value("OFPAT_SET_NW_SRC")+1))
+        if (self.act_set_nw_dst):
+            value += (1 << (ofmsg.get_value("OFPAT_SET_NW_DST")+1))
+        if (self.act_set_tp_src):
+            value += (1 << (ofmsg.get_value("OFPAT_SET_TP_SRC")+1))
+        if (self.act_set_tp_dst):
+            value += (1 << (ofmsg.get_value("OFPAT_SET_TP_DST")+1))
+        return value
+
+class port:
+    """Class to hold information about port
+    
+    Copyright(C) 2009, Stanford University
+    Date October 2009
+    Created by ykk
+    """
+    def __init__(self, port_no, stp=(2 << 8), hw_addr=None, name=""):
+        """Initialize
+        """
+        ##Port properties
+        self.port_no = port_no
+        if (hw_addr != None):
+            self.hw_addr = hw_addr
+        else:
+            self.hw_addr = random.randrange(1, pow(2,48))
+        self.name = name
+        ##Port config
+        self.port_down = False
+        self.no_stp = False
+        self.no_recv = False
+        self.no_recv_stp = False
+        self.no_flood = False
+        self.no_fwd = False
+        self.no_packet_in = False
+        #Port state
+        self.link_down = False
+        self.stp = stp
diff --git a/tools/pylibopenflow/pylib/of/pythonize.py b/tools/pylibopenflow/pylib/of/pythonize.py
new file mode 100644
index 0000000..687512b
--- /dev/null
+++ b/tools/pylibopenflow/pylib/of/pythonize.py
@@ -0,0 +1,57 @@
+"""This module generate Python code for OpenFlow structs.
+
+(C) Copyright Stanford University
+Date December 2009
+Created by ykk
+"""
+import cpythonize
+from config import *
+
+class rules(cpythonize.rules):
+    """Class that specify rules for pythonization of OpenFlow messages
+
+    (C) Copyright Stanford University
+    Date December 2009
+    Created by ykk
+    """
+    def __init__(self, ofmsg):
+        """Initialize rules
+        """
+        cpythonize.rules.__init__(self)
+        ##Reference to ofmsg
+        self.__ofmsg = ofmsg
+        ##Default values for members
+        self.default_values[('ofp_header','version')] = self.__ofmsg.get_value('OFP_VERSION')
+        self.default_values[('ofp_switch_config',\
+                             'miss_send_len')] = self.__ofmsg.get_value('OFP_DEFAULT_MISS_SEND_LEN')
+        for x in ['ofp_flow_mod','ofp_flow_expired','ofp_flow_stats']:
+            self.default_values[(x,'priority')] = self.__ofmsg.get_value('OFP_DEFAULT_PRIORITY')
+        #Default values for struct
+        self.struct_default[('ofp_flow_mod',
+                             'header')] = ".type = OFPT_FLOW_MOD"
+#                             'header')] = ".type = "+str(self.__ofmsg.get_value('OFPT_FLOW_MOD'))
+        ##Macros to exclude
+        self.excluded_macros = ['OFP_ASSERT(EXPR)','OFP_ASSERT(_EXPR)','OFP_ASSERT',
+                                'icmp_type','icmp_code','OFP_PACKED',
+                                'OPENFLOW_OPENFLOW_H']
+        ##Enforce mapping
+        if GEN_ENUM_VALUES_LIST:
+            self.enforced_maps['ofp_header'] = [ ('type','ofp_type_values') ]
+        elif GEN_ENUM_DICTIONARY:
+            self.enforced_maps['ofp_header'] = \
+                [ ('type','ofp_type_map.values()') ]
+        
+class pythonizer(cpythonize.pythonizer):
+    """Class that pythonize C structures of OpenFlow messages
+
+    (C) Copyright Stanford University
+    Date December 2009
+    Created by ykk
+    """
+    def __init__(self, ofmsg):
+        """Initialize
+        """
+        ofrules =  rules(ofmsg)
+        cpythonize.pythonizer.__init__(self, ofmsg, ofrules)
+        ##Reference to OpenFlow message class
+        self.__ofmsg = ofmsg
diff --git a/tools/pylibopenflow/pylib/of/simu.py b/tools/pylibopenflow/pylib/of/simu.py
new file mode 100644
index 0000000..508b076
--- /dev/null
+++ b/tools/pylibopenflow/pylib/of/simu.py
@@ -0,0 +1,144 @@
+"""This module simulates the network.
+
+Copyright(C) 2009, Stanford University
+Date November 2009
+Created by ykk
+"""
+import openflow
+import output
+import of.msg
+import of.network
+
+class network(of.network.network):
+    """Class to simulate OpenFlow network
+
+    Copyright(C) 2009, Stanford University
+    Date November 2009
+    Created by ykk
+    """
+    def __init__(self):
+        """Initialize network
+        """
+        of.network.network.__init__(self)
+        ##Name of use for output
+        self.name = self.__class__.__name__+str(id(self))
+
+class link(of.network.link):
+    """Class to simulate link
+
+    Copyright(C) 2009, Stanford University
+    Date November 2009
+    Created by ykk
+    """
+    def __init__(self, switch1, switch2, isUp=True):
+        """Initialize link
+        """
+        of.network.link.__init__(self, switch1, switch2)
+        ##Name of use for output
+        self.name = self.__class__.__name__+str(id(self))
+        ##Indicate if link is up
+        self.isUp = isUp
+
+class switch(of.network.switch):
+    """Class to simulate OpenFlow switch
+
+    Copyright(C) 2009, Stanford University
+    Date November 2009
+    Created by ykk
+    """
+    def __init__(self,  messages, controller, port, miss_send_len=128,
+                 dpid=None, n_buffers=100, n_tables=1,
+                 capability=None, parser=None, connection=None):
+        """Initialize switch
+        """
+        of.network.switch.__init__(self,  miss_send_len,
+                                   None, dpid, n_buffers, n_tables,
+                                   capability)
+        ##Name of use for output
+        self.name = self.__class__.__name__+str(id(self))
+        ##Reference to OpenFlow messages
+        self.__messages = messages
+        ##Reference to connection
+        self.connection = openflow.tcpsocket(messages, controller, port)
+        self.sock = self.connection.sock
+        ##Reference to Parser
+        self.parser = None
+        if (parser == None):
+            self.parser = of.msg.parser(messages)
+        else:
+            self.parser = parser
+
+    def receive_openflow(self, packet):
+        """Switch receive OpenFlow packet, and respond accordingly
+        """
+        dic = self.__messages.peek_from_front("ofp_header", packet)
+        if (dic["type"][0] == self.__messages.get_value("OFPT_HELLO")):
+            output.dbg("Receive hello", self.name)
+        elif (dic["type"][0] == self.__messages.get_value("OFPT_ECHO_REQUEST")):
+            self.reply_echo(dic["xid"][0])
+        elif (dic["type"][0] == self.__messages.get_value("OFPT_FEATURES_REQUEST")):
+            self.reply_features(dic["xid"][0])
+        elif (dic["type"][0] == self.__messages.get_value("OFPT_FLOW_MOD")):
+            self.handle_flow_mod(packet)
+        else:
+            output.dbg("Unprocessed message "+self.parser.header_describe(dic),
+                       self.name)
+
+    def send_hello(self):
+        """Send hello
+        """
+        self.connection.structsend("ofp_hello",
+                                   0, self.__messages.get_value("OFPT_HELLO"),
+                                   0, 0)
+        output.dbg("Send hello",self.name)
+
+    def send_packet(self, inport, bufferid=None, packet="", xid=0, reason=None):
+        """Send packet in
+        Assume no match as reason, bufferid = 0xFFFFFFFF,
+        and empty packet by default
+        """
+        if (reason == None):
+            reason = self.__messages.get_value("OFPR_NO_MATCH")
+        if (bufferid == None):
+            bufferid = int("0xFFFFFFFF",16)
+        pktin = self.__messages.pack("ofp_packet_in",
+                                     0, self.__messages.get_value("OFPT_PACKET_IN"),
+                                     0, xid, #header
+                                     bufferid, len(packet),
+                                     inport, reason, 0)
+        self.connection.structsend_raw(pktin+packet)
+        output.dbg("Send packet ",self.name)
+
+    def send_echo(self, xid=0):
+        """Send echo
+        """
+        self.connection.structsend_xid("ofp_header",
+                                       0, self.__messages.get_value("OFPT_ECHO_REQUEST"),
+                                       0, xid)
+        output.dbg("Send echo", self.name)
+
+    def reply_echo(self, xid):
+        """Reply to echo request
+        """
+        self.connection.structsend_xid("ofp_header",
+                                       0, self.__messages.get_value("OFPT_ECHO_REPLY"),
+                                       0, xid)                                 
+        output.dbg("Reply echo of xid:"+str(xid),self.name)
+
+    def reply_features(self, xid):
+        """Reply to feature request
+        """
+        self.connection.structsend_xid("ofp_switch_features",
+                                       0, self.__messages.get_value("OFPT_FEATURES_REPLY"),
+                                       0, xid,
+                                       self.datapath_id, self.n_buffers,
+                                       self.n_tables,0,0,0,
+                                       self.capability.get_capability(self.__messages),
+                                       self.capability.get_actions(self.__messages))
+        output.dbg("Replied features request of xid "+str(xid), self.name)
+        
+    def handle_flow_mod(self, packet):
+        """Handle flow mod: just print it here
+        """
+        output.dbg(self.parser.flow_mod_describe(packet), self.name)
+        
diff --git a/tools/pylibopenflow/pylib/openflow.py b/tools/pylibopenflow/pylib/openflow.py
new file mode 100644
index 0000000..25945b9
--- /dev/null
+++ b/tools/pylibopenflow/pylib/openflow.py
@@ -0,0 +1,336 @@
+"""This module exports OpenFlow protocol to Python.
+
+(C) Copyright Stanford University
+Date October 2009
+Created by ykk
+"""
+import c2py
+import cheader
+import os
+import socket
+import select
+import struct
+import time
+
+class messages(cheader.cheaderfile,c2py.cstruct2py,c2py.structpacker):
+    """Class to handle OpenFlow messages
+
+    (C) Copyright Stanford University
+    Date October 2009
+    Created by ykk
+    """
+    def __init__(self, openflow_headerfile=None):
+        """Initialize with OpenFlow header file
+
+        If filename is not provided, check the environment
+        variable PYLIB_OPENFLOW_HEADER and search for openflow.h
+        """
+        if (openflow_headerfile != None):
+            cheader.cheaderfile.__init__(self, openflow_headerfile)
+        else:
+            #Check environment variable
+            path = os.getenv("PYLIB_OPENFLOW_HEADER")
+            if not path:
+                print "PYLIB_OPENFLOW_HEADER is not set in environment"
+                sys.exit(2)
+            cheader.cheaderfile.__init__(self, path+"/openflow.h")
+        #Initialize cstruct2py
+        c2py.cstruct2py.__init__(self)
+        #Initalize packet
+        c2py.structpacker.__init__(self, "!")
+        ##Cached patterns
+        self.patterns={}
+        for (cstructname, cstruct) in self.structs.items():
+            self.patterns[cstructname] = self.get_pattern(cstruct)
+
+    def get_size(self, ctype):
+        """Get size for ctype or name of type.
+        Return None if ctype is not expanded or
+        type with name is not found.
+        """
+        pattern = self.get_pattern(ctype)
+        if (pattern != None):
+            return c2py.cstruct2py.get_size(self,pattern)
+    
+    def get_pattern(self,ctype):
+        """Get pattern string for ctype or name of type.
+        Return None if ctype is not expanded or
+        type with name is not found.
+        """
+        if (isinstance(ctype, str)):
+            #Is name
+            return self.patterns[ctype]
+        else:
+            return c2py.cstruct2py.get_pattern(self, ctype)
+        
+    def pack(self, ctype, *arg):
+        """Pack packet accordingly ctype or name of type provided.
+        Return struct packed.
+        """
+        if (isinstance(ctype, str)):
+            return struct.pack(self.prefix+self.patterns[ctype], *arg)
+        else:
+            return c2py.structpacker.pack(self, ctype, *arg)
+
+    def peek_from_front(self, ctype, binaryString, returnDictionary=True):
+        """Unpack packet using front of the packet,
+        accordingly ctype or name of ctype provided.
+
+        Return dictionary of values indexed by arg name, 
+        if ctype is known struct/type and returnDictionary is True,
+        else return array of data unpacked.
+        """
+        if (isinstance(ctype,str)):
+            data = c2py.structpacker.peek_from_front(self,
+                                                     self.patterns[ctype],
+                                                     binaryString,
+                                                     returnDictionary)
+            return self.data2dic(self.structs[ctype], data)
+        else:
+            return c2py.structpacker.peek_from_front(self,
+                                                     ctype,
+                                                     binaryString,
+                                                     returnDictionary)
+        
+    def unpack_from_front(self, ctype, binaryString, returnDictionary=True):
+        """Unpack packet using front of packet,
+        accordingly ctype or name of ctype provided.
+
+        Return (dictionary of values indexed by arg name, 
+        remaining binary string) if ctype is known struct/type
+        and returnDictionary is True,
+        else return (array of data unpacked, remaining binary string).
+        """
+        if (isinstance(ctype,str)):
+            (data, remaining) = c2py.structpacker.unpack_from_front(self,
+                                                                    self.patterns[ctype],
+                                                                    binaryString,
+                                                                    returnDictionary)
+            return (self.data2dic(self.structs[ctype], data), remaining)
+        else:
+            return c2py.structpacker.unpack_from_front(self,
+                                                       ctype,
+                                                       binaryString,
+                                                       returnDictionary)
+
+class connection:
+    """Class to hold a connection.
+
+    (C) Copyright Stanford University
+    Date October 2009
+    Created by ykk
+    """
+    def __init__(self, messages, sock=None):
+        """Initialize
+        """
+        ##Reference to socket
+        self.sock = sock
+        ##Internal reference to OpenFlow messages
+        self._messages = messages
+        ##Buffer
+        self.buffer = ""
+        ##Header length for OpenFlow
+        self.__header_length = self._messages.get_size("ofp_header")
+
+    def send(self, msg):
+        """Send bare message (given as binary string)
+        """
+        raise NotImplementedError()
+
+    def structsend(self, ctype, *arg):
+        """Build and send message.
+        """
+        self.send(self._messages.pack(ctype, *arg))
+
+    def receive(self, maxlength=1024):
+       """Receive raw in non-blocking way.
+
+       Return buffer
+       """
+       if (select.select([self.sock],[],[],0)[0]):
+           self.buffer += self.sock.recv(maxlength)
+       return self.buffer
+
+    def buffer_has_msg(self):
+        """Check if buffer has a complete message
+        """
+        #Check at least ofp_header is received
+        if (len(self.buffer) < self.__header_length):
+            return False
+        values = self._messages.peek_from_front("ofp_header", self.buffer)
+        return (len(self.buffer) >= values["length"][0])
+
+    def get_msg(self):
+        """Get message from current buffer
+        """
+        if (self.buffer_has_msg()):
+            values = self._messages.peek_from_front("ofp_header", self.buffer)
+            msg = self.buffer[:values["length"][0]]
+            self.buffer = self.buffer[values["length"][0]:]
+            return msg
+        else:
+            return None
+
+    def msgreceive(self, blocking=False, pollInterval=0.001):
+        """Receive OpenFlow message.
+
+        If non-blocking, can return None.
+        """
+        self.receive()
+        if (self.buffer_has_msg()):
+            return self.get_msg()
+        if (blocking):
+            while (not self.buffer_has_msg()):
+                time.sleep(pollInterval)
+                self.receive()
+        return self.get_msg()
+
+class safeconnection(connection):
+    """OpenFlow connection with safety checks
+    
+    (C) Copyright Stanford University
+    Date October 2009
+    Created by ykk
+    """
+    def __init__(self, messages, sock=None, version=None,
+                 xidstart = 0, autoxid=True):
+        """Initialize with OpenFlow version.
+        """
+        connection.__init__(self, messages, sock)
+        ##OpenFlow version
+        if (version != None):
+            self.version = version
+        else:
+            self.version = messages.get_value("OFP_VERSION")
+        ##xid Counter
+        self.nextxid = xidstart
+        ##Automatic xid
+        self.autoxid = autoxid
+        ##Miss auto xid
+        self.skipautoxid = 0
+
+    def skip_auto_xid(self, n):
+        """Miss automatic xid for the next n packets
+        """
+        self.skipautoxid = n
+
+    def structsend_xid(self, ctype, *arg):
+        """Build and send message, populating header automatically.
+        Type and xid of message is not populated.
+        """
+        self.skipautoxid+=1
+        self.structsend(ctype, *arg)
+
+    def structsend(self, ctype, *arg):
+        """Build and send message, populating header automatically.
+        Type of message is not populated
+        """
+        msg = self._messages.pack(ctype, *arg)
+        self.structsend_raw(msg)
+        
+    def structsend_raw(self, msg):
+        """Check ofp_header and ensure correctness before sending.
+        """
+        (dic, remaining) = self._messages.unpack_from_front("ofp_header", msg)
+        #Amend header
+        if (self.version != None):
+            dic["version"][0] = self.version
+        if (self.autoxid and (self.skipautoxid == 0)):
+            dic["xid"][0] = self.nextxid
+            self.nextxid+=1
+        if (self.skipautoxid != 0):
+            self.skipautoxid-=1
+        dic["length"][0] = len(remaining)+8
+        #Send message
+        self.send(self._messages.pack("ofp_header",
+                                      dic["version"][0],
+                                      dic["type"][0],
+                                      dic["length"][0],
+                                      dic["xid"][0])+\
+                  remaining)
+
+class tcpsocket(safeconnection):
+    """Class to hold connection
+
+    (C) Copyright Stanford University
+    Date October 2009
+    Created by ykk
+    """
+    def __init__(self, messages, host, port):
+        """Initialize TCP socket to host and port
+        """
+        safeconnection.__init__(self, messages)
+        ##Reference to socket
+        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        self.sock.connect((host, port))
+        self.sock.setblocking(False)
+        self.sock.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 0)
+
+    def __del__(self):
+        """Terminate connection
+        """
+        self.sock.shutdown(1)
+        self.sock.close()
+
+    def send(self, msg):
+        """Send raw message (binary string)
+        """
+        self.sock.sendall(msg)
+
+class connections:
+    """Class to hold multiple connections
+    
+    (C) Copyright Stanford University
+    Date November 2009
+    Created by ykk
+    """
+    def __init__(self):
+        """Initialize
+        """
+        ##List of sockets
+        self.__sockets = []
+        ##Dicionary of sockets to connection
+        self.__connections = {}
+        
+    def add_connection(self, reference, connect):
+        """Add connection with opaque reference object
+        """
+        if (not isinstance(connect,connection)): 
+            raise RuntimeError("Connection must be openflow.connection!")
+        self.__sockets.append(connect.sock)
+        self.__connections[connect.sock] = (reference, connect)
+
+    def receive(self, maxlength=1024):
+        """Receive raw in non-blocking way
+        """
+        read_ready = select.select(self.__sockets,[],[],0)[0]
+        for sock in read_ready:
+            self.__connections[sock][1].receive(maxlength)
+        
+    def has_msg(self):
+        """Check if any of the connections has a message
+
+        Return (reference,connection) with message
+        """
+        for sock, refconnect in self.__connections.items():
+            if (refconnect[1].buffer_has_msg()):
+                return refconnect
+        return None
+
+    def msgreceive(self, blocking=False, pollInterval=0.001):
+        """Receive OpenFlow message.
+
+        If non-blocking, can return None.
+        """
+        self.receive()
+        c = self.has_msg()
+        if (c != None):
+            return (c[0],c[1].get_msg())
+        if (blocking):
+            while (c == None):
+                time.sleep(pollInterval)
+                self.receive()
+                c = self.has_msg()
+        else:
+            return (None, None)
+        return (c[0],c[1].get_msg())
diff --git a/tools/pylibopenflow/pylib/output.py b/tools/pylibopenflow/pylib/output.py
new file mode 100644
index 0000000..64df4f5
--- /dev/null
+++ b/tools/pylibopenflow/pylib/output.py
@@ -0,0 +1,85 @@
+"""This module implements output printing.
+
+Output are divided into 4 levels and
+can be configured for different verbosity
+
+Copyright(C) 2009, Stanford University
+Date August 2009
+Created by ykk
+"""
+
+##Various output modes
+MODE = {}
+MODE["ERR"] = 0
+MODE["WARN"] = 1
+MODE["INFO"] = 2
+MODE["DBG"] = 3
+
+#Global mode
+global output_mode
+output_mode = None
+
+def set_mode(msg_mode, who=None):
+    """Set the message mode for who
+    If who is None, set global mode
+    """
+    global output_mode
+    if (output_mode == None):
+        output_mode = {}
+        output_mode["global"] = MODE["WARN"]
+        output_mode["DBG"] = []
+        output_mode["INFO"] = []
+        output_mode["WARN"] = []
+
+    #Set global mode
+    if (who == None):
+        output_mode["global"] = MODE[msg_mode]
+        return
+    
+    #Individual mode
+    if (msg_mode == "ERR"):
+        return
+    for mode in ["WARN","INFO","DBG"]:
+        if (not (who in mode[mode])):
+            mode[mode].append(who)
+        if (msg_mode == mode):
+            return
+    
+def output(msg_mode, msg, who=None):
+    """Print message
+    """
+    global output_mode
+    if (output_mode == None):
+        raise RuntimeException("Output mode is not set")
+
+    #Indicate who string
+    if (who == None):
+        whostr = ""
+    else:
+        whostr = who+":"
+
+    #Print output 
+    if (MODE[msg_mode] <= output_mode["global"]):
+        print msg_mode.ljust(4, ' ')+"|"+whostr+msg
+    elif (who in output_mode[msg_mode]):
+        print msg_mode.ljust(4, ' ')+"|"+whostr+msg
+        
+def err(msg, who=None):
+    """Print error messages
+    """
+    output("ERR", msg, who)
+
+def warn(msg, who=None):
+    """Print warning messages
+    """
+    output("WARN", msg, who)
+
+def info(msg, who=None):
+    """Print informational messages
+    """
+    output("INFO", msg, who)
+
+def dbg(msg, who=None):
+    """Print debug messages
+    """
+    output("DBG", msg, who)