xref: /freebsd/contrib/tcpdump/print-openflow-1.0.c (revision ee67461e56828dd1f8de165947ba83f6d9148a87)
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  *
9*ee67461eSJoseph Mingrone  * [OF10] https://www.opennetworking.org/wp-content/uploads/2013/04/openflow-spec-v1.0.0.pdf
103c602fabSXin LI  *
11*ee67461eSJoseph Mingrone  * Most functions in this file take the following arguments:
128bdc5a62SPatrick Kelsey  * * cp -- the pointer to the first octet to decode
13*ee67461eSJoseph Mingrone  * * len -- the declared length of the structure to decode
14*ee67461eSJoseph Mingrone  * The convention is that a printer function returns iff the given structure is
15*ee67461eSJoseph Mingrone  * completely within the packet buffer; otherwise it processes the part that is
16*ee67461eSJoseph Mingrone  * within the buffer, sooner of later takes the "truncated packet" shortcut via
17*ee67461eSJoseph Mingrone  * longjmp() and never returns. With that in mind, the function may return
18*ee67461eSJoseph Mingrone  * without printing the structure completely if it is invalid or the ndo_vflag
19*ee67461eSJoseph Mingrone  * value is not high enough. This way the calling function can try to decode
20*ee67461eSJoseph 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 
623c602fabSXin LI #ifdef HAVE_CONFIG_H
63*ee67461eSJoseph Mingrone #include <config.h>
643c602fabSXin LI #endif
653c602fabSXin LI 
66*ee67461eSJoseph Mingrone #include "netdissect-stdinc.h"
673c602fabSXin LI 
68*ee67461eSJoseph Mingrone #define ND_LONGJMP_FROM_TCHECK
693340d773SGleb Smirnoff #include "netdissect.h"
703c602fabSXin LI #include "extract.h"
713c602fabSXin LI #include "addrtoname.h"
723c602fabSXin LI #include "ethertype.h"
733c602fabSXin LI #include "ipproto.h"
748bdc5a62SPatrick Kelsey #include "oui.h"
753c602fabSXin LI #include "openflow.h"
763c602fabSXin LI 
773c602fabSXin LI 
783c602fabSXin LI #define OFPT_HELLO                    0x00
793c602fabSXin LI #define OFPT_ERROR                    0x01
803c602fabSXin LI #define OFPT_ECHO_REQUEST             0x02
813c602fabSXin LI #define OFPT_ECHO_REPLY               0x03
823c602fabSXin LI #define OFPT_VENDOR                   0x04
833c602fabSXin LI #define OFPT_FEATURES_REQUEST         0x05
843c602fabSXin LI #define OFPT_FEATURES_REPLY           0x06
853c602fabSXin LI #define OFPT_GET_CONFIG_REQUEST       0x07
863c602fabSXin LI #define OFPT_GET_CONFIG_REPLY         0x08
873c602fabSXin LI #define OFPT_SET_CONFIG               0x09
883c602fabSXin LI #define OFPT_PACKET_IN                0x0a
893c602fabSXin LI #define OFPT_FLOW_REMOVED             0x0b
903c602fabSXin LI #define OFPT_PORT_STATUS              0x0c
913c602fabSXin LI #define OFPT_PACKET_OUT               0x0d
923c602fabSXin LI #define OFPT_FLOW_MOD                 0x0e
933c602fabSXin LI #define OFPT_PORT_MOD                 0x0f
943c602fabSXin LI #define OFPT_STATS_REQUEST            0x10
953c602fabSXin LI #define OFPT_STATS_REPLY              0x11
963c602fabSXin LI #define OFPT_BARRIER_REQUEST          0x12
973c602fabSXin LI #define OFPT_BARRIER_REPLY            0x13
983c602fabSXin LI #define OFPT_QUEUE_GET_CONFIG_REQUEST 0x14
993c602fabSXin LI #define OFPT_QUEUE_GET_CONFIG_REPLY   0x15
100*ee67461eSJoseph Mingrone #define OFPT_MAX                      OFPT_QUEUE_GET_CONFIG_REPLY
1013c602fabSXin LI 
102*ee67461eSJoseph Mingrone #define OFPPC_PORT_DOWN    (1U <<0)
103*ee67461eSJoseph Mingrone #define OFPPC_NO_STP       (1U <<1)
104*ee67461eSJoseph Mingrone #define OFPPC_NO_RECV      (1U <<2)
105*ee67461eSJoseph Mingrone #define OFPPC_NO_RECV_STP  (1U <<3)
106*ee67461eSJoseph Mingrone #define OFPPC_NO_FLOOD     (1U <<4)
107*ee67461eSJoseph Mingrone #define OFPPC_NO_FWD       (1U <<5)
108*ee67461eSJoseph Mingrone #define OFPPC_NO_PACKET_IN (1U <<6)
1093c602fabSXin LI static const struct tok ofppc_bm[] = {
1103c602fabSXin LI 	{ OFPPC_PORT_DOWN,    "PORT_DOWN"    },
1113c602fabSXin LI 	{ OFPPC_NO_STP,       "NO_STP"       },
1123c602fabSXin LI 	{ OFPPC_NO_RECV,      "NO_RECV"      },
1133c602fabSXin LI 	{ OFPPC_NO_RECV_STP,  "NO_RECV_STP"  },
1143c602fabSXin LI 	{ OFPPC_NO_FLOOD,     "NO_FLOOD"     },
1153c602fabSXin LI 	{ OFPPC_NO_FWD,       "NO_FWD"       },
1163c602fabSXin LI 	{ OFPPC_NO_PACKET_IN, "NO_PACKET_IN" },
1173c602fabSXin LI 	{ 0, NULL }
1183c602fabSXin LI };
1193c602fabSXin LI #define OFPPC_U (~(OFPPC_PORT_DOWN | OFPPC_NO_STP | OFPPC_NO_RECV | \
1203c602fabSXin LI                    OFPPC_NO_RECV_STP | OFPPC_NO_FLOOD | OFPPC_NO_FWD | \
1213c602fabSXin LI                    OFPPC_NO_PACKET_IN))
1223c602fabSXin LI 
123*ee67461eSJoseph Mingrone /*
124*ee67461eSJoseph Mingrone  * [OF10] lists all FPPS_ constants in one enum, but they mean a 1-bit bitmap
125*ee67461eSJoseph Mingrone  * in the least significant octet and a 2-bit code point in the next octet.
126*ee67461eSJoseph Mingrone  * Remember to mix or to separate these two parts as the context requires.
127*ee67461eSJoseph Mingrone  */
128*ee67461eSJoseph Mingrone #define OFPPS_LINK_DOWN   (1U << 0) /* bitmap             */
129*ee67461eSJoseph Mingrone #define OFPPS_STP_LISTEN  (0U << 8) /* code point         */
130*ee67461eSJoseph Mingrone #define OFPPS_STP_LEARN   (1U << 8) /* code point         */
131*ee67461eSJoseph Mingrone #define OFPPS_STP_FORWARD (2U << 8) /* code point         */
132*ee67461eSJoseph Mingrone #define OFPPS_STP_BLOCK   (3U << 8) /* code point         */
133*ee67461eSJoseph Mingrone #define OFPPS_STP_MASK    (3U << 8) /* code point bitmask */
134*ee67461eSJoseph Mingrone static const struct tok ofpps_stp_str[] = {
1353c602fabSXin LI 	{ OFPPS_STP_LISTEN,  "STP_LISTEN"  },
1363c602fabSXin LI 	{ OFPPS_STP_LEARN,   "STP_LEARN"   },
1373c602fabSXin LI 	{ OFPPS_STP_FORWARD, "STP_FORWARD" },
1383c602fabSXin LI 	{ OFPPS_STP_BLOCK,   "STP_BLOCK"   },
1393c602fabSXin LI 	{ 0, NULL }
1403c602fabSXin LI };
1413c602fabSXin LI #define OFPPS_U (~(OFPPS_LINK_DOWN | OFPPS_STP_LISTEN | OFPPS_STP_LEARN | \
1423c602fabSXin LI                    OFPPS_STP_FORWARD | OFPPS_STP_BLOCK))
1433c602fabSXin LI 
144*ee67461eSJoseph Mingrone #define OFPP_MAX        0xff00U
145*ee67461eSJoseph Mingrone #define OFPP_IN_PORT    0xfff8U
146*ee67461eSJoseph Mingrone #define OFPP_TABLE      0xfff9U
147*ee67461eSJoseph Mingrone #define OFPP_NORMAL     0xfffaU
148*ee67461eSJoseph Mingrone #define OFPP_FLOOD      0xfffbU
149*ee67461eSJoseph Mingrone #define OFPP_ALL        0xfffcU
150*ee67461eSJoseph Mingrone #define OFPP_CONTROLLER 0xfffdU
151*ee67461eSJoseph Mingrone #define OFPP_LOCAL      0xfffeU
152*ee67461eSJoseph Mingrone #define OFPP_NONE       0xffffU
1533c602fabSXin LI static const struct tok ofpp_str[] = {
1543c602fabSXin LI 	{ OFPP_MAX,        "MAX"        },
1553c602fabSXin LI 	{ OFPP_IN_PORT,    "IN_PORT"    },
1563c602fabSXin LI 	{ OFPP_TABLE,      "TABLE"      },
1573c602fabSXin LI 	{ OFPP_NORMAL,     "NORMAL"     },
1583c602fabSXin LI 	{ OFPP_FLOOD,      "FLOOD"      },
1593c602fabSXin LI 	{ OFPP_ALL,        "ALL"        },
1603c602fabSXin LI 	{ OFPP_CONTROLLER, "CONTROLLER" },
1613c602fabSXin LI 	{ OFPP_LOCAL,      "LOCAL"      },
1623c602fabSXin LI 	{ OFPP_NONE,       "NONE"       },
1633c602fabSXin LI 	{ 0, NULL }
1643c602fabSXin LI };
1653c602fabSXin LI 
166*ee67461eSJoseph Mingrone #define OFPPF_10MB_HD    (1U << 0)
167*ee67461eSJoseph Mingrone #define OFPPF_10MB_FD    (1U << 1)
168*ee67461eSJoseph Mingrone #define OFPPF_100MB_HD   (1U << 2)
169*ee67461eSJoseph Mingrone #define OFPPF_100MB_FD   (1U << 3)
170*ee67461eSJoseph Mingrone #define OFPPF_1GB_HD     (1U << 4)
171*ee67461eSJoseph Mingrone #define OFPPF_1GB_FD     (1U << 5)
172*ee67461eSJoseph Mingrone #define OFPPF_10GB_FD    (1U << 6)
173*ee67461eSJoseph Mingrone #define OFPPF_COPPER     (1U << 7)
174*ee67461eSJoseph Mingrone #define OFPPF_FIBER      (1U << 8)
175*ee67461eSJoseph Mingrone #define OFPPF_AUTONEG    (1U << 9)
176*ee67461eSJoseph Mingrone #define OFPPF_PAUSE      (1U <<10)
177*ee67461eSJoseph Mingrone #define OFPPF_PAUSE_ASYM (1U <<11)
1783c602fabSXin LI static const struct tok ofppf_bm[] = {
1793c602fabSXin LI 	{ OFPPF_10MB_HD,    "10MB_HD"    },
1803c602fabSXin LI 	{ OFPPF_10MB_FD,    "10MB_FD"    },
1813c602fabSXin LI 	{ OFPPF_100MB_HD,   "100MB_HD"   },
1823c602fabSXin LI 	{ OFPPF_100MB_FD,   "100MB_FD"   },
1833c602fabSXin LI 	{ OFPPF_1GB_HD,     "1GB_HD"     },
1843c602fabSXin LI 	{ OFPPF_1GB_FD,     "1GB_FD"     },
1853c602fabSXin LI 	{ OFPPF_10GB_FD,    "10GB_FD"    },
1863c602fabSXin LI 	{ OFPPF_COPPER,     "COPPER"     },
1873c602fabSXin LI 	{ OFPPF_FIBER,      "FIBER"      },
1883c602fabSXin LI 	{ OFPPF_AUTONEG,    "AUTONEG"    },
1893c602fabSXin LI 	{ OFPPF_PAUSE,      "PAUSE"      },
1903c602fabSXin LI 	{ OFPPF_PAUSE_ASYM, "PAUSE_ASYM" },
1913c602fabSXin LI 	{ 0, NULL }
1923c602fabSXin LI };
1933c602fabSXin LI #define OFPPF_U (~(OFPPF_10MB_HD | OFPPF_10MB_FD | OFPPF_100MB_HD | \
1943c602fabSXin LI                    OFPPF_100MB_FD | OFPPF_1GB_HD | OFPPF_1GB_FD | \
1953c602fabSXin LI                    OFPPF_10GB_FD | OFPPF_COPPER | OFPPF_FIBER | \
1963c602fabSXin LI                    OFPPF_AUTONEG | OFPPF_PAUSE | OFPPF_PAUSE_ASYM))
1973c602fabSXin LI 
1983c602fabSXin LI #define OFPQT_NONE     0x0000
1993c602fabSXin LI #define OFPQT_MIN_RATE 0x0001
2003c602fabSXin LI static const struct tok ofpqt_str[] = {
2013c602fabSXin LI 	{ OFPQT_NONE,     "NONE"     },
2023c602fabSXin LI 	{ OFPQT_MIN_RATE, "MIN_RATE" },
2033c602fabSXin LI 	{ 0, NULL }
2043c602fabSXin LI };
2053c602fabSXin LI 
206*ee67461eSJoseph Mingrone #define OFPFW_IN_PORT      (1U <<0)
207*ee67461eSJoseph Mingrone #define OFPFW_DL_VLAN      (1U <<1)
208*ee67461eSJoseph Mingrone #define OFPFW_DL_SRC       (1U <<2)
209*ee67461eSJoseph Mingrone #define OFPFW_DL_DST       (1U <<3)
210*ee67461eSJoseph Mingrone #define OFPFW_DL_TYPE      (1U <<4)
211*ee67461eSJoseph Mingrone #define OFPFW_NW_PROTO     (1U <<5)
212*ee67461eSJoseph Mingrone #define OFPFW_TP_SRC       (1U <<6)
213*ee67461eSJoseph Mingrone #define OFPFW_TP_DST       (1U <<7)
2143c602fabSXin LI #define OFPFW_NW_SRC_SHIFT 8
2153c602fabSXin LI #define OFPFW_NW_SRC_BITS  6
216*ee67461eSJoseph Mingrone #define OFPFW_NW_SRC_MASK  (((1U <<OFPFW_NW_SRC_BITS) - 1) << OFPFW_NW_SRC_SHIFT)
2173c602fabSXin LI #define OFPFW_NW_DST_SHIFT 14
2183c602fabSXin LI #define OFPFW_NW_DST_BITS  6
219*ee67461eSJoseph Mingrone #define OFPFW_NW_DST_MASK  (((1U <<OFPFW_NW_DST_BITS) - 1) << OFPFW_NW_DST_SHIFT)
220*ee67461eSJoseph Mingrone #define OFPFW_DL_VLAN_PCP  (1U <<20)
221*ee67461eSJoseph Mingrone #define OFPFW_NW_TOS       (1U <<21)
222*ee67461eSJoseph Mingrone #define OFPFW_ALL          ((1U <<22) - 1)
2233c602fabSXin LI static const struct tok ofpfw_bm[] = {
2243c602fabSXin LI 	{ OFPFW_IN_PORT,     "IN_PORT"     },
2253c602fabSXin LI 	{ OFPFW_DL_VLAN,     "DL_VLAN"     },
2263c602fabSXin LI 	{ OFPFW_DL_SRC,      "DL_SRC"      },
2273c602fabSXin LI 	{ OFPFW_DL_DST,      "DL_DST"      },
2283c602fabSXin LI 	{ OFPFW_DL_TYPE,     "DL_TYPE"     },
2293c602fabSXin LI 	{ OFPFW_NW_PROTO,    "NW_PROTO"    },
2303c602fabSXin LI 	{ OFPFW_TP_SRC,      "TP_SRC"      },
2313c602fabSXin LI 	{ OFPFW_TP_DST,      "TP_DST"      },
2323c602fabSXin LI 	{ OFPFW_DL_VLAN_PCP, "DL_VLAN_PCP" },
2333c602fabSXin LI 	{ OFPFW_NW_TOS,      "NW_TOS"      },
2343c602fabSXin LI 	{ 0, NULL }
2353c602fabSXin LI };
2363c602fabSXin LI /* The above array does not include bits 8~13 (OFPFW_NW_SRC_*) and 14~19
2373c602fabSXin LI  * (OFPFW_NW_DST_*), which are not a part of the bitmap and require decoding
2383c602fabSXin LI  * other than that of tok2str(). The macro below includes these bits such that
2393c602fabSXin LI  * they are not reported as bogus in the decoding. */
2403c602fabSXin LI #define OFPFW_U (~(OFPFW_ALL))
2413c602fabSXin LI 
242*ee67461eSJoseph Mingrone #define OFPAT_OUTPUT       0x0000U
243*ee67461eSJoseph Mingrone #define OFPAT_SET_VLAN_VID 0x0001U
244*ee67461eSJoseph Mingrone #define OFPAT_SET_VLAN_PCP 0x0002U
245*ee67461eSJoseph Mingrone #define OFPAT_STRIP_VLAN   0x0003U
246*ee67461eSJoseph Mingrone #define OFPAT_SET_DL_SRC   0x0004U
247*ee67461eSJoseph Mingrone #define OFPAT_SET_DL_DST   0x0005U
248*ee67461eSJoseph Mingrone #define OFPAT_SET_NW_SRC   0x0006U
249*ee67461eSJoseph Mingrone #define OFPAT_SET_NW_DST   0x0007U
250*ee67461eSJoseph Mingrone #define OFPAT_SET_NW_TOS   0x0008U
251*ee67461eSJoseph Mingrone #define OFPAT_SET_TP_SRC   0x0009U
252*ee67461eSJoseph Mingrone #define OFPAT_SET_TP_DST   0x000aU
253*ee67461eSJoseph Mingrone #define OFPAT_ENQUEUE      0x000bU
254*ee67461eSJoseph Mingrone #define OFPAT_VENDOR       0xffffU
2553c602fabSXin LI static const struct tok ofpat_str[] = {
2563c602fabSXin LI 	{ OFPAT_OUTPUT,       "OUTPUT"       },
2573c602fabSXin LI 	{ OFPAT_SET_VLAN_VID, "SET_VLAN_VID" },
2583c602fabSXin LI 	{ OFPAT_SET_VLAN_PCP, "SET_VLAN_PCP" },
2593c602fabSXin LI 	{ OFPAT_STRIP_VLAN,   "STRIP_VLAN"   },
2603c602fabSXin LI 	{ OFPAT_SET_DL_SRC,   "SET_DL_SRC"   },
2613c602fabSXin LI 	{ OFPAT_SET_DL_DST,   "SET_DL_DST"   },
2623c602fabSXin LI 	{ OFPAT_SET_NW_SRC,   "SET_NW_SRC"   },
2633c602fabSXin LI 	{ OFPAT_SET_NW_DST,   "SET_NW_DST"   },
2643c602fabSXin LI 	{ OFPAT_SET_NW_TOS,   "SET_NW_TOS"   },
2653c602fabSXin LI 	{ OFPAT_SET_TP_SRC,   "SET_TP_SRC"   },
2663c602fabSXin LI 	{ OFPAT_SET_TP_DST,   "SET_TP_DST"   },
2673c602fabSXin LI 	{ OFPAT_ENQUEUE,      "ENQUEUE"      },
2683c602fabSXin LI 	{ OFPAT_VENDOR,       "VENDOR"       },
2693c602fabSXin LI 	{ 0, NULL }
2703c602fabSXin LI };
2713c602fabSXin LI 
2723c602fabSXin LI /* bit-shifted, w/o vendor action */
2733c602fabSXin LI static const struct tok ofpat_bm[] = {
274*ee67461eSJoseph Mingrone 	{ 1U <<OFPAT_OUTPUT,       "OUTPUT"       },
275*ee67461eSJoseph Mingrone 	{ 1U <<OFPAT_SET_VLAN_VID, "SET_VLAN_VID" },
276*ee67461eSJoseph Mingrone 	{ 1U <<OFPAT_SET_VLAN_PCP, "SET_VLAN_PCP" },
277*ee67461eSJoseph Mingrone 	{ 1U <<OFPAT_STRIP_VLAN,   "STRIP_VLAN"   },
278*ee67461eSJoseph Mingrone 	{ 1U <<OFPAT_SET_DL_SRC,   "SET_DL_SRC"   },
279*ee67461eSJoseph Mingrone 	{ 1U <<OFPAT_SET_DL_DST,   "SET_DL_DST"   },
280*ee67461eSJoseph Mingrone 	{ 1U <<OFPAT_SET_NW_SRC,   "SET_NW_SRC"   },
281*ee67461eSJoseph Mingrone 	{ 1U <<OFPAT_SET_NW_DST,   "SET_NW_DST"   },
282*ee67461eSJoseph Mingrone 	{ 1U <<OFPAT_SET_NW_TOS,   "SET_NW_TOS"   },
283*ee67461eSJoseph Mingrone 	{ 1U <<OFPAT_SET_TP_SRC,   "SET_TP_SRC"   },
284*ee67461eSJoseph Mingrone 	{ 1U <<OFPAT_SET_TP_DST,   "SET_TP_DST"   },
285*ee67461eSJoseph Mingrone 	{ 1U <<OFPAT_ENQUEUE,      "ENQUEUE"      },
2863c602fabSXin LI 	{ 0, NULL }
2873c602fabSXin LI };
288*ee67461eSJoseph Mingrone #define OFPAT_U (~(1U <<OFPAT_OUTPUT | 1U <<OFPAT_SET_VLAN_VID | \
289*ee67461eSJoseph Mingrone                    1U <<OFPAT_SET_VLAN_PCP | 1U <<OFPAT_STRIP_VLAN | \
290*ee67461eSJoseph Mingrone                    1U <<OFPAT_SET_DL_SRC | 1U <<OFPAT_SET_DL_DST | \
291*ee67461eSJoseph Mingrone                    1U <<OFPAT_SET_NW_SRC | 1U <<OFPAT_SET_NW_DST | \
292*ee67461eSJoseph Mingrone                    1U <<OFPAT_SET_NW_TOS | 1U <<OFPAT_SET_TP_SRC | \
293*ee67461eSJoseph Mingrone                    1U <<OFPAT_SET_TP_DST | 1U <<OFPAT_ENQUEUE))
2943c602fabSXin LI 
295*ee67461eSJoseph Mingrone #define OFPC_FLOW_STATS   (1U <<0)
296*ee67461eSJoseph Mingrone #define OFPC_TABLE_STATS  (1U <<1)
297*ee67461eSJoseph Mingrone #define OFPC_PORT_STATS   (1U <<2)
298*ee67461eSJoseph Mingrone #define OFPC_STP          (1U <<3)
299*ee67461eSJoseph Mingrone #define OFPC_RESERVED     (1U <<4)
300*ee67461eSJoseph Mingrone #define OFPC_IP_REASM     (1U <<5)
301*ee67461eSJoseph Mingrone #define OFPC_QUEUE_STATS  (1U <<6)
302*ee67461eSJoseph Mingrone #define OFPC_ARP_MATCH_IP (1U <<7)
3033c602fabSXin LI static const struct tok ofp_capabilities_bm[] = {
3043c602fabSXin LI 	{ OFPC_FLOW_STATS,   "FLOW_STATS"   },
3053c602fabSXin LI 	{ OFPC_TABLE_STATS,  "TABLE_STATS"  },
3063c602fabSXin LI 	{ OFPC_PORT_STATS,   "PORT_STATS"   },
3073c602fabSXin LI 	{ OFPC_STP,          "STP"          },
3083c602fabSXin LI 	{ OFPC_RESERVED,     "RESERVED"     }, /* not in the mask below */
3093c602fabSXin LI 	{ OFPC_IP_REASM,     "IP_REASM"     },
3103c602fabSXin LI 	{ OFPC_QUEUE_STATS,  "QUEUE_STATS"  },
3113c602fabSXin LI 	{ OFPC_ARP_MATCH_IP, "ARP_MATCH_IP" },
3123c602fabSXin LI 	{ 0, NULL }
3133c602fabSXin LI };
3143c602fabSXin LI #define OFPCAP_U (~(OFPC_FLOW_STATS | OFPC_TABLE_STATS | OFPC_PORT_STATS | \
3153c602fabSXin LI                     OFPC_STP | OFPC_IP_REASM | OFPC_QUEUE_STATS | \
3163c602fabSXin LI                     OFPC_ARP_MATCH_IP))
3173c602fabSXin LI 
318*ee67461eSJoseph Mingrone #define OFPC_FRAG_NORMAL 0x0000U
319*ee67461eSJoseph Mingrone #define OFPC_FRAG_DROP   0x0001U
320*ee67461eSJoseph Mingrone #define OFPC_FRAG_REASM  0x0002U
321*ee67461eSJoseph Mingrone #define OFPC_FRAG_MASK   0x0003U
3223c602fabSXin LI static const struct tok ofp_config_str[] = {
3233c602fabSXin LI 	{ OFPC_FRAG_NORMAL, "FRAG_NORMAL" },
3243c602fabSXin LI 	{ OFPC_FRAG_DROP,   "FRAG_DROP"   },
3253c602fabSXin LI 	{ OFPC_FRAG_REASM,  "FRAG_REASM"  },
3263c602fabSXin LI 	{ 0, NULL }
3273c602fabSXin LI };
3283c602fabSXin LI 
329*ee67461eSJoseph Mingrone #define OFPFC_ADD           0x0000U
330*ee67461eSJoseph Mingrone #define OFPFC_MODIFY        0x0001U
331*ee67461eSJoseph Mingrone #define OFPFC_MODIFY_STRICT 0x0002U
332*ee67461eSJoseph Mingrone #define OFPFC_DELETE        0x0003U
333*ee67461eSJoseph Mingrone #define OFPFC_DELETE_STRICT 0x0004U
3343c602fabSXin LI static const struct tok ofpfc_str[] = {
3353c602fabSXin LI 	{ OFPFC_ADD,           "ADD"           },
3363c602fabSXin LI 	{ OFPFC_MODIFY,        "MODIFY"        },
3373c602fabSXin LI 	{ OFPFC_MODIFY_STRICT, "MODIFY_STRICT" },
3383c602fabSXin LI 	{ OFPFC_DELETE,        "DELETE"        },
3393c602fabSXin LI 	{ OFPFC_DELETE_STRICT, "DELETE_STRICT" },
3403c602fabSXin LI 	{ 0, NULL }
3413c602fabSXin LI };
3423c602fabSXin LI 
3433c602fabSXin LI static const struct tok bufferid_str[] = {
3443c602fabSXin LI 	{ 0xffffffff, "NONE" },
3453c602fabSXin LI 	{ 0, NULL }
3463c602fabSXin LI };
3473c602fabSXin LI 
348*ee67461eSJoseph Mingrone #define OFPFF_SEND_FLOW_REM (1U <<0)
349*ee67461eSJoseph Mingrone #define OFPFF_CHECK_OVERLAP (1U <<1)
350*ee67461eSJoseph Mingrone #define OFPFF_EMERG         (1U <<2)
3513c602fabSXin LI static const struct tok ofpff_bm[] = {
3523c602fabSXin LI 	{ OFPFF_SEND_FLOW_REM, "SEND_FLOW_REM" },
3533c602fabSXin LI 	{ OFPFF_CHECK_OVERLAP, "CHECK_OVERLAP" },
3543c602fabSXin LI 	{ OFPFF_EMERG,         "EMERG"         },
3553c602fabSXin LI 	{ 0, NULL }
3563c602fabSXin LI };
3573c602fabSXin LI #define OFPFF_U (~(OFPFF_SEND_FLOW_REM | OFPFF_CHECK_OVERLAP | OFPFF_EMERG))
3583c602fabSXin LI 
359*ee67461eSJoseph Mingrone #define OFPST_DESC      0x0000U
360*ee67461eSJoseph Mingrone #define OFPST_FLOW      0x0001U
361*ee67461eSJoseph Mingrone #define OFPST_AGGREGATE 0x0002U
362*ee67461eSJoseph Mingrone #define OFPST_TABLE     0x0003U
363*ee67461eSJoseph Mingrone #define OFPST_PORT      0x0004U
364*ee67461eSJoseph Mingrone #define OFPST_QUEUE     0x0005U
365*ee67461eSJoseph Mingrone #define OFPST_VENDOR    0xffffU
3663c602fabSXin LI static const struct tok ofpst_str[] = {
3673c602fabSXin LI 	{ OFPST_DESC,      "DESC"      },
3683c602fabSXin LI 	{ OFPST_FLOW,      "FLOW"      },
3693c602fabSXin LI 	{ OFPST_AGGREGATE, "AGGREGATE" },
3703c602fabSXin LI 	{ OFPST_TABLE,     "TABLE"     },
3713c602fabSXin LI 	{ OFPST_PORT,      "PORT"      },
3723c602fabSXin LI 	{ OFPST_QUEUE,     "QUEUE"     },
3733c602fabSXin LI 	{ OFPST_VENDOR,    "VENDOR"    },
3743c602fabSXin LI 	{ 0, NULL }
3753c602fabSXin LI };
3763c602fabSXin LI 
3773c602fabSXin LI static const struct tok tableid_str[] = {
378*ee67461eSJoseph Mingrone 	{ 0xfeU, "EMERG" },
379*ee67461eSJoseph Mingrone 	{ 0xffU, "ALL"   },
3803c602fabSXin LI 	{ 0, NULL }
3813c602fabSXin LI };
3823c602fabSXin LI 
383*ee67461eSJoseph Mingrone #define OFPQ_ALL      0xffffffffU
3843c602fabSXin LI static const struct tok ofpq_str[] = {
3853c602fabSXin LI 	{ OFPQ_ALL, "ALL" },
3863c602fabSXin LI 	{ 0, NULL }
3873c602fabSXin LI };
3883c602fabSXin LI 
389*ee67461eSJoseph Mingrone #define OFPSF_REPLY_MORE 0x0001U
3903c602fabSXin LI static const struct tok ofpsf_reply_bm[] = {
3913c602fabSXin LI 	{ OFPSF_REPLY_MORE, "MORE" },
3923c602fabSXin LI 	{ 0, NULL }
3933c602fabSXin LI };
3943c602fabSXin LI #define OFPSF_REPLY_U (~(OFPSF_REPLY_MORE))
3953c602fabSXin LI 
396*ee67461eSJoseph Mingrone #define OFPR_NO_MATCH 0x00U
397*ee67461eSJoseph Mingrone #define OFPR_ACTION   0x01U
3983c602fabSXin LI static const struct tok ofpr_str[] = {
3993c602fabSXin LI 	{ OFPR_NO_MATCH, "NO_MATCH" },
4003c602fabSXin LI 	{ OFPR_ACTION,   "ACTION"   },
4013c602fabSXin LI 	{ 0, NULL }
4023c602fabSXin LI };
4033c602fabSXin LI 
404*ee67461eSJoseph Mingrone #define OFPRR_IDLE_TIMEOUT 0x00U
405*ee67461eSJoseph Mingrone #define OFPRR_HARD_TIMEOUT 0x01U
406*ee67461eSJoseph Mingrone #define OFPRR_DELETE       0x02U
4073c602fabSXin LI static const struct tok ofprr_str[] = {
4083c602fabSXin LI 	{ OFPRR_IDLE_TIMEOUT, "IDLE_TIMEOUT" },
4093c602fabSXin LI 	{ OFPRR_HARD_TIMEOUT, "HARD_TIMEOUT" },
4103c602fabSXin LI 	{ OFPRR_DELETE,       "DELETE"       },
4113c602fabSXin LI 	{ 0, NULL }
4123c602fabSXin LI };
4133c602fabSXin LI 
414*ee67461eSJoseph Mingrone #define OFPPR_ADD    0x00U
415*ee67461eSJoseph Mingrone #define OFPPR_DELETE 0x01U
416*ee67461eSJoseph Mingrone #define OFPPR_MODIFY 0x02U
4173c602fabSXin LI static const struct tok ofppr_str[] = {
4183c602fabSXin LI 	{ OFPPR_ADD,    "ADD"    },
4193c602fabSXin LI 	{ OFPPR_DELETE, "DELETE" },
4203c602fabSXin LI 	{ OFPPR_MODIFY, "MODIFY" },
4213c602fabSXin LI 	{ 0, NULL }
4223c602fabSXin LI };
4233c602fabSXin LI 
424*ee67461eSJoseph Mingrone #define OFPET_HELLO_FAILED    0x0000U
425*ee67461eSJoseph Mingrone #define OFPET_BAD_REQUEST     0x0001U
426*ee67461eSJoseph Mingrone #define OFPET_BAD_ACTION      0x0002U
427*ee67461eSJoseph Mingrone #define OFPET_FLOW_MOD_FAILED 0x0003U
428*ee67461eSJoseph Mingrone #define OFPET_PORT_MOD_FAILED 0x0004U
429*ee67461eSJoseph Mingrone #define OFPET_QUEUE_OP_FAILED 0x0005U
4303c602fabSXin LI static const struct tok ofpet_str[] = {
4313c602fabSXin LI 	{ OFPET_HELLO_FAILED,    "HELLO_FAILED"    },
4323c602fabSXin LI 	{ OFPET_BAD_REQUEST,     "BAD_REQUEST"     },
4333c602fabSXin LI 	{ OFPET_BAD_ACTION,      "BAD_ACTION"      },
4343c602fabSXin LI 	{ OFPET_FLOW_MOD_FAILED, "FLOW_MOD_FAILED" },
4353c602fabSXin LI 	{ OFPET_PORT_MOD_FAILED, "PORT_MOD_FAILED" },
4363c602fabSXin LI 	{ OFPET_QUEUE_OP_FAILED, "QUEUE_OP_FAILED" },
4373c602fabSXin LI 	{ 0, NULL }
4383c602fabSXin LI };
4393c602fabSXin LI 
440*ee67461eSJoseph Mingrone #define OFPHFC_INCOMPATIBLE 0x0000U
441*ee67461eSJoseph Mingrone #define OFPHFC_EPERM        0x0001U
4423c602fabSXin LI static const struct tok ofphfc_str[] = {
4433c602fabSXin LI 	{ OFPHFC_INCOMPATIBLE, "INCOMPATIBLE" },
4443c602fabSXin LI 	{ OFPHFC_EPERM,        "EPERM"        },
4453c602fabSXin LI 	{ 0, NULL }
4463c602fabSXin LI };
4473c602fabSXin LI 
448*ee67461eSJoseph Mingrone #define OFPBRC_BAD_VERSION    0x0000U
449*ee67461eSJoseph Mingrone #define OFPBRC_BAD_TYPE       0x0001U
450*ee67461eSJoseph Mingrone #define OFPBRC_BAD_STAT       0x0002U
451*ee67461eSJoseph Mingrone #define OFPBRC_BAD_VENDOR     0x0003U
452*ee67461eSJoseph Mingrone #define OFPBRC_BAD_SUBTYPE    0x0004U
453*ee67461eSJoseph Mingrone #define OFPBRC_EPERM          0x0005U
454*ee67461eSJoseph Mingrone #define OFPBRC_BAD_LEN        0x0006U
455*ee67461eSJoseph Mingrone #define OFPBRC_BUFFER_EMPTY   0x0007U
456*ee67461eSJoseph Mingrone #define OFPBRC_BUFFER_UNKNOWN 0x0008U
4573c602fabSXin LI static const struct tok ofpbrc_str[] = {
4583c602fabSXin LI 	{ OFPBRC_BAD_VERSION,    "BAD_VERSION"    },
4593c602fabSXin LI 	{ OFPBRC_BAD_TYPE,       "BAD_TYPE"       },
4603c602fabSXin LI 	{ OFPBRC_BAD_STAT,       "BAD_STAT"       },
4613c602fabSXin LI 	{ OFPBRC_BAD_VENDOR,     "BAD_VENDOR"     },
4623c602fabSXin LI 	{ OFPBRC_BAD_SUBTYPE,    "BAD_SUBTYPE"    },
4633c602fabSXin LI 	{ OFPBRC_EPERM,          "EPERM"          },
4643c602fabSXin LI 	{ OFPBRC_BAD_LEN,        "BAD_LEN"        },
4653c602fabSXin LI 	{ OFPBRC_BUFFER_EMPTY,   "BUFFER_EMPTY"   },
4663c602fabSXin LI 	{ OFPBRC_BUFFER_UNKNOWN, "BUFFER_UNKNOWN" },
4673c602fabSXin LI 	{ 0, NULL }
4683c602fabSXin LI };
4693c602fabSXin LI 
470*ee67461eSJoseph Mingrone #define OFPBAC_BAD_TYPE        0x0000U
471*ee67461eSJoseph Mingrone #define OFPBAC_BAD_LEN         0x0001U
472*ee67461eSJoseph Mingrone #define OFPBAC_BAD_VENDOR      0x0002U
473*ee67461eSJoseph Mingrone #define OFPBAC_BAD_VENDOR_TYPE 0x0003U
474*ee67461eSJoseph Mingrone #define OFPBAC_BAD_OUT_PORT    0x0004U
475*ee67461eSJoseph Mingrone #define OFPBAC_BAD_ARGUMENT    0x0005U
476*ee67461eSJoseph Mingrone #define OFPBAC_EPERM           0x0006U
477*ee67461eSJoseph Mingrone #define OFPBAC_TOO_MANY        0x0007U
478*ee67461eSJoseph Mingrone #define OFPBAC_BAD_QUEUE       0x0008U
4793c602fabSXin LI static const struct tok ofpbac_str[] = {
4803c602fabSXin LI 	{ OFPBAC_BAD_TYPE,        "BAD_TYPE"        },
4813c602fabSXin LI 	{ OFPBAC_BAD_LEN,         "BAD_LEN"         },
4823c602fabSXin LI 	{ OFPBAC_BAD_VENDOR,      "BAD_VENDOR"      },
4833c602fabSXin LI 	{ OFPBAC_BAD_VENDOR_TYPE, "BAD_VENDOR_TYPE" },
4843c602fabSXin LI 	{ OFPBAC_BAD_OUT_PORT,    "BAD_OUT_PORT"    },
4853c602fabSXin LI 	{ OFPBAC_BAD_ARGUMENT,    "BAD_ARGUMENT"    },
4863c602fabSXin LI 	{ OFPBAC_EPERM,           "EPERM"           },
4873c602fabSXin LI 	{ OFPBAC_TOO_MANY,        "TOO_MANY"        },
4883c602fabSXin LI 	{ OFPBAC_BAD_QUEUE,       "BAD_QUEUE"       },
4893c602fabSXin LI 	{ 0, NULL }
4903c602fabSXin LI };
4913c602fabSXin LI 
492*ee67461eSJoseph Mingrone #define OFPFMFC_ALL_TABLES_FULL   0x0000U
493*ee67461eSJoseph Mingrone #define OFPFMFC_OVERLAP           0x0001U
494*ee67461eSJoseph Mingrone #define OFPFMFC_EPERM             0x0002U
495*ee67461eSJoseph Mingrone #define OFPFMFC_BAD_EMERG_TIMEOUT 0x0003U
496*ee67461eSJoseph Mingrone #define OFPFMFC_BAD_COMMAND       0x0004U
497*ee67461eSJoseph Mingrone #define OFPFMFC_UNSUPPORTED       0x0005U
4983c602fabSXin LI static const struct tok ofpfmfc_str[] = {
4993c602fabSXin LI 	{ OFPFMFC_ALL_TABLES_FULL,   "ALL_TABLES_FULL"   },
5003c602fabSXin LI 	{ OFPFMFC_OVERLAP,           "OVERLAP"           },
5013c602fabSXin LI 	{ OFPFMFC_EPERM,             "EPERM"             },
5023c602fabSXin LI 	{ OFPFMFC_BAD_EMERG_TIMEOUT, "BAD_EMERG_TIMEOUT" },
5033c602fabSXin LI 	{ OFPFMFC_BAD_COMMAND,       "BAD_COMMAND"       },
5043c602fabSXin LI 	{ OFPFMFC_UNSUPPORTED,       "UNSUPPORTED"       },
5053c602fabSXin LI 	{ 0, NULL }
5063c602fabSXin LI };
5073c602fabSXin LI 
508*ee67461eSJoseph Mingrone #define OFPPMFC_BAD_PORT    0x0000U
509*ee67461eSJoseph Mingrone #define OFPPMFC_BAD_HW_ADDR 0x0001U
5103c602fabSXin LI static const struct tok ofppmfc_str[] = {
5113c602fabSXin LI 	{ OFPPMFC_BAD_PORT,    "BAD_PORT"    },
5123c602fabSXin LI 	{ OFPPMFC_BAD_HW_ADDR, "BAD_HW_ADDR" },
5133c602fabSXin LI 	{ 0, NULL }
5143c602fabSXin LI };
5153c602fabSXin LI 
516*ee67461eSJoseph Mingrone #define OFPQOFC_BAD_PORT  0x0000U
517*ee67461eSJoseph Mingrone #define OFPQOFC_BAD_QUEUE 0x0001U
518*ee67461eSJoseph Mingrone #define OFPQOFC_EPERM     0x0002U
5193c602fabSXin LI static const struct tok ofpqofc_str[] = {
5203c602fabSXin LI 	{ OFPQOFC_BAD_PORT,  "BAD_PORT"  },
5213c602fabSXin LI 	{ OFPQOFC_BAD_QUEUE, "BAD_QUEUE" },
5223c602fabSXin LI 	{ OFPQOFC_EPERM,     "EPERM"     },
5233c602fabSXin LI 	{ 0, NULL }
5243c602fabSXin LI };
5253c602fabSXin LI 
526*ee67461eSJoseph Mingrone static const struct uint_tokary of10_ofpet2tokary[] = {
527*ee67461eSJoseph Mingrone 	{ OFPET_HELLO_FAILED,    ofphfc_str  },
528*ee67461eSJoseph Mingrone 	{ OFPET_BAD_REQUEST,     ofpbrc_str  },
529*ee67461eSJoseph Mingrone 	{ OFPET_BAD_ACTION,      ofpbac_str  },
530*ee67461eSJoseph Mingrone 	{ OFPET_FLOW_MOD_FAILED, ofpfmfc_str },
531*ee67461eSJoseph Mingrone 	{ OFPET_PORT_MOD_FAILED, ofppmfc_str },
532*ee67461eSJoseph Mingrone 	{ OFPET_QUEUE_OP_FAILED, ofpqofc_str },
533*ee67461eSJoseph Mingrone 	/* uint2tokary() does not use array termination. */
5343c602fabSXin LI };
5353c602fabSXin LI 
536*ee67461eSJoseph Mingrone /* lengths (fixed or minimal) of particular message types, where not 0 */
537*ee67461eSJoseph Mingrone #define OF_SWITCH_CONFIG_FIXLEN            (12U - OF_HEADER_FIXLEN)
538*ee67461eSJoseph Mingrone #define OF_FEATURES_REPLY_MINLEN           (32U - OF_HEADER_FIXLEN)
539*ee67461eSJoseph Mingrone #define OF_PORT_STATUS_FIXLEN              (64U - OF_HEADER_FIXLEN)
540*ee67461eSJoseph Mingrone #define OF_PORT_MOD_FIXLEN                 (32U - OF_HEADER_FIXLEN)
541*ee67461eSJoseph Mingrone #define OF_PACKET_IN_MINLEN                (20U - OF_HEADER_FIXLEN) /* with 2 mock octets */
542*ee67461eSJoseph Mingrone #define OF_PACKET_OUT_MINLEN               (16U - OF_HEADER_FIXLEN)
543*ee67461eSJoseph Mingrone #define OF_FLOW_MOD_MINLEN                 (72U - OF_HEADER_FIXLEN)
544*ee67461eSJoseph Mingrone #define OF_FLOW_REMOVED_FIXLEN             (88U - OF_HEADER_FIXLEN)
545*ee67461eSJoseph Mingrone #define OF_ERROR_MSG_MINLEN                (12U - OF_HEADER_FIXLEN)
546*ee67461eSJoseph Mingrone #define OF_STATS_REQUEST_MINLEN            (12U - OF_HEADER_FIXLEN)
547*ee67461eSJoseph Mingrone #define OF_STATS_REPLY_MINLEN              (12U - OF_HEADER_FIXLEN)
548*ee67461eSJoseph Mingrone #define OF_VENDOR_MINLEN                   (12U - OF_HEADER_FIXLEN)
549*ee67461eSJoseph Mingrone #define OF_QUEUE_GET_CONFIG_REQUEST_FIXLEN (12U - OF_HEADER_FIXLEN)
550*ee67461eSJoseph Mingrone #define OF_QUEUE_GET_CONFIG_REPLY_MINLEN   (16U - OF_HEADER_FIXLEN)
551*ee67461eSJoseph Mingrone 
5523c602fabSXin LI /* lengths (fixed or minimal) of particular protocol structures */
553*ee67461eSJoseph Mingrone #define OF_PHY_PORT_FIXLEN                    48
554*ee67461eSJoseph Mingrone #define OF_ACTION_MINLEN                       8
555*ee67461eSJoseph Mingrone #define OF_MATCH_FIXLEN                       40
556*ee67461eSJoseph Mingrone #define OF_DESC_STATS_REPLY_FIXLEN          1056
557*ee67461eSJoseph Mingrone #define OF_FLOW_STATS_REQUEST_FIXLEN          44
558*ee67461eSJoseph Mingrone #define OF_FLOW_STATS_REPLY_MINLEN            88
559*ee67461eSJoseph Mingrone #define OF_AGGREGATE_STATS_REPLY_FIXLEN       24
560*ee67461eSJoseph Mingrone #define OF_TABLE_STATS_REPLY_FIXLEN           64
561*ee67461eSJoseph Mingrone #define OF_PORT_STATS_REQUEST_FIXLEN           8
562*ee67461eSJoseph Mingrone #define OF_PORT_STATS_REPLY_FIXLEN           104
563*ee67461eSJoseph Mingrone #define OF_QUEUE_PROP_MINLEN                   8
564*ee67461eSJoseph Mingrone #define OF_QUEUE_PROP_MIN_RATE_FIXLEN         16
565*ee67461eSJoseph Mingrone #define OF_PACKET_QUEUE_MINLEN                 8
566*ee67461eSJoseph Mingrone #define OF_QUEUE_STATS_REQUEST_FIXLEN          8
567*ee67461eSJoseph Mingrone #define OF_QUEUE_STATS_REPLY_FIXLEN           32
5683c602fabSXin LI 
5693c602fabSXin LI /* miscellaneous constants from [OF10] */
5703c602fabSXin LI #define OFP_MAX_TABLE_NAME_LEN     32
5713c602fabSXin LI #define OFP_MAX_PORT_NAME_LEN      16
5723c602fabSXin LI #define DESC_STR_LEN              256
5733c602fabSXin LI #define SERIAL_NUM_LEN             32
574*ee67461eSJoseph Mingrone #define OFP_VLAN_NONE          0xffffU
5753c602fabSXin LI 
5768bdc5a62SPatrick Kelsey /* vendor extensions */
5778bdc5a62SPatrick Kelsey #define BSN_SET_IP_MASK                    0
5788bdc5a62SPatrick Kelsey #define BSN_GET_IP_MASK_REQUEST            1
5798bdc5a62SPatrick Kelsey #define BSN_GET_IP_MASK_REPLY              2
5808bdc5a62SPatrick Kelsey #define BSN_SET_MIRRORING                  3
5818bdc5a62SPatrick Kelsey #define BSN_GET_MIRRORING_REQUEST          4
5828bdc5a62SPatrick Kelsey #define BSN_GET_MIRRORING_REPLY            5
5838bdc5a62SPatrick Kelsey #define BSN_SHELL_COMMAND                  6
5848bdc5a62SPatrick Kelsey #define BSN_SHELL_OUTPUT                   7
5858bdc5a62SPatrick Kelsey #define BSN_SHELL_STATUS                   8
5868bdc5a62SPatrick Kelsey #define BSN_GET_INTERFACES_REQUEST         9
5878bdc5a62SPatrick Kelsey #define BSN_GET_INTERFACES_REPLY          10
5888bdc5a62SPatrick Kelsey #define BSN_SET_PKTIN_SUPPRESSION_REQUEST 11
5898bdc5a62SPatrick Kelsey #define BSN_SET_L2_TABLE_REQUEST          12
5908bdc5a62SPatrick Kelsey #define BSN_GET_L2_TABLE_REQUEST          13
5918bdc5a62SPatrick Kelsey #define BSN_GET_L2_TABLE_REPLY            14
5928bdc5a62SPatrick Kelsey #define BSN_VIRTUAL_PORT_CREATE_REQUEST   15
5938bdc5a62SPatrick Kelsey #define BSN_VIRTUAL_PORT_CREATE_REPLY     16
5948bdc5a62SPatrick Kelsey #define BSN_VIRTUAL_PORT_REMOVE_REQUEST   17
5958bdc5a62SPatrick Kelsey #define BSN_BW_ENABLE_SET_REQUEST         18
5968bdc5a62SPatrick Kelsey #define BSN_BW_ENABLE_GET_REQUEST         19
5978bdc5a62SPatrick Kelsey #define BSN_BW_ENABLE_GET_REPLY           20
5988bdc5a62SPatrick Kelsey #define BSN_BW_CLEAR_DATA_REQUEST         21
5998bdc5a62SPatrick Kelsey #define BSN_BW_CLEAR_DATA_REPLY           22
6008bdc5a62SPatrick Kelsey #define BSN_BW_ENABLE_SET_REPLY           23
6018bdc5a62SPatrick Kelsey #define BSN_SET_L2_TABLE_REPLY            24
6028bdc5a62SPatrick Kelsey #define BSN_SET_PKTIN_SUPPRESSION_REPLY   25
6038bdc5a62SPatrick Kelsey #define BSN_VIRTUAL_PORT_REMOVE_REPLY     26
6048bdc5a62SPatrick Kelsey #define BSN_HYBRID_GET_REQUEST            27
6058bdc5a62SPatrick Kelsey #define BSN_HYBRID_GET_REPLY              28
6068bdc5a62SPatrick Kelsey                                        /* 29 */
6078bdc5a62SPatrick Kelsey                                        /* 30 */
6088bdc5a62SPatrick Kelsey #define BSN_PDU_TX_REQUEST                31
6098bdc5a62SPatrick Kelsey #define BSN_PDU_TX_REPLY                  32
6108bdc5a62SPatrick Kelsey #define BSN_PDU_RX_REQUEST                33
6118bdc5a62SPatrick Kelsey #define BSN_PDU_RX_REPLY                  34
6128bdc5a62SPatrick Kelsey #define BSN_PDU_RX_TIMEOUT                35
6138bdc5a62SPatrick Kelsey 
6148bdc5a62SPatrick Kelsey static const struct tok bsn_subtype_str[] = {
6158bdc5a62SPatrick Kelsey 	{ BSN_SET_IP_MASK,                   "SET_IP_MASK"                   },
6168bdc5a62SPatrick Kelsey 	{ BSN_GET_IP_MASK_REQUEST,           "GET_IP_MASK_REQUEST"           },
6178bdc5a62SPatrick Kelsey 	{ BSN_GET_IP_MASK_REPLY,             "GET_IP_MASK_REPLY"             },
6188bdc5a62SPatrick Kelsey 	{ BSN_SET_MIRRORING,                 "SET_MIRRORING"                 },
6198bdc5a62SPatrick Kelsey 	{ BSN_GET_MIRRORING_REQUEST,         "GET_MIRRORING_REQUEST"         },
6208bdc5a62SPatrick Kelsey 	{ BSN_GET_MIRRORING_REPLY,           "GET_MIRRORING_REPLY"           },
6218bdc5a62SPatrick Kelsey 	{ BSN_SHELL_COMMAND,                 "SHELL_COMMAND"                 },
6228bdc5a62SPatrick Kelsey 	{ BSN_SHELL_OUTPUT,                  "SHELL_OUTPUT"                  },
6238bdc5a62SPatrick Kelsey 	{ BSN_SHELL_STATUS,                  "SHELL_STATUS"                  },
6248bdc5a62SPatrick Kelsey 	{ BSN_GET_INTERFACES_REQUEST,        "GET_INTERFACES_REQUEST"        },
6258bdc5a62SPatrick Kelsey 	{ BSN_GET_INTERFACES_REPLY,          "GET_INTERFACES_REPLY"          },
6268bdc5a62SPatrick Kelsey 	{ BSN_SET_PKTIN_SUPPRESSION_REQUEST, "SET_PKTIN_SUPPRESSION_REQUEST" },
6278bdc5a62SPatrick Kelsey 	{ BSN_SET_L2_TABLE_REQUEST,          "SET_L2_TABLE_REQUEST"          },
6288bdc5a62SPatrick Kelsey 	{ BSN_GET_L2_TABLE_REQUEST,          "GET_L2_TABLE_REQUEST"          },
6298bdc5a62SPatrick Kelsey 	{ BSN_GET_L2_TABLE_REPLY,            "GET_L2_TABLE_REPLY"            },
6308bdc5a62SPatrick Kelsey 	{ BSN_VIRTUAL_PORT_CREATE_REQUEST,   "VIRTUAL_PORT_CREATE_REQUEST"   },
6318bdc5a62SPatrick Kelsey 	{ BSN_VIRTUAL_PORT_CREATE_REPLY,     "VIRTUAL_PORT_CREATE_REPLY"     },
6328bdc5a62SPatrick Kelsey 	{ BSN_VIRTUAL_PORT_REMOVE_REQUEST,   "VIRTUAL_PORT_REMOVE_REQUEST"   },
6338bdc5a62SPatrick Kelsey 	{ BSN_BW_ENABLE_SET_REQUEST,         "BW_ENABLE_SET_REQUEST"         },
6348bdc5a62SPatrick Kelsey 	{ BSN_BW_ENABLE_GET_REQUEST,         "BW_ENABLE_GET_REQUEST"         },
6358bdc5a62SPatrick Kelsey 	{ BSN_BW_ENABLE_GET_REPLY,           "BW_ENABLE_GET_REPLY"           },
6368bdc5a62SPatrick Kelsey 	{ BSN_BW_CLEAR_DATA_REQUEST,         "BW_CLEAR_DATA_REQUEST"         },
6378bdc5a62SPatrick Kelsey 	{ BSN_BW_CLEAR_DATA_REPLY,           "BW_CLEAR_DATA_REPLY"           },
6388bdc5a62SPatrick Kelsey 	{ BSN_BW_ENABLE_SET_REPLY,           "BW_ENABLE_SET_REPLY"           },
6398bdc5a62SPatrick Kelsey 	{ BSN_SET_L2_TABLE_REPLY,            "SET_L2_TABLE_REPLY"            },
6408bdc5a62SPatrick Kelsey 	{ BSN_SET_PKTIN_SUPPRESSION_REPLY,   "SET_PKTIN_SUPPRESSION_REPLY"   },
6418bdc5a62SPatrick Kelsey 	{ BSN_VIRTUAL_PORT_REMOVE_REPLY,     "VIRTUAL_PORT_REMOVE_REPLY"     },
6428bdc5a62SPatrick Kelsey 	{ BSN_HYBRID_GET_REQUEST,            "HYBRID_GET_REQUEST"            },
6438bdc5a62SPatrick Kelsey 	{ BSN_HYBRID_GET_REPLY,              "HYBRID_GET_REPLY"              },
6448bdc5a62SPatrick Kelsey 	{ BSN_PDU_TX_REQUEST,                "PDU_TX_REQUEST"                },
6458bdc5a62SPatrick Kelsey 	{ BSN_PDU_TX_REPLY,                  "PDU_TX_REPLY"                  },
6468bdc5a62SPatrick Kelsey 	{ BSN_PDU_RX_REQUEST,                "PDU_RX_REQUEST"                },
6478bdc5a62SPatrick Kelsey 	{ BSN_PDU_RX_REPLY,                  "PDU_RX_REPLY"                  },
6488bdc5a62SPatrick Kelsey 	{ BSN_PDU_RX_TIMEOUT,                "PDU_RX_TIMEOUT"                },
6498bdc5a62SPatrick Kelsey 	{ 0, NULL }
6508bdc5a62SPatrick Kelsey };
6518bdc5a62SPatrick Kelsey 
6528bdc5a62SPatrick Kelsey #define BSN_ACTION_MIRROR                  1
6538bdc5a62SPatrick Kelsey #define BSN_ACTION_SET_TUNNEL_DST          2
6548bdc5a62SPatrick Kelsey                                         /* 3 */
6558bdc5a62SPatrick Kelsey #define BSN_ACTION_CHECKSUM                4
6568bdc5a62SPatrick Kelsey 
6578bdc5a62SPatrick Kelsey static const struct tok bsn_action_subtype_str[] = {
6588bdc5a62SPatrick Kelsey 	{ BSN_ACTION_MIRROR,                 "MIRROR"                        },
6598bdc5a62SPatrick Kelsey 	{ BSN_ACTION_SET_TUNNEL_DST,         "SET_TUNNEL_DST"                },
6608bdc5a62SPatrick Kelsey 	{ BSN_ACTION_CHECKSUM,               "CHECKSUM"                      },
6618bdc5a62SPatrick Kelsey 	{ 0, NULL }
6628bdc5a62SPatrick Kelsey };
6638bdc5a62SPatrick Kelsey 
6648bdc5a62SPatrick Kelsey static const struct tok bsn_mirror_copy_stage_str[] = {
6658bdc5a62SPatrick Kelsey 	{ 0, "INGRESS" },
6668bdc5a62SPatrick Kelsey 	{ 1, "EGRESS"  },
6678bdc5a62SPatrick Kelsey 	{ 0, NULL },
6688bdc5a62SPatrick Kelsey };
6698bdc5a62SPatrick Kelsey 
6708bdc5a62SPatrick Kelsey static const struct tok bsn_onoff_str[] = {
6718bdc5a62SPatrick Kelsey 	{ 0, "OFF" },
6728bdc5a62SPatrick Kelsey 	{ 1, "ON"  },
6738bdc5a62SPatrick Kelsey 	{ 0, NULL },
6748bdc5a62SPatrick Kelsey };
6758bdc5a62SPatrick Kelsey 
6763c602fabSXin LI static const char *
6778bdc5a62SPatrick Kelsey vlan_str(const uint16_t vid)
6788bdc5a62SPatrick Kelsey {
6793c602fabSXin LI 	static char buf[sizeof("65535 (bogus)")];
6803c602fabSXin LI 
6813c602fabSXin LI 	if (vid == OFP_VLAN_NONE)
6823c602fabSXin LI 		return "NONE";
683*ee67461eSJoseph Mingrone 	snprintf(buf, sizeof(buf), "%u%s", vid,
684*ee67461eSJoseph Mingrone 	         (vid > 0 && vid < 0x0fff) ? "" : " (bogus)");
6853c602fabSXin LI 	return buf;
6863c602fabSXin LI }
6873c602fabSXin LI 
6883c602fabSXin LI static const char *
6898bdc5a62SPatrick Kelsey pcp_str(const uint8_t pcp)
6908bdc5a62SPatrick Kelsey {
6913c602fabSXin LI 	static char buf[sizeof("255 (bogus)")];
692*ee67461eSJoseph Mingrone 	snprintf(buf, sizeof(buf), "%u%s", pcp,
693*ee67461eSJoseph Mingrone 	         pcp <= 7 ? "" : " (bogus)");
6943c602fabSXin LI 	return buf;
6953c602fabSXin LI }
6963c602fabSXin LI 
6973c602fabSXin LI static void
6988bdc5a62SPatrick Kelsey of10_bsn_message_print(netdissect_options *ndo,
699*ee67461eSJoseph Mingrone                        const u_char *cp, u_int len)
7008bdc5a62SPatrick Kelsey {
7018bdc5a62SPatrick Kelsey 	uint32_t subtype;
7028bdc5a62SPatrick Kelsey 
7038bdc5a62SPatrick Kelsey 	if (len < 4)
7043340d773SGleb Smirnoff 		goto invalid;
7058bdc5a62SPatrick Kelsey 	/* subtype */
706*ee67461eSJoseph Mingrone 	subtype = GET_BE_U_4(cp);
707*ee67461eSJoseph Mingrone 	OF_FWD(4);
708*ee67461eSJoseph Mingrone 	ND_PRINT("\n\t subtype %s", tok2str(bsn_subtype_str, "unknown (0x%08x)", subtype));
7098bdc5a62SPatrick Kelsey 	switch (subtype) {
7108bdc5a62SPatrick Kelsey 	case BSN_GET_IP_MASK_REQUEST:
7118bdc5a62SPatrick Kelsey 		/*
7128bdc5a62SPatrick Kelsey 		 *  0                   1                   2                   3
7138bdc5a62SPatrick 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
7148bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
7158bdc5a62SPatrick Kelsey 		 * |                            subtype                            |
7168bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
7178bdc5a62SPatrick Kelsey 		 * |     index     |                      pad                      |
7188bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
7198bdc5a62SPatrick Kelsey 		 * |                              pad                              |
7208bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
7218bdc5a62SPatrick Kelsey 		 *
7228bdc5a62SPatrick Kelsey 		 */
723*ee67461eSJoseph Mingrone 		if (len != 8)
7243340d773SGleb Smirnoff 			goto invalid;
7258bdc5a62SPatrick Kelsey 		/* index */
726*ee67461eSJoseph Mingrone 		ND_PRINT(", index %u", GET_U_1(cp));
727*ee67461eSJoseph Mingrone 		OF_FWD(1);
7288bdc5a62SPatrick Kelsey 		/* pad */
729*ee67461eSJoseph Mingrone 		/* Always the last field, check bounds. */
730*ee67461eSJoseph Mingrone 		ND_TCHECK_7(cp);
7318bdc5a62SPatrick Kelsey 		break;
7328bdc5a62SPatrick Kelsey 	case BSN_SET_IP_MASK:
7338bdc5a62SPatrick Kelsey 	case BSN_GET_IP_MASK_REPLY:
7348bdc5a62SPatrick Kelsey 		/*
7358bdc5a62SPatrick Kelsey 		 *  0                   1                   2                   3
7368bdc5a62SPatrick 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
7378bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
7388bdc5a62SPatrick Kelsey 		 * |                            subtype                            |
7398bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
7408bdc5a62SPatrick Kelsey 		 * |     index     |                      pad                      |
7418bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
7428bdc5a62SPatrick Kelsey 		 * |                              mask                             |
7438bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
7448bdc5a62SPatrick Kelsey 		 *
7458bdc5a62SPatrick Kelsey 		 */
746*ee67461eSJoseph Mingrone 		if (len != 8)
7473340d773SGleb Smirnoff 			goto invalid;
7488bdc5a62SPatrick Kelsey 		/* index */
749*ee67461eSJoseph Mingrone 		ND_PRINT(", index %u", GET_U_1(cp));
750*ee67461eSJoseph Mingrone 		OF_FWD(1);
7518bdc5a62SPatrick Kelsey 		/* pad */
752*ee67461eSJoseph Mingrone 		OF_FWD(3);
7538bdc5a62SPatrick Kelsey 		/* mask */
754*ee67461eSJoseph Mingrone 		ND_PRINT(", mask %s", GET_IPADDR_STRING(cp));
7558bdc5a62SPatrick Kelsey 		break;
7568bdc5a62SPatrick Kelsey 	case BSN_SET_MIRRORING:
7578bdc5a62SPatrick Kelsey 	case BSN_GET_MIRRORING_REQUEST:
7588bdc5a62SPatrick Kelsey 	case BSN_GET_MIRRORING_REPLY:
7598bdc5a62SPatrick Kelsey 		/*
7608bdc5a62SPatrick Kelsey 		 *  0                   1                   2                   3
7618bdc5a62SPatrick 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
7628bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
7638bdc5a62SPatrick Kelsey 		 * |                            subtype                            |
7648bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
7658bdc5a62SPatrick Kelsey 		 * | report m. p.  |                      pad                      |
7668bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
7678bdc5a62SPatrick Kelsey 		 *
7688bdc5a62SPatrick Kelsey 		 */
769*ee67461eSJoseph Mingrone 		if (len != 4)
7703340d773SGleb Smirnoff 			goto invalid;
7718bdc5a62SPatrick Kelsey 		/* report_mirror_ports */
772*ee67461eSJoseph Mingrone 		ND_PRINT(", report_mirror_ports %s",
773*ee67461eSJoseph Mingrone 			 tok2str(bsn_onoff_str, "bogus (%u)", GET_U_1(cp)));
774*ee67461eSJoseph Mingrone 		OF_FWD(1);
7758bdc5a62SPatrick Kelsey 		/* pad */
776*ee67461eSJoseph Mingrone 		/* Always the last field, check bounds. */
777*ee67461eSJoseph Mingrone 		ND_TCHECK_3(cp);
7788bdc5a62SPatrick Kelsey 		break;
7798bdc5a62SPatrick Kelsey 	case BSN_GET_INTERFACES_REQUEST:
7808bdc5a62SPatrick Kelsey 	case BSN_GET_L2_TABLE_REQUEST:
7818bdc5a62SPatrick Kelsey 	case BSN_BW_ENABLE_GET_REQUEST:
7828bdc5a62SPatrick Kelsey 	case BSN_BW_CLEAR_DATA_REQUEST:
7838bdc5a62SPatrick Kelsey 	case BSN_HYBRID_GET_REQUEST:
7848bdc5a62SPatrick Kelsey 		/*
7858bdc5a62SPatrick Kelsey 		 *  0                   1                   2                   3
7868bdc5a62SPatrick 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
7878bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
7888bdc5a62SPatrick Kelsey 		 * |                            subtype                            |
7898bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
7908bdc5a62SPatrick Kelsey 		 *
7918bdc5a62SPatrick Kelsey 		 */
792*ee67461eSJoseph Mingrone 		if (len)
7933340d773SGleb Smirnoff 			goto invalid;
7948bdc5a62SPatrick Kelsey 		break;
7958bdc5a62SPatrick Kelsey 	case BSN_VIRTUAL_PORT_REMOVE_REQUEST:
7968bdc5a62SPatrick Kelsey 		/*
7978bdc5a62SPatrick Kelsey 		 *  0                   1                   2                   3
7988bdc5a62SPatrick 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
7998bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
8008bdc5a62SPatrick Kelsey 		 * |                            subtype                            |
8018bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
8028bdc5a62SPatrick Kelsey 		 * |                           vport_no                            |
8038bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
8048bdc5a62SPatrick Kelsey 		 *
8058bdc5a62SPatrick Kelsey 		 */
806*ee67461eSJoseph Mingrone 		if (len != 4)
8073340d773SGleb Smirnoff 			goto invalid;
8088bdc5a62SPatrick Kelsey 		/* vport_no */
809*ee67461eSJoseph Mingrone 		ND_PRINT(", vport_no %u", GET_BE_U_4(cp));
8108bdc5a62SPatrick Kelsey 		break;
8118bdc5a62SPatrick Kelsey 	case BSN_SHELL_COMMAND:
8128bdc5a62SPatrick Kelsey 		/*
8138bdc5a62SPatrick Kelsey 		 *  0                   1                   2                   3
8148bdc5a62SPatrick 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
8158bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
8168bdc5a62SPatrick Kelsey 		 * |                            subtype                            |
8178bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
8188bdc5a62SPatrick Kelsey 		 * |                            service                            |
8198bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
8208bdc5a62SPatrick Kelsey 		 * |                             data ...
8218bdc5a62SPatrick Kelsey 		 * +---------------+---------------+--------
8228bdc5a62SPatrick Kelsey 		 *
8238bdc5a62SPatrick Kelsey 		 */
824*ee67461eSJoseph Mingrone 		if (len < 4)
8253340d773SGleb Smirnoff 			goto invalid;
8268bdc5a62SPatrick Kelsey 		/* service */
827*ee67461eSJoseph Mingrone 		ND_PRINT(", service %u", GET_BE_U_4(cp));
828*ee67461eSJoseph Mingrone 		OF_FWD(4);
8298bdc5a62SPatrick Kelsey 		/* data */
830*ee67461eSJoseph Mingrone 		ND_PRINT(", data '");
831*ee67461eSJoseph Mingrone 		(void)nd_printn(ndo, cp, len, NULL);
832*ee67461eSJoseph Mingrone 		ND_PRINT("'");
8338bdc5a62SPatrick Kelsey 		break;
8348bdc5a62SPatrick Kelsey 	case BSN_SHELL_OUTPUT:
8358bdc5a62SPatrick Kelsey 		/*
8368bdc5a62SPatrick Kelsey 		 *  0                   1                   2                   3
8378bdc5a62SPatrick 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
8388bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
8398bdc5a62SPatrick Kelsey 		 * |                            subtype                            |
8408bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
8418bdc5a62SPatrick Kelsey 		 * |                             data ...
8428bdc5a62SPatrick Kelsey 		 * +---------------+---------------+--------
8438bdc5a62SPatrick Kelsey 		 *
8448bdc5a62SPatrick Kelsey 		 */
8458bdc5a62SPatrick Kelsey 		/* already checked that len >= 4 */
8468bdc5a62SPatrick Kelsey 		/* data */
847*ee67461eSJoseph Mingrone 		ND_PRINT(", data '");
848*ee67461eSJoseph Mingrone 		(void)nd_printn(ndo, cp, len, NULL);
849*ee67461eSJoseph Mingrone 		ND_PRINT("'");
8508bdc5a62SPatrick Kelsey 		break;
8518bdc5a62SPatrick Kelsey 	case BSN_SHELL_STATUS:
8528bdc5a62SPatrick Kelsey 		/*
8538bdc5a62SPatrick Kelsey 		 *  0                   1                   2                   3
8548bdc5a62SPatrick 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
8558bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
8568bdc5a62SPatrick Kelsey 		 * |                            subtype                            |
8578bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
8588bdc5a62SPatrick Kelsey 		 * |                            status                             |
8598bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
8608bdc5a62SPatrick Kelsey 		 *
8618bdc5a62SPatrick Kelsey 		 */
862*ee67461eSJoseph Mingrone 		if (len != 4)
8633340d773SGleb Smirnoff 			goto invalid;
8648bdc5a62SPatrick Kelsey 		/* status */
865*ee67461eSJoseph Mingrone 		ND_PRINT(", status 0x%08x", GET_BE_U_4(cp));
8668bdc5a62SPatrick Kelsey 		break;
8678bdc5a62SPatrick Kelsey 	default:
868*ee67461eSJoseph Mingrone 		ND_TCHECK_LEN(cp, len);
8698bdc5a62SPatrick Kelsey 	}
870*ee67461eSJoseph Mingrone 	return;
8718bdc5a62SPatrick Kelsey 
8723340d773SGleb Smirnoff invalid: /* skip the undersized data */
873*ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
874*ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
8758bdc5a62SPatrick Kelsey }
8768bdc5a62SPatrick Kelsey 
877*ee67461eSJoseph Mingrone static void
8788bdc5a62SPatrick Kelsey of10_bsn_actions_print(netdissect_options *ndo,
879*ee67461eSJoseph Mingrone                        const u_char *cp, u_int len)
8808bdc5a62SPatrick Kelsey {
8818bdc5a62SPatrick Kelsey 	uint32_t subtype, vlan_tag;
8828bdc5a62SPatrick Kelsey 
8838bdc5a62SPatrick Kelsey 	if (len < 4)
8843340d773SGleb Smirnoff 		goto invalid;
8858bdc5a62SPatrick Kelsey 	/* subtype */
886*ee67461eSJoseph Mingrone 	subtype = GET_BE_U_4(cp);
887*ee67461eSJoseph Mingrone 	OF_FWD(4);
888*ee67461eSJoseph Mingrone 	ND_PRINT("\n\t  subtype %s", tok2str(bsn_action_subtype_str, "unknown (0x%08x)", subtype));
8898bdc5a62SPatrick Kelsey 	switch (subtype) {
8908bdc5a62SPatrick Kelsey 	case BSN_ACTION_MIRROR:
8918bdc5a62SPatrick Kelsey 		/*
8928bdc5a62SPatrick Kelsey 		 *  0                   1                   2                   3
8938bdc5a62SPatrick 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
8948bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
8958bdc5a62SPatrick Kelsey 		 * |                            subtype                            |
8968bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
8978bdc5a62SPatrick Kelsey 		 * |                           dest_port                           |
8988bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
8998bdc5a62SPatrick Kelsey 		 * |                           vlan_tag                            |
9008bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
9018bdc5a62SPatrick Kelsey 		 * |  copy_stage   |                      pad                      |
9028bdc5a62SPatrick Kelsey 		 * +---------------+---------------+---------------+---------------+
9038bdc5a62SPatrick Kelsey 		 *
9048bdc5a62SPatrick Kelsey 		 */
905*ee67461eSJoseph Mingrone 		if (len != 12)
9063340d773SGleb Smirnoff 			goto invalid;
9078bdc5a62SPatrick Kelsey 		/* dest_port */
908*ee67461eSJoseph Mingrone 		ND_PRINT(", dest_port %u", GET_BE_U_4(cp));
909*ee67461eSJoseph Mingrone 		OF_FWD(4);
9108bdc5a62SPatrick Kelsey 		/* vlan_tag */
911*ee67461eSJoseph Mingrone 		vlan_tag = GET_BE_U_4(cp);
912*ee67461eSJoseph Mingrone 		OF_FWD(4);
9138bdc5a62SPatrick Kelsey 		switch (vlan_tag >> 16) {
9148bdc5a62SPatrick Kelsey 		case 0:
915*ee67461eSJoseph Mingrone 			ND_PRINT(", vlan_tag none");
9168bdc5a62SPatrick Kelsey 			break;
9178bdc5a62SPatrick Kelsey 		case ETHERTYPE_8021Q:
918*ee67461eSJoseph Mingrone 			ND_PRINT(", vlan_tag 802.1Q (%s)", ieee8021q_tci_string(vlan_tag & 0xffff));
9198bdc5a62SPatrick Kelsey 			break;
9208bdc5a62SPatrick Kelsey 		default:
921*ee67461eSJoseph Mingrone 			ND_PRINT(", vlan_tag unknown (0x%04x)", vlan_tag >> 16);
9228bdc5a62SPatrick Kelsey 		}
9238bdc5a62SPatrick Kelsey 		/* copy_stage */
924*ee67461eSJoseph Mingrone 		ND_PRINT(", copy_stage %s",
925*ee67461eSJoseph Mingrone 			 tok2str(bsn_mirror_copy_stage_str, "unknown (%u)", GET_U_1(cp)));
926*ee67461eSJoseph Mingrone 		OF_FWD(1);
9278bdc5a62SPatrick Kelsey 		/* pad */
928*ee67461eSJoseph Mingrone 		/* Always the last field, check bounds. */
929*ee67461eSJoseph Mingrone 		ND_TCHECK_3(cp);
9308bdc5a62SPatrick Kelsey 		break;
9318bdc5a62SPatrick Kelsey 	default:
932*ee67461eSJoseph Mingrone 		ND_TCHECK_LEN(cp, len);
9338bdc5a62SPatrick Kelsey 	}
934*ee67461eSJoseph Mingrone 	return;
9358bdc5a62SPatrick Kelsey 
9363340d773SGleb Smirnoff invalid:
937*ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
938*ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
9398bdc5a62SPatrick Kelsey }
9408bdc5a62SPatrick Kelsey 
941*ee67461eSJoseph Mingrone static void
9428bdc5a62SPatrick Kelsey of10_vendor_action_print(netdissect_options *ndo,
943*ee67461eSJoseph Mingrone                          const u_char *cp, u_int len)
9448bdc5a62SPatrick Kelsey {
9458bdc5a62SPatrick Kelsey 	uint32_t vendor;
946*ee67461eSJoseph Mingrone 	void (*decoder)(netdissect_options *, const u_char *, u_int);
9478bdc5a62SPatrick Kelsey 
9483c602fabSXin LI 	if (len < 4)
9493340d773SGleb Smirnoff 		goto invalid;
9503c602fabSXin LI 	/* vendor */
951*ee67461eSJoseph Mingrone 	vendor = GET_BE_U_4(cp);
952*ee67461eSJoseph Mingrone 	OF_FWD(4);
953*ee67461eSJoseph Mingrone 	ND_PRINT(", vendor 0x%08x (%s)", vendor, of_vendor_name(vendor));
9548bdc5a62SPatrick Kelsey 	/* data */
9558bdc5a62SPatrick Kelsey 	decoder =
9568bdc5a62SPatrick Kelsey 		vendor == OUI_BSN         ? of10_bsn_actions_print         :
957*ee67461eSJoseph Mingrone 		of_data_print;
958*ee67461eSJoseph Mingrone 	decoder(ndo, cp, len);
959*ee67461eSJoseph Mingrone 	return;
9608bdc5a62SPatrick Kelsey 
9613340d773SGleb Smirnoff invalid: /* skip the undersized data */
962*ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
963*ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
9648bdc5a62SPatrick Kelsey }
9658bdc5a62SPatrick Kelsey 
966*ee67461eSJoseph Mingrone /* [OF10] Section 5.5.4 */
967*ee67461eSJoseph Mingrone static void
9688bdc5a62SPatrick Kelsey of10_vendor_message_print(netdissect_options *ndo,
969*ee67461eSJoseph Mingrone                           const u_char *cp, u_int len)
9708bdc5a62SPatrick Kelsey {
9718bdc5a62SPatrick Kelsey 	uint32_t vendor;
972*ee67461eSJoseph Mingrone 	void (*decoder)(netdissect_options *, const u_char *, u_int);
9738bdc5a62SPatrick Kelsey 
9748bdc5a62SPatrick Kelsey 	/* vendor */
975*ee67461eSJoseph Mingrone 	vendor = GET_BE_U_4(cp);
976*ee67461eSJoseph Mingrone 	OF_FWD(4);
977*ee67461eSJoseph Mingrone 	ND_PRINT(", vendor 0x%08x (%s)", vendor, of_vendor_name(vendor));
9788bdc5a62SPatrick Kelsey 	/* data */
9798bdc5a62SPatrick Kelsey 	decoder =
9808bdc5a62SPatrick Kelsey 		vendor == OUI_BSN         ? of10_bsn_message_print         :
981*ee67461eSJoseph Mingrone 		of_data_print;
982*ee67461eSJoseph Mingrone 	decoder(ndo, cp, len);
9838bdc5a62SPatrick Kelsey }
9848bdc5a62SPatrick Kelsey 
9858bdc5a62SPatrick Kelsey /* Vendor ID is mandatory, data is optional. */
986*ee67461eSJoseph Mingrone static void
9878bdc5a62SPatrick Kelsey of10_vendor_data_print(netdissect_options *ndo,
988*ee67461eSJoseph Mingrone                        const u_char *cp, u_int len)
9898bdc5a62SPatrick Kelsey {
9908bdc5a62SPatrick Kelsey 	uint32_t vendor;
9918bdc5a62SPatrick Kelsey 
9928bdc5a62SPatrick Kelsey 	if (len < 4)
9933340d773SGleb Smirnoff 		goto invalid;
9948bdc5a62SPatrick Kelsey 	/* vendor */
995*ee67461eSJoseph Mingrone 	vendor = GET_BE_U_4(cp);
996*ee67461eSJoseph Mingrone 	OF_FWD(4);
997*ee67461eSJoseph Mingrone 	ND_PRINT(", vendor 0x%08x (%s)", vendor, of_vendor_name(vendor));
9983c602fabSXin LI 	/* data */
999*ee67461eSJoseph Mingrone 	of_data_print(ndo, cp, len);
1000*ee67461eSJoseph Mingrone 	return;
10013c602fabSXin LI 
10023340d773SGleb Smirnoff invalid: /* skip the undersized data */
1003*ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
1004*ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
10053c602fabSXin LI }
10063c602fabSXin LI 
1007*ee67461eSJoseph Mingrone static void
10083c602fabSXin LI of10_packet_data_print(netdissect_options *ndo,
1009*ee67461eSJoseph Mingrone                        const u_char *cp, const u_int len)
10108bdc5a62SPatrick Kelsey {
10113c602fabSXin LI 	if (len == 0)
1012*ee67461eSJoseph Mingrone 		return;
10133c602fabSXin LI 	/* data */
1014*ee67461eSJoseph Mingrone 	ND_PRINT("\n\t data (%u octets)", len);
1015*ee67461eSJoseph Mingrone 	if (ndo->ndo_vflag < 3) {
1016*ee67461eSJoseph Mingrone 		ND_TCHECK_LEN(cp, len);
1017*ee67461eSJoseph Mingrone 		return;
1018*ee67461eSJoseph Mingrone 	}
10193c602fabSXin LI 	ndo->ndo_vflag -= 3;
1020*ee67461eSJoseph Mingrone 	ND_PRINT(", frame decoding below\n");
1021*ee67461eSJoseph Mingrone 	/*
1022*ee67461eSJoseph Mingrone 	 * The encapsulated Ethernet frame is not necessarily the last
1023*ee67461eSJoseph Mingrone 	 * data of this packet (i.e. there may be more OpenFlow messages
1024*ee67461eSJoseph Mingrone 	 * after the current OFPT_PACKET_IN/OFPT_PACKET_OUT message, in
1025*ee67461eSJoseph Mingrone 	 * which case the current (outer) packet's snapshot end is not
1026*ee67461eSJoseph Mingrone 	 * what ether_print() needs to decode an Ethernet frame nested in
1027*ee67461eSJoseph Mingrone 	 * the middle of a TCP payload.
1028*ee67461eSJoseph Mingrone 	 */
1029*ee67461eSJoseph Mingrone 	const u_char *snapend_save = ndo->ndo_snapend;
1030*ee67461eSJoseph Mingrone 	ndo->ndo_snapend = ND_MIN(cp + len, ndo->ndo_snapend);
1031*ee67461eSJoseph Mingrone 	ether_print(ndo, cp, len, ND_BYTES_AVAILABLE_AFTER(cp), NULL, NULL);
1032*ee67461eSJoseph Mingrone 	ndo->ndo_snapend = snapend_save;
10333c602fabSXin LI 	ndo->ndo_vflag += 3;
10343c602fabSXin LI }
10353c602fabSXin LI 
10363c602fabSXin LI /* [OF10] Section 5.2.1 */
1037*ee67461eSJoseph Mingrone static void
1038*ee67461eSJoseph Mingrone of10_phy_port_print(netdissect_options *ndo,
1039*ee67461eSJoseph Mingrone                     const u_char *cp)
10408bdc5a62SPatrick Kelsey {
1041*ee67461eSJoseph Mingrone 	uint32_t state;
10423c602fabSXin LI 
10433c602fabSXin LI 	/* port_no */
1044*ee67461eSJoseph Mingrone 	ND_PRINT("\n\t  port_no %s",
1045*ee67461eSJoseph Mingrone 		 tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
10463c602fabSXin LI 	cp += 2;
10473c602fabSXin LI 	/* hw_addr */
1048*ee67461eSJoseph Mingrone 	ND_PRINT(", hw_addr %s", GET_ETHERADDR_STRING(cp));
1049*ee67461eSJoseph Mingrone 	cp += MAC_ADDR_LEN;
10503c602fabSXin LI 	/* name */
1051*ee67461eSJoseph Mingrone 	ND_PRINT(", name '");
1052*ee67461eSJoseph Mingrone 	nd_printjnp(ndo, cp, OFP_MAX_PORT_NAME_LEN);
1053*ee67461eSJoseph Mingrone 	ND_PRINT("'");
10543c602fabSXin LI 	cp += OFP_MAX_PORT_NAME_LEN;
10553c602fabSXin LI 
10563c602fabSXin LI 	if (ndo->ndo_vflag < 2) {
1057*ee67461eSJoseph Mingrone 		ND_TCHECK_LEN(cp, 24);
1058*ee67461eSJoseph Mingrone 		return;
10593c602fabSXin LI 	}
10603c602fabSXin LI 	/* config */
1061*ee67461eSJoseph Mingrone 	ND_PRINT("\n\t   config 0x%08x", GET_BE_U_4(cp));
1062*ee67461eSJoseph Mingrone 	of_bitmap_print(ndo, ofppc_bm, GET_BE_U_4(cp), OFPPC_U);
10633c602fabSXin LI 	cp += 4;
10643c602fabSXin LI 	/* state */
1065*ee67461eSJoseph Mingrone 	state = GET_BE_U_4(cp);
1066*ee67461eSJoseph Mingrone 	/*
1067*ee67461eSJoseph Mingrone 	 * Decode the code point and the single bit separately, but
1068*ee67461eSJoseph Mingrone 	 * format the result as a single sequence of comma-separated
1069*ee67461eSJoseph Mingrone 	 * strings (see the comments at the OFPPS_ props).
1070*ee67461eSJoseph Mingrone 	 */
1071*ee67461eSJoseph Mingrone 	ND_PRINT("\n\t   state 0x%08x (%s%s)%s", state,
1072*ee67461eSJoseph Mingrone 	         tok2str(ofpps_stp_str, "", state & OFPPS_STP_MASK),
1073*ee67461eSJoseph Mingrone 	         state & OFPPS_LINK_DOWN ? ", LINK_DOWN" : "",
1074*ee67461eSJoseph Mingrone 	         state & OFPPS_U ? " (bogus)" : "");
10753c602fabSXin LI 	cp += 4;
10763c602fabSXin LI 	/* curr */
1077*ee67461eSJoseph Mingrone 	ND_PRINT("\n\t   curr 0x%08x", GET_BE_U_4(cp));
1078*ee67461eSJoseph Mingrone 	of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U);
10793c602fabSXin LI 	cp += 4;
10803c602fabSXin LI 	/* advertised */
1081*ee67461eSJoseph Mingrone 	ND_PRINT("\n\t   advertised 0x%08x", GET_BE_U_4(cp));
1082*ee67461eSJoseph Mingrone 	of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U);
10833c602fabSXin LI 	cp += 4;
10843c602fabSXin LI 	/* supported */
1085*ee67461eSJoseph Mingrone 	ND_PRINT("\n\t   supported 0x%08x", GET_BE_U_4(cp));
1086*ee67461eSJoseph Mingrone 	of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U);
10873c602fabSXin LI 	cp += 4;
10883c602fabSXin LI 	/* peer */
1089*ee67461eSJoseph Mingrone 	ND_PRINT("\n\t   peer 0x%08x", GET_BE_U_4(cp));
1090*ee67461eSJoseph Mingrone 	of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U);
10913c602fabSXin LI }
10923c602fabSXin LI 
10933c602fabSXin LI /* [OF10] Section 5.2.2 */
1094*ee67461eSJoseph Mingrone static void
10953c602fabSXin LI of10_queue_props_print(netdissect_options *ndo,
1096*ee67461eSJoseph Mingrone                        const u_char *cp, u_int len)
10978bdc5a62SPatrick Kelsey {
10983c602fabSXin LI 	while (len) {
1099*ee67461eSJoseph Mingrone 		uint16_t property, plen;
11003c602fabSXin LI 		u_char plen_bogus = 0, skip = 0;
11013c602fabSXin LI 
1102*ee67461eSJoseph Mingrone 		if (len < OF_QUEUE_PROP_MINLEN)
11033340d773SGleb Smirnoff 			goto invalid;
11043c602fabSXin LI 		/* property */
1105*ee67461eSJoseph Mingrone 		property = GET_BE_U_2(cp);
1106*ee67461eSJoseph Mingrone 		OF_FWD(2);
1107*ee67461eSJoseph Mingrone 		ND_PRINT("\n\t   property %s", tok2str(ofpqt_str, "invalid (0x%04x)", property));
11083c602fabSXin LI 		/* len */
1109*ee67461eSJoseph Mingrone 		plen = GET_BE_U_2(cp);
1110*ee67461eSJoseph Mingrone 		OF_FWD(2);
1111*ee67461eSJoseph Mingrone 		ND_PRINT(", len %u", plen);
1112*ee67461eSJoseph Mingrone 		if (plen < OF_QUEUE_PROP_MINLEN || plen > len + 4)
11133340d773SGleb Smirnoff 			goto invalid;
11143c602fabSXin LI 		/* pad */
1115*ee67461eSJoseph Mingrone 		/* Sometimes the last field, check bounds. */
1116*ee67461eSJoseph Mingrone 		OF_CHK_FWD(4);
11173c602fabSXin LI 		/* property-specific constraints and decoding */
11183c602fabSXin LI 		switch (property) {
11193c602fabSXin LI 		case OFPQT_NONE:
1120*ee67461eSJoseph Mingrone 			plen_bogus = plen != OF_QUEUE_PROP_MINLEN;
11213c602fabSXin LI 			break;
11223c602fabSXin LI 		case OFPQT_MIN_RATE:
1123*ee67461eSJoseph Mingrone 			plen_bogus = plen != OF_QUEUE_PROP_MIN_RATE_FIXLEN;
11243c602fabSXin LI 			break;
11253c602fabSXin LI 		default:
11263c602fabSXin LI 			skip = 1;
11273c602fabSXin LI 		}
11283c602fabSXin LI 		if (plen_bogus) {
1129*ee67461eSJoseph Mingrone 			ND_PRINT(" (bogus)");
11303c602fabSXin LI 			skip = 1;
11313c602fabSXin LI 		}
11323c602fabSXin LI 		if (skip) {
1133*ee67461eSJoseph Mingrone 			/*
1134*ee67461eSJoseph Mingrone 			 * plen >= OF_QUEUE_PROP_MINLEN
1135*ee67461eSJoseph Mingrone 			 * cp is OF_QUEUE_PROP_MINLEN bytes in
1136*ee67461eSJoseph Mingrone 			 */
1137*ee67461eSJoseph Mingrone 			OF_CHK_FWD(plen - OF_QUEUE_PROP_MINLEN);
1138*ee67461eSJoseph Mingrone 			continue;
11393c602fabSXin LI 		}
11403c602fabSXin LI 		if (property == OFPQT_MIN_RATE) { /* the only case of property decoding */
11413c602fabSXin LI 			/* rate */
1142*ee67461eSJoseph Mingrone 			uint16_t rate = GET_BE_U_2(cp);
1143*ee67461eSJoseph Mingrone 			OF_FWD(2);
11443c602fabSXin LI 			if (rate > 1000)
1145*ee67461eSJoseph Mingrone 				ND_PRINT(", rate disabled");
11463c602fabSXin LI 			else
1147*ee67461eSJoseph Mingrone 				ND_PRINT(", rate %u.%u%%", rate / 10, rate % 10);
11483c602fabSXin LI 			/* pad */
1149*ee67461eSJoseph Mingrone 			/* Sometimes the last field, check bounds. */
1150*ee67461eSJoseph Mingrone 			OF_CHK_FWD(6);
11513c602fabSXin LI 		}
11523c602fabSXin LI 	} /* while */
1153*ee67461eSJoseph Mingrone 	return;
11543c602fabSXin LI 
11553340d773SGleb Smirnoff invalid: /* skip the rest of queue properties */
1156*ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
1157*ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
11583c602fabSXin LI }
11593c602fabSXin LI 
11603c602fabSXin LI /* ibid */
1161*ee67461eSJoseph Mingrone static void
11623c602fabSXin LI of10_queues_print(netdissect_options *ndo,
1163*ee67461eSJoseph Mingrone                   const u_char *cp, u_int len)
11648bdc5a62SPatrick Kelsey {
1165*ee67461eSJoseph Mingrone 	while (len) {
11663c602fabSXin LI 		uint16_t desclen;
11673c602fabSXin LI 
1168*ee67461eSJoseph Mingrone 		if (len < OF_PACKET_QUEUE_MINLEN)
11693340d773SGleb Smirnoff 			goto invalid;
11703c602fabSXin LI 		/* queue_id */
1171*ee67461eSJoseph Mingrone 		ND_PRINT("\n\t  queue_id %u", GET_BE_U_4(cp));
1172*ee67461eSJoseph Mingrone 		OF_FWD(4);
11733c602fabSXin LI 		/* len */
1174*ee67461eSJoseph Mingrone 		desclen = GET_BE_U_2(cp);
1175*ee67461eSJoseph Mingrone 		OF_FWD(2);
1176*ee67461eSJoseph Mingrone 		ND_PRINT(", len %u", desclen);
1177*ee67461eSJoseph Mingrone 		if (desclen < OF_PACKET_QUEUE_MINLEN || desclen > len + 6)
11783340d773SGleb Smirnoff 			goto invalid;
11793c602fabSXin LI 		/* pad */
1180*ee67461eSJoseph Mingrone 		/* Sometimes the last field, check bounds. */
1181*ee67461eSJoseph Mingrone 		OF_CHK_FWD(2);
11823c602fabSXin LI 		/* properties */
1183*ee67461eSJoseph Mingrone 		if (ndo->ndo_vflag >= 2)
1184*ee67461eSJoseph Mingrone 			of10_queue_props_print(ndo, cp, desclen - OF_PACKET_QUEUE_MINLEN);
1185*ee67461eSJoseph Mingrone 		else
1186*ee67461eSJoseph Mingrone 			ND_TCHECK_LEN(cp, desclen - OF_PACKET_QUEUE_MINLEN);
1187*ee67461eSJoseph Mingrone 		OF_FWD(desclen - OF_PACKET_QUEUE_MINLEN);
11883c602fabSXin LI 	} /* while */
1189*ee67461eSJoseph Mingrone 	return;
11903c602fabSXin LI 
11913340d773SGleb Smirnoff invalid: /* skip the rest of queues */
1192*ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
1193*ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
11943c602fabSXin LI }
11953c602fabSXin LI 
11963c602fabSXin LI /* [OF10] Section 5.2.3 */
1197*ee67461eSJoseph Mingrone static void
11983c602fabSXin LI of10_match_print(netdissect_options *ndo,
1199*ee67461eSJoseph Mingrone                  const char *pfx, const u_char *cp)
12008bdc5a62SPatrick Kelsey {
12013c602fabSXin LI 	uint32_t wildcards;
12023c602fabSXin LI 	uint16_t dl_type;
12033c602fabSXin LI 	uint8_t nw_proto;
1204*ee67461eSJoseph Mingrone 	u_int nw_bits;
12053c602fabSXin LI 	const char *field_name;
12063c602fabSXin LI 
12073c602fabSXin LI 	/* wildcards */
1208*ee67461eSJoseph Mingrone 	wildcards = GET_BE_U_4(cp);
12093c602fabSXin LI 	if (wildcards & OFPFW_U)
1210*ee67461eSJoseph Mingrone 		ND_PRINT("%swildcards 0x%08x (bogus)", pfx, wildcards);
12113c602fabSXin LI 	cp += 4;
12123c602fabSXin LI 	/* in_port */
12133c602fabSXin LI 	if (! (wildcards & OFPFW_IN_PORT))
1214*ee67461eSJoseph Mingrone 		ND_PRINT("%smatch in_port %s", pfx,
1215*ee67461eSJoseph Mingrone 		         tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
12163c602fabSXin LI 	cp += 2;
12173c602fabSXin LI 	/* dl_src */
12183c602fabSXin LI 	if (! (wildcards & OFPFW_DL_SRC))
1219*ee67461eSJoseph Mingrone 		ND_PRINT("%smatch dl_src %s", pfx, GET_ETHERADDR_STRING(cp));
1220*ee67461eSJoseph Mingrone 	cp += MAC_ADDR_LEN;
12213c602fabSXin LI 	/* dl_dst */
12223c602fabSXin LI 	if (! (wildcards & OFPFW_DL_DST))
1223*ee67461eSJoseph Mingrone 		ND_PRINT("%smatch dl_dst %s", pfx, GET_ETHERADDR_STRING(cp));
1224*ee67461eSJoseph Mingrone 	cp += MAC_ADDR_LEN;
12253c602fabSXin LI 	/* dl_vlan */
12263c602fabSXin LI 	if (! (wildcards & OFPFW_DL_VLAN))
1227*ee67461eSJoseph Mingrone 		ND_PRINT("%smatch dl_vlan %s", pfx, vlan_str(GET_BE_U_2(cp)));
12283c602fabSXin LI 	cp += 2;
12293c602fabSXin LI 	/* dl_vlan_pcp */
12303c602fabSXin LI 	if (! (wildcards & OFPFW_DL_VLAN_PCP))
1231*ee67461eSJoseph Mingrone 		ND_PRINT("%smatch dl_vlan_pcp %s", pfx, pcp_str(GET_U_1(cp)));
12323c602fabSXin LI 	cp += 1;
12333c602fabSXin LI 	/* pad1 */
12343c602fabSXin LI 	cp += 1;
12353c602fabSXin LI 	/* dl_type */
1236*ee67461eSJoseph Mingrone 	dl_type = GET_BE_U_2(cp);
12373c602fabSXin LI 	cp += 2;
12383c602fabSXin LI 	if (! (wildcards & OFPFW_DL_TYPE))
1239*ee67461eSJoseph Mingrone 		ND_PRINT("%smatch dl_type 0x%04x", pfx, dl_type);
12403c602fabSXin LI 	/* nw_tos */
12413c602fabSXin LI 	if (! (wildcards & OFPFW_NW_TOS))
1242*ee67461eSJoseph Mingrone 		ND_PRINT("%smatch nw_tos 0x%02x", pfx, GET_U_1(cp));
12433c602fabSXin LI 	cp += 1;
12443c602fabSXin LI 	/* nw_proto */
1245*ee67461eSJoseph Mingrone 	nw_proto = GET_U_1(cp);
12463c602fabSXin LI 	cp += 1;
12473c602fabSXin LI 	if (! (wildcards & OFPFW_NW_PROTO)) {
12483c602fabSXin LI 		field_name = ! (wildcards & OFPFW_DL_TYPE) && dl_type == ETHERTYPE_ARP
12493c602fabSXin LI 		  ? "arp_opcode" : "nw_proto";
1250*ee67461eSJoseph Mingrone 		ND_PRINT("%smatch %s %u", pfx, field_name, nw_proto);
12513c602fabSXin LI 	}
12523c602fabSXin LI 	/* pad2 */
12533c602fabSXin LI 	cp += 2;
12543c602fabSXin LI 	/* nw_src */
12553c602fabSXin LI 	nw_bits = (wildcards & OFPFW_NW_SRC_MASK) >> OFPFW_NW_SRC_SHIFT;
12563c602fabSXin LI 	if (nw_bits < 32)
1257*ee67461eSJoseph Mingrone 		ND_PRINT("%smatch nw_src %s/%u", pfx, GET_IPADDR_STRING(cp), 32 - nw_bits);
12583c602fabSXin LI 	cp += 4;
12593c602fabSXin LI 	/* nw_dst */
12603c602fabSXin LI 	nw_bits = (wildcards & OFPFW_NW_DST_MASK) >> OFPFW_NW_DST_SHIFT;
12613c602fabSXin LI 	if (nw_bits < 32)
1262*ee67461eSJoseph Mingrone 		ND_PRINT("%smatch nw_dst %s/%u", pfx, GET_IPADDR_STRING(cp), 32 - nw_bits);
12633c602fabSXin LI 	cp += 4;
12643c602fabSXin LI 	/* tp_src */
12653c602fabSXin LI 	if (! (wildcards & OFPFW_TP_SRC)) {
12663c602fabSXin LI 		field_name = ! (wildcards & OFPFW_DL_TYPE) && dl_type == ETHERTYPE_IP
12673c602fabSXin LI 		  && ! (wildcards & OFPFW_NW_PROTO) && nw_proto == IPPROTO_ICMP
12683c602fabSXin LI 		  ? "icmp_type" : "tp_src";
1269*ee67461eSJoseph Mingrone 		ND_PRINT("%smatch %s %u", pfx, field_name, GET_BE_U_2(cp));
12703c602fabSXin LI 	}
12713c602fabSXin LI 	cp += 2;
12723c602fabSXin LI 	/* tp_dst */
1273*ee67461eSJoseph Mingrone 	/* The last unconditional check was at nw_proto, so have an "else" here. */
12743c602fabSXin LI 	if (! (wildcards & OFPFW_TP_DST)) {
12753c602fabSXin LI 		field_name = ! (wildcards & OFPFW_DL_TYPE) && dl_type == ETHERTYPE_IP
12763c602fabSXin LI 		  && ! (wildcards & OFPFW_NW_PROTO) && nw_proto == IPPROTO_ICMP
12773c602fabSXin LI 		  ? "icmp_code" : "tp_dst";
1278*ee67461eSJoseph Mingrone 		ND_PRINT("%smatch %s %u", pfx, field_name, GET_BE_U_2(cp));
12793c602fabSXin LI 	}
1280*ee67461eSJoseph Mingrone 	else
1281*ee67461eSJoseph Mingrone 		ND_TCHECK_2(cp);
12823c602fabSXin LI }
12833c602fabSXin LI 
12843c602fabSXin LI /* [OF10] Section 5.2.4 */
1285*ee67461eSJoseph Mingrone static void
12863c602fabSXin LI of10_actions_print(netdissect_options *ndo,
1287*ee67461eSJoseph Mingrone                    const char *pfx, const u_char *cp, u_int len)
12888bdc5a62SPatrick Kelsey {
12893c602fabSXin LI 	while (len) {
1290*ee67461eSJoseph Mingrone 		uint16_t type, alen, output_port;
12913c602fabSXin LI 		u_char alen_bogus = 0, skip = 0;
12923c602fabSXin LI 
1293*ee67461eSJoseph Mingrone 		if (len < OF_ACTION_MINLEN)
12943340d773SGleb Smirnoff 			goto invalid;
12953c602fabSXin LI 		/* type */
1296*ee67461eSJoseph Mingrone 		type = GET_BE_U_2(cp);
1297*ee67461eSJoseph Mingrone 		OF_FWD(2);
1298*ee67461eSJoseph Mingrone 		ND_PRINT("%saction type %s", pfx, tok2str(ofpat_str, "invalid (0x%04x)", type));
12993c602fabSXin LI 		/* length */
1300*ee67461eSJoseph Mingrone 		alen = GET_BE_U_2(cp);
1301*ee67461eSJoseph Mingrone 		OF_FWD(2);
1302*ee67461eSJoseph Mingrone 		ND_PRINT(", len %u", alen);
1303*ee67461eSJoseph Mingrone 		/*
1304*ee67461eSJoseph Mingrone 		 * The 4-byte "pad" in the specification is not a field of the
1305*ee67461eSJoseph Mingrone 		 * action header, but a placeholder to illustrate the 64-bit
1306*ee67461eSJoseph Mingrone 		 * alignment requirement. Action type specific case blocks
1307*ee67461eSJoseph Mingrone 		 * below fetch these 4 bytes.
1308*ee67461eSJoseph Mingrone 		 */
1309*ee67461eSJoseph Mingrone 
13103c602fabSXin LI 		/* On action size underrun/overrun skip the rest of the action list. */
1311*ee67461eSJoseph Mingrone 		if (alen < OF_ACTION_MINLEN || alen > len + 4)
13123340d773SGleb Smirnoff 			goto invalid;
1313*ee67461eSJoseph Mingrone 		/*
1314*ee67461eSJoseph Mingrone 		 * After validating the basic length constraint it will be safe
1315*ee67461eSJoseph Mingrone 		 * to skip the current action if the action size is not valid
1316*ee67461eSJoseph Mingrone 		 * for the type or the type is invalid.
1317*ee67461eSJoseph Mingrone 		 */
13183c602fabSXin LI 		switch (type) {
13193c602fabSXin LI 		case OFPAT_OUTPUT:
13203c602fabSXin LI 		case OFPAT_SET_VLAN_VID:
13213c602fabSXin LI 		case OFPAT_SET_VLAN_PCP:
13223c602fabSXin LI 		case OFPAT_STRIP_VLAN:
13233c602fabSXin LI 		case OFPAT_SET_NW_SRC:
13243c602fabSXin LI 		case OFPAT_SET_NW_DST:
13253c602fabSXin LI 		case OFPAT_SET_NW_TOS:
13263c602fabSXin LI 		case OFPAT_SET_TP_SRC:
13273c602fabSXin LI 		case OFPAT_SET_TP_DST:
13283c602fabSXin LI 			alen_bogus = alen != 8;
13293c602fabSXin LI 			break;
13303c602fabSXin LI 		case OFPAT_SET_DL_SRC:
13313c602fabSXin LI 		case OFPAT_SET_DL_DST:
13323c602fabSXin LI 		case OFPAT_ENQUEUE:
13333c602fabSXin LI 			alen_bogus = alen != 16;
13343c602fabSXin LI 			break;
13353c602fabSXin LI 		case OFPAT_VENDOR:
13363c602fabSXin LI 			alen_bogus = alen % 8 != 0; /* already >= 8 so far */
13373c602fabSXin LI 			break;
13383c602fabSXin LI 		default:
13393c602fabSXin LI 			skip = 1;
13403c602fabSXin LI 		}
13413c602fabSXin LI 		if (alen_bogus) {
1342*ee67461eSJoseph Mingrone 			ND_PRINT(" (bogus)");
13433c602fabSXin LI 			skip = 1;
13443c602fabSXin LI 		}
13453c602fabSXin LI 		if (skip) {
1346*ee67461eSJoseph Mingrone 			/*
1347*ee67461eSJoseph Mingrone 			 * alen >= OF_ACTION_MINLEN
1348*ee67461eSJoseph Mingrone 			 * cp is 4 bytes in
1349*ee67461eSJoseph Mingrone 			 */
1350*ee67461eSJoseph Mingrone 			OF_CHK_FWD(alen - 4);
1351*ee67461eSJoseph Mingrone 			continue;
13523c602fabSXin LI 		}
13533c602fabSXin LI 		/* OK to decode the rest of the action structure */
13543c602fabSXin LI 		switch (type) {
13553c602fabSXin LI 		case OFPAT_OUTPUT:
13563c602fabSXin LI 			/* port */
1357*ee67461eSJoseph Mingrone 			output_port = GET_BE_U_2(cp);
1358*ee67461eSJoseph Mingrone 			OF_FWD(2);
1359*ee67461eSJoseph Mingrone 			ND_PRINT(", port %s", tok2str(ofpp_str, "%u", output_port));
13603c602fabSXin LI 			/* max_len */
13613c602fabSXin LI 			if (output_port == OFPP_CONTROLLER)
1362*ee67461eSJoseph Mingrone 				ND_PRINT(", max_len %u", GET_BE_U_2(cp));
1363*ee67461eSJoseph Mingrone 			else
1364*ee67461eSJoseph Mingrone 				ND_TCHECK_2(cp);
1365*ee67461eSJoseph Mingrone 			OF_FWD(2);
13663c602fabSXin LI 			break;
13673c602fabSXin LI 		case OFPAT_SET_VLAN_VID:
13683c602fabSXin LI 			/* vlan_vid */
1369*ee67461eSJoseph Mingrone 			ND_PRINT(", vlan_vid %s", vlan_str(GET_BE_U_2(cp)));
1370*ee67461eSJoseph Mingrone 			OF_FWD(2);
13713c602fabSXin LI 			/* pad */
1372*ee67461eSJoseph Mingrone 			/* Sometimes the last field, check bounds. */
1373*ee67461eSJoseph Mingrone 			OF_CHK_FWD(2);
13743c602fabSXin LI 			break;
13753c602fabSXin LI 		case OFPAT_SET_VLAN_PCP:
13763c602fabSXin LI 			/* vlan_pcp */
1377*ee67461eSJoseph Mingrone 			ND_PRINT(", vlan_pcp %s", pcp_str(GET_U_1(cp)));
1378*ee67461eSJoseph Mingrone 			OF_FWD(1);
13793c602fabSXin LI 			/* pad */
1380*ee67461eSJoseph Mingrone 			/* Sometimes the last field, check bounds. */
1381*ee67461eSJoseph Mingrone 			OF_CHK_FWD(3);
13823c602fabSXin LI 			break;
13833c602fabSXin LI 		case OFPAT_SET_DL_SRC:
13843c602fabSXin LI 		case OFPAT_SET_DL_DST:
13853c602fabSXin LI 			/* dl_addr */
1386*ee67461eSJoseph Mingrone 			ND_PRINT(", dl_addr %s", GET_ETHERADDR_STRING(cp));
1387*ee67461eSJoseph Mingrone 			OF_FWD(MAC_ADDR_LEN);
13883c602fabSXin LI 			/* pad */
1389*ee67461eSJoseph Mingrone 			/* Sometimes the last field, check bounds. */
1390*ee67461eSJoseph Mingrone 			OF_CHK_FWD(6);
13913c602fabSXin LI 			break;
13923c602fabSXin LI 		case OFPAT_SET_NW_SRC:
13933c602fabSXin LI 		case OFPAT_SET_NW_DST:
13943c602fabSXin LI 			/* nw_addr */
1395*ee67461eSJoseph Mingrone 			ND_PRINT(", nw_addr %s", GET_IPADDR_STRING(cp));
1396*ee67461eSJoseph Mingrone 			OF_FWD(4);
13973c602fabSXin LI 			break;
13983c602fabSXin LI 		case OFPAT_SET_NW_TOS:
13993c602fabSXin LI 			/* nw_tos */
1400*ee67461eSJoseph Mingrone 			ND_PRINT(", nw_tos 0x%02x", GET_U_1(cp));
1401*ee67461eSJoseph Mingrone 			OF_FWD(1);
14023c602fabSXin LI 			/* pad */
1403*ee67461eSJoseph Mingrone 			/* Sometimes the last field, check bounds. */
1404*ee67461eSJoseph Mingrone 			OF_CHK_FWD(3);
14053c602fabSXin LI 			break;
14063c602fabSXin LI 		case OFPAT_SET_TP_SRC:
14073c602fabSXin LI 		case OFPAT_SET_TP_DST:
14083c602fabSXin LI 			/* nw_tos */
1409*ee67461eSJoseph Mingrone 			ND_PRINT(", tp_port %u", GET_BE_U_2(cp));
1410*ee67461eSJoseph Mingrone 			OF_FWD(2);
14113c602fabSXin LI 			/* pad */
1412*ee67461eSJoseph Mingrone 			/* Sometimes the last field, check bounds. */
1413*ee67461eSJoseph Mingrone 			OF_CHK_FWD(2);
14143c602fabSXin LI 			break;
14153c602fabSXin LI 		case OFPAT_ENQUEUE:
14163c602fabSXin LI 			/* port */
1417*ee67461eSJoseph Mingrone 			ND_PRINT(", port %s",
1418*ee67461eSJoseph Mingrone 				 tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1419*ee67461eSJoseph Mingrone 			OF_FWD(2);
14203c602fabSXin LI 			/* pad */
1421*ee67461eSJoseph Mingrone 			OF_FWD(6);
14223c602fabSXin LI 			/* queue_id */
1423*ee67461eSJoseph Mingrone 			ND_PRINT(", queue_id %s",
1424*ee67461eSJoseph Mingrone 				 tok2str(ofpq_str, "%u", GET_BE_U_4(cp)));
1425*ee67461eSJoseph Mingrone 			OF_FWD(4);
14263c602fabSXin LI 			break;
14273c602fabSXin LI 		case OFPAT_VENDOR:
1428*ee67461eSJoseph Mingrone 			of10_vendor_action_print(ndo, cp, alen - 4);
1429*ee67461eSJoseph Mingrone 			OF_FWD(alen - 4);
14303c602fabSXin LI 			break;
14313c602fabSXin LI 		case OFPAT_STRIP_VLAN:
14323c602fabSXin LI 			/* pad */
1433*ee67461eSJoseph Mingrone 			/* Sometimes the last field, check bounds. */
1434*ee67461eSJoseph Mingrone 			OF_CHK_FWD(4);
14353c602fabSXin LI 			break;
14363c602fabSXin LI 		} /* switch */
14373c602fabSXin LI 	} /* while */
1438*ee67461eSJoseph Mingrone 	return;
14393c602fabSXin LI 
14403340d773SGleb Smirnoff invalid: /* skip the rest of actions */
1441*ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
1442*ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
14433c602fabSXin LI }
14443c602fabSXin LI 
14453c602fabSXin LI /* [OF10] Section 5.3.1 */
1446*ee67461eSJoseph Mingrone static void
14473c602fabSXin LI of10_features_reply_print(netdissect_options *ndo,
1448*ee67461eSJoseph Mingrone                           const u_char *cp, u_int len)
14498bdc5a62SPatrick Kelsey {
14503c602fabSXin LI 	/* datapath_id */
1451*ee67461eSJoseph Mingrone 	ND_PRINT("\n\t dpid 0x%016" PRIx64, GET_BE_U_8(cp));
1452*ee67461eSJoseph Mingrone 	OF_FWD(8);
14533c602fabSXin LI 	/* n_buffers */
1454*ee67461eSJoseph Mingrone 	ND_PRINT(", n_buffers %u", GET_BE_U_4(cp));
1455*ee67461eSJoseph Mingrone 	OF_FWD(4);
14563c602fabSXin LI 	/* n_tables */
1457*ee67461eSJoseph Mingrone 	ND_PRINT(", n_tables %u", GET_U_1(cp));
1458*ee67461eSJoseph Mingrone 	OF_FWD(1);
14593c602fabSXin LI 	/* pad */
1460*ee67461eSJoseph Mingrone 	OF_FWD(3);
14613c602fabSXin LI 	/* capabilities */
1462*ee67461eSJoseph Mingrone 	ND_PRINT("\n\t capabilities 0x%08x", GET_BE_U_4(cp));
1463*ee67461eSJoseph Mingrone 	of_bitmap_print(ndo, ofp_capabilities_bm, GET_BE_U_4(cp), OFPCAP_U);
1464*ee67461eSJoseph Mingrone 	OF_FWD(4);
14653c602fabSXin LI 	/* actions */
1466*ee67461eSJoseph Mingrone 	ND_PRINT("\n\t actions 0x%08x", GET_BE_U_4(cp));
1467*ee67461eSJoseph Mingrone 	of_bitmap_print(ndo, ofpat_bm, GET_BE_U_4(cp), OFPAT_U);
1468*ee67461eSJoseph Mingrone 	OF_FWD(4);
14693c602fabSXin LI 	/* ports */
1470*ee67461eSJoseph Mingrone 	while (len) {
1471*ee67461eSJoseph Mingrone 		if (len < OF_PHY_PORT_FIXLEN)
1472*ee67461eSJoseph Mingrone 			goto invalid;
1473*ee67461eSJoseph Mingrone 		of10_phy_port_print(ndo, cp);
1474*ee67461eSJoseph Mingrone 		OF_FWD(OF_PHY_PORT_FIXLEN);
1475*ee67461eSJoseph Mingrone 	}
1476*ee67461eSJoseph Mingrone 	return;
14773c602fabSXin LI 
1478*ee67461eSJoseph Mingrone invalid: /* skip the undersized trailing data */
1479*ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
1480*ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
1481*ee67461eSJoseph Mingrone }
1482*ee67461eSJoseph Mingrone 
1483*ee67461eSJoseph Mingrone /* [OF10] Section 5.3.2 */
1484*ee67461eSJoseph Mingrone static void
1485*ee67461eSJoseph Mingrone of10_switch_config_msg_print(netdissect_options *ndo,
1486*ee67461eSJoseph Mingrone                              const u_char *cp, u_int len _U_)
1487*ee67461eSJoseph Mingrone {
1488*ee67461eSJoseph Mingrone 	/* flags */
1489*ee67461eSJoseph Mingrone 	ND_PRINT("\n\t flags %s",
1490*ee67461eSJoseph Mingrone 	         tok2str(ofp_config_str, "invalid (0x%04x)", GET_BE_U_2(cp)));
1491*ee67461eSJoseph Mingrone 	cp += 2;
1492*ee67461eSJoseph Mingrone 	/* miss_send_len */
1493*ee67461eSJoseph Mingrone 	ND_PRINT(", miss_send_len %u", GET_BE_U_2(cp));
14943c602fabSXin LI }
14953c602fabSXin LI 
14963c602fabSXin LI /* [OF10] Section 5.3.3 */
1497*ee67461eSJoseph Mingrone static void
14983c602fabSXin LI of10_flow_mod_print(netdissect_options *ndo,
1499*ee67461eSJoseph Mingrone                     const u_char *cp, u_int len)
15008bdc5a62SPatrick Kelsey {
15013c602fabSXin LI 	uint16_t command;
15023c602fabSXin LI 
15033c602fabSXin LI 	/* match */
1504*ee67461eSJoseph Mingrone 	of10_match_print(ndo, "\n\t ", cp);
1505*ee67461eSJoseph Mingrone 	OF_FWD(OF_MATCH_FIXLEN);
15063c602fabSXin LI 	/* cookie */
1507*ee67461eSJoseph Mingrone 	ND_PRINT("\n\t cookie 0x%016" PRIx64, GET_BE_U_8(cp));
1508*ee67461eSJoseph Mingrone 	OF_FWD(8);
15093c602fabSXin LI 	/* command */
1510*ee67461eSJoseph Mingrone 	command = GET_BE_U_2(cp);
1511*ee67461eSJoseph Mingrone 	ND_PRINT(", command %s", tok2str(ofpfc_str, "invalid (0x%04x)", command));
1512*ee67461eSJoseph Mingrone 	OF_FWD(2);
15133c602fabSXin LI 	/* idle_timeout */
1514*ee67461eSJoseph Mingrone 	if (GET_BE_U_2(cp))
1515*ee67461eSJoseph Mingrone 		ND_PRINT(", idle_timeout %u", GET_BE_U_2(cp));
1516*ee67461eSJoseph Mingrone 	OF_FWD(2);
15173c602fabSXin LI 	/* hard_timeout */
1518*ee67461eSJoseph Mingrone 	if (GET_BE_U_2(cp))
1519*ee67461eSJoseph Mingrone 		ND_PRINT(", hard_timeout %u", GET_BE_U_2(cp));
1520*ee67461eSJoseph Mingrone 	OF_FWD(2);
15213c602fabSXin LI 	/* priority */
1522*ee67461eSJoseph Mingrone 	if (GET_BE_U_2(cp))
1523*ee67461eSJoseph Mingrone 		ND_PRINT(", priority %u", GET_BE_U_2(cp));
1524*ee67461eSJoseph Mingrone 	OF_FWD(2);
15253c602fabSXin LI 	/* buffer_id */
15263c602fabSXin LI 	if (command == OFPFC_ADD || command == OFPFC_MODIFY ||
15273c602fabSXin LI 	    command == OFPFC_MODIFY_STRICT)
1528*ee67461eSJoseph Mingrone 		ND_PRINT(", buffer_id %s",
1529*ee67461eSJoseph Mingrone 		         tok2str(bufferid_str, "0x%08x", GET_BE_U_4(cp)));
1530*ee67461eSJoseph Mingrone 	OF_FWD(4);
15313c602fabSXin LI 	/* out_port */
15323c602fabSXin LI 	if (command == OFPFC_DELETE || command == OFPFC_DELETE_STRICT)
1533*ee67461eSJoseph Mingrone 		ND_PRINT(", out_port %s",
1534*ee67461eSJoseph Mingrone 		         tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1535*ee67461eSJoseph Mingrone 	OF_FWD(2);
15363c602fabSXin LI 	/* flags */
1537*ee67461eSJoseph Mingrone 	ND_PRINT(", flags 0x%04x", GET_BE_U_2(cp));
1538*ee67461eSJoseph Mingrone 	of_bitmap_print(ndo, ofpff_bm, GET_BE_U_2(cp), OFPFF_U);
1539*ee67461eSJoseph Mingrone 	OF_FWD(2);
15403c602fabSXin LI 	/* actions */
1541*ee67461eSJoseph Mingrone 	of10_actions_print(ndo, "\n\t ", cp, len);
15423c602fabSXin LI }
15433c602fabSXin LI 
15443c602fabSXin LI /* ibid */
1545*ee67461eSJoseph Mingrone static void
15463c602fabSXin LI of10_port_mod_print(netdissect_options *ndo,
1547*ee67461eSJoseph Mingrone                     const u_char *cp, u_int len _U_)
15488bdc5a62SPatrick Kelsey {
15493c602fabSXin LI 	/* port_no */
1550*ee67461eSJoseph Mingrone 	ND_PRINT("\n\t port_no %s", tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
15513c602fabSXin LI 	cp += 2;
15523c602fabSXin LI 	/* hw_addr */
1553*ee67461eSJoseph Mingrone 	ND_PRINT(", hw_addr %s", GET_ETHERADDR_STRING(cp));
1554*ee67461eSJoseph Mingrone 	cp += MAC_ADDR_LEN;
15553c602fabSXin LI 	/* config */
1556*ee67461eSJoseph Mingrone 	ND_PRINT("\n\t config 0x%08x", GET_BE_U_4(cp));
1557*ee67461eSJoseph Mingrone 	of_bitmap_print(ndo, ofppc_bm, GET_BE_U_4(cp), OFPPC_U);
15583c602fabSXin LI 	cp += 4;
15593c602fabSXin LI 	/* mask */
1560*ee67461eSJoseph Mingrone 	ND_PRINT("\n\t mask 0x%08x", GET_BE_U_4(cp));
1561*ee67461eSJoseph Mingrone 	of_bitmap_print(ndo, ofppc_bm, GET_BE_U_4(cp), OFPPC_U);
15623c602fabSXin LI 	cp += 4;
15633c602fabSXin LI 	/* advertise */
1564*ee67461eSJoseph Mingrone 	ND_PRINT("\n\t advertise 0x%08x", GET_BE_U_4(cp));
1565*ee67461eSJoseph Mingrone 	of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U);
15663c602fabSXin LI 	cp += 4;
15673c602fabSXin LI 	/* pad */
1568*ee67461eSJoseph Mingrone 	/* Always the last field, check bounds. */
1569*ee67461eSJoseph Mingrone 	ND_TCHECK_4(cp);
1570*ee67461eSJoseph Mingrone }
15713c602fabSXin LI 
1572*ee67461eSJoseph Mingrone /* [OF10] Section 5.3.4 */
1573*ee67461eSJoseph Mingrone static void
1574*ee67461eSJoseph Mingrone of10_queue_get_config_request_print(netdissect_options *ndo,
1575*ee67461eSJoseph Mingrone                                     const u_char *cp, u_int len _U_)
1576*ee67461eSJoseph Mingrone {
1577*ee67461eSJoseph Mingrone 	/* port */
1578*ee67461eSJoseph Mingrone 	ND_PRINT("\n\t port %s", tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1579*ee67461eSJoseph Mingrone 	cp += 2;
1580*ee67461eSJoseph Mingrone 	/* pad */
1581*ee67461eSJoseph Mingrone 	/* Always the last field, check bounds. */
1582*ee67461eSJoseph Mingrone 	ND_TCHECK_2(cp);
1583*ee67461eSJoseph Mingrone }
1584*ee67461eSJoseph Mingrone 
1585*ee67461eSJoseph Mingrone /* ibid */
1586*ee67461eSJoseph Mingrone static void
1587*ee67461eSJoseph Mingrone of10_queue_get_config_reply_print(netdissect_options *ndo,
1588*ee67461eSJoseph Mingrone                                   const u_char *cp, u_int len)
1589*ee67461eSJoseph Mingrone {
1590*ee67461eSJoseph Mingrone 	/* port */
1591*ee67461eSJoseph Mingrone 	ND_PRINT("\n\t port %s", tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1592*ee67461eSJoseph Mingrone 	OF_FWD(2);
1593*ee67461eSJoseph Mingrone 	/* pad */
1594*ee67461eSJoseph Mingrone 	/* Sometimes the last field, check bounds. */
1595*ee67461eSJoseph Mingrone 	OF_CHK_FWD(6);
1596*ee67461eSJoseph Mingrone 	/* queues */
1597*ee67461eSJoseph Mingrone 	of10_queues_print(ndo, cp, len);
15983c602fabSXin LI }
15993c602fabSXin LI 
16003c602fabSXin LI /* [OF10] Section 5.3.5 */
1601*ee67461eSJoseph Mingrone static void
16023c602fabSXin LI of10_stats_request_print(netdissect_options *ndo,
1603*ee67461eSJoseph Mingrone                          const u_char *cp, u_int len)
16048bdc5a62SPatrick Kelsey {
16053c602fabSXin LI 	uint16_t type;
16063c602fabSXin LI 
16073c602fabSXin LI 	/* type */
1608*ee67461eSJoseph Mingrone 	type = GET_BE_U_2(cp);
1609*ee67461eSJoseph Mingrone 	OF_FWD(2);
1610*ee67461eSJoseph Mingrone 	ND_PRINT("\n\t type %s", tok2str(ofpst_str, "invalid (0x%04x)", type));
16113c602fabSXin LI 	/* flags */
1612*ee67461eSJoseph Mingrone 	ND_PRINT(", flags 0x%04x", GET_BE_U_2(cp));
1613*ee67461eSJoseph Mingrone 	if (GET_BE_U_2(cp))
1614*ee67461eSJoseph Mingrone 		ND_PRINT(" (bogus)");
1615*ee67461eSJoseph Mingrone 	OF_FWD(2);
16163c602fabSXin LI 	/* type-specific body of one of fixed lengths */
16173c602fabSXin LI 	switch(type) {
16183c602fabSXin LI 	case OFPST_DESC:
16193c602fabSXin LI 	case OFPST_TABLE:
16203c602fabSXin LI 		if (len)
16213340d773SGleb Smirnoff 			goto invalid;
1622*ee67461eSJoseph Mingrone 		return;
16233c602fabSXin LI 	case OFPST_FLOW:
16243c602fabSXin LI 	case OFPST_AGGREGATE:
1625*ee67461eSJoseph Mingrone 		if (len != OF_FLOW_STATS_REQUEST_FIXLEN)
16263340d773SGleb Smirnoff 			goto invalid;
16273c602fabSXin LI 		/* match */
1628*ee67461eSJoseph Mingrone 		of10_match_print(ndo, "\n\t ", cp);
1629*ee67461eSJoseph Mingrone 		OF_FWD(OF_MATCH_FIXLEN);
16303c602fabSXin LI 		/* table_id */
1631*ee67461eSJoseph Mingrone 		ND_PRINT("\n\t table_id %s",
1632*ee67461eSJoseph Mingrone 			 tok2str(tableid_str, "%u", GET_U_1(cp)));
1633*ee67461eSJoseph Mingrone 		OF_FWD(1);
16343c602fabSXin LI 		/* pad */
1635*ee67461eSJoseph Mingrone 		OF_FWD(1);
16363c602fabSXin LI 		/* out_port */
1637*ee67461eSJoseph Mingrone 		ND_PRINT(", out_port %s",
1638*ee67461eSJoseph Mingrone 			 tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1639*ee67461eSJoseph Mingrone 		return;
16403c602fabSXin LI 	case OFPST_PORT:
1641*ee67461eSJoseph Mingrone 		if (len != OF_PORT_STATS_REQUEST_FIXLEN)
16423340d773SGleb Smirnoff 			goto invalid;
16433c602fabSXin LI 		/* port_no */
1644*ee67461eSJoseph Mingrone 		ND_PRINT("\n\t port_no %s",
1645*ee67461eSJoseph Mingrone 			 tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1646*ee67461eSJoseph Mingrone 		OF_FWD(2);
16473c602fabSXin LI 		/* pad */
1648*ee67461eSJoseph Mingrone 		/* Always the last field, check bounds. */
1649*ee67461eSJoseph Mingrone 		OF_CHK_FWD(6);
1650*ee67461eSJoseph Mingrone 		return;
16513c602fabSXin LI 	case OFPST_QUEUE:
1652*ee67461eSJoseph Mingrone 		if (len != OF_QUEUE_STATS_REQUEST_FIXLEN)
16533340d773SGleb Smirnoff 			goto invalid;
16543c602fabSXin LI 		/* port_no */
1655*ee67461eSJoseph Mingrone 		ND_PRINT("\n\t port_no %s",
1656*ee67461eSJoseph Mingrone 			 tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1657*ee67461eSJoseph Mingrone 		OF_FWD(2);
16583c602fabSXin LI 		/* pad */
1659*ee67461eSJoseph Mingrone 		OF_FWD(2);
16603c602fabSXin LI 		/* queue_id */
1661*ee67461eSJoseph Mingrone 		ND_PRINT(", queue_id %s",
1662*ee67461eSJoseph Mingrone 			 tok2str(ofpq_str, "%u", GET_BE_U_4(cp)));
1663*ee67461eSJoseph Mingrone 		return;
16643c602fabSXin LI 	case OFPST_VENDOR:
1665*ee67461eSJoseph Mingrone 		of10_vendor_data_print(ndo, cp, len);
1666*ee67461eSJoseph Mingrone 		return;
16673c602fabSXin LI 	}
1668*ee67461eSJoseph Mingrone 	return;
16693c602fabSXin LI 
16703340d773SGleb Smirnoff invalid: /* skip the message body */
1671*ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
1672*ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
16733c602fabSXin LI }
16743c602fabSXin LI 
16753c602fabSXin LI /* ibid */
1676*ee67461eSJoseph Mingrone static void
16773c602fabSXin LI of10_desc_stats_reply_print(netdissect_options *ndo,
1678*ee67461eSJoseph Mingrone                             const u_char *cp, u_int len)
16798bdc5a62SPatrick Kelsey {
1680*ee67461eSJoseph Mingrone 	if (len != OF_DESC_STATS_REPLY_FIXLEN)
16813340d773SGleb Smirnoff 		goto invalid;
16823c602fabSXin LI 	/* mfr_desc */
1683*ee67461eSJoseph Mingrone 	ND_PRINT("\n\t  mfr_desc '");
1684*ee67461eSJoseph Mingrone 	nd_printjnp(ndo, cp, DESC_STR_LEN);
1685*ee67461eSJoseph Mingrone 	ND_PRINT("'");
1686*ee67461eSJoseph Mingrone 	OF_FWD(DESC_STR_LEN);
16873c602fabSXin LI 	/* hw_desc */
1688*ee67461eSJoseph Mingrone 	ND_PRINT("\n\t  hw_desc '");
1689*ee67461eSJoseph Mingrone 	nd_printjnp(ndo, cp, DESC_STR_LEN);
1690*ee67461eSJoseph Mingrone 	ND_PRINT("'");
1691*ee67461eSJoseph Mingrone 	OF_FWD(DESC_STR_LEN);
16923c602fabSXin LI 	/* sw_desc */
1693*ee67461eSJoseph Mingrone 	ND_PRINT("\n\t  sw_desc '");
1694*ee67461eSJoseph Mingrone 	nd_printjnp(ndo, cp, DESC_STR_LEN);
1695*ee67461eSJoseph Mingrone 	ND_PRINT("'");
1696*ee67461eSJoseph Mingrone 	OF_FWD(DESC_STR_LEN);
16973c602fabSXin LI 	/* serial_num */
1698*ee67461eSJoseph Mingrone 	ND_PRINT("\n\t  serial_num '");
1699*ee67461eSJoseph Mingrone 	nd_printjnp(ndo, cp, SERIAL_NUM_LEN);
1700*ee67461eSJoseph Mingrone 	ND_PRINT("'");
1701*ee67461eSJoseph Mingrone 	OF_FWD(SERIAL_NUM_LEN);
17023c602fabSXin LI 	/* dp_desc */
1703*ee67461eSJoseph Mingrone 	ND_PRINT("\n\t  dp_desc '");
1704*ee67461eSJoseph Mingrone 	nd_printjnp(ndo, cp, DESC_STR_LEN);
1705*ee67461eSJoseph Mingrone 	ND_PRINT("'");
1706*ee67461eSJoseph Mingrone 	return;
17073c602fabSXin LI 
17083340d773SGleb Smirnoff invalid: /* skip the message body */
1709*ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
1710*ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
17113c602fabSXin LI }
17123c602fabSXin LI 
17133c602fabSXin LI /* ibid */
1714*ee67461eSJoseph Mingrone static void
17153c602fabSXin LI of10_flow_stats_reply_print(netdissect_options *ndo,
1716*ee67461eSJoseph Mingrone                             const u_char *cp, u_int len)
17178bdc5a62SPatrick Kelsey {
1718*ee67461eSJoseph Mingrone 	while (len) {
17193c602fabSXin LI 		uint16_t entry_len;
17203c602fabSXin LI 
1721*ee67461eSJoseph Mingrone 		if (len < OF_FLOW_STATS_REPLY_MINLEN)
17223340d773SGleb Smirnoff 			goto invalid;
17233c602fabSXin LI 		/* length */
1724*ee67461eSJoseph Mingrone 		entry_len = GET_BE_U_2(cp);
1725*ee67461eSJoseph Mingrone 		ND_PRINT("\n\t length %u", entry_len);
1726*ee67461eSJoseph Mingrone 		if (entry_len < OF_FLOW_STATS_REPLY_MINLEN || entry_len > len)
17273340d773SGleb Smirnoff 			goto invalid;
1728*ee67461eSJoseph Mingrone 		OF_FWD(2);
17293c602fabSXin LI 		/* table_id */
1730*ee67461eSJoseph Mingrone 		ND_PRINT(", table_id %s",
1731*ee67461eSJoseph Mingrone 			 tok2str(tableid_str, "%u", GET_U_1(cp)));
1732*ee67461eSJoseph Mingrone 		OF_FWD(1);
17333c602fabSXin LI 		/* pad */
1734*ee67461eSJoseph Mingrone 		OF_FWD(1);
17353c602fabSXin LI 		/* match */
1736*ee67461eSJoseph Mingrone 		of10_match_print(ndo, "\n\t  ", cp);
1737*ee67461eSJoseph Mingrone 		OF_FWD(OF_MATCH_FIXLEN);
17383c602fabSXin LI 		/* duration_sec */
1739*ee67461eSJoseph Mingrone 		ND_PRINT("\n\t  duration_sec %u", GET_BE_U_4(cp));
1740*ee67461eSJoseph Mingrone 		OF_FWD(4);
17413c602fabSXin LI 		/* duration_nsec */
1742*ee67461eSJoseph Mingrone 		ND_PRINT(", duration_nsec %u", GET_BE_U_4(cp));
1743*ee67461eSJoseph Mingrone 		OF_FWD(4);
17443c602fabSXin LI 		/* priority */
1745*ee67461eSJoseph Mingrone 		ND_PRINT(", priority %u", GET_BE_U_2(cp));
1746*ee67461eSJoseph Mingrone 		OF_FWD(2);
17473c602fabSXin LI 		/* idle_timeout */
1748*ee67461eSJoseph Mingrone 		ND_PRINT(", idle_timeout %u", GET_BE_U_2(cp));
1749*ee67461eSJoseph Mingrone 		OF_FWD(2);
17503c602fabSXin LI 		/* hard_timeout */
1751*ee67461eSJoseph Mingrone 		ND_PRINT(", hard_timeout %u", GET_BE_U_2(cp));
1752*ee67461eSJoseph Mingrone 		OF_FWD(2);
17533c602fabSXin LI 		/* pad2 */
1754*ee67461eSJoseph Mingrone 		OF_FWD(6);
17553c602fabSXin LI 		/* cookie */
1756*ee67461eSJoseph Mingrone 		ND_PRINT(", cookie 0x%016" PRIx64, GET_BE_U_8(cp));
1757*ee67461eSJoseph Mingrone 		OF_FWD(8);
17583c602fabSXin LI 		/* packet_count */
1759*ee67461eSJoseph Mingrone 		ND_PRINT(", packet_count %" PRIu64, GET_BE_U_8(cp));
1760*ee67461eSJoseph Mingrone 		OF_FWD(8);
17613c602fabSXin LI 		/* byte_count */
1762*ee67461eSJoseph Mingrone 		ND_PRINT(", byte_count %" PRIu64, GET_BE_U_8(cp));
1763*ee67461eSJoseph Mingrone 		OF_FWD(8);
17643c602fabSXin LI 		/* actions */
1765*ee67461eSJoseph Mingrone 		of10_actions_print(ndo, "\n\t  ", cp, entry_len - OF_FLOW_STATS_REPLY_MINLEN);
1766*ee67461eSJoseph Mingrone 		OF_FWD(entry_len - OF_FLOW_STATS_REPLY_MINLEN);
17673c602fabSXin LI 	} /* while */
1768*ee67461eSJoseph Mingrone 	return;
17693c602fabSXin LI 
17703340d773SGleb Smirnoff invalid: /* skip the rest of flow statistics entries */
1771*ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
1772*ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
17733c602fabSXin LI }
17743c602fabSXin LI 
17753c602fabSXin LI /* ibid */
1776*ee67461eSJoseph Mingrone static void
17773c602fabSXin LI of10_aggregate_stats_reply_print(netdissect_options *ndo,
1778*ee67461eSJoseph Mingrone                                  const u_char *cp, u_int len)
17798bdc5a62SPatrick Kelsey {
1780*ee67461eSJoseph Mingrone 	if (len != OF_AGGREGATE_STATS_REPLY_FIXLEN)
17813340d773SGleb Smirnoff 		goto invalid;
17823c602fabSXin LI 	/* packet_count */
1783*ee67461eSJoseph Mingrone 	ND_PRINT("\n\t packet_count %" PRIu64, GET_BE_U_8(cp));
1784*ee67461eSJoseph Mingrone 	OF_FWD(8);
17853c602fabSXin LI 	/* byte_count */
1786*ee67461eSJoseph Mingrone 	ND_PRINT(", byte_count %" PRIu64, GET_BE_U_8(cp));
1787*ee67461eSJoseph Mingrone 	OF_FWD(8);
17883c602fabSXin LI 	/* flow_count */
1789*ee67461eSJoseph Mingrone 	ND_PRINT(", flow_count %u", GET_BE_U_4(cp));
1790*ee67461eSJoseph Mingrone 	OF_FWD(4);
17913c602fabSXin LI 	/* pad */
1792*ee67461eSJoseph Mingrone 	/* Always the last field, check bounds. */
1793*ee67461eSJoseph Mingrone 	ND_TCHECK_4(cp);
1794*ee67461eSJoseph Mingrone 	return;
17953c602fabSXin LI 
17963340d773SGleb Smirnoff invalid: /* skip the message body */
1797*ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
1798*ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
17993c602fabSXin LI }
18003c602fabSXin LI 
18013c602fabSXin LI /* ibid */
1802*ee67461eSJoseph Mingrone static void
18033c602fabSXin LI of10_table_stats_reply_print(netdissect_options *ndo,
1804*ee67461eSJoseph Mingrone                              const u_char *cp, u_int len)
18058bdc5a62SPatrick Kelsey {
18063c602fabSXin LI 	while (len) {
1807*ee67461eSJoseph Mingrone 		if (len < OF_TABLE_STATS_REPLY_FIXLEN)
18083340d773SGleb Smirnoff 			goto invalid;
18093c602fabSXin LI 		/* table_id */
1810*ee67461eSJoseph Mingrone 		ND_PRINT("\n\t table_id %s",
1811*ee67461eSJoseph Mingrone 		         tok2str(tableid_str, "%u", GET_U_1(cp)));
1812*ee67461eSJoseph Mingrone 		OF_FWD(1);
18133c602fabSXin LI 		/* pad */
1814*ee67461eSJoseph Mingrone 		OF_FWD(3);
18153c602fabSXin LI 		/* name */
1816*ee67461eSJoseph Mingrone 		ND_PRINT(", name '");
1817*ee67461eSJoseph Mingrone 		nd_printjnp(ndo, cp, OFP_MAX_TABLE_NAME_LEN);
1818*ee67461eSJoseph Mingrone 		ND_PRINT("'");
1819*ee67461eSJoseph Mingrone 		OF_FWD(OFP_MAX_TABLE_NAME_LEN);
18203c602fabSXin LI 		/* wildcards */
1821*ee67461eSJoseph Mingrone 		ND_PRINT("\n\t  wildcards 0x%08x", GET_BE_U_4(cp));
1822*ee67461eSJoseph Mingrone 		of_bitmap_print(ndo, ofpfw_bm, GET_BE_U_4(cp), OFPFW_U);
1823*ee67461eSJoseph Mingrone 		OF_FWD(4);
18243c602fabSXin LI 		/* max_entries */
1825*ee67461eSJoseph Mingrone 		ND_PRINT("\n\t  max_entries %u", GET_BE_U_4(cp));
1826*ee67461eSJoseph Mingrone 		OF_FWD(4);
18273c602fabSXin LI 		/* active_count */
1828*ee67461eSJoseph Mingrone 		ND_PRINT(", active_count %u", GET_BE_U_4(cp));
1829*ee67461eSJoseph Mingrone 		OF_FWD(4);
18303c602fabSXin LI 		/* lookup_count */
1831*ee67461eSJoseph Mingrone 		ND_PRINT(", lookup_count %" PRIu64, GET_BE_U_8(cp));
1832*ee67461eSJoseph Mingrone 		OF_FWD(8);
18333c602fabSXin LI 		/* matched_count */
1834*ee67461eSJoseph Mingrone 		ND_PRINT(", matched_count %" PRIu64, GET_BE_U_8(cp));
1835*ee67461eSJoseph Mingrone 		OF_FWD(8);
18363c602fabSXin LI 	} /* while */
1837*ee67461eSJoseph Mingrone 	return;
18383c602fabSXin LI 
18393340d773SGleb Smirnoff invalid: /* skip the undersized trailing data */
1840*ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
1841*ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
18423c602fabSXin LI }
18433c602fabSXin LI 
18443c602fabSXin LI /* ibid */
1845*ee67461eSJoseph Mingrone static void
18463c602fabSXin LI of10_port_stats_reply_print(netdissect_options *ndo,
1847*ee67461eSJoseph Mingrone                             const u_char *cp, u_int len)
18488bdc5a62SPatrick Kelsey {
18493c602fabSXin LI 	while (len) {
1850*ee67461eSJoseph Mingrone 		if (len < OF_PORT_STATS_REPLY_FIXLEN)
18513340d773SGleb Smirnoff 			goto invalid;
18523c602fabSXin LI 		/* port_no */
1853*ee67461eSJoseph Mingrone 		ND_PRINT("\n\t  port_no %s",
1854*ee67461eSJoseph Mingrone 			 tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1855*ee67461eSJoseph Mingrone 		OF_FWD(2);
18563c602fabSXin LI 		if (ndo->ndo_vflag < 2) {
1857*ee67461eSJoseph Mingrone 			OF_CHK_FWD(OF_PORT_STATS_REPLY_FIXLEN - 2);
1858*ee67461eSJoseph Mingrone 			continue;
18593c602fabSXin LI 		}
18603c602fabSXin LI 		/* pad */
1861*ee67461eSJoseph Mingrone 		OF_FWD(6);
18623c602fabSXin LI 		/* rx_packets */
1863*ee67461eSJoseph Mingrone 		ND_PRINT(", rx_packets %" PRIu64, GET_BE_U_8(cp));
1864*ee67461eSJoseph Mingrone 		OF_FWD(8);
18653c602fabSXin LI 		/* tx_packets */
1866*ee67461eSJoseph Mingrone 		ND_PRINT(", tx_packets %" PRIu64, GET_BE_U_8(cp));
1867*ee67461eSJoseph Mingrone 		OF_FWD(8);
18683c602fabSXin LI 		/* rx_bytes */
1869*ee67461eSJoseph Mingrone 		ND_PRINT(", rx_bytes %" PRIu64, GET_BE_U_8(cp));
1870*ee67461eSJoseph Mingrone 		OF_FWD(8);
18713c602fabSXin LI 		/* tx_bytes */
1872*ee67461eSJoseph Mingrone 		ND_PRINT(", tx_bytes %" PRIu64, GET_BE_U_8(cp));
1873*ee67461eSJoseph Mingrone 		OF_FWD(8);
18743c602fabSXin LI 		/* rx_dropped */
1875*ee67461eSJoseph Mingrone 		ND_PRINT(", rx_dropped %" PRIu64, GET_BE_U_8(cp));
1876*ee67461eSJoseph Mingrone 		OF_FWD(8);
18773c602fabSXin LI 		/* tx_dropped */
1878*ee67461eSJoseph Mingrone 		ND_PRINT(", tx_dropped %" PRIu64, GET_BE_U_8(cp));
1879*ee67461eSJoseph Mingrone 		OF_FWD(8);
18803c602fabSXin LI 		/* rx_errors */
1881*ee67461eSJoseph Mingrone 		ND_PRINT(", rx_errors %" PRIu64, GET_BE_U_8(cp));
1882*ee67461eSJoseph Mingrone 		OF_FWD(8);
18833c602fabSXin LI 		/* tx_errors */
1884*ee67461eSJoseph Mingrone 		ND_PRINT(", tx_errors %" PRIu64, GET_BE_U_8(cp));
1885*ee67461eSJoseph Mingrone 		OF_FWD(8);
18863c602fabSXin LI 		/* rx_frame_err */
1887*ee67461eSJoseph Mingrone 		ND_PRINT(", rx_frame_err %" PRIu64, GET_BE_U_8(cp));
1888*ee67461eSJoseph Mingrone 		OF_FWD(8);
18893c602fabSXin LI 		/* rx_over_err */
1890*ee67461eSJoseph Mingrone 		ND_PRINT(", rx_over_err %" PRIu64, GET_BE_U_8(cp));
1891*ee67461eSJoseph Mingrone 		OF_FWD(8);
18923c602fabSXin LI 		/* rx_crc_err */
1893*ee67461eSJoseph Mingrone 		ND_PRINT(", rx_crc_err %" PRIu64, GET_BE_U_8(cp));
1894*ee67461eSJoseph Mingrone 		OF_FWD(8);
18953c602fabSXin LI 		/* collisions */
1896*ee67461eSJoseph Mingrone 		ND_PRINT(", collisions %" PRIu64, GET_BE_U_8(cp));
1897*ee67461eSJoseph Mingrone 		OF_FWD(8);
18983c602fabSXin LI 	} /* while */
1899*ee67461eSJoseph Mingrone 	return;
19003c602fabSXin LI 
19013340d773SGleb Smirnoff invalid: /* skip the undersized trailing data */
1902*ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
1903*ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
19043c602fabSXin LI }
19053c602fabSXin LI 
19063c602fabSXin LI /* ibid */
1907*ee67461eSJoseph Mingrone static void
19083c602fabSXin LI of10_queue_stats_reply_print(netdissect_options *ndo,
1909*ee67461eSJoseph Mingrone                              const u_char *cp, u_int len)
19108bdc5a62SPatrick Kelsey {
19113c602fabSXin LI 	while (len) {
1912*ee67461eSJoseph Mingrone 		if (len < OF_QUEUE_STATS_REPLY_FIXLEN)
19133340d773SGleb Smirnoff 			goto invalid;
19143c602fabSXin LI 		/* port_no */
1915*ee67461eSJoseph Mingrone 		ND_PRINT("\n\t  port_no %s",
1916*ee67461eSJoseph Mingrone 		         tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1917*ee67461eSJoseph Mingrone 		OF_FWD(2);
19183c602fabSXin LI 		/* pad */
1919*ee67461eSJoseph Mingrone 		OF_FWD(2);
19203c602fabSXin LI 		/* queue_id */
1921*ee67461eSJoseph Mingrone 		ND_PRINT(", queue_id %u", GET_BE_U_4(cp));
1922*ee67461eSJoseph Mingrone 		OF_FWD(4);
19233c602fabSXin LI 		/* tx_bytes */
1924*ee67461eSJoseph Mingrone 		ND_PRINT(", tx_bytes %" PRIu64, GET_BE_U_8(cp));
1925*ee67461eSJoseph Mingrone 		OF_FWD(8);
19263c602fabSXin LI 		/* tx_packets */
1927*ee67461eSJoseph Mingrone 		ND_PRINT(", tx_packets %" PRIu64, GET_BE_U_8(cp));
1928*ee67461eSJoseph Mingrone 		OF_FWD(8);
19293c602fabSXin LI 		/* tx_errors */
1930*ee67461eSJoseph Mingrone 		ND_PRINT(", tx_errors %" PRIu64, GET_BE_U_8(cp));
1931*ee67461eSJoseph Mingrone 		OF_FWD(8);
19323c602fabSXin LI 	} /* while */
1933*ee67461eSJoseph Mingrone 	return;
19343c602fabSXin LI 
19353340d773SGleb Smirnoff invalid: /* skip the undersized trailing data */
1936*ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
1937*ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
19383c602fabSXin LI }
19393c602fabSXin LI 
19403c602fabSXin LI /* ibid */
1941*ee67461eSJoseph Mingrone static void
19423c602fabSXin LI of10_stats_reply_print(netdissect_options *ndo,
1943*ee67461eSJoseph Mingrone                        const u_char *cp, u_int len)
19448bdc5a62SPatrick Kelsey {
19453c602fabSXin LI 	uint16_t type;
19463c602fabSXin LI 
19473c602fabSXin LI 	/* type */
1948*ee67461eSJoseph Mingrone 	type = GET_BE_U_2(cp);
1949*ee67461eSJoseph Mingrone 	ND_PRINT("\n\t type %s", tok2str(ofpst_str, "invalid (0x%04x)", type));
1950*ee67461eSJoseph Mingrone 	OF_FWD(2);
19513c602fabSXin LI 	/* flags */
1952*ee67461eSJoseph Mingrone 	ND_PRINT(", flags 0x%04x", GET_BE_U_2(cp));
1953*ee67461eSJoseph Mingrone 	of_bitmap_print(ndo, ofpsf_reply_bm, GET_BE_U_2(cp), OFPSF_REPLY_U);
1954*ee67461eSJoseph Mingrone 	OF_FWD(2);
19553c602fabSXin LI 
19563c602fabSXin LI 	if (ndo->ndo_vflag > 0) {
1957*ee67461eSJoseph Mingrone 		void (*decoder)(netdissect_options *, const u_char *, u_int) =
19583c602fabSXin LI 			type == OFPST_DESC      ? of10_desc_stats_reply_print      :
19593c602fabSXin LI 			type == OFPST_FLOW      ? of10_flow_stats_reply_print      :
19603c602fabSXin LI 			type == OFPST_AGGREGATE ? of10_aggregate_stats_reply_print :
19613c602fabSXin LI 			type == OFPST_TABLE     ? of10_table_stats_reply_print     :
19623c602fabSXin LI 			type == OFPST_PORT      ? of10_port_stats_reply_print      :
19633c602fabSXin LI 			type == OFPST_QUEUE     ? of10_queue_stats_reply_print     :
19643c602fabSXin LI 			type == OFPST_VENDOR    ? of10_vendor_data_print           :
19653c602fabSXin LI 			NULL;
1966*ee67461eSJoseph Mingrone 		if (decoder != NULL) {
1967*ee67461eSJoseph Mingrone 			decoder(ndo, cp, len);
1968*ee67461eSJoseph Mingrone 			return;
19693c602fabSXin LI 		}
1970*ee67461eSJoseph Mingrone 	}
1971*ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
19723c602fabSXin LI }
19733c602fabSXin LI 
19743c602fabSXin LI /* [OF10] Section 5.3.6 */
1975*ee67461eSJoseph Mingrone static void
19763c602fabSXin LI of10_packet_out_print(netdissect_options *ndo,
1977*ee67461eSJoseph Mingrone                       const u_char *cp, u_int len)
19788bdc5a62SPatrick Kelsey {
19793c602fabSXin LI 	uint16_t actions_len;
19803c602fabSXin LI 
19813c602fabSXin LI 	/* buffer_id */
1982*ee67461eSJoseph Mingrone 	ND_PRINT("\n\t buffer_id 0x%08x", GET_BE_U_4(cp));
1983*ee67461eSJoseph Mingrone 	OF_FWD(4);
19843c602fabSXin LI 	/* in_port */
1985*ee67461eSJoseph Mingrone 	ND_PRINT(", in_port %s", tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1986*ee67461eSJoseph Mingrone 	OF_FWD(2);
19873c602fabSXin LI 	/* actions_len */
1988*ee67461eSJoseph Mingrone 	actions_len = GET_BE_U_2(cp);
1989*ee67461eSJoseph Mingrone 	OF_FWD(2);
1990*ee67461eSJoseph Mingrone 	if (actions_len > len)
19913340d773SGleb Smirnoff 		goto invalid;
19923c602fabSXin LI 	/* actions */
1993*ee67461eSJoseph Mingrone 	of10_actions_print(ndo, "\n\t ", cp, actions_len);
1994*ee67461eSJoseph Mingrone 	OF_FWD(actions_len);
19953c602fabSXin LI 	/* data */
1996*ee67461eSJoseph Mingrone 	of10_packet_data_print(ndo, cp, len);
1997*ee67461eSJoseph Mingrone 	return;
19983c602fabSXin LI 
19993340d773SGleb Smirnoff invalid: /* skip the rest of the message body */
2000*ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
2001*ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
20023c602fabSXin LI }
20033c602fabSXin LI 
20043c602fabSXin LI /* [OF10] Section 5.4.1 */
2005*ee67461eSJoseph Mingrone static void
20063c602fabSXin LI of10_packet_in_print(netdissect_options *ndo,
2007*ee67461eSJoseph Mingrone                      const u_char *cp, u_int len)
20088bdc5a62SPatrick Kelsey {
20093c602fabSXin LI 	/* buffer_id */
2010*ee67461eSJoseph Mingrone 	ND_PRINT("\n\t buffer_id %s",
2011*ee67461eSJoseph Mingrone 	         tok2str(bufferid_str, "0x%08x", GET_BE_U_4(cp)));
2012*ee67461eSJoseph Mingrone 	OF_FWD(4);
20133c602fabSXin LI 	/* total_len */
2014*ee67461eSJoseph Mingrone 	ND_PRINT(", total_len %u", GET_BE_U_2(cp));
2015*ee67461eSJoseph Mingrone 	OF_FWD(2);
20163c602fabSXin LI 	/* in_port */
2017*ee67461eSJoseph Mingrone 	ND_PRINT(", in_port %s", tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
2018*ee67461eSJoseph Mingrone 	OF_FWD(2);
20193c602fabSXin LI 	/* reason */
2020*ee67461eSJoseph Mingrone 	ND_PRINT(", reason %s",
2021*ee67461eSJoseph Mingrone 		 tok2str(ofpr_str, "invalid (0x%02x)", GET_U_1(cp)));
2022*ee67461eSJoseph Mingrone 	OF_FWD(1);
20233c602fabSXin LI 	/* pad */
2024*ee67461eSJoseph Mingrone 	/* Sometimes the last field, check bounds. */
2025*ee67461eSJoseph Mingrone 	OF_CHK_FWD(1);
20263c602fabSXin LI 	/* data */
2027*ee67461eSJoseph Mingrone 	of10_packet_data_print(ndo, cp, len);
20283c602fabSXin LI }
20293c602fabSXin LI 
20303c602fabSXin LI /* [OF10] Section 5.4.2 */
2031*ee67461eSJoseph Mingrone static void
20323c602fabSXin LI of10_flow_removed_print(netdissect_options *ndo,
2033*ee67461eSJoseph Mingrone                         const u_char *cp, u_int len _U_)
20348bdc5a62SPatrick Kelsey {
20353c602fabSXin LI 	/* match */
2036*ee67461eSJoseph Mingrone 	of10_match_print(ndo, "\n\t ", cp);
2037*ee67461eSJoseph Mingrone 	cp += OF_MATCH_FIXLEN;
20383c602fabSXin LI 	/* cookie */
2039*ee67461eSJoseph Mingrone 	ND_PRINT("\n\t cookie 0x%016" PRIx64, GET_BE_U_8(cp));
20403c602fabSXin LI 	cp += 8;
20413c602fabSXin LI 	/* priority */
2042*ee67461eSJoseph Mingrone 	if (GET_BE_U_2(cp))
2043*ee67461eSJoseph Mingrone 		ND_PRINT(", priority %u", GET_BE_U_2(cp));
20443c602fabSXin LI 	cp += 2;
20453c602fabSXin LI 	/* reason */
2046*ee67461eSJoseph Mingrone 	ND_PRINT(", reason %s",
2047*ee67461eSJoseph Mingrone 	         tok2str(ofprr_str, "unknown (0x%02x)", GET_U_1(cp)));
20483c602fabSXin LI 	cp += 1;
20493c602fabSXin LI 	/* pad */
20503c602fabSXin LI 	cp += 1;
20513c602fabSXin LI 	/* duration_sec */
2052*ee67461eSJoseph Mingrone 	ND_PRINT(", duration_sec %u", GET_BE_U_4(cp));
20533c602fabSXin LI 	cp += 4;
20543c602fabSXin LI 	/* duration_nsec */
2055*ee67461eSJoseph Mingrone 	ND_PRINT(", duration_nsec %u", GET_BE_U_4(cp));
20563c602fabSXin LI 	cp += 4;
20573c602fabSXin LI 	/* idle_timeout */
2058*ee67461eSJoseph Mingrone 	if (GET_BE_U_2(cp))
2059*ee67461eSJoseph Mingrone 		ND_PRINT(", idle_timeout %u", GET_BE_U_2(cp));
20603c602fabSXin LI 	cp += 2;
20613c602fabSXin LI 	/* pad2 */
20623c602fabSXin LI 	cp += 2;
20633c602fabSXin LI 	/* packet_count */
2064*ee67461eSJoseph Mingrone 	ND_PRINT(", packet_count %" PRIu64, GET_BE_U_8(cp));
20653c602fabSXin LI 	cp += 8;
20663c602fabSXin LI 	/* byte_count */
2067*ee67461eSJoseph Mingrone 	ND_PRINT(", byte_count %" PRIu64, GET_BE_U_8(cp));
2068*ee67461eSJoseph Mingrone }
20693c602fabSXin LI 
2070*ee67461eSJoseph Mingrone /* [OF10] Section 5.4.3 */
2071*ee67461eSJoseph Mingrone static void
2072*ee67461eSJoseph Mingrone of10_port_status_print(netdissect_options *ndo,
2073*ee67461eSJoseph Mingrone                        const u_char *cp, u_int len _U_)
2074*ee67461eSJoseph Mingrone {
2075*ee67461eSJoseph Mingrone 	/* reason */
2076*ee67461eSJoseph Mingrone 	ND_PRINT("\n\t reason %s",
2077*ee67461eSJoseph Mingrone 	         tok2str(ofppr_str, "invalid (0x%02x)", GET_U_1(cp)));
2078*ee67461eSJoseph Mingrone 	cp += 1;
2079*ee67461eSJoseph Mingrone 	/* pad */
2080*ee67461eSJoseph Mingrone 	/* No need to check bounds, more data follows. */
2081*ee67461eSJoseph Mingrone 	cp += 7;
2082*ee67461eSJoseph Mingrone 	/* desc */
2083*ee67461eSJoseph Mingrone 	of10_phy_port_print(ndo, cp);
20843c602fabSXin LI }
20853c602fabSXin LI 
20863c602fabSXin LI /* [OF10] Section 5.4.4 */
2087*ee67461eSJoseph Mingrone static void
20883c602fabSXin LI of10_error_print(netdissect_options *ndo,
2089*ee67461eSJoseph Mingrone                  const u_char *cp, u_int len)
20908bdc5a62SPatrick Kelsey {
2091*ee67461eSJoseph Mingrone 	uint16_t type, code;
20923c602fabSXin LI 	const struct tok *code_str;
20933c602fabSXin LI 
20943c602fabSXin LI 	/* type */
2095*ee67461eSJoseph Mingrone 	type = GET_BE_U_2(cp);
2096*ee67461eSJoseph Mingrone 	OF_FWD(2);
2097*ee67461eSJoseph Mingrone 	ND_PRINT("\n\t type %s", tok2str(ofpet_str, "invalid (0x%04x)", type));
20983c602fabSXin LI 	/* code */
2099*ee67461eSJoseph Mingrone 	code = GET_BE_U_2(cp);
2100*ee67461eSJoseph Mingrone 	OF_FWD(2);
2101*ee67461eSJoseph Mingrone 	code_str = uint2tokary(of10_ofpet2tokary, type);
2102*ee67461eSJoseph Mingrone 	if (code_str != NULL)
2103*ee67461eSJoseph Mingrone 		ND_PRINT(", code %s",
2104*ee67461eSJoseph Mingrone 		         tok2str(code_str, "invalid (0x%04x)", code));
2105*ee67461eSJoseph Mingrone 	else
2106*ee67461eSJoseph Mingrone 		ND_PRINT(", code invalid (0x%04x)", code);
21073c602fabSXin LI 	/* data */
2108*ee67461eSJoseph Mingrone 	of_data_print(ndo, cp, len);
21093c602fabSXin LI }
21103c602fabSXin LI 
2111*ee67461eSJoseph Mingrone static const struct of_msgtypeinfo of10_msgtypeinfo[OFPT_MAX + 1] = {
2112*ee67461eSJoseph Mingrone 	/*
2113*ee67461eSJoseph Mingrone 	 * [OF10] Section 5.5.1
2114*ee67461eSJoseph Mingrone 	 * Variable-size data.
2115*ee67461eSJoseph Mingrone 	 */
21168bdc5a62SPatrick Kelsey 	{
2117*ee67461eSJoseph Mingrone 		"HELLO",                    of_data_print,
2118*ee67461eSJoseph Mingrone 		REQ_MINLEN,                 0
2119*ee67461eSJoseph Mingrone 	},
2120*ee67461eSJoseph Mingrone 	/*
2121*ee67461eSJoseph Mingrone 	 * [OF10] Section 5.4.4
2122*ee67461eSJoseph Mingrone 	 * A fixed-size message body and variable-size data.
2123*ee67461eSJoseph Mingrone 	 */
2124*ee67461eSJoseph Mingrone 	{
2125*ee67461eSJoseph Mingrone 		"ERROR",                    of10_error_print,
2126*ee67461eSJoseph Mingrone 		REQ_MINLEN,                 OF_ERROR_MSG_MINLEN
2127*ee67461eSJoseph Mingrone 	},
2128*ee67461eSJoseph Mingrone 	/*
2129*ee67461eSJoseph Mingrone 	 * [OF10] Section 5.5.2
2130*ee67461eSJoseph Mingrone 	 * Variable-size data.
2131*ee67461eSJoseph Mingrone 	 */
2132*ee67461eSJoseph Mingrone 	{
2133*ee67461eSJoseph Mingrone 		"ECHO_REQUEST",             of_data_print,
2134*ee67461eSJoseph Mingrone 		REQ_MINLEN,                 0
2135*ee67461eSJoseph Mingrone 	},
2136*ee67461eSJoseph Mingrone 	/*
2137*ee67461eSJoseph Mingrone 	 * [OF10] Section 5.5.3
2138*ee67461eSJoseph Mingrone 	 * Variable-size data.
2139*ee67461eSJoseph Mingrone 	 */
2140*ee67461eSJoseph Mingrone 	{
2141*ee67461eSJoseph Mingrone 		"ECHO_REPLY",               of_data_print,
2142*ee67461eSJoseph Mingrone 		REQ_MINLEN,                 0
2143*ee67461eSJoseph Mingrone 	},
2144*ee67461eSJoseph Mingrone 	/*
2145*ee67461eSJoseph Mingrone 	 * [OF10] Section 5.5.4
2146*ee67461eSJoseph Mingrone 	 * A fixed-size message body and variable-size data.
2147*ee67461eSJoseph Mingrone 	 */
2148*ee67461eSJoseph Mingrone 	{
2149*ee67461eSJoseph Mingrone 		"VENDOR",                   of10_vendor_message_print,
2150*ee67461eSJoseph Mingrone 		REQ_MINLEN,                 OF_VENDOR_MINLEN
2151*ee67461eSJoseph Mingrone 	},
2152*ee67461eSJoseph Mingrone 	/*
2153*ee67461eSJoseph Mingrone 	 * [OF10] Section 5.3.1
2154*ee67461eSJoseph Mingrone 	 * No message body.
2155*ee67461eSJoseph Mingrone 	 */
2156*ee67461eSJoseph Mingrone 	{
2157*ee67461eSJoseph Mingrone 		"FEATURES_REQUEST",         NULL,
2158*ee67461eSJoseph Mingrone 		REQ_FIXLEN,                 0
2159*ee67461eSJoseph Mingrone 	},
2160*ee67461eSJoseph Mingrone 	/*
2161*ee67461eSJoseph Mingrone 	 * [OF10] Section 5.3.1
2162*ee67461eSJoseph Mingrone 	 * A fixed-size message body and n * fixed-size data units.
2163*ee67461eSJoseph Mingrone 	 */
2164*ee67461eSJoseph Mingrone 	{
2165*ee67461eSJoseph Mingrone 		"FEATURES_REPLY",           of10_features_reply_print,
2166*ee67461eSJoseph Mingrone 		REQ_MINLEN,                 OF_FEATURES_REPLY_MINLEN
2167*ee67461eSJoseph Mingrone 	},
2168*ee67461eSJoseph Mingrone 	/*
2169*ee67461eSJoseph Mingrone 	 * [OF10] Section 5.3.2
2170*ee67461eSJoseph Mingrone 	 * No message body.
2171*ee67461eSJoseph Mingrone 	 */
2172*ee67461eSJoseph Mingrone 	{
2173*ee67461eSJoseph Mingrone 		"GET_CONFIG_REQUEST",       NULL,
2174*ee67461eSJoseph Mingrone 		REQ_FIXLEN,                 0
2175*ee67461eSJoseph Mingrone 	},
2176*ee67461eSJoseph Mingrone 	/*
2177*ee67461eSJoseph Mingrone 	 * [OF10] Section 5.3.2
2178*ee67461eSJoseph Mingrone 	 * A fixed-size message body.
2179*ee67461eSJoseph Mingrone 	 */
2180*ee67461eSJoseph Mingrone 	{
2181*ee67461eSJoseph Mingrone 		"GET_CONFIG_REPLY",         of10_switch_config_msg_print,
2182*ee67461eSJoseph Mingrone 		REQ_FIXLEN,                 OF_SWITCH_CONFIG_FIXLEN
2183*ee67461eSJoseph Mingrone 	},
2184*ee67461eSJoseph Mingrone 	/*
2185*ee67461eSJoseph Mingrone 	 * [OF10] Section 5.3.2
2186*ee67461eSJoseph Mingrone 	 * A fixed-size message body.
2187*ee67461eSJoseph Mingrone 	 */
2188*ee67461eSJoseph Mingrone 	{
2189*ee67461eSJoseph Mingrone 		"SET_CONFIG",               of10_switch_config_msg_print,
2190*ee67461eSJoseph Mingrone 		REQ_FIXLEN,                 OF_SWITCH_CONFIG_FIXLEN
2191*ee67461eSJoseph Mingrone 	},
2192*ee67461eSJoseph Mingrone 	/*
2193*ee67461eSJoseph Mingrone 	 * [OF10] Section 5.4.1
2194*ee67461eSJoseph Mingrone 	 * A fixed-size message body and variable-size data.
2195*ee67461eSJoseph Mingrone 	 * (The 2 mock octets count in OF_PACKET_IN_MINLEN only.)
2196*ee67461eSJoseph Mingrone 	 */
2197*ee67461eSJoseph Mingrone 	{
2198*ee67461eSJoseph Mingrone 		"PACKET_IN",                of10_packet_in_print,
2199*ee67461eSJoseph Mingrone 		REQ_MINLEN,                 OF_PACKET_IN_MINLEN - 2
2200*ee67461eSJoseph Mingrone 	},
2201*ee67461eSJoseph Mingrone 	/*
2202*ee67461eSJoseph Mingrone 	 * [OF10] Section 5.4.2
2203*ee67461eSJoseph Mingrone 	 * A fixed-size message body.
2204*ee67461eSJoseph Mingrone 	 */
2205*ee67461eSJoseph Mingrone 	{
2206*ee67461eSJoseph Mingrone 		"FLOW_REMOVED",             of10_flow_removed_print,
2207*ee67461eSJoseph Mingrone 		REQ_FIXLEN,                 OF_FLOW_REMOVED_FIXLEN
2208*ee67461eSJoseph Mingrone 	},
2209*ee67461eSJoseph Mingrone 	/*
2210*ee67461eSJoseph Mingrone 	 * [OF10] Section 5.4.3
2211*ee67461eSJoseph Mingrone 	 * A fixed-size message body.
2212*ee67461eSJoseph Mingrone 	 */
2213*ee67461eSJoseph Mingrone 	{
2214*ee67461eSJoseph Mingrone 		"PORT_STATUS",              of10_port_status_print,
2215*ee67461eSJoseph Mingrone 		REQ_FIXLEN,                 OF_PORT_STATUS_FIXLEN
2216*ee67461eSJoseph Mingrone 	},
2217*ee67461eSJoseph Mingrone 	/*
2218*ee67461eSJoseph Mingrone 	 * [OF10] Section 5.3.6
2219*ee67461eSJoseph Mingrone 	 * A fixed-size message body, n * variable-size data units and
2220*ee67461eSJoseph Mingrone 	 * variable-size data.
2221*ee67461eSJoseph Mingrone 	 */
2222*ee67461eSJoseph Mingrone 	{
2223*ee67461eSJoseph Mingrone 		"PACKET_OUT",               of10_packet_out_print,
2224*ee67461eSJoseph Mingrone 		REQ_MINLEN,                 OF_PACKET_OUT_MINLEN
2225*ee67461eSJoseph Mingrone 	},
2226*ee67461eSJoseph Mingrone 	/*
2227*ee67461eSJoseph Mingrone 	 * [OF10] Section 5.3.3
2228*ee67461eSJoseph Mingrone 	 * A fixed-size message body and n * variable-size data units.
2229*ee67461eSJoseph Mingrone 	 */
2230*ee67461eSJoseph Mingrone 	{
2231*ee67461eSJoseph Mingrone 		"FLOW_MOD",                 of10_flow_mod_print,
2232*ee67461eSJoseph Mingrone 		REQ_MINLEN,                 OF_FLOW_MOD_MINLEN
2233*ee67461eSJoseph Mingrone 	},
2234*ee67461eSJoseph Mingrone 	/*
2235*ee67461eSJoseph Mingrone 	 * [OF10] Section 5.3.3
2236*ee67461eSJoseph Mingrone 	 * A fixed-size message body.
2237*ee67461eSJoseph Mingrone 	 */
2238*ee67461eSJoseph Mingrone 	{
2239*ee67461eSJoseph Mingrone 		"PORT_MOD",                 of10_port_mod_print,
2240*ee67461eSJoseph Mingrone 		REQ_FIXLEN,                 OF_PORT_MOD_FIXLEN
2241*ee67461eSJoseph Mingrone 	},
2242*ee67461eSJoseph Mingrone 	/*
2243*ee67461eSJoseph Mingrone 	 * [OF10] Section 5.3.5
2244*ee67461eSJoseph Mingrone 	 * A fixed-size message body and possibly more data of varying size
2245*ee67461eSJoseph Mingrone 	 * and structure.
2246*ee67461eSJoseph Mingrone 	 */
2247*ee67461eSJoseph Mingrone 	{
2248*ee67461eSJoseph Mingrone 		"STATS_REQUEST",            of10_stats_request_print,
2249*ee67461eSJoseph Mingrone 		REQ_MINLEN,                 OF_STATS_REQUEST_MINLEN
2250*ee67461eSJoseph Mingrone 	},
2251*ee67461eSJoseph Mingrone 	/*
2252*ee67461eSJoseph Mingrone 	 * [OF10] Section 5.3.5
2253*ee67461eSJoseph Mingrone 	 * A fixed-size message body and possibly more data of varying size
2254*ee67461eSJoseph Mingrone 	 * and structure.
2255*ee67461eSJoseph Mingrone 	 */
2256*ee67461eSJoseph Mingrone 	{
2257*ee67461eSJoseph Mingrone 		"STATS_REPLY",              of10_stats_reply_print,
2258*ee67461eSJoseph Mingrone 		REQ_MINLEN,                 OF_STATS_REPLY_MINLEN
2259*ee67461eSJoseph Mingrone 	},
2260*ee67461eSJoseph Mingrone 	/*
2261*ee67461eSJoseph Mingrone 	 * [OF10] Section 5.3.7
2262*ee67461eSJoseph Mingrone 	 * No message body.
2263*ee67461eSJoseph Mingrone 	 */
2264*ee67461eSJoseph Mingrone 	{
2265*ee67461eSJoseph Mingrone 		"BARRIER_REQUEST",          NULL,
2266*ee67461eSJoseph Mingrone 		REQ_FIXLEN,                 0
2267*ee67461eSJoseph Mingrone 	},
2268*ee67461eSJoseph Mingrone 	/*
2269*ee67461eSJoseph Mingrone 	 * [OF10] Section 5.3.7
2270*ee67461eSJoseph Mingrone 	 * No message body.
2271*ee67461eSJoseph Mingrone 	 */
2272*ee67461eSJoseph Mingrone 	{
2273*ee67461eSJoseph Mingrone 		"BARRIER_REPLY",            NULL,
2274*ee67461eSJoseph Mingrone 		REQ_FIXLEN,                 0
2275*ee67461eSJoseph Mingrone 	},
2276*ee67461eSJoseph Mingrone 	/*
2277*ee67461eSJoseph Mingrone 	 * [OF10] Section 5.3.4
2278*ee67461eSJoseph Mingrone 	 * A fixed-size message body.
2279*ee67461eSJoseph Mingrone 	 */
2280*ee67461eSJoseph Mingrone 	{
2281*ee67461eSJoseph Mingrone 		"QUEUE_GET_CONFIG_REQUEST", of10_queue_get_config_request_print,
2282*ee67461eSJoseph Mingrone 		REQ_FIXLEN,                 OF_QUEUE_GET_CONFIG_REQUEST_FIXLEN
2283*ee67461eSJoseph Mingrone 	},
2284*ee67461eSJoseph Mingrone 	/*
2285*ee67461eSJoseph Mingrone 	 * [OF10] Section 5.3.4
2286*ee67461eSJoseph Mingrone 	 * A fixed-size message body and n * variable-size data units.
2287*ee67461eSJoseph Mingrone 	 */
2288*ee67461eSJoseph Mingrone 	{
2289*ee67461eSJoseph Mingrone 		"QUEUE_GET_CONFIG_REPLY",   of10_queue_get_config_reply_print,
2290*ee67461eSJoseph Mingrone 		REQ_MINLEN,                 OF_QUEUE_GET_CONFIG_REPLY_MINLEN
2291*ee67461eSJoseph Mingrone 	},
2292*ee67461eSJoseph Mingrone };
22933c602fabSXin LI 
2294*ee67461eSJoseph Mingrone const struct of_msgtypeinfo *
2295*ee67461eSJoseph Mingrone of10_identify_msgtype(const uint8_t type)
2296*ee67461eSJoseph Mingrone {
2297*ee67461eSJoseph Mingrone 	return type <= OFPT_MAX ? &of10_msgtypeinfo[type] : NULL;
22983c602fabSXin LI }
2299