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