blob: 129bc4551481dae57d9e3f733af186bc876b3f0e [file] [log] [blame]
"""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+"eth_type"][0])+\
" vlan="+str(dic[nameprefix+"vlan_vid"][0])+\
" "+self.eth_describe(dic[nameprefix+"eth_src"])+"->"+\
self.eth_describe(dic[nameprefix+"eth_dst"])+\
prefix+" "+\
" ipproto="+str(dic[nameprefix+"ip_proto"][0])+\
" "+self.ip_describe(dic[nameprefix+"ipv4_src"][0])+\
"->"+self.ip_describe(dic[nameprefix+"ipv4_src"][0])+\
prefix+" "+\
" transport "+str(dic[nameprefix+"tcp_src"][0])+\
"->"+str(dic[nameprefix+"tcp_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