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