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>
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
12 * Ref https://www.opennetworking.org/sdn-resources/onf-specifications/openflow
17 #include <epan/packet.h>
18 #include <epan/expert.h>
20 void proto_register_openflow_v1(void);
21 void proto_reg_handoff_openflow_v1(void);
23 static dissector_handle_t eth_withoutfcs_handle
;
25 /* Initialize the protocol and registered fields */
26 static int proto_openflow_v1
;
27 static int hf_openflow_version
;
28 static int hf_openflow_1_0_type
;
29 static int hf_openflow_length
;
30 static int hf_openflow_xid
;
32 static int hf_openflow_datapath_id
;
33 static int hf_openflow_datapath_mac
;
34 static int hf_openflow_datapath_impl
;
35 static int hf_openflow_n_buffers
;
36 static int hf_openflow_n_tables
;
37 /* static int hf_openflow_auxiliary_id; */
38 static int hf_openflow_capabilities
;
39 static int hf_openflow_actions
;
40 /* static int hf_openflow_reserved32; */
41 static int hf_openflow_cap_flow_stats
;
42 static int hf_openflow_table_stats
;
43 static int hf_openflow_port_stats
;
44 static int hf_openflow_group_stats
;
45 static int hf_openflow_ip_reasm
;
46 static int hf_openflow_queue_stats
;
47 static int hf_openflow_port_blocked
;
49 static int hf_openflow_output
; /* Output to switch port. */
50 static int hf_openflow_set_vlan_vid
; /* Set the 802.1q VLAN id. */
51 static int hf_openflow_set_vlan_pcp
; /* Set the 802.1q priority. */
52 static int hf_openflow_strip_vlan
; /* Strip the 802.1q header. */
53 static int hf_openflow_set_dl_src
; /* Ethernet source address. */
54 static int hf_openflow_set_dl_dst
; /* Ethernet destination address. */
55 static int hf_openflow_set_nw_src
; /* IP source address. */
56 static int hf_openflow_set_nw_dst
; /* IP destination address. */
57 static int hf_openflow_set_nw_tos
; /* IP ToS (DSCP field, 6 bits). */
58 static int hf_openflow_set_tp_src
; /* TCP/UDP source port. */
59 static int hf_openflow_set_tp_dst
; /* TCP/UDP destination port. */
60 static int hf_openflow_enqueue
; /* Output to queue. */
62 static int hf_openflow_port_no
;
63 static int hf_openflow_hw_addr
;
64 static int hf_openflow_port_name
;
67 static int hf_openflow_port_config
;
68 static int hf_openflow_port_state
;
69 static int hf_openflow_port_curr
;
70 static int hf_openflow_port_advertised
;
71 static int hf_openflow_port_supported
;
72 static int hf_openflow_port_peer
;
74 static int hf_openflow_port_down
; /* Port is administratively down. */
75 static int hf_openflow_no_stp
; /* Disable 802.1D spanning tree on port. */
76 static int hf_openflow_no_recv
; /* Drop all packets except 802.1D spanning tree packets. */
77 static int hf_openflow_no_recv_stp
; /* Drop received 802.1D STP packets. */
78 static int hf_openflow_no_flood
; /* Do not include this port when flooding. */
79 static int hf_openflow_no_fwd
; /* Drop packets forwarded to port. */
80 static int hf_openflow_no_packet_in
; /* Do not send packet-in msgs for port. */
82 static int hf_openflow_link_down
; /* No physical link present. */
84 static int hf_openflow_10mb_hd
; /* 10 Mb half-duplex rate support. */
85 static int hf_openflow_10mb_fd
; /* 10 Mb full-duplex rate support. */
86 static int hf_openflow_100mb_hd
; /* 100 Mb half-duplex rate support. */
87 static int hf_openflow_100mb_fd
; /* 100 Mb full-duplex rate support. */
88 static int hf_openflow_1gb_hd
; /* 1 Gb half-duplex rate support. */
89 static int hf_openflow_1gb_fd
; /* 1 Gb full-duplex rate support. */
90 static int hf_openflow_10gb_fd
; /* 10 Gb full-duplex rate support. */
91 static int hf_openflow_copper
; /* Copper medium. */
92 static int hf_openflow_fiber
; /* Fiber medium. */
93 static int hf_openflow_autoneg
; /* Auto-negotiation. */
94 static int hf_openflow_pause
; /* Pause. */
95 static int hf_openflow_pause_asym
; /* Asymmetric pause. */
97 static int hf_openflow_config_flags
;
98 static int hf_openflow_miss_send_len
;
100 static int hf_openflow_buffer_id
;
101 static int hf_openflow_total_len
;
102 static int hf_openflow_in_port
;
103 static int hf_openflow_reason
;
104 static int hf_openflow_pkt_in_pad
;
105 static int hf_openflow_flow_removed_cookie
;
106 static int hf_openflow_flow_removed_priority
;
107 static int hf_openflow_flow_removed_reason
;
108 static int hf_openflow_flow_removed_pad1
;
109 static int hf_openflow_flow_removed_duration_sec
;
110 static int hf_openflow_flow_removed_duration_nsec
;
111 static int hf_openflow_flow_removed_idle_timeout
;
112 static int hf_openflow_flow_removed_pad2
;
113 static int hf_openflow_flow_removed_packet_count
;
114 static int hf_openflow_flow_removed_byte_count
;
115 static int hf_openflow_table_id
;
116 static int hf_openflow_cookie
;
117 /* static int hf_openflow_cookie_mask; */
118 static int hf_openflow_features_reply_pad
;
119 static int hf_openflow_actions_len
;
120 static int hf_openflow_action_type
;
121 static int hf_openflow_action_len
;
122 static int hf_openflow_output_port
;
123 static int hf_openflow_max_len
;
124 static int hf_openflow_wildcards
;
125 static int hf_openflow_command
;
126 static int hf_openflow_eth_src
;
127 static int hf_openflow_eth_dst
;
128 static int hf_openflow_dl_vlan
;
129 static int hf_openflow_dl_vlan_pcp
;
130 static int hf_openflow_ofp_match_pad
;
131 static int hf_openflow_match_dl_type
;
132 static int hf_openflow_ofp_match_tos
;
133 static int hf_openflow_ofp_match_nw_proto
;
134 static int hf_openflow_ofp_source_addr
;
135 static int hf_openflow_ofp_dest_addr
;
136 static int hf_openflow_ofp_source_port
;
137 static int hf_openflow_ofp_dest_port
;
138 static int hf_openflow_idle_timeout
;
139 static int hf_openflow_hard_timeout
;
140 static int hf_openflow_priority
;
141 static int hf_openflow_out_port
;
142 /* static int hf_openflow_out_group; */
143 static int hf_openflow_flags
;
144 static int hf_openflow_v1_stats_type
;
145 static int hf_openflow_v1_flow_stats_request_pad
;
147 /* Initialize the subtree pointers */
148 static int ett_openflow
;
149 static int ett_openflow_path_id
;
150 static int ett_openflow_cap
;
151 static int ett_openflow_act
;
152 static int ett_openflow_port
;
153 static int ett_openflow_port_cnf
;
154 static int ett_openflow_port_state
;
155 static int ett_openflow_port_cf
;
157 /* static expert_field ei_openflow_undecoded_data; */
158 static expert_field ei_openflow_action_type
;
159 static expert_field ei_openflow_1_0_type
;
161 static const value_string openflow_version_values
[] = {
167 /* Immutable messages. */
168 #define OFPT_1_0_HELLO 0 /* Symmetric message */
169 #define OFPT_1_0_ERROR 1 /* Symmetric message */
170 #define OFPT_1_0_ECHO_REQUEST 2 /* Symmetric message */
171 #define OFPT_1_0_ECHO_REPLY 3 /* Symmetric message */
172 #define OFPT_1_0_VENDOR 4 /* Symmetric message */
173 /* Switch configuration messages. */
174 #define OFPT_1_0_FEATURES_REQUEST 5 /* Controller/switch message */
175 #define OFPT_1_0_FEATURES_REPLY 6 /* Controller/switch message */
176 #define OFPT_1_0_GET_CONFIG_REQUEST 7 /* Controller/switch message */
177 #define OFPT_1_0_GET_CONFIG_REPLY 8 /* Controller/switch message */
178 #define OFPT_1_0_SET_CONFIG 9 /* Controller/switch message */
179 /* Asynchronous messages. */
180 #define OFPT_1_0_PACKET_IN 10 /* Async message */
181 #define OFPT_1_0_FLOW_REMOVED 11 /* Async message */
182 #define OFPT_1_0_PORT_STATUS 12 /* Async message */
183 /* Controller command messages. */
184 #define OFPT_1_0_PACKET_OUT 13 /* Controller/switch message */
185 #define OFPT_1_0_FLOW_MOD 14 /* Controller/switch message */
186 #define OFPT_1_0_PORT_MOD 15 /* Controller/switch message */
187 /* Statistics messages. */
188 #define OFPT_1_0_STATS_REQUEST 16 /* Controller/switch message */
189 #define OFPT_1_0_STATS_REPLY 17 /* Controller/switch message */
190 /* Barrier messages. */
191 #define OFPT_1_0_BARRIER_REQUEST 18 /* Controller/switch message */
192 #define OFPT_1_0_BARRIER_REPLY 19 /* Controller/switch message */
193 /* Queue Configuration messages. */
194 #define OFPT_1_0_QUEUE_GET_CONFIG_REQUEST 20 /* Controller/switch message */
195 #define OFPT_1_0_QUEUE_GET_CONFIG_REPLY 21 /* Controller/switch message */
198 static const value_string openflow_1_0_type_values
[] = {
199 /* Immutable messages. */
200 { 0, "OFPT_HELLO" }, /* Symmetric message */
201 { 1, "OFPT_ERROR" }, /* Symmetric message */
202 { 2, "OFPT_ECHO_REQUEST" }, /* Symmetric message */
203 { 3, "OFPT_ECHO_REPLY" }, /* Symmetric message */
204 { 4, "OFPT_VENDOR" }, /* Symmetric message */
205 /* Switch configuration messages. */
206 { 5, "OFPT_FEATURES_REQUEST" }, /* Controller/switch message */
207 { 6, "OFPT_FEATURES_REPLY" }, /* Controller/switch message */
208 { 7, "OFPT_GET_CONFIG_REQUEST" }, /* Controller/switch message */
209 { 8, "OFPT_GET_CONFIG_REPLY" }, /* Controller/switch message */
210 { 9, "OFPT_SET_CONFIG" }, /* Controller/switch message */
211 /* Asynchronous messages. */
212 { 10, "OFPT_PACKET_IN" }, /* Async message */
213 { 11, "OFPT_FLOW_REMOVED" }, /* Async message */
214 { 12, "OFPT_PORT_STATUS" }, /* Async message */
215 /* Controller command messages. */
216 { 13, "OFPT_PACKET_OUT" }, /* Controller/switch message */
217 { 14, "OFPT_FLOW_MOD" }, /* Controller/switch message */
218 { 15, "OFPT_PORT_MOD" }, /* Controller/switch message */
219 /* Statistics messages. */
220 { 16, "OFPT_STATS_REQUEST" }, /* Controller/switch message */
221 { 17, "OFPT_STATS_REPLY" }, /* Controller/switch message */
222 /* Barrier messages. */
223 { 18, "OFPT_BARRIER_REQUEST" }, /* Controller/switch message */
224 { 19, "OFPT_BARRIER_REPLY" }, /* Controller/switch message */
225 /* Queue Configuration messages. */
226 { 20, "OFPT_QUEUE_GET_CONFIG_REQUEST" }, /* Controller/switch message */
227 { 21, "OFPT_QUEUE_GET_CONFIG_REPLY" }, /* Controller/switch message */
230 static value_string_ext openflow_1_0_type_values_ext
= VALUE_STRING_EXT_INIT(openflow_1_0_type_values
);
232 #define OFPC_FLOW_STATS 1<<0 /* Flow statistics. */
233 #define OFPC_TABLE_STATS 1<<1 /* Table statistics. */
234 #define OFPC_PORT_STATS 1<<2 /* Port statistics. */
235 #define OFPC_GROUP_STATS 1<<3 /* Group statistics. */
236 #define OFPC_IP_REASM 1<<5 /* Can reassemble IP fragments. */
237 #define OFPC_QUEUE_STATS 1<<6 /* Queue statistics. */
238 #define OFPC_PORT_BLOCKED 1<<8 /* Switch will block looping ports. */
240 #define OFPAT_OUTPUT_MASK 1<<0 /* Output to switch port. */
241 #define OFPAT_SET_VLAN_VID_MASK 1<<1 /* Set the 802.1q VLAN id. */
242 #define OFPAT_SET_VLAN_PCP_MASK 1<<2 /* Set the 802.1q priority. */
243 #define OFPAT_STRIP_VLAN_MASK 1<<3 /* Strip the 802.1q header. */
244 #define OFPAT_SET_DL_SRC_MASK 1<<4 /* Ethernet source address. */
245 #define OFPAT_SET_DL_DST_MASK 1<<5 /* Ethernet destination address. */
246 #define OFPAT_SET_NW_SRC_MASK 1<<6 /* IP source address. */
247 #define OFPAT_SET_NW_DST_MASK 1<<7 /* IP destination address. */
248 #define OFPAT_SET_NW_TOS_MASK 1<<8 /* IP ToS (DSCP field, 6 bits). */
249 #define OFPAT_SET_TP_SRC_MASK 1<<9 /* TCP/UDP source port. */
250 #define OFPAT_SET_TP_DST_MASK 1<<10 /* TCP/UDP destination port. */
251 #define OFPAT_ENQUEUE_MASK 1<<11 /* Output to queue. */
253 #define OFPPC_PORT_DOWN 1<<0 /* Port is administratively down. */
254 #define OFPPC_NO_STP 1<<1 /* Disable 802.1D spanning tree on port. */
255 #define OFPPC_NO_RECV 1<<2 /* Drop all packets except 802.1D spanning tree packets. */
256 #define OFPPC_NO_RECV_STP 1<<3 /* Drop received 802.1D STP packets. */
257 #define OFPPC_NO_FLOOD 1<<4 /* Do not include this port when flooding. */
258 #define OFPPC_NO_FWD 1<<5 /* Drop packets forwarded to port. */
259 #define OFPPC_NO_PACKET_IN 1<<6 /* Do not send packet-in msgs for port. */
261 #define OFP_MAX_PORT_NAME_LEN 16
263 #define OFPPS_LINK_DOWN 1<<0 /* No physical link present. */
264 #define OFPPS_STP_LISTEN 0<<8 /* Not learning or relaying frames. */
265 #define OFPPS_STP_LEARN 1<<8 /* Learning but not relaying frames. */
266 #define OFPPS_STP_FORWARD 2<<8 /* Learning and relaying frames. */
267 #define OFPPS_STP_BLOCK 3<<8 /* Not part of spanning tree. */
268 #define OFPPS_STP_MASK 3<<8 /* Bit mask for OFPPS_STP_* values. */
271 #define OFPPF_10MB_HD 1<<0 /* 10 Mb half-duplex rate support. */
272 #define OFPPF_10MB_FD 1<<1 /* 10 Mb full-duplex rate support. */
273 #define OFPPF_100MB_HD 1<<2 /* 100 Mb half-duplex rate support. */
274 #define OFPPF_100MB_FD 1<<3 /* 100 Mb full-duplex rate support. */
275 #define OFPPF_1GB_HD 1<<4 /* 1 Gb half-duplex rate support. */
276 #define OFPPF_1GB_FD 1<<5 /* 1 Gb full-duplex rate support. */
277 #define OFPPF_10GB_FD 1<<6 /* 10 Gb full-duplex rate support. */
278 #define OFPPF_COPPER 1<<7 /* Copper medium. */
279 #define OFPPF_FIBER 1<<8 /* Fiber medium. */
280 #define OFPPF_AUTONEG 1<<9 /* Auto-negotiation. */
281 #define OFPPF_PAUSE 1<<10 /* Pause. */
282 #define OFPPF_PAUSE_ASYM 1<<11 /* Asymmetric pause. */
285 #define OFPAT_OUTPUT 0 /* Output to switch port. */
286 #define OFPAT_SET_VLAN_VID 1 /* Set the 802.1q VLAN id. */
287 #define OFPAT_SET_VLAN_PCP 2 /* Set the 802.1q priority. */
288 #define OFPAT_STRIP_VLAN 3 /* Strip the 802.1q header. */
289 #define OFPAT_SET_DL_SRC 4 /* Ethernet source address. */
290 #define OFPAT_SET_DL_DST 5 /* Ethernet destination address. */
291 #define OFPAT_SET_NW_SRC 6 /* IP source address. */
292 #define OFPAT_SET_NW_DST 7 /* IP destination address. */
293 #define OFPAT_SET_TP_SRC 8 /* TCP/UDP source port. */
294 #define OFPAT_SET_TP_DST 9 /* TCP/UDP destination port. */
295 #define OFPAT_VENDOR 0xffff
298 dissect_openflow_ofp_match_v1(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
, int offset
)
301 /* uint32_t wildcards; Wildcard fields. */
302 proto_tree_add_item(tree
, hf_openflow_wildcards
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
304 /* uint16_t in_port; Input switch port. */
305 proto_tree_add_item(tree
, hf_openflow_in_port
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
308 /* uint8_t dl_src[OFP_ETH_ALEN]; Ethernet source address. */
309 proto_tree_add_item(tree
, hf_openflow_eth_src
, tvb
, offset
, 6, ENC_NA
);
311 /* uint8_t dl_dst[OFP_ETH_ALEN]; Ethernet destination address. */
312 proto_tree_add_item(tree
, hf_openflow_eth_dst
, tvb
, offset
, 6, ENC_NA
);
314 /* uint16_t dl_vlan; Input VLAN id. */
315 proto_tree_add_item(tree
, hf_openflow_dl_vlan
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
317 /* uint8_t dl_vlan_pcp; Input VLAN priority. */
318 proto_tree_add_item(tree
, hf_openflow_dl_vlan_pcp
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
320 /* uint8_t pad1[1]; Align to 64-bits */
321 proto_tree_add_item(tree
, hf_openflow_ofp_match_pad
, tvb
, offset
, 1, ENC_NA
);
323 /* uint16_t dl_type; Ethernet frame type. */
324 proto_tree_add_item(tree
, hf_openflow_match_dl_type
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
326 /* uint8_t nw_tos; IP ToS (actually DSCP field, 6 bits). */
327 proto_tree_add_item(tree
, hf_openflow_ofp_match_tos
, tvb
, offset
, 1, ENC_NA
);
329 /* uint8_t nw_proto; IP protocol or lower 8 bits of
332 proto_tree_add_item(tree
, hf_openflow_ofp_match_nw_proto
, tvb
, offset
, 1, ENC_NA
);
334 /* uint8_t pad2[2]; Align to 64-bits */
335 proto_tree_add_item(tree
, hf_openflow_ofp_match_pad
, tvb
, offset
, 2, ENC_NA
);
337 /* uint32_t nw_src; IP source address. */
338 proto_tree_add_item(tree
, hf_openflow_ofp_source_addr
, tvb
, offset
, 4, ENC_NA
);
340 /* uint32_t nw_dst; IP destination address. */
341 proto_tree_add_item(tree
, hf_openflow_ofp_dest_addr
, tvb
, offset
, 4, ENC_NA
);
343 /* uint16_t tp_src; TCP/UDP source port. */
344 proto_tree_add_item(tree
, hf_openflow_ofp_source_port
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
346 /* uint16_t tp_dst; TCP/UDP destination port. */
347 proto_tree_add_item(tree
, hf_openflow_ofp_dest_port
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
353 dissect_openflow_flow_stats_request_v1(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
)
355 /* struct ofp_match match; Fields to match */
356 offset
= dissect_openflow_ofp_match_v1(tvb
, pinfo
, tree
, offset
);
358 /* uint8_t table_id; ID of table to read (from ofp_table_stats),
359 * 0xff for all tables or 0xfe for emergency.
361 proto_tree_add_item(tree
, hf_openflow_table_id
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
363 /* uint8_t pad; Align to 32 bits. */
364 proto_tree_add_item(tree
, hf_openflow_v1_flow_stats_request_pad
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
366 /* uint16_t out_port; */
367 proto_tree_add_item(tree
, hf_openflow_out_port
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
375 static const value_string openflow_action_values
[] = {
376 { OFPAT_OUTPUT
, "Output to switch port" },
377 { OFPAT_SET_VLAN_VID
, "Set the 802.1q VLAN id" },
378 { OFPAT_SET_VLAN_PCP
, "Set the 802.1q priority" },
379 { OFPAT_STRIP_VLAN
, "Strip the 802.1q header" },
380 { OFPAT_SET_DL_SRC
, "Ethernet source address" },
381 { OFPAT_SET_DL_DST
, "Ethernet destination address" },
382 { OFPAT_SET_NW_SRC
, "IP source address" },
383 { OFPAT_SET_NW_DST
, "IP destination address" },
384 { OFPAT_SET_TP_SRC
, "TCP/UDP source port" },
385 { OFPAT_SET_TP_DST
, "TCP/UDP destination port" },
386 { OFPAT_VENDOR
, "Vendor specific action"},
391 dissect_openflow_action_header(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
)
393 uint16_t action_type
, action_len
;
396 /* uint16_t type; One of OFPAT_*. */
397 action_type
= tvb_get_ntohs(tvb
, offset
);
398 ti
= proto_tree_add_item(tree
, hf_openflow_action_type
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
400 /* Length of action, including this
401 * header. This is the length of action,
402 * including any padding to make it
405 action_len
= tvb_get_ntohs(tvb
, offset
);
406 proto_tree_add_item(tree
, hf_openflow_action_len
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
411 /* uint16_t port; Output port. */
412 proto_tree_add_item(tree
, hf_openflow_output_port
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
414 /* uint16_t max_len; Max length to send to controller. */
415 proto_tree_add_item(tree
, hf_openflow_max_len
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
419 expert_add_info(pinfo
, ti
, &ei_openflow_action_type
);
420 offset
+=(action_len
-4);
427 dissect_openflow_phy_port(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
, int offset
)
430 proto_tree
*port_cnf_tree
, *port_state_tree
, *port_cf_tree
;
432 proto_tree_add_item(tree
, hf_openflow_port_no
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
434 proto_tree_add_item(tree
, hf_openflow_hw_addr
, tvb
, offset
, 6, ENC_NA
);
436 proto_tree_add_item(tree
, hf_openflow_port_name
, tvb
, offset
, OFP_MAX_PORT_NAME_LEN
, ENC_ASCII
);
437 offset
+=OFP_MAX_PORT_NAME_LEN
;
439 /* Bitmap of OFPPC_* flags. */
440 ti
= proto_tree_add_item(tree
, hf_openflow_port_config
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
441 port_cnf_tree
= proto_item_add_subtree(ti
, ett_openflow_port_cnf
);
443 /* Port is administratively down. */
444 proto_tree_add_item(port_cnf_tree
, hf_openflow_port_down
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
445 /* Disable 802.1D spanning tree on port. */
446 proto_tree_add_item(port_cnf_tree
, hf_openflow_no_stp
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
447 /* Drop all packets except 802.1D spanning tree packets. */
448 proto_tree_add_item(port_cnf_tree
, hf_openflow_no_recv
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
449 /* Drop received 802.1D STP packets. */
450 proto_tree_add_item(port_cnf_tree
, hf_openflow_no_recv_stp
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
451 /* Do not include this port when flooding. */
452 proto_tree_add_item(port_cnf_tree
, hf_openflow_no_flood
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
453 /* Drop packets forwarded to port. */
454 proto_tree_add_item(port_cnf_tree
, hf_openflow_no_fwd
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
455 /* Do not send packet-in msgs for port. */
456 proto_tree_add_item(port_cnf_tree
, hf_openflow_no_packet_in
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
459 /* Bitmap of OFPPS_* flags. */
460 ti
= proto_tree_add_item(tree
, hf_openflow_port_state
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
461 port_state_tree
= proto_item_add_subtree(ti
, ett_openflow_port_state
);
463 /* No physical link present. */
464 proto_tree_add_item(port_state_tree
, hf_openflow_link_down
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
468 /* Current features. */
469 ti
= proto_tree_add_item(tree
, hf_openflow_port_curr
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
470 port_cf_tree
= proto_item_add_subtree(ti
, ett_openflow_port_cf
);
471 /* 10 Mb half-duplex rate support. */
472 proto_tree_add_item(port_cf_tree
, hf_openflow_10mb_hd
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
473 /* 10 Mb full-duplex rate support. */
474 proto_tree_add_item(port_cf_tree
, hf_openflow_10mb_fd
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
475 /* 100 Mb half-duplex rate support. */
476 proto_tree_add_item(port_cf_tree
, hf_openflow_100mb_hd
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
477 /* 100 Mb full-duplex rate support. */
478 proto_tree_add_item(port_cf_tree
, hf_openflow_100mb_fd
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
479 /* 1 Gb half-duplex rate support. */
480 proto_tree_add_item(port_cf_tree
, hf_openflow_1gb_hd
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
481 /* 1 Gb full-duplex rate support. */
482 proto_tree_add_item(port_cf_tree
, hf_openflow_1gb_fd
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
483 /* 10 Gb full-duplex rate support. */
484 proto_tree_add_item(port_cf_tree
, hf_openflow_10gb_fd
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
486 proto_tree_add_item(port_cf_tree
, hf_openflow_copper
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
488 proto_tree_add_item(port_cf_tree
, hf_openflow_fiber
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
489 /* Auto-negotiation. */
490 proto_tree_add_item(port_cf_tree
, hf_openflow_autoneg
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
492 proto_tree_add_item(port_cf_tree
, hf_openflow_pause
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
493 /* Asymmetric pause. */
494 proto_tree_add_item(port_cf_tree
, hf_openflow_pause_asym
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
497 /* Features being advertised by the port. */
498 proto_tree_add_item(tree
, hf_openflow_port_advertised
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
501 /* Features supported by the port. */
502 proto_tree_add_item(tree
, hf_openflow_port_supported
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
504 /* Features advertised by peer. */
505 proto_tree_add_item(tree
, hf_openflow_port_peer
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
515 struct ofp_switch_features
{
516 struct ofp_header header
;
517 uint64_t datapath_id
; /* Datapath unique ID. The lower 48-bits are for
518 a MAC address, while the upper 16-bits are
519 implementer-defined. */
520 uint32_t n_buffers
; /* Max packets buffered at once. */
521 uint8_t n_tables
; /* Number of tables supported by datapath. */
522 uint8_t pad
[3]; /* Align to 64-bits. */
524 uint32_t capabilities
; /* Bitmap of support "ofp_capabilities". */
525 uint32_t actions
; /* Bitmap of supported "ofp_action_type"s. */
527 struct ofp_phy_port ports
[0]; /* Port definitions. The number of ports
528 is inferred from the length field in
533 dissect_openflow_features_reply_v1(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
, uint16_t length
)
536 proto_tree
*path_id_tree
, *cap_tree
, *act_tree
;
538 uint16_t length_remaining
;
540 ti
= proto_tree_add_item(tree
, hf_openflow_datapath_id
, tvb
, offset
, 8, ENC_BIG_ENDIAN
);
541 path_id_tree
= proto_item_add_subtree(ti
, ett_openflow_path_id
);
542 proto_tree_add_item(path_id_tree
, hf_openflow_datapath_impl
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
544 proto_tree_add_item(path_id_tree
, hf_openflow_datapath_mac
, tvb
, offset
, 6, ENC_NA
);
547 proto_tree_add_item(tree
, hf_openflow_n_buffers
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
550 proto_tree_add_item(tree
, hf_openflow_n_tables
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
553 proto_tree_add_item(tree
, hf_openflow_features_reply_pad
, tvb
, offset
, 3, ENC_NA
);
556 ti
= proto_tree_add_item(tree
, hf_openflow_capabilities
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
557 cap_tree
= proto_item_add_subtree(ti
, ett_openflow_cap
);
560 proto_tree_add_item(cap_tree
, hf_openflow_cap_flow_stats
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
561 proto_tree_add_item(cap_tree
, hf_openflow_table_stats
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
562 proto_tree_add_item(cap_tree
, hf_openflow_port_stats
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
563 proto_tree_add_item(cap_tree
, hf_openflow_group_stats
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
564 proto_tree_add_item(cap_tree
, hf_openflow_ip_reasm
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
565 proto_tree_add_item(cap_tree
, hf_openflow_queue_stats
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
566 proto_tree_add_item(cap_tree
, hf_openflow_port_blocked
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
569 ti
= proto_tree_add_item(tree
, hf_openflow_actions
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
570 act_tree
= proto_item_add_subtree(ti
, ett_openflow_act
);
572 proto_tree_add_item(act_tree
, hf_openflow_output
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
573 proto_tree_add_item(act_tree
, hf_openflow_set_vlan_vid
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
574 proto_tree_add_item(act_tree
, hf_openflow_set_vlan_pcp
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
575 proto_tree_add_item(act_tree
, hf_openflow_strip_vlan
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
576 proto_tree_add_item(act_tree
, hf_openflow_set_dl_src
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
577 proto_tree_add_item(act_tree
, hf_openflow_set_dl_dst
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
578 proto_tree_add_item(act_tree
, hf_openflow_set_nw_src
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
579 proto_tree_add_item(act_tree
, hf_openflow_set_nw_dst
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
580 proto_tree_add_item(act_tree
, hf_openflow_set_nw_tos
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
581 proto_tree_add_item(act_tree
, hf_openflow_set_tp_src
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
582 proto_tree_add_item(act_tree
, hf_openflow_set_tp_dst
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
583 proto_tree_add_item(act_tree
, hf_openflow_enqueue
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
586 length_remaining
= length
-32;
587 if(length_remaining
> 0){
588 uint16_t num_ports
= length_remaining
/48;
590 if((length_remaining
&0x003f) != 0){
593 for(i
=0; i
<num_ports
;i
++){
594 proto_tree
*port_tree
;
596 port_tree
= proto_tree_add_subtree_format(tree
, tvb
, offset
, 48, ett_openflow_port
, NULL
, "Port data %u",i
+1);
597 dissect_openflow_phy_port(tvb
, pinfo
, port_tree
, offset
);
606 dissect_openflow_switch_config(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
, int offset
, uint16_t length _U_
)
609 /* ofp_config_flags */
610 proto_tree_add_item(tree
, hf_openflow_config_flags
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
613 proto_tree_add_item(tree
, hf_openflow_miss_send_len
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
618 #define OFPR_NO_MATCH 0 /* No matching flow (table-miss flow entry). */
619 #define OFPR_ACTION 1 /* Action explicitly output to controller. */
620 #define OFPR_INVALID_TTL 2 /* Packet has invalid TTL */
622 static const value_string openflow_reason_values
[] = {
623 { OFPR_NO_MATCH
, "No matching flow (table-miss flow entry)" },
624 { OFPR_ACTION
, "Action explicitly output to controller" },
625 { OFPR_INVALID_TTL
, "Packet has invalid TTL" },
630 dissect_openflow_pkt_in(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
, uint16_t length
)
634 /* uint32_t buffer_id; ID assigned by datapath. */
635 proto_tree_add_item(tree
, hf_openflow_buffer_id
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
637 /* uint16_t total_len; Full length of frame. */
638 proto_tree_add_item(tree
, hf_openflow_total_len
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
641 /* uint16_t in_port; Port on which frame was received. */
642 proto_tree_add_item(tree
, hf_openflow_in_port
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
645 /* uint8_t reason; Reason packet is being sent (one of OFPR_*) */
646 proto_tree_add_item(tree
, hf_openflow_reason
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
649 proto_tree_add_item(tree
, hf_openflow_pkt_in_pad
, tvb
, offset
, 1, ENC_NA
);
652 next_tvb
= tvb_new_subset_length(tvb
, offset
, length
-offset
);
653 call_dissector(eth_withoutfcs_handle
, next_tvb
, pinfo
, tree
);
657 #define OFPRR_IDLE_TIMEOUT 0
658 #define OFPRR_HARD_TIMEOUT 1
659 #define OFPRR_DELETE 2
660 static const value_string openflow_flow_removed_reason_values
[] = {
661 { OFPRR_IDLE_TIMEOUT
, "OFPRR_IDLE_TIMEOUT" },
662 { OFPRR_HARD_TIMEOUT
, "OFPRR_HARD_TIMEOUT" },
663 { OFPRR_DELETE
, "OFPRR_DELETE" },
668 dissect_openflow_flow_removed(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
, uint16_t length _U_
)
671 offset
= dissect_openflow_ofp_match_v1(tvb
, pinfo
, tree
, offset
);
673 /* uint64_t cookie; */
674 proto_tree_add_item(tree
, hf_openflow_flow_removed_cookie
, tvb
, offset
, 8, ENC_BIG_ENDIAN
);
677 /* uint16_t priority; */
678 proto_tree_add_item(tree
, hf_openflow_flow_removed_priority
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
681 /* uint8_t reason; */
682 proto_tree_add_item(tree
, hf_openflow_flow_removed_reason
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
686 proto_tree_add_item(tree
, hf_openflow_flow_removed_pad1
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
689 /* uint32_t duration_sec; */
690 proto_tree_add_item(tree
, hf_openflow_flow_removed_duration_sec
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
693 /* uint32_t duration_nsec; */
694 proto_tree_add_item(tree
, hf_openflow_flow_removed_duration_nsec
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
697 /* uint16_t idle_timeout; */
698 proto_tree_add_item(tree
, hf_openflow_flow_removed_idle_timeout
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
702 proto_tree_add_item(tree
, hf_openflow_flow_removed_pad2
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
705 /* uint64_t packet_count; */
706 proto_tree_add_item(tree
, hf_openflow_flow_removed_packet_count
, tvb
, offset
, 8, ENC_BIG_ENDIAN
);
709 /* uint64_t byte_count; */
710 proto_tree_add_item(tree
, hf_openflow_flow_removed_byte_count
, tvb
, offset
, 8, ENC_BIG_ENDIAN
);
715 dissect_openflow_pkt_out(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
, uint16_t length
)
720 /* uint32_t buffer_id; ID assigned by datapath. */
721 buffer_id
= tvb_get_ntohl(tvb
, offset
);
722 proto_tree_add_item(tree
, hf_openflow_buffer_id
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
725 /* uint32_t in_port; Packet's input port or OFPP_CONTROLLER. */
726 proto_tree_add_item(tree
, hf_openflow_in_port
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
729 /* uint16_t actions_len; Size of action array in bytes. */
730 proto_tree_add_item(tree
, hf_openflow_actions_len
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
733 /* struct ofp_action_header actions[0]; Action list. */
734 offset
= dissect_openflow_action_header(tvb
, pinfo
, tree
, offset
);
735 /* Packet data. The length is inferred
736 from the length field in the header.
737 (Only meaningful if buffer_id == -1.)
740 next_tvb
= tvb_new_subset_length(tvb
, offset
, length
-offset
);
741 call_dissector(eth_withoutfcs_handle
, next_tvb
, pinfo
, tree
);
745 #define OFPFC_ADD 0 /* New flow. */
746 #define OFPFC_MODIFY 1 /* Modify all matching flows. */
747 #define OFPFC_MODIFY_STRICT 2 /* Modify entry strictly matching wildcards */
748 #define OFPFC_DELETE 3 /* Delete all matching flows. */
749 #define OFPFC_DELETE_STRICT 4 /* Strictly match wildcards and priority. */
751 static const value_string openflow_command_values
[] = {
752 { OFPFC_ADD
, "New flow" },
753 { OFPFC_MODIFY
, "Modify all matching flows" },
754 { OFPFC_MODIFY_STRICT
, "Modify entry strictly matching wildcards" },
755 { OFPFC_DELETE
, "Delete all matching flows" },
756 { OFPFC_DELETE_STRICT
, "Strictly match wildcards and priority" },
761 dissect_openflow_flow_mod(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
, uint16_t length _U_
)
764 /* struct ofp_match match; Fields to match */
765 offset
= dissect_openflow_ofp_match_v1(tvb
, pinfo
, tree
, offset
);
767 /* uint64_t cookie; Opaque controller-issued identifier. */
768 proto_tree_add_item(tree
, hf_openflow_cookie
, tvb
, offset
, 8, ENC_BIG_ENDIAN
);
771 /* uint16_t command; One of OFPFC_*. */
772 proto_tree_add_item(tree
, hf_openflow_command
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
775 /* uint16_t idle_timeout; Idle time before discarding (seconds). */
776 proto_tree_add_item(tree
, hf_openflow_idle_timeout
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
778 /* uint16_t hard_timeout; Max time before discarding (seconds). */
779 proto_tree_add_item(tree
, hf_openflow_hard_timeout
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
781 /* uint16_t priority; Priority level of flow entry. */
782 proto_tree_add_item(tree
, hf_openflow_priority
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
784 /* uint32_t buffer_id; Buffered packet to apply to, or OFP_NO_BUFFER.
785 Not meaningful for OFPFC_DELETE*.
787 proto_tree_add_item(tree
, hf_openflow_buffer_id
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
789 /* uint32_t out_port; For OFPFC_DELETE* commands, require
790 matching entries to include this as an output port. A value of OFPP_ANY
791 indicates no restriction.
793 proto_tree_add_item(tree
, hf_openflow_out_port
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
796 /* uint16_t flags; One of OFPFF_*. */
797 proto_tree_add_item(tree
, hf_openflow_flags
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
800 dissect_openflow_action_header(tvb
, pinfo
, tree
, offset
);
806 #define OFPST_AGGREGATE 2
807 #define OFPST_TABLE 3
809 #define OFPST_QUEUE 5
810 #define OFPST_VENDOR 0xffff
812 static const value_string openflow_stats_type_values
[] = {
813 { OFPST_DESC
, "OFPST_DESC" },
814 { OFPST_FLOW
, "OFPST_FLOW" },
815 { OFPST_AGGREGATE
, "OFPST_AGGREGATE" },
816 { OFPST_TABLE
, "OFPST_TABLE" },
817 { OFPST_PORT
, "OFPST_PORT" },
818 { OFPST_QUEUE
, "OFPST_QUEUE" },
819 { OFPST_VENDOR
, "OFPST_VENDOR" },
823 dissect_openflow_stats_req(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
, uint16_t length _U_
)
825 proto_item
*type_item
;
829 type_item
= proto_tree_add_item_ret_uint(tree
, hf_openflow_v1_stats_type
, tvb
, offset
, 2, ENC_BIG_ENDIAN
, &type
);
831 /* uint16_t flags; OFPSF_REQ_* flags (none yet defined). */
832 proto_tree_add_item(tree
, hf_openflow_flags
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
834 /* uint8_t body[0]; Body of the request. */
837 /* The request body is empty. */
840 dissect_openflow_flow_stats_request_v1(tvb
, pinfo
, tree
, offset
);
843 expert_add_info(pinfo
, type_item
, &ei_openflow_1_0_type
);
851 dissect_openflow_stats_resp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
, uint16_t length
)
854 proto_item
*type_item
;
858 type_item
= proto_tree_add_item_ret_uint(tree
, hf_openflow_v1_stats_type
, tvb
, offset
, 2, ENC_BIG_ENDIAN
, &type
);
860 /* uint16_t flags; OFPSF_REQ_ */
861 proto_tree_add_item(tree
, hf_openflow_flags
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
863 /* uint8_t body[0]; Body of the request. */
870 /* The request body is empty. */
875 expert_add_info(pinfo
, type_item
, &ei_openflow_1_0_type
);
883 dissect_openflow_v1(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
885 proto_item
*ti
, *type_item
;
886 proto_tree
*openflow_tree
;
891 type
= tvb_get_uint8(tvb
, 1);
893 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "Type: %s",
894 val_to_str_ext_const(type
, &openflow_1_0_type_values_ext
, "Unknown message type"));
896 /* Stop the Ethernet frame from overwriting the columns */
897 if((type
== OFPT_1_0_PACKET_IN
) || (type
== OFPT_1_0_PACKET_OUT
)){
898 col_set_writable(pinfo
->cinfo
, -1, false);
901 /* Create display subtree for the protocol */
902 ti
= proto_tree_add_item(tree
, proto_openflow_v1
, tvb
, 0, -1, ENC_NA
);
903 openflow_tree
= proto_item_add_subtree(ti
, ett_openflow
);
905 /* A.1 OpenFlow Header. */
907 proto_tree_add_item(openflow_tree
, hf_openflow_version
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
910 /* One of the OFPT_ constants. */
911 type_item
= proto_tree_add_item(openflow_tree
, hf_openflow_1_0_type
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
914 /* Length including this ofp_header. */
915 length
= tvb_get_ntohs(tvb
, offset
);
916 proto_tree_add_item(openflow_tree
, hf_openflow_length
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
919 /* Transaction id associated with this packet. Replies use the same id as was in the request
920 * to facilitate pairing.
922 proto_tree_add_item(openflow_tree
, hf_openflow_xid
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
926 case OFPT_1_0_HELLO
: /* 0 */
928 * The OFPT_HELLO message has no body;
931 case OFPT_1_0_FEATURES_REQUEST
: /* 5 */
933 * Upon TLS session establishment, the controller sends an OFPT_FEATURES_REQUEST
934 * message. This message does not contain a body beyond the OpenFlow header.
937 case OFPT_1_0_FEATURES_REPLY
: /* 6 */
938 dissect_openflow_features_reply_v1(tvb
, pinfo
, openflow_tree
, offset
, length
);
940 case OFPT_1_0_GET_CONFIG_REQUEST
: /* 7 */
941 /* A.3.2 There is no body for OFPT_GET_CONFIG_REQUEST beyond the OpenFlow header. */
943 case OFPT_1_0_GET_CONFIG_REPLY
: /* 8 */
945 case OFPT_1_0_SET_CONFIG
: /* 9 */
946 dissect_openflow_switch_config(tvb
, pinfo
, openflow_tree
, offset
, length
);
948 case OFPT_1_0_PACKET_IN
: /* 10 */
949 dissect_openflow_pkt_in(tvb
, pinfo
, openflow_tree
, offset
, length
);
951 case OFPT_1_0_FLOW_REMOVED
: /* 11 */
952 dissect_openflow_flow_removed(tvb
, pinfo
, openflow_tree
, offset
, length
);
954 case OFPT_1_0_PACKET_OUT
: /* 13 */
955 dissect_openflow_pkt_out(tvb
, pinfo
, openflow_tree
, offset
, length
);
957 case OFPT_1_0_FLOW_MOD
: /* 14 */
958 dissect_openflow_flow_mod(tvb
, pinfo
, openflow_tree
, offset
, length
);
960 case OFPT_1_0_STATS_REQUEST
: /* 16 */
961 dissect_openflow_stats_req(tvb
, pinfo
, openflow_tree
, offset
, length
);
963 case OFPT_1_0_STATS_REPLY
: /* 17 */
964 dissect_openflow_stats_resp(tvb
, pinfo
, openflow_tree
, offset
, length
);
968 expert_add_info(pinfo
, type_item
, &ei_openflow_1_0_type
);
973 return tvb_reported_length(tvb
);
979 * Register the protocol with Wireshark.
982 proto_register_openflow_v1(void)
984 static hf_register_info hf
[] = {
985 { &hf_openflow_version
,
986 { "Version", "openflow.version",
987 FT_UINT8
, BASE_HEX
, VALS(openflow_version_values
), 0x7f,
990 { &hf_openflow_1_0_type
,
991 { "Type", "openflow_1_0.type",
992 FT_UINT8
, BASE_DEC
| BASE_EXT_STRING
, &openflow_1_0_type_values_ext
, 0x0,
996 { "Transaction ID", "openflow.xid",
997 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
1000 { &hf_openflow_length
,
1001 { "Length", "openflow.length",
1002 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1005 { &hf_openflow_datapath_id
,
1006 { "Datapath unique ID", "openflow.datapath_id",
1007 FT_UINT64
, BASE_HEX
, NULL
, 0x0,
1010 { &hf_openflow_datapath_mac
,
1011 { "MAC addr", "openflow.datapath_mac",
1012 FT_ETHER
, BASE_NONE
, NULL
, 0x0,
1015 { &hf_openflow_datapath_impl
,
1016 { "Implementers part", "openflow.datapath_imp",
1017 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
1020 { &hf_openflow_n_buffers
,
1021 { "n_buffers", "openflow.n_buffers",
1022 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
1025 { &hf_openflow_n_tables
,
1026 { "n_tables", "openflow.n_tables",
1027 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1031 { &hf_openflow_auxiliary_id
,
1032 { "auxiliary_id", "openflow.auxiliary_id",
1033 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1037 { &hf_openflow_capabilities
,
1038 { "capabilities", "openflow.capabilities",
1039 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
1042 { &hf_openflow_actions
,
1043 { "actions", "openflow.actions",
1044 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
1048 { &hf_openflow_reserved32
,
1049 { "Reserved", "openflow.reserved32",
1050 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
1054 { &hf_openflow_cap_flow_stats
,
1055 { "Flow statistics", "openflow.flow_stats",
1056 FT_BOOLEAN
, 32, NULL
, OFPC_FLOW_STATS
,
1059 { &hf_openflow_table_stats
,
1060 { "Table statistics", "openflow.table_stats",
1061 FT_BOOLEAN
, 32, NULL
, OFPC_TABLE_STATS
,
1064 { &hf_openflow_port_stats
,
1065 { "Port statistics", "openflow.port_stats",
1066 FT_BOOLEAN
, 32, NULL
, OFPC_PORT_STATS
,
1069 { &hf_openflow_group_stats
,
1070 { "Group statistics", "openflow.group_stats",
1071 FT_BOOLEAN
, 32, NULL
, OFPC_GROUP_STATS
,
1074 { &hf_openflow_ip_reasm
,
1075 { "Can reassemble IP fragments", "openflow.ip_reasm",
1076 FT_BOOLEAN
, 32, NULL
, OFPC_IP_REASM
,
1079 { &hf_openflow_queue_stats
,
1080 { "Queue statistics", "openflow.queue_stats",
1081 FT_BOOLEAN
, 32, NULL
, OFPC_QUEUE_STATS
,
1084 { &hf_openflow_port_blocked
,
1085 { "Switch will block looping ports", "openflow.port_blocked",
1086 FT_BOOLEAN
, 32, NULL
, OFPC_PORT_BLOCKED
,
1089 { &hf_openflow_output
,
1090 { "Output to switch port", "openflow.output",
1091 FT_BOOLEAN
, 32, NULL
, OFPAT_OUTPUT_MASK
,
1094 { &hf_openflow_set_vlan_vid
,
1095 { "Set the 802.1q VLAN id", "openflow.set_vlan_vid",
1096 FT_BOOLEAN
, 32, NULL
, OFPAT_SET_VLAN_VID_MASK
,
1099 { &hf_openflow_set_vlan_pcp
,
1100 { "Set the 802.1q priority", "openflow.set_vlan_pcp",
1101 FT_BOOLEAN
, 32, NULL
, OFPAT_SET_VLAN_PCP_MASK
,
1104 { &hf_openflow_strip_vlan
,
1105 { "Strip the 802.1q header", "openflow.strip_vlan",
1106 FT_BOOLEAN
, 32, NULL
, OFPAT_STRIP_VLAN_MASK
,
1109 { &hf_openflow_set_dl_src
,
1110 { "Ethernet source address", "openflow.set_dl_src",
1111 FT_BOOLEAN
, 32, NULL
, OFPAT_SET_DL_SRC_MASK
,
1114 { &hf_openflow_set_dl_dst
,
1115 { "Ethernet destination address", "openflow.set_dl_ds",
1116 FT_BOOLEAN
, 32, NULL
, OFPAT_SET_DL_DST_MASK
,
1119 { &hf_openflow_set_nw_src
,
1120 { "IP source address", "openflow.set_nw_src",
1121 FT_BOOLEAN
, 32, NULL
, OFPAT_SET_NW_SRC_MASK
,
1124 { &hf_openflow_set_nw_dst
,
1125 { "IP destination address", "openflow.set_nw_ds",
1126 FT_BOOLEAN
, 32, NULL
, OFPAT_SET_NW_DST_MASK
,
1129 { &hf_openflow_set_nw_tos
,
1130 { "IP ToS (DSCP field, 6 bits)", "openflow.set_nw_tos",
1131 FT_BOOLEAN
, 32, NULL
, OFPAT_SET_NW_TOS_MASK
,
1134 { &hf_openflow_set_tp_src
,
1135 { "TCP/UDP source port", "openflow.set_tp_src",
1136 FT_BOOLEAN
, 32, NULL
, OFPAT_SET_TP_SRC_MASK
,
1139 { &hf_openflow_set_tp_dst
,
1140 { "TCP/UDP destination port", "openflow.set_tp_dst",
1141 FT_BOOLEAN
, 32, NULL
, OFPAT_SET_TP_DST_MASK
,
1144 { &hf_openflow_enqueue
,
1145 { "Output to queue", "openflow.enqueue",
1146 FT_BOOLEAN
, 32, NULL
, OFPAT_ENQUEUE_MASK
,
1149 { &hf_openflow_port_no
,
1150 { "Port number", "openflow.port_no",
1151 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1154 { &hf_openflow_hw_addr
,
1155 { "HW Address", "openflow.hw_add",
1156 FT_ETHER
, BASE_NONE
, NULL
, 0x0,
1159 { &hf_openflow_port_name
,
1160 { "Port Name", "openflow.port_name",
1161 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1164 { &hf_openflow_port_config
,
1165 { "Config flags", "openflow.port_config",
1166 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
1169 { &hf_openflow_port_state
,
1170 { "State flags", "openflow.port_state",
1171 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
1174 { &hf_openflow_port_curr
,
1175 { "Current features", "openflow.port_curr",
1176 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
1179 { &hf_openflow_port_advertised
,
1180 { "Advertised features", "openflow.port_advertised",
1181 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
1184 { &hf_openflow_port_supported
,
1185 { "Features supported", "openflow.port_supported",
1186 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
1189 { &hf_openflow_port_peer
,
1190 { "Features advertised by peer", "openflow.port_peer",
1191 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
1194 { &hf_openflow_port_down
,
1195 { "Port is administratively down", "openflow.port_down",
1196 FT_BOOLEAN
, 32, NULL
, OFPPC_PORT_DOWN
,
1199 { &hf_openflow_no_stp
,
1200 { "Disable 802.1D spanning tree on port", "openflow.no_stp",
1201 FT_BOOLEAN
, 32, NULL
, OFPPC_NO_STP
,
1204 { &hf_openflow_no_recv
,
1205 { "Drop all packets except 802.1D spanning tree packets", "openflow.no_recv",
1206 FT_BOOLEAN
, 32, NULL
, OFPPC_NO_RECV
,
1209 { &hf_openflow_no_recv_stp
,
1210 { "Drop received 802.1D STP packets", "openflow.no_recv_stp",
1211 FT_BOOLEAN
, 32, NULL
, OFPPC_NO_RECV_STP
,
1214 { &hf_openflow_no_flood
,
1215 { "Do not include this port when flooding", "openflow.no_flood",
1216 FT_BOOLEAN
, 32, NULL
, OFPPC_NO_FLOOD
,
1219 { &hf_openflow_no_fwd
,
1220 { "Drop packets forwarded to port", "openflow.no_fwd",
1221 FT_BOOLEAN
, 32, NULL
, OFPPC_NO_FWD
,
1224 { &hf_openflow_no_packet_in
,
1225 { "Do not send packet-in msgs for port", "openflow.no_packet_in",
1226 FT_BOOLEAN
, 32, NULL
, OFPPC_NO_PACKET_IN
,
1229 { &hf_openflow_link_down
,
1230 { "No physical link present", "openflow.link_down",
1231 FT_BOOLEAN
, 32, NULL
, OFPPS_LINK_DOWN
,
1234 { &hf_openflow_10mb_hd
,
1235 { "10 Mb half-duplex rate support", "openflow.10mb_hd",
1236 FT_BOOLEAN
, 32, NULL
, OFPPF_10MB_HD
,
1239 { &hf_openflow_10mb_fd
,
1240 { "10 Mb full-duplex rate support", "openflow.10mb_fd",
1241 FT_BOOLEAN
, 32, NULL
, OFPPF_10MB_FD
,
1244 { &hf_openflow_100mb_hd
,
1245 { "100 Mb half-duplex rate support", "openflow.100mb_hd",
1246 FT_BOOLEAN
, 32, NULL
, OFPPF_100MB_HD
,
1249 { &hf_openflow_100mb_fd
,
1250 { "100 Mb full-duplex rate support", "openflow.100mb_0fd",
1251 FT_BOOLEAN
, 32, NULL
, OFPPF_100MB_FD
,
1254 { &hf_openflow_1gb_hd
,
1255 { "1 Gb half-duplex rate support", "openflow.1gb_hd",
1256 FT_BOOLEAN
, 32, NULL
, OFPPF_1GB_HD
,
1259 { &hf_openflow_1gb_fd
,
1260 { "1 Gb full-duplex rate support", "openflow.1gb_fd",
1261 FT_BOOLEAN
, 32, NULL
, OFPPF_1GB_FD
,
1264 { &hf_openflow_10gb_fd
,
1265 { "10 Gb full-duplex rate support", "openflow.10gb_fd",
1266 FT_BOOLEAN
, 32, NULL
, OFPPF_10GB_FD
,
1269 { &hf_openflow_copper
,
1270 { "Copper medium", "openflow.copper",
1271 FT_BOOLEAN
, 32, NULL
, OFPPF_COPPER
,
1274 { &hf_openflow_fiber
,
1275 { "Fiber medium", "openflow.fiber",
1276 FT_BOOLEAN
, 32, NULL
, OFPPF_FIBER
,
1279 { &hf_openflow_autoneg
,
1280 { "Auto-negotiation", "openflow.autoneg",
1281 FT_BOOLEAN
, 32, NULL
, OFPPF_AUTONEG
,
1284 { &hf_openflow_pause
,
1285 { "Pause", "openflow.pause",
1286 FT_BOOLEAN
, 32, NULL
, OFPPF_PAUSE
,
1289 { &hf_openflow_pause_asym
,
1290 { "Asymmetric pause", "openflow.pause_asym",
1291 FT_BOOLEAN
, 32, NULL
, OFPPF_PAUSE_ASYM
,
1294 { &hf_openflow_config_flags
,
1295 { "Config flags", "openflow.config_flags",
1296 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
1299 { &hf_openflow_miss_send_len
,
1300 { "Max bytes of packet", "openflow.miss_send_len",
1301 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
1304 { &hf_openflow_buffer_id
,
1305 { "Buffer Id", "openflow.buffer_id",
1306 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
1309 { &hf_openflow_total_len
,
1310 { "Total length", "openflow.total_len",
1311 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1314 { &hf_openflow_in_port
,
1315 { "In port", "openflow.in_port",
1316 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1319 { &hf_openflow_reason
,
1320 { "Reason", "openflow.reason",
1321 FT_UINT8
, BASE_DEC
, VALS(openflow_reason_values
), 0x0,
1325 { &hf_openflow_pkt_in_pad
,
1326 { "Pad", "openflow.pkt_in.pad",
1327 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1330 { &hf_openflow_flow_removed_cookie
,
1331 { "Cookie", "openflow.flow_removed.cookie",
1332 FT_UINT64
, BASE_HEX
, NULL
, 0x0,
1335 { &hf_openflow_flow_removed_priority
,
1336 { "Priority", "openflow.flow_removed.priority",
1337 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1340 { &hf_openflow_flow_removed_reason
,
1341 { "Reason", "openflow.flow_removed.reason",
1342 FT_UINT8
, BASE_DEC
, VALS(openflow_flow_removed_reason_values
), 0x0,
1345 { &hf_openflow_flow_removed_pad1
,
1346 { "Pad1", "openflow.flow_removed.pad1",
1347 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1350 { &hf_openflow_flow_removed_duration_sec
,
1351 { "Duration sec", "openflow.flow_removed.duration_sec",
1352 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
1355 { &hf_openflow_flow_removed_duration_nsec
,
1356 { "Duration nsec", "openflow.flow_removed.duration_nsec",
1357 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
1360 { &hf_openflow_flow_removed_idle_timeout
,
1361 { "Idle timeout", "openflow.flow_removed.idle_timeout",
1362 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1365 { &hf_openflow_flow_removed_pad2
,
1366 { "Pad2", "openflow.flow_removed.pad2",
1367 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
1370 { &hf_openflow_flow_removed_packet_count
,
1371 { "Packet count", "openflow.flow_removed.packet_count",
1372 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
1375 { &hf_openflow_flow_removed_byte_count
,
1376 { "Byte count", "openflow.flow_removed.byte_count",
1377 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
1380 { &hf_openflow_table_id
,
1381 { "Table Id", "openflow.table_id",
1382 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1385 { &hf_openflow_cookie
,
1386 { "Cookie", "openflow.cookie",
1387 FT_UINT64
, BASE_HEX
, NULL
, 0x0,
1391 { &hf_openflow_cookie_mask
,
1392 { "Cookie mask", "openflow.cookie_mask",
1393 FT_UINT64
, BASE_HEX
, NULL
, 0x0,
1397 { &hf_openflow_features_reply_pad
,
1398 { "Pad", "openflow.features_reply.pad",
1399 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1402 { &hf_openflow_actions_len
,
1403 { "Actions length", "openflow.actions_len",
1404 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1407 { &hf_openflow_action_type
,
1408 { "Actions type", "openflow.action_typ",
1409 FT_UINT16
, BASE_DEC
, VALS(openflow_action_values
), 0x0,
1412 { &hf_openflow_action_len
,
1413 { "Action length", "openflow.action_len",
1414 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1417 { &hf_openflow_output_port
,
1418 { "Output port", "openflow.output_port",
1419 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1422 { &hf_openflow_max_len
,
1423 { "Max length", "openflow.max_len",
1424 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1427 { &hf_openflow_wildcards
,
1428 { "Wildcards", "openflow.wildcards",
1429 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
1432 { &hf_openflow_command
,
1433 { "Command", "openflow.command",
1434 FT_UINT16
, BASE_DEC
, VALS(openflow_command_values
), 0x0,
1437 { &hf_openflow_eth_src
,
1438 { "Ethernet source address", "openflow.eth_src",
1439 FT_ETHER
, BASE_NONE
, NULL
, 0x0,
1442 { &hf_openflow_eth_dst
,
1443 { "Ethernet destination address", "openflow.eth_dst",
1444 FT_ETHER
, BASE_NONE
, NULL
, 0x0,
1447 { &hf_openflow_dl_vlan
,
1448 { "Input VLAN id", "openflow.dl_vlan",
1449 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1452 { &hf_openflow_dl_vlan_pcp
,
1453 { "Input VLAN priority", "openflow.dl_vlan_pcp",
1454 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1457 { &hf_openflow_ofp_match_pad
,
1458 { "Pad", "openflow.ofp_match.pad",
1459 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1462 { &hf_openflow_match_dl_type
,
1463 { "Dl type", "openflow.ofp_match.dl_type",
1464 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1467 { &hf_openflow_ofp_match_tos
,
1468 { "IP ToS", "openflow.ofp_match.tos",
1469 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1472 { &hf_openflow_ofp_match_nw_proto
,
1473 { "IP protocol", "openflow.ofp_match.nw_proto",
1474 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1477 { &hf_openflow_ofp_source_addr
,
1478 { "Source Address", "openflow.ofp_match.source_addr",
1479 FT_IPv4
, BASE_NONE
, NULL
, 0x0,
1482 { &hf_openflow_ofp_dest_addr
,
1483 { "Destination Address", "openflow.ofp_match.dest_addr",
1484 FT_IPv4
, BASE_NONE
, NULL
, 0x0,
1487 { &hf_openflow_ofp_source_port
,
1488 { "Source Port", "openflow.ofp_match.source_port",
1489 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1492 { &hf_openflow_ofp_dest_port
,
1493 { "Destination Port", "openflow.ofp_match.dest_port",
1494 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1497 { &hf_openflow_idle_timeout
,
1498 { "Idle time-out", "openflow.idle_timeout",
1499 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1502 { &hf_openflow_hard_timeout
,
1503 { "hard time-out", "openflow.hard_timeout",
1504 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1507 { &hf_openflow_priority
,
1508 { "Priority", "openflow.priority",
1509 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1512 { &hf_openflow_out_port
,
1513 { "Out port", "openflow.out_port",
1514 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
1518 { &hf_openflow_out_group
,
1519 { "Out group", "openflow.out_group",
1520 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
1524 { &hf_openflow_flags
,
1525 { "Flags", "openflow.flags",
1526 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1529 { &hf_openflow_v1_stats_type
,
1530 { "Type", "openflow.stats.type",
1531 FT_UINT16
, BASE_DEC
, VALS(openflow_stats_type_values
), 0x0,
1534 { &hf_openflow_v1_flow_stats_request_pad
,
1535 { "Pad", "openflow.stats.request_pad",
1536 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1541 static int *ett
[] = {
1543 &ett_openflow_path_id
,
1547 &ett_openflow_port_cnf
,
1548 &ett_openflow_port_state
,
1549 &ett_openflow_port_cf
1552 static ei_register_info ei
[] = {
1554 { &ei_openflow_undecoded_data
, { "openflow.undecoded_data", PI_UNDECODED
, PI_WARN
, "Data not dissected yet", EXPFILL
}},
1556 { &ei_openflow_action_type
, { "openflow.action_typ.undecoded", PI_UNDECODED
, PI_WARN
, "Action not dissected yet", EXPFILL
}},
1557 { &ei_openflow_1_0_type
, { "openflow_1_0.type.undecoded", PI_UNDECODED
, PI_WARN
, "Message data not dissected yet", EXPFILL
}},
1560 expert_module_t
* expert_openflow_v1
;
1562 /* Register the protocol name and description */
1563 proto_openflow_v1
= proto_register_protocol("OpenFlow 1.0", "openflow_v1", "openflow_v1");
1565 register_dissector("openflow_v1", dissect_openflow_v1
, proto_openflow_v1
);
1567 /* Required function calls to register the header fields and subtrees */
1568 proto_register_field_array(proto_openflow_v1
, hf
, array_length(hf
));
1569 proto_register_subtree_array(ett
, array_length(ett
));
1570 expert_openflow_v1
= expert_register_protocol(proto_openflow_v1
);
1571 expert_register_field_array(expert_openflow_v1
, ei
, array_length(ei
));
1575 proto_reg_handoff_openflow_v1(void)
1577 eth_withoutfcs_handle
= find_dissector_add_dependency("eth_withoutfcs", proto_openflow_v1
);
1581 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1586 * indent-tabs-mode: nil
1589 * vi: set shiftwidth=4 tabstop=8 expandtab:
1590 * :indentSize=4:tabSize=8:noTabs=true: