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