blob: 12520ce8943a4e8c8ec74f077cd9944b9f19cfc9 [file] [log] [blame]
Rich Lane9cfa1652013-10-01 21:24:04 -07001:: # Copyright 2013, Big Switch Networks, Inc.
2:: #
3:: # LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
4:: # the following special exception:
5:: #
6:: # LOXI Exception
7:: #
8:: # As a special exception to the terms of the EPL, you may distribute libraries
9:: # generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
10:: # that copyright and licensing notices generated by LoxiGen are not altered or removed
11:: # from the LoxiGen Libraries and the notice provided below is (i) included in
12:: # the LoxiGen Libraries, if distributed in source code form and (ii) included in any
13:: # documentation for the LoxiGen Libraries, if distributed in binary form.
14:: #
15:: # Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
16:: #
17:: # You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
18:: # a copy of the EPL at:
19:: #
20:: # http://www.eclipse.org/legal/epl-v10.html
21:: #
22:: # Unless required by applicable law or agreed to in writing, software
23:: # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
24:: # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
25:: # EPL for the specific language governing permissions and limitations
26:: # under the EPL.
27::
Andreas Wundsamc2ce5fa2013-11-15 15:20:11 -080028:: import loxi_globals
29:: ir = loxi_globals.ir
Rich Laneeb10d162013-10-01 21:15:35 -070030:: include('_copyright.lua')
Rich Lane422d1b12013-06-04 13:09:17 -070031
Rich Lane9331e022013-11-20 12:41:25 -080032-- Copy this file to your wireshark plugin directory:
33-- Linux / OS X: ~/.wireshark/plugins/
34-- Windows: C:\Documents and Settings\<username>\Application Data\Wireshark\plugins\
35-- You may need to create the directory.
36
37-- The latest version of this dissector is always available at:
38-- http://www.projectfloodlight.org/openflow.lua
39
Rich Lane872b95a2013-06-17 18:39:14 -070040:: include('_ofreader.lua')
41
Rich Lane7708c182013-10-01 23:27:27 -070042:: include('_oftype_readers.lua')
43
Rich Lane422d1b12013-06-04 13:09:17 -070044p_of = Proto ("of", "OpenFlow")
45
Rich Lane972be332013-06-04 13:36:48 -070046local openflow_versions = {
Andreas Wundsamc2ce5fa2013-11-15 15:20:11 -080047:: for version in loxi_globals.OFVersions.all_supported:
48 [${version.wire_version}] = "${version.version}",
Rich Lane972be332013-06-04 13:36:48 -070049:: #endfor
Rich Lane422d1b12013-06-04 13:09:17 -070050}
51
Rich Lane972be332013-06-04 13:36:48 -070052:: for version, ofproto in ir.items():
53:: for enum in ofproto.enums:
Andreas Wundsamc2ce5fa2013-11-15 15:20:11 -080054local enum_v${version.wire_version}_${enum.name} = {
Rich Lane972be332013-06-04 13:36:48 -070055:: for (name, value) in enum.values:
56 [${value}] = "${name}",
57:: #endfor
58}
59
60:: #endfor
61
62:: #endfor
63
Tomasz635e20a2013-10-23 16:14:29 -070064
Rich Lane364e0292013-10-01 21:05:57 -070065fields = {}
Rich Laneb014bcf2013-06-19 11:14:11 -070066:: for field in fields:
Rich Lane4df40f32013-10-08 15:40:39 -070067:: if field.type in ["uint8", "uint16", "uint32", "uint64"]:
Rich Lane52452662013-10-25 13:34:42 -070068fields[${repr(field.fullname)}] = ProtoField.${field.type}("${field.fullname}", "${field.name}", base.${field.base}, ${field.enum_table})
Rich Lane4df40f32013-10-08 15:40:39 -070069:: elif field.type in ["ipv4", "ipv6", "ether", "bytes", "stringz"]:
70fields[${repr(field.fullname)}] = ProtoField.${field.type}("${field.fullname}", "${field.name}")
71:: else:
72:: raise NotImplementedError("unknown Wireshark type " + field.type)
73:: #endif
Rich Laneb014bcf2013-06-19 11:14:11 -070074:: #endfor
Rich Lane422d1b12013-06-04 13:09:17 -070075
76p_of.fields = {
Rich Laneb014bcf2013-06-19 11:14:11 -070077:: for field in fields:
Rich Lane364e0292013-10-01 21:05:57 -070078 fields[${repr(field.fullname)}],
Rich Laneb014bcf2013-06-19 11:14:11 -070079:: #endfor
Rich Lane422d1b12013-06-04 13:09:17 -070080}
81
Rich Lane4bbdcf52013-10-01 22:07:35 -070082-- Subclass maps for virtual classes
Rich Lane96641df2013-06-10 13:36:35 -070083:: for version, ofproto in ir.items():
Rich Lane4bbdcf52013-10-01 22:07:35 -070084:: for ofclass in ofproto.classes:
85:: if ofclass.virtual:
Andreas Wundsamc2ce5fa2013-11-15 15:20:11 -080086${ofclass.name}_v${version.wire_version}_dissectors = {}
Tomasza19e9d22013-12-08 11:18:11 -080087${ofclass.name}_v${version.wire_version}_dissectors_virtual = {}
Rich Lane4bbdcf52013-10-01 22:07:35 -070088:: #endif
Rich Lane96641df2013-06-10 13:36:35 -070089:: #endfor
Rich Lane96641df2013-06-10 13:36:35 -070090:: #endfor
91
Tomasza19e9d22013-12-08 11:18:11 -080092:: virtual_classes = []
Rich Lane4bbdcf52013-10-01 22:07:35 -070093
Tomasza19e9d22013-12-08 11:18:11 -080094--- Dissectors for each class
Rich Lane96641df2013-06-10 13:36:35 -070095:: for version, ofproto in ir.items():
96:: for ofclass in ofproto.classes:
Andreas Wundsamc2ce5fa2013-11-15 15:20:11 -080097:: name = 'dissect_%s_v%d' % (ofclass.name, version.wire_version)
Tomasza19e9d22013-12-08 11:18:11 -080098:: name_virtual = '%s_v%d_dissectors' % (ofclass.name, version.wire_version)
Rich Lane7708c182013-10-01 23:27:27 -070099:: include('_ofclass_dissector.lua', name=name, ofclass=ofclass, version=version)
Rich Lane4bbdcf52013-10-01 22:07:35 -0700100:: if ofclass.superclass:
Andreas Wundsamc2ce5fa2013-11-15 15:20:11 -0800101:: discriminator = ofclass.superclass.discriminator
Rich Lane586864e2013-10-01 23:26:35 -0700102:: discriminator_value = ofclass.member_by_name(discriminator.name).value
Tomasza19e9d22013-12-08 11:18:11 -0800103:: if ofclass.virtual:
104:: if discriminator_value not in virtual_classes:
105:: virtual_classes.append(discriminator_value)
106:: #endif
107${ofclass.superclass.name}_v${version.wire_version}_dissectors_virtual[${discriminator_value}] = ${name_virtual}
108:: #endif
Andreas Wundsamc2ce5fa2013-11-15 15:20:11 -0800109${ofclass.superclass.name}_v${version.wire_version}_dissectors[${discriminator_value}] = ${name}
Rich Lane96641df2013-06-10 13:36:35 -0700110
111:: #endif
112:: #endfor
113:: #endfor
114
Tomasza19e9d22013-12-08 11:18:11 -0800115local virtual_classes = {
116:: for classes in virtual_classes:
117 [${classes}] = ${classes},
118:: #endfor
119}
120
Rich Lane4bbdcf52013-10-01 22:07:35 -0700121local of_message_dissectors = {
122:: for version in ir:
Andreas Wundsamc2ce5fa2013-11-15 15:20:11 -0800123 [${version.wire_version}] = of_header_v${version.wire_version}_dissectors,
Rich Lane4bbdcf52013-10-01 22:07:35 -0700124:: #endfor
125}
126
Tomasza19e9d22013-12-08 11:18:11 -0800127local of_message_dissectors_virtual = {
128:: for version in ir:
129 [${version.wire_version}] = of_header_v${version.wire_version}_dissectors_virtual,
130:: #endfor
131}
132
Tomasz742c2ba2013-10-24 22:35:45 -0700133local of_oxm_dissectors = {
134:: for version in ir:
Andreas Wundsamc2ce5fa2013-11-15 15:20:11 -0800135 [${version.wire_version}] = of_oxm_v${version.wire_version}_dissectors,
Tomasz742c2ba2013-10-24 22:35:45 -0700136:: #endfor
137}
138
139local of_action_dissectors = {
140:: for version in ir:
Andreas Wundsamc2ce5fa2013-11-15 15:20:11 -0800141 [${version.wire_version}] = of_action_v${version.wire_version}_dissectors,
Tomasz742c2ba2013-10-24 22:35:45 -0700142:: #endfor
143}
144
145local of_instruction_dissectors = {
146:: for version in ir:
Andreas Wundsamc2ce5fa2013-11-15 15:20:11 -0800147 [${version.wire_version}] = of_instruction_v${version.wire_version}_dissectors,
Tomasz742c2ba2013-10-24 22:35:45 -0700148:: #endfor
149}
150
Tomasza17a6692013-10-30 17:34:18 -0700151local of_bucket_dissectors = {
152:: for version in ir:
Andreas Wundsamc2ce5fa2013-11-15 15:20:11 -0800153 [${version.wire_version}] = dissect_of_bucket_v${version.wire_version},
Tomasza17a6692013-10-30 17:34:18 -0700154:: #endfor
155}
156
Tomaszc595d5b2013-11-02 13:30:32 -0700157local of_port_desc_dissectors = {
158:: for version in ir:
Andreas Wundsamc2ce5fa2013-11-15 15:20:11 -0800159 [${version.wire_version}] = dissect_of_port_desc_v${version.wire_version},
Tomaszc595d5b2013-11-02 13:30:32 -0700160:: #endfor
161}
162
163local of_stats_reply_dissectors = {
164:: for version in ir:
Andreas Wundsamc2ce5fa2013-11-15 15:20:11 -0800165 [${version.wire_version}] = of_stats_reply_v${version.wire_version}_dissectors,
Tomaszc595d5b2013-11-02 13:30:32 -0700166:: #endfor
167}
168
169local of_stats_request_dissectors = {
170:: for version in ir:
Andreas Wundsamc2ce5fa2013-11-15 15:20:11 -0800171 [${version.wire_version}] = of_stats_request_v${version.wire_version}_dissectors,
Tomaszc595d5b2013-11-02 13:30:32 -0700172:: #endfor
173}
174
175local of_flow_stats_entry_dissectors = {
176:: for version in ir:
Andreas Wundsamc2ce5fa2013-11-15 15:20:11 -0800177 [${version.wire_version}] = dissect_of_flow_stats_entry_v${version.wire_version},
Tomaszc595d5b2013-11-02 13:30:32 -0700178:: #endfor
179}
180
181local of_port_stats_entry_dissectors = {
182:: for version in ir:
Andreas Wundsamc2ce5fa2013-11-15 15:20:11 -0800183 [${version.wire_version}] = dissect_of_port_stats_entry_v${version.wire_version},
Tomaszc595d5b2013-11-02 13:30:32 -0700184:: #endfor
185}
186
187local of_table_stats_entry_dissectors = {
188:: for version in ir:
Andreas Wundsamc2ce5fa2013-11-15 15:20:11 -0800189 [${version.wire_version}] = dissect_of_table_stats_entry_v${version.wire_version},
Tomaszc595d5b2013-11-02 13:30:32 -0700190:: #endfor
191}
192
193local of_queue_stats_entry_dissectors = {
194:: for version in ir:
Andreas Wundsamc2ce5fa2013-11-15 15:20:11 -0800195 [${version.wire_version}] = dissect_of_queue_stats_entry_v${version.wire_version},
Tomaszc595d5b2013-11-02 13:30:32 -0700196:: #endfor
197}
198
Rich Lane96641df2013-06-10 13:36:35 -0700199function dissect_of_message(buf, root)
Rich Lane93991e42013-10-01 22:24:51 -0700200 local reader = OFReader.new(buf)
Rich Lane422d1b12013-06-04 13:09:17 -0700201 local subtree = root:add(p_of, buf(0))
Rich Lane96641df2013-06-10 13:36:35 -0700202 local version_val = buf(0,1):uint()
Rich Lane422d1b12013-06-04 13:09:17 -0700203 local type_val = buf(1,1):uint()
Rich Laneb017c732013-10-02 14:05:01 -0700204
Tomasza19e9d22013-12-08 11:18:11 -0800205 local virtual_reader = OFReader.new(buf)
206
Rich Laneb017c732013-10-02 14:05:01 -0700207 local protocol = "OF ?"
208 if openflow_versions[version_val] then
209 protocol = "OF " .. openflow_versions[version_val]
Rich Lane96641df2013-06-10 13:36:35 -0700210 end
Tomasza19e9d22013-12-08 11:18:11 -0800211 if virtual_classes[type_val] then
212 info = of_message_dissectors_virtual[version_val][type_val][of_message_dissectors[version_val][type_val](virtual_reader, subtree)](reader, subtree)
213 else
Rich Laneb017c732013-10-02 14:05:01 -0700214 info = of_message_dissectors[version_val][type_val](reader, subtree)
215 end
216
217 return protocol, info
Rich Lane422d1b12013-06-04 13:09:17 -0700218end
219
Tomasz742c2ba2013-10-24 22:35:45 -0700220function dissect_of_oxm(reader, subtree, version_val)
Tomasze0584352013-10-23 16:43:26 -0700221 local type_val = reader.peek(0,4):uint()
Tomasze0584352013-10-23 16:43:26 -0700222 local info = "unknown"
Tomasz742c2ba2013-10-24 22:35:45 -0700223 if of_oxm_dissectors[version_val] and of_oxm_dissectors[version_val][type_val] then
224 info = of_oxm_dissectors[version_val][type_val](reader, subtree)
Tomasze0584352013-10-23 16:43:26 -0700225 end
226
227 return info
228end
Tomasz742c2ba2013-10-24 22:35:45 -0700229
230function dissect_of_action(reader, subtree, version_val)
231 local type_val = reader.peek(0,2):uint()
232 local info = "unknown"
233 if of_action_dissectors[version_val] and of_action_dissectors[version_val][type_val] then
234 info = of_action_dissectors[version_val][type_val](reader, subtree)
235 end
236
237 return info
238end
239
240function dissect_of_instruction(reader, subtree, version_val)
241 local type_val = reader.peek(0,2):uint()
242 local info = "unknown"
243 if of_instruction_dissectors[version_val] and of_instruction_dissectors[version_val][type_val] then
244 info = of_instruction_dissectors[version_val][type_val](reader, subtree)
245 end
246
247 return info
248end
249
Tomasza17a6692013-10-30 17:34:18 -0700250function dissect_of_bucket(reader, subtree, version_val)
251 local info = "unknown"
252 if of_bucket_dissectors[version_val] then
253 info = of_bucket_dissectors[version_val](reader, subtree)
254 end
255
256 return info
257end
258
Tomaszc595d5b2013-11-02 13:30:32 -0700259function dissect_of_port_desc(reader, subtree, version_val)
260 local info = "unknown"
261 if of_port_desc_dissectors[version_val] then
262 info = of_port_desc_dissectors[version_val](reader, subtree)
263 end
264
265 return info
266end
267
268function dissect_of_flow_stats_entry(reader, subtree, version_val)
269 local info = "unknown"
270 if of_flow_stats_entry_dissectors[version_val] then
271 info = of_flow_stats_entry_dissectors[version_val](reader, subtree)
272 end
273
274 return info
275end
276
277function dissect_of_port_stats_entry(reader, subtree, version_val)
278 local info = "unknown"
279 if of_port_stats_entry_dissectors[version_val] then
280 info = of_port_stats_entry_dissectors[version_val](reader, subtree)
281 end
282
283 return info
284end
285
286function dissect_of_table_stats_entry(reader, subtree, version_val)
287 local info = "unknown"
288 if of_table_stats_entry_dissectors[version_val] then
289 info = of_table_stats_entry_dissectors[version_val](reader, subtree)
290 end
291
292 return info
293end
294
295function dissect_of_queue_stats_entry(reader, subtree, version_val)
296 local info = "unknown"
297 if of_queue_stats_entry_dissectors[version_val] then
298 info = of_queue_stats_entry_dissectors[version_val](reader, subtree)
299 end
300
301 return info
302end
303
Rich Lane422d1b12013-06-04 13:09:17 -0700304-- of dissector function
305function p_of.dissector (buf, pkt, root)
Rich Lane422d1b12013-06-04 13:09:17 -0700306 local offset = 0
307 repeat
308 if buf:len() - offset >= 4 then
309 msg_len = buf(offset+2,2):uint()
310 if offset + msg_len > buf:len() then
311 -- we don't have all the data we need yet
312 pkt.desegment_len = offset + msg_len - buf:len()
313 return
314 end
315
Rich Laneb017c732013-10-02 14:05:01 -0700316 protocol, info = dissect_of_message(buf(offset, msg_len), root)
317
318 if offset == 0 then
319 pkt.cols.protocol:clear()
320 pkt.cols.info:clear()
321 else
Rich Lane7b8eaa12013-10-02 14:55:35 -0700322 pkt.cols.protocol:append(" + ")
323 pkt.cols.info:append(" + ")
Rich Laneb017c732013-10-02 14:05:01 -0700324 end
325 pkt.cols.protocol:append(protocol)
326 pkt.cols.info:append(info)
Rich Lane422d1b12013-06-04 13:09:17 -0700327 offset = offset + msg_len
328 else
329 -- we don't have all of length field yet
330 pkt.desegment_len = DESEGMENT_ONE_MORE_SEGMENT
331 return
332 end
333 until offset >= buf:len()
334end
335
336-- Initialization routine
337function p_of.init()
338end
339
Rich Lane88d3afc2013-10-01 21:07:22 -0700340-- register a chained dissector for OpenFlow port numbers
Rich Lane422d1b12013-06-04 13:09:17 -0700341local tcp_dissector_table = DissectorTable.get("tcp.port")
342tcp_dissector_table:add(6633, p_of)
Rich Lane88d3afc2013-10-01 21:07:22 -0700343tcp_dissector_table:add(6653, p_of)