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