xref: /freebsd/contrib/tcpdump/print-openflow-1.0.c (revision 0a7e5f1f02aad2ff5fff1c60f44c6975fd07e1d9)
13c602fabSXin LI /*
23c602fabSXin LI  * This module implements decoding of OpenFlow protocol version 1.0 (wire
33c602fabSXin LI  * protocol 0x01). The decoder implements terse (default), detailed (-v) and
43c602fabSXin LI  * full (-vv) output formats and, as much as each format implies, detects and
53c602fabSXin LI  * tries to work around sizing anomalies inside the messages. The decoder marks
63c602fabSXin LI  * up bogus values of selected message fields and decodes partially captured
73c602fabSXin LI  * messages up to the snapshot end. It is based on the specification below:
83c602fabSXin LI  *
9ee67461eSJoseph Mingrone  * [OF10] https://www.opennetworking.org/wp-content/uploads/2013/04/openflow-spec-v1.0.0.pdf
103c602fabSXin LI  *
11ee67461eSJoseph Mingrone  * Most functions in this file take the following arguments:
128bdc5a62SPatrick Kelsey  * * cp -- the pointer to the first octet to decode
13ee67461eSJoseph Mingrone  * * len -- the declared length of the structure to decode
14ee67461eSJoseph Mingrone  * The convention is that a printer function returns iff the given structure is
15ee67461eSJoseph Mingrone  * completely within the packet buffer; otherwise it processes the part that is
16ee67461eSJoseph Mingrone  * within the buffer, sooner of later takes the "truncated packet" shortcut via
17ee67461eSJoseph Mingrone  * longjmp() and never returns. With that in mind, the function may return
18ee67461eSJoseph Mingrone  * without printing the structure completely if it is invalid or the ndo_vflag
19ee67461eSJoseph Mingrone  * value is not high enough. This way the calling function can try to decode
20ee67461eSJoseph Mingrone  * the next data item.
218bdc5a62SPatrick Kelsey  *
223c602fabSXin LI  * Decoding of Ethernet frames nested in OFPT_PACKET_IN and OFPT_PACKET_OUT
233c602fabSXin LI  * messages is done only when the verbosity level set by command-line argument
243c602fabSXin LI  * is "-vvv" or higher. In that case the verbosity level is temporarily
253c602fabSXin LI  * decremented by 3 during the nested frame decoding. For example, running
263c602fabSXin LI  * tcpdump with "-vvvv" will do full decoding of OpenFlow and "-v" decoding of
273c602fabSXin LI  * the nested frames.
283c602fabSXin LI  *
298bdc5a62SPatrick Kelsey  * Partial decoding of Big Switch Networks vendor extensions is done after the
308bdc5a62SPatrick Kelsey  * oftest (OpenFlow Testing Framework) and Loxigen (library generator) source
318bdc5a62SPatrick Kelsey  * code.
328bdc5a62SPatrick Kelsey  *
333c602fabSXin LI  *
343c602fabSXin LI  * Copyright (c) 2013 The TCPDUMP project
353c602fabSXin LI  * All rights reserved.
363c602fabSXin LI  *
373c602fabSXin LI  * Redistribution and use in source and binary forms, with or without
383c602fabSXin LI  * modification, are permitted provided that the following conditions
393c602fabSXin LI  * are met:
403c602fabSXin LI  * 1. Redistributions of source code must retain the above copyright
413c602fabSXin LI  *    notice, this list of conditions and the following disclaimer.
423c602fabSXin LI  * 2. Redistributions in binary form must reproduce the above copyright
433c602fabSXin LI  *    notice, this list of conditions and the following disclaimer in the
443c602fabSXin LI  *    documentation and/or other materials provided with the distribution.
453c602fabSXin LI  *
463c602fabSXin LI  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
473c602fabSXin LI  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
483c602fabSXin LI  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
493c602fabSXin LI  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
503c602fabSXin LI  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
513c602fabSXin LI  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
523c602fabSXin LI  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
533c602fabSXin LI  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
543c602fabSXin LI  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
553c602fabSXin LI  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
563c602fabSXin LI  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
573c602fabSXin LI  * POSSIBILITY OF SUCH DAMAGE.
583c602fabSXin LI  */
593c602fabSXin LI 
603340d773SGleb Smirnoff /* \summary: OpenFlow protocol version 1.0 printer */
613340d773SGleb Smirnoff 
62ee67461eSJoseph Mingrone #include <config.h>
633c602fabSXin LI 
64ee67461eSJoseph Mingrone #include "netdissect-stdinc.h"
653c602fabSXin LI 
66ee67461eSJoseph Mingrone #define ND_LONGJMP_FROM_TCHECK
673340d773SGleb Smirnoff #include "netdissect.h"
683c602fabSXin LI #include "extract.h"
693c602fabSXin LI #include "addrtoname.h"
703c602fabSXin LI #include "ethertype.h"
713c602fabSXin LI #include "ipproto.h"
728bdc5a62SPatrick Kelsey #include "oui.h"
733c602fabSXin LI #include "openflow.h"
743c602fabSXin LI 
753c602fabSXin LI 
763c602fabSXin LI #define OFPT_HELLO                    0x00
773c602fabSXin LI #define OFPT_ERROR                    0x01
783c602fabSXin LI #define OFPT_ECHO_REQUEST             0x02
793c602fabSXin LI #define OFPT_ECHO_REPLY               0x03
803c602fabSXin LI #define OFPT_VENDOR                   0x04
813c602fabSXin LI #define OFPT_FEATURES_REQUEST         0x05
823c602fabSXin LI #define OFPT_FEATURES_REPLY           0x06
833c602fabSXin LI #define OFPT_GET_CONFIG_REQUEST       0x07
843c602fabSXin LI #define OFPT_GET_CONFIG_REPLY         0x08
853c602fabSXin LI #define OFPT_SET_CONFIG               0x09
863c602fabSXin LI #define OFPT_PACKET_IN                0x0a
873c602fabSXin LI #define OFPT_FLOW_REMOVED             0x0b
883c602fabSXin LI #define OFPT_PORT_STATUS              0x0c
893c602fabSXin LI #define OFPT_PACKET_OUT               0x0d
903c602fabSXin LI #define OFPT_FLOW_MOD                 0x0e
913c602fabSXin LI #define OFPT_PORT_MOD                 0x0f
923c602fabSXin LI #define OFPT_STATS_REQUEST            0x10
933c602fabSXin LI #define OFPT_STATS_REPLY              0x11
943c602fabSXin LI #define OFPT_BARRIER_REQUEST          0x12
953c602fabSXin LI #define OFPT_BARRIER_REPLY            0x13
963c602fabSXin LI #define OFPT_QUEUE_GET_CONFIG_REQUEST 0x14
973c602fabSXin LI #define OFPT_QUEUE_GET_CONFIG_REPLY   0x15
98ee67461eSJoseph Mingrone #define OFPT_MAX                      OFPT_QUEUE_GET_CONFIG_REPLY
993c602fabSXin LI 
100ee67461eSJoseph Mingrone #define OFPPC_PORT_DOWN    (1U <<0)
101ee67461eSJoseph Mingrone #define OFPPC_NO_STP       (1U <<1)
102ee67461eSJoseph Mingrone #define OFPPC_NO_RECV      (1U <<2)
103ee67461eSJoseph Mingrone #define OFPPC_NO_RECV_STP  (1U <<3)
104ee67461eSJoseph Mingrone #define OFPPC_NO_FLOOD     (1U <<4)
105ee67461eSJoseph Mingrone #define OFPPC_NO_FWD       (1U <<5)
106ee67461eSJoseph Mingrone #define OFPPC_NO_PACKET_IN (1U <<6)
1073c602fabSXin LI static const struct tok ofppc_bm[] = {
1083c602fabSXin LI 	{ OFPPC_PORT_DOWN,    "PORT_DOWN"    },
1093c602fabSXin LI 	{ OFPPC_NO_STP,       "NO_STP"       },
1103c602fabSXin LI 	{ OFPPC_NO_RECV,      "NO_RECV"      },
1113c602fabSXin LI 	{ OFPPC_NO_RECV_STP,  "NO_RECV_STP"  },
1123c602fabSXin LI 	{ OFPPC_NO_FLOOD,     "NO_FLOOD"     },
1133c602fabSXin LI 	{ OFPPC_NO_FWD,       "NO_FWD"       },
1143c602fabSXin LI 	{ OFPPC_NO_PACKET_IN, "NO_PACKET_IN" },
1153c602fabSXin LI 	{ 0, NULL }
1163c602fabSXin LI };
1173c602fabSXin LI #define OFPPC_U (~(OFPPC_PORT_DOWN | OFPPC_NO_STP | OFPPC_NO_RECV | \
1183c602fabSXin LI                    OFPPC_NO_RECV_STP | OFPPC_NO_FLOOD | OFPPC_NO_FWD | \
1193c602fabSXin LI                    OFPPC_NO_PACKET_IN))
1203c602fabSXin LI 
121ee67461eSJoseph Mingrone /*
122ee67461eSJoseph Mingrone  * [OF10] lists all FPPS_ constants in one enum, but they mean a 1-bit bitmap
123ee67461eSJoseph Mingrone  * in the least significant octet and a 2-bit code point in the next octet.
124ee67461eSJoseph Mingrone  * Remember to mix or to separate these two parts as the context requires.
125ee67461eSJoseph Mingrone  */
126ee67461eSJoseph Mingrone #define OFPPS_LINK_DOWN   (1U << 0) /* bitmap             */
127ee67461eSJoseph Mingrone #define OFPPS_STP_LISTEN  (0U << 8) /* code point         */
128ee67461eSJoseph Mingrone #define OFPPS_STP_LEARN   (1U << 8) /* code point         */
129ee67461eSJoseph Mingrone #define OFPPS_STP_FORWARD (2U << 8) /* code point         */
130ee67461eSJoseph Mingrone #define OFPPS_STP_BLOCK   (3U << 8) /* code point         */
131ee67461eSJoseph Mingrone #define OFPPS_STP_MASK    (3U << 8) /* code point bitmask */
132ee67461eSJoseph Mingrone static const struct tok ofpps_stp_str[] = {
1333c602fabSXin LI 	{ OFPPS_STP_LISTEN,  "STP_LISTEN"  },
1343c602fabSXin LI 	{ OFPPS_STP_LEARN,   "STP_LEARN"   },
1353c602fabSXin LI 	{ OFPPS_STP_FORWARD, "STP_FORWARD" },
1363c602fabSXin LI 	{ OFPPS_STP_BLOCK,   "STP_BLOCK"   },
1373c602fabSXin LI 	{ 0, NULL }
1383c602fabSXin LI };
1393c602fabSXin LI #define OFPPS_U (~(OFPPS_LINK_DOWN | OFPPS_STP_LISTEN | OFPPS_STP_LEARN | \
1403c602fabSXin LI                    OFPPS_STP_FORWARD | OFPPS_STP_BLOCK))
1413c602fabSXin LI 
142ee67461eSJoseph Mingrone #define OFPP_MAX        0xff00U
143ee67461eSJoseph Mingrone #define OFPP_IN_PORT    0xfff8U
144ee67461eSJoseph Mingrone #define OFPP_TABLE      0xfff9U
145ee67461eSJoseph Mingrone #define OFPP_NORMAL     0xfffaU
146ee67461eSJoseph Mingrone #define OFPP_FLOOD      0xfffbU
147ee67461eSJoseph Mingrone #define OFPP_ALL        0xfffcU
148ee67461eSJoseph Mingrone #define OFPP_CONTROLLER 0xfffdU
149ee67461eSJoseph Mingrone #define OFPP_LOCAL      0xfffeU
150ee67461eSJoseph Mingrone #define OFPP_NONE       0xffffU
1513c602fabSXin LI static const struct tok ofpp_str[] = {
1523c602fabSXin LI 	{ OFPP_MAX,        "MAX"        },
1533c602fabSXin LI 	{ OFPP_IN_PORT,    "IN_PORT"    },
1543c602fabSXin LI 	{ OFPP_TABLE,      "TABLE"      },
1553c602fabSXin LI 	{ OFPP_NORMAL,     "NORMAL"     },
1563c602fabSXin LI 	{ OFPP_FLOOD,      "FLOOD"      },
1573c602fabSXin LI 	{ OFPP_ALL,        "ALL"        },
1583c602fabSXin LI 	{ OFPP_CONTROLLER, "CONTROLLER" },
1593c602fabSXin LI 	{ OFPP_LOCAL,      "LOCAL"      },
1603c602fabSXin LI 	{ OFPP_NONE,       "NONE"       },
1613c602fabSXin LI 	{ 0, NULL }
1623c602fabSXin LI };
1633c602fabSXin LI 
164ee67461eSJoseph Mingrone #define OFPPF_10MB_HD    (1U << 0)
165ee67461eSJoseph Mingrone #define OFPPF_10MB_FD    (1U << 1)
166ee67461eSJoseph Mingrone #define OFPPF_100MB_HD   (1U << 2)
167ee67461eSJoseph Mingrone #define OFPPF_100MB_FD   (1U << 3)
168ee67461eSJoseph Mingrone #define OFPPF_1GB_HD     (1U << 4)
169ee67461eSJoseph Mingrone #define OFPPF_1GB_FD     (1U << 5)
170ee67461eSJoseph Mingrone #define OFPPF_10GB_FD    (1U << 6)
171ee67461eSJoseph Mingrone #define OFPPF_COPPER     (1U << 7)
172ee67461eSJoseph Mingrone #define OFPPF_FIBER      (1U << 8)
173ee67461eSJoseph Mingrone #define OFPPF_AUTONEG    (1U << 9)
174ee67461eSJoseph Mingrone #define OFPPF_PAUSE      (1U <<10)
175ee67461eSJoseph Mingrone #define OFPPF_PAUSE_ASYM (1U <<11)
1763c602fabSXin LI static const struct tok ofppf_bm[] = {
1773c602fabSXin LI 	{ OFPPF_10MB_HD,    "10MB_HD"    },
1783c602fabSXin LI 	{ OFPPF_10MB_FD,    "10MB_FD"    },
1793c602fabSXin LI 	{ OFPPF_100MB_HD,   "100MB_HD"   },
1803c602fabSXin LI 	{ OFPPF_100MB_FD,   "100MB_FD"   },
1813c602fabSXin LI 	{ OFPPF_1GB_HD,     "1GB_HD"     },
1823c602fabSXin LI 	{ OFPPF_1GB_FD,     "1GB_FD"     },
1833c602fabSXin LI 	{ OFPPF_10GB_FD,    "10GB_FD"    },
1843c602fabSXin LI 	{ OFPPF_COPPER,     "COPPER"     },
1853c602fabSXin LI 	{ OFPPF_FIBER,      "FIBER"      },
1863c602fabSXin LI 	{ OFPPF_AUTONEG,    "AUTONEG"    },
1873c602fabSXin LI 	{ OFPPF_PAUSE,      "PAUSE"      },
1883c602fabSXin LI 	{ OFPPF_PAUSE_ASYM, "PAUSE_ASYM" },
1893c602fabSXin LI 	{ 0, NULL }
1903c602fabSXin LI };
1913c602fabSXin LI #define OFPPF_U (~(OFPPF_10MB_HD | OFPPF_10MB_FD | OFPPF_100MB_HD | \
1923c602fabSXin LI                    OFPPF_100MB_FD | OFPPF_1GB_HD | OFPPF_1GB_FD | \
1933c602fabSXin LI                    OFPPF_10GB_FD | OFPPF_COPPER | OFPPF_FIBER | \
1943c602fabSXin LI                    OFPPF_AUTONEG | OFPPF_PAUSE | OFPPF_PAUSE_ASYM))
1953c602fabSXin LI 
1963c602fabSXin LI #define OFPQT_NONE     0x0000
1973c602fabSXin LI #define OFPQT_MIN_RATE 0x0001
1983c602fabSXin LI static const struct tok ofpqt_str[] = {
1993c602fabSXin LI 	{ OFPQT_NONE,     "NONE"     },
2003c602fabSXin LI 	{ OFPQT_MIN_RATE, "MIN_RATE" },
2013c602fabSXin LI 	{ 0, NULL }
2023c602fabSXin LI };
2033c602fabSXin LI 
204ee67461eSJoseph Mingrone #define OFPFW_IN_PORT      (1U <<0)
205ee67461eSJoseph Mingrone #define OFPFW_DL_VLAN      (1U <<1)
206ee67461eSJoseph Mingrone #define OFPFW_DL_SRC       (1U <<2)
207ee67461eSJoseph Mingrone #define OFPFW_DL_DST       (1U <<3)
208ee67461eSJoseph Mingrone #define OFPFW_DL_TYPE      (1U <<4)
209ee67461eSJoseph Mingrone #define OFPFW_NW_PROTO     (1U <<5)
210ee67461eSJoseph Mingrone #define OFPFW_TP_SRC       (1U <<6)
211ee67461eSJoseph Mingrone #define OFPFW_TP_DST       (1U <<7)
2123c602fabSXin LI #define OFPFW_NW_SRC_SHIFT 8
2133c602fabSXin LI #define OFPFW_NW_SRC_BITS  6
214ee67461eSJoseph Mingrone #define OFPFW_NW_SRC_MASK  (((1U <<OFPFW_NW_SRC_BITS) - 1) << OFPFW_NW_SRC_SHIFT)
2153c602fabSXin LI #define OFPFW_NW_DST_SHIFT 14
2163c602fabSXin LI #define OFPFW_NW_DST_BITS  6
217ee67461eSJoseph Mingrone #define OFPFW_NW_DST_MASK  (((1U <<OFPFW_NW_DST_BITS) - 1) << OFPFW_NW_DST_SHIFT)
218ee67461eSJoseph Mingrone #define OFPFW_DL_VLAN_PCP  (1U <<20)
219ee67461eSJoseph Mingrone #define OFPFW_NW_TOS       (1U <<21)
220ee67461eSJoseph Mingrone #define OFPFW_ALL          ((1U <<22) - 1)
2213c602fabSXin LI static const struct tok ofpfw_bm[] = {
2223c602fabSXin LI 	{ OFPFW_IN_PORT,     "IN_PORT"     },
2233c602fabSXin LI 	{ OFPFW_DL_VLAN,     "DL_VLAN"     },
2243c602fabSXin LI 	{ OFPFW_DL_SRC,      "DL_SRC"      },
2253c602fabSXin LI 	{ OFPFW_DL_DST,      "DL_DST"      },
2263c602fabSXin LI 	{ OFPFW_DL_TYPE,     "DL_TYPE"     },
2273c602fabSXin LI 	{ OFPFW_NW_PROTO,    "NW_PROTO"    },
2283c602fabSXin LI 	{ OFPFW_TP_SRC,      "TP_SRC"      },
2293c602fabSXin LI 	{ OFPFW_TP_DST,      "TP_DST"      },
2303c602fabSXin LI 	{ OFPFW_DL_VLAN_PCP, "DL_VLAN_PCP" },
2313c602fabSXin LI 	{ OFPFW_NW_TOS,      "NW_TOS"      },
2323c602fabSXin LI 	{ 0, NULL }
2333c602fabSXin LI };
2343c602fabSXin LI /* The above array does not include bits 8~13 (OFPFW_NW_SRC_*) and 14~19
2353c602fabSXin LI  * (OFPFW_NW_DST_*), which are not a part of the bitmap and require decoding
2363c602fabSXin LI  * other than that of tok2str(). The macro below includes these bits such that
2373c602fabSXin LI  * they are not reported as bogus in the decoding. */
2383c602fabSXin LI #define OFPFW_U (~(OFPFW_ALL))
2393c602fabSXin LI 
240ee67461eSJoseph Mingrone #define OFPAT_OUTPUT       0x0000U
241ee67461eSJoseph Mingrone #define OFPAT_SET_VLAN_VID 0x0001U
242ee67461eSJoseph Mingrone #define OFPAT_SET_VLAN_PCP 0x0002U
243ee67461eSJoseph Mingrone #define OFPAT_STRIP_VLAN   0x0003U
244ee67461eSJoseph Mingrone #define OFPAT_SET_DL_SRC   0x0004U
245ee67461eSJoseph Mingrone #define OFPAT_SET_DL_DST   0x0005U
246ee67461eSJoseph Mingrone #define OFPAT_SET_NW_SRC   0x0006U
247ee67461eSJoseph Mingrone #define OFPAT_SET_NW_DST   0x0007U
248ee67461eSJoseph Mingrone #define OFPAT_SET_NW_TOS   0x0008U
249ee67461eSJoseph Mingrone #define OFPAT_SET_TP_SRC   0x0009U
250ee67461eSJoseph Mingrone #define OFPAT_SET_TP_DST   0x000aU
251ee67461eSJoseph Mingrone #define OFPAT_ENQUEUE      0x000bU
252ee67461eSJoseph Mingrone #define OFPAT_VENDOR       0xffffU
2533c602fabSXin LI static const struct tok ofpat_str[] = {
2543c602fabSXin LI 	{ OFPAT_OUTPUT,       "OUTPUT"       },
2553c602fabSXin LI 	{ OFPAT_SET_VLAN_VID, "SET_VLAN_VID" },
2563c602fabSXin LI 	{ OFPAT_SET_VLAN_PCP, "SET_VLAN_PCP" },
2573c602fabSXin LI 	{ OFPAT_STRIP_VLAN,   "STRIP_VLAN"   },
2583c602fabSXin LI 	{ OFPAT_SET_DL_SRC,   "SET_DL_SRC"   },
2593c602fabSXin LI 	{ OFPAT_SET_DL_DST,   "SET_DL_DST"   },
2603c602fabSXin LI 	{ OFPAT_SET_NW_SRC,   "SET_NW_SRC"   },
2613c602fabSXin LI 	{ OFPAT_SET_NW_DST,   "SET_NW_DST"   },
2623c602fabSXin LI 	{ OFPAT_SET_NW_TOS,   "SET_NW_TOS"   },
2633c602fabSXin LI 	{ OFPAT_SET_TP_SRC,   "SET_TP_SRC"   },
2643c602fabSXin LI 	{ OFPAT_SET_TP_DST,   "SET_TP_DST"   },
2653c602fabSXin LI 	{ OFPAT_ENQUEUE,      "ENQUEUE"      },
2663c602fabSXin LI 	{ OFPAT_VENDOR,       "VENDOR"       },
2673c602fabSXin LI 	{ 0, NULL }
2683c602fabSXin LI };
2693c602fabSXin LI 
2703c602fabSXin LI /* bit-shifted, w/o vendor action */
2713c602fabSXin LI static const struct tok ofpat_bm[] = {
272ee67461eSJoseph Mingrone 	{ 1U <<OFPAT_OUTPUT,       "OUTPUT"       },
273ee67461eSJoseph Mingrone 	{ 1U <<OFPAT_SET_VLAN_VID, "SET_VLAN_VID" },
274ee67461eSJoseph Mingrone 	{ 1U <<OFPAT_SET_VLAN_PCP, "SET_VLAN_PCP" },
275ee67461eSJoseph Mingrone 	{ 1U <<OFPAT_STRIP_VLAN,   "STRIP_VLAN"   },
276ee67461eSJoseph Mingrone 	{ 1U <<OFPAT_SET_DL_SRC,   "SET_DL_SRC"   },
277ee67461eSJoseph Mingrone 	{ 1U <<OFPAT_SET_DL_DST,   "SET_DL_DST"   },
278ee67461eSJoseph Mingrone 	{ 1U <<OFPAT_SET_NW_SRC,   "SET_NW_SRC"   },
279ee67461eSJoseph Mingrone 	{ 1U <<OFPAT_SET_NW_DST,   "SET_NW_DST"   },
280ee67461eSJoseph Mingrone 	{ 1U <<OFPAT_SET_NW_TOS,   "SET_NW_TOS"   },
281ee67461eSJoseph Mingrone 	{ 1U <<OFPAT_SET_TP_SRC,   "SET_TP_SRC"   },
282ee67461eSJoseph Mingrone 	{ 1U <<OFPAT_SET_TP_DST,   "SET_TP_DST"   },
283ee67461eSJoseph Mingrone 	{ 1U <<OFPAT_ENQUEUE,      "ENQUEUE"      },
2843c602fabSXin LI 	{ 0, NULL }
2853c602fabSXin LI };
286ee67461eSJoseph Mingrone #define OFPAT_U (~(1U <<OFPAT_OUTPUT | 1U <<OFPAT_SET_VLAN_VID | \
287ee67461eSJoseph Mingrone                    1U <<OFPAT_SET_VLAN_PCP | 1U <<OFPAT_STRIP_VLAN | \
288ee67461eSJoseph Mingrone                    1U <<OFPAT_SET_DL_SRC | 1U <<OFPAT_SET_DL_DST | \
289ee67461eSJoseph Mingrone                    1U <<OFPAT_SET_NW_SRC | 1U <<OFPAT_SET_NW_DST | \
290ee67461eSJoseph Mingrone                    1U <<OFPAT_SET_NW_TOS | 1U <<OFPAT_SET_TP_SRC | \
291ee67461eSJoseph Mingrone                    1U <<OFPAT_SET_TP_DST | 1U <<OFPAT_ENQUEUE))
2923c602fabSXin LI 
293ee67461eSJoseph Mingrone #define OFPC_FLOW_STATS   (1U <<0)
294ee67461eSJoseph Mingrone #define OFPC_TABLE_STATS  (1U <<1)
295ee67461eSJoseph Mingrone #define OFPC_PORT_STATS   (1U <<2)
296ee67461eSJoseph Mingrone #define OFPC_STP          (1U <<3)
297ee67461eSJoseph Mingrone #define OFPC_RESERVED     (1U <<4)
298ee67461eSJoseph Mingrone #define OFPC_IP_REASM     (1U <<5)
299ee67461eSJoseph Mingrone #define OFPC_QUEUE_STATS  (1U <<6)
300ee67461eSJoseph Mingrone #define OFPC_ARP_MATCH_IP (1U <<7)
3013c602fabSXin LI static const struct tok ofp_capabilities_bm[] = {
3023c602fabSXin LI 	{ OFPC_FLOW_STATS,   "FLOW_STATS"   },
3033c602fabSXin LI 	{ OFPC_TABLE_STATS,  "TABLE_STATS"  },
3043c602fabSXin LI 	{ OFPC_PORT_STATS,   "PORT_STATS"   },
3053c602fabSXin LI 	{ OFPC_STP,          "STP"          },
3063c602fabSXin LI 	{ OFPC_RESERVED,     "RESERVED"     }, /* not in the mask below */
3073c602fabSXin LI 	{ OFPC_IP_REASM,     "IP_REASM"     },
3083c602fabSXin LI 	{ OFPC_QUEUE_STATS,  "QUEUE_STATS"  },
3093c602fabSXin LI 	{ OFPC_ARP_MATCH_IP, "ARP_MATCH_IP" },
3103c602fabSXin LI 	{ 0, NULL }
3113c602fabSXin LI };
3123c602fabSXin LI #define OFPCAP_U (~(OFPC_FLOW_STATS | OFPC_TABLE_STATS | OFPC_PORT_STATS | \
3133c602fabSXin LI                     OFPC_STP | OFPC_IP_REASM | OFPC_QUEUE_STATS | \
3143c602fabSXin LI                     OFPC_ARP_MATCH_IP))
3153c602fabSXin LI 
316ee67461eSJoseph Mingrone #define OFPC_FRAG_NORMAL 0x0000U
317ee67461eSJoseph Mingrone #define OFPC_FRAG_DROP   0x0001U
318ee67461eSJoseph Mingrone #define OFPC_FRAG_REASM  0x0002U
3193c602fabSXin LI static const struct tok ofp_config_str[] = {
3203c602fabSXin LI 	{ OFPC_FRAG_NORMAL, "FRAG_NORMAL" },
3213c602fabSXin LI 	{ OFPC_FRAG_DROP,   "FRAG_DROP"   },
3223c602fabSXin LI 	{ OFPC_FRAG_REASM,  "FRAG_REASM"  },
3233c602fabSXin LI 	{ 0, NULL }
3243c602fabSXin LI };
3253c602fabSXin LI 
326ee67461eSJoseph Mingrone #define OFPFC_ADD           0x0000U
327ee67461eSJoseph Mingrone #define OFPFC_MODIFY        0x0001U
328ee67461eSJoseph Mingrone #define OFPFC_MODIFY_STRICT 0x0002U
329ee67461eSJoseph Mingrone #define OFPFC_DELETE        0x0003U
330ee67461eSJoseph Mingrone #define OFPFC_DELETE_STRICT 0x0004U
3313c602fabSXin LI static const struct tok ofpfc_str[] = {
3323c602fabSXin LI 	{ OFPFC_ADD,           "ADD"           },
3333c602fabSXin LI 	{ OFPFC_MODIFY,        "MODIFY"        },
3343c602fabSXin LI 	{ OFPFC_MODIFY_STRICT, "MODIFY_STRICT" },
3353c602fabSXin LI 	{ OFPFC_DELETE,        "DELETE"        },
3363c602fabSXin LI 	{ OFPFC_DELETE_STRICT, "DELETE_STRICT" },
3373c602fabSXin LI 	{ 0, NULL }
3383c602fabSXin LI };
3393c602fabSXin LI 
3403c602fabSXin LI static const struct tok bufferid_str[] = {
3413c602fabSXin LI 	{ 0xffffffff, "NONE" },
3423c602fabSXin LI 	{ 0, NULL }
3433c602fabSXin LI };
3443c602fabSXin LI 
345ee67461eSJoseph Mingrone #define OFPFF_SEND_FLOW_REM (1U <<0)
346ee67461eSJoseph Mingrone #define OFPFF_CHECK_OVERLAP (1U <<1)
347ee67461eSJoseph Mingrone #define OFPFF_EMERG         (1U <<2)
3483c602fabSXin LI static const struct tok ofpff_bm[] = {
3493c602fabSXin LI 	{ OFPFF_SEND_FLOW_REM, "SEND_FLOW_REM" },
3503c602fabSXin LI 	{ OFPFF_CHECK_OVERLAP, "CHECK_OVERLAP" },
3513c602fabSXin LI 	{ OFPFF_EMERG,         "EMERG"         },
3523c602fabSXin LI 	{ 0, NULL }
3533c602fabSXin LI };
3543c602fabSXin LI #define OFPFF_U (~(OFPFF_SEND_FLOW_REM | OFPFF_CHECK_OVERLAP | OFPFF_EMERG))
3553c602fabSXin LI 
356ee67461eSJoseph Mingrone #define OFPST_DESC      0x0000U
357ee67461eSJoseph Mingrone #define OFPST_FLOW      0x0001U
358ee67461eSJoseph Mingrone #define OFPST_AGGREGATE 0x0002U
359ee67461eSJoseph Mingrone #define OFPST_TABLE     0x0003U
360ee67461eSJoseph Mingrone #define OFPST_PORT      0x0004U
361ee67461eSJoseph Mingrone #define OFPST_QUEUE     0x0005U
362ee67461eSJoseph Mingrone #define OFPST_VENDOR    0xffffU
3633c602fabSXin LI static const struct tok ofpst_str[] = {
3643c602fabSXin LI 	{ OFPST_DESC,      "DESC"      },
3653c602fabSXin LI 	{ OFPST_FLOW,      "FLOW"      },
3663c602fabSXin LI 	{ OFPST_AGGREGATE, "AGGREGATE" },
3673c602fabSXin LI 	{ OFPST_TABLE,     "TABLE"     },
3683c602fabSXin LI 	{ OFPST_PORT,      "PORT"      },
3693c602fabSXin LI 	{ OFPST_QUEUE,     "QUEUE"     },
3703c602fabSXin LI 	{ OFPST_VENDOR,    "VENDOR"    },
3713c602fabSXin LI 	{ 0, NULL }
3723c602fabSXin LI };
3733c602fabSXin LI 
3743c602fabSXin LI static const struct tok tableid_str[] = {
375ee67461eSJoseph Mingrone 	{ 0xfeU, "EMERG" },
376ee67461eSJoseph Mingrone 	{ 0xffU, "ALL"   },
3773c602fabSXin LI 	{ 0, NULL }
3783c602fabSXin LI };
3793c602fabSXin LI 
380ee67461eSJoseph Mingrone #define OFPQ_ALL      0xffffffffU
3813c602fabSXin LI static const struct tok ofpq_str[] = {
3823c602fabSXin LI 	{ OFPQ_ALL, "ALL" },
3833c602fabSXin LI 	{ 0, NULL }
3843c602fabSXin LI };
3853c602fabSXin LI 
386ee67461eSJoseph Mingrone #define OFPSF_REPLY_MORE 0x0001U
3873c602fabSXin LI static const struct tok ofpsf_reply_bm[] = {
3883c602fabSXin LI 	{ OFPSF_REPLY_MORE, "MORE" },
3893c602fabSXin LI 	{ 0, NULL }
3903c602fabSXin LI };
3913c602fabSXin LI #define OFPSF_REPLY_U (~(OFPSF_REPLY_MORE))
3923c602fabSXin LI 
393ee67461eSJoseph Mingrone #define OFPR_NO_MATCH 0x00U
394ee67461eSJoseph Mingrone #define OFPR_ACTION   0x01U
3953c602fabSXin LI static const struct tok ofpr_str[] = {
3963c602fabSXin LI 	{ OFPR_NO_MATCH, "NO_MATCH" },
3973c602fabSXin LI 	{ OFPR_ACTION,   "ACTION"   },
3983c602fabSXin LI 	{ 0, NULL }
3993c602fabSXin LI };
4003c602fabSXin LI 
401ee67461eSJoseph Mingrone #define OFPRR_IDLE_TIMEOUT 0x00U
402ee67461eSJoseph Mingrone #define OFPRR_HARD_TIMEOUT 0x01U
403ee67461eSJoseph Mingrone #define OFPRR_DELETE       0x02U
4043c602fabSXin LI static const struct tok ofprr_str[] = {
4053c602fabSXin LI 	{ OFPRR_IDLE_TIMEOUT, "IDLE_TIMEOUT" },
4063c602fabSXin LI 	{ OFPRR_HARD_TIMEOUT, "HARD_TIMEOUT" },
4073c602fabSXin LI 	{ OFPRR_DELETE,       "DELETE"       },
4083c602fabSXin LI 	{ 0, NULL }
4093c602fabSXin LI };
4103c602fabSXin LI 
411ee67461eSJoseph Mingrone #define OFPPR_ADD    0x00U
412ee67461eSJoseph Mingrone #define OFPPR_DELETE 0x01U
413ee67461eSJoseph Mingrone #define OFPPR_MODIFY 0x02U
4143c602fabSXin LI static const struct tok ofppr_str[] = {
4153c602fabSXin LI 	{ OFPPR_ADD,    "ADD"    },
4163c602fabSXin LI 	{ OFPPR_DELETE, "DELETE" },
4173c602fabSXin LI 	{ OFPPR_MODIFY, "MODIFY" },
4183c602fabSXin LI 	{ 0, NULL }
4193c602fabSXin LI };
4203c602fabSXin LI 
421ee67461eSJoseph Mingrone #define OFPET_HELLO_FAILED    0x0000U
422ee67461eSJoseph Mingrone #define OFPET_BAD_REQUEST     0x0001U
423ee67461eSJoseph Mingrone #define OFPET_BAD_ACTION      0x0002U
424ee67461eSJoseph Mingrone #define OFPET_FLOW_MOD_FAILED 0x0003U
425ee67461eSJoseph Mingrone #define OFPET_PORT_MOD_FAILED 0x0004U
426ee67461eSJoseph Mingrone #define OFPET_QUEUE_OP_FAILED 0x0005U
4273c602fabSXin LI static const struct tok ofpet_str[] = {
4283c602fabSXin LI 	{ OFPET_HELLO_FAILED,    "HELLO_FAILED"    },
4293c602fabSXin LI 	{ OFPET_BAD_REQUEST,     "BAD_REQUEST"     },
4303c602fabSXin LI 	{ OFPET_BAD_ACTION,      "BAD_ACTION"      },
4313c602fabSXin LI 	{ OFPET_FLOW_MOD_FAILED, "FLOW_MOD_FAILED" },
4323c602fabSXin LI 	{ OFPET_PORT_MOD_FAILED, "PORT_MOD_FAILED" },
4333c602fabSXin LI 	{ OFPET_QUEUE_OP_FAILED, "QUEUE_OP_FAILED" },
4343c602fabSXin LI 	{ 0, NULL }
4353c602fabSXin LI };
4363c602fabSXin LI 
437ee67461eSJoseph Mingrone #define OFPHFC_INCOMPATIBLE 0x0000U
438ee67461eSJoseph Mingrone #define OFPHFC_EPERM        0x0001U
4393c602fabSXin LI static const struct tok ofphfc_str[] = {
4403c602fabSXin LI 	{ OFPHFC_INCOMPATIBLE, "INCOMPATIBLE" },
4413c602fabSXin LI 	{ OFPHFC_EPERM,        "EPERM"        },
4423c602fabSXin LI 	{ 0, NULL }
4433c602fabSXin LI };
4443c602fabSXin LI 
445ee67461eSJoseph Mingrone #define OFPBRC_BAD_VERSION    0x0000U
446ee67461eSJoseph Mingrone #define OFPBRC_BAD_TYPE       0x0001U
447ee67461eSJoseph Mingrone #define OFPBRC_BAD_STAT       0x0002U
448ee67461eSJoseph Mingrone #define OFPBRC_BAD_VENDOR     0x0003U
449ee67461eSJoseph Mingrone #define OFPBRC_BAD_SUBTYPE    0x0004U
450ee67461eSJoseph Mingrone #define OFPBRC_EPERM          0x0005U
451ee67461eSJoseph Mingrone #define OFPBRC_BAD_LEN        0x0006U
452ee67461eSJoseph Mingrone #define OFPBRC_BUFFER_EMPTY   0x0007U
453ee67461eSJoseph Mingrone #define OFPBRC_BUFFER_UNKNOWN 0x0008U
4543c602fabSXin LI static const struct tok ofpbrc_str[] = {
4553c602fabSXin LI 	{ OFPBRC_BAD_VERSION,    "BAD_VERSION"    },
4563c602fabSXin LI 	{ OFPBRC_BAD_TYPE,       "BAD_TYPE"       },
4573c602fabSXin LI 	{ OFPBRC_BAD_STAT,       "BAD_STAT"       },
4583c602fabSXin LI 	{ OFPBRC_BAD_VENDOR,     "BAD_VENDOR"     },
4593c602fabSXin LI 	{ OFPBRC_BAD_SUBTYPE,    "BAD_SUBTYPE"    },
4603c602fabSXin LI 	{ OFPBRC_EPERM,          "EPERM"          },
4613c602fabSXin LI 	{ OFPBRC_BAD_LEN,        "BAD_LEN"        },
4623c602fabSXin LI 	{ OFPBRC_BUFFER_EMPTY,   "BUFFER_EMPTY"   },
4633c602fabSXin LI 	{ OFPBRC_BUFFER_UNKNOWN, "BUFFER_UNKNOWN" },
4643c602fabSXin LI 	{ 0, NULL }
4653c602fabSXin LI };
4663c602fabSXin LI 
467ee67461eSJoseph Mingrone #define OFPBAC_BAD_TYPE        0x0000U
468ee67461eSJoseph Mingrone #define OFPBAC_BAD_LEN         0x0001U
469ee67461eSJoseph Mingrone #define OFPBAC_BAD_VENDOR      0x0002U
470ee67461eSJoseph Mingrone #define OFPBAC_BAD_VENDOR_TYPE 0x0003U
471ee67461eSJoseph Mingrone #define OFPBAC_BAD_OUT_PORT    0x0004U
472ee67461eSJoseph Mingrone #define OFPBAC_BAD_ARGUMENT    0x0005U
473ee67461eSJoseph Mingrone #define OFPBAC_EPERM           0x0006U
474ee67461eSJoseph Mingrone #define OFPBAC_TOO_MANY        0x0007U
475ee67461eSJoseph Mingrone #define OFPBAC_BAD_QUEUE       0x0008U
4763c602fabSXin LI static const struct tok ofpbac_str[] = {
4773c602fabSXin LI 	{ OFPBAC_BAD_TYPE,        "BAD_TYPE"        },
4783c602fabSXin LI 	{ OFPBAC_BAD_LEN,         "BAD_LEN"         },
4793c602fabSXin LI 	{ OFPBAC_BAD_VENDOR,      "BAD_VENDOR"      },
4803c602fabSXin LI 	{ OFPBAC_BAD_VENDOR_TYPE, "BAD_VENDOR_TYPE" },
4813c602fabSXin LI 	{ OFPBAC_BAD_OUT_PORT,    "BAD_OUT_PORT"    },
4823c602fabSXin LI 	{ OFPBAC_BAD_ARGUMENT,    "BAD_ARGUMENT"    },
4833c602fabSXin LI 	{ OFPBAC_EPERM,           "EPERM"           },
4843c602fabSXin LI 	{ OFPBAC_TOO_MANY,        "TOO_MANY"        },
4853c602fabSXin LI 	{ OFPBAC_BAD_QUEUE,       "BAD_QUEUE"       },
4863c602fabSXin LI 	{ 0, NULL }
4873c602fabSXin LI };
4883c602fabSXin LI 
489ee67461eSJoseph Mingrone #define OFPFMFC_ALL_TABLES_FULL   0x0000U
490ee67461eSJoseph Mingrone #define OFPFMFC_OVERLAP           0x0001U
491ee67461eSJoseph Mingrone #define OFPFMFC_EPERM             0x0002U
492ee67461eSJoseph Mingrone #define OFPFMFC_BAD_EMERG_TIMEOUT 0x0003U
493ee67461eSJoseph Mingrone #define OFPFMFC_BAD_COMMAND       0x0004U
494ee67461eSJoseph Mingrone #define OFPFMFC_UNSUPPORTED       0x0005U
4953c602fabSXin LI static const struct tok ofpfmfc_str[] = {
4963c602fabSXin LI 	{ OFPFMFC_ALL_TABLES_FULL,   "ALL_TABLES_FULL"   },
4973c602fabSXin LI 	{ OFPFMFC_OVERLAP,           "OVERLAP"           },
4983c602fabSXin LI 	{ OFPFMFC_EPERM,             "EPERM"             },
4993c602fabSXin LI 	{ OFPFMFC_BAD_EMERG_TIMEOUT, "BAD_EMERG_TIMEOUT" },
5003c602fabSXin LI 	{ OFPFMFC_BAD_COMMAND,       "BAD_COMMAND"       },
5013c602fabSXin LI 	{ OFPFMFC_UNSUPPORTED,       "UNSUPPORTED"       },
5023c602fabSXin LI 	{ 0, NULL }
5033c602fabSXin LI };
5043c602fabSXin LI 
505ee67461eSJoseph Mingrone #define OFPPMFC_BAD_PORT    0x0000U
506ee67461eSJoseph Mingrone #define OFPPMFC_BAD_HW_ADDR 0x0001U
5073c602fabSXin LI static const struct tok ofppmfc_str[] = {
5083c602fabSXin LI 	{ OFPPMFC_BAD_PORT,    "BAD_PORT"    },
5093c602fabSXin LI 	{ OFPPMFC_BAD_HW_ADDR, "BAD_HW_ADDR" },
5103c602fabSXin LI 	{ 0, NULL }
5113c602fabSXin LI };
5123c602fabSXin LI 
513ee67461eSJoseph Mingrone #define OFPQOFC_BAD_PORT  0x0000U
514ee67461eSJoseph Mingrone #define OFPQOFC_BAD_QUEUE 0x0001U
515ee67461eSJoseph Mingrone #define OFPQOFC_EPERM     0x0002U
5163c602fabSXin LI static const struct tok ofpqofc_str[] = {
5173c602fabSXin LI 	{ OFPQOFC_BAD_PORT,  "BAD_PORT"  },
5183c602fabSXin LI 	{ OFPQOFC_BAD_QUEUE, "BAD_QUEUE" },
5193c602fabSXin LI 	{ OFPQOFC_EPERM,     "EPERM"     },
5203c602fabSXin LI 	{ 0, NULL }
5213c602fabSXin LI };
5223c602fabSXin LI 
523ee67461eSJoseph Mingrone static const struct uint_tokary of10_ofpet2tokary[] = {
524ee67461eSJoseph Mingrone 	{ OFPET_HELLO_FAILED,    ofphfc_str  },
525ee67461eSJoseph Mingrone 	{ OFPET_BAD_REQUEST,     ofpbrc_str  },
526ee67461eSJoseph Mingrone 	{ OFPET_BAD_ACTION,      ofpbac_str  },
527ee67461eSJoseph Mingrone 	{ OFPET_FLOW_MOD_FAILED, ofpfmfc_str },
528ee67461eSJoseph Mingrone 	{ OFPET_PORT_MOD_FAILED, ofppmfc_str },
529ee67461eSJoseph Mingrone 	{ OFPET_QUEUE_OP_FAILED, ofpqofc_str },
530ee67461eSJoseph Mingrone 	/* uint2tokary() does not use array termination. */
5313c602fabSXin LI };
5323c602fabSXin LI 
533ee67461eSJoseph Mingrone /* lengths (fixed or minimal) of particular message types, where not 0 */
534ee67461eSJoseph Mingrone #define OF_SWITCH_CONFIG_FIXLEN            (12U - OF_HEADER_FIXLEN)
535ee67461eSJoseph Mingrone #define OF_FEATURES_REPLY_MINLEN           (32U - OF_HEADER_FIXLEN)
536ee67461eSJoseph Mingrone #define OF_PORT_STATUS_FIXLEN              (64U - OF_HEADER_FIXLEN)
537ee67461eSJoseph Mingrone #define OF_PORT_MOD_FIXLEN                 (32U - OF_HEADER_FIXLEN)
538ee67461eSJoseph Mingrone #define OF_PACKET_IN_MINLEN                (20U - OF_HEADER_FIXLEN) /* with 2 mock octets */
539ee67461eSJoseph Mingrone #define OF_PACKET_OUT_MINLEN               (16U - OF_HEADER_FIXLEN)
540ee67461eSJoseph Mingrone #define OF_FLOW_MOD_MINLEN                 (72U - OF_HEADER_FIXLEN)
541ee67461eSJoseph Mingrone #define OF_FLOW_REMOVED_FIXLEN             (88U - OF_HEADER_FIXLEN)
542ee67461eSJoseph Mingrone #define OF_ERROR_MSG_MINLEN                (12U - OF_HEADER_FIXLEN)
543ee67461eSJoseph Mingrone #define OF_STATS_REQUEST_MINLEN            (12U - OF_HEADER_FIXLEN)
544ee67461eSJoseph Mingrone #define OF_STATS_REPLY_MINLEN              (12U - OF_HEADER_FIXLEN)
545ee67461eSJoseph Mingrone #define OF_VENDOR_MINLEN                   (12U - OF_HEADER_FIXLEN)
546ee67461eSJoseph Mingrone #define OF_QUEUE_GET_CONFIG_REQUEST_FIXLEN (12U - OF_HEADER_FIXLEN)
547ee67461eSJoseph Mingrone #define OF_QUEUE_GET_CONFIG_REPLY_MINLEN   (16U - OF_HEADER_FIXLEN)
548ee67461eSJoseph Mingrone 
5493c602fabSXin LI /* lengths (fixed or minimal) of particular protocol structures */
550ee67461eSJoseph Mingrone #define OF_PHY_PORT_FIXLEN                    48
551ee67461eSJoseph Mingrone #define OF_ACTION_MINLEN                       8
552ee67461eSJoseph Mingrone #define OF_MATCH_FIXLEN                       40
553ee67461eSJoseph Mingrone #define OF_DESC_STATS_REPLY_FIXLEN          1056
554ee67461eSJoseph Mingrone #define OF_FLOW_STATS_REQUEST_FIXLEN          44
555ee67461eSJoseph Mingrone #define OF_FLOW_STATS_REPLY_MINLEN            88
556ee67461eSJoseph Mingrone #define OF_AGGREGATE_STATS_REPLY_FIXLEN       24
557ee67461eSJoseph Mingrone #define OF_TABLE_STATS_REPLY_FIXLEN           64
558ee67461eSJoseph Mingrone #define OF_PORT_STATS_REQUEST_FIXLEN           8
559ee67461eSJoseph Mingrone #define OF_PORT_STATS_REPLY_FIXLEN           104
560ee67461eSJoseph Mingrone #define OF_QUEUE_PROP_MINLEN                   8
561ee67461eSJoseph Mingrone #define OF_QUEUE_PROP_MIN_RATE_FIXLEN         16
562ee67461eSJoseph Mingrone #define OF_PACKET_QUEUE_MINLEN                 8
563ee67461eSJoseph Mingrone #define OF_QUEUE_STATS_REQUEST_FIXLEN          8
564ee67461eSJoseph Mingrone #define OF_QUEUE_STATS_REPLY_FIXLEN           32
5653c602fabSXin LI 
5663c602fabSXin LI /* miscellaneous constants from [OF10] */
5673c602fabSXin LI #define OFP_MAX_TABLE_NAME_LEN     32
5683c602fabSXin LI #define OFP_MAX_PORT_NAME_LEN      16
5693c602fabSXin LI #define DESC_STR_LEN              256
5703c602fabSXin LI #define SERIAL_NUM_LEN             32
571ee67461eSJoseph Mingrone #define OFP_VLAN_NONE          0xffffU
5723c602fabSXin LI 
5738bdc5a62SPatrick Kelsey /* vendor extensions */
5748bdc5a62SPatrick Kelsey #define BSN_SET_IP_MASK                    0
5758bdc5a62SPatrick Kelsey #define BSN_GET_IP_MASK_REQUEST            1
5768bdc5a62SPatrick Kelsey #define BSN_GET_IP_MASK_REPLY              2
5778bdc5a62SPatrick Kelsey #define BSN_SET_MIRRORING                  3
5788bdc5a62SPatrick Kelsey #define BSN_GET_MIRRORING_REQUEST          4
5798bdc5a62SPatrick Kelsey #define BSN_GET_MIRRORING_REPLY            5
5808bdc5a62SPatrick Kelsey #define BSN_SHELL_COMMAND                  6
5818bdc5a62SPatrick Kelsey #define BSN_SHELL_OUTPUT                   7
5828bdc5a62SPatrick Kelsey #define BSN_SHELL_STATUS                   8
5838bdc5a62SPatrick Kelsey #define BSN_GET_INTERFACES_REQUEST         9
5848bdc5a62SPatrick Kelsey #define BSN_GET_INTERFACES_REPLY          10
5858bdc5a62SPatrick Kelsey #define BSN_SET_PKTIN_SUPPRESSION_REQUEST 11
5868bdc5a62SPatrick Kelsey #define BSN_SET_L2_TABLE_REQUEST          12
5878bdc5a62SPatrick Kelsey #define BSN_GET_L2_TABLE_REQUEST          13
5888bdc5a62SPatrick Kelsey #define BSN_GET_L2_TABLE_REPLY            14
5898bdc5a62SPatrick Kelsey #define BSN_VIRTUAL_PORT_CREATE_REQUEST   15
5908bdc5a62SPatrick Kelsey #define BSN_VIRTUAL_PORT_CREATE_REPLY     16
5918bdc5a62SPatrick Kelsey #define BSN_VIRTUAL_PORT_REMOVE_REQUEST   17
5928bdc5a62SPatrick Kelsey #define BSN_BW_ENABLE_SET_REQUEST         18
5938bdc5a62SPatrick Kelsey #define BSN_BW_ENABLE_GET_REQUEST         19
5948bdc5a62SPatrick Kelsey #define BSN_BW_ENABLE_GET_REPLY           20
5958bdc5a62SPatrick Kelsey #define BSN_BW_CLEAR_DATA_REQUEST         21
5968bdc5a62SPatrick Kelsey #define BSN_BW_CLEAR_DATA_REPLY           22
5978bdc5a62SPatrick Kelsey #define BSN_BW_ENABLE_SET_REPLY           23
5988bdc5a62SPatrick Kelsey #define BSN_SET_L2_TABLE_REPLY            24
5998bdc5a62SPatrick Kelsey #define BSN_SET_PKTIN_SUPPRESSION_REPLY   25
6008bdc5a62SPatrick Kelsey #define BSN_VIRTUAL_PORT_REMOVE_REPLY     26
6018bdc5a62SPatrick Kelsey #define BSN_HYBRID_GET_REQUEST            27
6028bdc5a62SPatrick Kelsey #define BSN_HYBRID_GET_REPLY              28
6038bdc5a62SPatrick Kelsey                                        /* 29 */
6048bdc5a62SPatrick Kelsey                                        /* 30 */
6058bdc5a62SPatrick Kelsey #define BSN_PDU_TX_REQUEST                31
6068bdc5a62SPatrick Kelsey #define BSN_PDU_TX_REPLY                  32
6078bdc5a62SPatrick Kelsey #define BSN_PDU_RX_REQUEST                33
6088bdc5a62SPatrick Kelsey #define BSN_PDU_RX_REPLY                  34
6098bdc5a62SPatrick Kelsey #define BSN_PDU_RX_TIMEOUT                35
6108bdc5a62SPatrick Kelsey 
6118bdc5a62SPatrick Kelsey static const struct tok bsn_subtype_str[] = {
6128bdc5a62SPatrick Kelsey 	{ BSN_SET_IP_MASK,                   "SET_IP_MASK"                   },
6138bdc5a62SPatrick Kelsey 	{ BSN_GET_IP_MASK_REQUEST,           "GET_IP_MASK_REQUEST"           },
6148bdc5a62SPatrick Kelsey 	{ BSN_GET_IP_MASK_REPLY,             "GET_IP_MASK_REPLY"             },
6158bdc5a62SPatrick Kelsey 	{ BSN_SET_MIRRORING,                 "SET_MIRRORING"                 },
6168bdc5a62SPatrick Kelsey 	{ BSN_GET_MIRRORING_REQUEST,         "GET_MIRRORING_REQUEST"         },
6178bdc5a62SPatrick Kelsey 	{ BSN_GET_MIRRORING_REPLY,           "GET_MIRRORING_REPLY"           },
6188bdc5a62SPatrick Kelsey 	{ BSN_SHELL_COMMAND,                 "SHELL_COMMAND"                 },
6198bdc5a62SPatrick Kelsey 	{ BSN_SHELL_OUTPUT,                  "SHELL_OUTPUT"                  },
6208bdc5a62SPatrick Kelsey 	{ BSN_SHELL_STATUS,                  "SHELL_STATUS"                  },
6218bdc5a62SPatrick Kelsey 	{ BSN_GET_INTERFACES_REQUEST,        "GET_INTERFACES_REQUEST"        },
6228bdc5a62SPatrick Kelsey 	{ BSN_GET_INTERFACES_REPLY,          "GET_INTERFACES_REPLY"          },
6238bdc5a62SPatrick Kelsey 	{ BSN_SET_PKTIN_SUPPRESSION_REQUEST, "SET_PKTIN_SUPPRESSION_REQUEST" },
6248bdc5a62SPatrick Kelsey 	{ BSN_SET_L2_TABLE_REQUEST,          "SET_L2_TABLE_REQUEST"          },
6258bdc5a62SPatrick Kelsey 	{ BSN_GET_L2_TABLE_REQUEST,          "GET_L2_TABLE_REQUEST"          },
6268bdc5a62SPatrick Kelsey 	{ BSN_GET_L2_TABLE_REPLY,            "GET_L2_TABLE_REPLY"            },
6278bdc5a62SPatrick Kelsey 	{ BSN_VIRTUAL_PORT_CREATE_REQUEST,   "VIRTUAL_PORT_CREATE_REQUEST"   },
6288bdc5a62SPatrick Kelsey 	{ BSN_VIRTUAL_PORT_CREATE_REPLY,     "VIRTUAL_PORT_CREATE_REPLY"     },
6298bdc5a62SPatrick Kelsey 	{ BSN_VIRTUAL_PORT_REMOVE_REQUEST,   "VIRTUAL_PORT_REMOVE_REQUEST"   },
6308bdc5a62SPatrick Kelsey 	{ BSN_BW_ENABLE_SET_REQUEST,         "BW_ENABLE_SET_REQUEST"         },
6318bdc5a62SPatrick Kelsey 	{ BSN_BW_ENABLE_GET_REQUEST,         "BW_ENABLE_GET_REQUEST"         },
6328bdc5a62SPatrick Kelsey 	{ BSN_BW_ENABLE_GET_REPLY,           "BW_ENABLE_GET_REPLY"           },
6338bdc5a62SPatrick Kelsey 	{ BSN_BW_CLEAR_DATA_REQUEST,         "BW_CLEAR_DATA_REQUEST"         },
6348bdc5a62SPatrick Kelsey 	{ BSN_BW_CLEAR_DATA_REPLY,           "BW_CLEAR_DATA_REPLY"           },
6358bdc5a62SPatrick Kelsey 	{ BSN_BW_ENABLE_SET_REPLY,           "BW_ENABLE_SET_REPLY"           },
6368bdc5a62SPatrick Kelsey 	{ BSN_SET_L2_TABLE_REPLY,            "SET_L2_TABLE_REPLY"            },
6378bdc5a62SPatrick Kelsey 	{ BSN_SET_PKTIN_SUPPRESSION_REPLY,   "SET_PKTIN_SUPPRESSION_REPLY"   },
6388bdc5a62SPatrick Kelsey 	{ BSN_VIRTUAL_PORT_REMOVE_REPLY,     "VIRTUAL_PORT_REMOVE_REPLY"     },
6398bdc5a62SPatrick Kelsey 	{ BSN_HYBRID_GET_REQUEST,            "HYBRID_GET_REQUEST"            },
6408bdc5a62SPatrick Kelsey 	{ BSN_HYBRID_GET_REPLY,              "HYBRID_GET_REPLY"              },
6418bdc5a62SPatrick Kelsey 	{ BSN_PDU_TX_REQUEST,                "PDU_TX_REQUEST"                },
6428bdc5a62SPatrick Kelsey 	{ BSN_PDU_TX_REPLY,                  "PDU_TX_REPLY"                  },
6438bdc5a62SPatrick Kelsey 	{ BSN_PDU_RX_REQUEST,                "PDU_RX_REQUEST"                },
6448bdc5a62SPatrick Kelsey 	{ BSN_PDU_RX_REPLY,                  "PDU_RX_REPLY"                  },
6458bdc5a62SPatrick Kelsey 	{ BSN_PDU_RX_TIMEOUT,                "PDU_RX_TIMEOUT"                },
6468bdc5a62SPatrick Kelsey 	{ 0, NULL }
6478bdc5a62SPatrick Kelsey };
6488bdc5a62SPatrick Kelsey 
6498bdc5a62SPatrick Kelsey #define BSN_ACTION_MIRROR                  1
6508bdc5a62SPatrick Kelsey #define BSN_ACTION_SET_TUNNEL_DST          2
6518bdc5a62SPatrick Kelsey                                         /* 3 */
6528bdc5a62SPatrick Kelsey #define BSN_ACTION_CHECKSUM                4
6538bdc5a62SPatrick Kelsey 
6548bdc5a62SPatrick Kelsey static const struct tok bsn_action_subtype_str[] = {
6558bdc5a62SPatrick Kelsey 	{ BSN_ACTION_MIRROR,                 "MIRROR"                        },
6568bdc5a62SPatrick Kelsey 	{ BSN_ACTION_SET_TUNNEL_DST,         "SET_TUNNEL_DST"                },
6578bdc5a62SPatrick Kelsey 	{ BSN_ACTION_CHECKSUM,               "CHECKSUM"                      },
6588bdc5a62SPatrick Kelsey 	{ 0, NULL }
6598bdc5a62SPatrick Kelsey };
6608bdc5a62SPatrick Kelsey 
6618bdc5a62SPatrick Kelsey static const struct tok bsn_mirror_copy_stage_str[] = {
6628bdc5a62SPatrick Kelsey 	{ 0, "INGRESS" },
6638bdc5a62SPatrick Kelsey 	{ 1, "EGRESS"  },
6648bdc5a62SPatrick Kelsey 	{ 0, NULL },
6658bdc5a62SPatrick Kelsey };
6668bdc5a62SPatrick Kelsey 
6678bdc5a62SPatrick Kelsey static const struct tok bsn_onoff_str[] = {
6688bdc5a62SPatrick Kelsey 	{ 0, "OFF" },
6698bdc5a62SPatrick Kelsey 	{ 1, "ON"  },
6708bdc5a62SPatrick Kelsey 	{ 0, NULL },
6718bdc5a62SPatrick Kelsey };
6728bdc5a62SPatrick Kelsey 
6733c602fabSXin LI static const char *
vlan_str(const uint16_t vid)6748bdc5a62SPatrick Kelsey vlan_str(const uint16_t vid)
6758bdc5a62SPatrick Kelsey {
6763c602fabSXin LI 	static char buf[sizeof("65535 (bogus)")];
6773c602fabSXin LI 
6783c602fabSXin LI 	if (vid == OFP_VLAN_NONE)
6793c602fabSXin LI 		return "NONE";
680ee67461eSJoseph Mingrone 	snprintf(buf, sizeof(buf), "%u%s", vid,
681ee67461eSJoseph Mingrone 	         (vid > 0 && vid < 0x0fff) ? "" : " (bogus)");
6823c602fabSXin LI 	return buf;
6833c602fabSXin LI }
6843c602fabSXin LI 
6853c602fabSXin LI static const char *
pcp_str(const uint8_t pcp)6868bdc5a62SPatrick Kelsey pcp_str(const uint8_t pcp)
6878bdc5a62SPatrick Kelsey {
6883c602fabSXin LI 	static char buf[sizeof("255 (bogus)")];
689ee67461eSJoseph Mingrone 	snprintf(buf, sizeof(buf), "%u%s", pcp,
690ee67461eSJoseph Mingrone 	         pcp <= 7 ? "" : " (bogus)");
6913c602fabSXin LI 	return buf;
6923c602fabSXin LI }
6933c602fabSXin LI 
6943c602fabSXin LI static void
of10_bsn_message_print(netdissect_options * ndo,const u_char * cp,u_int len)6958bdc5a62SPatrick Kelsey of10_bsn_message_print(netdissect_options *ndo,
696ee67461eSJoseph Mingrone                        const u_char *cp, u_int len)
6978bdc5a62SPatrick Kelsey {
6988bdc5a62SPatrick Kelsey 	uint32_t subtype;
6998bdc5a62SPatrick Kelsey 
700*0a7e5f1fSJoseph Mingrone 	ND_PRINT("\n\t");
701*0a7e5f1fSJoseph Mingrone 	ND_ICHECK_U(len, <, 4);
7028bdc5a62SPatrick Kelsey 	/* subtype */
703ee67461eSJoseph Mingrone 	subtype = GET_BE_U_4(cp);
704ee67461eSJoseph Mingrone 	OF_FWD(4);
705*0a7e5f1fSJoseph Mingrone 	ND_PRINT(" subtype %s", tok2str(bsn_subtype_str, "unknown (0x%08x)", subtype));
7068bdc5a62SPatrick Kelsey 	switch (subtype) {
7078bdc5a62SPatrick Kelsey 	case BSN_GET_IP_MASK_REQUEST:
7088bdc5a62SPatrick Kelsey 		/*
7098bdc5a62SPatrick Kelsey 		 *  0                   1                   2                   3
7108bdc5a62SPatrick Kelsey 		 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
7118bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
7128bdc5a62SPatrick Kelsey 		 * |                            subtype                            |
7138bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
7148bdc5a62SPatrick Kelsey 		 * |     index     |                      pad                      |
7158bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
7168bdc5a62SPatrick Kelsey 		 * |                              pad                              |
7178bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
7188bdc5a62SPatrick Kelsey 		 *
7198bdc5a62SPatrick Kelsey 		 */
720*0a7e5f1fSJoseph Mingrone 		ND_ICHECK_U(len, !=, 8);
7218bdc5a62SPatrick Kelsey 		/* index */
722ee67461eSJoseph Mingrone 		ND_PRINT(", index %u", GET_U_1(cp));
723ee67461eSJoseph Mingrone 		OF_FWD(1);
7248bdc5a62SPatrick Kelsey 		/* pad */
725ee67461eSJoseph Mingrone 		/* Always the last field, check bounds. */
726ee67461eSJoseph Mingrone 		ND_TCHECK_7(cp);
7278bdc5a62SPatrick Kelsey 		break;
7288bdc5a62SPatrick Kelsey 	case BSN_SET_IP_MASK:
7298bdc5a62SPatrick Kelsey 	case BSN_GET_IP_MASK_REPLY:
7308bdc5a62SPatrick Kelsey 		/*
7318bdc5a62SPatrick Kelsey 		 *  0                   1                   2                   3
7328bdc5a62SPatrick Kelsey 		 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
7338bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
7348bdc5a62SPatrick Kelsey 		 * |                            subtype                            |
7358bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
7368bdc5a62SPatrick Kelsey 		 * |     index     |                      pad                      |
7378bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
7388bdc5a62SPatrick Kelsey 		 * |                              mask                             |
7398bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
7408bdc5a62SPatrick Kelsey 		 *
7418bdc5a62SPatrick Kelsey 		 */
742*0a7e5f1fSJoseph Mingrone 		ND_ICHECK_U(len, !=, 8);
7438bdc5a62SPatrick Kelsey 		/* index */
744ee67461eSJoseph Mingrone 		ND_PRINT(", index %u", GET_U_1(cp));
745ee67461eSJoseph Mingrone 		OF_FWD(1);
7468bdc5a62SPatrick Kelsey 		/* pad */
747ee67461eSJoseph Mingrone 		OF_FWD(3);
7488bdc5a62SPatrick Kelsey 		/* mask */
749ee67461eSJoseph Mingrone 		ND_PRINT(", mask %s", GET_IPADDR_STRING(cp));
7508bdc5a62SPatrick Kelsey 		break;
7518bdc5a62SPatrick Kelsey 	case BSN_SET_MIRRORING:
7528bdc5a62SPatrick Kelsey 	case BSN_GET_MIRRORING_REQUEST:
7538bdc5a62SPatrick Kelsey 	case BSN_GET_MIRRORING_REPLY:
7548bdc5a62SPatrick Kelsey 		/*
7558bdc5a62SPatrick Kelsey 		 *  0                   1                   2                   3
7568bdc5a62SPatrick Kelsey 		 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
7578bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
7588bdc5a62SPatrick Kelsey 		 * |                            subtype                            |
7598bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
7608bdc5a62SPatrick Kelsey 		 * | report m. p.  |                      pad                      |
7618bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
7628bdc5a62SPatrick Kelsey 		 *
7638bdc5a62SPatrick Kelsey 		 */
764*0a7e5f1fSJoseph Mingrone 		ND_ICHECK_U(len, !=, 4);
7658bdc5a62SPatrick Kelsey 		/* report_mirror_ports */
766ee67461eSJoseph Mingrone 		ND_PRINT(", report_mirror_ports %s",
767ee67461eSJoseph Mingrone 			 tok2str(bsn_onoff_str, "bogus (%u)", GET_U_1(cp)));
768ee67461eSJoseph Mingrone 		OF_FWD(1);
7698bdc5a62SPatrick Kelsey 		/* pad */
770ee67461eSJoseph Mingrone 		/* Always the last field, check bounds. */
771ee67461eSJoseph Mingrone 		ND_TCHECK_3(cp);
7728bdc5a62SPatrick Kelsey 		break;
7738bdc5a62SPatrick Kelsey 	case BSN_GET_INTERFACES_REQUEST:
7748bdc5a62SPatrick Kelsey 	case BSN_GET_L2_TABLE_REQUEST:
7758bdc5a62SPatrick Kelsey 	case BSN_BW_ENABLE_GET_REQUEST:
7768bdc5a62SPatrick Kelsey 	case BSN_BW_CLEAR_DATA_REQUEST:
7778bdc5a62SPatrick Kelsey 	case BSN_HYBRID_GET_REQUEST:
7788bdc5a62SPatrick Kelsey 		/*
7798bdc5a62SPatrick Kelsey 		 *  0                   1                   2                   3
7808bdc5a62SPatrick Kelsey 		 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
7818bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
7828bdc5a62SPatrick Kelsey 		 * |                            subtype                            |
7838bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
7848bdc5a62SPatrick Kelsey 		 *
7858bdc5a62SPatrick Kelsey 		 */
786*0a7e5f1fSJoseph Mingrone 		ND_ICHECK_U(len, !=, 0);
7878bdc5a62SPatrick Kelsey 		break;
7888bdc5a62SPatrick Kelsey 	case BSN_VIRTUAL_PORT_REMOVE_REQUEST:
7898bdc5a62SPatrick Kelsey 		/*
7908bdc5a62SPatrick Kelsey 		 *  0                   1                   2                   3
7918bdc5a62SPatrick Kelsey 		 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
7928bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
7938bdc5a62SPatrick Kelsey 		 * |                            subtype                            |
7948bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
7958bdc5a62SPatrick Kelsey 		 * |                           vport_no                            |
7968bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
7978bdc5a62SPatrick Kelsey 		 *
7988bdc5a62SPatrick Kelsey 		 */
799*0a7e5f1fSJoseph Mingrone 		ND_ICHECK_U(len, !=, 4);
8008bdc5a62SPatrick Kelsey 		/* vport_no */
801ee67461eSJoseph Mingrone 		ND_PRINT(", vport_no %u", GET_BE_U_4(cp));
8028bdc5a62SPatrick Kelsey 		break;
8038bdc5a62SPatrick Kelsey 	case BSN_SHELL_COMMAND:
8048bdc5a62SPatrick Kelsey 		/*
8058bdc5a62SPatrick Kelsey 		 *  0                   1                   2                   3
8068bdc5a62SPatrick Kelsey 		 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
8078bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
8088bdc5a62SPatrick Kelsey 		 * |                            subtype                            |
8098bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
8108bdc5a62SPatrick Kelsey 		 * |                            service                            |
8118bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
8128bdc5a62SPatrick Kelsey 		 * |                             data ...
8138bdc5a62SPatrick Kelsey 		 * +---------------+---------------+--------
8148bdc5a62SPatrick Kelsey 		 *
8158bdc5a62SPatrick Kelsey 		 */
816*0a7e5f1fSJoseph Mingrone 		ND_ICHECK_U(len, <, 4);
8178bdc5a62SPatrick Kelsey 		/* service */
818ee67461eSJoseph Mingrone 		ND_PRINT(", service %u", GET_BE_U_4(cp));
819ee67461eSJoseph Mingrone 		OF_FWD(4);
8208bdc5a62SPatrick Kelsey 		/* data */
821ee67461eSJoseph Mingrone 		ND_PRINT(", data '");
822ee67461eSJoseph Mingrone 		(void)nd_printn(ndo, cp, len, NULL);
823ee67461eSJoseph Mingrone 		ND_PRINT("'");
8248bdc5a62SPatrick Kelsey 		break;
8258bdc5a62SPatrick Kelsey 	case BSN_SHELL_OUTPUT:
8268bdc5a62SPatrick Kelsey 		/*
8278bdc5a62SPatrick Kelsey 		 *  0                   1                   2                   3
8288bdc5a62SPatrick Kelsey 		 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
8298bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
8308bdc5a62SPatrick Kelsey 		 * |                            subtype                            |
8318bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
8328bdc5a62SPatrick Kelsey 		 * |                             data ...
8338bdc5a62SPatrick Kelsey 		 * +---------------+---------------+--------
8348bdc5a62SPatrick Kelsey 		 *
8358bdc5a62SPatrick Kelsey 		 */
8368bdc5a62SPatrick Kelsey 		/* already checked that len >= 4 */
8378bdc5a62SPatrick Kelsey 		/* data */
838ee67461eSJoseph Mingrone 		ND_PRINT(", data '");
839ee67461eSJoseph Mingrone 		(void)nd_printn(ndo, cp, len, NULL);
840ee67461eSJoseph Mingrone 		ND_PRINT("'");
8418bdc5a62SPatrick Kelsey 		break;
8428bdc5a62SPatrick Kelsey 	case BSN_SHELL_STATUS:
8438bdc5a62SPatrick Kelsey 		/*
8448bdc5a62SPatrick Kelsey 		 *  0                   1                   2                   3
8458bdc5a62SPatrick Kelsey 		 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
8468bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
8478bdc5a62SPatrick Kelsey 		 * |                            subtype                            |
8488bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
8498bdc5a62SPatrick Kelsey 		 * |                            status                             |
8508bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
8518bdc5a62SPatrick Kelsey 		 *
8528bdc5a62SPatrick Kelsey 		 */
853*0a7e5f1fSJoseph Mingrone 		ND_ICHECK_U(len, !=, 4);
8548bdc5a62SPatrick Kelsey 		/* status */
855ee67461eSJoseph Mingrone 		ND_PRINT(", status 0x%08x", GET_BE_U_4(cp));
8568bdc5a62SPatrick Kelsey 		break;
8578bdc5a62SPatrick Kelsey 	default:
858ee67461eSJoseph Mingrone 		ND_TCHECK_LEN(cp, len);
8598bdc5a62SPatrick Kelsey 	}
860ee67461eSJoseph Mingrone 	return;
8618bdc5a62SPatrick Kelsey 
8623340d773SGleb Smirnoff invalid: /* skip the undersized data */
863ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
864ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
8658bdc5a62SPatrick Kelsey }
8668bdc5a62SPatrick Kelsey 
867ee67461eSJoseph Mingrone static void
of10_bsn_actions_print(netdissect_options * ndo,const u_char * cp,u_int len)8688bdc5a62SPatrick Kelsey of10_bsn_actions_print(netdissect_options *ndo,
869ee67461eSJoseph Mingrone                        const u_char *cp, u_int len)
8708bdc5a62SPatrick Kelsey {
8718bdc5a62SPatrick Kelsey 	uint32_t subtype, vlan_tag;
8728bdc5a62SPatrick Kelsey 
873*0a7e5f1fSJoseph Mingrone 	ND_PRINT("\n\t ");
874*0a7e5f1fSJoseph Mingrone 	ND_ICHECK_U(len, <, 4);
8758bdc5a62SPatrick Kelsey 	/* subtype */
876ee67461eSJoseph Mingrone 	subtype = GET_BE_U_4(cp);
877ee67461eSJoseph Mingrone 	OF_FWD(4);
878*0a7e5f1fSJoseph Mingrone 	ND_PRINT(" subtype %s", tok2str(bsn_action_subtype_str, "unknown (0x%08x)", subtype));
8798bdc5a62SPatrick Kelsey 	switch (subtype) {
8808bdc5a62SPatrick Kelsey 	case BSN_ACTION_MIRROR:
8818bdc5a62SPatrick Kelsey 		/*
8828bdc5a62SPatrick Kelsey 		 *  0                   1                   2                   3
8838bdc5a62SPatrick Kelsey 		 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
8848bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
8858bdc5a62SPatrick Kelsey 		 * |                            subtype                            |
8868bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
8878bdc5a62SPatrick Kelsey 		 * |                           dest_port                           |
8888bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
8898bdc5a62SPatrick Kelsey 		 * |                           vlan_tag                            |
8908bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
8918bdc5a62SPatrick Kelsey 		 * |  copy_stage   |                      pad                      |
8928bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
8938bdc5a62SPatrick Kelsey 		 *
8948bdc5a62SPatrick Kelsey 		 */
895*0a7e5f1fSJoseph Mingrone 		ND_ICHECK_U(len, !=, 12);
8968bdc5a62SPatrick Kelsey 		/* dest_port */
897ee67461eSJoseph Mingrone 		ND_PRINT(", dest_port %u", GET_BE_U_4(cp));
898ee67461eSJoseph Mingrone 		OF_FWD(4);
8998bdc5a62SPatrick Kelsey 		/* vlan_tag */
900ee67461eSJoseph Mingrone 		vlan_tag = GET_BE_U_4(cp);
901ee67461eSJoseph Mingrone 		OF_FWD(4);
9028bdc5a62SPatrick Kelsey 		switch (vlan_tag >> 16) {
9038bdc5a62SPatrick Kelsey 		case 0:
904ee67461eSJoseph Mingrone 			ND_PRINT(", vlan_tag none");
9058bdc5a62SPatrick Kelsey 			break;
9068bdc5a62SPatrick Kelsey 		case ETHERTYPE_8021Q:
907ee67461eSJoseph Mingrone 			ND_PRINT(", vlan_tag 802.1Q (%s)", ieee8021q_tci_string(vlan_tag & 0xffff));
9088bdc5a62SPatrick Kelsey 			break;
9098bdc5a62SPatrick Kelsey 		default:
910ee67461eSJoseph Mingrone 			ND_PRINT(", vlan_tag unknown (0x%04x)", vlan_tag >> 16);
9118bdc5a62SPatrick Kelsey 		}
9128bdc5a62SPatrick Kelsey 		/* copy_stage */
913ee67461eSJoseph Mingrone 		ND_PRINT(", copy_stage %s",
914ee67461eSJoseph Mingrone 			 tok2str(bsn_mirror_copy_stage_str, "unknown (%u)", GET_U_1(cp)));
915ee67461eSJoseph Mingrone 		OF_FWD(1);
9168bdc5a62SPatrick Kelsey 		/* pad */
917ee67461eSJoseph Mingrone 		/* Always the last field, check bounds. */
918ee67461eSJoseph Mingrone 		ND_TCHECK_3(cp);
9198bdc5a62SPatrick Kelsey 		break;
9208bdc5a62SPatrick Kelsey 	default:
921ee67461eSJoseph Mingrone 		ND_TCHECK_LEN(cp, len);
9228bdc5a62SPatrick Kelsey 	}
923ee67461eSJoseph Mingrone 	return;
9248bdc5a62SPatrick Kelsey 
9253340d773SGleb Smirnoff invalid:
926ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
927ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
9288bdc5a62SPatrick Kelsey }
9298bdc5a62SPatrick Kelsey 
930ee67461eSJoseph Mingrone static void
of10_vendor_action_print(netdissect_options * ndo,const u_char * cp,u_int len)9318bdc5a62SPatrick Kelsey of10_vendor_action_print(netdissect_options *ndo,
932ee67461eSJoseph Mingrone                          const u_char *cp, u_int len)
9338bdc5a62SPatrick Kelsey {
9348bdc5a62SPatrick Kelsey 	uint32_t vendor;
935ee67461eSJoseph Mingrone 	void (*decoder)(netdissect_options *, const u_char *, u_int);
9368bdc5a62SPatrick Kelsey 
937*0a7e5f1fSJoseph Mingrone 	ND_ICHECK_U(len, <, 4);
9383c602fabSXin LI 	/* vendor */
939ee67461eSJoseph Mingrone 	vendor = GET_BE_U_4(cp);
940ee67461eSJoseph Mingrone 	OF_FWD(4);
941ee67461eSJoseph Mingrone 	ND_PRINT(", vendor 0x%08x (%s)", vendor, of_vendor_name(vendor));
9428bdc5a62SPatrick Kelsey 	/* data */
9438bdc5a62SPatrick Kelsey 	decoder =
9448bdc5a62SPatrick Kelsey 		vendor == OUI_BSN         ? of10_bsn_actions_print         :
945ee67461eSJoseph Mingrone 		of_data_print;
946ee67461eSJoseph Mingrone 	decoder(ndo, cp, len);
947ee67461eSJoseph Mingrone 	return;
9488bdc5a62SPatrick Kelsey 
9493340d773SGleb Smirnoff invalid: /* skip the undersized data */
950ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
951ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
9528bdc5a62SPatrick Kelsey }
9538bdc5a62SPatrick Kelsey 
954ee67461eSJoseph Mingrone /* [OF10] Section 5.5.4 */
955ee67461eSJoseph Mingrone static void
of10_vendor_message_print(netdissect_options * ndo,const u_char * cp,u_int len)9568bdc5a62SPatrick Kelsey of10_vendor_message_print(netdissect_options *ndo,
957ee67461eSJoseph Mingrone                           const u_char *cp, u_int len)
9588bdc5a62SPatrick Kelsey {
9598bdc5a62SPatrick Kelsey 	uint32_t vendor;
960ee67461eSJoseph Mingrone 	void (*decoder)(netdissect_options *, const u_char *, u_int);
9618bdc5a62SPatrick Kelsey 
9628bdc5a62SPatrick Kelsey 	/* vendor */
963ee67461eSJoseph Mingrone 	vendor = GET_BE_U_4(cp);
964ee67461eSJoseph Mingrone 	OF_FWD(4);
965ee67461eSJoseph Mingrone 	ND_PRINT(", vendor 0x%08x (%s)", vendor, of_vendor_name(vendor));
9668bdc5a62SPatrick Kelsey 	/* data */
9678bdc5a62SPatrick Kelsey 	decoder =
9688bdc5a62SPatrick Kelsey 		vendor == OUI_BSN         ? of10_bsn_message_print         :
969ee67461eSJoseph Mingrone 		of_data_print;
970ee67461eSJoseph Mingrone 	decoder(ndo, cp, len);
9718bdc5a62SPatrick Kelsey }
9728bdc5a62SPatrick Kelsey 
9738bdc5a62SPatrick Kelsey /* Vendor ID is mandatory, data is optional. */
974ee67461eSJoseph Mingrone static void
of10_vendor_data_print(netdissect_options * ndo,const u_char * cp,u_int len)9758bdc5a62SPatrick Kelsey of10_vendor_data_print(netdissect_options *ndo,
976ee67461eSJoseph Mingrone                        const u_char *cp, u_int len)
9778bdc5a62SPatrick Kelsey {
9788bdc5a62SPatrick Kelsey 	uint32_t vendor;
9798bdc5a62SPatrick Kelsey 
980*0a7e5f1fSJoseph Mingrone 	ND_ICHECK_U(len, <, 4);
9818bdc5a62SPatrick Kelsey 	/* vendor */
982ee67461eSJoseph Mingrone 	vendor = GET_BE_U_4(cp);
983ee67461eSJoseph Mingrone 	OF_FWD(4);
984ee67461eSJoseph Mingrone 	ND_PRINT(", vendor 0x%08x (%s)", vendor, of_vendor_name(vendor));
9853c602fabSXin LI 	/* data */
986ee67461eSJoseph Mingrone 	of_data_print(ndo, cp, len);
987ee67461eSJoseph Mingrone 	return;
9883c602fabSXin LI 
9893340d773SGleb Smirnoff invalid: /* skip the undersized data */
990ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
991ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
9923c602fabSXin LI }
9933c602fabSXin LI 
994ee67461eSJoseph Mingrone static void
of10_packet_data_print(netdissect_options * ndo,const u_char * cp,const u_int len)9953c602fabSXin LI of10_packet_data_print(netdissect_options *ndo,
996ee67461eSJoseph Mingrone                        const u_char *cp, const u_int len)
9978bdc5a62SPatrick Kelsey {
9983c602fabSXin LI 	if (len == 0)
999ee67461eSJoseph Mingrone 		return;
10003c602fabSXin LI 	/* data */
1001ee67461eSJoseph Mingrone 	ND_PRINT("\n\t data (%u octets)", len);
1002ee67461eSJoseph Mingrone 	if (ndo->ndo_vflag < 3) {
1003ee67461eSJoseph Mingrone 		ND_TCHECK_LEN(cp, len);
1004ee67461eSJoseph Mingrone 		return;
1005ee67461eSJoseph Mingrone 	}
10063c602fabSXin LI 	ndo->ndo_vflag -= 3;
1007ee67461eSJoseph Mingrone 	ND_PRINT(", frame decoding below\n");
1008ee67461eSJoseph Mingrone 	/*
1009ee67461eSJoseph Mingrone 	 * The encapsulated Ethernet frame is not necessarily the last
1010ee67461eSJoseph Mingrone 	 * data of this packet (i.e. there may be more OpenFlow messages
1011ee67461eSJoseph Mingrone 	 * after the current OFPT_PACKET_IN/OFPT_PACKET_OUT message, in
1012ee67461eSJoseph Mingrone 	 * which case the current (outer) packet's snapshot end is not
1013ee67461eSJoseph Mingrone 	 * what ether_print() needs to decode an Ethernet frame nested in
1014ee67461eSJoseph Mingrone 	 * the middle of a TCP payload.
1015ee67461eSJoseph Mingrone 	 */
1016ee67461eSJoseph Mingrone 	const u_char *snapend_save = ndo->ndo_snapend;
1017ee67461eSJoseph Mingrone 	ndo->ndo_snapend = ND_MIN(cp + len, ndo->ndo_snapend);
1018ee67461eSJoseph Mingrone 	ether_print(ndo, cp, len, ND_BYTES_AVAILABLE_AFTER(cp), NULL, NULL);
1019ee67461eSJoseph Mingrone 	ndo->ndo_snapend = snapend_save;
10203c602fabSXin LI 	ndo->ndo_vflag += 3;
10213c602fabSXin LI }
10223c602fabSXin LI 
10233c602fabSXin LI /* [OF10] Section 5.2.1 */
1024ee67461eSJoseph Mingrone static void
of10_phy_port_print(netdissect_options * ndo,const u_char * cp)1025ee67461eSJoseph Mingrone of10_phy_port_print(netdissect_options *ndo,
1026ee67461eSJoseph Mingrone                     const u_char *cp)
10278bdc5a62SPatrick Kelsey {
1028ee67461eSJoseph Mingrone 	uint32_t state;
10293c602fabSXin LI 
10303c602fabSXin LI 	/* port_no */
1031ee67461eSJoseph Mingrone 	ND_PRINT("\n\t  port_no %s",
1032ee67461eSJoseph Mingrone 		 tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
10333c602fabSXin LI 	cp += 2;
10343c602fabSXin LI 	/* hw_addr */
1035ee67461eSJoseph Mingrone 	ND_PRINT(", hw_addr %s", GET_ETHERADDR_STRING(cp));
1036ee67461eSJoseph Mingrone 	cp += MAC_ADDR_LEN;
10373c602fabSXin LI 	/* name */
1038ee67461eSJoseph Mingrone 	ND_PRINT(", name '");
1039ee67461eSJoseph Mingrone 	nd_printjnp(ndo, cp, OFP_MAX_PORT_NAME_LEN);
1040ee67461eSJoseph Mingrone 	ND_PRINT("'");
10413c602fabSXin LI 	cp += OFP_MAX_PORT_NAME_LEN;
10423c602fabSXin LI 
10433c602fabSXin LI 	if (ndo->ndo_vflag < 2) {
1044ee67461eSJoseph Mingrone 		ND_TCHECK_LEN(cp, 24);
1045ee67461eSJoseph Mingrone 		return;
10463c602fabSXin LI 	}
10473c602fabSXin LI 	/* config */
1048ee67461eSJoseph Mingrone 	ND_PRINT("\n\t   config 0x%08x", GET_BE_U_4(cp));
1049ee67461eSJoseph Mingrone 	of_bitmap_print(ndo, ofppc_bm, GET_BE_U_4(cp), OFPPC_U);
10503c602fabSXin LI 	cp += 4;
10513c602fabSXin LI 	/* state */
1052ee67461eSJoseph Mingrone 	state = GET_BE_U_4(cp);
1053ee67461eSJoseph Mingrone 	/*
1054ee67461eSJoseph Mingrone 	 * Decode the code point and the single bit separately, but
1055ee67461eSJoseph Mingrone 	 * format the result as a single sequence of comma-separated
1056ee67461eSJoseph Mingrone 	 * strings (see the comments at the OFPPS_ props).
1057ee67461eSJoseph Mingrone 	 */
1058ee67461eSJoseph Mingrone 	ND_PRINT("\n\t   state 0x%08x (%s%s)%s", state,
1059ee67461eSJoseph Mingrone 	         tok2str(ofpps_stp_str, "", state & OFPPS_STP_MASK),
1060ee67461eSJoseph Mingrone 	         state & OFPPS_LINK_DOWN ? ", LINK_DOWN" : "",
1061ee67461eSJoseph Mingrone 	         state & OFPPS_U ? " (bogus)" : "");
10623c602fabSXin LI 	cp += 4;
10633c602fabSXin LI 	/* curr */
1064ee67461eSJoseph Mingrone 	ND_PRINT("\n\t   curr 0x%08x", GET_BE_U_4(cp));
1065ee67461eSJoseph Mingrone 	of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U);
10663c602fabSXin LI 	cp += 4;
10673c602fabSXin LI 	/* advertised */
1068ee67461eSJoseph Mingrone 	ND_PRINT("\n\t   advertised 0x%08x", GET_BE_U_4(cp));
1069ee67461eSJoseph Mingrone 	of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U);
10703c602fabSXin LI 	cp += 4;
10713c602fabSXin LI 	/* supported */
1072ee67461eSJoseph Mingrone 	ND_PRINT("\n\t   supported 0x%08x", GET_BE_U_4(cp));
1073ee67461eSJoseph Mingrone 	of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U);
10743c602fabSXin LI 	cp += 4;
10753c602fabSXin LI 	/* peer */
1076ee67461eSJoseph Mingrone 	ND_PRINT("\n\t   peer 0x%08x", GET_BE_U_4(cp));
1077ee67461eSJoseph Mingrone 	of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U);
10783c602fabSXin LI }
10793c602fabSXin LI 
10803c602fabSXin LI /* [OF10] Section 5.2.2 */
1081ee67461eSJoseph Mingrone static void
of10_queue_props_print(netdissect_options * ndo,const u_char * cp,u_int len)10823c602fabSXin LI of10_queue_props_print(netdissect_options *ndo,
1083ee67461eSJoseph Mingrone                        const u_char *cp, u_int len)
10848bdc5a62SPatrick Kelsey {
10853c602fabSXin LI 	while (len) {
1086ee67461eSJoseph Mingrone 		uint16_t property, plen;
10873c602fabSXin LI 		u_char plen_bogus = 0, skip = 0;
10883c602fabSXin LI 
1089*0a7e5f1fSJoseph Mingrone 		ND_PRINT("\n\t  ");
1090*0a7e5f1fSJoseph Mingrone 		ND_ICHECKMSG_U("remaining length", len, <, OF_QUEUE_PROP_MINLEN);
10913c602fabSXin LI 		/* property */
1092ee67461eSJoseph Mingrone 		property = GET_BE_U_2(cp);
1093ee67461eSJoseph Mingrone 		OF_FWD(2);
1094*0a7e5f1fSJoseph Mingrone 		ND_PRINT(" property %s", tok2str(ofpqt_str, "invalid (0x%04x)", property));
10953c602fabSXin LI 		/* len */
1096ee67461eSJoseph Mingrone 		plen = GET_BE_U_2(cp);
1097ee67461eSJoseph Mingrone 		OF_FWD(2);
1098ee67461eSJoseph Mingrone 		ND_PRINT(", len %u", plen);
1099*0a7e5f1fSJoseph Mingrone 		ND_ICHECKMSG_U("property length", plen, <, OF_QUEUE_PROP_MINLEN);
1100*0a7e5f1fSJoseph Mingrone 		ND_ICHECKMSG_U("property length", plen, >, len + 4);
11013c602fabSXin LI 		/* pad */
1102ee67461eSJoseph Mingrone 		/* Sometimes the last field, check bounds. */
1103ee67461eSJoseph Mingrone 		OF_CHK_FWD(4);
11043c602fabSXin LI 		/* property-specific constraints and decoding */
11053c602fabSXin LI 		switch (property) {
11063c602fabSXin LI 		case OFPQT_NONE:
1107ee67461eSJoseph Mingrone 			plen_bogus = plen != OF_QUEUE_PROP_MINLEN;
11083c602fabSXin LI 			break;
11093c602fabSXin LI 		case OFPQT_MIN_RATE:
1110ee67461eSJoseph Mingrone 			plen_bogus = plen != OF_QUEUE_PROP_MIN_RATE_FIXLEN;
11113c602fabSXin LI 			break;
11123c602fabSXin LI 		default:
11133c602fabSXin LI 			skip = 1;
11143c602fabSXin LI 		}
11153c602fabSXin LI 		if (plen_bogus) {
1116ee67461eSJoseph Mingrone 			ND_PRINT(" (bogus)");
11173c602fabSXin LI 			skip = 1;
11183c602fabSXin LI 		}
11193c602fabSXin LI 		if (skip) {
1120ee67461eSJoseph Mingrone 			/*
1121ee67461eSJoseph Mingrone 			 * plen >= OF_QUEUE_PROP_MINLEN
1122ee67461eSJoseph Mingrone 			 * cp is OF_QUEUE_PROP_MINLEN bytes in
1123ee67461eSJoseph Mingrone 			 */
1124ee67461eSJoseph Mingrone 			OF_CHK_FWD(plen - OF_QUEUE_PROP_MINLEN);
1125ee67461eSJoseph Mingrone 			continue;
11263c602fabSXin LI 		}
11273c602fabSXin LI 		if (property == OFPQT_MIN_RATE) { /* the only case of property decoding */
11283c602fabSXin LI 			/* rate */
1129ee67461eSJoseph Mingrone 			uint16_t rate = GET_BE_U_2(cp);
1130ee67461eSJoseph Mingrone 			OF_FWD(2);
11313c602fabSXin LI 			if (rate > 1000)
1132ee67461eSJoseph Mingrone 				ND_PRINT(", rate disabled");
11333c602fabSXin LI 			else
1134ee67461eSJoseph Mingrone 				ND_PRINT(", rate %u.%u%%", rate / 10, rate % 10);
11353c602fabSXin LI 			/* pad */
1136ee67461eSJoseph Mingrone 			/* Sometimes the last field, check bounds. */
1137ee67461eSJoseph Mingrone 			OF_CHK_FWD(6);
11383c602fabSXin LI 		}
11393c602fabSXin LI 	} /* while */
1140ee67461eSJoseph Mingrone 	return;
11413c602fabSXin LI 
11423340d773SGleb Smirnoff invalid: /* skip the rest of queue properties */
1143ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
1144ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
11453c602fabSXin LI }
11463c602fabSXin LI 
11473c602fabSXin LI /* ibid */
1148ee67461eSJoseph Mingrone static void
of10_queues_print(netdissect_options * ndo,const u_char * cp,u_int len)11493c602fabSXin LI of10_queues_print(netdissect_options *ndo,
1150ee67461eSJoseph Mingrone                   const u_char *cp, u_int len)
11518bdc5a62SPatrick Kelsey {
1152ee67461eSJoseph Mingrone 	while (len) {
11533c602fabSXin LI 		uint16_t desclen;
11543c602fabSXin LI 
1155*0a7e5f1fSJoseph Mingrone 		ND_PRINT("\n\t ");
1156*0a7e5f1fSJoseph Mingrone 		ND_ICHECKMSG_U("remaining length", len, <, OF_PACKET_QUEUE_MINLEN);
11573c602fabSXin LI 		/* queue_id */
1158*0a7e5f1fSJoseph Mingrone 		ND_PRINT(" queue_id %u", GET_BE_U_4(cp));
1159ee67461eSJoseph Mingrone 		OF_FWD(4);
11603c602fabSXin LI 		/* len */
1161ee67461eSJoseph Mingrone 		desclen = GET_BE_U_2(cp);
1162ee67461eSJoseph Mingrone 		OF_FWD(2);
1163ee67461eSJoseph Mingrone 		ND_PRINT(", len %u", desclen);
1164*0a7e5f1fSJoseph Mingrone 		ND_ICHECKMSG_U("prop. desc. length", desclen, <, OF_PACKET_QUEUE_MINLEN);
1165*0a7e5f1fSJoseph Mingrone 		ND_ICHECKMSG_U("prop. desc. length", desclen, >, len + 6);
11663c602fabSXin LI 		/* pad */
1167ee67461eSJoseph Mingrone 		/* Sometimes the last field, check bounds. */
1168ee67461eSJoseph Mingrone 		OF_CHK_FWD(2);
11693c602fabSXin LI 		/* properties */
1170ee67461eSJoseph Mingrone 		if (ndo->ndo_vflag >= 2)
1171ee67461eSJoseph Mingrone 			of10_queue_props_print(ndo, cp, desclen - OF_PACKET_QUEUE_MINLEN);
1172ee67461eSJoseph Mingrone 		else
1173ee67461eSJoseph Mingrone 			ND_TCHECK_LEN(cp, desclen - OF_PACKET_QUEUE_MINLEN);
1174ee67461eSJoseph Mingrone 		OF_FWD(desclen - OF_PACKET_QUEUE_MINLEN);
11753c602fabSXin LI 	} /* while */
1176ee67461eSJoseph Mingrone 	return;
11773c602fabSXin LI 
11783340d773SGleb Smirnoff invalid: /* skip the rest of queues */
1179ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
1180ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
11813c602fabSXin LI }
11823c602fabSXin LI 
11833c602fabSXin LI /* [OF10] Section 5.2.3 */
1184ee67461eSJoseph Mingrone static void
of10_match_print(netdissect_options * ndo,const char * pfx,const u_char * cp)11853c602fabSXin LI of10_match_print(netdissect_options *ndo,
1186ee67461eSJoseph Mingrone                  const char *pfx, const u_char *cp)
11878bdc5a62SPatrick Kelsey {
11883c602fabSXin LI 	uint32_t wildcards;
11893c602fabSXin LI 	uint16_t dl_type;
11903c602fabSXin LI 	uint8_t nw_proto;
1191ee67461eSJoseph Mingrone 	u_int nw_bits;
11923c602fabSXin LI 	const char *field_name;
11933c602fabSXin LI 
11943c602fabSXin LI 	/* wildcards */
1195ee67461eSJoseph Mingrone 	wildcards = GET_BE_U_4(cp);
11963c602fabSXin LI 	if (wildcards & OFPFW_U)
1197ee67461eSJoseph Mingrone 		ND_PRINT("%swildcards 0x%08x (bogus)", pfx, wildcards);
11983c602fabSXin LI 	cp += 4;
11993c602fabSXin LI 	/* in_port */
12003c602fabSXin LI 	if (! (wildcards & OFPFW_IN_PORT))
1201ee67461eSJoseph Mingrone 		ND_PRINT("%smatch in_port %s", pfx,
1202ee67461eSJoseph Mingrone 		         tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
12033c602fabSXin LI 	cp += 2;
12043c602fabSXin LI 	/* dl_src */
12053c602fabSXin LI 	if (! (wildcards & OFPFW_DL_SRC))
1206ee67461eSJoseph Mingrone 		ND_PRINT("%smatch dl_src %s", pfx, GET_ETHERADDR_STRING(cp));
1207ee67461eSJoseph Mingrone 	cp += MAC_ADDR_LEN;
12083c602fabSXin LI 	/* dl_dst */
12093c602fabSXin LI 	if (! (wildcards & OFPFW_DL_DST))
1210ee67461eSJoseph Mingrone 		ND_PRINT("%smatch dl_dst %s", pfx, GET_ETHERADDR_STRING(cp));
1211ee67461eSJoseph Mingrone 	cp += MAC_ADDR_LEN;
12123c602fabSXin LI 	/* dl_vlan */
12133c602fabSXin LI 	if (! (wildcards & OFPFW_DL_VLAN))
1214ee67461eSJoseph Mingrone 		ND_PRINT("%smatch dl_vlan %s", pfx, vlan_str(GET_BE_U_2(cp)));
12153c602fabSXin LI 	cp += 2;
12163c602fabSXin LI 	/* dl_vlan_pcp */
12173c602fabSXin LI 	if (! (wildcards & OFPFW_DL_VLAN_PCP))
1218ee67461eSJoseph Mingrone 		ND_PRINT("%smatch dl_vlan_pcp %s", pfx, pcp_str(GET_U_1(cp)));
12193c602fabSXin LI 	cp += 1;
12203c602fabSXin LI 	/* pad1 */
12213c602fabSXin LI 	cp += 1;
12223c602fabSXin LI 	/* dl_type */
1223ee67461eSJoseph Mingrone 	dl_type = GET_BE_U_2(cp);
12243c602fabSXin LI 	cp += 2;
12253c602fabSXin LI 	if (! (wildcards & OFPFW_DL_TYPE))
1226ee67461eSJoseph Mingrone 		ND_PRINT("%smatch dl_type 0x%04x", pfx, dl_type);
12273c602fabSXin LI 	/* nw_tos */
12283c602fabSXin LI 	if (! (wildcards & OFPFW_NW_TOS))
1229ee67461eSJoseph Mingrone 		ND_PRINT("%smatch nw_tos 0x%02x", pfx, GET_U_1(cp));
12303c602fabSXin LI 	cp += 1;
12313c602fabSXin LI 	/* nw_proto */
1232ee67461eSJoseph Mingrone 	nw_proto = GET_U_1(cp);
12333c602fabSXin LI 	cp += 1;
12343c602fabSXin LI 	if (! (wildcards & OFPFW_NW_PROTO)) {
12353c602fabSXin LI 		field_name = ! (wildcards & OFPFW_DL_TYPE) && dl_type == ETHERTYPE_ARP
12363c602fabSXin LI 		  ? "arp_opcode" : "nw_proto";
1237ee67461eSJoseph Mingrone 		ND_PRINT("%smatch %s %u", pfx, field_name, nw_proto);
12383c602fabSXin LI 	}
12393c602fabSXin LI 	/* pad2 */
12403c602fabSXin LI 	cp += 2;
12413c602fabSXin LI 	/* nw_src */
12423c602fabSXin LI 	nw_bits = (wildcards & OFPFW_NW_SRC_MASK) >> OFPFW_NW_SRC_SHIFT;
12433c602fabSXin LI 	if (nw_bits < 32)
1244ee67461eSJoseph Mingrone 		ND_PRINT("%smatch nw_src %s/%u", pfx, GET_IPADDR_STRING(cp), 32 - nw_bits);
12453c602fabSXin LI 	cp += 4;
12463c602fabSXin LI 	/* nw_dst */
12473c602fabSXin LI 	nw_bits = (wildcards & OFPFW_NW_DST_MASK) >> OFPFW_NW_DST_SHIFT;
12483c602fabSXin LI 	if (nw_bits < 32)
1249ee67461eSJoseph Mingrone 		ND_PRINT("%smatch nw_dst %s/%u", pfx, GET_IPADDR_STRING(cp), 32 - nw_bits);
12503c602fabSXin LI 	cp += 4;
12513c602fabSXin LI 	/* tp_src */
12523c602fabSXin LI 	if (! (wildcards & OFPFW_TP_SRC)) {
12533c602fabSXin LI 		field_name = ! (wildcards & OFPFW_DL_TYPE) && dl_type == ETHERTYPE_IP
12543c602fabSXin LI 		  && ! (wildcards & OFPFW_NW_PROTO) && nw_proto == IPPROTO_ICMP
12553c602fabSXin LI 		  ? "icmp_type" : "tp_src";
1256ee67461eSJoseph Mingrone 		ND_PRINT("%smatch %s %u", pfx, field_name, GET_BE_U_2(cp));
12573c602fabSXin LI 	}
12583c602fabSXin LI 	cp += 2;
12593c602fabSXin LI 	/* tp_dst */
1260ee67461eSJoseph Mingrone 	/* The last unconditional check was at nw_proto, so have an "else" here. */
12613c602fabSXin LI 	if (! (wildcards & OFPFW_TP_DST)) {
12623c602fabSXin LI 		field_name = ! (wildcards & OFPFW_DL_TYPE) && dl_type == ETHERTYPE_IP
12633c602fabSXin LI 		  && ! (wildcards & OFPFW_NW_PROTO) && nw_proto == IPPROTO_ICMP
12643c602fabSXin LI 		  ? "icmp_code" : "tp_dst";
1265ee67461eSJoseph Mingrone 		ND_PRINT("%smatch %s %u", pfx, field_name, GET_BE_U_2(cp));
1266*0a7e5f1fSJoseph Mingrone 	} else
1267ee67461eSJoseph Mingrone 		ND_TCHECK_2(cp);
12683c602fabSXin LI }
12693c602fabSXin LI 
12703c602fabSXin LI /* [OF10] Section 5.2.4 */
1271ee67461eSJoseph Mingrone static void
of10_actions_print(netdissect_options * ndo,const char * pfx,const u_char * cp,u_int len)12723c602fabSXin LI of10_actions_print(netdissect_options *ndo,
1273ee67461eSJoseph Mingrone                    const char *pfx, const u_char *cp, u_int len)
12748bdc5a62SPatrick Kelsey {
12753c602fabSXin LI 	while (len) {
1276ee67461eSJoseph Mingrone 		uint16_t type, alen, output_port;
12773c602fabSXin LI 		u_char alen_bogus = 0, skip = 0;
12783c602fabSXin LI 
1279*0a7e5f1fSJoseph Mingrone 		ND_PRINT("%saction", pfx);
1280*0a7e5f1fSJoseph Mingrone 		ND_ICHECKMSG_U("remaining length", len, <, OF_ACTION_MINLEN);
12813c602fabSXin LI 		/* type */
1282ee67461eSJoseph Mingrone 		type = GET_BE_U_2(cp);
1283ee67461eSJoseph Mingrone 		OF_FWD(2);
1284*0a7e5f1fSJoseph Mingrone 		ND_PRINT(" type %s", tok2str(ofpat_str, "invalid (0x%04x)", type));
12853c602fabSXin LI 		/* length */
1286ee67461eSJoseph Mingrone 		alen = GET_BE_U_2(cp);
1287ee67461eSJoseph Mingrone 		OF_FWD(2);
1288ee67461eSJoseph Mingrone 		ND_PRINT(", len %u", alen);
1289ee67461eSJoseph Mingrone 		/*
1290ee67461eSJoseph Mingrone 		 * The 4-byte "pad" in the specification is not a field of the
1291ee67461eSJoseph Mingrone 		 * action header, but a placeholder to illustrate the 64-bit
1292ee67461eSJoseph Mingrone 		 * alignment requirement. Action type specific case blocks
1293ee67461eSJoseph Mingrone 		 * below fetch these 4 bytes.
1294ee67461eSJoseph Mingrone 		 */
1295ee67461eSJoseph Mingrone 
12963c602fabSXin LI 		/* On action size underrun/overrun skip the rest of the action list. */
1297*0a7e5f1fSJoseph Mingrone 		ND_ICHECK_U(alen, <, OF_ACTION_MINLEN);
1298*0a7e5f1fSJoseph Mingrone 		ND_ICHECK_U(alen, >, len + 4);
1299ee67461eSJoseph Mingrone 		/*
1300ee67461eSJoseph Mingrone 		 * After validating the basic length constraint it will be safe
1301ee67461eSJoseph Mingrone 		 * to skip the current action if the action size is not valid
1302ee67461eSJoseph Mingrone 		 * for the type or the type is invalid.
1303ee67461eSJoseph Mingrone 		 */
13043c602fabSXin LI 		switch (type) {
13053c602fabSXin LI 		case OFPAT_OUTPUT:
13063c602fabSXin LI 		case OFPAT_SET_VLAN_VID:
13073c602fabSXin LI 		case OFPAT_SET_VLAN_PCP:
13083c602fabSXin LI 		case OFPAT_STRIP_VLAN:
13093c602fabSXin LI 		case OFPAT_SET_NW_SRC:
13103c602fabSXin LI 		case OFPAT_SET_NW_DST:
13113c602fabSXin LI 		case OFPAT_SET_NW_TOS:
13123c602fabSXin LI 		case OFPAT_SET_TP_SRC:
13133c602fabSXin LI 		case OFPAT_SET_TP_DST:
13143c602fabSXin LI 			alen_bogus = alen != 8;
13153c602fabSXin LI 			break;
13163c602fabSXin LI 		case OFPAT_SET_DL_SRC:
13173c602fabSXin LI 		case OFPAT_SET_DL_DST:
13183c602fabSXin LI 		case OFPAT_ENQUEUE:
13193c602fabSXin LI 			alen_bogus = alen != 16;
13203c602fabSXin LI 			break;
13213c602fabSXin LI 		case OFPAT_VENDOR:
13223c602fabSXin LI 			alen_bogus = alen % 8 != 0; /* already >= 8 so far */
13233c602fabSXin LI 			break;
13243c602fabSXin LI 		default:
13253c602fabSXin LI 			skip = 1;
13263c602fabSXin LI 		}
13273c602fabSXin LI 		if (alen_bogus) {
1328ee67461eSJoseph Mingrone 			ND_PRINT(" (bogus)");
13293c602fabSXin LI 			skip = 1;
13303c602fabSXin LI 		}
13313c602fabSXin LI 		if (skip) {
1332ee67461eSJoseph Mingrone 			/*
1333ee67461eSJoseph Mingrone 			 * alen >= OF_ACTION_MINLEN
1334ee67461eSJoseph Mingrone 			 * cp is 4 bytes in
1335ee67461eSJoseph Mingrone 			 */
1336ee67461eSJoseph Mingrone 			OF_CHK_FWD(alen - 4);
1337ee67461eSJoseph Mingrone 			continue;
13383c602fabSXin LI 		}
13393c602fabSXin LI 		/* OK to decode the rest of the action structure */
13403c602fabSXin LI 		switch (type) {
13413c602fabSXin LI 		case OFPAT_OUTPUT:
13423c602fabSXin LI 			/* port */
1343ee67461eSJoseph Mingrone 			output_port = GET_BE_U_2(cp);
1344ee67461eSJoseph Mingrone 			OF_FWD(2);
1345ee67461eSJoseph Mingrone 			ND_PRINT(", port %s", tok2str(ofpp_str, "%u", output_port));
13463c602fabSXin LI 			/* max_len */
13473c602fabSXin LI 			if (output_port == OFPP_CONTROLLER)
1348ee67461eSJoseph Mingrone 				ND_PRINT(", max_len %u", GET_BE_U_2(cp));
1349ee67461eSJoseph Mingrone 			else
1350ee67461eSJoseph Mingrone 				ND_TCHECK_2(cp);
1351ee67461eSJoseph Mingrone 			OF_FWD(2);
13523c602fabSXin LI 			break;
13533c602fabSXin LI 		case OFPAT_SET_VLAN_VID:
13543c602fabSXin LI 			/* vlan_vid */
1355ee67461eSJoseph Mingrone 			ND_PRINT(", vlan_vid %s", vlan_str(GET_BE_U_2(cp)));
1356ee67461eSJoseph Mingrone 			OF_FWD(2);
13573c602fabSXin LI 			/* pad */
1358ee67461eSJoseph Mingrone 			/* Sometimes the last field, check bounds. */
1359ee67461eSJoseph Mingrone 			OF_CHK_FWD(2);
13603c602fabSXin LI 			break;
13613c602fabSXin LI 		case OFPAT_SET_VLAN_PCP:
13623c602fabSXin LI 			/* vlan_pcp */
1363ee67461eSJoseph Mingrone 			ND_PRINT(", vlan_pcp %s", pcp_str(GET_U_1(cp)));
1364ee67461eSJoseph Mingrone 			OF_FWD(1);
13653c602fabSXin LI 			/* pad */
1366ee67461eSJoseph Mingrone 			/* Sometimes the last field, check bounds. */
1367ee67461eSJoseph Mingrone 			OF_CHK_FWD(3);
13683c602fabSXin LI 			break;
13693c602fabSXin LI 		case OFPAT_SET_DL_SRC:
13703c602fabSXin LI 		case OFPAT_SET_DL_DST:
13713c602fabSXin LI 			/* dl_addr */
1372ee67461eSJoseph Mingrone 			ND_PRINT(", dl_addr %s", GET_ETHERADDR_STRING(cp));
1373ee67461eSJoseph Mingrone 			OF_FWD(MAC_ADDR_LEN);
13743c602fabSXin LI 			/* pad */
1375ee67461eSJoseph Mingrone 			/* Sometimes the last field, check bounds. */
1376ee67461eSJoseph Mingrone 			OF_CHK_FWD(6);
13773c602fabSXin LI 			break;
13783c602fabSXin LI 		case OFPAT_SET_NW_SRC:
13793c602fabSXin LI 		case OFPAT_SET_NW_DST:
13803c602fabSXin LI 			/* nw_addr */
1381ee67461eSJoseph Mingrone 			ND_PRINT(", nw_addr %s", GET_IPADDR_STRING(cp));
1382ee67461eSJoseph Mingrone 			OF_FWD(4);
13833c602fabSXin LI 			break;
13843c602fabSXin LI 		case OFPAT_SET_NW_TOS:
13853c602fabSXin LI 			/* nw_tos */
1386ee67461eSJoseph Mingrone 			ND_PRINT(", nw_tos 0x%02x", GET_U_1(cp));
1387ee67461eSJoseph Mingrone 			OF_FWD(1);
13883c602fabSXin LI 			/* pad */
1389ee67461eSJoseph Mingrone 			/* Sometimes the last field, check bounds. */
1390ee67461eSJoseph Mingrone 			OF_CHK_FWD(3);
13913c602fabSXin LI 			break;
13923c602fabSXin LI 		case OFPAT_SET_TP_SRC:
13933c602fabSXin LI 		case OFPAT_SET_TP_DST:
13943c602fabSXin LI 			/* nw_tos */
1395ee67461eSJoseph Mingrone 			ND_PRINT(", tp_port %u", GET_BE_U_2(cp));
1396ee67461eSJoseph Mingrone 			OF_FWD(2);
13973c602fabSXin LI 			/* pad */
1398ee67461eSJoseph Mingrone 			/* Sometimes the last field, check bounds. */
1399ee67461eSJoseph Mingrone 			OF_CHK_FWD(2);
14003c602fabSXin LI 			break;
14013c602fabSXin LI 		case OFPAT_ENQUEUE:
14023c602fabSXin LI 			/* port */
1403ee67461eSJoseph Mingrone 			ND_PRINT(", port %s",
1404ee67461eSJoseph Mingrone 				 tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1405ee67461eSJoseph Mingrone 			OF_FWD(2);
14063c602fabSXin LI 			/* pad */
1407ee67461eSJoseph Mingrone 			OF_FWD(6);
14083c602fabSXin LI 			/* queue_id */
1409ee67461eSJoseph Mingrone 			ND_PRINT(", queue_id %s",
1410ee67461eSJoseph Mingrone 				 tok2str(ofpq_str, "%u", GET_BE_U_4(cp)));
1411ee67461eSJoseph Mingrone 			OF_FWD(4);
14123c602fabSXin LI 			break;
14133c602fabSXin LI 		case OFPAT_VENDOR:
1414ee67461eSJoseph Mingrone 			of10_vendor_action_print(ndo, cp, alen - 4);
1415ee67461eSJoseph Mingrone 			OF_FWD(alen - 4);
14163c602fabSXin LI 			break;
14173c602fabSXin LI 		case OFPAT_STRIP_VLAN:
14183c602fabSXin LI 			/* pad */
1419ee67461eSJoseph Mingrone 			/* Sometimes the last field, check bounds. */
1420ee67461eSJoseph Mingrone 			OF_CHK_FWD(4);
14213c602fabSXin LI 			break;
14223c602fabSXin LI 		} /* switch */
14233c602fabSXin LI 	} /* while */
1424ee67461eSJoseph Mingrone 	return;
14253c602fabSXin LI 
14263340d773SGleb Smirnoff invalid: /* skip the rest of actions */
1427ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
1428ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
14293c602fabSXin LI }
14303c602fabSXin LI 
14313c602fabSXin LI /* [OF10] Section 5.3.1 */
1432ee67461eSJoseph Mingrone static void
of10_features_reply_print(netdissect_options * ndo,const u_char * cp,u_int len)14333c602fabSXin LI of10_features_reply_print(netdissect_options *ndo,
1434ee67461eSJoseph Mingrone                           const u_char *cp, u_int len)
14358bdc5a62SPatrick Kelsey {
14363c602fabSXin LI 	/* datapath_id */
1437ee67461eSJoseph Mingrone 	ND_PRINT("\n\t dpid 0x%016" PRIx64, GET_BE_U_8(cp));
1438ee67461eSJoseph Mingrone 	OF_FWD(8);
14393c602fabSXin LI 	/* n_buffers */
1440ee67461eSJoseph Mingrone 	ND_PRINT(", n_buffers %u", GET_BE_U_4(cp));
1441ee67461eSJoseph Mingrone 	OF_FWD(4);
14423c602fabSXin LI 	/* n_tables */
1443ee67461eSJoseph Mingrone 	ND_PRINT(", n_tables %u", GET_U_1(cp));
1444ee67461eSJoseph Mingrone 	OF_FWD(1);
14453c602fabSXin LI 	/* pad */
1446ee67461eSJoseph Mingrone 	OF_FWD(3);
14473c602fabSXin LI 	/* capabilities */
1448ee67461eSJoseph Mingrone 	ND_PRINT("\n\t capabilities 0x%08x", GET_BE_U_4(cp));
1449ee67461eSJoseph Mingrone 	of_bitmap_print(ndo, ofp_capabilities_bm, GET_BE_U_4(cp), OFPCAP_U);
1450ee67461eSJoseph Mingrone 	OF_FWD(4);
14513c602fabSXin LI 	/* actions */
1452ee67461eSJoseph Mingrone 	ND_PRINT("\n\t actions 0x%08x", GET_BE_U_4(cp));
1453ee67461eSJoseph Mingrone 	of_bitmap_print(ndo, ofpat_bm, GET_BE_U_4(cp), OFPAT_U);
1454ee67461eSJoseph Mingrone 	OF_FWD(4);
14553c602fabSXin LI 	/* ports */
1456ee67461eSJoseph Mingrone 	while (len) {
1457*0a7e5f1fSJoseph Mingrone 		ND_ICHECKMSG_U("\n\t  port def. length", len, <, OF_PHY_PORT_FIXLEN);
1458ee67461eSJoseph Mingrone 		of10_phy_port_print(ndo, cp);
1459ee67461eSJoseph Mingrone 		OF_FWD(OF_PHY_PORT_FIXLEN);
1460ee67461eSJoseph Mingrone 	}
1461ee67461eSJoseph Mingrone 	return;
14623c602fabSXin LI 
1463ee67461eSJoseph Mingrone invalid: /* skip the undersized trailing data */
1464ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
1465ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
1466ee67461eSJoseph Mingrone }
1467ee67461eSJoseph Mingrone 
1468ee67461eSJoseph Mingrone /* [OF10] Section 5.3.2 */
1469ee67461eSJoseph Mingrone static void
of10_switch_config_msg_print(netdissect_options * ndo,const u_char * cp,u_int len _U_)1470ee67461eSJoseph Mingrone of10_switch_config_msg_print(netdissect_options *ndo,
1471ee67461eSJoseph Mingrone                              const u_char *cp, u_int len _U_)
1472ee67461eSJoseph Mingrone {
1473ee67461eSJoseph Mingrone 	/* flags */
1474ee67461eSJoseph Mingrone 	ND_PRINT("\n\t flags %s",
1475ee67461eSJoseph Mingrone 	         tok2str(ofp_config_str, "invalid (0x%04x)", GET_BE_U_2(cp)));
1476ee67461eSJoseph Mingrone 	cp += 2;
1477ee67461eSJoseph Mingrone 	/* miss_send_len */
1478ee67461eSJoseph Mingrone 	ND_PRINT(", miss_send_len %u", GET_BE_U_2(cp));
14793c602fabSXin LI }
14803c602fabSXin LI 
14813c602fabSXin LI /* [OF10] Section 5.3.3 */
1482ee67461eSJoseph Mingrone static void
of10_flow_mod_print(netdissect_options * ndo,const u_char * cp,u_int len)14833c602fabSXin LI of10_flow_mod_print(netdissect_options *ndo,
1484ee67461eSJoseph Mingrone                     const u_char *cp, u_int len)
14858bdc5a62SPatrick Kelsey {
14863c602fabSXin LI 	uint16_t command;
14873c602fabSXin LI 
14883c602fabSXin LI 	/* match */
1489ee67461eSJoseph Mingrone 	of10_match_print(ndo, "\n\t ", cp);
1490ee67461eSJoseph Mingrone 	OF_FWD(OF_MATCH_FIXLEN);
14913c602fabSXin LI 	/* cookie */
1492ee67461eSJoseph Mingrone 	ND_PRINT("\n\t cookie 0x%016" PRIx64, GET_BE_U_8(cp));
1493ee67461eSJoseph Mingrone 	OF_FWD(8);
14943c602fabSXin LI 	/* command */
1495ee67461eSJoseph Mingrone 	command = GET_BE_U_2(cp);
1496ee67461eSJoseph Mingrone 	ND_PRINT(", command %s", tok2str(ofpfc_str, "invalid (0x%04x)", command));
1497ee67461eSJoseph Mingrone 	OF_FWD(2);
14983c602fabSXin LI 	/* idle_timeout */
1499ee67461eSJoseph Mingrone 	if (GET_BE_U_2(cp))
1500ee67461eSJoseph Mingrone 		ND_PRINT(", idle_timeout %u", GET_BE_U_2(cp));
1501ee67461eSJoseph Mingrone 	OF_FWD(2);
15023c602fabSXin LI 	/* hard_timeout */
1503ee67461eSJoseph Mingrone 	if (GET_BE_U_2(cp))
1504ee67461eSJoseph Mingrone 		ND_PRINT(", hard_timeout %u", GET_BE_U_2(cp));
1505ee67461eSJoseph Mingrone 	OF_FWD(2);
15063c602fabSXin LI 	/* priority */
1507ee67461eSJoseph Mingrone 	if (GET_BE_U_2(cp))
1508ee67461eSJoseph Mingrone 		ND_PRINT(", priority %u", GET_BE_U_2(cp));
1509ee67461eSJoseph Mingrone 	OF_FWD(2);
15103c602fabSXin LI 	/* buffer_id */
15113c602fabSXin LI 	if (command == OFPFC_ADD || command == OFPFC_MODIFY ||
15123c602fabSXin LI 	    command == OFPFC_MODIFY_STRICT)
1513ee67461eSJoseph Mingrone 		ND_PRINT(", buffer_id %s",
1514ee67461eSJoseph Mingrone 		         tok2str(bufferid_str, "0x%08x", GET_BE_U_4(cp)));
1515ee67461eSJoseph Mingrone 	OF_FWD(4);
15163c602fabSXin LI 	/* out_port */
15173c602fabSXin LI 	if (command == OFPFC_DELETE || command == OFPFC_DELETE_STRICT)
1518ee67461eSJoseph Mingrone 		ND_PRINT(", out_port %s",
1519ee67461eSJoseph Mingrone 		         tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1520ee67461eSJoseph Mingrone 	OF_FWD(2);
15213c602fabSXin LI 	/* flags */
1522ee67461eSJoseph Mingrone 	ND_PRINT(", flags 0x%04x", GET_BE_U_2(cp));
1523ee67461eSJoseph Mingrone 	of_bitmap_print(ndo, ofpff_bm, GET_BE_U_2(cp), OFPFF_U);
1524ee67461eSJoseph Mingrone 	OF_FWD(2);
15253c602fabSXin LI 	/* actions */
1526ee67461eSJoseph Mingrone 	of10_actions_print(ndo, "\n\t ", cp, len);
15273c602fabSXin LI }
15283c602fabSXin LI 
15293c602fabSXin LI /* ibid */
1530ee67461eSJoseph Mingrone static void
of10_port_mod_print(netdissect_options * ndo,const u_char * cp,u_int len _U_)15313c602fabSXin LI of10_port_mod_print(netdissect_options *ndo,
1532ee67461eSJoseph Mingrone                     const u_char *cp, u_int len _U_)
15338bdc5a62SPatrick Kelsey {
15343c602fabSXin LI 	/* port_no */
1535ee67461eSJoseph Mingrone 	ND_PRINT("\n\t port_no %s", tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
15363c602fabSXin LI 	cp += 2;
15373c602fabSXin LI 	/* hw_addr */
1538ee67461eSJoseph Mingrone 	ND_PRINT(", hw_addr %s", GET_ETHERADDR_STRING(cp));
1539ee67461eSJoseph Mingrone 	cp += MAC_ADDR_LEN;
15403c602fabSXin LI 	/* config */
1541ee67461eSJoseph Mingrone 	ND_PRINT("\n\t  config 0x%08x", GET_BE_U_4(cp));
1542ee67461eSJoseph Mingrone 	of_bitmap_print(ndo, ofppc_bm, GET_BE_U_4(cp), OFPPC_U);
15433c602fabSXin LI 	cp += 4;
15443c602fabSXin LI 	/* mask */
1545ee67461eSJoseph Mingrone 	ND_PRINT("\n\t  mask 0x%08x", GET_BE_U_4(cp));
1546ee67461eSJoseph Mingrone 	of_bitmap_print(ndo, ofppc_bm, GET_BE_U_4(cp), OFPPC_U);
15473c602fabSXin LI 	cp += 4;
15483c602fabSXin LI 	/* advertise */
1549ee67461eSJoseph Mingrone 	ND_PRINT("\n\t  advertise 0x%08x", GET_BE_U_4(cp));
1550ee67461eSJoseph Mingrone 	of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U);
15513c602fabSXin LI 	cp += 4;
15523c602fabSXin LI 	/* pad */
1553ee67461eSJoseph Mingrone 	/* Always the last field, check bounds. */
1554ee67461eSJoseph Mingrone 	ND_TCHECK_4(cp);
1555ee67461eSJoseph Mingrone }
15563c602fabSXin LI 
1557ee67461eSJoseph Mingrone /* [OF10] Section 5.3.4 */
1558ee67461eSJoseph Mingrone static void
of10_queue_get_config_request_print(netdissect_options * ndo,const u_char * cp,u_int len _U_)1559ee67461eSJoseph Mingrone of10_queue_get_config_request_print(netdissect_options *ndo,
1560ee67461eSJoseph Mingrone                                     const u_char *cp, u_int len _U_)
1561ee67461eSJoseph Mingrone {
1562ee67461eSJoseph Mingrone 	/* port */
1563ee67461eSJoseph Mingrone 	ND_PRINT("\n\t port %s", tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1564ee67461eSJoseph Mingrone 	cp += 2;
1565ee67461eSJoseph Mingrone 	/* pad */
1566ee67461eSJoseph Mingrone 	/* Always the last field, check bounds. */
1567ee67461eSJoseph Mingrone 	ND_TCHECK_2(cp);
1568ee67461eSJoseph Mingrone }
1569ee67461eSJoseph Mingrone 
1570ee67461eSJoseph Mingrone /* ibid */
1571ee67461eSJoseph Mingrone static void
of10_queue_get_config_reply_print(netdissect_options * ndo,const u_char * cp,u_int len)1572ee67461eSJoseph Mingrone of10_queue_get_config_reply_print(netdissect_options *ndo,
1573ee67461eSJoseph Mingrone                                   const u_char *cp, u_int len)
1574ee67461eSJoseph Mingrone {
1575ee67461eSJoseph Mingrone 	/* port */
1576ee67461eSJoseph Mingrone 	ND_PRINT("\n\t port %s", tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1577ee67461eSJoseph Mingrone 	OF_FWD(2);
1578ee67461eSJoseph Mingrone 	/* pad */
1579ee67461eSJoseph Mingrone 	/* Sometimes the last field, check bounds. */
1580ee67461eSJoseph Mingrone 	OF_CHK_FWD(6);
1581ee67461eSJoseph Mingrone 	/* queues */
1582ee67461eSJoseph Mingrone 	of10_queues_print(ndo, cp, len);
15833c602fabSXin LI }
15843c602fabSXin LI 
15853c602fabSXin LI /* [OF10] Section 5.3.5 */
1586ee67461eSJoseph Mingrone static void
of10_stats_request_print(netdissect_options * ndo,const u_char * cp,u_int len)15873c602fabSXin LI of10_stats_request_print(netdissect_options *ndo,
1588ee67461eSJoseph Mingrone                          const u_char *cp, u_int len)
15898bdc5a62SPatrick Kelsey {
15903c602fabSXin LI 	uint16_t type;
15913c602fabSXin LI 
15923c602fabSXin LI 	/* type */
1593ee67461eSJoseph Mingrone 	type = GET_BE_U_2(cp);
1594ee67461eSJoseph Mingrone 	OF_FWD(2);
1595ee67461eSJoseph Mingrone 	ND_PRINT("\n\t type %s", tok2str(ofpst_str, "invalid (0x%04x)", type));
15963c602fabSXin LI 	/* flags */
1597ee67461eSJoseph Mingrone 	ND_PRINT(", flags 0x%04x", GET_BE_U_2(cp));
1598ee67461eSJoseph Mingrone 	if (GET_BE_U_2(cp))
1599ee67461eSJoseph Mingrone 		ND_PRINT(" (bogus)");
1600ee67461eSJoseph Mingrone 	OF_FWD(2);
16013c602fabSXin LI 	/* type-specific body of one of fixed lengths */
16023c602fabSXin LI 	switch(type) {
16033c602fabSXin LI 	case OFPST_DESC:
16043c602fabSXin LI 	case OFPST_TABLE:
1605*0a7e5f1fSJoseph Mingrone 		ND_ICHECK_U(len, !=, 0);
1606ee67461eSJoseph Mingrone 		return;
16073c602fabSXin LI 	case OFPST_FLOW:
16083c602fabSXin LI 	case OFPST_AGGREGATE:
1609*0a7e5f1fSJoseph Mingrone 		ND_ICHECK_U(len, !=, OF_FLOW_STATS_REQUEST_FIXLEN);
16103c602fabSXin LI 		/* match */
1611ee67461eSJoseph Mingrone 		of10_match_print(ndo, "\n\t ", cp);
1612ee67461eSJoseph Mingrone 		OF_FWD(OF_MATCH_FIXLEN);
16133c602fabSXin LI 		/* table_id */
1614ee67461eSJoseph Mingrone 		ND_PRINT("\n\t table_id %s",
1615ee67461eSJoseph Mingrone 			 tok2str(tableid_str, "%u", GET_U_1(cp)));
1616ee67461eSJoseph Mingrone 		OF_FWD(1);
16173c602fabSXin LI 		/* pad */
1618ee67461eSJoseph Mingrone 		OF_FWD(1);
16193c602fabSXin LI 		/* out_port */
1620ee67461eSJoseph Mingrone 		ND_PRINT(", out_port %s",
1621ee67461eSJoseph Mingrone 			 tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1622ee67461eSJoseph Mingrone 		return;
16233c602fabSXin LI 	case OFPST_PORT:
1624*0a7e5f1fSJoseph Mingrone 		ND_ICHECK_U(len, !=, OF_PORT_STATS_REQUEST_FIXLEN);
16253c602fabSXin LI 		/* port_no */
1626ee67461eSJoseph Mingrone 		ND_PRINT("\n\t port_no %s",
1627ee67461eSJoseph Mingrone 			 tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1628ee67461eSJoseph Mingrone 		OF_FWD(2);
16293c602fabSXin LI 		/* pad */
1630ee67461eSJoseph Mingrone 		/* Always the last field, check bounds. */
1631ee67461eSJoseph Mingrone 		OF_CHK_FWD(6);
1632ee67461eSJoseph Mingrone 		return;
16333c602fabSXin LI 	case OFPST_QUEUE:
1634*0a7e5f1fSJoseph Mingrone 		ND_ICHECK_U(len, !=, OF_QUEUE_STATS_REQUEST_FIXLEN);
16353c602fabSXin LI 		/* port_no */
1636ee67461eSJoseph Mingrone 		ND_PRINT("\n\t port_no %s",
1637ee67461eSJoseph Mingrone 			 tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1638ee67461eSJoseph Mingrone 		OF_FWD(2);
16393c602fabSXin LI 		/* pad */
1640ee67461eSJoseph Mingrone 		OF_FWD(2);
16413c602fabSXin LI 		/* queue_id */
1642ee67461eSJoseph Mingrone 		ND_PRINT(", queue_id %s",
1643ee67461eSJoseph Mingrone 			 tok2str(ofpq_str, "%u", GET_BE_U_4(cp)));
1644ee67461eSJoseph Mingrone 		return;
16453c602fabSXin LI 	case OFPST_VENDOR:
1646ee67461eSJoseph Mingrone 		of10_vendor_data_print(ndo, cp, len);
1647ee67461eSJoseph Mingrone 		return;
16483c602fabSXin LI 	}
1649ee67461eSJoseph Mingrone 	return;
16503c602fabSXin LI 
16513340d773SGleb Smirnoff invalid: /* skip the message body */
1652ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
1653ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
16543c602fabSXin LI }
16553c602fabSXin LI 
16563c602fabSXin LI /* ibid */
1657ee67461eSJoseph Mingrone static void
of10_desc_stats_reply_print(netdissect_options * ndo,const u_char * cp,u_int len)16583c602fabSXin LI of10_desc_stats_reply_print(netdissect_options *ndo,
1659ee67461eSJoseph Mingrone                             const u_char *cp, u_int len)
16608bdc5a62SPatrick Kelsey {
1661*0a7e5f1fSJoseph Mingrone 	ND_PRINT("\n\t ");
1662*0a7e5f1fSJoseph Mingrone 	ND_ICHECK_U(len, !=, OF_DESC_STATS_REPLY_FIXLEN);
16633c602fabSXin LI 	/* mfr_desc */
1664*0a7e5f1fSJoseph Mingrone 	ND_PRINT(" mfr_desc '");
1665ee67461eSJoseph Mingrone 	nd_printjnp(ndo, cp, DESC_STR_LEN);
1666ee67461eSJoseph Mingrone 	ND_PRINT("'");
1667ee67461eSJoseph Mingrone 	OF_FWD(DESC_STR_LEN);
16683c602fabSXin LI 	/* hw_desc */
1669ee67461eSJoseph Mingrone 	ND_PRINT("\n\t  hw_desc '");
1670ee67461eSJoseph Mingrone 	nd_printjnp(ndo, cp, DESC_STR_LEN);
1671ee67461eSJoseph Mingrone 	ND_PRINT("'");
1672ee67461eSJoseph Mingrone 	OF_FWD(DESC_STR_LEN);
16733c602fabSXin LI 	/* sw_desc */
1674ee67461eSJoseph Mingrone 	ND_PRINT("\n\t  sw_desc '");
1675ee67461eSJoseph Mingrone 	nd_printjnp(ndo, cp, DESC_STR_LEN);
1676ee67461eSJoseph Mingrone 	ND_PRINT("'");
1677ee67461eSJoseph Mingrone 	OF_FWD(DESC_STR_LEN);
16783c602fabSXin LI 	/* serial_num */
1679ee67461eSJoseph Mingrone 	ND_PRINT("\n\t  serial_num '");
1680ee67461eSJoseph Mingrone 	nd_printjnp(ndo, cp, SERIAL_NUM_LEN);
1681ee67461eSJoseph Mingrone 	ND_PRINT("'");
1682ee67461eSJoseph Mingrone 	OF_FWD(SERIAL_NUM_LEN);
16833c602fabSXin LI 	/* dp_desc */
1684ee67461eSJoseph Mingrone 	ND_PRINT("\n\t  dp_desc '");
1685ee67461eSJoseph Mingrone 	nd_printjnp(ndo, cp, DESC_STR_LEN);
1686ee67461eSJoseph Mingrone 	ND_PRINT("'");
1687ee67461eSJoseph Mingrone 	return;
16883c602fabSXin LI 
16893340d773SGleb Smirnoff invalid: /* skip the message body */
1690ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
1691ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
16923c602fabSXin LI }
16933c602fabSXin LI 
16943c602fabSXin LI /* ibid */
1695ee67461eSJoseph Mingrone static void
of10_flow_stats_reply_print(netdissect_options * ndo,const u_char * cp,u_int len)16963c602fabSXin LI of10_flow_stats_reply_print(netdissect_options *ndo,
1697ee67461eSJoseph Mingrone                             const u_char *cp, u_int len)
16988bdc5a62SPatrick Kelsey {
1699ee67461eSJoseph Mingrone 	while (len) {
17003c602fabSXin LI 		uint16_t entry_len;
17013c602fabSXin LI 
1702*0a7e5f1fSJoseph Mingrone 		ND_PRINT("\n\t");
1703*0a7e5f1fSJoseph Mingrone 		ND_ICHECKMSG_U("remaining length", len, <, OF_FLOW_STATS_REPLY_MINLEN);
17043c602fabSXin LI 		/* length */
1705ee67461eSJoseph Mingrone 		entry_len = GET_BE_U_2(cp);
1706*0a7e5f1fSJoseph Mingrone 		ND_PRINT(" length %u", entry_len);
1707*0a7e5f1fSJoseph Mingrone 		ND_ICHECK_U(entry_len, <, OF_FLOW_STATS_REPLY_MINLEN);
1708*0a7e5f1fSJoseph Mingrone 		ND_ICHECK_U(entry_len, >, len);
1709ee67461eSJoseph Mingrone 		OF_FWD(2);
17103c602fabSXin LI 		/* table_id */
1711ee67461eSJoseph Mingrone 		ND_PRINT(", table_id %s",
1712ee67461eSJoseph Mingrone 			 tok2str(tableid_str, "%u", GET_U_1(cp)));
1713ee67461eSJoseph Mingrone 		OF_FWD(1);
17143c602fabSXin LI 		/* pad */
1715ee67461eSJoseph Mingrone 		OF_FWD(1);
17163c602fabSXin LI 		/* match */
1717ee67461eSJoseph Mingrone 		of10_match_print(ndo, "\n\t  ", cp);
1718ee67461eSJoseph Mingrone 		OF_FWD(OF_MATCH_FIXLEN);
17193c602fabSXin LI 		/* duration_sec */
1720ee67461eSJoseph Mingrone 		ND_PRINT("\n\t  duration_sec %u", GET_BE_U_4(cp));
1721ee67461eSJoseph Mingrone 		OF_FWD(4);
17223c602fabSXin LI 		/* duration_nsec */
1723ee67461eSJoseph Mingrone 		ND_PRINT(", duration_nsec %u", GET_BE_U_4(cp));
1724ee67461eSJoseph Mingrone 		OF_FWD(4);
17253c602fabSXin LI 		/* priority */
1726ee67461eSJoseph Mingrone 		ND_PRINT(", priority %u", GET_BE_U_2(cp));
1727ee67461eSJoseph Mingrone 		OF_FWD(2);
17283c602fabSXin LI 		/* idle_timeout */
1729ee67461eSJoseph Mingrone 		ND_PRINT(", idle_timeout %u", GET_BE_U_2(cp));
1730ee67461eSJoseph Mingrone 		OF_FWD(2);
17313c602fabSXin LI 		/* hard_timeout */
1732ee67461eSJoseph Mingrone 		ND_PRINT(", hard_timeout %u", GET_BE_U_2(cp));
1733ee67461eSJoseph Mingrone 		OF_FWD(2);
17343c602fabSXin LI 		/* pad2 */
1735ee67461eSJoseph Mingrone 		OF_FWD(6);
17363c602fabSXin LI 		/* cookie */
1737ee67461eSJoseph Mingrone 		ND_PRINT(", cookie 0x%016" PRIx64, GET_BE_U_8(cp));
1738ee67461eSJoseph Mingrone 		OF_FWD(8);
17393c602fabSXin LI 		/* packet_count */
1740ee67461eSJoseph Mingrone 		ND_PRINT(", packet_count %" PRIu64, GET_BE_U_8(cp));
1741ee67461eSJoseph Mingrone 		OF_FWD(8);
17423c602fabSXin LI 		/* byte_count */
1743ee67461eSJoseph Mingrone 		ND_PRINT(", byte_count %" PRIu64, GET_BE_U_8(cp));
1744ee67461eSJoseph Mingrone 		OF_FWD(8);
17453c602fabSXin LI 		/* actions */
1746ee67461eSJoseph Mingrone 		of10_actions_print(ndo, "\n\t  ", cp, entry_len - OF_FLOW_STATS_REPLY_MINLEN);
1747ee67461eSJoseph Mingrone 		OF_FWD(entry_len - OF_FLOW_STATS_REPLY_MINLEN);
17483c602fabSXin LI 	} /* while */
1749ee67461eSJoseph Mingrone 	return;
17503c602fabSXin LI 
17513340d773SGleb Smirnoff invalid: /* skip the rest of flow statistics entries */
1752ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
1753ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
17543c602fabSXin LI }
17553c602fabSXin LI 
17563c602fabSXin LI /* ibid */
1757ee67461eSJoseph Mingrone static void
of10_aggregate_stats_reply_print(netdissect_options * ndo,const u_char * cp,u_int len)17583c602fabSXin LI of10_aggregate_stats_reply_print(netdissect_options *ndo,
1759ee67461eSJoseph Mingrone                                  const u_char *cp, u_int len)
17608bdc5a62SPatrick Kelsey {
1761*0a7e5f1fSJoseph Mingrone 	ND_PRINT("\n\t");
1762*0a7e5f1fSJoseph Mingrone 	ND_ICHECKMSG_U("remaining length", len, !=, OF_AGGREGATE_STATS_REPLY_FIXLEN);
17633c602fabSXin LI 	/* packet_count */
1764*0a7e5f1fSJoseph Mingrone 	ND_PRINT(" packet_count %" PRIu64, GET_BE_U_8(cp));
1765ee67461eSJoseph Mingrone 	OF_FWD(8);
17663c602fabSXin LI 	/* byte_count */
1767ee67461eSJoseph Mingrone 	ND_PRINT(", byte_count %" PRIu64, GET_BE_U_8(cp));
1768ee67461eSJoseph Mingrone 	OF_FWD(8);
17693c602fabSXin LI 	/* flow_count */
1770ee67461eSJoseph Mingrone 	ND_PRINT(", flow_count %u", GET_BE_U_4(cp));
1771ee67461eSJoseph Mingrone 	OF_FWD(4);
17723c602fabSXin LI 	/* pad */
1773ee67461eSJoseph Mingrone 	/* Always the last field, check bounds. */
1774ee67461eSJoseph Mingrone 	ND_TCHECK_4(cp);
1775ee67461eSJoseph Mingrone 	return;
17763c602fabSXin LI 
17773340d773SGleb Smirnoff invalid: /* skip the message body */
1778ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
1779ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
17803c602fabSXin LI }
17813c602fabSXin LI 
17823c602fabSXin LI /* ibid */
1783ee67461eSJoseph Mingrone static void
of10_table_stats_reply_print(netdissect_options * ndo,const u_char * cp,u_int len)17843c602fabSXin LI of10_table_stats_reply_print(netdissect_options *ndo,
1785ee67461eSJoseph Mingrone                              const u_char *cp, u_int len)
17868bdc5a62SPatrick Kelsey {
17873c602fabSXin LI 	while (len) {
1788*0a7e5f1fSJoseph Mingrone 		ND_PRINT("\n\t");
1789*0a7e5f1fSJoseph Mingrone 		ND_ICHECKMSG_U("remaining length", len, <, OF_TABLE_STATS_REPLY_FIXLEN);
17903c602fabSXin LI 		/* table_id */
1791*0a7e5f1fSJoseph Mingrone 		ND_PRINT(" table_id %s",
1792ee67461eSJoseph Mingrone 		         tok2str(tableid_str, "%u", GET_U_1(cp)));
1793ee67461eSJoseph Mingrone 		OF_FWD(1);
17943c602fabSXin LI 		/* pad */
1795ee67461eSJoseph Mingrone 		OF_FWD(3);
17963c602fabSXin LI 		/* name */
1797ee67461eSJoseph Mingrone 		ND_PRINT(", name '");
1798ee67461eSJoseph Mingrone 		nd_printjnp(ndo, cp, OFP_MAX_TABLE_NAME_LEN);
1799ee67461eSJoseph Mingrone 		ND_PRINT("'");
1800ee67461eSJoseph Mingrone 		OF_FWD(OFP_MAX_TABLE_NAME_LEN);
18013c602fabSXin LI 		/* wildcards */
1802ee67461eSJoseph Mingrone 		ND_PRINT("\n\t  wildcards 0x%08x", GET_BE_U_4(cp));
1803ee67461eSJoseph Mingrone 		of_bitmap_print(ndo, ofpfw_bm, GET_BE_U_4(cp), OFPFW_U);
1804ee67461eSJoseph Mingrone 		OF_FWD(4);
18053c602fabSXin LI 		/* max_entries */
1806ee67461eSJoseph Mingrone 		ND_PRINT("\n\t  max_entries %u", GET_BE_U_4(cp));
1807ee67461eSJoseph Mingrone 		OF_FWD(4);
18083c602fabSXin LI 		/* active_count */
1809ee67461eSJoseph Mingrone 		ND_PRINT(", active_count %u", GET_BE_U_4(cp));
1810ee67461eSJoseph Mingrone 		OF_FWD(4);
18113c602fabSXin LI 		/* lookup_count */
1812ee67461eSJoseph Mingrone 		ND_PRINT(", lookup_count %" PRIu64, GET_BE_U_8(cp));
1813ee67461eSJoseph Mingrone 		OF_FWD(8);
18143c602fabSXin LI 		/* matched_count */
1815ee67461eSJoseph Mingrone 		ND_PRINT(", matched_count %" PRIu64, GET_BE_U_8(cp));
1816ee67461eSJoseph Mingrone 		OF_FWD(8);
18173c602fabSXin LI 	} /* while */
1818ee67461eSJoseph Mingrone 	return;
18193c602fabSXin LI 
18203340d773SGleb Smirnoff invalid: /* skip the undersized trailing data */
1821ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
1822ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
18233c602fabSXin LI }
18243c602fabSXin LI 
18253c602fabSXin LI /* ibid */
1826ee67461eSJoseph Mingrone static void
of10_port_stats_reply_print(netdissect_options * ndo,const u_char * cp,u_int len)18273c602fabSXin LI of10_port_stats_reply_print(netdissect_options *ndo,
1828ee67461eSJoseph Mingrone                             const u_char *cp, u_int len)
18298bdc5a62SPatrick Kelsey {
18303c602fabSXin LI 	while (len) {
1831*0a7e5f1fSJoseph Mingrone 		ND_PRINT("\n\t ");
1832*0a7e5f1fSJoseph Mingrone 		ND_ICHECKMSG_U("remaining length", len, <, OF_PORT_STATS_REPLY_FIXLEN);
18333c602fabSXin LI 		/* port_no */
1834*0a7e5f1fSJoseph Mingrone 		ND_PRINT(" port_no %s",
1835ee67461eSJoseph Mingrone 			 tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1836ee67461eSJoseph Mingrone 		OF_FWD(2);
18373c602fabSXin LI 		if (ndo->ndo_vflag < 2) {
1838ee67461eSJoseph Mingrone 			OF_CHK_FWD(OF_PORT_STATS_REPLY_FIXLEN - 2);
1839ee67461eSJoseph Mingrone 			continue;
18403c602fabSXin LI 		}
18413c602fabSXin LI 		/* pad */
1842ee67461eSJoseph Mingrone 		OF_FWD(6);
18433c602fabSXin LI 		/* rx_packets */
1844ee67461eSJoseph Mingrone 		ND_PRINT(", rx_packets %" PRIu64, GET_BE_U_8(cp));
1845ee67461eSJoseph Mingrone 		OF_FWD(8);
18463c602fabSXin LI 		/* tx_packets */
1847ee67461eSJoseph Mingrone 		ND_PRINT(", tx_packets %" PRIu64, GET_BE_U_8(cp));
1848ee67461eSJoseph Mingrone 		OF_FWD(8);
18493c602fabSXin LI 		/* rx_bytes */
1850ee67461eSJoseph Mingrone 		ND_PRINT(", rx_bytes %" PRIu64, GET_BE_U_8(cp));
1851ee67461eSJoseph Mingrone 		OF_FWD(8);
18523c602fabSXin LI 		/* tx_bytes */
1853ee67461eSJoseph Mingrone 		ND_PRINT(", tx_bytes %" PRIu64, GET_BE_U_8(cp));
1854ee67461eSJoseph Mingrone 		OF_FWD(8);
18553c602fabSXin LI 		/* rx_dropped */
1856ee67461eSJoseph Mingrone 		ND_PRINT(", rx_dropped %" PRIu64, GET_BE_U_8(cp));
1857ee67461eSJoseph Mingrone 		OF_FWD(8);
18583c602fabSXin LI 		/* tx_dropped */
1859ee67461eSJoseph Mingrone 		ND_PRINT(", tx_dropped %" PRIu64, GET_BE_U_8(cp));
1860ee67461eSJoseph Mingrone 		OF_FWD(8);
18613c602fabSXin LI 		/* rx_errors */
1862ee67461eSJoseph Mingrone 		ND_PRINT(", rx_errors %" PRIu64, GET_BE_U_8(cp));
1863ee67461eSJoseph Mingrone 		OF_FWD(8);
18643c602fabSXin LI 		/* tx_errors */
1865ee67461eSJoseph Mingrone 		ND_PRINT(", tx_errors %" PRIu64, GET_BE_U_8(cp));
1866ee67461eSJoseph Mingrone 		OF_FWD(8);
18673c602fabSXin LI 		/* rx_frame_err */
1868ee67461eSJoseph Mingrone 		ND_PRINT(", rx_frame_err %" PRIu64, GET_BE_U_8(cp));
1869ee67461eSJoseph Mingrone 		OF_FWD(8);
18703c602fabSXin LI 		/* rx_over_err */
1871ee67461eSJoseph Mingrone 		ND_PRINT(", rx_over_err %" PRIu64, GET_BE_U_8(cp));
1872ee67461eSJoseph Mingrone 		OF_FWD(8);
18733c602fabSXin LI 		/* rx_crc_err */
1874ee67461eSJoseph Mingrone 		ND_PRINT(", rx_crc_err %" PRIu64, GET_BE_U_8(cp));
1875ee67461eSJoseph Mingrone 		OF_FWD(8);
18763c602fabSXin LI 		/* collisions */
1877ee67461eSJoseph Mingrone 		ND_PRINT(", collisions %" PRIu64, GET_BE_U_8(cp));
1878ee67461eSJoseph Mingrone 		OF_FWD(8);
18793c602fabSXin LI 	} /* while */
1880ee67461eSJoseph Mingrone 	return;
18813c602fabSXin LI 
18823340d773SGleb Smirnoff invalid: /* skip the undersized trailing data */
1883ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
1884ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
18853c602fabSXin LI }
18863c602fabSXin LI 
18873c602fabSXin LI /* ibid */
1888ee67461eSJoseph Mingrone static void
of10_queue_stats_reply_print(netdissect_options * ndo,const u_char * cp,u_int len)18893c602fabSXin LI of10_queue_stats_reply_print(netdissect_options *ndo,
1890ee67461eSJoseph Mingrone                              const u_char *cp, u_int len)
18918bdc5a62SPatrick Kelsey {
18923c602fabSXin LI 	while (len) {
1893*0a7e5f1fSJoseph Mingrone 		ND_PRINT("\n\t ");
1894*0a7e5f1fSJoseph Mingrone 		ND_ICHECKMSG_U("remaining length", len, <, OF_QUEUE_STATS_REPLY_FIXLEN);
18953c602fabSXin LI 		/* port_no */
1896*0a7e5f1fSJoseph Mingrone 		ND_PRINT(" port_no %s",
1897ee67461eSJoseph Mingrone 		         tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1898ee67461eSJoseph Mingrone 		OF_FWD(2);
18993c602fabSXin LI 		/* pad */
1900ee67461eSJoseph Mingrone 		OF_FWD(2);
19013c602fabSXin LI 		/* queue_id */
1902ee67461eSJoseph Mingrone 		ND_PRINT(", queue_id %u", GET_BE_U_4(cp));
1903ee67461eSJoseph Mingrone 		OF_FWD(4);
19043c602fabSXin LI 		/* tx_bytes */
1905ee67461eSJoseph Mingrone 		ND_PRINT(", tx_bytes %" PRIu64, GET_BE_U_8(cp));
1906ee67461eSJoseph Mingrone 		OF_FWD(8);
19073c602fabSXin LI 		/* tx_packets */
1908ee67461eSJoseph Mingrone 		ND_PRINT(", tx_packets %" PRIu64, GET_BE_U_8(cp));
1909ee67461eSJoseph Mingrone 		OF_FWD(8);
19103c602fabSXin LI 		/* tx_errors */
1911ee67461eSJoseph Mingrone 		ND_PRINT(", tx_errors %" PRIu64, GET_BE_U_8(cp));
1912ee67461eSJoseph Mingrone 		OF_FWD(8);
19133c602fabSXin LI 	} /* while */
1914ee67461eSJoseph Mingrone 	return;
19153c602fabSXin LI 
19163340d773SGleb Smirnoff invalid: /* skip the undersized trailing data */
1917ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
1918ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
19193c602fabSXin LI }
19203c602fabSXin LI 
19213c602fabSXin LI /* ibid */
1922ee67461eSJoseph Mingrone static void
of10_stats_reply_print(netdissect_options * ndo,const u_char * cp,u_int len)19233c602fabSXin LI of10_stats_reply_print(netdissect_options *ndo,
1924ee67461eSJoseph Mingrone                        const u_char *cp, u_int len)
19258bdc5a62SPatrick Kelsey {
19263c602fabSXin LI 	uint16_t type;
19273c602fabSXin LI 
19283c602fabSXin LI 	/* type */
1929ee67461eSJoseph Mingrone 	type = GET_BE_U_2(cp);
1930ee67461eSJoseph Mingrone 	ND_PRINT("\n\t type %s", tok2str(ofpst_str, "invalid (0x%04x)", type));
1931ee67461eSJoseph Mingrone 	OF_FWD(2);
19323c602fabSXin LI 	/* flags */
1933ee67461eSJoseph Mingrone 	ND_PRINT(", flags 0x%04x", GET_BE_U_2(cp));
1934ee67461eSJoseph Mingrone 	of_bitmap_print(ndo, ofpsf_reply_bm, GET_BE_U_2(cp), OFPSF_REPLY_U);
1935ee67461eSJoseph Mingrone 	OF_FWD(2);
19363c602fabSXin LI 
19373c602fabSXin LI 	if (ndo->ndo_vflag > 0) {
1938ee67461eSJoseph Mingrone 		void (*decoder)(netdissect_options *, const u_char *, u_int) =
19393c602fabSXin LI 			type == OFPST_DESC      ? of10_desc_stats_reply_print      :
19403c602fabSXin LI 			type == OFPST_FLOW      ? of10_flow_stats_reply_print      :
19413c602fabSXin LI 			type == OFPST_AGGREGATE ? of10_aggregate_stats_reply_print :
19423c602fabSXin LI 			type == OFPST_TABLE     ? of10_table_stats_reply_print     :
19433c602fabSXin LI 			type == OFPST_PORT      ? of10_port_stats_reply_print      :
19443c602fabSXin LI 			type == OFPST_QUEUE     ? of10_queue_stats_reply_print     :
19453c602fabSXin LI 			type == OFPST_VENDOR    ? of10_vendor_data_print           :
19463c602fabSXin LI 			NULL;
1947ee67461eSJoseph Mingrone 		if (decoder != NULL) {
1948ee67461eSJoseph Mingrone 			decoder(ndo, cp, len);
1949ee67461eSJoseph Mingrone 			return;
19503c602fabSXin LI 		}
1951ee67461eSJoseph Mingrone 	}
1952ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
19533c602fabSXin LI }
19543c602fabSXin LI 
19553c602fabSXin LI /* [OF10] Section 5.3.6 */
1956ee67461eSJoseph Mingrone static void
of10_packet_out_print(netdissect_options * ndo,const u_char * cp,u_int len)19573c602fabSXin LI of10_packet_out_print(netdissect_options *ndo,
1958ee67461eSJoseph Mingrone                       const u_char *cp, u_int len)
19598bdc5a62SPatrick Kelsey {
19603c602fabSXin LI 	uint16_t actions_len;
19613c602fabSXin LI 
19623c602fabSXin LI 	/* buffer_id */
1963ee67461eSJoseph Mingrone 	ND_PRINT("\n\t buffer_id 0x%08x", GET_BE_U_4(cp));
1964ee67461eSJoseph Mingrone 	OF_FWD(4);
19653c602fabSXin LI 	/* in_port */
1966ee67461eSJoseph Mingrone 	ND_PRINT(", in_port %s", tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1967ee67461eSJoseph Mingrone 	OF_FWD(2);
19683c602fabSXin LI 	/* actions_len */
1969ee67461eSJoseph Mingrone 	actions_len = GET_BE_U_2(cp);
1970*0a7e5f1fSJoseph Mingrone 	ND_PRINT(", actions_len %u", actions_len);
1971ee67461eSJoseph Mingrone 	OF_FWD(2);
1972*0a7e5f1fSJoseph Mingrone 	ND_ICHECK_U(actions_len, >, len);
19733c602fabSXin LI 	/* actions */
1974ee67461eSJoseph Mingrone 	of10_actions_print(ndo, "\n\t ", cp, actions_len);
1975ee67461eSJoseph Mingrone 	OF_FWD(actions_len);
19763c602fabSXin LI 	/* data */
1977ee67461eSJoseph Mingrone 	of10_packet_data_print(ndo, cp, len);
1978ee67461eSJoseph Mingrone 	return;
19793c602fabSXin LI 
19803340d773SGleb Smirnoff invalid: /* skip the rest of the message body */
1981ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
1982ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
19833c602fabSXin LI }
19843c602fabSXin LI 
19853c602fabSXin LI /* [OF10] Section 5.4.1 */
1986ee67461eSJoseph Mingrone static void
of10_packet_in_print(netdissect_options * ndo,const u_char * cp,u_int len)19873c602fabSXin LI of10_packet_in_print(netdissect_options *ndo,
1988ee67461eSJoseph Mingrone                      const u_char *cp, u_int len)
19898bdc5a62SPatrick Kelsey {
19903c602fabSXin LI 	/* buffer_id */
1991ee67461eSJoseph Mingrone 	ND_PRINT("\n\t buffer_id %s",
1992ee67461eSJoseph Mingrone 	         tok2str(bufferid_str, "0x%08x", GET_BE_U_4(cp)));
1993ee67461eSJoseph Mingrone 	OF_FWD(4);
19943c602fabSXin LI 	/* total_len */
1995ee67461eSJoseph Mingrone 	ND_PRINT(", total_len %u", GET_BE_U_2(cp));
1996ee67461eSJoseph Mingrone 	OF_FWD(2);
19973c602fabSXin LI 	/* in_port */
1998ee67461eSJoseph Mingrone 	ND_PRINT(", in_port %s", tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1999ee67461eSJoseph Mingrone 	OF_FWD(2);
20003c602fabSXin LI 	/* reason */
2001ee67461eSJoseph Mingrone 	ND_PRINT(", reason %s",
2002ee67461eSJoseph Mingrone 		 tok2str(ofpr_str, "invalid (0x%02x)", GET_U_1(cp)));
2003ee67461eSJoseph Mingrone 	OF_FWD(1);
20043c602fabSXin LI 	/* pad */
2005ee67461eSJoseph Mingrone 	/* Sometimes the last field, check bounds. */
2006ee67461eSJoseph Mingrone 	OF_CHK_FWD(1);
20073c602fabSXin LI 	/* data */
2008ee67461eSJoseph Mingrone 	of10_packet_data_print(ndo, cp, len);
20093c602fabSXin LI }
20103c602fabSXin LI 
20113c602fabSXin LI /* [OF10] Section 5.4.2 */
2012ee67461eSJoseph Mingrone static void
of10_flow_removed_print(netdissect_options * ndo,const u_char * cp,u_int len _U_)20133c602fabSXin LI of10_flow_removed_print(netdissect_options *ndo,
2014ee67461eSJoseph Mingrone                         const u_char *cp, u_int len _U_)
20158bdc5a62SPatrick Kelsey {
20163c602fabSXin LI 	/* match */
2017ee67461eSJoseph Mingrone 	of10_match_print(ndo, "\n\t ", cp);
2018ee67461eSJoseph Mingrone 	cp += OF_MATCH_FIXLEN;
20193c602fabSXin LI 	/* cookie */
2020ee67461eSJoseph Mingrone 	ND_PRINT("\n\t cookie 0x%016" PRIx64, GET_BE_U_8(cp));
20213c602fabSXin LI 	cp += 8;
20223c602fabSXin LI 	/* priority */
2023ee67461eSJoseph Mingrone 	if (GET_BE_U_2(cp))
2024ee67461eSJoseph Mingrone 		ND_PRINT(", priority %u", GET_BE_U_2(cp));
20253c602fabSXin LI 	cp += 2;
20263c602fabSXin LI 	/* reason */
2027ee67461eSJoseph Mingrone 	ND_PRINT(", reason %s",
2028ee67461eSJoseph Mingrone 	         tok2str(ofprr_str, "unknown (0x%02x)", GET_U_1(cp)));
20293c602fabSXin LI 	cp += 1;
20303c602fabSXin LI 	/* pad */
20313c602fabSXin LI 	cp += 1;
20323c602fabSXin LI 	/* duration_sec */
2033ee67461eSJoseph Mingrone 	ND_PRINT(", duration_sec %u", GET_BE_U_4(cp));
20343c602fabSXin LI 	cp += 4;
20353c602fabSXin LI 	/* duration_nsec */
2036ee67461eSJoseph Mingrone 	ND_PRINT(", duration_nsec %u", GET_BE_U_4(cp));
20373c602fabSXin LI 	cp += 4;
20383c602fabSXin LI 	/* idle_timeout */
2039ee67461eSJoseph Mingrone 	if (GET_BE_U_2(cp))
2040ee67461eSJoseph Mingrone 		ND_PRINT(", idle_timeout %u", GET_BE_U_2(cp));
20413c602fabSXin LI 	cp += 2;
20423c602fabSXin LI 	/* pad2 */
20433c602fabSXin LI 	cp += 2;
20443c602fabSXin LI 	/* packet_count */
2045ee67461eSJoseph Mingrone 	ND_PRINT(", packet_count %" PRIu64, GET_BE_U_8(cp));
20463c602fabSXin LI 	cp += 8;
20473c602fabSXin LI 	/* byte_count */
2048ee67461eSJoseph Mingrone 	ND_PRINT(", byte_count %" PRIu64, GET_BE_U_8(cp));
2049ee67461eSJoseph Mingrone }
20503c602fabSXin LI 
2051ee67461eSJoseph Mingrone /* [OF10] Section 5.4.3 */
2052ee67461eSJoseph Mingrone static void
of10_port_status_print(netdissect_options * ndo,const u_char * cp,u_int len _U_)2053ee67461eSJoseph Mingrone of10_port_status_print(netdissect_options *ndo,
2054ee67461eSJoseph Mingrone                        const u_char *cp, u_int len _U_)
2055ee67461eSJoseph Mingrone {
2056ee67461eSJoseph Mingrone 	/* reason */
2057ee67461eSJoseph Mingrone 	ND_PRINT("\n\t reason %s",
2058ee67461eSJoseph Mingrone 	         tok2str(ofppr_str, "invalid (0x%02x)", GET_U_1(cp)));
2059ee67461eSJoseph Mingrone 	cp += 1;
2060ee67461eSJoseph Mingrone 	/* pad */
2061ee67461eSJoseph Mingrone 	/* No need to check bounds, more data follows. */
2062ee67461eSJoseph Mingrone 	cp += 7;
2063ee67461eSJoseph Mingrone 	/* desc */
2064ee67461eSJoseph Mingrone 	of10_phy_port_print(ndo, cp);
20653c602fabSXin LI }
20663c602fabSXin LI 
20673c602fabSXin LI /* [OF10] Section 5.4.4 */
2068ee67461eSJoseph Mingrone static void
of10_error_print(netdissect_options * ndo,const u_char * cp,u_int len)20693c602fabSXin LI of10_error_print(netdissect_options *ndo,
2070ee67461eSJoseph Mingrone                  const u_char *cp, u_int len)
20718bdc5a62SPatrick Kelsey {
2072ee67461eSJoseph Mingrone 	uint16_t type, code;
20733c602fabSXin LI 	const struct tok *code_str;
20743c602fabSXin LI 
20753c602fabSXin LI 	/* type */
2076ee67461eSJoseph Mingrone 	type = GET_BE_U_2(cp);
2077ee67461eSJoseph Mingrone 	OF_FWD(2);
2078ee67461eSJoseph Mingrone 	ND_PRINT("\n\t type %s", tok2str(ofpet_str, "invalid (0x%04x)", type));
20793c602fabSXin LI 	/* code */
2080ee67461eSJoseph Mingrone 	code = GET_BE_U_2(cp);
2081ee67461eSJoseph Mingrone 	OF_FWD(2);
2082ee67461eSJoseph Mingrone 	code_str = uint2tokary(of10_ofpet2tokary, type);
2083ee67461eSJoseph Mingrone 	if (code_str != NULL)
2084ee67461eSJoseph Mingrone 		ND_PRINT(", code %s",
2085ee67461eSJoseph Mingrone 		         tok2str(code_str, "invalid (0x%04x)", code));
2086ee67461eSJoseph Mingrone 	else
2087ee67461eSJoseph Mingrone 		ND_PRINT(", code invalid (0x%04x)", code);
20883c602fabSXin LI 	/* data */
2089ee67461eSJoseph Mingrone 	of_data_print(ndo, cp, len);
20903c602fabSXin LI }
20913c602fabSXin LI 
2092ee67461eSJoseph Mingrone static const struct of_msgtypeinfo of10_msgtypeinfo[OFPT_MAX + 1] = {
2093ee67461eSJoseph Mingrone 	/*
2094ee67461eSJoseph Mingrone 	 * [OF10] Section 5.5.1
2095ee67461eSJoseph Mingrone 	 * Variable-size data.
2096ee67461eSJoseph Mingrone 	 */
20978bdc5a62SPatrick Kelsey 	{
2098ee67461eSJoseph Mingrone 		"HELLO",                    of_data_print,
2099ee67461eSJoseph Mingrone 		REQ_MINLEN,                 0
2100ee67461eSJoseph Mingrone 	},
2101ee67461eSJoseph Mingrone 	/*
2102ee67461eSJoseph Mingrone 	 * [OF10] Section 5.4.4
2103ee67461eSJoseph Mingrone 	 * A fixed-size message body and variable-size data.
2104ee67461eSJoseph Mingrone 	 */
2105ee67461eSJoseph Mingrone 	{
2106ee67461eSJoseph Mingrone 		"ERROR",                    of10_error_print,
2107ee67461eSJoseph Mingrone 		REQ_MINLEN,                 OF_ERROR_MSG_MINLEN
2108ee67461eSJoseph Mingrone 	},
2109ee67461eSJoseph Mingrone 	/*
2110ee67461eSJoseph Mingrone 	 * [OF10] Section 5.5.2
2111ee67461eSJoseph Mingrone 	 * Variable-size data.
2112ee67461eSJoseph Mingrone 	 */
2113ee67461eSJoseph Mingrone 	{
2114ee67461eSJoseph Mingrone 		"ECHO_REQUEST",             of_data_print,
2115ee67461eSJoseph Mingrone 		REQ_MINLEN,                 0
2116ee67461eSJoseph Mingrone 	},
2117ee67461eSJoseph Mingrone 	/*
2118ee67461eSJoseph Mingrone 	 * [OF10] Section 5.5.3
2119ee67461eSJoseph Mingrone 	 * Variable-size data.
2120ee67461eSJoseph Mingrone 	 */
2121ee67461eSJoseph Mingrone 	{
2122ee67461eSJoseph Mingrone 		"ECHO_REPLY",               of_data_print,
2123ee67461eSJoseph Mingrone 		REQ_MINLEN,                 0
2124ee67461eSJoseph Mingrone 	},
2125ee67461eSJoseph Mingrone 	/*
2126ee67461eSJoseph Mingrone 	 * [OF10] Section 5.5.4
2127ee67461eSJoseph Mingrone 	 * A fixed-size message body and variable-size data.
2128ee67461eSJoseph Mingrone 	 */
2129ee67461eSJoseph Mingrone 	{
2130ee67461eSJoseph Mingrone 		"VENDOR",                   of10_vendor_message_print,
2131ee67461eSJoseph Mingrone 		REQ_MINLEN,                 OF_VENDOR_MINLEN
2132ee67461eSJoseph Mingrone 	},
2133ee67461eSJoseph Mingrone 	/*
2134ee67461eSJoseph Mingrone 	 * [OF10] Section 5.3.1
2135ee67461eSJoseph Mingrone 	 * No message body.
2136ee67461eSJoseph Mingrone 	 */
2137ee67461eSJoseph Mingrone 	{
2138ee67461eSJoseph Mingrone 		"FEATURES_REQUEST",         NULL,
2139ee67461eSJoseph Mingrone 		REQ_FIXLEN,                 0
2140ee67461eSJoseph Mingrone 	},
2141ee67461eSJoseph Mingrone 	/*
2142ee67461eSJoseph Mingrone 	 * [OF10] Section 5.3.1
2143ee67461eSJoseph Mingrone 	 * A fixed-size message body and n * fixed-size data units.
2144ee67461eSJoseph Mingrone 	 */
2145ee67461eSJoseph Mingrone 	{
2146ee67461eSJoseph Mingrone 		"FEATURES_REPLY",           of10_features_reply_print,
2147ee67461eSJoseph Mingrone 		REQ_MINLEN,                 OF_FEATURES_REPLY_MINLEN
2148ee67461eSJoseph Mingrone 	},
2149ee67461eSJoseph Mingrone 	/*
2150ee67461eSJoseph Mingrone 	 * [OF10] Section 5.3.2
2151ee67461eSJoseph Mingrone 	 * No message body.
2152ee67461eSJoseph Mingrone 	 */
2153ee67461eSJoseph Mingrone 	{
2154ee67461eSJoseph Mingrone 		"GET_CONFIG_REQUEST",       NULL,
2155ee67461eSJoseph Mingrone 		REQ_FIXLEN,                 0
2156ee67461eSJoseph Mingrone 	},
2157ee67461eSJoseph Mingrone 	/*
2158ee67461eSJoseph Mingrone 	 * [OF10] Section 5.3.2
2159ee67461eSJoseph Mingrone 	 * A fixed-size message body.
2160ee67461eSJoseph Mingrone 	 */
2161ee67461eSJoseph Mingrone 	{
2162ee67461eSJoseph Mingrone 		"GET_CONFIG_REPLY",         of10_switch_config_msg_print,
2163ee67461eSJoseph Mingrone 		REQ_FIXLEN,                 OF_SWITCH_CONFIG_FIXLEN
2164ee67461eSJoseph Mingrone 	},
2165ee67461eSJoseph Mingrone 	/*
2166ee67461eSJoseph Mingrone 	 * [OF10] Section 5.3.2
2167ee67461eSJoseph Mingrone 	 * A fixed-size message body.
2168ee67461eSJoseph Mingrone 	 */
2169ee67461eSJoseph Mingrone 	{
2170ee67461eSJoseph Mingrone 		"SET_CONFIG",               of10_switch_config_msg_print,
2171ee67461eSJoseph Mingrone 		REQ_FIXLEN,                 OF_SWITCH_CONFIG_FIXLEN
2172ee67461eSJoseph Mingrone 	},
2173ee67461eSJoseph Mingrone 	/*
2174ee67461eSJoseph Mingrone 	 * [OF10] Section 5.4.1
2175ee67461eSJoseph Mingrone 	 * A fixed-size message body and variable-size data.
2176ee67461eSJoseph Mingrone 	 * (The 2 mock octets count in OF_PACKET_IN_MINLEN only.)
2177ee67461eSJoseph Mingrone 	 */
2178ee67461eSJoseph Mingrone 	{
2179ee67461eSJoseph Mingrone 		"PACKET_IN",                of10_packet_in_print,
2180ee67461eSJoseph Mingrone 		REQ_MINLEN,                 OF_PACKET_IN_MINLEN - 2
2181ee67461eSJoseph Mingrone 	},
2182ee67461eSJoseph Mingrone 	/*
2183ee67461eSJoseph Mingrone 	 * [OF10] Section 5.4.2
2184ee67461eSJoseph Mingrone 	 * A fixed-size message body.
2185ee67461eSJoseph Mingrone 	 */
2186ee67461eSJoseph Mingrone 	{
2187ee67461eSJoseph Mingrone 		"FLOW_REMOVED",             of10_flow_removed_print,
2188ee67461eSJoseph Mingrone 		REQ_FIXLEN,                 OF_FLOW_REMOVED_FIXLEN
2189ee67461eSJoseph Mingrone 	},
2190ee67461eSJoseph Mingrone 	/*
2191ee67461eSJoseph Mingrone 	 * [OF10] Section 5.4.3
2192ee67461eSJoseph Mingrone 	 * A fixed-size message body.
2193ee67461eSJoseph Mingrone 	 */
2194ee67461eSJoseph Mingrone 	{
2195ee67461eSJoseph Mingrone 		"PORT_STATUS",              of10_port_status_print,
2196ee67461eSJoseph Mingrone 		REQ_FIXLEN,                 OF_PORT_STATUS_FIXLEN
2197ee67461eSJoseph Mingrone 	},
2198ee67461eSJoseph Mingrone 	/*
2199ee67461eSJoseph Mingrone 	 * [OF10] Section 5.3.6
2200ee67461eSJoseph Mingrone 	 * A fixed-size message body, n * variable-size data units and
2201ee67461eSJoseph Mingrone 	 * variable-size data.
2202ee67461eSJoseph Mingrone 	 */
2203ee67461eSJoseph Mingrone 	{
2204ee67461eSJoseph Mingrone 		"PACKET_OUT",               of10_packet_out_print,
2205ee67461eSJoseph Mingrone 		REQ_MINLEN,                 OF_PACKET_OUT_MINLEN
2206ee67461eSJoseph Mingrone 	},
2207ee67461eSJoseph Mingrone 	/*
2208ee67461eSJoseph Mingrone 	 * [OF10] Section 5.3.3
2209ee67461eSJoseph Mingrone 	 * A fixed-size message body and n * variable-size data units.
2210ee67461eSJoseph Mingrone 	 */
2211ee67461eSJoseph Mingrone 	{
2212ee67461eSJoseph Mingrone 		"FLOW_MOD",                 of10_flow_mod_print,
2213ee67461eSJoseph Mingrone 		REQ_MINLEN,                 OF_FLOW_MOD_MINLEN
2214ee67461eSJoseph Mingrone 	},
2215ee67461eSJoseph Mingrone 	/*
2216ee67461eSJoseph Mingrone 	 * [OF10] Section 5.3.3
2217ee67461eSJoseph Mingrone 	 * A fixed-size message body.
2218ee67461eSJoseph Mingrone 	 */
2219ee67461eSJoseph Mingrone 	{
2220ee67461eSJoseph Mingrone 		"PORT_MOD",                 of10_port_mod_print,
2221ee67461eSJoseph Mingrone 		REQ_FIXLEN,                 OF_PORT_MOD_FIXLEN
2222ee67461eSJoseph Mingrone 	},
2223ee67461eSJoseph Mingrone 	/*
2224ee67461eSJoseph Mingrone 	 * [OF10] Section 5.3.5
2225ee67461eSJoseph Mingrone 	 * A fixed-size message body and possibly more data of varying size
2226ee67461eSJoseph Mingrone 	 * and structure.
2227ee67461eSJoseph Mingrone 	 */
2228ee67461eSJoseph Mingrone 	{
2229ee67461eSJoseph Mingrone 		"STATS_REQUEST",            of10_stats_request_print,
2230ee67461eSJoseph Mingrone 		REQ_MINLEN,                 OF_STATS_REQUEST_MINLEN
2231ee67461eSJoseph Mingrone 	},
2232ee67461eSJoseph Mingrone 	/*
2233ee67461eSJoseph Mingrone 	 * [OF10] Section 5.3.5
2234ee67461eSJoseph Mingrone 	 * A fixed-size message body and possibly more data of varying size
2235ee67461eSJoseph Mingrone 	 * and structure.
2236ee67461eSJoseph Mingrone 	 */
2237ee67461eSJoseph Mingrone 	{
2238ee67461eSJoseph Mingrone 		"STATS_REPLY",              of10_stats_reply_print,
2239ee67461eSJoseph Mingrone 		REQ_MINLEN,                 OF_STATS_REPLY_MINLEN
2240ee67461eSJoseph Mingrone 	},
2241ee67461eSJoseph Mingrone 	/*
2242ee67461eSJoseph Mingrone 	 * [OF10] Section 5.3.7
2243ee67461eSJoseph Mingrone 	 * No message body.
2244ee67461eSJoseph Mingrone 	 */
2245ee67461eSJoseph Mingrone 	{
2246ee67461eSJoseph Mingrone 		"BARRIER_REQUEST",          NULL,
2247ee67461eSJoseph Mingrone 		REQ_FIXLEN,                 0
2248ee67461eSJoseph Mingrone 	},
2249ee67461eSJoseph Mingrone 	/*
2250ee67461eSJoseph Mingrone 	 * [OF10] Section 5.3.7
2251ee67461eSJoseph Mingrone 	 * No message body.
2252ee67461eSJoseph Mingrone 	 */
2253ee67461eSJoseph Mingrone 	{
2254ee67461eSJoseph Mingrone 		"BARRIER_REPLY",            NULL,
2255ee67461eSJoseph Mingrone 		REQ_FIXLEN,                 0
2256ee67461eSJoseph Mingrone 	},
2257ee67461eSJoseph Mingrone 	/*
2258ee67461eSJoseph Mingrone 	 * [OF10] Section 5.3.4
2259ee67461eSJoseph Mingrone 	 * A fixed-size message body.
2260ee67461eSJoseph Mingrone 	 */
2261ee67461eSJoseph Mingrone 	{
2262ee67461eSJoseph Mingrone 		"QUEUE_GET_CONFIG_REQUEST", of10_queue_get_config_request_print,
2263ee67461eSJoseph Mingrone 		REQ_FIXLEN,                 OF_QUEUE_GET_CONFIG_REQUEST_FIXLEN
2264ee67461eSJoseph Mingrone 	},
2265ee67461eSJoseph Mingrone 	/*
2266ee67461eSJoseph Mingrone 	 * [OF10] Section 5.3.4
2267ee67461eSJoseph Mingrone 	 * A fixed-size message body and n * variable-size data units.
2268ee67461eSJoseph Mingrone 	 */
2269ee67461eSJoseph Mingrone 	{
2270ee67461eSJoseph Mingrone 		"QUEUE_GET_CONFIG_REPLY",   of10_queue_get_config_reply_print,
2271ee67461eSJoseph Mingrone 		REQ_MINLEN,                 OF_QUEUE_GET_CONFIG_REPLY_MINLEN
2272ee67461eSJoseph Mingrone 	},
2273ee67461eSJoseph Mingrone };
22743c602fabSXin LI 
2275ee67461eSJoseph Mingrone const struct of_msgtypeinfo *
of10_identify_msgtype(const uint8_t type)2276ee67461eSJoseph Mingrone of10_identify_msgtype(const uint8_t type)
2277ee67461eSJoseph Mingrone {
2278ee67461eSJoseph Mingrone 	return type <= OFPT_MAX ? &of10_msgtypeinfo[type] : NULL;
22793c602fabSXin LI }
2280