blob: 8617f56e23e44655e75905b771fa2f0d4aa3a222 [file] [log] [blame]
Dan Talaycof75360a2010-02-05 22:22:54 -08001"""This module parses OpenFlow packets.
2
3Unfortunately, this has to be updated manually for each OpenFlow version
4and packet type. Ugly.
5
6(C) Copyright Stanford University
7Date October 2009
8Created by ykk
9"""
10class parser:
11 """Parser for OpenFlow packets
12
13 (C) Copyright Stanford University
14 Date October 2009
15 Created by ykk
16 """
17 def __init__(self, messages):
18 """Initialize
19 """
20 ##Internal reference to OpenFlow messages
21 self.__messages = messages
22
23 def describe(self, packet):
24 """Parse OpenFlow packet and return string description
25 """
26 dic = self.__messages.peek_from_front("ofp_header", packet)
27 desc = self.header_describe(dic)
28 if (dic["type"][0] == self.__messages.get_value("OFPT_HELLO")):
29 pass
30 elif (dic["type"][0] == self.__messages.get_value("OFPT_SET_CONFIG")):
31 desc += "\n\t"+self.switch_config_describe(packet)
32 elif (dic["type"][0] == self.__messages.get_value("OFPT_FLOW_MOD")):
33 (fmdic, remaining) = self.__messages.unpack_from_front("ofp_flow_mod", packet)
34 desc += self.flow_mod_describe(fmdic, "\n\t")
35 desc += "\n\twith remaining "+str(len(remaining))+" bytes"
36 else:
37 desc += "\n\tUnparsed..."
38 return desc
39
40 def flow_mod_describe(self, packet, prefix=""):
41 """Parse flow mod and return description
42 """
43 dic = self.__assert_dic(packet, "ofp_flow_mod")
44 if (dic == None):
45 return ""
46 return prefix+\
47 "Flow_mod of command "+self.__messages.get_enum_name("ofp_flow_mod_command", dic["command"][0])+\
48 " idle/hard timeout:"+str(dic["idle_timeout"][0])+"/"+str(dic["hard_timeout"][0])+\
49 self.match_describe(dic, "match.", "\n\t")+\
50 prefix+\
51 "(priority:"+str(dic["priority"][0])+\
52 "/buffer id:"+str(dic["buffer_id"][0])+\
53 "/out port:"+str(dic["out_port"][0])+")"
54
55 def match_describe(self, dic, nameprefix="", prefix=""):
56 """Return description for ofp match
57 """
58 return prefix+"match wildcards:%x" % dic[nameprefix+"wildcards"][0]+\
59 " inport="+str(dic[nameprefix+"in_port"][0])+\
60 prefix+" "+\
61 " ethertype="+str(dic[nameprefix+"dl_type"][0])+\
62 " vlan="+str(dic[nameprefix+"dl_vlan"][0])+\
63 " "+self.eth_describe(dic[nameprefix+"dl_src"])+"->"+\
64 self.eth_describe(dic[nameprefix+"dl_dst"])+\
65 prefix+" "+\
66 " ipproto="+str(dic[nameprefix+"nw_proto"][0])+\
67 " "+self.ip_describe(dic[nameprefix+"nw_src"][0])+\
68 "->"+self.ip_describe(dic[nameprefix+"nw_src"][0])+\
69 prefix+" "+\
70 " transport "+str(dic[nameprefix+"tp_src"][0])+\
71 "->"+str(dic[nameprefix+"tp_dst"][0])
72
73 def switch_config_describe(self, packet):
74 """Parse OpenFlow switch config and return description
75 """
76 dic = self.__assert_dic(packet, "ofp_switch_config")
77 if (dic == None):
78 return ""
79 return "with flag "+str(self.__messages.get_enum_name("ofp_config_flags", dic["flags"][0]))+\
80 " and miss send length "+str(dic["miss_send_len"][0])
81
82 def header_describe(self, packet):
83 """Parse OpenFlow header and return string description
84 """
85 dic = self.__assert_dic(packet, "ofp_header")
86 if (dic == None):
87 return ""
88 return self.__messages.get_enum_name("ofp_type", dic["type"][0])+" packet "+\
89 "(length:"+str(dic["length"][0])+\
90 "/xid:"+str(dic["xid"][0])+")"
91
92 def ip_describe(self, value):
93 """Return string for ip address
94 """
95 desc = ""
96 for i in range(0,4):
97 (value, cv) = divmod(value, 256)
98 desc = str(cv).strip() +"." + desc
99 return desc
100
101 def eth_describe(self, etheraddr):
102 """Return string for ethernet address
103 """
104 desc = ""
105 for value in etheraddr:
106 desc += ":"+("%x" % value).zfill(2)
107 return desc[1:]
108
109 def __assert_dic(self, packet, typename):
110 """Assert and ensure dictionary is given
111 """
112 dic = None
113 if (isinstance(packet, str)):
114 dic = self.__messages.peek_from_front(typename, packet)
115 elif (isinstance(packet, dict)):
116 dic = packet
117 return dic