2 * Routines for OpenFlow dissection
3 * Copyright 2013, Anders Broman <anders.broman@ericsson.com>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 * Ref https://www.opennetworking.org/sdn-resources/onf-specifications/openflow
32 #include <epan/packet.h>
33 #include <epan/prefs.h>
35 #include "packet-tcp.h"
37 void proto_register_openflow(void);
38 void proto_reg_handoff_openflow(void);
40 static int g_openflow_port = 0;
42 static dissector_handle_t openflow_v4_handle;
43 static dissector_handle_t eth_withoutfcs_handle;
45 /* Initialize the protocol and registered fields */
46 static int proto_openflow = -1;
47 static int hf_openflow_version = -1;
48 static int hf_openflow_1_0_type = -1;
49 static int hf_openflow_length = -1;
50 static int hf_openflow_xid = -1;
52 static int hf_openflow_datapath_id = -1;
53 static int hf_openflow_datapath_mac = -1;
54 static int hf_openflow_datapath_impl = -1;
55 static int hf_openflow_n_buffers = -1;
56 static int hf_openflow_n_tables = -1;
57 static int hf_openflow_auxiliary_id = -1;
58 static int hf_openflow_pad3 = -1;
59 static int hf_openflow_capabilities = -1;
60 static int hf_openflow_actions = -1;
61 static int hf_openflow_reserved32 = -1;
62 static int hf_openflow_cap_flow_stats = -1;
63 static int hf_openflow_table_stats = -1;
64 static int hf_openflow_port_stats = -1;
65 static int hf_openflow_group_stats = -1;
66 static int hf_openflow_ip_reasm = -1;
67 static int hf_openflow_queue_stats = -1;
68 static int hf_openflow_port_blocked = -1;
70 static int hf_openflow_output = -1; /* Output to switch port. */
71 static int hf_openflow_set_vlan_vid = -1; /* Set the 802.1q VLAN id. */
72 static int hf_openflow_set_vlan_pcp = -1; /* Set the 802.1q priority. */
73 static int hf_openflow_strip_vlan = -1; /* Strip the 802.1q header. */
74 static int hf_openflow_set_dl_src = -1; /* Ethernet source address. */
75 static int hf_openflow_set_dl_dst = -1; /* Ethernet destination address. */
76 static int hf_openflow_set_nw_src = -1; /* IP source address. */
77 static int hf_openflow_set_nw_dst = -1; /* IP destination address. */
78 static int hf_openflow_set_nw_tos = -1; /* IP ToS (DSCP field, 6 bits). */
79 static int hf_openflow_set_tp_src = -1; /* TCP/UDP source port. */
80 static int hf_openflow_set_tp_dst = -1; /* TCP/UDP destination port. */
81 static int hf_openflow_enqueue = -1; /* Output to queue. */
83 static int hf_openflow_port_no = -1;
84 static int hf_openflow_hw_addr = -1;
85 static int hf_openflow_port_name = -1;
88 static int hf_openflow_port_config = -1;
89 static int hf_openflow_port_state = -1;
90 static int hf_openflow_port_curr = -1;
91 static int hf_openflow_port_advertised = -1;
92 static int hf_openflow_port_supported = -1;
93 static int hf_openflow_port_peer = -1;
95 static int hf_openflow_port_down = -1; /* Port is administratively down. */
96 static int hf_openflow_no_stp = -1; /* Disable 802.1D spanning tree on port. */
97 static int hf_openflow_no_recv = -1; /* Drop all packets except 802.1D spanning tree packets. */
98 static int hf_openflow_no_recv_stp = -1; /* Drop received 802.1D STP packets. */
99 static int hf_openflow_no_flood = -1; /* Do not include this port when flooding. */
100 static int hf_openflow_no_fwd = -1; /* Drop packets forwarded to port. */
101 static int hf_openflow_no_packet_in = -1; /* Do not send packet-in msgs for port. */
103 static int hf_openflow_link_down = -1; /* No physical link present. */
105 static int hf_openflow_10mb_hd = -1; /* 10 Mb half-duplex rate support. */
106 static int hf_openflow_10mb_fd = -1; /* 10 Mb full-duplex rate support. */
107 static int hf_openflow_100mb_hd = -1; /* 100 Mb half-duplex rate support. */
108 static int hf_openflow_100mb_fd = -1; /* 100 Mb full-duplex rate support. */
109 static int hf_openflow_1gb_hd = -1; /* 1 Gb half-duplex rate support. */
110 static int hf_openflow_1gb_fd = -1; /* 1 Gb full-duplex rate support. */
111 static int hf_openflow_10gb_fd = -1; /* 10 Gb full-duplex rate support. */
112 static int hf_openflow_copper = -1; /* Copper medium. */
113 static int hf_openflow_fiber = -1; /* Fiber medium. */
114 static int hf_openflow_autoneg = -1; /* Auto-negotiation. */
115 static int hf_openflow_pause = -1; /* Pause. */
116 static int hf_openflow_pause_asym = -1; /* Asymmetric pause. */
118 static int hf_openflow_config_flags = -1;
119 static int hf_openflow_miss_send_len = -1;
121 static int hf_openflow_buffer_id = -1;
122 static int hf_openflow_total_len = -1;
123 static int hf_openflow_in_port = -1;
124 static int hf_openflow_reason = -1;
125 static int hf_openflow_table_id = -1;
126 static int hf_openflow_cookie = -1;
127 static int hf_openflow_cookie_mask = -1;
128 static int hf_openflow_padd8 = -1;
129 static int hf_openflow_padd16 = -1;
130 static int hf_openflow_padd48 = -1;
131 static int hf_openflow_actions_len = -1;
132 static int hf_openflow_action_type = -1;
133 static int hf_openflow_action_len = -1;
134 static int hf_openflow_output_port = -1;
135 static int hf_openflow_max_len = -1;
136 static int hf_openflow_wildcards = -1;
137 static int hf_openflow_command = -1;
138 static int hf_openflow_eth_src = -1;
139 static int hf_openflow_eth_dst = -1;
140 static int hf_openflow_dl_vlan = -1;
141 static int hf_openflow_dl_vlan_pcp = -1;
142 static int hf_openflow_idle_timeout = -1;
143 static int hf_openflow_hard_timeout = -1;
144 static int hf_openflow_priority = -1;
145 static int hf_openflow_out_port = -1;
146 static int hf_openflow_out_group = -1;
147 static int hf_openflow_flags = -1;
149 /* Initialize the subtree pointers */
150 static gint ett_openflow = -1;
151 static gint ett_openflow_path_id = -1;
152 static gint ett_openflow_cap = -1;
153 static gint ett_openflow_act = -1;
154 static gint ett_openflow_port = -1;
155 static gint ett_openflow_port_cnf = -1;
156 static gint ett_openflow_port_state = -1;
157 static gint ett_openflow_port_cf = -1;
159 static gboolean openflow_desegment = TRUE;
161 #define OFP_VERSION_1_0 1
162 #define OFP_VERSION_1_1 2
163 #define OFP_VERSION_1_2 3
164 #define OFP_VERSION_1_3 4
166 static const value_string openflow_version_values[] = {
174 /* Immutable messages. */
175 #define OFPT_1_0_HELLO 0 /* Symmetric message */
176 #define OFPT_1_0_ERROR 1 /* Symmetric message */
177 #define OFPT_1_0_ECHO_REQUEST 2 /* Symmetric message */
178 #define OFPT_1_0_ECHO_REPLY 3 /* Symmetric message */
179 #define OFPT_1_0_VENDOR 4 /* Symmetric message */
180 /* Switch configuration messages. */
181 #define OFPT_1_0_FEATURES_REQUEST 5 /* Controller/switch message */
182 #define OFPT_1_0_FEATURES_REPLY 6 /* Controller/switch message */
183 #define OFPT_1_0_GET_CONFIG_REQUEST 7 /* Controller/switch message */
184 #define OFPT_1_0_GET_CONFIG_REPLY 8 /* Controller/switch message */
185 #define OFPT_1_0_SET_CONFIG 9 /* Controller/switch message */
186 /* Asynchronous messages. */
187 #define OFPT_1_0_PACKET_IN 10 /* Async message */
188 #define OFPT_1_0_FLOW_REMOVED 11 /* Async message */
189 #define OFPT_1_0_PORT_STATUS 12 /* Async message */
190 /* Controller command messages. */
191 #define OFPT_1_0_PACKET_OUT 13 /* Controller/switch message */
192 #define OFPT_1_0_FLOW_MOD 14 /* Controller/switch message */
193 #define OFPT_1_0_PORT_MOD 15 /* Controller/switch message */
194 /* Statistics messages. */
195 #define OFPT_1_0_STATS_REQUEST 16 /* Controller/switch message */
196 #define OFPT_1_0_STATS_REPLY 17 /* Controller/switch message */
197 /* Barrier messages. */
198 #define OFPT_1_0_BARRIER_REQUEST 18 /* Controller/switch message */
199 #define OFPT_1_0_BARRIER_REPLY 19 /* Controller/switch message */
200 /* Queue Configuration messages. */
201 #define OFPT_1_0_QUEUE_GET_CONFIG_REQUEST 20 /* Controller/switch message */
202 #define OFPT_1_0_QUEUE_GET_CONFIG_REPLY 21 /* Controller/switch message */
205 static const value_string openflow_1_0_type_values[] = {
206 /* Immutable messages. */
208 /* Immutable messages. */
209 { 0, "OFPT_HELLO" }, /* Symmetric message */
210 { 1, "OFPT_ERROR" }, /* Symmetric message */
211 { 2, "OFPT_ECHO_REQUEST" }, /* Symmetric message */
212 { 3, "OFPT_ECHO_REPLY" }, /* Symmetric message */
213 { 4, "OFPT_VENDOR" }, /* Symmetric message */
214 /* Switch configuration messages. */
215 { 5, "OFPT_FEATURES_REQUEST" }, /* Controller/switch message */
216 { 6, "OFPT_FEATURES_REPLY" }, /* Controller/switch message */
217 { 7, "OFPT_GET_CONFIG_REQUEST" }, /* Controller/switch message */
218 { 8, "OFPT_GET_CONFIG_REPLY" }, /* Controller/switch message */
219 { 9, "OFPT_SET_CONFIG" }, /* Controller/switch message */
220 /* Asynchronous messages. */
221 { 10, "OFPT_PACKET_IN" }, /* Async message */
222 { 11, "OFPT_FLOW_REMOVED" }, /* Async message */
223 { 12, "OFPT_PORT_STATUS" }, /* Async message */
224 /* Controller command messages. */
225 { 13, "OFPT_PACKET_OUT" }, /* Controller/switch message */
226 { 14, "OFPT_FLOW_MOD" }, /* Controller/switch message */
227 { 15, "OFPT_PORT_MOD" }, /* Controller/switch message */
228 /* Statistics messages. */
229 { 16, "OFPT_STATS_REQUEST" }, /* Controller/switch message */
230 { 17, "OFPT_STATS_REPLY" }, /* Controller/switch message */
231 /* Barrier messages. */
232 { 18, "OFPT_BARRIER_REQUEST" }, /* Controller/switch message */
233 { 19, "OFPT_BARRIER_REPLY" }, /* Controller/switch message */
234 /* Queue Configuration messages. */
235 { 20, "OFPT_QUEUE_GET_CONFIG_REQUEST" }, /* Controller/switch message */
236 { 21, "OFPT_QUEUE_GET_CONFIG_REPLY" }, /* Controller/switch message */
241 #define OFPC_FLOW_STATS 1<<0 /* Flow statistics. */
242 #define OFPC_TABLE_STATS 1<<1 /* Table statistics. */
243 #define OFPC_PORT_STATS 1<<2 /* Port statistics. */
244 #define OFPC_GROUP_STATS 1<<3 /* Group statistics. */
245 #define OFPC_IP_REASM 1<<5 /* Can reassemble IP fragments. */
246 #define OFPC_QUEUE_STATS 1<<6 /* Queue statistics. */
247 #define OFPC_PORT_BLOCKED 1<<8 /* Switch will block looping ports. */
249 #define OFPAT_OUTPUT_MASK 1<<0 /* Output to switch port. */
250 #define OFPAT_SET_VLAN_VID_MASK 1<<1 /* Set the 802.1q VLAN id. */
251 #define OFPAT_SET_VLAN_PCP_MASK 1<<2 /* Set the 802.1q priority. */
252 #define OFPAT_STRIP_VLAN_MASK 1<<3 /* Strip the 802.1q header. */
253 #define OFPAT_SET_DL_SRC_MASK 1<<4 /* Ethernet source address. */
254 #define OFPAT_SET_DL_DST_MASK 1<<5 /* Ethernet destination address. */
255 #define OFPAT_SET_NW_SRC_MASK 1<<6 /* IP source address. */
256 #define OFPAT_SET_NW_DST_MASK 1<<7 /* IP destination address. */
257 #define OFPAT_SET_NW_TOS_MASK 1<<8 /* IP ToS (DSCP field, 6 bits). */
258 #define OFPAT_SET_TP_SRC_MASK 1<<9 /* TCP/UDP source port. */
259 #define OFPAT_SET_TP_DST_MASK 1<<10 /* TCP/UDP destination port. */
260 #define OFPAT_ENQUEUE_MASK 1<<11 /* Output to queue. */
262 #define OFPPC_PORT_DOWN 1<<0 /* Port is administratively down. */
263 #define OFPPC_NO_STP 1<<1 /* Disable 802.1D spanning tree on port. */
264 #define OFPPC_NO_RECV 1<<2 /* Drop all packets except 802.1D spanning tree packets. */
265 #define OFPPC_NO_RECV_STP 1<<3 /* Drop received 802.1D STP packets. */
266 #define OFPPC_NO_FLOOD 1<<4 /* Do not include this port when flooding. */
267 #define OFPPC_NO_FWD 1<<5 /* Drop packets forwarded to port. */
268 #define OFPPC_NO_PACKET_IN 1<<6 /* Do not send packet-in msgs for port. */
270 #define OFP_MAX_PORT_NAME_LEN 16
272 #define OFPPS_LINK_DOWN 1<<0 /* No physical link present. */
273 #define OFPPS_STP_LISTEN 0<<8 /* Not learning or relaying frames. */
274 #define OFPPS_STP_LEARN 1<<8 /* Learning but not relaying frames. */
275 #define OFPPS_STP_FORWARD 2<<8 /* Learning and relaying frames. */
276 #define OFPPS_STP_BLOCK 3<<8 /* Not part of spanning tree. */
277 #define OFPPS_STP_MASK 3<<8 /* Bit mask for OFPPS_STP_* values. */
280 #define OFPPF_10MB_HD 1<<0 /* 10 Mb half-duplex rate support. */
281 #define OFPPF_10MB_FD 1<<1 /* 10 Mb full-duplex rate support. */
282 #define OFPPF_100MB_HD 1<<2 /* 100 Mb half-duplex rate support. */
283 #define OFPPF_100MB_FD 1<<3 /* 100 Mb full-duplex rate support. */
284 #define OFPPF_1GB_HD 1<<4 /* 1 Gb half-duplex rate support. */
285 #define OFPPF_1GB_FD 1<<5 /* 1 Gb full-duplex rate support. */
286 #define OFPPF_10GB_FD 1<<6 /* 10 Gb full-duplex rate support. */
287 #define OFPPF_COPPER 1<<7 /* Copper medium. */
288 #define OFPPF_FIBER 1<<8 /* Fiber medium. */
289 #define OFPPF_AUTONEG 1<<9 /* Auto-negotiation. */
290 #define OFPPF_PAUSE 1<<10 /* Pause. */
291 #define OFPPF_PAUSE_ASYM 1<<11 /* Asymmetric pause. */
294 #define OFPAT_OUTPUT 0 /* Output to switch port. */
295 #define OFPAT_SET_VLAN_VID 1 /* Set the 802.1q VLAN id. */
296 #define OFPAT_SET_VLAN_PCP 2 /* Set the 802.1q priority. */
297 #define OFPAT_STRIP_VLAN 3 /* Strip the 802.1q header. */
298 #define OFPAT_SET_DL_SRC 4 /* Ethernet source address. */
299 #define OFPAT_SET_DL_DST 5 /* Ethernet destination address. */
300 #define OFPAT_SET_NW_SRC 6 /* IP source address. */
301 #define OFPAT_SET_NW_DST 7 /* IP destination address. */
302 #define OFPAT_SET_TP_SRC 8 /* TCP/UDP source port. */
303 #define OFPAT_SET_TP_DST 9 /* TCP/UDP destination port. */
304 #define OFPAT_VENDOR 0xffff
307 dissect_openflow_ofp_match_v_1_0(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
310 /* uint32_t wildcards; Wildcard fields. */
311 proto_tree_add_item(tree, hf_openflow_wildcards, tvb, offset, 4, ENC_BIG_ENDIAN);
313 /* uint16_t in_port; Input switch port. */
314 proto_tree_add_item(tree, hf_openflow_in_port, tvb, offset, 2, ENC_BIG_ENDIAN);
317 /* uint8_t dl_src[OFP_ETH_ALEN]; Ethernet source address. */
318 proto_tree_add_item(tree, hf_openflow_eth_src, tvb, offset, 6, ENC_NA);
320 /* uint8_t dl_dst[OFP_ETH_ALEN]; Ethernet destination address. */
321 proto_tree_add_item(tree, hf_openflow_eth_dst, tvb, offset, 6, ENC_NA);
323 /* uint16_t dl_vlan; Input VLAN id. */
324 proto_tree_add_item(tree, hf_openflow_dl_vlan, tvb, offset, 2, ENC_BIG_ENDIAN);
326 /* uint8_t dl_vlan_pcp; Input VLAN priority. */
327 proto_tree_add_item(tree, hf_openflow_dl_vlan_pcp, tvb, offset, 1, ENC_BIG_ENDIAN);
329 /* uint8_t pad1[1]; Align to 64-bits */
330 proto_tree_add_item(tree, hf_openflow_padd8, tvb, offset, 1, ENC_BIG_ENDIAN);
332 /* uint16_t dl_type; Ethernet frame type. */
333 /* uint8_t nw_tos; IP ToS (actually DSCP field, 6 bits). */
334 /* uint8_t nw_proto; IP protocol or lower 8 bits of
337 /* uint8_t pad2[2]; Align to 64-bits */
338 /* uint32_t nw_src; IP source address. */
339 /* uint32_t nw_dst; IP destination address. */
340 /* uint16_t tp_src; TCP/UDP source port. */
341 /* uint16_t tp_dst; TCP/UDP destination port. */
342 proto_tree_add_text(tree, tvb, offset, 18, "Data not dissected yet");
349 static const value_string openflow_action_values[] = {
350 { OFPAT_OUTPUT, "Output to switch port" },
351 { OFPAT_SET_VLAN_VID, "Set the 802.1q VLAN id" },
352 { OFPAT_SET_VLAN_PCP, "Set the 802.1q priority" },
353 { OFPAT_STRIP_VLAN, "Strip the 802.1q header" },
354 { OFPAT_SET_DL_SRC, "Ethernet source address" },
355 { OFPAT_SET_DL_DST, "Ethernet destination address" },
356 { OFPAT_SET_NW_SRC, "IP source address" },
357 { OFPAT_SET_NW_DST, "IP destination address" },
358 { OFPAT_SET_TP_SRC, "TCP/UDP source port" },
359 { OFPAT_SET_TP_DST, "TCP/UDP destination port" },
360 { OFPAT_VENDOR, "Vendor specific action"},
365 dissect_openflow_action_header(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
367 guint16 action_type, action_len;
369 /* uint16_t type; One of OFPAT_*. */
370 action_type = tvb_get_ntohs(tvb, offset);
371 proto_tree_add_item(tree, hf_openflow_action_type, tvb, offset, 2, ENC_BIG_ENDIAN);
373 /* Length of action, including this
374 * header. This is the length of action,
375 * including any padding to make it
378 action_len = tvb_get_ntohs(tvb, offset);
379 proto_tree_add_item(tree, hf_openflow_action_len, tvb, offset, 2, ENC_BIG_ENDIAN);
384 /* uint16_t port; Output port. */
385 proto_tree_add_item(tree, hf_openflow_output_port, tvb, offset, 2, ENC_BIG_ENDIAN);
387 /* uint16_t max_len; Max length to send to controller. */
388 proto_tree_add_item(tree, hf_openflow_max_len, tvb, offset, 2, ENC_BIG_ENDIAN);
392 proto_tree_add_text(tree, tvb, offset, action_len-4, "Action not dissected yet");
393 offset+=(action_len-4);
400 dissect_openflow_phy_port(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
403 proto_tree *port_cnf_tree, *port_state_tree, *port_cf_tree;
405 proto_tree_add_item(tree, hf_openflow_port_no, tvb, offset, 2, ENC_BIG_ENDIAN);
407 proto_tree_add_item(tree, hf_openflow_hw_addr, tvb, offset, 6, ENC_NA);
409 proto_tree_add_item(tree, hf_openflow_port_name, tvb, offset, OFP_MAX_PORT_NAME_LEN, ENC_ASCII|ENC_NA);
410 offset+=OFP_MAX_PORT_NAME_LEN;
412 /* Bitmap of OFPPC_* flags. */
413 ti = proto_tree_add_item(tree, hf_openflow_port_config, tvb, offset, 4, ENC_BIG_ENDIAN);
414 port_cnf_tree = proto_item_add_subtree(ti, ett_openflow_port_cnf);
416 /* Port is administratively down. */
417 proto_tree_add_item(port_cnf_tree, hf_openflow_port_down, tvb, offset, 4, ENC_BIG_ENDIAN);
418 /* Disable 802.1D spanning tree on port. */
419 proto_tree_add_item(port_cnf_tree, hf_openflow_no_stp, tvb, offset, 4, ENC_BIG_ENDIAN);
420 /* Drop all packets except 802.1D spanning tree packets. */
421 proto_tree_add_item(port_cnf_tree, hf_openflow_no_recv, tvb, offset, 4, ENC_BIG_ENDIAN);
422 /* Drop received 802.1D STP packets. */
423 proto_tree_add_item(port_cnf_tree, hf_openflow_no_recv_stp, tvb, offset, 4, ENC_BIG_ENDIAN);
424 /* Do not include this port when flooding. */
425 proto_tree_add_item(port_cnf_tree, hf_openflow_no_flood, tvb, offset, 4, ENC_BIG_ENDIAN);
426 /* Drop packets forwarded to port. */
427 proto_tree_add_item(port_cnf_tree, hf_openflow_no_fwd, tvb, offset, 4, ENC_BIG_ENDIAN);
428 /* Do not send packet-in msgs for port. */
429 proto_tree_add_item(port_cnf_tree, hf_openflow_no_packet_in, tvb, offset, 4, ENC_BIG_ENDIAN);
432 /* Bitmap of OFPPS_* flags. */
433 ti = proto_tree_add_item(tree, hf_openflow_port_state, tvb, offset, 4, ENC_BIG_ENDIAN);
434 port_state_tree = proto_item_add_subtree(ti, ett_openflow_port_state);
436 /* No physical link present. */
437 proto_tree_add_item(port_state_tree, hf_openflow_link_down, tvb, offset, 4, ENC_BIG_ENDIAN);
441 /* Current features. */
442 ti = proto_tree_add_item(tree, hf_openflow_port_curr, tvb, offset, 4, ENC_BIG_ENDIAN);
443 port_cf_tree = proto_item_add_subtree(ti, ett_openflow_port_cf);
444 /* 10 Mb half-duplex rate support. */
445 proto_tree_add_item(port_cf_tree, hf_openflow_10mb_hd, tvb, offset, 4, ENC_BIG_ENDIAN);
446 /* 10 Mb full-duplex rate support. */
447 proto_tree_add_item(port_cf_tree, hf_openflow_10mb_fd, tvb, offset, 4, ENC_BIG_ENDIAN);
448 /* 100 Mb half-duplex rate support. */
449 proto_tree_add_item(port_cf_tree, hf_openflow_100mb_hd, tvb, offset, 4, ENC_BIG_ENDIAN);
450 /* 100 Mb full-duplex rate support. */
451 proto_tree_add_item(port_cf_tree, hf_openflow_100mb_fd, tvb, offset, 4, ENC_BIG_ENDIAN);
452 /* 1 Gb half-duplex rate support. */
453 proto_tree_add_item(port_cf_tree, hf_openflow_1gb_hd, tvb, offset, 4, ENC_BIG_ENDIAN);
454 /* 1 Gb full-duplex rate support. */
455 proto_tree_add_item(port_cf_tree, hf_openflow_1gb_fd, tvb, offset, 4, ENC_BIG_ENDIAN);
456 /* 10 Gb full-duplex rate support. */
457 proto_tree_add_item(port_cf_tree, hf_openflow_10gb_fd, tvb, offset, 4, ENC_BIG_ENDIAN);
459 proto_tree_add_item(port_cf_tree, hf_openflow_copper, tvb, offset, 4, ENC_BIG_ENDIAN);
461 proto_tree_add_item(port_cf_tree, hf_openflow_fiber, tvb, offset, 4, ENC_BIG_ENDIAN);
462 /* Auto-negotiation. */
463 proto_tree_add_item(port_cf_tree, hf_openflow_autoneg, tvb, offset, 4, ENC_BIG_ENDIAN);
465 proto_tree_add_item(port_cf_tree, hf_openflow_pause, tvb, offset, 4, ENC_BIG_ENDIAN);
466 /* Asymmetric pause. */
467 proto_tree_add_item(port_cf_tree, hf_openflow_pause_asym, tvb, offset, 4, ENC_BIG_ENDIAN);
470 /* Features being advertised by the port. */
471 proto_tree_add_item(tree, hf_openflow_port_advertised, tvb, offset, 4, ENC_BIG_ENDIAN);
474 /* Features supported by the port. */
475 proto_tree_add_item(tree, hf_openflow_port_supported, tvb, offset, 4, ENC_BIG_ENDIAN);
477 /* Features advertised by peer. */
478 proto_tree_add_item(tree, hf_openflow_port_peer, tvb, offset, 4, ENC_BIG_ENDIAN);
488 struct ofp_switch_features {
489 struct ofp_header header;
490 uint64_t datapath_id; /* Datapath unique ID. The lower 48-bits are for
491 a MAC address, while the upper 16-bits are
492 implementer-defined. */
493 uint32_t n_buffers; /* Max packets buffered at once. */
494 uint8_t n_tables; /* Number of tables supported by datapath. */
495 uint8_t pad[3]; /* Align to 64-bits. */
497 uint32_t capabilities; /* Bitmap of support "ofp_capabilities". */
498 uint32_t actions; /* Bitmap of supported "ofp_action_type"s. */
500 struct ofp_phy_port ports[0]; /* Port definitions. The number of ports
501 is inferred from the length field in
506 dissect_openflow_features_reply_v1_0(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, guint16 length)
509 proto_tree *path_id_tree, *cap_tree, *act_tree;
511 guint16 length_remaining;
513 ti = proto_tree_add_item(tree, hf_openflow_datapath_id, tvb, offset, 8, ENC_BIG_ENDIAN);
514 path_id_tree = proto_item_add_subtree(ti, ett_openflow_path_id);
515 proto_tree_add_item(path_id_tree, hf_openflow_datapath_mac, tvb, offset, 6, ENC_NA);
517 proto_tree_add_item(path_id_tree, hf_openflow_datapath_impl, tvb, offset, 2, ENC_BIG_ENDIAN);
520 proto_tree_add_item(tree, hf_openflow_n_buffers, tvb, offset, 4, ENC_BIG_ENDIAN);
523 proto_tree_add_item(tree, hf_openflow_n_tables, tvb, offset, 1, ENC_BIG_ENDIAN);
526 ti = proto_tree_add_item(tree, hf_openflow_capabilities, tvb, offset, 4, ENC_BIG_ENDIAN);
527 cap_tree = proto_item_add_subtree(ti, ett_openflow_cap);
530 proto_tree_add_item(cap_tree, hf_openflow_cap_flow_stats, tvb, offset, 4, ENC_BIG_ENDIAN);
531 proto_tree_add_item(cap_tree, hf_openflow_table_stats, tvb, offset, 4, ENC_BIG_ENDIAN);
532 proto_tree_add_item(cap_tree, hf_openflow_port_stats, tvb, offset, 4, ENC_BIG_ENDIAN);
533 proto_tree_add_item(cap_tree, hf_openflow_group_stats, tvb, offset, 4, ENC_BIG_ENDIAN);
534 proto_tree_add_item(cap_tree, hf_openflow_ip_reasm, tvb, offset, 4, ENC_BIG_ENDIAN);
535 proto_tree_add_item(cap_tree, hf_openflow_queue_stats, tvb, offset, 4, ENC_BIG_ENDIAN);
536 proto_tree_add_item(cap_tree, hf_openflow_port_blocked, tvb, offset, 4, ENC_BIG_ENDIAN);
539 ti = proto_tree_add_item(tree, hf_openflow_actions, tvb, offset, 4, ENC_BIG_ENDIAN);
540 act_tree = proto_item_add_subtree(ti, ett_openflow_act);
542 proto_tree_add_item(act_tree, hf_openflow_output, tvb, offset, 4, ENC_BIG_ENDIAN);
543 proto_tree_add_item(act_tree, hf_openflow_set_vlan_vid, tvb, offset, 4, ENC_BIG_ENDIAN);
544 proto_tree_add_item(act_tree, hf_openflow_set_vlan_pcp, tvb, offset, 4, ENC_BIG_ENDIAN);
545 proto_tree_add_item(act_tree, hf_openflow_strip_vlan, tvb, offset, 4, ENC_BIG_ENDIAN);
546 proto_tree_add_item(act_tree, hf_openflow_set_dl_src, tvb, offset, 4, ENC_BIG_ENDIAN);
547 proto_tree_add_item(act_tree, hf_openflow_set_dl_dst, tvb, offset, 4, ENC_BIG_ENDIAN);
548 proto_tree_add_item(act_tree, hf_openflow_set_nw_src, tvb, offset, 4, ENC_BIG_ENDIAN);
549 proto_tree_add_item(act_tree, hf_openflow_set_nw_dst, tvb, offset, 4, ENC_BIG_ENDIAN);
550 proto_tree_add_item(act_tree, hf_openflow_set_nw_tos, tvb, offset, 4, ENC_BIG_ENDIAN);
551 proto_tree_add_item(act_tree, hf_openflow_set_tp_src, tvb, offset, 4, ENC_BIG_ENDIAN);
552 proto_tree_add_item(act_tree, hf_openflow_set_tp_dst, tvb, offset, 4, ENC_BIG_ENDIAN);
553 proto_tree_add_item(act_tree, hf_openflow_enqueue, tvb, offset, 4, ENC_BIG_ENDIAN);
556 length_remaining = length-32;
557 if(length_remaining > 0){
558 guint16 num_ports = length_remaining/48;
560 if ((length_remaining&0x003f) != 0){
563 for(i=0; i<num_ports ;i++){
564 proto_tree *port_tree;
566 ti = proto_tree_add_text(tree, tvb, offset, 48, "Port data %u",i+1);
567 port_tree = proto_item_add_subtree(ti, ett_openflow_port);
568 dissect_openflow_phy_port(tvb, pinfo, port_tree, offset);
577 dissect_openflow_switch_config(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, guint8 version _U_, guint16 length _U_)
580 /* ofp_config_flags */
581 proto_tree_add_item(tree, hf_openflow_config_flags, tvb, offset, 2, ENC_BIG_ENDIAN);
584 proto_tree_add_item(tree, hf_openflow_miss_send_len, tvb, offset, 2, ENC_BIG_ENDIAN);
589 #define OFPR_NO_MATCH 0 /* No matching flow (table-miss flow entry). */
590 #define OFPR_ACTION 1 /* Action explicitly output to controller. */
591 #define OFPR_INVALID_TTL 2 /* Packet has invalid TTL */
593 static const value_string openflow_reason_values[] = {
594 { OFPR_NO_MATCH, "No matching flow (table-miss flow entry)" },
595 { OFPR_ACTION, "Action explicitly output to controller" },
596 { OFPR_INVALID_TTL, "Packet has invalid TTL" },
601 dissect_openflow_pkt_in(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, guint8 version, guint16 length)
605 /* uint32_t buffer_id; ID assigned by datapath. */
606 proto_tree_add_item(tree, hf_openflow_buffer_id, tvb, offset, 4, ENC_BIG_ENDIAN);
608 /* uint16_t total_len; Full length of frame. */
609 proto_tree_add_item(tree, hf_openflow_total_len, tvb, offset, 2, ENC_BIG_ENDIAN);
611 if(version == OFP_VERSION_1_0){
612 /* uint16_t in_port; Port on which frame was received. */
613 proto_tree_add_item(tree, hf_openflow_in_port, tvb, offset, 2, ENC_BIG_ENDIAN);
616 /* uint8_t reason; Reason packet is being sent (one of OFPR_*) */
617 proto_tree_add_item(tree, hf_openflow_reason, tvb, offset, 1, ENC_BIG_ENDIAN);
619 if(version > OFP_VERSION_1_2){
620 /* uint8_t table_id; ID of the table that was looked up */
621 proto_tree_add_item(tree, hf_openflow_table_id, tvb, offset, 1, ENC_BIG_ENDIAN);
623 /* uint64_t cookie; Cookie of the flow entry that was looked up. */
624 proto_tree_add_item(tree, hf_openflow_cookie, tvb, offset, 8, ENC_BIG_ENDIAN);
627 * - Exactly 2 all-zero padding bytes, then
628 * - An Ethernet frame whose length is inferred from header.length.
629 * The padding bytes preceding the Ethernet frame ensure that the IP
630 * header (if any) following the Ethernet header is 32-bit aligned.
632 proto_tree_add_item(tree, hf_openflow_padd16, tvb, offset, 2, ENC_BIG_ENDIAN);
635 proto_tree_add_item(tree, hf_openflow_padd8, tvb, offset, 1, ENC_BIG_ENDIAN);
639 /*proto_tree_add_text(tree, tvb, offset, length-offset, "Offset=%u, remaining %u", offset, length-offset);*/
640 next_tvb = tvb_new_subset(tvb, offset, length-offset, length-offset);
641 call_dissector(eth_withoutfcs_handle, next_tvb, pinfo, tree);
646 dissect_openflow_pkt_out(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, guint8 version, guint16 length _U_)
651 /* uint32_t buffer_id; ID assigned by datapath. */
652 buffer_id = tvb_get_ntohl(tvb, offset);
653 proto_tree_add_item(tree, hf_openflow_buffer_id, tvb, offset, 4, ENC_BIG_ENDIAN);
656 /* uint32_t in_port; Packet's input port or OFPP_CONTROLLER. */
657 proto_tree_add_item(tree, hf_openflow_in_port, tvb, offset, 2, ENC_BIG_ENDIAN);
660 /* uint16_t actions_len; Size of action array in bytes. */
661 proto_tree_add_item(tree, hf_openflow_actions_len, tvb, offset, 2, ENC_BIG_ENDIAN);
664 if(version > OFP_VERSION_1_2){
665 /* uint8_t pad[6]; */
666 proto_tree_add_item(tree, hf_openflow_padd48, tvb, offset, 2, ENC_BIG_ENDIAN);
669 /* struct ofp_action_header actions[0]; Action list. */
670 offset = dissect_openflow_action_header(tvb, pinfo, tree, offset);
671 /* Packet data. The length is inferred
672 from the length field in the header.
673 (Only meaningful if buffer_id == -1.)
676 /* proto_tree_add_text(tree, tvb, offset, -1, "Packet data"); */
677 next_tvb = tvb_new_subset(tvb, offset, length-offset, length-offset);
678 call_dissector(eth_withoutfcs_handle, next_tvb, pinfo, tree);
682 #define OFPFC_ADD 0 /* New flow. */
683 #define OFPFC_MODIFY 1 /* Modify all matching flows. */
684 #define OFPFC_MODIFY_STRICT 2 /* Modify entry strictly matching wildcards */
685 #define OFPFC_DELETE 3 /* Delete all matching flows. */
686 #define OFPFC_DELETE_STRICT 4 /* Strictly match wildcards and priority. */
688 static const value_string openflow_command_values[] = {
689 { OFPFC_ADD, "New flow" },
690 { OFPFC_MODIFY, "Modify all matching flows" },
691 { OFPFC_MODIFY_STRICT, "Modify entry strictly matching wildcards" },
692 { OFPFC_DELETE, "Delete all matching flows" },
693 { OFPFC_DELETE_STRICT, "Strictly match wildcards and priority" },
698 dissect_openflow_flow_mod(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, guint8 version, guint16 length _U_)
701 /* struct ofp_match match; Fields to match */
702 if(version < OFP_VERSION_1_2){
703 offset = dissect_openflow_ofp_match_v_1_0(tvb, pinfo, tree, offset);
706 /* uint64_t cookie; Opaque controller-issued identifier. */
707 proto_tree_add_item(tree, hf_openflow_cookie, tvb, offset, 8, ENC_BIG_ENDIAN);
709 if(version > OFP_VERSION_1_2){
710 /* uint64_t cookie_mask; Mask used to restrict the cookie bits
711 * that must match when the command is
712 * OFPFC_MODIFY* or OFPFC_DELETE*. A value
713 * of 0 indicates no restriction.
715 proto_tree_add_item(tree, hf_openflow_cookie_mask, tvb, offset, 8, ENC_BIG_ENDIAN);
718 /* uint8_t table_id; ID of the table to put the flow in.
719 For OFPFC_DELETE_* commands, OFPTT_ALL can also be used to delete matching
720 flows from all tables.
722 proto_tree_add_item(tree, hf_openflow_table_id, tvb, offset, 1, ENC_BIG_ENDIAN);
725 if(version > OFP_VERSION_1_2){
726 /* uint8_t command; One of OFPFC_*. */
727 proto_tree_add_item(tree, hf_openflow_command, tvb, offset, 1, ENC_BIG_ENDIAN);
730 /* uint16_t command; One of OFPFC_*. */
731 proto_tree_add_item(tree, hf_openflow_command, tvb, offset, 2, ENC_BIG_ENDIAN);
734 /* uint16_t idle_timeout; Idle time before discarding (seconds). */
735 proto_tree_add_item(tree, hf_openflow_idle_timeout, tvb, offset, 2, ENC_BIG_ENDIAN);
737 /* uint16_t hard_timeout; Max time before discarding (seconds). */
738 proto_tree_add_item(tree, hf_openflow_hard_timeout, tvb, offset, 2, ENC_BIG_ENDIAN);
740 /* uint16_t priority; Priority level of flow entry. */
741 proto_tree_add_item(tree, hf_openflow_priority, tvb, offset, 2, ENC_BIG_ENDIAN);
743 /* uint32_t buffer_id; Buffered packet to apply to, or OFP_NO_BUFFER.
744 Not meaningful for OFPFC_DELETE*.
746 proto_tree_add_item(tree, hf_openflow_buffer_id, tvb, offset, 4, ENC_BIG_ENDIAN);
748 /* uint32_t out_port; For OFPFC_DELETE* commands, require
749 matching entries to include this as an output port. A value of OFPP_ANY
750 indicates no restriction.
752 if(version > OFP_VERSION_1_2){
753 proto_tree_add_item(tree, hf_openflow_out_port, tvb, offset, 4, ENC_BIG_ENDIAN);
756 proto_tree_add_item(tree, hf_openflow_out_port, tvb, offset, 2, ENC_BIG_ENDIAN);
760 if(version > OFP_VERSION_1_2){
761 /* uint32_t out_group; For OFPFC_DELETE* commands, require
762 matching entries to include this as an
763 output group. A value of OFPG_ANY
764 indicates no restriction.
766 proto_tree_add_item(tree, hf_openflow_out_group, tvb, offset, 4, ENC_BIG_ENDIAN);
769 /* uint16_t flags; One of OFPFF_*. */
770 proto_tree_add_item(tree, hf_openflow_flags, tvb, offset, 2, ENC_BIG_ENDIAN);
772 if(version > OFP_VERSION_1_2){
773 /* uint8_t pad[2]; */
774 proto_tree_add_item(tree, hf_openflow_padd16, tvb, offset, 2, ENC_BIG_ENDIAN);
779 if(version < OFP_VERSION_1_2){
780 /* The action length is inferred
781 from the length field in the
783 /*struct ofp_action_header actions[0]; */
785 /* struct ofp_match match; Fields to match. Variable size. */
791 dissect_openflow_v_1_0(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
794 proto_tree *openflow_tree;
796 guint8 type, version;
799 version = tvb_get_guint8(tvb, 0);
800 type = tvb_get_guint8(tvb, 1);
802 col_append_fstr(pinfo->cinfo, COL_INFO, "Type: %s",
803 val_to_str_const(type, openflow_1_0_type_values, "Unknown Messagetype"));
805 /* Stop the Ethernet frame from overwriting the columns */
806 if((type == OFPT_1_0_PACKET_IN) || (type == OFPT_1_0_PACKET_OUT)){
807 col_set_writable(pinfo->cinfo, FALSE);
810 /* Create display subtree for the protocol */
811 ti = proto_tree_add_item(tree, proto_openflow, tvb, 0, -1, ENC_NA);
812 openflow_tree = proto_item_add_subtree(ti, ett_openflow);
814 /* A.1 OpenFlow Header. */
816 proto_tree_add_item(openflow_tree, hf_openflow_version, tvb, offset, 1, ENC_BIG_ENDIAN);
819 /* One of the OFPT_ constants. */
820 proto_tree_add_item(openflow_tree, hf_openflow_1_0_type, tvb, offset, 1, ENC_BIG_ENDIAN);
823 /* Length including this ofp_header. */
824 length = tvb_get_ntohs(tvb, offset);
825 proto_tree_add_item(openflow_tree, hf_openflow_length, tvb, offset, 2, ENC_BIG_ENDIAN);
828 /* Transaction id associated with this packet. Replies use the same id as was in the request
829 * to facilitate pairing.
831 proto_tree_add_item(openflow_tree, hf_openflow_xid, tvb, offset, 4, ENC_BIG_ENDIAN);
835 case OFPT_1_0_HELLO: /* 0 */
837 * The OFPT_HELLO message has no body;
840 case OFPT_1_0_FEATURES_REQUEST: /* 5 */
842 * Upon TLS session establishment, the controller sends an OFPT_FEATURES_REQUEST
843 * message. This message does not contain a body beyond the OpenFlow header.
846 case OFPT_1_0_FEATURES_REPLY: /* 6 */
847 dissect_openflow_features_reply_v1_0(tvb, pinfo, openflow_tree, offset, length);
849 case OFPT_1_0_GET_CONFIG_REQUEST: /* 7 */
850 /* A.3.2 There is no body for OFPT_GET_CONFIG_REQUEST beyond the OpenFlow header. */
852 case OFPT_1_0_GET_CONFIG_REPLY: /* 8 */
854 case OFPT_1_0_SET_CONFIG: /* 9 */
855 dissect_openflow_switch_config(tvb, pinfo, openflow_tree, offset, version, length);
857 case OFPT_1_0_PACKET_IN: /* 10 */
858 dissect_openflow_pkt_in(tvb, pinfo, openflow_tree, offset, version, length);
860 case OFPT_1_0_PACKET_OUT: /* 13 */
861 dissect_openflow_pkt_out(tvb, pinfo, openflow_tree, offset, version, length);
863 case OFPT_1_0_FLOW_MOD: /* 14 */
864 dissect_openflow_flow_mod(tvb, pinfo, openflow_tree, offset, version, length);
868 proto_tree_add_text(tree, tvb, offset, -1, "Message data not dissected yet");
873 return tvb_length(tvb);
879 get_openflow_pdu_length(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
881 return tvb_get_ntohs(tvb, offset + 2);
886 dissect_openflow_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
891 version = tvb_get_guint8(tvb, 0);
892 /* Set the Protocol column to the constant string of openflow */
893 col_set_str(pinfo->cinfo, COL_PROTOCOL, "OpenFlow");
894 col_clear(pinfo->cinfo,COL_INFO);
897 case OFP_VERSION_1_0:
898 dissect_openflow_v_1_0(tvb, pinfo, tree);
900 case OFP_VERSION_1_3:
901 call_dissector(openflow_v4_handle, tvb, pinfo, tree);
904 proto_tree_add_item(tree, hf_openflow_version, tvb, offset, 1, ENC_BIG_ENDIAN);
905 proto_tree_add_text(tree, tvb, offset, -1, "Unsuported version not dissected");
911 #define OFP_HEADER_LEN 8
913 dissect_openflow(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
915 tcp_dissect_pdus(tvb, pinfo, tree, openflow_desegment, OFP_HEADER_LEN,
916 get_openflow_pdu_length, dissect_openflow_tcp_pdu);
917 return tvb_length(tvb);
921 * Register the protocol with Wireshark.
924 proto_register_openflow(void)
926 module_t *openflow_module;
928 static hf_register_info hf[] = {
929 { &hf_openflow_version,
930 { "Version", "openflow.version",
931 FT_UINT8, BASE_HEX, VALS(openflow_version_values), 0x7f,
934 { &hf_openflow_1_0_type,
935 { "Type", "openflow_1_0.type",
936 FT_UINT8, BASE_DEC, VALS(openflow_1_0_type_values), 0x0,
940 { "Transaction ID", "openflow.xid",
941 FT_UINT32, BASE_DEC, NULL, 0x0,
944 { &hf_openflow_length,
945 { "Length", "openflow.length",
946 FT_UINT16, BASE_DEC, NULL, 0x0,
949 { &hf_openflow_datapath_id,
950 { "Datapath unique ID", "openflow.datapath_id",
951 FT_UINT64, BASE_HEX, NULL, 0x0,
954 { &hf_openflow_datapath_mac,
955 { "MAC addr", "openflow.datapath_mac",
956 FT_ETHER, BASE_NONE, NULL, 0x0,
959 { &hf_openflow_datapath_impl,
960 { "Implementers part", "openflow.datapath_imp",
961 FT_UINT16, BASE_HEX, NULL, 0x0,
964 { &hf_openflow_n_buffers,
965 { "n_buffers", "openflow.n_buffers",
966 FT_UINT32, BASE_DEC, NULL, 0x0,
969 { &hf_openflow_n_tables,
970 { "n_tables", "openflow.n_tables",
971 FT_UINT8, BASE_DEC, NULL, 0x0,
974 { &hf_openflow_auxiliary_id,
975 { "auxiliary_id", "openflow.auxiliary_id",
976 FT_UINT8, BASE_DEC, NULL, 0x0,
980 { "Padding", "openflow.pad3",
981 FT_UINT24, BASE_DEC, NULL, 0x0,
984 { &hf_openflow_capabilities,
985 { "capabilities", "openflow.capabilities",
986 FT_UINT32, BASE_HEX, NULL, 0x0,
989 { &hf_openflow_actions,
990 { "actions", "openflow.actions",
991 FT_UINT32, BASE_HEX, NULL, 0x0,
994 { &hf_openflow_reserved32,
995 { "Reserved", "openflow.reserved32",
996 FT_UINT32, BASE_DEC, NULL, 0x0,
999 { &hf_openflow_cap_flow_stats,
1000 { "Flow statistics", "openflow.flow_stats",
1001 FT_BOOLEAN, 32, NULL, OFPC_FLOW_STATS,
1004 { &hf_openflow_table_stats,
1005 { "Table statistics", "openflow.table_stats",
1006 FT_BOOLEAN, 32, NULL, OFPC_TABLE_STATS,
1009 { &hf_openflow_port_stats,
1010 { "Port statistics", "openflow.port_stats",
1011 FT_BOOLEAN, 32, NULL, OFPC_PORT_STATS,
1014 { &hf_openflow_group_stats,
1015 { "Group statistics", "openflow.group_stats",
1016 FT_BOOLEAN, 32, NULL, OFPC_GROUP_STATS,
1019 { &hf_openflow_ip_reasm,
1020 { "Can reassemble IP fragments", "openflow.ip_reasm",
1021 FT_BOOLEAN, 32, NULL, OFPC_IP_REASM,
1024 { &hf_openflow_queue_stats,
1025 { "Queue statistics", "openflow.queue_stats",
1026 FT_BOOLEAN, 32, NULL, OFPC_QUEUE_STATS,
1029 { &hf_openflow_port_blocked,
1030 { "Switch will block looping ports", "openflow.port_blocked",
1031 FT_BOOLEAN, 32, NULL, OFPC_PORT_BLOCKED,
1034 { &hf_openflow_output,
1035 { "Output to switch port", "openflow.output",
1036 FT_BOOLEAN, 32, NULL, OFPAT_OUTPUT_MASK,
1039 { &hf_openflow_set_vlan_vid,
1040 { "Set the 802.1q VLAN id", "openflow.set_vlan_vid",
1041 FT_BOOLEAN, 32, NULL, OFPAT_SET_VLAN_VID_MASK,
1044 { &hf_openflow_set_vlan_pcp,
1045 { "Set the 802.1q priority", "openflow.set_vlan_pcp",
1046 FT_BOOLEAN, 32, NULL, OFPAT_SET_VLAN_PCP_MASK,
1049 { &hf_openflow_strip_vlan,
1050 { "Strip the 802.1q header", "openflow.strip_vlan",
1051 FT_BOOLEAN, 32, NULL, OFPAT_STRIP_VLAN_MASK,
1054 { &hf_openflow_set_dl_src,
1055 { "Ethernet source address", "openflow.set_dl_src",
1056 FT_BOOLEAN, 32, NULL, OFPAT_SET_DL_SRC_MASK,
1059 { &hf_openflow_set_dl_dst,
1060 { "Ethernet destination address", "openflow.set_dl_ds",
1061 FT_BOOLEAN, 32, NULL, OFPAT_SET_DL_DST_MASK,
1064 { &hf_openflow_set_nw_src,
1065 { "IP source address", "openflow.set_nw_src",
1066 FT_BOOLEAN, 32, NULL, OFPAT_SET_NW_SRC_MASK,
1069 { &hf_openflow_set_nw_dst,
1070 { "IP destination address", "openflow.set_nw_ds",
1071 FT_BOOLEAN, 32, NULL, OFPAT_SET_NW_DST_MASK,
1074 { &hf_openflow_set_nw_tos,
1075 { "IP ToS (DSCP field, 6 bits)", "openflow.set_nw_tos",
1076 FT_BOOLEAN, 32, NULL, OFPAT_SET_NW_TOS_MASK,
1079 { &hf_openflow_set_tp_src,
1080 { "TCP/UDP source port", "openflow.set_tp_src",
1081 FT_BOOLEAN, 32, NULL, OFPAT_SET_TP_SRC_MASK,
1084 { &hf_openflow_set_tp_dst,
1085 { "TCP/UDP destination port", "openflow.set_tp_dst",
1086 FT_BOOLEAN, 32, NULL, OFPAT_SET_TP_DST_MASK,
1089 { &hf_openflow_enqueue,
1090 { "Output to queue", "openflow.enqueue",
1091 FT_BOOLEAN, 32, NULL, OFPAT_ENQUEUE_MASK,
1094 { &hf_openflow_port_no,
1095 { "Port number", "openflow.port_no",
1096 FT_UINT16, BASE_DEC, NULL, 0x0,
1099 { &hf_openflow_hw_addr,
1100 { "HW Address", "openflow.hw_add",
1101 FT_ETHER, BASE_NONE, NULL, 0x0,
1104 { &hf_openflow_port_name,
1105 { "Name", "openflow.hw_add",
1106 FT_STRING, BASE_NONE, NULL, 0x0,
1109 { &hf_openflow_port_config,
1110 { "Config flags", "openflow.port_config",
1111 FT_UINT32, BASE_HEX, NULL, 0x0,
1114 { &hf_openflow_port_state,
1115 { "State flags", "openflow.port_state",
1116 FT_UINT32, BASE_HEX, NULL, 0x0,
1119 { &hf_openflow_port_curr,
1120 { "Current features", "openflow.port_curr",
1121 FT_UINT32, BASE_HEX, NULL, 0x0,
1124 { &hf_openflow_port_advertised,
1125 { "Advertised features", "openflow.port_advertised",
1126 FT_UINT32, BASE_HEX, NULL, 0x0,
1129 { &hf_openflow_port_supported,
1130 { "Features supported", "openflow.port_supported",
1131 FT_UINT32, BASE_HEX, NULL, 0x0,
1134 { &hf_openflow_port_peer,
1135 { "Features advertised by peer", "openflow.port_peer",
1136 FT_UINT32, BASE_HEX, NULL, 0x0,
1139 { &hf_openflow_port_down,
1140 { "Port is administratively down", "openflow.port_down",
1141 FT_BOOLEAN, 32, NULL, OFPPC_PORT_DOWN,
1144 { &hf_openflow_no_stp,
1145 { "Disable 802.1D spanning tree on port", "openflow.no_stp",
1146 FT_BOOLEAN, 32, NULL, OFPPC_NO_STP,
1149 { &hf_openflow_no_recv,
1150 { "Drop all packets except 802.1D spanning tree packets", "openflow.no_recv",
1151 FT_BOOLEAN, 32, NULL, OFPPC_NO_RECV,
1154 { &hf_openflow_no_recv_stp,
1155 { "Drop received 802.1D STP packets", "openflow.no_recv",
1156 FT_BOOLEAN, 32, NULL, OFPPC_NO_RECV_STP,
1159 { &hf_openflow_no_flood,
1160 { "Do not include this port when flooding", "openflow.no_flood",
1161 FT_BOOLEAN, 32, NULL, OFPPC_NO_FLOOD,
1164 { &hf_openflow_no_fwd,
1165 { "Drop packets forwarded to port", "openflow.no_fwd",
1166 FT_BOOLEAN, 32, NULL, OFPPC_NO_FWD,
1169 { &hf_openflow_no_packet_in,
1170 { "Do not send packet-in msgs for port", "openflow.no_packet_in",
1171 FT_BOOLEAN, 32, NULL, OFPPC_NO_PACKET_IN,
1174 { &hf_openflow_link_down,
1175 { "No physical link present", "openflow.link_down",
1176 FT_BOOLEAN, 32, NULL, OFPPS_LINK_DOWN,
1179 { &hf_openflow_10mb_hd,
1180 { "10 Mb half-duplex rate support", "openflow.10mb_hd",
1181 FT_BOOLEAN, 32, NULL, OFPPF_10MB_HD,
1184 { &hf_openflow_10mb_fd,
1185 { "10 Mb full-duplex rate support", "openflow.10mb_fd",
1186 FT_BOOLEAN, 32, NULL, OFPPF_10MB_FD,
1189 { &hf_openflow_100mb_hd,
1190 { "100 Mb half-duplex rate support", "openflow.100mb_hd",
1191 FT_BOOLEAN, 32, NULL, OFPPF_100MB_HD,
1194 { &hf_openflow_100mb_fd,
1195 { "100 Mb full-duplex rate support", "openflow.100mb_0fd",
1196 FT_BOOLEAN, 32, NULL, OFPPF_100MB_FD,
1199 { &hf_openflow_1gb_hd,
1200 { "1 Gb half-duplex rate support", "openflow.1gb_hd",
1201 FT_BOOLEAN, 32, NULL, OFPPF_1GB_HD,
1204 { &hf_openflow_1gb_fd,
1205 { "1 Gb full-duplex rate support", "openflow.1gb_fd",
1206 FT_BOOLEAN, 32, NULL, OFPPF_1GB_FD,
1209 { &hf_openflow_10gb_fd,
1210 { "10 Gb full-duplex rate support", "openflow.10gb_fd",
1211 FT_BOOLEAN, 32, NULL, OFPPF_10GB_FD,
1214 { &hf_openflow_copper,
1215 { "Copper medium", "openflow.copper",
1216 FT_BOOLEAN, 32, NULL, OFPPF_COPPER,
1219 { &hf_openflow_fiber,
1220 { "Fiber medium", "openflow.fiber",
1221 FT_BOOLEAN, 32, NULL, OFPPF_FIBER,
1224 { &hf_openflow_autoneg,
1225 { "Auto-negotiation", "openflow.autoneg",
1226 FT_BOOLEAN, 32, NULL, OFPPF_AUTONEG,
1229 { &hf_openflow_pause,
1230 { "Pause", "openflow.pause",
1231 FT_BOOLEAN, 32, NULL, OFPPF_PAUSE,
1234 { &hf_openflow_pause_asym,
1235 { "Asymmetric pause", "openflow.pause_asym",
1236 FT_BOOLEAN, 32, NULL, OFPPF_PAUSE_ASYM,
1239 { &hf_openflow_config_flags,
1240 { "Config flags", "openflow.config_flags",
1241 FT_UINT16, BASE_HEX, NULL, 0x0,
1244 { &hf_openflow_miss_send_len,
1245 { "Max bytes of packet", "openflow.miss_send_len",
1246 FT_UINT16, BASE_HEX, NULL, 0x0,
1249 { &hf_openflow_buffer_id,
1250 { "Buffser Id", "openflow.buffer_id",
1251 FT_UINT32, BASE_HEX, NULL, 0x0,
1254 { &hf_openflow_total_len,
1255 { "Total length", "openflow.total_len",
1256 FT_UINT16, BASE_DEC, NULL, 0x0,
1259 { &hf_openflow_in_port,
1260 { "In port", "openflow.in_port",
1261 FT_UINT16, BASE_DEC, NULL, 0x0,
1264 { &hf_openflow_reason,
1265 { "Reason", "openflow.reason",
1266 FT_UINT8, BASE_DEC, VALS(openflow_reason_values), 0x0,
1269 { &hf_openflow_table_id,
1270 { "Table Id", "openflow.table_id",
1271 FT_UINT8, BASE_DEC, NULL, 0x0,
1274 { &hf_openflow_cookie,
1275 { "Cookie", "openflow.cookie",
1276 FT_UINT64, BASE_HEX, NULL, 0x0,
1279 { &hf_openflow_cookie_mask,
1280 { "Cookie mask", "openflow.cookie",
1281 FT_UINT64, BASE_HEX, NULL, 0x0,
1284 { &hf_openflow_padd8,
1285 { "Padding", "openflow.padding8",
1286 FT_UINT8, BASE_DEC, NULL, 0x0,
1289 { &hf_openflow_padd16,
1290 { "Padding", "openflow.padding16",
1291 FT_UINT16, BASE_DEC, NULL, 0x0,
1294 { &hf_openflow_padd48,
1295 { "Padding", "openflow.padding48",
1296 FT_UINT64, BASE_DEC, NULL, 0x0,
1299 { &hf_openflow_actions_len,
1300 { "Actions length", "openflow.actions_len",
1301 FT_UINT16, BASE_DEC, NULL, 0x0,
1304 { &hf_openflow_action_type,
1305 { "Actions type", "openflow.action_typ",
1306 FT_UINT16, BASE_DEC, VALS(openflow_action_values), 0x0,
1309 { &hf_openflow_action_len,
1310 { "Action length", "openflow.action_len",
1311 FT_UINT16, BASE_DEC, NULL, 0x0,
1314 { &hf_openflow_output_port,
1315 { "Output port", "openflow.output_port",
1316 FT_UINT16, BASE_DEC, NULL, 0x0,
1319 { &hf_openflow_max_len,
1320 { "Max length", "openflow.max_len",
1321 FT_UINT16, BASE_DEC, NULL, 0x0,
1324 { &hf_openflow_wildcards,
1325 { "Wildcards", "openflow.wildcards",
1326 FT_UINT32, BASE_DEC, NULL, 0x0,
1329 { &hf_openflow_command,
1330 { "Command", "openflow.command",
1331 FT_UINT16, BASE_DEC, VALS(openflow_command_values), 0x0,
1334 { &hf_openflow_eth_src,
1335 { "Ethernet source address", "openflow.eth_src",
1336 FT_ETHER, BASE_NONE, NULL, 0x0,
1339 { &hf_openflow_eth_dst,
1340 { "Ethernet destination address", "openflow.eth_src",
1341 FT_ETHER, BASE_NONE, NULL, 0x0,
1344 { &hf_openflow_dl_vlan,
1345 { "Input VLAN id", "openflow.dl_vlan",
1346 FT_UINT16, BASE_DEC, NULL, 0x0,
1349 { &hf_openflow_dl_vlan_pcp,
1350 { "Input VLAN priority", "openflow.dl_vlan_pcp",
1351 FT_UINT8, BASE_DEC, NULL, 0x0,
1354 { &hf_openflow_idle_timeout,
1355 { "Idle time-out", "openflow.idle_timeout",
1356 FT_UINT16, BASE_DEC, NULL, 0x0,
1359 { &hf_openflow_hard_timeout,
1360 { "hard time-out", "openflow.hard_timeout",
1361 FT_UINT16, BASE_DEC, NULL, 0x0,
1364 { &hf_openflow_priority,
1365 { "Priority", "openflow.priority",
1366 FT_UINT16, BASE_DEC, NULL, 0x0,
1369 { &hf_openflow_out_port,
1370 { "Out port", "openflow.out_port",
1371 FT_UINT32, BASE_DEC, NULL, 0x0,
1374 { &hf_openflow_out_group,
1375 { "Out group", "openflow.out_group",
1376 FT_UINT32, BASE_DEC, NULL, 0x0,
1379 { &hf_openflow_flags,
1380 { "Flags", "openflow.flags",
1381 FT_UINT16, BASE_DEC, NULL, 0x0,
1386 static gint *ett[] = {
1388 &ett_openflow_path_id,
1392 &ett_openflow_port_cnf,
1393 &ett_openflow_port_state,
1394 &ett_openflow_port_cf
1397 /* Register the protocol name and description */
1398 proto_openflow = proto_register_protocol("OpenFlow",
1399 "openflow", "openflow");
1401 new_register_dissector("openflow", dissect_openflow, proto_openflow);
1403 /* Required function calls to register the header fields and subtrees */
1404 proto_register_field_array(proto_openflow, hf, array_length(hf));
1405 proto_register_subtree_array(ett, array_length(ett));
1407 openflow_module = prefs_register_protocol(proto_openflow, proto_reg_handoff_openflow);
1409 /* Register port preference */
1410 prefs_register_uint_preference(openflow_module, "tcp.port", "openflow TCP Port",
1411 " openflow TCP port if other than the default",
1412 10, &g_openflow_port);
1414 /* Register desegment preference */
1415 prefs_register_bool_preference(openflow_module, "desegment",
1416 "Reassemble OpenFlow messages spanning multiple TCP segments",
1417 "Whether the OpenFlow dissector should reassemble messages spanning multiple TCP segments."
1418 " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
1419 &openflow_desegment);
1423 proto_reg_handoff_openflow(void)
1425 static gboolean initialized = FALSE;
1426 static dissector_handle_t openflow_handle;
1427 static int currentPort;
1430 openflow_handle = new_create_dissector_handle(dissect_openflow, proto_openflow);
1434 dissector_delete_uint("tcp.port", currentPort, openflow_handle);
1437 currentPort = g_openflow_port;
1439 dissector_add_uint("tcp.port", currentPort, openflow_handle);
1440 eth_withoutfcs_handle = find_dissector("eth_withoutfcs");
1441 openflow_v4_handle = find_dissector("openflow_v4");
1447 * Editor modelines - http://www.wireshark.org/tools/modelines.html
1452 * indent-tabs-mode: nil
1455 * vi: set shiftwidth=4 tabstop=8 expandtab:
1456 * :indentSize=4:tabSize=8:noTabs=true: