2 * This module implements decoding of OpenFlow protocol version 1.0 (wire
3 * protocol 0x01). The decoder implements terse (default), detailed (-v) and
4 * full (-vv) output formats and, as much as each format implies, detects and
5 * tries to work around sizing anomalies inside the messages. The decoder marks
6 * up bogus values of selected message fields and decodes partially captured
7 * messages up to the snapshot end. It is based on the specification below:
9 * [OF10] http://www.openflow.org/documents/openflow-spec-v1.0.0.pdf
12 * Copyright (c) 2013 The TCPDUMP project
13 * All rights reserved.
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
18 * 1. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution.
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
42 #include <tcpdump-stdinc.h>
44 #include "interface.h"
46 #include "addrtoname.h"
47 #include "ethertype.h"
49 #include "openflow-1.0.h"
51 static const struct tok ofpt_str
[] = {
52 { OFPT_HELLO
, "HELLO" },
53 { OFPT_ERROR
, "ERROR" },
54 { OFPT_ECHO_REQUEST
, "ECHO_REQUEST" },
55 { OFPT_ECHO_REPLY
, "ECHO_REPLY" },
56 { OFPT_VENDOR
, "VENDOR" },
57 { OFPT_FEATURES_REQUEST
, "FEATURES_REQUEST" },
58 { OFPT_FEATURES_REPLY
, "FEATURES_REPLY" },
59 { OFPT_GET_CONFIG_REQUEST
, "GET_CONFIG_REQUEST" },
60 { OFPT_GET_CONFIG_REPLY
, "GET_CONFIG_REPLY" },
61 { OFPT_SET_CONFIG
, "SET_CONFIG" },
62 { OFPT_PACKET_IN
, "PACKET_IN" },
63 { OFPT_FLOW_REMOVED
, "FLOW_REMOVED" },
64 { OFPT_PORT_STATUS
, "PORT_STATUS" },
65 { OFPT_PACKET_OUT
, "PACKET_OUT" },
66 { OFPT_FLOW_MOD
, "FLOW_MOD" },
67 { OFPT_PORT_MOD
, "PORT_MOD" },
68 { OFPT_STATS_REQUEST
, "STATS_REQUEST" },
69 { OFPT_STATS_REPLY
, "STATS_REPLY" },
70 { OFPT_BARRIER_REQUEST
, "BARRIER_REQUEST" },
71 { OFPT_BARRIER_REPLY
, "BARRIER_REPLY" },
72 { OFPT_QUEUE_GET_CONFIG_REQUEST
, "QUEUE_GET_CONFIG_REQUEST" },
73 { OFPT_QUEUE_GET_CONFIG_REPLY
, "QUEUE_GET_CONFIG_REPLY" },
77 static const struct tok ofppc_bm
[] = {
78 { OFPPC_PORT_DOWN
, "PORT_DOWN" },
79 { OFPPC_NO_STP
, "NO_STP" },
80 { OFPPC_NO_RECV
, "NO_RECV" },
81 { OFPPC_NO_RECV_STP
, "NO_RECV_STP" },
82 { OFPPC_NO_FLOOD
, "NO_FLOOD" },
83 { OFPPC_NO_FWD
, "NO_FWD" },
84 { OFPPC_NO_PACKET_IN
, "NO_PACKET_IN" },
87 #define OFPPC_U (~(OFPPC_PORT_DOWN | OFPPC_NO_STP | OFPPC_NO_RECV | \
88 OFPPC_NO_RECV_STP | OFPPC_NO_FLOOD | OFPPC_NO_FWD | \
91 static const struct tok ofpps_bm
[] = {
92 { OFPPS_LINK_DOWN
, "LINK_DOWN" },
93 { OFPPS_STP_LISTEN
, "STP_LISTEN" },
94 { OFPPS_STP_LEARN
, "STP_LEARN" },
95 { OFPPS_STP_FORWARD
, "STP_FORWARD" },
96 { OFPPS_STP_BLOCK
, "STP_BLOCK" },
99 #define OFPPS_U (~(OFPPS_LINK_DOWN | OFPPS_STP_LISTEN | OFPPS_STP_LEARN | \
100 OFPPS_STP_FORWARD | OFPPS_STP_BLOCK))
102 static const struct tok ofpp_str
[] = {
104 { OFPP_IN_PORT
, "IN_PORT" },
105 { OFPP_TABLE
, "TABLE" },
106 { OFPP_NORMAL
, "NORMAL" },
107 { OFPP_FLOOD
, "FLOOD" },
109 { OFPP_CONTROLLER
, "CONTROLLER" },
110 { OFPP_LOCAL
, "LOCAL" },
111 { OFPP_NONE
, "NONE" },
115 static const struct tok ofppf_bm
[] = {
116 { OFPPF_10MB_HD
, "10MB_HD" },
117 { OFPPF_10MB_FD
, "10MB_FD" },
118 { OFPPF_100MB_HD
, "100MB_HD" },
119 { OFPPF_100MB_FD
, "100MB_FD" },
120 { OFPPF_1GB_HD
, "1GB_HD" },
121 { OFPPF_1GB_FD
, "1GB_FD" },
122 { OFPPF_10GB_FD
, "10GB_FD" },
123 { OFPPF_COPPER
, "COPPER" },
124 { OFPPF_FIBER
, "FIBER" },
125 { OFPPF_AUTONEG
, "AUTONEG" },
126 { OFPPF_PAUSE
, "PAUSE" },
127 { OFPPF_PAUSE_ASYM
, "PAUSE_ASYM" },
130 #define OFPPF_U (~(OFPPF_10MB_HD | OFPPF_10MB_FD | OFPPF_100MB_HD | \
131 OFPPF_100MB_FD | OFPPF_1GB_HD | OFPPF_1GB_FD | \
132 OFPPF_10GB_FD | OFPPF_COPPER | OFPPF_FIBER | \
133 OFPPF_AUTONEG | OFPPF_PAUSE | OFPPF_PAUSE_ASYM))
135 static const struct tok ofpqt_str
[] = {
136 { OFPQT_NONE
, "NONE" },
137 { OFPQT_MIN_RATE
, "MIN_RATE" },
141 static const struct tok ofpfw_bm
[] = {
142 { OFPFW_IN_PORT
, "IN_PORT" },
143 { OFPFW_DL_VLAN
, "DL_VLAN" },
144 { OFPFW_DL_SRC
, "DL_SRC" },
145 { OFPFW_DL_DST
, "DL_DST" },
146 { OFPFW_DL_TYPE
, "DL_TYPE" },
147 { OFPFW_NW_PROTO
, "NW_PROTO" },
148 { OFPFW_TP_SRC
, "TP_SRC" },
149 { OFPFW_TP_DST
, "TP_DST" },
150 { OFPFW_DL_VLAN_PCP
, "DL_VLAN_PCP" },
151 { OFPFW_NW_TOS
, "NW_TOS" },
154 /* The above array does not include bits 8~13 (OFPFW_NW_SRC_*) and 14~19
155 * (OFPFW_NW_DST_*), which are not a part of the bitmap and require decoding
156 * other than that of tok2str(). The macro below includes these bits such that
157 * they are not reported as bogus in the decoding. */
158 #define OFPFW_U (~(OFPFW_ALL))
160 static const struct tok ofpat_str
[] = {
161 { OFPAT_OUTPUT
, "OUTPUT" },
162 { OFPAT_SET_VLAN_VID
, "SET_VLAN_VID" },
163 { OFPAT_SET_VLAN_PCP
, "SET_VLAN_PCP" },
164 { OFPAT_STRIP_VLAN
, "STRIP_VLAN" },
165 { OFPAT_SET_DL_SRC
, "SET_DL_SRC" },
166 { OFPAT_SET_DL_DST
, "SET_DL_DST" },
167 { OFPAT_SET_NW_SRC
, "SET_NW_SRC" },
168 { OFPAT_SET_NW_DST
, "SET_NW_DST" },
169 { OFPAT_SET_NW_TOS
, "SET_NW_TOS" },
170 { OFPAT_SET_TP_SRC
, "SET_TP_SRC" },
171 { OFPAT_SET_TP_DST
, "SET_TP_DST" },
172 { OFPAT_ENQUEUE
, "ENQUEUE" },
173 { OFPAT_VENDOR
, "VENDOR" },
177 /* bit-shifted, w/o vendor action */
178 static const struct tok ofpat_bm
[] = {
179 { 1 << OFPAT_OUTPUT
, "OUTPUT" },
180 { 1 << OFPAT_SET_VLAN_VID
, "SET_VLAN_VID" },
181 { 1 << OFPAT_SET_VLAN_PCP
, "SET_VLAN_PCP" },
182 { 1 << OFPAT_STRIP_VLAN
, "STRIP_VLAN" },
183 { 1 << OFPAT_SET_DL_SRC
, "SET_DL_SRC" },
184 { 1 << OFPAT_SET_DL_DST
, "SET_DL_DST" },
185 { 1 << OFPAT_SET_NW_SRC
, "SET_NW_SRC" },
186 { 1 << OFPAT_SET_NW_DST
, "SET_NW_DST" },
187 { 1 << OFPAT_SET_NW_TOS
, "SET_NW_TOS" },
188 { 1 << OFPAT_SET_TP_SRC
, "SET_TP_SRC" },
189 { 1 << OFPAT_SET_TP_DST
, "SET_TP_DST" },
190 { 1 << OFPAT_ENQUEUE
, "ENQUEUE" },
193 #define OFPAT_U (~(1 << OFPAT_OUTPUT | 1 << OFPAT_SET_VLAN_VID | \
194 1 << OFPAT_SET_VLAN_PCP | 1 << OFPAT_STRIP_VLAN | \
195 1 << OFPAT_SET_DL_SRC | 1 << OFPAT_SET_DL_DST | \
196 1 << OFPAT_SET_NW_SRC | 1 << OFPAT_SET_NW_DST | \
197 1 << OFPAT_SET_NW_TOS | 1 << OFPAT_SET_TP_SRC | \
198 1 << OFPAT_SET_TP_DST | 1 << OFPAT_ENQUEUE))
200 static const struct tok ofp_capabilities_bm
[] = {
201 { OFPC_FLOW_STATS
, "FLOW_STATS" },
202 { OFPC_TABLE_STATS
, "TABLE_STATS" },
203 { OFPC_PORT_STATS
, "PORT_STATS" },
205 { OFPC_RESERVED
, "RESERVED" }, /* not in the mask below */
206 { OFPC_IP_REASM
, "IP_REASM" },
207 { OFPC_QUEUE_STATS
, "QUEUE_STATS" },
208 { OFPC_ARP_MATCH_IP
, "ARP_MATCH_IP" },
211 #define OFPCAP_U (~(OFPC_FLOW_STATS | OFPC_TABLE_STATS | OFPC_PORT_STATS | \
212 OFPC_STP | OFPC_IP_REASM | OFPC_QUEUE_STATS | \
215 static const struct tok ofp_config_str
[] = {
216 { OFPC_FRAG_NORMAL
, "FRAG_NORMAL" },
217 { OFPC_FRAG_DROP
, "FRAG_DROP" },
218 { OFPC_FRAG_REASM
, "FRAG_REASM" },
222 static const struct tok ofpfc_str
[] = {
223 { OFPFC_ADD
, "ADD" },
224 { OFPFC_MODIFY
, "MODIFY" },
225 { OFPFC_MODIFY_STRICT
, "MODIFY_STRICT" },
226 { OFPFC_DELETE
, "DELETE" },
227 { OFPFC_DELETE_STRICT
, "DELETE_STRICT" },
231 static const struct tok bufferid_str
[] = {
232 { 0xffffffff, "NONE" },
236 static const struct tok ofpff_bm
[] = {
237 { OFPFF_SEND_FLOW_REM
, "SEND_FLOW_REM" },
238 { OFPFF_CHECK_OVERLAP
, "CHECK_OVERLAP" },
239 { OFPFF_EMERG
, "EMERG" },
242 #define OFPFF_U (~(OFPFF_SEND_FLOW_REM | OFPFF_CHECK_OVERLAP | OFPFF_EMERG))
244 static const struct tok ofpst_str
[] = {
245 { OFPST_DESC
, "DESC" },
246 { OFPST_FLOW
, "FLOW" },
247 { OFPST_AGGREGATE
, "AGGREGATE" },
248 { OFPST_TABLE
, "TABLE" },
249 { OFPST_PORT
, "PORT" },
250 { OFPST_QUEUE
, "QUEUE" },
251 { OFPST_VENDOR
, "VENDOR" },
255 static const struct tok tableid_str
[] = {
261 static const struct tok ofpq_str
[] = {
266 static const struct tok ofpsf_reply_bm
[] = {
267 { OFPSF_REPLY_MORE
, "MORE" },
270 #define OFPSF_REPLY_U (~(OFPSF_REPLY_MORE))
272 static const struct tok ofpr_str
[] = {
273 { OFPR_NO_MATCH
, "NO_MATCH" },
274 { OFPR_ACTION
, "ACTION" },
278 static const struct tok ofprr_str
[] = {
279 { OFPRR_IDLE_TIMEOUT
, "IDLE_TIMEOUT" },
280 { OFPRR_HARD_TIMEOUT
, "HARD_TIMEOUT" },
281 { OFPRR_DELETE
, "DELETE" },
285 static const struct tok ofppr_str
[] = {
286 { OFPPR_ADD
, "ADD" },
287 { OFPPR_DELETE
, "DELETE" },
288 { OFPPR_MODIFY
, "MODIFY" },
292 static const struct tok ofpet_str
[] = {
293 { OFPET_HELLO_FAILED
, "HELLO_FAILED" },
294 { OFPET_BAD_REQUEST
, "BAD_REQUEST" },
295 { OFPET_BAD_ACTION
, "BAD_ACTION" },
296 { OFPET_FLOW_MOD_FAILED
, "FLOW_MOD_FAILED" },
297 { OFPET_PORT_MOD_FAILED
, "PORT_MOD_FAILED" },
298 { OFPET_QUEUE_OP_FAILED
, "QUEUE_OP_FAILED" },
302 static const struct tok ofphfc_str
[] = {
303 { OFPHFC_INCOMPATIBLE
, "INCOMPATIBLE" },
304 { OFPHFC_EPERM
, "EPERM" },
308 static const struct tok ofpbrc_str
[] = {
309 { OFPBRC_BAD_VERSION
, "BAD_VERSION" },
310 { OFPBRC_BAD_TYPE
, "BAD_TYPE" },
311 { OFPBRC_BAD_STAT
, "BAD_STAT" },
312 { OFPBRC_BAD_VENDOR
, "BAD_VENDOR" },
313 { OFPBRC_BAD_SUBTYPE
, "BAD_SUBTYPE" },
314 { OFPBRC_EPERM
, "EPERM" },
315 { OFPBRC_BAD_LEN
, "BAD_LEN" },
316 { OFPBRC_BUFFER_EMPTY
, "BUFFER_EMPTY" },
317 { OFPBRC_BUFFER_UNKNOWN
, "BUFFER_UNKNOWN" },
321 static const struct tok ofpbac_str
[] = {
322 { OFPBAC_BAD_TYPE
, "BAD_TYPE" },
323 { OFPBAC_BAD_LEN
, "BAD_LEN" },
324 { OFPBAC_BAD_VENDOR
, "BAD_VENDOR" },
325 { OFPBAC_BAD_VENDOR_TYPE
, "BAD_VENDOR_TYPE" },
326 { OFPBAC_BAD_OUT_PORT
, "BAD_OUT_PORT" },
327 { OFPBAC_BAD_ARGUMENT
, "BAD_ARGUMENT" },
328 { OFPBAC_EPERM
, "EPERM" },
329 { OFPBAC_TOO_MANY
, "TOO_MANY" },
330 { OFPBAC_BAD_QUEUE
, "BAD_QUEUE" },
334 static const struct tok ofpfmfc_str
[] = {
335 { OFPFMFC_ALL_TABLES_FULL
, "ALL_TABLES_FULL" },
336 { OFPFMFC_OVERLAP
, "OVERLAP" },
337 { OFPFMFC_EPERM
, "EPERM" },
338 { OFPFMFC_BAD_EMERG_TIMEOUT
, "BAD_EMERG_TIMEOUT" },
339 { OFPFMFC_BAD_COMMAND
, "BAD_COMMAND" },
340 { OFPFMFC_UNSUPPORTED
, "UNSUPPORTED" },
344 static const struct tok ofppmfc_str
[] = {
345 { OFPPMFC_BAD_PORT
, "BAD_PORT" },
346 { OFPPMFC_BAD_HW_ADDR
, "BAD_HW_ADDR" },
350 static const struct tok ofpqofc_str
[] = {
351 { OFPQOFC_BAD_PORT
, "BAD_PORT" },
352 { OFPQOFC_BAD_QUEUE
, "BAD_QUEUE" },
353 { OFPQOFC_EPERM
, "EPERM" },
357 static const struct tok empty_str
[] = {
363 vlan_str(const uint16_t vid
) {
364 static char buf
[sizeof("65535 (bogus)")];
367 if (vid
== OFP_VLAN_NONE
)
369 fmt
= (vid
> 0 && vid
< 0x0fff) ? "%u" : "%u (bogus)";
370 snprintf(buf
, sizeof(buf
), fmt
, vid
);
375 pcp_str(const uint8_t pcp
) {
376 static char buf
[sizeof("255 (bogus)")];
377 snprintf(buf
, sizeof(buf
), pcp
<= 7 ? "%u" : "%u (bogus)", pcp
);
382 of10_bitmap_print(const struct tok
*t
, const uint32_t v
, const uint32_t u
) {
383 const char *sep
= " (";
388 for (; t
->s
!= NULL
; t
++)
390 printf("%s%s", sep
, t
->s
);
393 /* unassigned bits? */
394 printf(v
& u
? ") (bogus)" : ")");
397 static const u_char
*
398 of10_data_print(const u_char
*cp
, const u_char
*ep
, const u_int len
) {
402 printf("\n\t data (%u octets)", len
);
405 hex_and_ascii_print("\n\t ", cp
, len
);
409 printf(" [|openflow]");
413 /* Vendor ID is mandatory, data is optional. */
414 static const u_char
*
415 of10_vendor_data_print(const u_char
*cp
, const u_char
*ep
, const u_int len
) {
420 printf(", vendor 0x%08x", EXTRACT_32BITS(cp
));
423 return of10_data_print(cp
, ep
, len
- 4);
425 corrupt
: /* skip the undersized data */
426 printf(" (corrupt)");
430 printf(" [|openflow]");
434 /* [OF10] Section 5.2.1 */
435 static const u_char
*
436 of10_phy_ports_print(const u_char
*cp
, const u_char
*ep
, u_int len
) {
437 const u_char
*cp0
= cp
;
438 const u_int len0
= len
;
441 if (len
< sizeof(struct ofp_phy_port
))
445 printf("\n\t port_no %s", tok2str(ofpp_str
, "%u", EXTRACT_16BITS(cp
)));
448 TCHECK2(*cp
, OFP_ETH_ALEN
);
449 printf(", hw_addr %s", etheraddr_string(cp
));
452 TCHECK2(*cp
, OFP_MAX_PORT_NAME_LEN
);
454 fn_print(cp
, cp
+ OFP_MAX_PORT_NAME_LEN
);
456 cp
+= OFP_MAX_PORT_NAME_LEN
;
465 printf("\n\t config 0x%08x", EXTRACT_32BITS(cp
));
466 of10_bitmap_print(ofppc_bm
, EXTRACT_32BITS(cp
), OFPPC_U
);
470 printf("\n\t state 0x%08x", EXTRACT_32BITS(cp
));
471 of10_bitmap_print(ofpps_bm
, EXTRACT_32BITS(cp
), OFPPS_U
);
475 printf("\n\t curr 0x%08x", EXTRACT_32BITS(cp
));
476 of10_bitmap_print(ofppf_bm
, EXTRACT_32BITS(cp
), OFPPF_U
);
480 printf("\n\t advertised 0x%08x", EXTRACT_32BITS(cp
));
481 of10_bitmap_print(ofppf_bm
, EXTRACT_32BITS(cp
), OFPPF_U
);
485 printf("\n\t supported 0x%08x", EXTRACT_32BITS(cp
));
486 of10_bitmap_print(ofppf_bm
, EXTRACT_32BITS(cp
), OFPPF_U
);
490 printf("\n\t peer 0x%08x", EXTRACT_32BITS(cp
));
491 of10_bitmap_print(ofppf_bm
, EXTRACT_32BITS(cp
), OFPPF_U
);
494 len
-= sizeof(struct ofp_phy_port
);
498 corrupt
: /* skip the undersized trailing data */
499 printf(" (corrupt)");
503 printf(" [|openflow]");
507 /* [OF10] Section 5.2.2 */
508 static const u_char
*
509 of10_queue_props_print(const u_char
*cp
, const u_char
*ep
, u_int len
) {
510 const u_char
*cp0
= cp
;
511 const u_int len0
= len
;
512 uint16_t property
, plen
, rate
;
515 u_char plen_bogus
= 0, skip
= 0;
517 if (len
< sizeof(struct ofp_queue_prop_header
))
521 property
= EXTRACT_16BITS(cp
);
523 printf("\n\t property %s", tok2str(ofpqt_str
, "invalid (0x%04x)", property
));
526 plen
= EXTRACT_16BITS(cp
);
528 printf(", len %u", plen
);
529 if (plen
< sizeof(struct ofp_queue_prop_header
) || plen
> len
)
534 /* property-specific constraints and decoding */
537 plen_bogus
= plen
!= sizeof(struct ofp_queue_prop_header
);
540 plen_bogus
= plen
!= sizeof(struct ofp_queue_prop_min_rate
);
550 TCHECK2(*cp
, plen
- 4);
554 if (property
== OFPQT_MIN_RATE
) { /* the only case of property decoding */
557 rate
= EXTRACT_16BITS(cp
);
560 printf(", rate disabled");
562 printf(", rate %u.%u%%", rate
/ 10, rate
% 10);
572 corrupt
: /* skip the rest of queue properties */
573 printf(" (corrupt)");
577 printf(" [|openflow]");
582 static const u_char
*
583 of10_queues_print(const u_char
*cp
, const u_char
*ep
, u_int len
) {
584 const u_char
*cp0
= cp
;
585 const u_int len0
= len
;
589 if (len
< sizeof(struct ofp_packet_queue
))
593 printf("\n\t queue_id %u", EXTRACT_32BITS(cp
));
597 desclen
= EXTRACT_16BITS(cp
);
599 printf(", len %u", desclen
);
600 if (desclen
< sizeof(struct ofp_packet_queue
) || desclen
> len
)
607 TCHECK2(*cp
, desclen
- sizeof(struct ofp_packet_queue
));
608 cp
+= desclen
- sizeof(struct ofp_packet_queue
);
611 if (ep
== (cp
= of10_queue_props_print(cp
, ep
, desclen
- sizeof(struct ofp_packet_queue
))))
612 return ep
; /* end of snapshot */
618 corrupt
: /* skip the rest of queues */
619 printf(" (corrupt)");
623 printf(" [|openflow]");
627 /* [OF10] Section 5.2.3 */
628 static const u_char
*
629 of10_match_print(const char *pfx
, const u_char
*cp
, const u_char
*ep
) {
634 const char *field_name
;
638 wildcards
= EXTRACT_32BITS(cp
);
639 if (wildcards
& OFPFW_U
)
640 printf("%swildcards 0x%08x (bogus)", pfx
, wildcards
);
644 if (! (wildcards
& OFPFW_IN_PORT
))
645 printf("%smatch in_port %s", pfx
, tok2str(ofpp_str
, "%u", EXTRACT_16BITS(cp
)));
648 TCHECK2(*cp
, OFP_ETH_ALEN
);
649 if (! (wildcards
& OFPFW_DL_SRC
))
650 printf("%smatch dl_src %s", pfx
, etheraddr_string(cp
));
653 TCHECK2(*cp
, OFP_ETH_ALEN
);
654 if (! (wildcards
& OFPFW_DL_DST
))
655 printf("%smatch dl_dst %s", pfx
, etheraddr_string(cp
));
659 if (! (wildcards
& OFPFW_DL_VLAN
))
660 printf("%smatch dl_vlan %s", pfx
, vlan_str(EXTRACT_16BITS(cp
)));
664 if (! (wildcards
& OFPFW_DL_VLAN_PCP
))
665 printf("%smatch dl_vlan_pcp %s", pfx
, pcp_str(*cp
));
672 dl_type
= EXTRACT_16BITS(cp
);
674 if (! (wildcards
& OFPFW_DL_TYPE
))
675 printf("%smatch dl_type 0x%04x", pfx
, dl_type
);
678 if (! (wildcards
& OFPFW_NW_TOS
))
679 printf("%smatch nw_tos 0x%02x", pfx
, *cp
);
685 if (! (wildcards
& OFPFW_NW_PROTO
)) {
686 field_name
= ! (wildcards
& OFPFW_DL_TYPE
) && dl_type
== ETHERTYPE_ARP
687 ? "arp_opcode" : "nw_proto";
688 printf("%smatch %s %u", pfx
, field_name
, nw_proto
);
695 nw_bits
= (wildcards
& OFPFW_NW_SRC_MASK
) >> OFPFW_NW_SRC_SHIFT
;
697 printf("%smatch nw_src %s/%u", pfx
, ipaddr_string(cp
), 32 - nw_bits
);
701 nw_bits
= (wildcards
& OFPFW_NW_DST_MASK
) >> OFPFW_NW_DST_SHIFT
;
703 printf("%smatch nw_dst %s/%u", pfx
, ipaddr_string(cp
), 32 - nw_bits
);
707 if (! (wildcards
& OFPFW_TP_SRC
)) {
708 field_name
= ! (wildcards
& OFPFW_DL_TYPE
) && dl_type
== ETHERTYPE_IP
709 && ! (wildcards
& OFPFW_NW_PROTO
) && nw_proto
== IPPROTO_ICMP
710 ? "icmp_type" : "tp_src";
711 printf("%smatch %s %u", pfx
, field_name
, EXTRACT_16BITS(cp
));
716 if (! (wildcards
& OFPFW_TP_DST
)) {
717 field_name
= ! (wildcards
& OFPFW_DL_TYPE
) && dl_type
== ETHERTYPE_IP
718 && ! (wildcards
& OFPFW_NW_PROTO
) && nw_proto
== IPPROTO_ICMP
719 ? "icmp_code" : "tp_dst";
720 printf("%smatch %s %u", pfx
, field_name
, EXTRACT_16BITS(cp
));
725 printf(" [|openflow]");
729 /* [OF10] Section 5.2.4 */
730 static const u_char
*
731 of10_actions_print(const char *pfx
, const u_char
*cp
, const u_char
*ep
,
733 const u_char
*cp0
= cp
;
734 const u_int len0
= len
;
735 uint16_t type
, alen
, output_port
;
738 u_char alen_bogus
= 0, skip
= 0;
740 if (len
< sizeof(struct ofp_action_header
))
744 type
= EXTRACT_16BITS(cp
);
746 printf("%saction type %s", pfx
, tok2str(ofpat_str
, "invalid (0x%04x)", type
));
749 alen
= EXTRACT_16BITS(cp
);
751 printf(", len %u", alen
);
752 /* On action size underrun/overrun skip the rest of the action list. */
753 if (alen
< sizeof(struct ofp_action_header
) || alen
> len
)
755 /* On action size inappropriate for the given type or invalid type just skip
756 * the current action, as the basic length constraint has been met. */
759 case OFPAT_SET_VLAN_VID
:
760 case OFPAT_SET_VLAN_PCP
:
761 case OFPAT_STRIP_VLAN
:
762 case OFPAT_SET_NW_SRC
:
763 case OFPAT_SET_NW_DST
:
764 case OFPAT_SET_NW_TOS
:
765 case OFPAT_SET_TP_SRC
:
766 case OFPAT_SET_TP_DST
:
767 alen_bogus
= alen
!= 8;
769 case OFPAT_SET_DL_SRC
:
770 case OFPAT_SET_DL_DST
:
772 alen_bogus
= alen
!= 16;
775 alen_bogus
= alen
% 8 != 0; /* already >= 8 so far */
785 TCHECK2(*cp
, alen
- 4);
789 /* OK to decode the rest of the action structure */
794 output_port
= EXTRACT_16BITS(cp
);
796 printf(", port %s", tok2str(ofpp_str
, "%u", output_port
));
799 if (output_port
== OFPP_CONTROLLER
)
800 printf(", max_len %u", EXTRACT_16BITS(cp
));
803 case OFPAT_SET_VLAN_VID
:
806 printf(", vlan_vid %s", vlan_str(EXTRACT_16BITS(cp
)));
812 case OFPAT_SET_VLAN_PCP
:
815 printf(", vlan_pcp %s", pcp_str(*cp
));
821 case OFPAT_SET_DL_SRC
:
822 case OFPAT_SET_DL_DST
:
824 TCHECK2(*cp
, OFP_ETH_ALEN
);
825 printf(", dl_addr %s", etheraddr_string(cp
));
831 case OFPAT_SET_NW_SRC
:
832 case OFPAT_SET_NW_DST
:
835 printf(", nw_addr %s", ipaddr_string(cp
));
838 case OFPAT_SET_NW_TOS
:
841 printf(", nw_tos 0x%02x", *cp
);
847 case OFPAT_SET_TP_SRC
:
848 case OFPAT_SET_TP_DST
:
851 printf(", tp_port %u", EXTRACT_16BITS(cp
));
860 printf(", port %s", tok2str(ofpp_str
, "%u", EXTRACT_16BITS(cp
)));
867 printf(", queue_id %s", tok2str(ofpq_str
, "%u", EXTRACT_32BITS(cp
)));
871 if (ep
== (cp
= of10_vendor_data_print(cp
, ep
, alen
- 4)))
872 return ep
; /* end of snapshot */
874 case OFPAT_STRIP_VLAN
:
885 corrupt
: /* skip the rest of actions */
886 printf(" (corrupt)");
890 printf(" [|openflow]");
894 /* [OF10] Section 5.3.1 */
895 static const u_char
*
896 of10_features_reply_print(const u_char
*cp
, const u_char
*ep
, const u_int len
) {
899 printf("\n\t dpid 0x%016" PRIx64
, EXTRACT_64BITS(cp
));
903 printf(", n_buffers %u", EXTRACT_32BITS(cp
));
907 printf(", n_tables %u", *cp
);
914 printf("\n\t capabilities 0x%08x", EXTRACT_32BITS(cp
));
915 of10_bitmap_print(ofp_capabilities_bm
, EXTRACT_32BITS(cp
), OFPCAP_U
);
919 printf("\n\t actions 0x%08x", EXTRACT_32BITS(cp
));
920 of10_bitmap_print(ofpat_bm
, EXTRACT_32BITS(cp
), OFPAT_U
);
923 return of10_phy_ports_print(cp
, ep
, len
- sizeof(struct ofp_switch_features
));
926 printf(" [|openflow]");
930 /* [OF10] Section 5.3.3 */
931 static const u_char
*
932 of10_flow_mod_print(const u_char
*cp
, const u_char
*ep
, const u_int len
) {
936 if (ep
== (cp
= of10_match_print("\n\t ", cp
, ep
)))
937 return ep
; /* end of snapshot */
940 printf("\n\t cookie 0x%016" PRIx64
, EXTRACT_64BITS(cp
));
944 command
= EXTRACT_16BITS(cp
);
945 printf(", command %s", tok2str(ofpfc_str
, "invalid (0x%04x)", command
));
949 if (EXTRACT_16BITS(cp
))
950 printf(", idle_timeout %u", EXTRACT_16BITS(cp
));
954 if (EXTRACT_16BITS(cp
))
955 printf(", hard_timeout %u", EXTRACT_16BITS(cp
));
959 if (EXTRACT_16BITS(cp
))
960 printf(", priority %u", EXTRACT_16BITS(cp
));
964 if (command
== OFPFC_ADD
|| command
== OFPFC_MODIFY
||
965 command
== OFPFC_MODIFY_STRICT
)
966 printf(", buffer_id %s", tok2str(bufferid_str
, "0x%08x", EXTRACT_32BITS(cp
)));
970 if (command
== OFPFC_DELETE
|| command
== OFPFC_DELETE_STRICT
)
971 printf(", out_port %s", tok2str(ofpp_str
, "%u", EXTRACT_16BITS(cp
)));
975 printf(", flags 0x%04x", EXTRACT_16BITS(cp
));
976 of10_bitmap_print(ofpff_bm
, EXTRACT_16BITS(cp
), OFPFF_U
);
979 return of10_actions_print("\n\t ", cp
, ep
, len
- sizeof(struct ofp_flow_mod
));
982 printf(" [|openflow]");
987 static const u_char
*
988 of10_port_mod_print(const u_char
*cp
, const u_char
*ep
) {
991 printf("\n\t port_no %s", tok2str(ofpp_str
, "%u", EXTRACT_16BITS(cp
)));
994 TCHECK2(*cp
, OFP_ETH_ALEN
);
995 printf(", hw_addr %s", etheraddr_string(cp
));
999 printf("\n\t config 0x%08x", EXTRACT_32BITS(cp
));
1000 of10_bitmap_print(ofppc_bm
, EXTRACT_32BITS(cp
), OFPPC_U
);
1004 printf("\n\t mask 0x%08x", EXTRACT_32BITS(cp
));
1005 of10_bitmap_print(ofppc_bm
, EXTRACT_32BITS(cp
), OFPPC_U
);
1009 printf("\n\t advertise 0x%08x", EXTRACT_32BITS(cp
));
1010 of10_bitmap_print(ofppf_bm
, EXTRACT_32BITS(cp
), OFPPF_U
);
1017 printf(" [|openflow]");
1021 /* [OF10] Section 5.3.5 */
1022 static const u_char
*
1023 of10_stats_request_print(const u_char
*cp
, const u_char
*ep
, u_int len
) {
1024 const u_char
*cp0
= cp
;
1025 const u_int len0
= len
;
1030 type
= EXTRACT_16BITS(cp
);
1032 printf("\n\t type %s", tok2str(ofpst_str
, "invalid (0x%04x)", type
));
1035 printf(", flags 0x%04x", EXTRACT_16BITS(cp
));
1036 if (EXTRACT_16BITS(cp
))
1039 /* type-specific body of one of fixed lengths */
1040 len
-= sizeof(struct ofp_stats_request
);
1048 case OFPST_AGGREGATE
:
1049 if (len
!= sizeof(struct ofp_flow_stats_request
))
1052 if (ep
== (cp
= of10_match_print("\n\t ", cp
, ep
)))
1053 return ep
; /* end of snapshot */
1056 printf("\n\t table_id %s", tok2str(tableid_str
, "%u", *cp
));
1063 printf(", out_port %s", tok2str(ofpp_str
, "%u", EXTRACT_16BITS(cp
)));
1066 if (len
!= sizeof(struct ofp_port_stats_request
))
1070 printf("\n\t port_no %s", tok2str(ofpp_str
, "%u", EXTRACT_16BITS(cp
)));
1076 if (len
!= sizeof(struct ofp_queue_stats_request
))
1080 printf("\n\t port_no %s", tok2str(ofpp_str
, "%u", EXTRACT_16BITS(cp
)));
1087 printf(", queue_id %s", tok2str(ofpq_str
, "%u", EXTRACT_32BITS(cp
)));
1090 return of10_vendor_data_print(cp
, ep
, len
);
1094 corrupt
: /* skip the message body */
1095 printf(" (corrupt)");
1096 TCHECK2(*cp0
, len0
);
1099 printf(" [|openflow]");
1104 static const u_char
*
1105 of10_desc_stats_reply_print(const u_char
*cp
, const u_char
*ep
, const u_int len
) {
1106 if (len
!= sizeof(struct ofp_desc_stats
))
1109 TCHECK2(*cp
, DESC_STR_LEN
);
1110 printf("\n\t mfr_desc '");
1111 fn_print(cp
, cp
+ DESC_STR_LEN
);
1115 TCHECK2(*cp
, DESC_STR_LEN
);
1116 printf("\n\t hw_desc '");
1117 fn_print(cp
, cp
+ DESC_STR_LEN
);
1121 TCHECK2(*cp
, DESC_STR_LEN
);
1122 printf("\n\t sw_desc '");
1123 fn_print(cp
, cp
+ DESC_STR_LEN
);
1127 TCHECK2(*cp
, SERIAL_NUM_LEN
);
1128 printf("\n\t serial_num '");
1129 fn_print(cp
, cp
+ SERIAL_NUM_LEN
);
1131 cp
+= SERIAL_NUM_LEN
;
1133 TCHECK2(*cp
, DESC_STR_LEN
);
1134 printf("\n\t dp_desc '");
1135 fn_print(cp
, cp
+ DESC_STR_LEN
);
1137 return cp
+ DESC_STR_LEN
;
1139 corrupt
: /* skip the message body */
1140 printf(" (corrupt)");
1144 printf(" [|openflow]");
1149 static const u_char
*
1150 of10_flow_stats_reply_print(const u_char
*cp
, const u_char
*ep
, u_int len
) {
1151 const u_char
*cp0
= cp
;
1152 const u_int len0
= len
;
1156 if (len
< sizeof(struct ofp_flow_stats
))
1160 entry_len
= EXTRACT_16BITS(cp
);
1161 printf("\n\t length %u", entry_len
);
1162 if (entry_len
< sizeof(struct ofp_flow_stats
) || entry_len
> len
)
1167 printf(", table_id %s", tok2str(tableid_str
, "%u", *cp
));
1173 if (ep
== (cp
= of10_match_print("\n\t ", cp
, ep
)))
1174 return ep
; /* end of snapshot */
1177 printf("\n\t duration_sec %u", EXTRACT_32BITS(cp
));
1181 printf(", duration_nsec %u", EXTRACT_32BITS(cp
));
1185 printf(", priority %u", EXTRACT_16BITS(cp
));
1189 printf(", idle_timeout %u", EXTRACT_16BITS(cp
));
1193 printf(", hard_timeout %u", EXTRACT_16BITS(cp
));
1200 printf(", cookie 0x%016" PRIx64
, EXTRACT_64BITS(cp
));
1204 printf(", packet_count %" PRIu64
, EXTRACT_64BITS(cp
));
1208 printf(", byte_count %" PRIu64
, EXTRACT_64BITS(cp
));
1211 if (ep
== (cp
= of10_actions_print("\n\t ", cp
, ep
, entry_len
- sizeof(struct ofp_flow_stats
))))
1212 return ep
; /* end of snapshot */
1218 corrupt
: /* skip the rest of flow statistics entries */
1219 printf(" (corrupt)");
1220 TCHECK2(*cp0
, len0
);
1223 printf(" [|openflow]");
1228 static const u_char
*
1229 of10_aggregate_stats_reply_print(const u_char
*cp
, const u_char
*ep
,
1231 if (len
!= sizeof(struct ofp_aggregate_stats_reply
))
1235 printf("\n\t packet_count %" PRIu64
, EXTRACT_64BITS(cp
));
1239 printf(", byte_count %" PRIu64
, EXTRACT_64BITS(cp
));
1243 printf(", flow_count %u", EXTRACT_32BITS(cp
));
1249 corrupt
: /* skip the message body */
1250 printf(" (corrupt)");
1254 printf(" [|openflow]");
1259 static const u_char
*
1260 of10_table_stats_reply_print(const u_char
*cp
, const u_char
*ep
, u_int len
) {
1261 const u_char
*cp0
= cp
;
1262 const u_int len0
= len
;
1265 if (len
< sizeof(struct ofp_table_stats
))
1269 printf("\n\t table_id %s", tok2str(tableid_str
, "%u", *cp
));
1275 TCHECK2(*cp
, OFP_MAX_TABLE_NAME_LEN
);
1277 fn_print(cp
, cp
+ OFP_MAX_TABLE_NAME_LEN
);
1279 cp
+= OFP_MAX_TABLE_NAME_LEN
;
1282 printf("\n\t wildcards 0x%08x", EXTRACT_32BITS(cp
));
1283 of10_bitmap_print(ofpfw_bm
, EXTRACT_32BITS(cp
), OFPFW_U
);
1287 printf("\n\t max_entries %u", EXTRACT_32BITS(cp
));
1291 printf(", active_count %u", EXTRACT_32BITS(cp
));
1295 printf(", lookup_count %" PRIu64
, EXTRACT_64BITS(cp
));
1299 printf(", matched_count %" PRIu64
, EXTRACT_64BITS(cp
));
1302 len
-= sizeof(struct ofp_table_stats
);
1306 corrupt
: /* skip the undersized trailing data */
1307 printf(" (corrupt)");
1308 TCHECK2(*cp0
, len0
);
1311 printf(" [|openflow]");
1316 static const u_char
*
1317 of10_port_stats_reply_print(const u_char
*cp
, const u_char
*ep
, u_int len
) {
1318 const u_char
*cp0
= cp
;
1319 const u_int len0
= len
;
1322 if (len
< sizeof(struct ofp_port_stats
))
1326 printf("\n\t port_no %s", tok2str(ofpp_str
, "%u", EXTRACT_16BITS(cp
)));
1329 TCHECK2(*cp
, sizeof(struct ofp_port_stats
) - 2);
1330 cp
+= sizeof(struct ofp_port_stats
) - 2;
1338 printf(", rx_packets %" PRIu64
, EXTRACT_64BITS(cp
));
1342 printf(", tx_packets %" PRIu64
, EXTRACT_64BITS(cp
));
1346 printf(", rx_bytes %" PRIu64
, EXTRACT_64BITS(cp
));
1350 printf(", tx_bytes %" PRIu64
, EXTRACT_64BITS(cp
));
1354 printf(", rx_dropped %" PRIu64
, EXTRACT_64BITS(cp
));
1358 printf(", tx_dropped %" PRIu64
, EXTRACT_64BITS(cp
));
1362 printf(", rx_errors %" PRIu64
, EXTRACT_64BITS(cp
));
1366 printf(", tx_errors %" PRIu64
, EXTRACT_64BITS(cp
));
1370 printf(", rx_frame_err %" PRIu64
, EXTRACT_64BITS(cp
));
1374 printf(", rx_over_err %" PRIu64
, EXTRACT_64BITS(cp
));
1378 printf(", rx_crc_err %" PRIu64
, EXTRACT_64BITS(cp
));
1382 printf(", collisions %" PRIu64
, EXTRACT_64BITS(cp
));
1385 len
-= sizeof(struct ofp_port_stats
);
1389 corrupt
: /* skip the undersized trailing data */
1390 printf(" (corrupt)");
1391 TCHECK2(*cp0
, len0
);
1394 printf(" [|openflow]");
1399 static const u_char
*
1400 of10_queue_stats_reply_print(const u_char
*cp
, const u_char
*ep
, u_int len
) {
1401 const u_char
*cp0
= cp
;
1402 const u_int len0
= len
;
1405 if (len
< sizeof(struct ofp_queue_stats
))
1409 printf("\n\t port_no %s", tok2str(ofpp_str
, "%u", EXTRACT_16BITS(cp
)));
1416 printf(", queue_id %u", EXTRACT_32BITS(cp
));
1420 printf(", tx_bytes %" PRIu64
, EXTRACT_64BITS(cp
));
1424 printf(", tx_packets %" PRIu64
, EXTRACT_64BITS(cp
));
1428 printf(", tx_errors %" PRIu64
, EXTRACT_64BITS(cp
));
1431 len
-= sizeof(struct ofp_port_stats
);
1435 corrupt
: /* skip the undersized trailing data */
1436 printf(" (corrupt)");
1437 TCHECK2(*cp0
, len0
);
1440 printf(" [|openflow]");
1445 static const u_char
*
1446 of10_stats_reply_print(const u_char
*cp
, const u_char
*ep
, const u_int len
) {
1447 const u_char
*cp0
= cp
;
1452 type
= EXTRACT_16BITS(cp
);
1453 printf("\n\t type %s", tok2str(ofpst_str
, "invalid (0x%04x)", type
));
1457 printf(", flags 0x%04x", EXTRACT_16BITS(cp
));
1458 of10_bitmap_print(ofpsf_reply_bm
, EXTRACT_16BITS(cp
), OFPSF_REPLY_U
);
1462 const u_char
*(*decoder
)(const u_char
*, const u_char
*, u_int
) =
1463 type
== OFPST_DESC
? of10_desc_stats_reply_print
:
1464 type
== OFPST_FLOW
? of10_flow_stats_reply_print
:
1465 type
== OFPST_AGGREGATE
? of10_aggregate_stats_reply_print
:
1466 type
== OFPST_TABLE
? of10_table_stats_reply_print
:
1467 type
== OFPST_PORT
? of10_port_stats_reply_print
:
1468 type
== OFPST_QUEUE
? of10_queue_stats_reply_print
:
1469 type
== OFPST_VENDOR
? of10_vendor_data_print
:
1471 if (decoder
!= NULL
)
1472 return decoder(cp
, ep
, len
- sizeof(struct ofp_stats_reply
));
1478 printf(" [|openflow]");
1482 /* [OF10] Section 5.3.6 */
1483 static const u_char
*
1484 of10_packet_out_print(const u_char
*cp
, const u_char
*ep
, const u_int len
) {
1485 const u_char
*cp0
= cp
;
1486 const u_int len0
= len
;
1487 uint16_t actions_len
;
1491 printf("\n\t buffer_id 0x%08x", EXTRACT_32BITS(cp
));
1495 printf(", in_port %s", tok2str(ofpp_str
, "%u", EXTRACT_16BITS(cp
)));
1499 actions_len
= EXTRACT_16BITS(cp
);
1501 if (actions_len
> len
- sizeof(struct ofp_packet_out
))
1504 if (ep
== (cp
= of10_actions_print("\n\t ", cp
, ep
, actions_len
)))
1505 return ep
; /* end of snapshot */
1507 return of10_data_print(cp
, ep
, len
- sizeof(struct ofp_packet_out
) - actions_len
);
1509 corrupt
: /* skip the rest of the message body */
1510 printf(" (corrupt)");
1511 TCHECK2(*cp0
, len0
);
1514 printf(" [|openflow]");
1518 /* [OF10] Section 5.4.1 */
1519 static const u_char
*
1520 of10_packet_in_print(const u_char
*cp
, const u_char
*ep
, const u_int len
) {
1523 printf("\n\t buffer_id %s", tok2str(bufferid_str
, "0x%08x", EXTRACT_32BITS(cp
)));
1527 printf(", total_len %u", EXTRACT_16BITS(cp
));
1531 printf(", in_port %s", tok2str(ofpp_str
, "%u", EXTRACT_16BITS(cp
)));
1535 printf(", reason %s", tok2str(ofpr_str
, "invalid (0x%02x)", *cp
));
1541 /* 2 mock octets count in sizeof() but not in len */
1542 return of10_data_print(cp
, ep
, len
- (sizeof(struct ofp_packet_in
) - 2));
1545 printf(" [|openflow]");
1549 /* [OF10] Section 5.4.2 */
1550 static const u_char
*
1551 of10_flow_removed_print(const u_char
*cp
, const u_char
*ep
) {
1553 if (ep
== (cp
= of10_match_print("\n\t ", cp
, ep
)))
1554 return ep
; /* end of snapshot */
1557 printf("\n\t cookie 0x%016" PRIx64
, EXTRACT_64BITS(cp
));
1561 if (EXTRACT_16BITS(cp
))
1562 printf(", priority %u", EXTRACT_16BITS(cp
));
1566 printf(", reason %s", tok2str(ofprr_str
, "unknown (0x%02x)", *cp
));
1573 printf(", duration_sec %u", EXTRACT_32BITS(cp
));
1577 printf(", duration_nsec %u", EXTRACT_32BITS(cp
));
1581 if (EXTRACT_16BITS(cp
))
1582 printf(", idle_timeout %u", EXTRACT_16BITS(cp
));
1589 printf(", packet_count %" PRIu64
, EXTRACT_64BITS(cp
));
1593 printf(", byte_count %" PRIu64
, EXTRACT_64BITS(cp
));
1597 printf(" [|openflow]");
1601 /* [OF10] Section 5.4.4 */
1602 static const u_char
*
1603 of10_error_print(const u_char
*cp
, const u_char
*ep
, const u_int len
) {
1605 const struct tok
*code_str
;
1609 type
= EXTRACT_16BITS(cp
);
1611 printf("\n\t type %s", tok2str(ofpet_str
, "invalid (0x%04x)", type
));
1615 type
== OFPET_HELLO_FAILED
? ofphfc_str
:
1616 type
== OFPET_BAD_REQUEST
? ofpbrc_str
:
1617 type
== OFPET_BAD_ACTION
? ofpbac_str
:
1618 type
== OFPET_FLOW_MOD_FAILED
? ofpfmfc_str
:
1619 type
== OFPET_PORT_MOD_FAILED
? ofppmfc_str
:
1620 type
== OFPET_QUEUE_OP_FAILED
? ofpqofc_str
:
1622 printf(", code %s", tok2str(code_str
, "invalid (0x%04x)", EXTRACT_16BITS(cp
)));
1625 return of10_data_print(cp
, ep
, len
- sizeof(struct ofp_error_msg
));
1628 printf(" [|openflow]");
1633 of10_header_body_print(const u_char
*cp
, const u_char
*ep
, const uint8_t type
,
1634 const uint16_t len
, const uint32_t xid
) {
1635 const u_char
*cp0
= cp
;
1636 const u_int len0
= len
;
1637 /* Thus far message length is not less than the basic header size, but most
1638 * message types have additional assorted constraints on the length. Wherever
1639 * possible, check that message length meets the constraint, in remaining
1640 * cases check that the length is OK to begin decoding and leave any final
1641 * verification up to a lower-layer function. When the current message is
1642 * corrupt, proceed to the next message. */
1644 /* [OF10] Section 5.1 */
1645 printf("\n\tversion 1.0, type %s, length %u, xid 0x%08x",
1646 tok2str(ofpt_str
, "invalid (0x%02x)", type
), len
, xid
);
1648 /* OpenFlow header only. */
1649 case OFPT_FEATURES_REQUEST
: /* [OF10] Section 5.3.1 */
1650 case OFPT_GET_CONFIG_REQUEST
: /* [OF10] Section 5.3.2 */
1651 case OFPT_BARRIER_REQUEST
: /* [OF10] Section 5.3.7 */
1652 case OFPT_BARRIER_REPLY
: /* ibid */
1653 if (len
!= sizeof(struct ofp_header
))
1657 /* OpenFlow header and fixed-size message body. */
1658 case OFPT_SET_CONFIG
: /* [OF10] Section 5.3.2 */
1659 case OFPT_GET_CONFIG_REPLY
: /* ibid */
1660 if (len
!= sizeof(struct ofp_switch_config
))
1666 printf("\n\t flags %s", tok2str(ofp_config_str
, "invalid (0x%04x)", EXTRACT_16BITS(cp
)));
1670 printf(", miss_send_len %u", EXTRACT_16BITS(cp
));
1673 if (len
!= sizeof(struct ofp_port_mod
))
1677 return of10_port_mod_print(cp
, ep
);
1678 case OFPT_QUEUE_GET_CONFIG_REQUEST
: /* [OF10] Section 5.3.4 */
1679 if (len
!= sizeof(struct ofp_queue_get_config_request
))
1685 printf("\n\t port_no %s", tok2str(ofpp_str
, "%u", EXTRACT_16BITS(cp
)));
1690 case OFPT_FLOW_REMOVED
:
1691 if (len
!= sizeof(struct ofp_flow_removed
))
1695 return of10_flow_removed_print(cp
, ep
);
1696 case OFPT_PORT_STATUS
: /* [OF10] Section 5.4.3 */
1697 if (len
!= sizeof(struct ofp_port_status
))
1703 printf("\n\t reason %s", tok2str(ofppr_str
, "invalid (0x%02x)", *cp
));
1709 return of10_phy_ports_print(cp
, ep
, sizeof(struct ofp_phy_port
));
1711 /* OpenFlow header, fixed-size message body and n * fixed-size data units. */
1712 case OFPT_FEATURES_REPLY
:
1713 if (len
< sizeof(struct ofp_switch_features
))
1717 return of10_features_reply_print(cp
, ep
, len
);
1719 /* OpenFlow header and variable-size data. */
1720 case OFPT_HELLO
: /* [OF10] Section 5.5.1 */
1721 case OFPT_ECHO_REQUEST
: /* [OF10] Section 5.5.2 */
1722 case OFPT_ECHO_REPLY
: /* [OF10] Section 5.5.3 */
1725 return of10_data_print(cp
, ep
, len
- sizeof(struct ofp_header
));
1727 /* OpenFlow header, fixed-size message body and variable-size data. */
1729 if (len
< sizeof(struct ofp_error_msg
))
1733 return of10_error_print(cp
, ep
, len
);
1735 /* [OF10] Section 5.5.4 */
1736 if (len
< sizeof(struct ofp_vendor_header
))
1740 return of10_vendor_data_print(cp
, ep
, len
- sizeof(struct ofp_header
));
1741 case OFPT_PACKET_IN
:
1742 /* 2 mock octets count in sizeof() but not in len */
1743 if (len
< sizeof(struct ofp_packet_in
) - 2)
1747 return of10_packet_in_print(cp
, ep
, len
);
1749 /* a. OpenFlow header. */
1750 /* b. OpenFlow header and one of the fixed-size message bodies. */
1751 /* c. OpenFlow header, fixed-size message body and variable-size data. */
1752 case OFPT_STATS_REQUEST
:
1753 if (len
< sizeof(struct ofp_stats_request
))
1757 return of10_stats_request_print(cp
, ep
, len
);
1759 /* a. OpenFlow header and fixed-size message body. */
1760 /* b. OpenFlow header and n * fixed-size data units. */
1761 /* c. OpenFlow header and n * variable-size data units. */
1762 /* d. OpenFlow header, fixed-size message body and variable-size data. */
1763 case OFPT_STATS_REPLY
:
1764 if (len
< sizeof(struct ofp_stats_reply
))
1768 return of10_stats_reply_print(cp
, ep
, len
);
1770 /* OpenFlow header and n * variable-size data units and variable-size data. */
1771 case OFPT_PACKET_OUT
:
1772 if (len
< sizeof(struct ofp_packet_out
))
1776 return of10_packet_out_print(cp
, ep
, len
);
1778 /* OpenFlow header, fixed-size message body and n * variable-size data units. */
1780 if (len
< sizeof(struct ofp_flow_mod
))
1784 return of10_flow_mod_print(cp
, ep
, len
);
1786 /* OpenFlow header, fixed-size message body and n * variable-size data units. */
1787 case OFPT_QUEUE_GET_CONFIG_REPLY
: /* [OF10] Section 5.3.4 */
1788 if (len
< sizeof(struct ofp_queue_get_config_reply
))
1794 printf("\n\t port_no %s", tok2str(ofpp_str
, "%u", EXTRACT_16BITS(cp
)));
1800 return of10_queues_print(cp
, ep
, len
- sizeof(struct ofp_queue_get_config_reply
));
1801 } /* switch (type) */
1804 corrupt
: /* skip the message body */
1805 printf(" (corrupt)");
1807 TCHECK2(*cp0
, len0
- sizeof(struct ofp_header
));
1808 return cp0
+ len0
- sizeof(struct ofp_header
);
1810 printf(" [|openflow]");