1 /* packet-openflow_v1.c
2 * Routines for OpenFlow dissection
3 * Copyright 2013, Anders Broman <anders.broman@ericsson.com>
4 * Copyright 2013, Zoltan Lajos Kis <zoltan.lajos.kis@ericsson.com>
5 *
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
9 *
10 * SPDX-License-Identifier: GPL-2.0-or-later
11 *
12 * Ref https://www.opennetworking.org/sdn-resources/onf-specifications/openflow
13 */
14
15 #include "config.h"
16
17 #include <epan/packet.h>
18 #include <epan/expert.h>
19
20 void proto_register_openflow_v1(void);
21 void proto_reg_handoff_openflow_v1(void);
22
23 static dissector_handle_t eth_withoutfcs_handle;
24
25 /* Initialize the protocol and registered fields */
26 static int proto_openflow_v1 = -1;
27 static int hf_openflow_version = -1;
28 static int hf_openflow_1_0_type = -1;
29 static int hf_openflow_length = -1;
30 static int hf_openflow_xid = -1;
31
32 static int hf_openflow_datapath_id = -1;
33 static int hf_openflow_datapath_mac = -1;
34 static int hf_openflow_datapath_impl = -1;
35 static int hf_openflow_n_buffers = -1;
36 static int hf_openflow_n_tables = -1;
37 /* static int hf_openflow_auxiliary_id = -1; */
38 static int hf_openflow_capabilities = -1;
39 static int hf_openflow_actions = -1;
40 /* static int hf_openflow_reserved32 = -1; */
41 static int hf_openflow_cap_flow_stats = -1;
42 static int hf_openflow_table_stats = -1;
43 static int hf_openflow_port_stats = -1;
44 static int hf_openflow_group_stats = -1;
45 static int hf_openflow_ip_reasm = -1;
46 static int hf_openflow_queue_stats = -1;
47 static int hf_openflow_port_blocked = -1;
48
49 static int hf_openflow_output = -1; /* Output to switch port. */
50 static int hf_openflow_set_vlan_vid = -1; /* Set the 802.1q VLAN id. */
51 static int hf_openflow_set_vlan_pcp = -1; /* Set the 802.1q priority. */
52 static int hf_openflow_strip_vlan = -1; /* Strip the 802.1q header. */
53 static int hf_openflow_set_dl_src = -1; /* Ethernet source address. */
54 static int hf_openflow_set_dl_dst = -1; /* Ethernet destination address. */
55 static int hf_openflow_set_nw_src = -1; /* IP source address. */
56 static int hf_openflow_set_nw_dst = -1; /* IP destination address. */
57 static int hf_openflow_set_nw_tos = -1; /* IP ToS (DSCP field, 6 bits). */
58 static int hf_openflow_set_tp_src = -1; /* TCP/UDP source port. */
59 static int hf_openflow_set_tp_dst = -1; /* TCP/UDP destination port. */
60 static int hf_openflow_enqueue = -1; /* Output to queue. */
61
62 static int hf_openflow_port_no = -1;
63 static int hf_openflow_hw_addr = -1;
64 static int hf_openflow_port_name = -1;
65
66
67 static int hf_openflow_port_config = -1;
68 static int hf_openflow_port_state = -1;
69 static int hf_openflow_port_curr = -1;
70 static int hf_openflow_port_advertised = -1;
71 static int hf_openflow_port_supported = -1;
72 static int hf_openflow_port_peer = -1;
73
74 static int hf_openflow_port_down = -1; /* Port is administratively down. */
75 static int hf_openflow_no_stp = -1; /* Disable 802.1D spanning tree on port. */
76 static int hf_openflow_no_recv = -1; /* Drop all packets except 802.1D spanning tree packets. */
77 static int hf_openflow_no_recv_stp = -1; /* Drop received 802.1D STP packets. */
78 static int hf_openflow_no_flood = -1; /* Do not include this port when flooding. */
79 static int hf_openflow_no_fwd = -1; /* Drop packets forwarded to port. */
80 static int hf_openflow_no_packet_in = -1; /* Do not send packet-in msgs for port. */
81
82 static int hf_openflow_link_down = -1; /* No physical link present. */
83
84 static int hf_openflow_10mb_hd = -1; /* 10 Mb half-duplex rate support. */
85 static int hf_openflow_10mb_fd = -1; /* 10 Mb full-duplex rate support. */
86 static int hf_openflow_100mb_hd = -1; /* 100 Mb half-duplex rate support. */
87 static int hf_openflow_100mb_fd = -1; /* 100 Mb full-duplex rate support. */
88 static int hf_openflow_1gb_hd = -1; /* 1 Gb half-duplex rate support. */
89 static int hf_openflow_1gb_fd = -1; /* 1 Gb full-duplex rate support. */
90 static int hf_openflow_10gb_fd = -1; /* 10 Gb full-duplex rate support. */
91 static int hf_openflow_copper = -1; /* Copper medium. */
92 static int hf_openflow_fiber = -1; /* Fiber medium. */
93 static int hf_openflow_autoneg = -1; /* Auto-negotiation. */
94 static int hf_openflow_pause = -1; /* Pause. */
95 static int hf_openflow_pause_asym = -1; /* Asymmetric pause. */
96
97 static int hf_openflow_config_flags = -1;
98 static int hf_openflow_miss_send_len = -1;
99
100 static int hf_openflow_buffer_id = -1;
101 static int hf_openflow_total_len = -1;
102 static int hf_openflow_in_port = -1;
103 static int hf_openflow_reason = -1;
104 static int hf_openflow_pkt_in_pad = -1;
105 static int hf_openflow_table_id = -1;
106 static int hf_openflow_cookie = -1;
107 /* static int hf_openflow_cookie_mask = -1; */
108 static int hf_openflow_features_reply_pad = -1;
109 static int hf_openflow_actions_len = -1;
110 static int hf_openflow_action_type = -1;
111 static int hf_openflow_action_len = -1;
112 static int hf_openflow_output_port = -1;
113 static int hf_openflow_max_len = -1;
114 static int hf_openflow_wildcards = -1;
115 static int hf_openflow_command = -1;
116 static int hf_openflow_eth_src = -1;
117 static int hf_openflow_eth_dst = -1;
118 static int hf_openflow_dl_vlan = -1;
119 static int hf_openflow_dl_vlan_pcp = -1;
120 static int hf_openflow_ofp_match_pad = -1;
121 static int hf_openflow_match_dl_type = -1;
122 static int hf_openflow_ofp_match_tos = -1;
123 static int hf_openflow_ofp_match_nw_proto = -1;
124 static int hf_openflow_ofp_source_addr = -1;
125 static int hf_openflow_ofp_dest_addr = -1;
126 static int hf_openflow_ofp_source_port = -1;
127 static int hf_openflow_ofp_dest_port = -1;
128 static int hf_openflow_idle_timeout = -1;
129 static int hf_openflow_hard_timeout = -1;
130 static int hf_openflow_priority = -1;
131 static int hf_openflow_out_port = -1;
132 /* static int hf_openflow_out_group = -1; */
133 static int hf_openflow_flags = -1;
134 static int hf_openflow_v1_stats_type = -1;
135 static int hf_openflow_v1_flow_stats_request_pad = -1;
136
137 /* Initialize the subtree pointers */
138 static gint ett_openflow = -1;
139 static gint ett_openflow_path_id = -1;
140 static gint ett_openflow_cap = -1;
141 static gint ett_openflow_act = -1;
142 static gint ett_openflow_port = -1;
143 static gint ett_openflow_port_cnf = -1;
144 static gint ett_openflow_port_state = -1;
145 static gint ett_openflow_port_cf = -1;
146
147 /* static expert_field ei_openflow_undecoded_data = EI_INIT; */
148 static expert_field ei_openflow_action_type = EI_INIT;
149 static expert_field ei_openflow_1_0_type = EI_INIT;
150
151 static const value_string openflow_version_values[] = {
152 { 0x01, "1.0" },
153 { 0, NULL }
154 };
155
156
157 /* Immutable messages. */
158 #define OFPT_1_0_HELLO 0 /* Symmetric message */
159 #define OFPT_1_0_ERROR 1 /* Symmetric message */
160 #define OFPT_1_0_ECHO_REQUEST 2 /* Symmetric message */
161 #define OFPT_1_0_ECHO_REPLY 3 /* Symmetric message */
162 #define OFPT_1_0_VENDOR 4 /* Symmetric message */
163 /* Switch configuration messages. */
164 #define OFPT_1_0_FEATURES_REQUEST 5 /* Controller/switch message */
165 #define OFPT_1_0_FEATURES_REPLY 6 /* Controller/switch message */
166 #define OFPT_1_0_GET_CONFIG_REQUEST 7 /* Controller/switch message */
167 #define OFPT_1_0_GET_CONFIG_REPLY 8 /* Controller/switch message */
168 #define OFPT_1_0_SET_CONFIG 9 /* Controller/switch message */
169 /* Asynchronous messages. */
170 #define OFPT_1_0_PACKET_IN 10 /* Async message */
171 #define OFPT_1_0_FLOW_REMOVED 11 /* Async message */
172 #define OFPT_1_0_PORT_STATUS 12 /* Async message */
173 /* Controller command messages. */
174 #define OFPT_1_0_PACKET_OUT 13 /* Controller/switch message */
175 #define OFPT_1_0_FLOW_MOD 14 /* Controller/switch message */
176 #define OFPT_1_0_PORT_MOD 15 /* Controller/switch message */
177 /* Statistics messages. */
178 #define OFPT_1_0_STATS_REQUEST 16 /* Controller/switch message */
179 #define OFPT_1_0_STATS_REPLY 17 /* Controller/switch message */
180 /* Barrier messages. */
181 #define OFPT_1_0_BARRIER_REQUEST 18 /* Controller/switch message */
182 #define OFPT_1_0_BARRIER_REPLY 19 /* Controller/switch message */
183 /* Queue Configuration messages. */
184 #define OFPT_1_0_QUEUE_GET_CONFIG_REQUEST 20 /* Controller/switch message */
185 #define OFPT_1_0_QUEUE_GET_CONFIG_REPLY 21 /* Controller/switch message */
186
187
188 static const value_string openflow_1_0_type_values[] = {
189 /* Immutable messages. */
190 { 0, "OFPT_HELLO" }, /* Symmetric message */
191 { 1, "OFPT_ERROR" }, /* Symmetric message */
192 { 2, "OFPT_ECHO_REQUEST" }, /* Symmetric message */
193 { 3, "OFPT_ECHO_REPLY" }, /* Symmetric message */
194 { 4, "OFPT_VENDOR" }, /* Symmetric message */
195 /* Switch configuration messages. */
196 { 5, "OFPT_FEATURES_REQUEST" }, /* Controller/switch message */
197 { 6, "OFPT_FEATURES_REPLY" }, /* Controller/switch message */
198 { 7, "OFPT_GET_CONFIG_REQUEST" }, /* Controller/switch message */
199 { 8, "OFPT_GET_CONFIG_REPLY" }, /* Controller/switch message */
200 { 9, "OFPT_SET_CONFIG" }, /* Controller/switch message */
201 /* Asynchronous messages. */
202 { 10, "OFPT_PACKET_IN" }, /* Async message */
203 { 11, "OFPT_FLOW_REMOVED" }, /* Async message */
204 { 12, "OFPT_PORT_STATUS" }, /* Async message */
205 /* Controller command messages. */
206 { 13, "OFPT_PACKET_OUT" }, /* Controller/switch message */
207 { 14, "OFPT_FLOW_MOD" }, /* Controller/switch message */
208 { 15, "OFPT_PORT_MOD" }, /* Controller/switch message */
209 /* Statistics messages. */
210 { 16, "OFPT_STATS_REQUEST" }, /* Controller/switch message */
211 { 17, "OFPT_STATS_REPLY" }, /* Controller/switch message */
212 /* Barrier messages. */
213 { 18, "OFPT_BARRIER_REQUEST" }, /* Controller/switch message */
214 { 19, "OFPT_BARRIER_REPLY" }, /* Controller/switch message */
215 /* Queue Configuration messages. */
216 { 20, "OFPT_QUEUE_GET_CONFIG_REQUEST" }, /* Controller/switch message */
217 { 21, "OFPT_QUEUE_GET_CONFIG_REPLY" }, /* Controller/switch message */
218 { 0, NULL }
219 };
220 static value_string_ext openflow_1_0_type_values_ext = VALUE_STRING_EXT_INIT(openflow_1_0_type_values);
221
222 #define OFPC_FLOW_STATS 1<<0 /* Flow statistics. */
223 #define OFPC_TABLE_STATS 1<<1 /* Table statistics. */
224 #define OFPC_PORT_STATS 1<<2 /* Port statistics. */
225 #define OFPC_GROUP_STATS 1<<3 /* Group statistics. */
226 #define OFPC_IP_REASM 1<<5 /* Can reassemble IP fragments. */
227 #define OFPC_QUEUE_STATS 1<<6 /* Queue statistics. */
228 #define OFPC_PORT_BLOCKED 1<<8 /* Switch will block looping ports. */
229
230 #define OFPAT_OUTPUT_MASK 1<<0 /* Output to switch port. */
231 #define OFPAT_SET_VLAN_VID_MASK 1<<1 /* Set the 802.1q VLAN id. */
232 #define OFPAT_SET_VLAN_PCP_MASK 1<<2 /* Set the 802.1q priority. */
233 #define OFPAT_STRIP_VLAN_MASK 1<<3 /* Strip the 802.1q header. */
234 #define OFPAT_SET_DL_SRC_MASK 1<<4 /* Ethernet source address. */
235 #define OFPAT_SET_DL_DST_MASK 1<<5 /* Ethernet destination address. */
236 #define OFPAT_SET_NW_SRC_MASK 1<<6 /* IP source address. */
237 #define OFPAT_SET_NW_DST_MASK 1<<7 /* IP destination address. */
238 #define OFPAT_SET_NW_TOS_MASK 1<<8 /* IP ToS (DSCP field, 6 bits). */
239 #define OFPAT_SET_TP_SRC_MASK 1<<9 /* TCP/UDP source port. */
240 #define OFPAT_SET_TP_DST_MASK 1<<10 /* TCP/UDP destination port. */
241 #define OFPAT_ENQUEUE_MASK 1<<11 /* Output to queue. */
242
243 #define OFPPC_PORT_DOWN 1<<0 /* Port is administratively down. */
244 #define OFPPC_NO_STP 1<<1 /* Disable 802.1D spanning tree on port. */
245 #define OFPPC_NO_RECV 1<<2 /* Drop all packets except 802.1D spanning tree packets. */
246 #define OFPPC_NO_RECV_STP 1<<3 /* Drop received 802.1D STP packets. */
247 #define OFPPC_NO_FLOOD 1<<4 /* Do not include this port when flooding. */
248 #define OFPPC_NO_FWD 1<<5 /* Drop packets forwarded to port. */
249 #define OFPPC_NO_PACKET_IN 1<<6 /* Do not send packet-in msgs for port. */
250
251 #define OFP_MAX_PORT_NAME_LEN 16
252
253 #define OFPPS_LINK_DOWN 1<<0 /* No physical link present. */
254 #define OFPPS_STP_LISTEN 0<<8 /* Not learning or relaying frames. */
255 #define OFPPS_STP_LEARN 1<<8 /* Learning but not relaying frames. */
256 #define OFPPS_STP_FORWARD 2<<8 /* Learning and relaying frames. */
257 #define OFPPS_STP_BLOCK 3<<8 /* Not part of spanning tree. */
258 #define OFPPS_STP_MASK 3<<8 /* Bit mask for OFPPS_STP_* values. */
259
260
261 #define OFPPF_10MB_HD 1<<0 /* 10 Mb half-duplex rate support. */
262 #define OFPPF_10MB_FD 1<<1 /* 10 Mb full-duplex rate support. */
263 #define OFPPF_100MB_HD 1<<2 /* 100 Mb half-duplex rate support. */
264 #define OFPPF_100MB_FD 1<<3 /* 100 Mb full-duplex rate support. */
265 #define OFPPF_1GB_HD 1<<4 /* 1 Gb half-duplex rate support. */
266 #define OFPPF_1GB_FD 1<<5 /* 1 Gb full-duplex rate support. */
267 #define OFPPF_10GB_FD 1<<6 /* 10 Gb full-duplex rate support. */
268 #define OFPPF_COPPER 1<<7 /* Copper medium. */
269 #define OFPPF_FIBER 1<<8 /* Fiber medium. */
270 #define OFPPF_AUTONEG 1<<9 /* Auto-negotiation. */
271 #define OFPPF_PAUSE 1<<10 /* Pause. */
272 #define OFPPF_PAUSE_ASYM 1<<11 /* Asymmetric pause. */
273
274
275 #define OFPAT_OUTPUT 0 /* Output to switch port. */
276 #define OFPAT_SET_VLAN_VID 1 /* Set the 802.1q VLAN id. */
277 #define OFPAT_SET_VLAN_PCP 2 /* Set the 802.1q priority. */
278 #define OFPAT_STRIP_VLAN 3 /* Strip the 802.1q header. */
279 #define OFPAT_SET_DL_SRC 4 /* Ethernet source address. */
280 #define OFPAT_SET_DL_DST 5 /* Ethernet destination address. */
281 #define OFPAT_SET_NW_SRC 6 /* IP source address. */
282 #define OFPAT_SET_NW_DST 7 /* IP destination address. */
283 #define OFPAT_SET_TP_SRC 8 /* TCP/UDP source port. */
284 #define OFPAT_SET_TP_DST 9 /* TCP/UDP destination port. */
285 #define OFPAT_VENDOR 0xffff
286
287 static int
dissect_openflow_ofp_match_v1(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,int offset)288 dissect_openflow_ofp_match_v1(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
289 {
290
291 /* uint32_t wildcards; Wildcard fields. */
292 proto_tree_add_item(tree, hf_openflow_wildcards, tvb, offset, 4, ENC_BIG_ENDIAN);
293 offset+=4;
294 /* uint16_t in_port; Input switch port. */
295 proto_tree_add_item(tree, hf_openflow_in_port, tvb, offset, 2, ENC_BIG_ENDIAN);
296 offset+=2;
297
298 /* uint8_t dl_src[OFP_ETH_ALEN]; Ethernet source address. */
299 proto_tree_add_item(tree, hf_openflow_eth_src, tvb, offset, 6, ENC_NA);
300 offset+=6;
301 /* uint8_t dl_dst[OFP_ETH_ALEN]; Ethernet destination address. */
302 proto_tree_add_item(tree, hf_openflow_eth_dst, tvb, offset, 6, ENC_NA);
303 offset+=6;
304 /* uint16_t dl_vlan; Input VLAN id. */
305 proto_tree_add_item(tree, hf_openflow_dl_vlan, tvb, offset, 2, ENC_BIG_ENDIAN);
306 offset+=2;
307 /* uint8_t dl_vlan_pcp; Input VLAN priority. */
308 proto_tree_add_item(tree, hf_openflow_dl_vlan_pcp, tvb, offset, 1, ENC_BIG_ENDIAN);
309 offset++;
310 /* uint8_t pad1[1]; Align to 64-bits */
311 proto_tree_add_item(tree, hf_openflow_ofp_match_pad, tvb, offset, 1, ENC_NA);
312 offset++;
313 /* uint16_t dl_type; Ethernet frame type. */
314 proto_tree_add_item(tree, hf_openflow_match_dl_type, tvb, offset, 2, ENC_BIG_ENDIAN);
315 offset += 2;
316 /* uint8_t nw_tos; IP ToS (actually DSCP field, 6 bits). */
317 proto_tree_add_item(tree, hf_openflow_ofp_match_tos, tvb, offset, 1, ENC_NA);
318 offset++;
319 /* uint8_t nw_proto; IP protocol or lower 8 bits of
320 * ARP opcode.
321 */
322 proto_tree_add_item(tree, hf_openflow_ofp_match_nw_proto, tvb, offset, 1, ENC_NA);
323 offset++;
324 /* uint8_t pad2[2]; Align to 64-bits */
325 proto_tree_add_item(tree, hf_openflow_ofp_match_pad, tvb, offset, 2, ENC_NA);
326 offset += 2;
327 /* uint32_t nw_src; IP source address. */
328 proto_tree_add_item(tree, hf_openflow_ofp_source_addr, tvb, offset, 4, ENC_NA);
329 offset += 4;
330 /* uint32_t nw_dst; IP destination address. */
331 proto_tree_add_item(tree, hf_openflow_ofp_dest_addr, tvb, offset, 4, ENC_NA);
332 offset += 4;
333 /* uint16_t tp_src; TCP/UDP source port. */
334 proto_tree_add_item(tree, hf_openflow_ofp_source_port, tvb, offset, 2, ENC_BIG_ENDIAN);
335 offset += 2;
336 /* uint16_t tp_dst; TCP/UDP destination port. */
337 proto_tree_add_item(tree, hf_openflow_ofp_dest_port, tvb, offset, 2, ENC_BIG_ENDIAN);
338 offset += 2;
339 return offset;
340 }
341
342 static int
dissect_openflow_flow_stats_request_v1(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,int offset)343 dissect_openflow_flow_stats_request_v1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
344 {
345 /* struct ofp_match match; Fields to match */
346 offset = dissect_openflow_ofp_match_v1(tvb, pinfo, tree, offset);
347
348 /* uint8_t table_id; ID of table to read (from ofp_table_stats),
349 * 0xff for all tables or 0xfe for emergency.
350 */
351 proto_tree_add_item(tree, hf_openflow_table_id, tvb, offset, 1, ENC_BIG_ENDIAN);
352 offset++;
353 /* uint8_t pad; Align to 32 bits. */
354 proto_tree_add_item(tree, hf_openflow_v1_flow_stats_request_pad, tvb, offset, 1, ENC_BIG_ENDIAN);
355 offset++;
356 /* uint16_t out_port; */
357 proto_tree_add_item(tree, hf_openflow_out_port, tvb, offset, 2, ENC_BIG_ENDIAN);
358 offset += 2;
359
360 return offset;
361
362 }
363
364
365 static const value_string openflow_action_values[] = {
366 { OFPAT_OUTPUT, "Output to switch port" },
367 { OFPAT_SET_VLAN_VID, "Set the 802.1q VLAN id" },
368 { OFPAT_SET_VLAN_PCP, "Set the 802.1q priority" },
369 { OFPAT_STRIP_VLAN, "Strip the 802.1q header" },
370 { OFPAT_SET_DL_SRC, "Ethernet source address" },
371 { OFPAT_SET_DL_DST, "Ethernet destination address" },
372 { OFPAT_SET_NW_SRC, "IP source address" },
373 { OFPAT_SET_NW_DST, "IP destination address" },
374 { OFPAT_SET_TP_SRC, "TCP/UDP source port" },
375 { OFPAT_SET_TP_DST, "TCP/UDP destination port" },
376 { OFPAT_VENDOR, "Vendor specific action"},
377 { 0, NULL }
378 };
379
380 static int
dissect_openflow_action_header(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,int offset)381 dissect_openflow_action_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
382 {
383 guint16 action_type, action_len;
384 proto_item* ti;
385
386 /* uint16_t type; One of OFPAT_*. */
387 action_type = tvb_get_ntohs(tvb, offset);
388 ti = proto_tree_add_item(tree, hf_openflow_action_type, tvb, offset, 2, ENC_BIG_ENDIAN);
389 offset+=2;
390 /* Length of action, including this
391 * header. This is the length of action,
392 * including any padding to make it
393 * 64-bit aligned.
394 */
395 action_len = tvb_get_ntohs(tvb, offset);
396 proto_tree_add_item(tree, hf_openflow_action_len, tvb, offset, 2, ENC_BIG_ENDIAN);
397 offset+=2;
398
399 switch(action_type){
400 case OFPAT_OUTPUT:
401 /* uint16_t port; Output port. */
402 proto_tree_add_item(tree, hf_openflow_output_port, tvb, offset, 2, ENC_BIG_ENDIAN);
403 offset+=2;
404 /* uint16_t max_len; Max length to send to controller. */
405 proto_tree_add_item(tree, hf_openflow_max_len, tvb, offset, 2, ENC_BIG_ENDIAN);
406 offset+=2;
407 break;
408 default:
409 expert_add_info(pinfo, ti, &ei_openflow_action_type);
410 offset+=(action_len-4);
411 break;
412 }
413
414 return offset;
415 }
416 static void
dissect_openflow_phy_port(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,int offset)417 dissect_openflow_phy_port(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
418 {
419 proto_item *ti;
420 proto_tree *port_cnf_tree, *port_state_tree, *port_cf_tree;
421
422 proto_tree_add_item(tree, hf_openflow_port_no, tvb, offset, 2, ENC_BIG_ENDIAN);
423 offset+=2;
424 proto_tree_add_item(tree, hf_openflow_hw_addr, tvb, offset, 6, ENC_NA);
425 offset+=6;
426 proto_tree_add_item(tree, hf_openflow_port_name, tvb, offset, OFP_MAX_PORT_NAME_LEN, ENC_ASCII|ENC_NA);
427 offset+=OFP_MAX_PORT_NAME_LEN;
428
429 /* Bitmap of OFPPC_* flags. */
430 ti = proto_tree_add_item(tree, hf_openflow_port_config, tvb, offset, 4, ENC_BIG_ENDIAN);
431 port_cnf_tree = proto_item_add_subtree(ti, ett_openflow_port_cnf);
432
433 /* Port is administratively down. */
434 proto_tree_add_item(port_cnf_tree, hf_openflow_port_down, tvb, offset, 4, ENC_BIG_ENDIAN);
435 /* Disable 802.1D spanning tree on port. */
436 proto_tree_add_item(port_cnf_tree, hf_openflow_no_stp, tvb, offset, 4, ENC_BIG_ENDIAN);
437 /* Drop all packets except 802.1D spanning tree packets. */
438 proto_tree_add_item(port_cnf_tree, hf_openflow_no_recv, tvb, offset, 4, ENC_BIG_ENDIAN);
439 /* Drop received 802.1D STP packets. */
440 proto_tree_add_item(port_cnf_tree, hf_openflow_no_recv_stp, tvb, offset, 4, ENC_BIG_ENDIAN);
441 /* Do not include this port when flooding. */
442 proto_tree_add_item(port_cnf_tree, hf_openflow_no_flood, tvb, offset, 4, ENC_BIG_ENDIAN);
443 /* Drop packets forwarded to port. */
444 proto_tree_add_item(port_cnf_tree, hf_openflow_no_fwd, tvb, offset, 4, ENC_BIG_ENDIAN);
445 /* Do not send packet-in msgs for port. */
446 proto_tree_add_item(port_cnf_tree, hf_openflow_no_packet_in, tvb, offset, 4, ENC_BIG_ENDIAN);
447 offset+=4;
448
449 /* Bitmap of OFPPS_* flags. */
450 ti = proto_tree_add_item(tree, hf_openflow_port_state, tvb, offset, 4, ENC_BIG_ENDIAN);
451 port_state_tree = proto_item_add_subtree(ti, ett_openflow_port_state);
452
453 /* No physical link present. */
454 proto_tree_add_item(port_state_tree, hf_openflow_link_down, tvb, offset, 4, ENC_BIG_ENDIAN);
455
456 offset+=4;
457
458 /* Current features. */
459 ti = proto_tree_add_item(tree, hf_openflow_port_curr, tvb, offset, 4, ENC_BIG_ENDIAN);
460 port_cf_tree = proto_item_add_subtree(ti, ett_openflow_port_cf);
461 /* 10 Mb half-duplex rate support. */
462 proto_tree_add_item(port_cf_tree, hf_openflow_10mb_hd, tvb, offset, 4, ENC_BIG_ENDIAN);
463 /* 10 Mb full-duplex rate support. */
464 proto_tree_add_item(port_cf_tree, hf_openflow_10mb_fd, tvb, offset, 4, ENC_BIG_ENDIAN);
465 /* 100 Mb half-duplex rate support. */
466 proto_tree_add_item(port_cf_tree, hf_openflow_100mb_hd, tvb, offset, 4, ENC_BIG_ENDIAN);
467 /* 100 Mb full-duplex rate support. */
468 proto_tree_add_item(port_cf_tree, hf_openflow_100mb_fd, tvb, offset, 4, ENC_BIG_ENDIAN);
469 /* 1 Gb half-duplex rate support. */
470 proto_tree_add_item(port_cf_tree, hf_openflow_1gb_hd, tvb, offset, 4, ENC_BIG_ENDIAN);
471 /* 1 Gb full-duplex rate support. */
472 proto_tree_add_item(port_cf_tree, hf_openflow_1gb_fd, tvb, offset, 4, ENC_BIG_ENDIAN);
473 /* 10 Gb full-duplex rate support. */
474 proto_tree_add_item(port_cf_tree, hf_openflow_10gb_fd, tvb, offset, 4, ENC_BIG_ENDIAN);
475 /* Copper medium. */
476 proto_tree_add_item(port_cf_tree, hf_openflow_copper, tvb, offset, 4, ENC_BIG_ENDIAN);
477 /* Fiber medium. */
478 proto_tree_add_item(port_cf_tree, hf_openflow_fiber, tvb, offset, 4, ENC_BIG_ENDIAN);
479 /* Auto-negotiation. */
480 proto_tree_add_item(port_cf_tree, hf_openflow_autoneg, tvb, offset, 4, ENC_BIG_ENDIAN);
481 /* Pause. */
482 proto_tree_add_item(port_cf_tree, hf_openflow_pause, tvb, offset, 4, ENC_BIG_ENDIAN);
483 /* Asymmetric pause. */
484 proto_tree_add_item(port_cf_tree, hf_openflow_pause_asym, tvb, offset, 4, ENC_BIG_ENDIAN);
485 offset+=4;
486
487 /* Features being advertised by the port. */
488 proto_tree_add_item(tree, hf_openflow_port_advertised, tvb, offset, 4, ENC_BIG_ENDIAN);
489 offset+=4;
490
491 /* Features supported by the port. */
492 proto_tree_add_item(tree, hf_openflow_port_supported, tvb, offset, 4, ENC_BIG_ENDIAN);
493 offset+=4;
494 /* Features advertised by peer. */
495 proto_tree_add_item(tree, hf_openflow_port_peer, tvb, offset, 4, ENC_BIG_ENDIAN);
496
497
498 }
499
500 #if 0
501 /*
502 * Switch features.
503 */
504
505 struct ofp_switch_features {
506 struct ofp_header header;
507 uint64_t datapath_id; /* Datapath unique ID. The lower 48-bits are for
508 a MAC address, while the upper 16-bits are
509 implementer-defined. */
510 uint32_t n_buffers; /* Max packets buffered at once. */
511 uint8_t n_tables; /* Number of tables supported by datapath. */
512 uint8_t pad[3]; /* Align to 64-bits. */
513 /* Features. */
514 uint32_t capabilities; /* Bitmap of support "ofp_capabilities". */
515 uint32_t actions; /* Bitmap of supported "ofp_action_type"s. */
516 /* Port info.*/
517 struct ofp_phy_port ports[0]; /* Port definitions. The number of ports
518 is inferred from the length field in
519 the header. */
520 #endif
521
522 static void
dissect_openflow_features_reply_v1(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,int offset,guint16 length)523 dissect_openflow_features_reply_v1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, guint16 length)
524 {
525 proto_item *ti;
526 proto_tree *path_id_tree, *cap_tree, *act_tree;
527
528 guint16 length_remaining;
529
530 ti = proto_tree_add_item(tree, hf_openflow_datapath_id, tvb, offset, 8, ENC_BIG_ENDIAN);
531 path_id_tree = proto_item_add_subtree(ti, ett_openflow_path_id);
532 proto_tree_add_item(path_id_tree, hf_openflow_datapath_mac, tvb, offset, 6, ENC_NA);
533 offset+=6;
534 proto_tree_add_item(path_id_tree, hf_openflow_datapath_impl, tvb, offset, 2, ENC_BIG_ENDIAN);
535 offset+=2;
536
537 proto_tree_add_item(tree, hf_openflow_n_buffers, tvb, offset, 4, ENC_BIG_ENDIAN);
538 offset+=4;
539
540 proto_tree_add_item(tree, hf_openflow_n_tables, tvb, offset, 1, ENC_BIG_ENDIAN);
541 offset++;
542
543 proto_tree_add_item(tree, hf_openflow_features_reply_pad, tvb, offset, 3, ENC_NA);
544 offset+=3;
545
546 ti = proto_tree_add_item(tree, hf_openflow_capabilities, tvb, offset, 4, ENC_BIG_ENDIAN);
547 cap_tree = proto_item_add_subtree(ti, ett_openflow_cap);
548
549 /* Dissect flags */
550 proto_tree_add_item(cap_tree, hf_openflow_cap_flow_stats, tvb, offset, 4, ENC_BIG_ENDIAN);
551 proto_tree_add_item(cap_tree, hf_openflow_table_stats, tvb, offset, 4, ENC_BIG_ENDIAN);
552 proto_tree_add_item(cap_tree, hf_openflow_port_stats, tvb, offset, 4, ENC_BIG_ENDIAN);
553 proto_tree_add_item(cap_tree, hf_openflow_group_stats, tvb, offset, 4, ENC_BIG_ENDIAN);
554 proto_tree_add_item(cap_tree, hf_openflow_ip_reasm, tvb, offset, 4, ENC_BIG_ENDIAN);
555 proto_tree_add_item(cap_tree, hf_openflow_queue_stats, tvb, offset, 4, ENC_BIG_ENDIAN);
556 proto_tree_add_item(cap_tree, hf_openflow_port_blocked, tvb, offset, 4, ENC_BIG_ENDIAN);
557 offset+=4;
558
559 ti = proto_tree_add_item(tree, hf_openflow_actions, tvb, offset, 4, ENC_BIG_ENDIAN);
560 act_tree = proto_item_add_subtree(ti, ett_openflow_act);
561 /* Dissect flags */
562 proto_tree_add_item(act_tree, hf_openflow_output, tvb, offset, 4, ENC_BIG_ENDIAN);
563 proto_tree_add_item(act_tree, hf_openflow_set_vlan_vid, tvb, offset, 4, ENC_BIG_ENDIAN);
564 proto_tree_add_item(act_tree, hf_openflow_set_vlan_pcp, tvb, offset, 4, ENC_BIG_ENDIAN);
565 proto_tree_add_item(act_tree, hf_openflow_strip_vlan, tvb, offset, 4, ENC_BIG_ENDIAN);
566 proto_tree_add_item(act_tree, hf_openflow_set_dl_src, tvb, offset, 4, ENC_BIG_ENDIAN);
567 proto_tree_add_item(act_tree, hf_openflow_set_dl_dst, tvb, offset, 4, ENC_BIG_ENDIAN);
568 proto_tree_add_item(act_tree, hf_openflow_set_nw_src, tvb, offset, 4, ENC_BIG_ENDIAN);
569 proto_tree_add_item(act_tree, hf_openflow_set_nw_dst, tvb, offset, 4, ENC_BIG_ENDIAN);
570 proto_tree_add_item(act_tree, hf_openflow_set_nw_tos, tvb, offset, 4, ENC_BIG_ENDIAN);
571 proto_tree_add_item(act_tree, hf_openflow_set_tp_src, tvb, offset, 4, ENC_BIG_ENDIAN);
572 proto_tree_add_item(act_tree, hf_openflow_set_tp_dst, tvb, offset, 4, ENC_BIG_ENDIAN);
573 proto_tree_add_item(act_tree, hf_openflow_enqueue, tvb, offset, 4, ENC_BIG_ENDIAN);
574 offset+=4;
575
576 length_remaining = length-32;
577 if(length_remaining > 0){
578 guint16 num_ports = length_remaining/48;
579 int i;
580 if((length_remaining&0x003f) != 0){
581 /* protocol_error */
582 }
583 for(i=0; i<num_ports ;i++){
584 proto_tree *port_tree;
585
586 port_tree = proto_tree_add_subtree_format(tree, tvb, offset, 48, ett_openflow_port, NULL, "Port data %u",i+1);
587 dissect_openflow_phy_port(tvb, pinfo, port_tree, offset);
588 offset+=48;
589 }
590 }
591
592 }
593
594
595 static void
dissect_openflow_switch_config(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,int offset,guint16 length _U_)596 dissect_openflow_switch_config(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, guint16 length _U_)
597 {
598
599 /* ofp_config_flags */
600 proto_tree_add_item(tree, hf_openflow_config_flags, tvb, offset, 2, ENC_BIG_ENDIAN);
601 offset+=2;
602 /* miss_send_len */
603 proto_tree_add_item(tree, hf_openflow_miss_send_len, tvb, offset, 2, ENC_BIG_ENDIAN);
604 /*offset+=2;*/
605
606 }
607
608 #define OFPR_NO_MATCH 0 /* No matching flow (table-miss flow entry). */
609 #define OFPR_ACTION 1 /* Action explicitly output to controller. */
610 #define OFPR_INVALID_TTL 2 /* Packet has invalid TTL */
611
612 static const value_string openflow_reason_values[] = {
613 { OFPR_NO_MATCH, "No matching flow (table-miss flow entry)" },
614 { OFPR_ACTION, "Action explicitly output to controller" },
615 { OFPR_INVALID_TTL, "Packet has invalid TTL" },
616 { 0, NULL }
617 };
618
619 static void
dissect_openflow_pkt_in(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,int offset,guint16 length)620 dissect_openflow_pkt_in(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, guint16 length)
621 {
622 tvbuff_t *next_tvb;
623
624 /* uint32_t buffer_id; ID assigned by datapath. */
625 proto_tree_add_item(tree, hf_openflow_buffer_id, tvb, offset, 4, ENC_BIG_ENDIAN);
626 offset+=4;
627 /* uint16_t total_len; Full length of frame. */
628 proto_tree_add_item(tree, hf_openflow_total_len, tvb, offset, 2, ENC_BIG_ENDIAN);
629 offset+=2;
630
631 /* uint16_t in_port; Port on which frame was received. */
632 proto_tree_add_item(tree, hf_openflow_in_port, tvb, offset, 2, ENC_BIG_ENDIAN);
633 offset+=2;
634
635 /* uint8_t reason; Reason packet is being sent (one of OFPR_*) */
636 proto_tree_add_item(tree, hf_openflow_reason, tvb, offset, 1, ENC_BIG_ENDIAN);
637 offset++;
638
639 proto_tree_add_item(tree, hf_openflow_pkt_in_pad, tvb, offset, 1, ENC_NA);
640 offset+=1;
641
642 next_tvb = tvb_new_subset_length(tvb, offset, length-offset);
643 call_dissector(eth_withoutfcs_handle, next_tvb, pinfo, tree);
644
645 }
646
647 static void
dissect_openflow_pkt_out(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,int offset,guint16 length)648 dissect_openflow_pkt_out(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, guint16 length)
649 {
650 tvbuff_t *next_tvb;
651 gint32 buffer_id;
652
653 /* uint32_t buffer_id; ID assigned by datapath. */
654 buffer_id = tvb_get_ntohl(tvb, offset);
655 proto_tree_add_item(tree, hf_openflow_buffer_id, tvb, offset, 4, ENC_BIG_ENDIAN);
656 offset+=4;
657
658 /* uint32_t in_port; Packet's input port or OFPP_CONTROLLER. */
659 proto_tree_add_item(tree, hf_openflow_in_port, tvb, offset, 2, ENC_BIG_ENDIAN);
660 offset+=2;
661
662 /* uint16_t actions_len; Size of action array in bytes. */
663 proto_tree_add_item(tree, hf_openflow_actions_len, tvb, offset, 2, ENC_BIG_ENDIAN);
664 offset+=2;
665
666 /* struct ofp_action_header actions[0]; Action list. */
667 offset = dissect_openflow_action_header(tvb, pinfo, tree, offset);
668 /* Packet data. The length is inferred
669 from the length field in the header.
670 (Only meaningful if buffer_id == -1.)
671 */
672 if(buffer_id == -1){
673 next_tvb = tvb_new_subset_length(tvb, offset, length-offset);
674 call_dissector(eth_withoutfcs_handle, next_tvb, pinfo, tree);
675 }
676 }
677
678 #define OFPFC_ADD 0 /* New flow. */
679 #define OFPFC_MODIFY 1 /* Modify all matching flows. */
680 #define OFPFC_MODIFY_STRICT 2 /* Modify entry strictly matching wildcards */
681 #define OFPFC_DELETE 3 /* Delete all matching flows. */
682 #define OFPFC_DELETE_STRICT 4 /* Strictly match wildcards and priority. */
683
684 static const value_string openflow_command_values[] = {
685 { OFPFC_ADD, "New flow" },
686 { OFPFC_MODIFY, "Modify all matching flows" },
687 { OFPFC_MODIFY_STRICT, "Modify entry strictly matching wildcards" },
688 { OFPFC_DELETE, "Delete all matching flows" },
689 { OFPFC_DELETE_STRICT, "Strictly match wildcards and priority" },
690 { 0, NULL }
691 };
692
693 static void
dissect_openflow_flow_mod(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,int offset,guint16 length _U_)694 dissect_openflow_flow_mod(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, guint16 length _U_)
695 {
696
697 /* struct ofp_match match; Fields to match */
698 offset = dissect_openflow_ofp_match_v1(tvb, pinfo, tree, offset);
699
700 /* uint64_t cookie; Opaque controller-issued identifier. */
701 proto_tree_add_item(tree, hf_openflow_cookie, tvb, offset, 8, ENC_BIG_ENDIAN);
702 offset += 8;
703
704 /* uint16_t command; One of OFPFC_*. */
705 proto_tree_add_item(tree, hf_openflow_command, tvb, offset, 2, ENC_BIG_ENDIAN);
706 offset += 2;
707
708 /* uint16_t idle_timeout; Idle time before discarding (seconds). */
709 proto_tree_add_item(tree, hf_openflow_idle_timeout, tvb, offset, 2, ENC_BIG_ENDIAN);
710 offset += 2;
711 /* uint16_t hard_timeout; Max time before discarding (seconds). */
712 proto_tree_add_item(tree, hf_openflow_hard_timeout, tvb, offset, 2, ENC_BIG_ENDIAN);
713 offset += 2;
714 /* uint16_t priority; Priority level of flow entry. */
715 proto_tree_add_item(tree, hf_openflow_priority, tvb, offset, 2, ENC_BIG_ENDIAN);
716 offset += 2;
717 /* uint32_t buffer_id; Buffered packet to apply to, or OFP_NO_BUFFER.
718 Not meaningful for OFPFC_DELETE*.
719 */
720 proto_tree_add_item(tree, hf_openflow_buffer_id, tvb, offset, 4, ENC_BIG_ENDIAN);
721 offset += 4;
722 /* uint32_t out_port; For OFPFC_DELETE* commands, require
723 matching entries to include this as an output port. A value of OFPP_ANY
724 indicates no restriction.
725 */
726 proto_tree_add_item(tree, hf_openflow_out_port, tvb, offset, 2, ENC_BIG_ENDIAN);
727 offset += 2;
728
729 /* uint16_t flags; One of OFPFF_*. */
730 proto_tree_add_item(tree, hf_openflow_flags, tvb, offset, 2, ENC_BIG_ENDIAN);
731 /*offset+=2;*/
732 }
733
734
735 #define OFPST_DESC 0
736 #define OFPST_FLOW 1
737 #define OFPST_AGGREGATE 2
738 #define OFPST_TABLE 3
739 #define OFPST_PORT 4
740 #define OFPST_QUEUE 5
741 #define OFPST_VENDOR 0xffff
742
743 static const value_string openflow_stats_type_values[] = {
744 { OFPST_DESC, "OFPST_DESC" },
745 { OFPST_FLOW, "OFPST_FLOW" },
746 { OFPST_AGGREGATE, "OFPST_AGGREGATE" },
747 { OFPST_TABLE, "OFPST_TABLE" },
748 { OFPST_PORT, "OFPST_PORT" },
749 { OFPST_QUEUE, "OFPST_QUEUE" },
750 { OFPST_VENDOR, "OFPST_VENDOR" },
751 { 0, NULL }
752 };
753 static int
dissect_openflow_stats_req(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,int offset,guint16 length _U_)754 dissect_openflow_stats_req(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, guint16 length _U_)
755 {
756 proto_item *type_item;
757 guint32 type;
758
759 /* uint16_t type; */
760 type_item = proto_tree_add_item_ret_uint(tree, hf_openflow_v1_stats_type, tvb, offset, 2, ENC_BIG_ENDIAN, &type);
761 offset += 2;
762 /* uint16_t flags; OFPSF_REQ_* flags (none yet defined). */
763 proto_tree_add_item(tree, hf_openflow_flags, tvb, offset, 2, ENC_BIG_ENDIAN);
764 offset += 2;
765 /* uint8_t body[0]; Body of the request. */
766 switch (type) {
767 case OFPST_DESC:
768 /* The request body is empty. */
769 break;
770 case OFPST_FLOW:
771 dissect_openflow_flow_stats_request_v1(tvb, pinfo, tree, offset);
772 break;
773 default:
774 expert_add_info(pinfo, type_item, &ei_openflow_1_0_type);
775 break;
776 }
777
778 return offset;
779 }
780
781 static int
dissect_openflow_stats_resp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,int offset,guint16 length)782 dissect_openflow_stats_resp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, guint16 length)
783 {
784
785 proto_item *type_item;
786 guint32 type;
787
788 /* uint16_t type; */
789 type_item = proto_tree_add_item_ret_uint(tree, hf_openflow_v1_stats_type, tvb, offset, 2, ENC_BIG_ENDIAN, &type);
790 offset += 2;
791 /* uint16_t flags; OFPSF_REQ_ */
792 proto_tree_add_item(tree, hf_openflow_flags, tvb, offset, 2, ENC_BIG_ENDIAN);
793 offset += 2;
794 /* uint8_t body[0]; Body of the request. */
795 if (length == 12 ) {
796 /* No body */
797 return offset;
798 }
799 switch (type) {
800 case OFPST_DESC:
801 /* The request body is empty. */
802 break;
803 case OFPST_FLOW:
804 /* fall trough */
805 default:
806 expert_add_info(pinfo, type_item, &ei_openflow_1_0_type);
807 break;
808 }
809
810 return offset;
811 }
812
813 static int
dissect_openflow_v1(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)814 dissect_openflow_v1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
815 {
816 proto_item *ti, *type_item;
817 proto_tree *openflow_tree;
818 guint offset = 0;
819 guint8 type;
820 guint16 length;
821
822 type = tvb_get_guint8(tvb, 1);
823
824 col_append_fstr(pinfo->cinfo, COL_INFO, "Type: %s",
825 val_to_str_ext_const(type, &openflow_1_0_type_values_ext, "Unknown message type"));
826
827 /* Stop the Ethernet frame from overwriting the columns */
828 if((type == OFPT_1_0_PACKET_IN) || (type == OFPT_1_0_PACKET_OUT)){
829 col_set_writable(pinfo->cinfo, -1, FALSE);
830 }
831
832 /* Create display subtree for the protocol */
833 ti = proto_tree_add_item(tree, proto_openflow_v1, tvb, 0, -1, ENC_NA);
834 openflow_tree = proto_item_add_subtree(ti, ett_openflow);
835
836 /* A.1 OpenFlow Header. */
837 /* OFP_VERSION. */
838 proto_tree_add_item(openflow_tree, hf_openflow_version, tvb, offset, 1, ENC_BIG_ENDIAN);
839 offset++;
840
841 /* One of the OFPT_ constants. */
842 type_item = proto_tree_add_item(openflow_tree, hf_openflow_1_0_type, tvb, offset, 1, ENC_BIG_ENDIAN);
843 offset++;
844
845 /* Length including this ofp_header. */
846 length = tvb_get_ntohs(tvb, offset);
847 proto_tree_add_item(openflow_tree, hf_openflow_length, tvb, offset, 2, ENC_BIG_ENDIAN);
848 offset+=2;
849
850 /* Transaction id associated with this packet. Replies use the same id as was in the request
851 * to facilitate pairing.
852 */
853 proto_tree_add_item(openflow_tree, hf_openflow_xid, tvb, offset, 4, ENC_BIG_ENDIAN);
854 offset+=4;
855
856 switch(type){
857 case OFPT_1_0_HELLO: /* 0 */
858 /* 5.5.1 Hello
859 * The OFPT_HELLO message has no body;
860 */
861 break;
862 case OFPT_1_0_FEATURES_REQUEST: /* 5 */
863 /* 5.3.1 Handshake
864 * Upon TLS session establishment, the controller sends an OFPT_FEATURES_REQUEST
865 * message. This message does not contain a body beyond the OpenFlow header.
866 */
867 break;
868 case OFPT_1_0_FEATURES_REPLY: /* 6 */
869 dissect_openflow_features_reply_v1(tvb, pinfo, openflow_tree, offset, length);
870 break;
871 case OFPT_1_0_GET_CONFIG_REQUEST: /* 7 */
872 /* A.3.2 There is no body for OFPT_GET_CONFIG_REQUEST beyond the OpenFlow header. */
873 break;
874 case OFPT_1_0_GET_CONFIG_REPLY: /* 8 */
875 /* Fall trough */
876 case OFPT_1_0_SET_CONFIG: /* 9 */
877 dissect_openflow_switch_config(tvb, pinfo, openflow_tree, offset, length);
878 break;
879 case OFPT_1_0_PACKET_IN: /* 10 */
880 dissect_openflow_pkt_in(tvb, pinfo, openflow_tree, offset, length);
881 break;
882 case OFPT_1_0_PACKET_OUT: /* 13 */
883 dissect_openflow_pkt_out(tvb, pinfo, openflow_tree, offset, length);
884 break;
885 case OFPT_1_0_FLOW_MOD: /* 14 */
886 dissect_openflow_flow_mod(tvb, pinfo, openflow_tree, offset, length);
887 break;
888 case OFPT_1_0_STATS_REQUEST: /* 16 */
889 dissect_openflow_stats_req(tvb, pinfo, openflow_tree, offset, length);
890 break;
891 case OFPT_1_0_STATS_REPLY: /* 17 */
892 dissect_openflow_stats_resp(tvb, pinfo, openflow_tree, offset, length);
893 break;
894 default:
895 if(length>8){
896 expert_add_info(pinfo, type_item, &ei_openflow_1_0_type);
897 }
898 break;
899 }
900
901 return tvb_reported_length(tvb);
902
903 }
904
905
906 /*
907 * Register the protocol with Wireshark.
908 */
909 void
proto_register_openflow_v1(void)910 proto_register_openflow_v1(void)
911 {
912 static hf_register_info hf[] = {
913 { &hf_openflow_version,
914 { "Version", "openflow.version",
915 FT_UINT8, BASE_HEX, VALS(openflow_version_values), 0x7f,
916 NULL, HFILL }
917 },
918 { &hf_openflow_1_0_type,
919 { "Type", "openflow_1_0.type",
920 FT_UINT8, BASE_DEC | BASE_EXT_STRING, &openflow_1_0_type_values_ext, 0x0,
921 NULL, HFILL }
922 },
923 { &hf_openflow_xid,
924 { "Transaction ID", "openflow.xid",
925 FT_UINT32, BASE_DEC, NULL, 0x0,
926 NULL, HFILL }
927 },
928 { &hf_openflow_length,
929 { "Length", "openflow.length",
930 FT_UINT16, BASE_DEC, NULL, 0x0,
931 NULL, HFILL }
932 },
933 { &hf_openflow_datapath_id,
934 { "Datapath unique ID", "openflow.datapath_id",
935 FT_UINT64, BASE_HEX, NULL, 0x0,
936 NULL, HFILL }
937 },
938 { &hf_openflow_datapath_mac,
939 { "MAC addr", "openflow.datapath_mac",
940 FT_ETHER, BASE_NONE, NULL, 0x0,
941 NULL, HFILL }
942 },
943 { &hf_openflow_datapath_impl,
944 { "Implementers part", "openflow.datapath_imp",
945 FT_UINT16, BASE_HEX, NULL, 0x0,
946 NULL, HFILL }
947 },
948 { &hf_openflow_n_buffers,
949 { "n_buffers", "openflow.n_buffers",
950 FT_UINT32, BASE_DEC, NULL, 0x0,
951 NULL, HFILL }
952 },
953 { &hf_openflow_n_tables,
954 { "n_tables", "openflow.n_tables",
955 FT_UINT8, BASE_DEC, NULL, 0x0,
956 NULL, HFILL }
957 },
958 #if 0
959 { &hf_openflow_auxiliary_id,
960 { "auxiliary_id", "openflow.auxiliary_id",
961 FT_UINT8, BASE_DEC, NULL, 0x0,
962 NULL, HFILL }
963 },
964 #endif
965 { &hf_openflow_capabilities,
966 { "capabilities", "openflow.capabilities",
967 FT_UINT32, BASE_HEX, NULL, 0x0,
968 NULL, HFILL }
969 },
970 { &hf_openflow_actions,
971 { "actions", "openflow.actions",
972 FT_UINT32, BASE_HEX, NULL, 0x0,
973 NULL, HFILL }
974 },
975 #if 0
976 { &hf_openflow_reserved32,
977 { "Reserved", "openflow.reserved32",
978 FT_UINT32, BASE_DEC, NULL, 0x0,
979 NULL, HFILL }
980 },
981 #endif
982 { &hf_openflow_cap_flow_stats,
983 { "Flow statistics", "openflow.flow_stats",
984 FT_BOOLEAN, 32, NULL, OFPC_FLOW_STATS,
985 NULL, HFILL }
986 },
987 { &hf_openflow_table_stats,
988 { "Table statistics", "openflow.table_stats",
989 FT_BOOLEAN, 32, NULL, OFPC_TABLE_STATS,
990 NULL, HFILL }
991 },
992 { &hf_openflow_port_stats,
993 { "Port statistics", "openflow.port_stats",
994 FT_BOOLEAN, 32, NULL, OFPC_PORT_STATS,
995 NULL, HFILL }
996 },
997 { &hf_openflow_group_stats,
998 { "Group statistics", "openflow.group_stats",
999 FT_BOOLEAN, 32, NULL, OFPC_GROUP_STATS,
1000 NULL, HFILL }
1001 },
1002 { &hf_openflow_ip_reasm,
1003 { "Can reassemble IP fragments", "openflow.ip_reasm",
1004 FT_BOOLEAN, 32, NULL, OFPC_IP_REASM,
1005 NULL, HFILL }
1006 },
1007 { &hf_openflow_queue_stats,
1008 { "Queue statistics", "openflow.queue_stats",
1009 FT_BOOLEAN, 32, NULL, OFPC_QUEUE_STATS,
1010 NULL, HFILL }
1011 },
1012 { &hf_openflow_port_blocked,
1013 { "Switch will block looping ports", "openflow.port_blocked",
1014 FT_BOOLEAN, 32, NULL, OFPC_PORT_BLOCKED,
1015 NULL, HFILL }
1016 },
1017 { &hf_openflow_output,
1018 { "Output to switch port", "openflow.output",
1019 FT_BOOLEAN, 32, NULL, OFPAT_OUTPUT_MASK,
1020 NULL, HFILL }
1021 },
1022 { &hf_openflow_set_vlan_vid,
1023 { "Set the 802.1q VLAN id", "openflow.set_vlan_vid",
1024 FT_BOOLEAN, 32, NULL, OFPAT_SET_VLAN_VID_MASK,
1025 NULL, HFILL }
1026 },
1027 { &hf_openflow_set_vlan_pcp,
1028 { "Set the 802.1q priority", "openflow.set_vlan_pcp",
1029 FT_BOOLEAN, 32, NULL, OFPAT_SET_VLAN_PCP_MASK,
1030 NULL, HFILL }
1031 },
1032 { &hf_openflow_strip_vlan,
1033 { "Strip the 802.1q header", "openflow.strip_vlan",
1034 FT_BOOLEAN, 32, NULL, OFPAT_STRIP_VLAN_MASK,
1035 NULL, HFILL }
1036 },
1037 { &hf_openflow_set_dl_src,
1038 { "Ethernet source address", "openflow.set_dl_src",
1039 FT_BOOLEAN, 32, NULL, OFPAT_SET_DL_SRC_MASK,
1040 NULL, HFILL }
1041 },
1042 { &hf_openflow_set_dl_dst,
1043 { "Ethernet destination address", "openflow.set_dl_ds",
1044 FT_BOOLEAN, 32, NULL, OFPAT_SET_DL_DST_MASK,
1045 NULL, HFILL }
1046 },
1047 { &hf_openflow_set_nw_src,
1048 { "IP source address", "openflow.set_nw_src",
1049 FT_BOOLEAN, 32, NULL, OFPAT_SET_NW_SRC_MASK,
1050 NULL, HFILL }
1051 },
1052 { &hf_openflow_set_nw_dst,
1053 { "IP destination address", "openflow.set_nw_ds",
1054 FT_BOOLEAN, 32, NULL, OFPAT_SET_NW_DST_MASK,
1055 NULL, HFILL }
1056 },
1057 { &hf_openflow_set_nw_tos,
1058 { "IP ToS (DSCP field, 6 bits)", "openflow.set_nw_tos",
1059 FT_BOOLEAN, 32, NULL, OFPAT_SET_NW_TOS_MASK,
1060 NULL, HFILL }
1061 },
1062 { &hf_openflow_set_tp_src,
1063 { "TCP/UDP source port", "openflow.set_tp_src",
1064 FT_BOOLEAN, 32, NULL, OFPAT_SET_TP_SRC_MASK,
1065 NULL, HFILL }
1066 },
1067 { &hf_openflow_set_tp_dst,
1068 { "TCP/UDP destination port", "openflow.set_tp_dst",
1069 FT_BOOLEAN, 32, NULL, OFPAT_SET_TP_DST_MASK,
1070 NULL, HFILL }
1071 },
1072 { &hf_openflow_enqueue,
1073 { "Output to queue", "openflow.enqueue",
1074 FT_BOOLEAN, 32, NULL, OFPAT_ENQUEUE_MASK,
1075 NULL, HFILL }
1076 },
1077 { &hf_openflow_port_no,
1078 { "Port number", "openflow.port_no",
1079 FT_UINT16, BASE_DEC, NULL, 0x0,
1080 NULL, HFILL }
1081 },
1082 { &hf_openflow_hw_addr,
1083 { "HW Address", "openflow.hw_add",
1084 FT_ETHER, BASE_NONE, NULL, 0x0,
1085 NULL, HFILL }
1086 },
1087 { &hf_openflow_port_name,
1088 { "Port Name", "openflow.port_name",
1089 FT_STRING, BASE_NONE, NULL, 0x0,
1090 NULL, HFILL }
1091 },
1092 { &hf_openflow_port_config,
1093 { "Config flags", "openflow.port_config",
1094 FT_UINT32, BASE_HEX, NULL, 0x0,
1095 NULL, HFILL }
1096 },
1097 { &hf_openflow_port_state,
1098 { "State flags", "openflow.port_state",
1099 FT_UINT32, BASE_HEX, NULL, 0x0,
1100 NULL, HFILL }
1101 },
1102 { &hf_openflow_port_curr,
1103 { "Current features", "openflow.port_curr",
1104 FT_UINT32, BASE_HEX, NULL, 0x0,
1105 NULL, HFILL }
1106 },
1107 { &hf_openflow_port_advertised,
1108 { "Advertised features", "openflow.port_advertised",
1109 FT_UINT32, BASE_HEX, NULL, 0x0,
1110 NULL, HFILL }
1111 },
1112 { &hf_openflow_port_supported,
1113 { "Features supported", "openflow.port_supported",
1114 FT_UINT32, BASE_HEX, NULL, 0x0,
1115 NULL, HFILL }
1116 },
1117 { &hf_openflow_port_peer,
1118 { "Features advertised by peer", "openflow.port_peer",
1119 FT_UINT32, BASE_HEX, NULL, 0x0,
1120 NULL, HFILL }
1121 },
1122 { &hf_openflow_port_down,
1123 { "Port is administratively down", "openflow.port_down",
1124 FT_BOOLEAN, 32, NULL, OFPPC_PORT_DOWN,
1125 NULL, HFILL }
1126 },
1127 { &hf_openflow_no_stp,
1128 { "Disable 802.1D spanning tree on port", "openflow.no_stp",
1129 FT_BOOLEAN, 32, NULL, OFPPC_NO_STP,
1130 NULL, HFILL }
1131 },
1132 { &hf_openflow_no_recv,
1133 { "Drop all packets except 802.1D spanning tree packets", "openflow.no_recv",
1134 FT_BOOLEAN, 32, NULL, OFPPC_NO_RECV,
1135 NULL, HFILL }
1136 },
1137 { &hf_openflow_no_recv_stp,
1138 { "Drop received 802.1D STP packets", "openflow.no_recv_stp",
1139 FT_BOOLEAN, 32, NULL, OFPPC_NO_RECV_STP,
1140 NULL, HFILL }
1141 },
1142 { &hf_openflow_no_flood,
1143 { "Do not include this port when flooding", "openflow.no_flood",
1144 FT_BOOLEAN, 32, NULL, OFPPC_NO_FLOOD,
1145 NULL, HFILL }
1146 },
1147 { &hf_openflow_no_fwd,
1148 { "Drop packets forwarded to port", "openflow.no_fwd",
1149 FT_BOOLEAN, 32, NULL, OFPPC_NO_FWD,
1150 NULL, HFILL }
1151 },
1152 { &hf_openflow_no_packet_in,
1153 { "Do not send packet-in msgs for port", "openflow.no_packet_in",
1154 FT_BOOLEAN, 32, NULL, OFPPC_NO_PACKET_IN,
1155 NULL, HFILL }
1156 },
1157 { &hf_openflow_link_down,
1158 { "No physical link present", "openflow.link_down",
1159 FT_BOOLEAN, 32, NULL, OFPPS_LINK_DOWN,
1160 NULL, HFILL }
1161 },
1162 { &hf_openflow_10mb_hd,
1163 { "10 Mb half-duplex rate support", "openflow.10mb_hd",
1164 FT_BOOLEAN, 32, NULL, OFPPF_10MB_HD,
1165 NULL, HFILL }
1166 },
1167 { &hf_openflow_10mb_fd,
1168 { "10 Mb full-duplex rate support", "openflow.10mb_fd",
1169 FT_BOOLEAN, 32, NULL, OFPPF_10MB_FD,
1170 NULL, HFILL }
1171 },
1172 { &hf_openflow_100mb_hd,
1173 { "100 Mb half-duplex rate support", "openflow.100mb_hd",
1174 FT_BOOLEAN, 32, NULL, OFPPF_100MB_HD,
1175 NULL, HFILL }
1176 },
1177 { &hf_openflow_100mb_fd,
1178 { "100 Mb full-duplex rate support", "openflow.100mb_0fd",
1179 FT_BOOLEAN, 32, NULL, OFPPF_100MB_FD,
1180 NULL, HFILL }
1181 },
1182 { &hf_openflow_1gb_hd,
1183 { "1 Gb half-duplex rate support", "openflow.1gb_hd",
1184 FT_BOOLEAN, 32, NULL, OFPPF_1GB_HD,
1185 NULL, HFILL }
1186 },
1187 { &hf_openflow_1gb_fd,
1188 { "1 Gb full-duplex rate support", "openflow.1gb_fd",
1189 FT_BOOLEAN, 32, NULL, OFPPF_1GB_FD,
1190 NULL, HFILL }
1191 },
1192 { &hf_openflow_10gb_fd,
1193 { "10 Gb full-duplex rate support", "openflow.10gb_fd",
1194 FT_BOOLEAN, 32, NULL, OFPPF_10GB_FD,
1195 NULL, HFILL }
1196 },
1197 { &hf_openflow_copper,
1198 { "Copper medium", "openflow.copper",
1199 FT_BOOLEAN, 32, NULL, OFPPF_COPPER,
1200 NULL, HFILL }
1201 },
1202 { &hf_openflow_fiber,
1203 { "Fiber medium", "openflow.fiber",
1204 FT_BOOLEAN, 32, NULL, OFPPF_FIBER,
1205 NULL, HFILL }
1206 },
1207 { &hf_openflow_autoneg,
1208 { "Auto-negotiation", "openflow.autoneg",
1209 FT_BOOLEAN, 32, NULL, OFPPF_AUTONEG,
1210 NULL, HFILL }
1211 },
1212 { &hf_openflow_pause,
1213 { "Pause", "openflow.pause",
1214 FT_BOOLEAN, 32, NULL, OFPPF_PAUSE,
1215 NULL, HFILL }
1216 },
1217 { &hf_openflow_pause_asym,
1218 { "Asymmetric pause", "openflow.pause_asym",
1219 FT_BOOLEAN, 32, NULL, OFPPF_PAUSE_ASYM,
1220 NULL, HFILL }
1221 },
1222 { &hf_openflow_config_flags,
1223 { "Config flags", "openflow.config_flags",
1224 FT_UINT16, BASE_HEX, NULL, 0x0,
1225 NULL, HFILL }
1226 },
1227 { &hf_openflow_miss_send_len,
1228 { "Max bytes of packet", "openflow.miss_send_len",
1229 FT_UINT16, BASE_HEX, NULL, 0x0,
1230 NULL, HFILL }
1231 },
1232 { &hf_openflow_buffer_id,
1233 { "Buffer Id", "openflow.buffer_id",
1234 FT_UINT32, BASE_HEX, NULL, 0x0,
1235 NULL, HFILL }
1236 },
1237 { &hf_openflow_total_len,
1238 { "Total length", "openflow.total_len",
1239 FT_UINT16, BASE_DEC, NULL, 0x0,
1240 NULL, HFILL }
1241 },
1242 { &hf_openflow_in_port,
1243 { "In port", "openflow.in_port",
1244 FT_UINT16, BASE_DEC, NULL, 0x0,
1245 NULL, HFILL }
1246 },
1247 { &hf_openflow_reason,
1248 { "Reason", "openflow.reason",
1249 FT_UINT8, BASE_DEC, VALS(openflow_reason_values), 0x0,
1250 NULL, HFILL }
1251 },
1252
1253 { &hf_openflow_pkt_in_pad,
1254 { "Pad", "openflow.pkt_in.pad",
1255 FT_BYTES, BASE_NONE, NULL, 0x0,
1256 NULL, HFILL }
1257 },
1258 { &hf_openflow_table_id,
1259 { "Table Id", "openflow.table_id",
1260 FT_UINT8, BASE_DEC, NULL, 0x0,
1261 NULL, HFILL }
1262 },
1263 { &hf_openflow_cookie,
1264 { "Cookie", "openflow.cookie",
1265 FT_UINT64, BASE_HEX, NULL, 0x0,
1266 NULL, HFILL }
1267 },
1268 #if 0
1269 { &hf_openflow_cookie_mask,
1270 { "Cookie mask", "openflow.cookie_mask",
1271 FT_UINT64, BASE_HEX, NULL, 0x0,
1272 NULL, HFILL }
1273 },
1274 #endif
1275 { &hf_openflow_features_reply_pad,
1276 { "Pad", "openflow.features_reply.pad",
1277 FT_BYTES, BASE_NONE, NULL, 0x0,
1278 NULL, HFILL }
1279 },
1280 { &hf_openflow_actions_len,
1281 { "Actions length", "openflow.actions_len",
1282 FT_UINT16, BASE_DEC, NULL, 0x0,
1283 NULL, HFILL }
1284 },
1285 { &hf_openflow_action_type,
1286 { "Actions type", "openflow.action_typ",
1287 FT_UINT16, BASE_DEC, VALS(openflow_action_values), 0x0,
1288 NULL, HFILL }
1289 },
1290 { &hf_openflow_action_len,
1291 { "Action length", "openflow.action_len",
1292 FT_UINT16, BASE_DEC, NULL, 0x0,
1293 NULL, HFILL }
1294 },
1295 { &hf_openflow_output_port,
1296 { "Output port", "openflow.output_port",
1297 FT_UINT16, BASE_DEC, NULL, 0x0,
1298 NULL, HFILL }
1299 },
1300 { &hf_openflow_max_len,
1301 { "Max length", "openflow.max_len",
1302 FT_UINT16, BASE_DEC, NULL, 0x0,
1303 NULL, HFILL }
1304 },
1305 { &hf_openflow_wildcards,
1306 { "Wildcards", "openflow.wildcards",
1307 FT_UINT32, BASE_DEC, NULL, 0x0,
1308 NULL, HFILL }
1309 },
1310 { &hf_openflow_command,
1311 { "Command", "openflow.command",
1312 FT_UINT16, BASE_DEC, VALS(openflow_command_values), 0x0,
1313 NULL, HFILL }
1314 },
1315 { &hf_openflow_eth_src,
1316 { "Ethernet source address", "openflow.eth_src",
1317 FT_ETHER, BASE_NONE, NULL, 0x0,
1318 NULL, HFILL }
1319 },
1320 { &hf_openflow_eth_dst,
1321 { "Ethernet destination address", "openflow.eth_dst",
1322 FT_ETHER, BASE_NONE, NULL, 0x0,
1323 NULL, HFILL }
1324 },
1325 { &hf_openflow_dl_vlan,
1326 { "Input VLAN id", "openflow.dl_vlan",
1327 FT_UINT16, BASE_DEC, NULL, 0x0,
1328 NULL, HFILL }
1329 },
1330 { &hf_openflow_dl_vlan_pcp,
1331 { "Input VLAN priority", "openflow.dl_vlan_pcp",
1332 FT_UINT8, BASE_DEC, NULL, 0x0,
1333 NULL, HFILL }
1334 },
1335 { &hf_openflow_ofp_match_pad,
1336 { "Pad", "openflow.ofp_match.pad",
1337 FT_BYTES, BASE_NONE, NULL, 0x0,
1338 NULL, HFILL }
1339 },
1340 { &hf_openflow_match_dl_type,
1341 { "Dl type", "openflow.ofp_match.dl_type",
1342 FT_UINT16, BASE_DEC, NULL, 0x0,
1343 NULL, HFILL }
1344 },
1345 { &hf_openflow_ofp_match_tos,
1346 { "IP ToS", "openflow.ofp_match.tos",
1347 FT_UINT8, BASE_DEC, NULL, 0x0,
1348 NULL, HFILL }
1349 },
1350 { &hf_openflow_ofp_match_nw_proto,
1351 { "IP protocol", "openflow.ofp_match.nw_proto",
1352 FT_UINT8, BASE_DEC, NULL, 0x0,
1353 NULL, HFILL }
1354 },
1355 { &hf_openflow_ofp_source_addr,
1356 { "Source Address", "openflow.ofp_match.source_addr",
1357 FT_IPv4, BASE_NONE, NULL, 0x0,
1358 NULL, HFILL }
1359 },
1360 { &hf_openflow_ofp_dest_addr,
1361 { "Destination Address", "openflow.ofp_match.dest_addr",
1362 FT_IPv4, BASE_NONE, NULL, 0x0,
1363 NULL, HFILL }
1364 },
1365 { &hf_openflow_ofp_source_port,
1366 { "Source Port", "openflow.ofp_match.source_port",
1367 FT_UINT16, BASE_DEC, NULL, 0x0,
1368 NULL, HFILL }
1369 },
1370 { &hf_openflow_ofp_dest_port,
1371 { "Destination Port", "openflow.ofp_match.dest_port",
1372 FT_UINT16, BASE_DEC, NULL, 0x0,
1373 NULL, HFILL }
1374 },
1375 { &hf_openflow_idle_timeout,
1376 { "Idle time-out", "openflow.idle_timeout",
1377 FT_UINT16, BASE_DEC, NULL, 0x0,
1378 NULL, HFILL }
1379 },
1380 { &hf_openflow_hard_timeout,
1381 { "hard time-out", "openflow.hard_timeout",
1382 FT_UINT16, BASE_DEC, NULL, 0x0,
1383 NULL, HFILL }
1384 },
1385 { &hf_openflow_priority,
1386 { "Priority", "openflow.priority",
1387 FT_UINT16, BASE_DEC, NULL, 0x0,
1388 NULL, HFILL }
1389 },
1390 { &hf_openflow_out_port,
1391 { "Out port", "openflow.out_port",
1392 FT_UINT32, BASE_DEC, NULL, 0x0,
1393 NULL, HFILL }
1394 },
1395 #if 0
1396 { &hf_openflow_out_group,
1397 { "Out group", "openflow.out_group",
1398 FT_UINT32, BASE_DEC, NULL, 0x0,
1399 NULL, HFILL }
1400 },
1401 #endif
1402 { &hf_openflow_flags,
1403 { "Flags", "openflow.flags",
1404 FT_UINT16, BASE_DEC, NULL, 0x0,
1405 NULL, HFILL }
1406 },
1407 { &hf_openflow_v1_stats_type,
1408 { "Type", "openflow.stats.type",
1409 FT_UINT16, BASE_DEC, VALS(openflow_stats_type_values), 0x0,
1410 NULL, HFILL }
1411 },
1412 { &hf_openflow_v1_flow_stats_request_pad,
1413 { "Pad", "openflow.stats.request_pad",
1414 FT_UINT8, BASE_DEC, NULL, 0x0,
1415 NULL, HFILL }
1416 },
1417 };
1418
1419 static gint *ett[] = {
1420 &ett_openflow,
1421 &ett_openflow_path_id,
1422 &ett_openflow_cap,
1423 &ett_openflow_act,
1424 &ett_openflow_port,
1425 &ett_openflow_port_cnf,
1426 &ett_openflow_port_state,
1427 &ett_openflow_port_cf
1428 };
1429
1430 static ei_register_info ei[] = {
1431 #if 0
1432 { &ei_openflow_undecoded_data, { "openflow.undecoded_data", PI_UNDECODED, PI_WARN, "Data not dissected yet", EXPFILL }},
1433 #endif
1434 { &ei_openflow_action_type, { "openflow.action_typ.undecoded", PI_UNDECODED, PI_WARN, "Action not dissected yet", EXPFILL }},
1435 { &ei_openflow_1_0_type, { "openflow_1_0.type.undecoded", PI_UNDECODED, PI_WARN, "Message data not dissected yet", EXPFILL }},
1436 };
1437
1438 expert_module_t* expert_openflow_v1;
1439
1440 /* Register the protocol name and description */
1441 proto_openflow_v1 = proto_register_protocol("OpenFlow 1.0",
1442 "openflow_v1", "openflow_v1");
1443
1444 register_dissector("openflow_v1", dissect_openflow_v1, proto_openflow_v1);
1445
1446 /* Required function calls to register the header fields and subtrees */
1447 proto_register_field_array(proto_openflow_v1, hf, array_length(hf));
1448 proto_register_subtree_array(ett, array_length(ett));
1449 expert_openflow_v1 = expert_register_protocol(proto_openflow_v1);
1450 expert_register_field_array(expert_openflow_v1, ei, array_length(ei));
1451 }
1452
1453 void
proto_reg_handoff_openflow_v1(void)1454 proto_reg_handoff_openflow_v1(void)
1455 {
1456 eth_withoutfcs_handle = find_dissector_add_dependency("eth_withoutfcs", proto_openflow_v1);
1457 }
1458
1459 /*
1460 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1461 *
1462 * Local variables:
1463 * c-basic-offset: 4
1464 * tab-width: 8
1465 * indent-tabs-mode: nil
1466 * End:
1467 *
1468 * vi: set shiftwidth=4 tabstop=8 expandtab:
1469 * :indentSize=4:tabSize=8:noTabs=true:
1470 */
1471