1411677aeSAaron LI /*
2411677aeSAaron LI  * This module implements decoding of OpenFlow protocol version 1.0 (wire
3411677aeSAaron LI  * protocol 0x01). The decoder implements terse (default), detailed (-v) and
4411677aeSAaron LI  * full (-vv) output formats and, as much as each format implies, detects and
5411677aeSAaron LI  * tries to work around sizing anomalies inside the messages. The decoder marks
6411677aeSAaron LI  * up bogus values of selected message fields and decodes partially captured
7411677aeSAaron LI  * messages up to the snapshot end. It is based on the specification below:
8411677aeSAaron LI  *
9*ed775ee7SAntonio Huete Jimenez  * [OF10] https://www.opennetworking.org/wp-content/uploads/2013/04/openflow-spec-v1.0.0.pdf
10411677aeSAaron LI  *
11*ed775ee7SAntonio Huete Jimenez  * Most functions in this file take the following arguments:
12411677aeSAaron LI  * * cp -- the pointer to the first octet to decode
13*ed775ee7SAntonio Huete Jimenez  * * len -- the declared length of the structure to decode
14*ed775ee7SAntonio Huete Jimenez  * The convention is that a printer function returns iff the given structure is
15*ed775ee7SAntonio Huete Jimenez  * completely within the packet buffer; otherwise it processes the part that is
16*ed775ee7SAntonio Huete Jimenez  * within the buffer, sooner of later takes the "truncated packet" shortcut via
17*ed775ee7SAntonio Huete Jimenez  * longjmp() and never returns. With that in mind, the function may return
18*ed775ee7SAntonio Huete Jimenez  * without printing the structure completely if it is invalid or the ndo_vflag
19*ed775ee7SAntonio Huete Jimenez  * value is not high enough. This way the calling function can try to decode
20*ed775ee7SAntonio Huete Jimenez  * the next data item.
21411677aeSAaron LI  *
22411677aeSAaron LI  * Decoding of Ethernet frames nested in OFPT_PACKET_IN and OFPT_PACKET_OUT
23411677aeSAaron LI  * messages is done only when the verbosity level set by command-line argument
24411677aeSAaron LI  * is "-vvv" or higher. In that case the verbosity level is temporarily
25411677aeSAaron LI  * decremented by 3 during the nested frame decoding. For example, running
26411677aeSAaron LI  * tcpdump with "-vvvv" will do full decoding of OpenFlow and "-v" decoding of
27411677aeSAaron LI  * the nested frames.
28411677aeSAaron LI  *
29411677aeSAaron LI  * Partial decoding of Big Switch Networks vendor extensions is done after the
30411677aeSAaron LI  * oftest (OpenFlow Testing Framework) and Loxigen (library generator) source
31411677aeSAaron LI  * code.
32411677aeSAaron LI  *
33411677aeSAaron LI  *
34411677aeSAaron LI  * Copyright (c) 2013 The TCPDUMP project
35411677aeSAaron LI  * All rights reserved.
36411677aeSAaron LI  *
37411677aeSAaron LI  * Redistribution and use in source and binary forms, with or without
38411677aeSAaron LI  * modification, are permitted provided that the following conditions
39411677aeSAaron LI  * are met:
40411677aeSAaron LI  * 1. Redistributions of source code must retain the above copyright
41411677aeSAaron LI  *    notice, this list of conditions and the following disclaimer.
42411677aeSAaron LI  * 2. Redistributions in binary form must reproduce the above copyright
43411677aeSAaron LI  *    notice, this list of conditions and the following disclaimer in the
44411677aeSAaron LI  *    documentation and/or other materials provided with the distribution.
45411677aeSAaron LI  *
46411677aeSAaron LI  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
47411677aeSAaron LI  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
48411677aeSAaron LI  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
49411677aeSAaron LI  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
50411677aeSAaron LI  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
51411677aeSAaron LI  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
52411677aeSAaron LI  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
53411677aeSAaron LI  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
54411677aeSAaron LI  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55411677aeSAaron LI  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
56411677aeSAaron LI  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
57411677aeSAaron LI  * POSSIBILITY OF SUCH DAMAGE.
58411677aeSAaron LI  */
59411677aeSAaron LI 
60411677aeSAaron LI /* \summary: OpenFlow protocol version 1.0 printer */
61411677aeSAaron LI 
62411677aeSAaron LI #ifdef HAVE_CONFIG_H
63*ed775ee7SAntonio Huete Jimenez #include <config.h>
64411677aeSAaron LI #endif
65411677aeSAaron LI 
66*ed775ee7SAntonio Huete Jimenez #include "netdissect-stdinc.h"
67411677aeSAaron LI 
68*ed775ee7SAntonio Huete Jimenez #define ND_LONGJMP_FROM_TCHECK
69411677aeSAaron LI #include "netdissect.h"
70411677aeSAaron LI #include "extract.h"
71411677aeSAaron LI #include "addrtoname.h"
72411677aeSAaron LI #include "ethertype.h"
73411677aeSAaron LI #include "ipproto.h"
74411677aeSAaron LI #include "oui.h"
75411677aeSAaron LI #include "openflow.h"
76411677aeSAaron LI 
77411677aeSAaron LI 
78411677aeSAaron LI #define OFPT_HELLO                    0x00
79411677aeSAaron LI #define OFPT_ERROR                    0x01
80411677aeSAaron LI #define OFPT_ECHO_REQUEST             0x02
81411677aeSAaron LI #define OFPT_ECHO_REPLY               0x03
82411677aeSAaron LI #define OFPT_VENDOR                   0x04
83411677aeSAaron LI #define OFPT_FEATURES_REQUEST         0x05
84411677aeSAaron LI #define OFPT_FEATURES_REPLY           0x06
85411677aeSAaron LI #define OFPT_GET_CONFIG_REQUEST       0x07
86411677aeSAaron LI #define OFPT_GET_CONFIG_REPLY         0x08
87411677aeSAaron LI #define OFPT_SET_CONFIG               0x09
88411677aeSAaron LI #define OFPT_PACKET_IN                0x0a
89411677aeSAaron LI #define OFPT_FLOW_REMOVED             0x0b
90411677aeSAaron LI #define OFPT_PORT_STATUS              0x0c
91411677aeSAaron LI #define OFPT_PACKET_OUT               0x0d
92411677aeSAaron LI #define OFPT_FLOW_MOD                 0x0e
93411677aeSAaron LI #define OFPT_PORT_MOD                 0x0f
94411677aeSAaron LI #define OFPT_STATS_REQUEST            0x10
95411677aeSAaron LI #define OFPT_STATS_REPLY              0x11
96411677aeSAaron LI #define OFPT_BARRIER_REQUEST          0x12
97411677aeSAaron LI #define OFPT_BARRIER_REPLY            0x13
98411677aeSAaron LI #define OFPT_QUEUE_GET_CONFIG_REQUEST 0x14
99411677aeSAaron LI #define OFPT_QUEUE_GET_CONFIG_REPLY   0x15
100*ed775ee7SAntonio Huete Jimenez #define OFPT_MAX                      OFPT_QUEUE_GET_CONFIG_REPLY
101411677aeSAaron LI 
102*ed775ee7SAntonio Huete Jimenez #define OFPPC_PORT_DOWN    (1U <<0)
103*ed775ee7SAntonio Huete Jimenez #define OFPPC_NO_STP       (1U <<1)
104*ed775ee7SAntonio Huete Jimenez #define OFPPC_NO_RECV      (1U <<2)
105*ed775ee7SAntonio Huete Jimenez #define OFPPC_NO_RECV_STP  (1U <<3)
106*ed775ee7SAntonio Huete Jimenez #define OFPPC_NO_FLOOD     (1U <<4)
107*ed775ee7SAntonio Huete Jimenez #define OFPPC_NO_FWD       (1U <<5)
108*ed775ee7SAntonio Huete Jimenez #define OFPPC_NO_PACKET_IN (1U <<6)
109411677aeSAaron LI static const struct tok ofppc_bm[] = {
110411677aeSAaron LI 	{ OFPPC_PORT_DOWN,    "PORT_DOWN"    },
111411677aeSAaron LI 	{ OFPPC_NO_STP,       "NO_STP"       },
112411677aeSAaron LI 	{ OFPPC_NO_RECV,      "NO_RECV"      },
113411677aeSAaron LI 	{ OFPPC_NO_RECV_STP,  "NO_RECV_STP"  },
114411677aeSAaron LI 	{ OFPPC_NO_FLOOD,     "NO_FLOOD"     },
115411677aeSAaron LI 	{ OFPPC_NO_FWD,       "NO_FWD"       },
116411677aeSAaron LI 	{ OFPPC_NO_PACKET_IN, "NO_PACKET_IN" },
117411677aeSAaron LI 	{ 0, NULL }
118411677aeSAaron LI };
119411677aeSAaron LI #define OFPPC_U (~(OFPPC_PORT_DOWN | OFPPC_NO_STP | OFPPC_NO_RECV | \
120411677aeSAaron LI                    OFPPC_NO_RECV_STP | OFPPC_NO_FLOOD | OFPPC_NO_FWD | \
121411677aeSAaron LI                    OFPPC_NO_PACKET_IN))
122411677aeSAaron LI 
123*ed775ee7SAntonio Huete Jimenez /*
124*ed775ee7SAntonio Huete Jimenez  * [OF10] lists all FPPS_ constants in one enum, but they mean a 1-bit bitmap
125*ed775ee7SAntonio Huete Jimenez  * in the least significant octet and a 2-bit code point in the next octet.
126*ed775ee7SAntonio Huete Jimenez  * Remember to mix or to separate these two parts as the context requires.
127*ed775ee7SAntonio Huete Jimenez  */
128*ed775ee7SAntonio Huete Jimenez #define OFPPS_LINK_DOWN   (1U << 0) /* bitmap             */
129*ed775ee7SAntonio Huete Jimenez #define OFPPS_STP_LISTEN  (0U << 8) /* code point         */
130*ed775ee7SAntonio Huete Jimenez #define OFPPS_STP_LEARN   (1U << 8) /* code point         */
131*ed775ee7SAntonio Huete Jimenez #define OFPPS_STP_FORWARD (2U << 8) /* code point         */
132*ed775ee7SAntonio Huete Jimenez #define OFPPS_STP_BLOCK   (3U << 8) /* code point         */
133*ed775ee7SAntonio Huete Jimenez #define OFPPS_STP_MASK    (3U << 8) /* code point bitmask */
134*ed775ee7SAntonio Huete Jimenez static const struct tok ofpps_stp_str[] = {
135411677aeSAaron LI 	{ OFPPS_STP_LISTEN,  "STP_LISTEN"  },
136411677aeSAaron LI 	{ OFPPS_STP_LEARN,   "STP_LEARN"   },
137411677aeSAaron LI 	{ OFPPS_STP_FORWARD, "STP_FORWARD" },
138411677aeSAaron LI 	{ OFPPS_STP_BLOCK,   "STP_BLOCK"   },
139411677aeSAaron LI 	{ 0, NULL }
140411677aeSAaron LI };
141411677aeSAaron LI #define OFPPS_U (~(OFPPS_LINK_DOWN | OFPPS_STP_LISTEN | OFPPS_STP_LEARN | \
142411677aeSAaron LI                    OFPPS_STP_FORWARD | OFPPS_STP_BLOCK))
143411677aeSAaron LI 
144*ed775ee7SAntonio Huete Jimenez #define OFPP_MAX        0xff00U
145*ed775ee7SAntonio Huete Jimenez #define OFPP_IN_PORT    0xfff8U
146*ed775ee7SAntonio Huete Jimenez #define OFPP_TABLE      0xfff9U
147*ed775ee7SAntonio Huete Jimenez #define OFPP_NORMAL     0xfffaU
148*ed775ee7SAntonio Huete Jimenez #define OFPP_FLOOD      0xfffbU
149*ed775ee7SAntonio Huete Jimenez #define OFPP_ALL        0xfffcU
150*ed775ee7SAntonio Huete Jimenez #define OFPP_CONTROLLER 0xfffdU
151*ed775ee7SAntonio Huete Jimenez #define OFPP_LOCAL      0xfffeU
152*ed775ee7SAntonio Huete Jimenez #define OFPP_NONE       0xffffU
153411677aeSAaron LI static const struct tok ofpp_str[] = {
154411677aeSAaron LI 	{ OFPP_MAX,        "MAX"        },
155411677aeSAaron LI 	{ OFPP_IN_PORT,    "IN_PORT"    },
156411677aeSAaron LI 	{ OFPP_TABLE,      "TABLE"      },
157411677aeSAaron LI 	{ OFPP_NORMAL,     "NORMAL"     },
158411677aeSAaron LI 	{ OFPP_FLOOD,      "FLOOD"      },
159411677aeSAaron LI 	{ OFPP_ALL,        "ALL"        },
160411677aeSAaron LI 	{ OFPP_CONTROLLER, "CONTROLLER" },
161411677aeSAaron LI 	{ OFPP_LOCAL,      "LOCAL"      },
162411677aeSAaron LI 	{ OFPP_NONE,       "NONE"       },
163411677aeSAaron LI 	{ 0, NULL }
164411677aeSAaron LI };
165411677aeSAaron LI 
166*ed775ee7SAntonio Huete Jimenez #define OFPPF_10MB_HD    (1U << 0)
167*ed775ee7SAntonio Huete Jimenez #define OFPPF_10MB_FD    (1U << 1)
168*ed775ee7SAntonio Huete Jimenez #define OFPPF_100MB_HD   (1U << 2)
169*ed775ee7SAntonio Huete Jimenez #define OFPPF_100MB_FD   (1U << 3)
170*ed775ee7SAntonio Huete Jimenez #define OFPPF_1GB_HD     (1U << 4)
171*ed775ee7SAntonio Huete Jimenez #define OFPPF_1GB_FD     (1U << 5)
172*ed775ee7SAntonio Huete Jimenez #define OFPPF_10GB_FD    (1U << 6)
173*ed775ee7SAntonio Huete Jimenez #define OFPPF_COPPER     (1U << 7)
174*ed775ee7SAntonio Huete Jimenez #define OFPPF_FIBER      (1U << 8)
175*ed775ee7SAntonio Huete Jimenez #define OFPPF_AUTONEG    (1U << 9)
176*ed775ee7SAntonio Huete Jimenez #define OFPPF_PAUSE      (1U <<10)
177*ed775ee7SAntonio Huete Jimenez #define OFPPF_PAUSE_ASYM (1U <<11)
178411677aeSAaron LI static const struct tok ofppf_bm[] = {
179411677aeSAaron LI 	{ OFPPF_10MB_HD,    "10MB_HD"    },
180411677aeSAaron LI 	{ OFPPF_10MB_FD,    "10MB_FD"    },
181411677aeSAaron LI 	{ OFPPF_100MB_HD,   "100MB_HD"   },
182411677aeSAaron LI 	{ OFPPF_100MB_FD,   "100MB_FD"   },
183411677aeSAaron LI 	{ OFPPF_1GB_HD,     "1GB_HD"     },
184411677aeSAaron LI 	{ OFPPF_1GB_FD,     "1GB_FD"     },
185411677aeSAaron LI 	{ OFPPF_10GB_FD,    "10GB_FD"    },
186411677aeSAaron LI 	{ OFPPF_COPPER,     "COPPER"     },
187411677aeSAaron LI 	{ OFPPF_FIBER,      "FIBER"      },
188411677aeSAaron LI 	{ OFPPF_AUTONEG,    "AUTONEG"    },
189411677aeSAaron LI 	{ OFPPF_PAUSE,      "PAUSE"      },
190411677aeSAaron LI 	{ OFPPF_PAUSE_ASYM, "PAUSE_ASYM" },
191411677aeSAaron LI 	{ 0, NULL }
192411677aeSAaron LI };
193411677aeSAaron LI #define OFPPF_U (~(OFPPF_10MB_HD | OFPPF_10MB_FD | OFPPF_100MB_HD | \
194411677aeSAaron LI                    OFPPF_100MB_FD | OFPPF_1GB_HD | OFPPF_1GB_FD | \
195411677aeSAaron LI                    OFPPF_10GB_FD | OFPPF_COPPER | OFPPF_FIBER | \
196411677aeSAaron LI                    OFPPF_AUTONEG | OFPPF_PAUSE | OFPPF_PAUSE_ASYM))
197411677aeSAaron LI 
198411677aeSAaron LI #define OFPQT_NONE     0x0000
199411677aeSAaron LI #define OFPQT_MIN_RATE 0x0001
200411677aeSAaron LI static const struct tok ofpqt_str[] = {
201411677aeSAaron LI 	{ OFPQT_NONE,     "NONE"     },
202411677aeSAaron LI 	{ OFPQT_MIN_RATE, "MIN_RATE" },
203411677aeSAaron LI 	{ 0, NULL }
204411677aeSAaron LI };
205411677aeSAaron LI 
206*ed775ee7SAntonio Huete Jimenez #define OFPFW_IN_PORT      (1U <<0)
207*ed775ee7SAntonio Huete Jimenez #define OFPFW_DL_VLAN      (1U <<1)
208*ed775ee7SAntonio Huete Jimenez #define OFPFW_DL_SRC       (1U <<2)
209*ed775ee7SAntonio Huete Jimenez #define OFPFW_DL_DST       (1U <<3)
210*ed775ee7SAntonio Huete Jimenez #define OFPFW_DL_TYPE      (1U <<4)
211*ed775ee7SAntonio Huete Jimenez #define OFPFW_NW_PROTO     (1U <<5)
212*ed775ee7SAntonio Huete Jimenez #define OFPFW_TP_SRC       (1U <<6)
213*ed775ee7SAntonio Huete Jimenez #define OFPFW_TP_DST       (1U <<7)
214411677aeSAaron LI #define OFPFW_NW_SRC_SHIFT 8
215411677aeSAaron LI #define OFPFW_NW_SRC_BITS  6
216*ed775ee7SAntonio Huete Jimenez #define OFPFW_NW_SRC_MASK  (((1U <<OFPFW_NW_SRC_BITS) - 1) << OFPFW_NW_SRC_SHIFT)
217411677aeSAaron LI #define OFPFW_NW_DST_SHIFT 14
218411677aeSAaron LI #define OFPFW_NW_DST_BITS  6
219*ed775ee7SAntonio Huete Jimenez #define OFPFW_NW_DST_MASK  (((1U <<OFPFW_NW_DST_BITS) - 1) << OFPFW_NW_DST_SHIFT)
220*ed775ee7SAntonio Huete Jimenez #define OFPFW_DL_VLAN_PCP  (1U <<20)
221*ed775ee7SAntonio Huete Jimenez #define OFPFW_NW_TOS       (1U <<21)
222*ed775ee7SAntonio Huete Jimenez #define OFPFW_ALL          ((1U <<22) - 1)
223411677aeSAaron LI static const struct tok ofpfw_bm[] = {
224411677aeSAaron LI 	{ OFPFW_IN_PORT,     "IN_PORT"     },
225411677aeSAaron LI 	{ OFPFW_DL_VLAN,     "DL_VLAN"     },
226411677aeSAaron LI 	{ OFPFW_DL_SRC,      "DL_SRC"      },
227411677aeSAaron LI 	{ OFPFW_DL_DST,      "DL_DST"      },
228411677aeSAaron LI 	{ OFPFW_DL_TYPE,     "DL_TYPE"     },
229411677aeSAaron LI 	{ OFPFW_NW_PROTO,    "NW_PROTO"    },
230411677aeSAaron LI 	{ OFPFW_TP_SRC,      "TP_SRC"      },
231411677aeSAaron LI 	{ OFPFW_TP_DST,      "TP_DST"      },
232411677aeSAaron LI 	{ OFPFW_DL_VLAN_PCP, "DL_VLAN_PCP" },
233411677aeSAaron LI 	{ OFPFW_NW_TOS,      "NW_TOS"      },
234411677aeSAaron LI 	{ 0, NULL }
235411677aeSAaron LI };
236411677aeSAaron LI /* The above array does not include bits 8~13 (OFPFW_NW_SRC_*) and 14~19
237411677aeSAaron LI  * (OFPFW_NW_DST_*), which are not a part of the bitmap and require decoding
238411677aeSAaron LI  * other than that of tok2str(). The macro below includes these bits such that
239411677aeSAaron LI  * they are not reported as bogus in the decoding. */
240411677aeSAaron LI #define OFPFW_U (~(OFPFW_ALL))
241411677aeSAaron LI 
242*ed775ee7SAntonio Huete Jimenez #define OFPAT_OUTPUT       0x0000U
243*ed775ee7SAntonio Huete Jimenez #define OFPAT_SET_VLAN_VID 0x0001U
244*ed775ee7SAntonio Huete Jimenez #define OFPAT_SET_VLAN_PCP 0x0002U
245*ed775ee7SAntonio Huete Jimenez #define OFPAT_STRIP_VLAN   0x0003U
246*ed775ee7SAntonio Huete Jimenez #define OFPAT_SET_DL_SRC   0x0004U
247*ed775ee7SAntonio Huete Jimenez #define OFPAT_SET_DL_DST   0x0005U
248*ed775ee7SAntonio Huete Jimenez #define OFPAT_SET_NW_SRC   0x0006U
249*ed775ee7SAntonio Huete Jimenez #define OFPAT_SET_NW_DST   0x0007U
250*ed775ee7SAntonio Huete Jimenez #define OFPAT_SET_NW_TOS   0x0008U
251*ed775ee7SAntonio Huete Jimenez #define OFPAT_SET_TP_SRC   0x0009U
252*ed775ee7SAntonio Huete Jimenez #define OFPAT_SET_TP_DST   0x000aU
253*ed775ee7SAntonio Huete Jimenez #define OFPAT_ENQUEUE      0x000bU
254*ed775ee7SAntonio Huete Jimenez #define OFPAT_VENDOR       0xffffU
255411677aeSAaron LI static const struct tok ofpat_str[] = {
256411677aeSAaron LI 	{ OFPAT_OUTPUT,       "OUTPUT"       },
257411677aeSAaron LI 	{ OFPAT_SET_VLAN_VID, "SET_VLAN_VID" },
258411677aeSAaron LI 	{ OFPAT_SET_VLAN_PCP, "SET_VLAN_PCP" },
259411677aeSAaron LI 	{ OFPAT_STRIP_VLAN,   "STRIP_VLAN"   },
260411677aeSAaron LI 	{ OFPAT_SET_DL_SRC,   "SET_DL_SRC"   },
261411677aeSAaron LI 	{ OFPAT_SET_DL_DST,   "SET_DL_DST"   },
262411677aeSAaron LI 	{ OFPAT_SET_NW_SRC,   "SET_NW_SRC"   },
263411677aeSAaron LI 	{ OFPAT_SET_NW_DST,   "SET_NW_DST"   },
264411677aeSAaron LI 	{ OFPAT_SET_NW_TOS,   "SET_NW_TOS"   },
265411677aeSAaron LI 	{ OFPAT_SET_TP_SRC,   "SET_TP_SRC"   },
266411677aeSAaron LI 	{ OFPAT_SET_TP_DST,   "SET_TP_DST"   },
267411677aeSAaron LI 	{ OFPAT_ENQUEUE,      "ENQUEUE"      },
268411677aeSAaron LI 	{ OFPAT_VENDOR,       "VENDOR"       },
269411677aeSAaron LI 	{ 0, NULL }
270411677aeSAaron LI };
271411677aeSAaron LI 
272411677aeSAaron LI /* bit-shifted, w/o vendor action */
273411677aeSAaron LI static const struct tok ofpat_bm[] = {
274*ed775ee7SAntonio Huete Jimenez 	{ 1U <<OFPAT_OUTPUT,       "OUTPUT"       },
275*ed775ee7SAntonio Huete Jimenez 	{ 1U <<OFPAT_SET_VLAN_VID, "SET_VLAN_VID" },
276*ed775ee7SAntonio Huete Jimenez 	{ 1U <<OFPAT_SET_VLAN_PCP, "SET_VLAN_PCP" },
277*ed775ee7SAntonio Huete Jimenez 	{ 1U <<OFPAT_STRIP_VLAN,   "STRIP_VLAN"   },
278*ed775ee7SAntonio Huete Jimenez 	{ 1U <<OFPAT_SET_DL_SRC,   "SET_DL_SRC"   },
279*ed775ee7SAntonio Huete Jimenez 	{ 1U <<OFPAT_SET_DL_DST,   "SET_DL_DST"   },
280*ed775ee7SAntonio Huete Jimenez 	{ 1U <<OFPAT_SET_NW_SRC,   "SET_NW_SRC"   },
281*ed775ee7SAntonio Huete Jimenez 	{ 1U <<OFPAT_SET_NW_DST,   "SET_NW_DST"   },
282*ed775ee7SAntonio Huete Jimenez 	{ 1U <<OFPAT_SET_NW_TOS,   "SET_NW_TOS"   },
283*ed775ee7SAntonio Huete Jimenez 	{ 1U <<OFPAT_SET_TP_SRC,   "SET_TP_SRC"   },
284*ed775ee7SAntonio Huete Jimenez 	{ 1U <<OFPAT_SET_TP_DST,   "SET_TP_DST"   },
285*ed775ee7SAntonio Huete Jimenez 	{ 1U <<OFPAT_ENQUEUE,      "ENQUEUE"      },
286411677aeSAaron LI 	{ 0, NULL }
287411677aeSAaron LI };
288*ed775ee7SAntonio Huete Jimenez #define OFPAT_U (~(1U <<OFPAT_OUTPUT | 1U <<OFPAT_SET_VLAN_VID | \
289*ed775ee7SAntonio Huete Jimenez                    1U <<OFPAT_SET_VLAN_PCP | 1U <<OFPAT_STRIP_VLAN | \
290*ed775ee7SAntonio Huete Jimenez                    1U <<OFPAT_SET_DL_SRC | 1U <<OFPAT_SET_DL_DST | \
291*ed775ee7SAntonio Huete Jimenez                    1U <<OFPAT_SET_NW_SRC | 1U <<OFPAT_SET_NW_DST | \
292*ed775ee7SAntonio Huete Jimenez                    1U <<OFPAT_SET_NW_TOS | 1U <<OFPAT_SET_TP_SRC | \
293*ed775ee7SAntonio Huete Jimenez                    1U <<OFPAT_SET_TP_DST | 1U <<OFPAT_ENQUEUE))
294411677aeSAaron LI 
295*ed775ee7SAntonio Huete Jimenez #define OFPC_FLOW_STATS   (1U <<0)
296*ed775ee7SAntonio Huete Jimenez #define OFPC_TABLE_STATS  (1U <<1)
297*ed775ee7SAntonio Huete Jimenez #define OFPC_PORT_STATS   (1U <<2)
298*ed775ee7SAntonio Huete Jimenez #define OFPC_STP          (1U <<3)
299*ed775ee7SAntonio Huete Jimenez #define OFPC_RESERVED     (1U <<4)
300*ed775ee7SAntonio Huete Jimenez #define OFPC_IP_REASM     (1U <<5)
301*ed775ee7SAntonio Huete Jimenez #define OFPC_QUEUE_STATS  (1U <<6)
302*ed775ee7SAntonio Huete Jimenez #define OFPC_ARP_MATCH_IP (1U <<7)
303411677aeSAaron LI static const struct tok ofp_capabilities_bm[] = {
304411677aeSAaron LI 	{ OFPC_FLOW_STATS,   "FLOW_STATS"   },
305411677aeSAaron LI 	{ OFPC_TABLE_STATS,  "TABLE_STATS"  },
306411677aeSAaron LI 	{ OFPC_PORT_STATS,   "PORT_STATS"   },
307411677aeSAaron LI 	{ OFPC_STP,          "STP"          },
308411677aeSAaron LI 	{ OFPC_RESERVED,     "RESERVED"     }, /* not in the mask below */
309411677aeSAaron LI 	{ OFPC_IP_REASM,     "IP_REASM"     },
310411677aeSAaron LI 	{ OFPC_QUEUE_STATS,  "QUEUE_STATS"  },
311411677aeSAaron LI 	{ OFPC_ARP_MATCH_IP, "ARP_MATCH_IP" },
312411677aeSAaron LI 	{ 0, NULL }
313411677aeSAaron LI };
314411677aeSAaron LI #define OFPCAP_U (~(OFPC_FLOW_STATS | OFPC_TABLE_STATS | OFPC_PORT_STATS | \
315411677aeSAaron LI                     OFPC_STP | OFPC_IP_REASM | OFPC_QUEUE_STATS | \
316411677aeSAaron LI                     OFPC_ARP_MATCH_IP))
317411677aeSAaron LI 
318*ed775ee7SAntonio Huete Jimenez #define OFPC_FRAG_NORMAL 0x0000U
319*ed775ee7SAntonio Huete Jimenez #define OFPC_FRAG_DROP   0x0001U
320*ed775ee7SAntonio Huete Jimenez #define OFPC_FRAG_REASM  0x0002U
321*ed775ee7SAntonio Huete Jimenez #define OFPC_FRAG_MASK   0x0003U
322411677aeSAaron LI static const struct tok ofp_config_str[] = {
323411677aeSAaron LI 	{ OFPC_FRAG_NORMAL, "FRAG_NORMAL" },
324411677aeSAaron LI 	{ OFPC_FRAG_DROP,   "FRAG_DROP"   },
325411677aeSAaron LI 	{ OFPC_FRAG_REASM,  "FRAG_REASM"  },
326411677aeSAaron LI 	{ 0, NULL }
327411677aeSAaron LI };
328411677aeSAaron LI 
329*ed775ee7SAntonio Huete Jimenez #define OFPFC_ADD           0x0000U
330*ed775ee7SAntonio Huete Jimenez #define OFPFC_MODIFY        0x0001U
331*ed775ee7SAntonio Huete Jimenez #define OFPFC_MODIFY_STRICT 0x0002U
332*ed775ee7SAntonio Huete Jimenez #define OFPFC_DELETE        0x0003U
333*ed775ee7SAntonio Huete Jimenez #define OFPFC_DELETE_STRICT 0x0004U
334411677aeSAaron LI static const struct tok ofpfc_str[] = {
335411677aeSAaron LI 	{ OFPFC_ADD,           "ADD"           },
336411677aeSAaron LI 	{ OFPFC_MODIFY,        "MODIFY"        },
337411677aeSAaron LI 	{ OFPFC_MODIFY_STRICT, "MODIFY_STRICT" },
338411677aeSAaron LI 	{ OFPFC_DELETE,        "DELETE"        },
339411677aeSAaron LI 	{ OFPFC_DELETE_STRICT, "DELETE_STRICT" },
340411677aeSAaron LI 	{ 0, NULL }
341411677aeSAaron LI };
342411677aeSAaron LI 
343411677aeSAaron LI static const struct tok bufferid_str[] = {
344411677aeSAaron LI 	{ 0xffffffff, "NONE" },
345411677aeSAaron LI 	{ 0, NULL }
346411677aeSAaron LI };
347411677aeSAaron LI 
348*ed775ee7SAntonio Huete Jimenez #define OFPFF_SEND_FLOW_REM (1U <<0)
349*ed775ee7SAntonio Huete Jimenez #define OFPFF_CHECK_OVERLAP (1U <<1)
350*ed775ee7SAntonio Huete Jimenez #define OFPFF_EMERG         (1U <<2)
351411677aeSAaron LI static const struct tok ofpff_bm[] = {
352411677aeSAaron LI 	{ OFPFF_SEND_FLOW_REM, "SEND_FLOW_REM" },
353411677aeSAaron LI 	{ OFPFF_CHECK_OVERLAP, "CHECK_OVERLAP" },
354411677aeSAaron LI 	{ OFPFF_EMERG,         "EMERG"         },
355411677aeSAaron LI 	{ 0, NULL }
356411677aeSAaron LI };
357411677aeSAaron LI #define OFPFF_U (~(OFPFF_SEND_FLOW_REM | OFPFF_CHECK_OVERLAP | OFPFF_EMERG))
358411677aeSAaron LI 
359*ed775ee7SAntonio Huete Jimenez #define OFPST_DESC      0x0000U
360*ed775ee7SAntonio Huete Jimenez #define OFPST_FLOW      0x0001U
361*ed775ee7SAntonio Huete Jimenez #define OFPST_AGGREGATE 0x0002U
362*ed775ee7SAntonio Huete Jimenez #define OFPST_TABLE     0x0003U
363*ed775ee7SAntonio Huete Jimenez #define OFPST_PORT      0x0004U
364*ed775ee7SAntonio Huete Jimenez #define OFPST_QUEUE     0x0005U
365*ed775ee7SAntonio Huete Jimenez #define OFPST_VENDOR    0xffffU
366411677aeSAaron LI static const struct tok ofpst_str[] = {
367411677aeSAaron LI 	{ OFPST_DESC,      "DESC"      },
368411677aeSAaron LI 	{ OFPST_FLOW,      "FLOW"      },
369411677aeSAaron LI 	{ OFPST_AGGREGATE, "AGGREGATE" },
370411677aeSAaron LI 	{ OFPST_TABLE,     "TABLE"     },
371411677aeSAaron LI 	{ OFPST_PORT,      "PORT"      },
372411677aeSAaron LI 	{ OFPST_QUEUE,     "QUEUE"     },
373411677aeSAaron LI 	{ OFPST_VENDOR,    "VENDOR"    },
374411677aeSAaron LI 	{ 0, NULL }
375411677aeSAaron LI };
376411677aeSAaron LI 
377411677aeSAaron LI static const struct tok tableid_str[] = {
378*ed775ee7SAntonio Huete Jimenez 	{ 0xfeU, "EMERG" },
379*ed775ee7SAntonio Huete Jimenez 	{ 0xffU, "ALL"   },
380411677aeSAaron LI 	{ 0, NULL }
381411677aeSAaron LI };
382411677aeSAaron LI 
383*ed775ee7SAntonio Huete Jimenez #define OFPQ_ALL      0xffffffffU
384411677aeSAaron LI static const struct tok ofpq_str[] = {
385411677aeSAaron LI 	{ OFPQ_ALL, "ALL" },
386411677aeSAaron LI 	{ 0, NULL }
387411677aeSAaron LI };
388411677aeSAaron LI 
389*ed775ee7SAntonio Huete Jimenez #define OFPSF_REPLY_MORE 0x0001U
390411677aeSAaron LI static const struct tok ofpsf_reply_bm[] = {
391411677aeSAaron LI 	{ OFPSF_REPLY_MORE, "MORE" },
392411677aeSAaron LI 	{ 0, NULL }
393411677aeSAaron LI };
394411677aeSAaron LI #define OFPSF_REPLY_U (~(OFPSF_REPLY_MORE))
395411677aeSAaron LI 
396*ed775ee7SAntonio Huete Jimenez #define OFPR_NO_MATCH 0x00U
397*ed775ee7SAntonio Huete Jimenez #define OFPR_ACTION   0x01U
398411677aeSAaron LI static const struct tok ofpr_str[] = {
399411677aeSAaron LI 	{ OFPR_NO_MATCH, "NO_MATCH" },
400411677aeSAaron LI 	{ OFPR_ACTION,   "ACTION"   },
401411677aeSAaron LI 	{ 0, NULL }
402411677aeSAaron LI };
403411677aeSAaron LI 
404*ed775ee7SAntonio Huete Jimenez #define OFPRR_IDLE_TIMEOUT 0x00U
405*ed775ee7SAntonio Huete Jimenez #define OFPRR_HARD_TIMEOUT 0x01U
406*ed775ee7SAntonio Huete Jimenez #define OFPRR_DELETE       0x02U
407411677aeSAaron LI static const struct tok ofprr_str[] = {
408411677aeSAaron LI 	{ OFPRR_IDLE_TIMEOUT, "IDLE_TIMEOUT" },
409411677aeSAaron LI 	{ OFPRR_HARD_TIMEOUT, "HARD_TIMEOUT" },
410411677aeSAaron LI 	{ OFPRR_DELETE,       "DELETE"       },
411411677aeSAaron LI 	{ 0, NULL }
412411677aeSAaron LI };
413411677aeSAaron LI 
414*ed775ee7SAntonio Huete Jimenez #define OFPPR_ADD    0x00U
415*ed775ee7SAntonio Huete Jimenez #define OFPPR_DELETE 0x01U
416*ed775ee7SAntonio Huete Jimenez #define OFPPR_MODIFY 0x02U
417411677aeSAaron LI static const struct tok ofppr_str[] = {
418411677aeSAaron LI 	{ OFPPR_ADD,    "ADD"    },
419411677aeSAaron LI 	{ OFPPR_DELETE, "DELETE" },
420411677aeSAaron LI 	{ OFPPR_MODIFY, "MODIFY" },
421411677aeSAaron LI 	{ 0, NULL }
422411677aeSAaron LI };
423411677aeSAaron LI 
424*ed775ee7SAntonio Huete Jimenez #define OFPET_HELLO_FAILED    0x0000U
425*ed775ee7SAntonio Huete Jimenez #define OFPET_BAD_REQUEST     0x0001U
426*ed775ee7SAntonio Huete Jimenez #define OFPET_BAD_ACTION      0x0002U
427*ed775ee7SAntonio Huete Jimenez #define OFPET_FLOW_MOD_FAILED 0x0003U
428*ed775ee7SAntonio Huete Jimenez #define OFPET_PORT_MOD_FAILED 0x0004U
429*ed775ee7SAntonio Huete Jimenez #define OFPET_QUEUE_OP_FAILED 0x0005U
430411677aeSAaron LI static const struct tok ofpet_str[] = {
431411677aeSAaron LI 	{ OFPET_HELLO_FAILED,    "HELLO_FAILED"    },
432411677aeSAaron LI 	{ OFPET_BAD_REQUEST,     "BAD_REQUEST"     },
433411677aeSAaron LI 	{ OFPET_BAD_ACTION,      "BAD_ACTION"      },
434411677aeSAaron LI 	{ OFPET_FLOW_MOD_FAILED, "FLOW_MOD_FAILED" },
435411677aeSAaron LI 	{ OFPET_PORT_MOD_FAILED, "PORT_MOD_FAILED" },
436411677aeSAaron LI 	{ OFPET_QUEUE_OP_FAILED, "QUEUE_OP_FAILED" },
437411677aeSAaron LI 	{ 0, NULL }
438411677aeSAaron LI };
439411677aeSAaron LI 
440*ed775ee7SAntonio Huete Jimenez #define OFPHFC_INCOMPATIBLE 0x0000U
441*ed775ee7SAntonio Huete Jimenez #define OFPHFC_EPERM        0x0001U
442411677aeSAaron LI static const struct tok ofphfc_str[] = {
443411677aeSAaron LI 	{ OFPHFC_INCOMPATIBLE, "INCOMPATIBLE" },
444411677aeSAaron LI 	{ OFPHFC_EPERM,        "EPERM"        },
445411677aeSAaron LI 	{ 0, NULL }
446411677aeSAaron LI };
447411677aeSAaron LI 
448*ed775ee7SAntonio Huete Jimenez #define OFPBRC_BAD_VERSION    0x0000U
449*ed775ee7SAntonio Huete Jimenez #define OFPBRC_BAD_TYPE       0x0001U
450*ed775ee7SAntonio Huete Jimenez #define OFPBRC_BAD_STAT       0x0002U
451*ed775ee7SAntonio Huete Jimenez #define OFPBRC_BAD_VENDOR     0x0003U
452*ed775ee7SAntonio Huete Jimenez #define OFPBRC_BAD_SUBTYPE    0x0004U
453*ed775ee7SAntonio Huete Jimenez #define OFPBRC_EPERM          0x0005U
454*ed775ee7SAntonio Huete Jimenez #define OFPBRC_BAD_LEN        0x0006U
455*ed775ee7SAntonio Huete Jimenez #define OFPBRC_BUFFER_EMPTY   0x0007U
456*ed775ee7SAntonio Huete Jimenez #define OFPBRC_BUFFER_UNKNOWN 0x0008U
457411677aeSAaron LI static const struct tok ofpbrc_str[] = {
458411677aeSAaron LI 	{ OFPBRC_BAD_VERSION,    "BAD_VERSION"    },
459411677aeSAaron LI 	{ OFPBRC_BAD_TYPE,       "BAD_TYPE"       },
460411677aeSAaron LI 	{ OFPBRC_BAD_STAT,       "BAD_STAT"       },
461411677aeSAaron LI 	{ OFPBRC_BAD_VENDOR,     "BAD_VENDOR"     },
462411677aeSAaron LI 	{ OFPBRC_BAD_SUBTYPE,    "BAD_SUBTYPE"    },
463411677aeSAaron LI 	{ OFPBRC_EPERM,          "EPERM"          },
464411677aeSAaron LI 	{ OFPBRC_BAD_LEN,        "BAD_LEN"        },
465411677aeSAaron LI 	{ OFPBRC_BUFFER_EMPTY,   "BUFFER_EMPTY"   },
466411677aeSAaron LI 	{ OFPBRC_BUFFER_UNKNOWN, "BUFFER_UNKNOWN" },
467411677aeSAaron LI 	{ 0, NULL }
468411677aeSAaron LI };
469411677aeSAaron LI 
470*ed775ee7SAntonio Huete Jimenez #define OFPBAC_BAD_TYPE        0x0000U
471*ed775ee7SAntonio Huete Jimenez #define OFPBAC_BAD_LEN         0x0001U
472*ed775ee7SAntonio Huete Jimenez #define OFPBAC_BAD_VENDOR      0x0002U
473*ed775ee7SAntonio Huete Jimenez #define OFPBAC_BAD_VENDOR_TYPE 0x0003U
474*ed775ee7SAntonio Huete Jimenez #define OFPBAC_BAD_OUT_PORT    0x0004U
475*ed775ee7SAntonio Huete Jimenez #define OFPBAC_BAD_ARGUMENT    0x0005U
476*ed775ee7SAntonio Huete Jimenez #define OFPBAC_EPERM           0x0006U
477*ed775ee7SAntonio Huete Jimenez #define OFPBAC_TOO_MANY        0x0007U
478*ed775ee7SAntonio Huete Jimenez #define OFPBAC_BAD_QUEUE       0x0008U
479411677aeSAaron LI static const struct tok ofpbac_str[] = {
480411677aeSAaron LI 	{ OFPBAC_BAD_TYPE,        "BAD_TYPE"        },
481411677aeSAaron LI 	{ OFPBAC_BAD_LEN,         "BAD_LEN"         },
482411677aeSAaron LI 	{ OFPBAC_BAD_VENDOR,      "BAD_VENDOR"      },
483411677aeSAaron LI 	{ OFPBAC_BAD_VENDOR_TYPE, "BAD_VENDOR_TYPE" },
484411677aeSAaron LI 	{ OFPBAC_BAD_OUT_PORT,    "BAD_OUT_PORT"    },
485411677aeSAaron LI 	{ OFPBAC_BAD_ARGUMENT,    "BAD_ARGUMENT"    },
486411677aeSAaron LI 	{ OFPBAC_EPERM,           "EPERM"           },
487411677aeSAaron LI 	{ OFPBAC_TOO_MANY,        "TOO_MANY"        },
488411677aeSAaron LI 	{ OFPBAC_BAD_QUEUE,       "BAD_QUEUE"       },
489411677aeSAaron LI 	{ 0, NULL }
490411677aeSAaron LI };
491411677aeSAaron LI 
492*ed775ee7SAntonio Huete Jimenez #define OFPFMFC_ALL_TABLES_FULL   0x0000U
493*ed775ee7SAntonio Huete Jimenez #define OFPFMFC_OVERLAP           0x0001U
494*ed775ee7SAntonio Huete Jimenez #define OFPFMFC_EPERM             0x0002U
495*ed775ee7SAntonio Huete Jimenez #define OFPFMFC_BAD_EMERG_TIMEOUT 0x0003U
496*ed775ee7SAntonio Huete Jimenez #define OFPFMFC_BAD_COMMAND       0x0004U
497*ed775ee7SAntonio Huete Jimenez #define OFPFMFC_UNSUPPORTED       0x0005U
498411677aeSAaron LI static const struct tok ofpfmfc_str[] = {
499411677aeSAaron LI 	{ OFPFMFC_ALL_TABLES_FULL,   "ALL_TABLES_FULL"   },
500411677aeSAaron LI 	{ OFPFMFC_OVERLAP,           "OVERLAP"           },
501411677aeSAaron LI 	{ OFPFMFC_EPERM,             "EPERM"             },
502411677aeSAaron LI 	{ OFPFMFC_BAD_EMERG_TIMEOUT, "BAD_EMERG_TIMEOUT" },
503411677aeSAaron LI 	{ OFPFMFC_BAD_COMMAND,       "BAD_COMMAND"       },
504411677aeSAaron LI 	{ OFPFMFC_UNSUPPORTED,       "UNSUPPORTED"       },
505411677aeSAaron LI 	{ 0, NULL }
506411677aeSAaron LI };
507411677aeSAaron LI 
508*ed775ee7SAntonio Huete Jimenez #define OFPPMFC_BAD_PORT    0x0000U
509*ed775ee7SAntonio Huete Jimenez #define OFPPMFC_BAD_HW_ADDR 0x0001U
510411677aeSAaron LI static const struct tok ofppmfc_str[] = {
511411677aeSAaron LI 	{ OFPPMFC_BAD_PORT,    "BAD_PORT"    },
512411677aeSAaron LI 	{ OFPPMFC_BAD_HW_ADDR, "BAD_HW_ADDR" },
513411677aeSAaron LI 	{ 0, NULL }
514411677aeSAaron LI };
515411677aeSAaron LI 
516*ed775ee7SAntonio Huete Jimenez #define OFPQOFC_BAD_PORT  0x0000U
517*ed775ee7SAntonio Huete Jimenez #define OFPQOFC_BAD_QUEUE 0x0001U
518*ed775ee7SAntonio Huete Jimenez #define OFPQOFC_EPERM     0x0002U
519411677aeSAaron LI static const struct tok ofpqofc_str[] = {
520411677aeSAaron LI 	{ OFPQOFC_BAD_PORT,  "BAD_PORT"  },
521411677aeSAaron LI 	{ OFPQOFC_BAD_QUEUE, "BAD_QUEUE" },
522411677aeSAaron LI 	{ OFPQOFC_EPERM,     "EPERM"     },
523411677aeSAaron LI 	{ 0, NULL }
524411677aeSAaron LI };
525411677aeSAaron LI 
526*ed775ee7SAntonio Huete Jimenez static const struct uint_tokary of10_ofpet2tokary[] = {
527*ed775ee7SAntonio Huete Jimenez 	{ OFPET_HELLO_FAILED,    ofphfc_str  },
528*ed775ee7SAntonio Huete Jimenez 	{ OFPET_BAD_REQUEST,     ofpbrc_str  },
529*ed775ee7SAntonio Huete Jimenez 	{ OFPET_BAD_ACTION,      ofpbac_str  },
530*ed775ee7SAntonio Huete Jimenez 	{ OFPET_FLOW_MOD_FAILED, ofpfmfc_str },
531*ed775ee7SAntonio Huete Jimenez 	{ OFPET_PORT_MOD_FAILED, ofppmfc_str },
532*ed775ee7SAntonio Huete Jimenez 	{ OFPET_QUEUE_OP_FAILED, ofpqofc_str },
533*ed775ee7SAntonio Huete Jimenez 	/* uint2tokary() does not use array termination. */
534411677aeSAaron LI };
535411677aeSAaron LI 
536*ed775ee7SAntonio Huete Jimenez /* lengths (fixed or minimal) of particular message types, where not 0 */
537*ed775ee7SAntonio Huete Jimenez #define OF_SWITCH_CONFIG_FIXLEN            (12U - OF_HEADER_FIXLEN)
538*ed775ee7SAntonio Huete Jimenez #define OF_FEATURES_REPLY_MINLEN           (32U - OF_HEADER_FIXLEN)
539*ed775ee7SAntonio Huete Jimenez #define OF_PORT_STATUS_FIXLEN              (64U - OF_HEADER_FIXLEN)
540*ed775ee7SAntonio Huete Jimenez #define OF_PORT_MOD_FIXLEN                 (32U - OF_HEADER_FIXLEN)
541*ed775ee7SAntonio Huete Jimenez #define OF_PACKET_IN_MINLEN                (20U - OF_HEADER_FIXLEN) /* with 2 mock octets */
542*ed775ee7SAntonio Huete Jimenez #define OF_PACKET_OUT_MINLEN               (16U - OF_HEADER_FIXLEN)
543*ed775ee7SAntonio Huete Jimenez #define OF_FLOW_MOD_MINLEN                 (72U - OF_HEADER_FIXLEN)
544*ed775ee7SAntonio Huete Jimenez #define OF_FLOW_REMOVED_FIXLEN             (88U - OF_HEADER_FIXLEN)
545*ed775ee7SAntonio Huete Jimenez #define OF_ERROR_MSG_MINLEN                (12U - OF_HEADER_FIXLEN)
546*ed775ee7SAntonio Huete Jimenez #define OF_STATS_REQUEST_MINLEN            (12U - OF_HEADER_FIXLEN)
547*ed775ee7SAntonio Huete Jimenez #define OF_STATS_REPLY_MINLEN              (12U - OF_HEADER_FIXLEN)
548*ed775ee7SAntonio Huete Jimenez #define OF_VENDOR_MINLEN                   (12U - OF_HEADER_FIXLEN)
549*ed775ee7SAntonio Huete Jimenez #define OF_QUEUE_GET_CONFIG_REQUEST_FIXLEN (12U - OF_HEADER_FIXLEN)
550*ed775ee7SAntonio Huete Jimenez #define OF_QUEUE_GET_CONFIG_REPLY_MINLEN   (16U - OF_HEADER_FIXLEN)
551*ed775ee7SAntonio Huete Jimenez 
552411677aeSAaron LI /* lengths (fixed or minimal) of particular protocol structures */
553*ed775ee7SAntonio Huete Jimenez #define OF_PHY_PORT_FIXLEN                    48
554*ed775ee7SAntonio Huete Jimenez #define OF_ACTION_MINLEN                       8
555*ed775ee7SAntonio Huete Jimenez #define OF_MATCH_FIXLEN                       40
556*ed775ee7SAntonio Huete Jimenez #define OF_DESC_STATS_REPLY_FIXLEN          1056
557*ed775ee7SAntonio Huete Jimenez #define OF_FLOW_STATS_REQUEST_FIXLEN          44
558*ed775ee7SAntonio Huete Jimenez #define OF_FLOW_STATS_REPLY_MINLEN            88
559*ed775ee7SAntonio Huete Jimenez #define OF_AGGREGATE_STATS_REPLY_FIXLEN       24
560*ed775ee7SAntonio Huete Jimenez #define OF_TABLE_STATS_REPLY_FIXLEN           64
561*ed775ee7SAntonio Huete Jimenez #define OF_PORT_STATS_REQUEST_FIXLEN           8
562*ed775ee7SAntonio Huete Jimenez #define OF_PORT_STATS_REPLY_FIXLEN           104
563*ed775ee7SAntonio Huete Jimenez #define OF_QUEUE_PROP_MINLEN                   8
564*ed775ee7SAntonio Huete Jimenez #define OF_QUEUE_PROP_MIN_RATE_FIXLEN         16
565*ed775ee7SAntonio Huete Jimenez #define OF_PACKET_QUEUE_MINLEN                 8
566*ed775ee7SAntonio Huete Jimenez #define OF_QUEUE_STATS_REQUEST_FIXLEN          8
567*ed775ee7SAntonio Huete Jimenez #define OF_QUEUE_STATS_REPLY_FIXLEN           32
568411677aeSAaron LI 
569411677aeSAaron LI /* miscellaneous constants from [OF10] */
570411677aeSAaron LI #define OFP_MAX_TABLE_NAME_LEN     32
571411677aeSAaron LI #define OFP_MAX_PORT_NAME_LEN      16
572411677aeSAaron LI #define DESC_STR_LEN              256
573411677aeSAaron LI #define SERIAL_NUM_LEN             32
574*ed775ee7SAntonio Huete Jimenez #define OFP_VLAN_NONE          0xffffU
575411677aeSAaron LI 
576411677aeSAaron LI /* vendor extensions */
577411677aeSAaron LI #define BSN_SET_IP_MASK                    0
578411677aeSAaron LI #define BSN_GET_IP_MASK_REQUEST            1
579411677aeSAaron LI #define BSN_GET_IP_MASK_REPLY              2
580411677aeSAaron LI #define BSN_SET_MIRRORING                  3
581411677aeSAaron LI #define BSN_GET_MIRRORING_REQUEST          4
582411677aeSAaron LI #define BSN_GET_MIRRORING_REPLY            5
583411677aeSAaron LI #define BSN_SHELL_COMMAND                  6
584411677aeSAaron LI #define BSN_SHELL_OUTPUT                   7
585411677aeSAaron LI #define BSN_SHELL_STATUS                   8
586411677aeSAaron LI #define BSN_GET_INTERFACES_REQUEST         9
587411677aeSAaron LI #define BSN_GET_INTERFACES_REPLY          10
588411677aeSAaron LI #define BSN_SET_PKTIN_SUPPRESSION_REQUEST 11
589411677aeSAaron LI #define BSN_SET_L2_TABLE_REQUEST          12
590411677aeSAaron LI #define BSN_GET_L2_TABLE_REQUEST          13
591411677aeSAaron LI #define BSN_GET_L2_TABLE_REPLY            14
592411677aeSAaron LI #define BSN_VIRTUAL_PORT_CREATE_REQUEST   15
593411677aeSAaron LI #define BSN_VIRTUAL_PORT_CREATE_REPLY     16
594411677aeSAaron LI #define BSN_VIRTUAL_PORT_REMOVE_REQUEST   17
595411677aeSAaron LI #define BSN_BW_ENABLE_SET_REQUEST         18
596411677aeSAaron LI #define BSN_BW_ENABLE_GET_REQUEST         19
597411677aeSAaron LI #define BSN_BW_ENABLE_GET_REPLY           20
598411677aeSAaron LI #define BSN_BW_CLEAR_DATA_REQUEST         21
599411677aeSAaron LI #define BSN_BW_CLEAR_DATA_REPLY           22
600411677aeSAaron LI #define BSN_BW_ENABLE_SET_REPLY           23
601411677aeSAaron LI #define BSN_SET_L2_TABLE_REPLY            24
602411677aeSAaron LI #define BSN_SET_PKTIN_SUPPRESSION_REPLY   25
603411677aeSAaron LI #define BSN_VIRTUAL_PORT_REMOVE_REPLY     26
604411677aeSAaron LI #define BSN_HYBRID_GET_REQUEST            27
605411677aeSAaron LI #define BSN_HYBRID_GET_REPLY              28
606411677aeSAaron LI                                        /* 29 */
607411677aeSAaron LI                                        /* 30 */
608411677aeSAaron LI #define BSN_PDU_TX_REQUEST                31
609411677aeSAaron LI #define BSN_PDU_TX_REPLY                  32
610411677aeSAaron LI #define BSN_PDU_RX_REQUEST                33
611411677aeSAaron LI #define BSN_PDU_RX_REPLY                  34
612411677aeSAaron LI #define BSN_PDU_RX_TIMEOUT                35
613411677aeSAaron LI 
614411677aeSAaron LI static const struct tok bsn_subtype_str[] = {
615411677aeSAaron LI 	{ BSN_SET_IP_MASK,                   "SET_IP_MASK"                   },
616411677aeSAaron LI 	{ BSN_GET_IP_MASK_REQUEST,           "GET_IP_MASK_REQUEST"           },
617411677aeSAaron LI 	{ BSN_GET_IP_MASK_REPLY,             "GET_IP_MASK_REPLY"             },
618411677aeSAaron LI 	{ BSN_SET_MIRRORING,                 "SET_MIRRORING"                 },
619411677aeSAaron LI 	{ BSN_GET_MIRRORING_REQUEST,         "GET_MIRRORING_REQUEST"         },
620411677aeSAaron LI 	{ BSN_GET_MIRRORING_REPLY,           "GET_MIRRORING_REPLY"           },
621411677aeSAaron LI 	{ BSN_SHELL_COMMAND,                 "SHELL_COMMAND"                 },
622411677aeSAaron LI 	{ BSN_SHELL_OUTPUT,                  "SHELL_OUTPUT"                  },
623411677aeSAaron LI 	{ BSN_SHELL_STATUS,                  "SHELL_STATUS"                  },
624411677aeSAaron LI 	{ BSN_GET_INTERFACES_REQUEST,        "GET_INTERFACES_REQUEST"        },
625411677aeSAaron LI 	{ BSN_GET_INTERFACES_REPLY,          "GET_INTERFACES_REPLY"          },
626411677aeSAaron LI 	{ BSN_SET_PKTIN_SUPPRESSION_REQUEST, "SET_PKTIN_SUPPRESSION_REQUEST" },
627411677aeSAaron LI 	{ BSN_SET_L2_TABLE_REQUEST,          "SET_L2_TABLE_REQUEST"          },
628411677aeSAaron LI 	{ BSN_GET_L2_TABLE_REQUEST,          "GET_L2_TABLE_REQUEST"          },
629411677aeSAaron LI 	{ BSN_GET_L2_TABLE_REPLY,            "GET_L2_TABLE_REPLY"            },
630411677aeSAaron LI 	{ BSN_VIRTUAL_PORT_CREATE_REQUEST,   "VIRTUAL_PORT_CREATE_REQUEST"   },
631411677aeSAaron LI 	{ BSN_VIRTUAL_PORT_CREATE_REPLY,     "VIRTUAL_PORT_CREATE_REPLY"     },
632411677aeSAaron LI 	{ BSN_VIRTUAL_PORT_REMOVE_REQUEST,   "VIRTUAL_PORT_REMOVE_REQUEST"   },
633411677aeSAaron LI 	{ BSN_BW_ENABLE_SET_REQUEST,         "BW_ENABLE_SET_REQUEST"         },
634411677aeSAaron LI 	{ BSN_BW_ENABLE_GET_REQUEST,         "BW_ENABLE_GET_REQUEST"         },
635411677aeSAaron LI 	{ BSN_BW_ENABLE_GET_REPLY,           "BW_ENABLE_GET_REPLY"           },
636411677aeSAaron LI 	{ BSN_BW_CLEAR_DATA_REQUEST,         "BW_CLEAR_DATA_REQUEST"         },
637411677aeSAaron LI 	{ BSN_BW_CLEAR_DATA_REPLY,           "BW_CLEAR_DATA_REPLY"           },
638411677aeSAaron LI 	{ BSN_BW_ENABLE_SET_REPLY,           "BW_ENABLE_SET_REPLY"           },
639411677aeSAaron LI 	{ BSN_SET_L2_TABLE_REPLY,            "SET_L2_TABLE_REPLY"            },
640411677aeSAaron LI 	{ BSN_SET_PKTIN_SUPPRESSION_REPLY,   "SET_PKTIN_SUPPRESSION_REPLY"   },
641411677aeSAaron LI 	{ BSN_VIRTUAL_PORT_REMOVE_REPLY,     "VIRTUAL_PORT_REMOVE_REPLY"     },
642411677aeSAaron LI 	{ BSN_HYBRID_GET_REQUEST,            "HYBRID_GET_REQUEST"            },
643411677aeSAaron LI 	{ BSN_HYBRID_GET_REPLY,              "HYBRID_GET_REPLY"              },
644411677aeSAaron LI 	{ BSN_PDU_TX_REQUEST,                "PDU_TX_REQUEST"                },
645411677aeSAaron LI 	{ BSN_PDU_TX_REPLY,                  "PDU_TX_REPLY"                  },
646411677aeSAaron LI 	{ BSN_PDU_RX_REQUEST,                "PDU_RX_REQUEST"                },
647411677aeSAaron LI 	{ BSN_PDU_RX_REPLY,                  "PDU_RX_REPLY"                  },
648411677aeSAaron LI 	{ BSN_PDU_RX_TIMEOUT,                "PDU_RX_TIMEOUT"                },
649411677aeSAaron LI 	{ 0, NULL }
650411677aeSAaron LI };
651411677aeSAaron LI 
652411677aeSAaron LI #define BSN_ACTION_MIRROR                  1
653411677aeSAaron LI #define BSN_ACTION_SET_TUNNEL_DST          2
654411677aeSAaron LI                                         /* 3 */
655411677aeSAaron LI #define BSN_ACTION_CHECKSUM                4
656411677aeSAaron LI 
657411677aeSAaron LI static const struct tok bsn_action_subtype_str[] = {
658411677aeSAaron LI 	{ BSN_ACTION_MIRROR,                 "MIRROR"                        },
659411677aeSAaron LI 	{ BSN_ACTION_SET_TUNNEL_DST,         "SET_TUNNEL_DST"                },
660411677aeSAaron LI 	{ BSN_ACTION_CHECKSUM,               "CHECKSUM"                      },
661411677aeSAaron LI 	{ 0, NULL }
662411677aeSAaron LI };
663411677aeSAaron LI 
664411677aeSAaron LI static const struct tok bsn_mirror_copy_stage_str[] = {
665411677aeSAaron LI 	{ 0, "INGRESS" },
666411677aeSAaron LI 	{ 1, "EGRESS"  },
667411677aeSAaron LI 	{ 0, NULL },
668411677aeSAaron LI };
669411677aeSAaron LI 
670411677aeSAaron LI static const struct tok bsn_onoff_str[] = {
671411677aeSAaron LI 	{ 0, "OFF" },
672411677aeSAaron LI 	{ 1, "ON"  },
673411677aeSAaron LI 	{ 0, NULL },
674411677aeSAaron LI };
675411677aeSAaron LI 
676411677aeSAaron LI static const char *
vlan_str(const uint16_t vid)677411677aeSAaron LI vlan_str(const uint16_t vid)
678411677aeSAaron LI {
679411677aeSAaron LI 	static char buf[sizeof("65535 (bogus)")];
680411677aeSAaron LI 
681411677aeSAaron LI 	if (vid == OFP_VLAN_NONE)
682411677aeSAaron LI 		return "NONE";
683*ed775ee7SAntonio Huete Jimenez 	snprintf(buf, sizeof(buf), "%u%s", vid,
684*ed775ee7SAntonio Huete Jimenez 	         (vid > 0 && vid < 0x0fff) ? "" : " (bogus)");
685411677aeSAaron LI 	return buf;
686411677aeSAaron LI }
687411677aeSAaron LI 
688411677aeSAaron LI static const char *
pcp_str(const uint8_t pcp)689411677aeSAaron LI pcp_str(const uint8_t pcp)
690411677aeSAaron LI {
691411677aeSAaron LI 	static char buf[sizeof("255 (bogus)")];
692*ed775ee7SAntonio Huete Jimenez 	snprintf(buf, sizeof(buf), "%u%s", pcp,
693*ed775ee7SAntonio Huete Jimenez 	         pcp <= 7 ? "" : " (bogus)");
694411677aeSAaron LI 	return buf;
695411677aeSAaron LI }
696411677aeSAaron LI 
697411677aeSAaron LI static void
of10_bsn_message_print(netdissect_options * ndo,const u_char * cp,u_int len)698411677aeSAaron LI of10_bsn_message_print(netdissect_options *ndo,
699*ed775ee7SAntonio Huete Jimenez                        const u_char *cp, u_int len)
700411677aeSAaron LI {
701411677aeSAaron LI 	uint32_t subtype;
702411677aeSAaron LI 
703411677aeSAaron LI 	if (len < 4)
704411677aeSAaron LI 		goto invalid;
705411677aeSAaron LI 	/* subtype */
706*ed775ee7SAntonio Huete Jimenez 	subtype = GET_BE_U_4(cp);
707*ed775ee7SAntonio Huete Jimenez 	OF_FWD(4);
708*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("\n\t subtype %s", tok2str(bsn_subtype_str, "unknown (0x%08x)", subtype));
709411677aeSAaron LI 	switch (subtype) {
710411677aeSAaron LI 	case BSN_GET_IP_MASK_REQUEST:
711411677aeSAaron LI 		/*
712411677aeSAaron LI 		 *  0                   1                   2                   3
713411677aeSAaron LI 		 *  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
714411677aeSAaron LI 		 * +---------------+---------------+---------------+---------------+
715411677aeSAaron LI 		 * |                            subtype                            |
716411677aeSAaron LI 		 * +---------------+---------------+---------------+---------------+
717411677aeSAaron LI 		 * |     index     |                      pad                      |
718411677aeSAaron LI 		 * +---------------+---------------+---------------+---------------+
719411677aeSAaron LI 		 * |                              pad                              |
720411677aeSAaron LI 		 * +---------------+---------------+---------------+---------------+
721411677aeSAaron LI 		 *
722411677aeSAaron LI 		 */
723*ed775ee7SAntonio Huete Jimenez 		if (len != 8)
724411677aeSAaron LI 			goto invalid;
725411677aeSAaron LI 		/* index */
726*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", index %u", GET_U_1(cp));
727*ed775ee7SAntonio Huete Jimenez 		OF_FWD(1);
728411677aeSAaron LI 		/* pad */
729*ed775ee7SAntonio Huete Jimenez 		/* Always the last field, check bounds. */
730*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_7(cp);
731411677aeSAaron LI 		break;
732411677aeSAaron LI 	case BSN_SET_IP_MASK:
733411677aeSAaron LI 	case BSN_GET_IP_MASK_REPLY:
734411677aeSAaron LI 		/*
735411677aeSAaron LI 		 *  0                   1                   2                   3
736411677aeSAaron LI 		 *  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
737411677aeSAaron LI 		 * +---------------+---------------+---------------+---------------+
738411677aeSAaron LI 		 * |                            subtype                            |
739411677aeSAaron LI 		 * +---------------+---------------+---------------+---------------+
740411677aeSAaron LI 		 * |     index     |                      pad                      |
741411677aeSAaron LI 		 * +---------------+---------------+---------------+---------------+
742411677aeSAaron LI 		 * |                              mask                             |
743411677aeSAaron LI 		 * +---------------+---------------+---------------+---------------+
744411677aeSAaron LI 		 *
745411677aeSAaron LI 		 */
746*ed775ee7SAntonio Huete Jimenez 		if (len != 8)
747411677aeSAaron LI 			goto invalid;
748411677aeSAaron LI 		/* index */
749*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", index %u", GET_U_1(cp));
750*ed775ee7SAntonio Huete Jimenez 		OF_FWD(1);
751411677aeSAaron LI 		/* pad */
752*ed775ee7SAntonio Huete Jimenez 		OF_FWD(3);
753411677aeSAaron LI 		/* mask */
754*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", mask %s", GET_IPADDR_STRING(cp));
755411677aeSAaron LI 		break;
756411677aeSAaron LI 	case BSN_SET_MIRRORING:
757411677aeSAaron LI 	case BSN_GET_MIRRORING_REQUEST:
758411677aeSAaron LI 	case BSN_GET_MIRRORING_REPLY:
759411677aeSAaron LI 		/*
760411677aeSAaron LI 		 *  0                   1                   2                   3
761411677aeSAaron LI 		 *  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
762411677aeSAaron LI 		 * +---------------+---------------+---------------+---------------+
763411677aeSAaron LI 		 * |                            subtype                            |
764411677aeSAaron LI 		 * +---------------+---------------+---------------+---------------+
765411677aeSAaron LI 		 * | report m. p.  |                      pad                      |
766411677aeSAaron LI 		 * +---------------+---------------+---------------+---------------+
767411677aeSAaron LI 		 *
768411677aeSAaron LI 		 */
769*ed775ee7SAntonio Huete Jimenez 		if (len != 4)
770411677aeSAaron LI 			goto invalid;
771411677aeSAaron LI 		/* report_mirror_ports */
772*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", report_mirror_ports %s",
773*ed775ee7SAntonio Huete Jimenez 			 tok2str(bsn_onoff_str, "bogus (%u)", GET_U_1(cp)));
774*ed775ee7SAntonio Huete Jimenez 		OF_FWD(1);
775411677aeSAaron LI 		/* pad */
776*ed775ee7SAntonio Huete Jimenez 		/* Always the last field, check bounds. */
777*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_3(cp);
778411677aeSAaron LI 		break;
779411677aeSAaron LI 	case BSN_GET_INTERFACES_REQUEST:
780411677aeSAaron LI 	case BSN_GET_L2_TABLE_REQUEST:
781411677aeSAaron LI 	case BSN_BW_ENABLE_GET_REQUEST:
782411677aeSAaron LI 	case BSN_BW_CLEAR_DATA_REQUEST:
783411677aeSAaron LI 	case BSN_HYBRID_GET_REQUEST:
784411677aeSAaron LI 		/*
785411677aeSAaron LI 		 *  0                   1                   2                   3
786411677aeSAaron LI 		 *  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
787411677aeSAaron LI 		 * +---------------+---------------+---------------+---------------+
788411677aeSAaron LI 		 * |                            subtype                            |
789411677aeSAaron LI 		 * +---------------+---------------+---------------+---------------+
790411677aeSAaron LI 		 *
791411677aeSAaron LI 		 */
792*ed775ee7SAntonio Huete Jimenez 		if (len)
793411677aeSAaron LI 			goto invalid;
794411677aeSAaron LI 		break;
795411677aeSAaron LI 	case BSN_VIRTUAL_PORT_REMOVE_REQUEST:
796411677aeSAaron LI 		/*
797411677aeSAaron LI 		 *  0                   1                   2                   3
798411677aeSAaron LI 		 *  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
799411677aeSAaron LI 		 * +---------------+---------------+---------------+---------------+
800411677aeSAaron LI 		 * |                            subtype                            |
801411677aeSAaron LI 		 * +---------------+---------------+---------------+---------------+
802411677aeSAaron LI 		 * |                           vport_no                            |
803411677aeSAaron LI 		 * +---------------+---------------+---------------+---------------+
804411677aeSAaron LI 		 *
805411677aeSAaron LI 		 */
806*ed775ee7SAntonio Huete Jimenez 		if (len != 4)
807411677aeSAaron LI 			goto invalid;
808411677aeSAaron LI 		/* vport_no */
809*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", vport_no %u", GET_BE_U_4(cp));
810411677aeSAaron LI 		break;
811411677aeSAaron LI 	case BSN_SHELL_COMMAND:
812411677aeSAaron LI 		/*
813411677aeSAaron LI 		 *  0                   1                   2                   3
814411677aeSAaron LI 		 *  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
815411677aeSAaron LI 		 * +---------------+---------------+---------------+---------------+
816411677aeSAaron LI 		 * |                            subtype                            |
817411677aeSAaron LI 		 * +---------------+---------------+---------------+---------------+
818411677aeSAaron LI 		 * |                            service                            |
819411677aeSAaron LI 		 * +---------------+---------------+---------------+---------------+
820411677aeSAaron LI 		 * |                             data ...
821411677aeSAaron LI 		 * +---------------+---------------+--------
822411677aeSAaron LI 		 *
823411677aeSAaron LI 		 */
824*ed775ee7SAntonio Huete Jimenez 		if (len < 4)
825411677aeSAaron LI 			goto invalid;
826411677aeSAaron LI 		/* service */
827*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", service %u", GET_BE_U_4(cp));
828*ed775ee7SAntonio Huete Jimenez 		OF_FWD(4);
829411677aeSAaron LI 		/* data */
830*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", data '");
831*ed775ee7SAntonio Huete Jimenez 		(void)nd_printn(ndo, cp, len, NULL);
832*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("'");
833411677aeSAaron LI 		break;
834411677aeSAaron LI 	case BSN_SHELL_OUTPUT:
835411677aeSAaron LI 		/*
836411677aeSAaron LI 		 *  0                   1                   2                   3
837411677aeSAaron LI 		 *  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
838411677aeSAaron LI 		 * +---------------+---------------+---------------+---------------+
839411677aeSAaron LI 		 * |                            subtype                            |
840411677aeSAaron LI 		 * +---------------+---------------+---------------+---------------+
841411677aeSAaron LI 		 * |                             data ...
842411677aeSAaron LI 		 * +---------------+---------------+--------
843411677aeSAaron LI 		 *
844411677aeSAaron LI 		 */
845411677aeSAaron LI 		/* already checked that len >= 4 */
846411677aeSAaron LI 		/* data */
847*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", data '");
848*ed775ee7SAntonio Huete Jimenez 		(void)nd_printn(ndo, cp, len, NULL);
849*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("'");
850411677aeSAaron LI 		break;
851411677aeSAaron LI 	case BSN_SHELL_STATUS:
852411677aeSAaron LI 		/*
853411677aeSAaron LI 		 *  0                   1                   2                   3
854411677aeSAaron LI 		 *  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
855411677aeSAaron LI 		 * +---------------+---------------+---------------+---------------+
856411677aeSAaron LI 		 * |                            subtype                            |
857411677aeSAaron LI 		 * +---------------+---------------+---------------+---------------+
858411677aeSAaron LI 		 * |                            status                             |
859411677aeSAaron LI 		 * +---------------+---------------+---------------+---------------+
860411677aeSAaron LI 		 *
861411677aeSAaron LI 		 */
862*ed775ee7SAntonio Huete Jimenez 		if (len != 4)
863411677aeSAaron LI 			goto invalid;
864411677aeSAaron LI 		/* status */
865*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", status 0x%08x", GET_BE_U_4(cp));
866411677aeSAaron LI 		break;
867411677aeSAaron LI 	default:
868*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_LEN(cp, len);
869411677aeSAaron LI 	}
870*ed775ee7SAntonio Huete Jimenez 	return;
871411677aeSAaron LI 
872411677aeSAaron LI invalid: /* skip the undersized data */
873*ed775ee7SAntonio Huete Jimenez 	nd_print_invalid(ndo);
874*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_LEN(cp, len);
875411677aeSAaron LI }
876411677aeSAaron LI 
877*ed775ee7SAntonio Huete Jimenez static void
of10_bsn_actions_print(netdissect_options * ndo,const u_char * cp,u_int len)878411677aeSAaron LI of10_bsn_actions_print(netdissect_options *ndo,
879*ed775ee7SAntonio Huete Jimenez                        const u_char *cp, u_int len)
880411677aeSAaron LI {
881411677aeSAaron LI 	uint32_t subtype, vlan_tag;
882411677aeSAaron LI 
883411677aeSAaron LI 	if (len < 4)
884411677aeSAaron LI 		goto invalid;
885411677aeSAaron LI 	/* subtype */
886*ed775ee7SAntonio Huete Jimenez 	subtype = GET_BE_U_4(cp);
887*ed775ee7SAntonio Huete Jimenez 	OF_FWD(4);
888*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("\n\t  subtype %s", tok2str(bsn_action_subtype_str, "unknown (0x%08x)", subtype));
889411677aeSAaron LI 	switch (subtype) {
890411677aeSAaron LI 	case BSN_ACTION_MIRROR:
891411677aeSAaron LI 		/*
892411677aeSAaron LI 		 *  0                   1                   2                   3
893411677aeSAaron LI 		 *  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
894411677aeSAaron LI 		 * +---------------+---------------+---------------+---------------+
895411677aeSAaron LI 		 * |                            subtype                            |
896411677aeSAaron LI 		 * +---------------+---------------+---------------+---------------+
897411677aeSAaron LI 		 * |                           dest_port                           |
898411677aeSAaron LI 		 * +---------------+---------------+---------------+---------------+
899411677aeSAaron LI 		 * |                           vlan_tag                            |
900411677aeSAaron LI 		 * +---------------+---------------+---------------+---------------+
901411677aeSAaron LI 		 * |  copy_stage   |                      pad                      |
902411677aeSAaron LI 		 * +---------------+---------------+---------------+---------------+
903411677aeSAaron LI 		 *
904411677aeSAaron LI 		 */
905*ed775ee7SAntonio Huete Jimenez 		if (len != 12)
906411677aeSAaron LI 			goto invalid;
907411677aeSAaron LI 		/* dest_port */
908*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", dest_port %u", GET_BE_U_4(cp));
909*ed775ee7SAntonio Huete Jimenez 		OF_FWD(4);
910411677aeSAaron LI 		/* vlan_tag */
911*ed775ee7SAntonio Huete Jimenez 		vlan_tag = GET_BE_U_4(cp);
912*ed775ee7SAntonio Huete Jimenez 		OF_FWD(4);
913411677aeSAaron LI 		switch (vlan_tag >> 16) {
914411677aeSAaron LI 		case 0:
915*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(", vlan_tag none");
916411677aeSAaron LI 			break;
917411677aeSAaron LI 		case ETHERTYPE_8021Q:
918*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(", vlan_tag 802.1Q (%s)", ieee8021q_tci_string(vlan_tag & 0xffff));
919411677aeSAaron LI 			break;
920411677aeSAaron LI 		default:
921*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(", vlan_tag unknown (0x%04x)", vlan_tag >> 16);
922411677aeSAaron LI 		}
923411677aeSAaron LI 		/* copy_stage */
924*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", copy_stage %s",
925*ed775ee7SAntonio Huete Jimenez 			 tok2str(bsn_mirror_copy_stage_str, "unknown (%u)", GET_U_1(cp)));
926*ed775ee7SAntonio Huete Jimenez 		OF_FWD(1);
927411677aeSAaron LI 		/* pad */
928*ed775ee7SAntonio Huete Jimenez 		/* Always the last field, check bounds. */
929*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_3(cp);
930411677aeSAaron LI 		break;
931411677aeSAaron LI 	default:
932*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_LEN(cp, len);
933411677aeSAaron LI 	}
934*ed775ee7SAntonio Huete Jimenez 	return;
935411677aeSAaron LI 
936411677aeSAaron LI invalid:
937*ed775ee7SAntonio Huete Jimenez 	nd_print_invalid(ndo);
938*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_LEN(cp, len);
939411677aeSAaron LI }
940411677aeSAaron LI 
941*ed775ee7SAntonio Huete Jimenez static void
of10_vendor_action_print(netdissect_options * ndo,const u_char * cp,u_int len)942411677aeSAaron LI of10_vendor_action_print(netdissect_options *ndo,
943*ed775ee7SAntonio Huete Jimenez                          const u_char *cp, u_int len)
944411677aeSAaron LI {
945411677aeSAaron LI 	uint32_t vendor;
946*ed775ee7SAntonio Huete Jimenez 	void (*decoder)(netdissect_options *, const u_char *, u_int);
947411677aeSAaron LI 
948411677aeSAaron LI 	if (len < 4)
949411677aeSAaron LI 		goto invalid;
950411677aeSAaron LI 	/* vendor */
951*ed775ee7SAntonio Huete Jimenez 	vendor = GET_BE_U_4(cp);
952*ed775ee7SAntonio Huete Jimenez 	OF_FWD(4);
953*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(", vendor 0x%08x (%s)", vendor, of_vendor_name(vendor));
954411677aeSAaron LI 	/* data */
955411677aeSAaron LI 	decoder =
956411677aeSAaron LI 		vendor == OUI_BSN         ? of10_bsn_actions_print         :
957*ed775ee7SAntonio Huete Jimenez 		of_data_print;
958*ed775ee7SAntonio Huete Jimenez 	decoder(ndo, cp, len);
959*ed775ee7SAntonio Huete Jimenez 	return;
960411677aeSAaron LI 
961411677aeSAaron LI invalid: /* skip the undersized data */
962*ed775ee7SAntonio Huete Jimenez 	nd_print_invalid(ndo);
963*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_LEN(cp, len);
964411677aeSAaron LI }
965411677aeSAaron LI 
966*ed775ee7SAntonio Huete Jimenez /* [OF10] Section 5.5.4 */
967*ed775ee7SAntonio Huete Jimenez static void
of10_vendor_message_print(netdissect_options * ndo,const u_char * cp,u_int len)968411677aeSAaron LI of10_vendor_message_print(netdissect_options *ndo,
969*ed775ee7SAntonio Huete Jimenez                           const u_char *cp, u_int len)
970411677aeSAaron LI {
971411677aeSAaron LI 	uint32_t vendor;
972*ed775ee7SAntonio Huete Jimenez 	void (*decoder)(netdissect_options *, const u_char *, u_int);
973411677aeSAaron LI 
974411677aeSAaron LI 	/* vendor */
975*ed775ee7SAntonio Huete Jimenez 	vendor = GET_BE_U_4(cp);
976*ed775ee7SAntonio Huete Jimenez 	OF_FWD(4);
977*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(", vendor 0x%08x (%s)", vendor, of_vendor_name(vendor));
978411677aeSAaron LI 	/* data */
979411677aeSAaron LI 	decoder =
980411677aeSAaron LI 		vendor == OUI_BSN         ? of10_bsn_message_print         :
981*ed775ee7SAntonio Huete Jimenez 		of_data_print;
982*ed775ee7SAntonio Huete Jimenez 	decoder(ndo, cp, len);
983411677aeSAaron LI }
984411677aeSAaron LI 
985411677aeSAaron LI /* Vendor ID is mandatory, data is optional. */
986*ed775ee7SAntonio Huete Jimenez static void
of10_vendor_data_print(netdissect_options * ndo,const u_char * cp,u_int len)987411677aeSAaron LI of10_vendor_data_print(netdissect_options *ndo,
988*ed775ee7SAntonio Huete Jimenez                        const u_char *cp, u_int len)
989411677aeSAaron LI {
990411677aeSAaron LI 	uint32_t vendor;
991411677aeSAaron LI 
992411677aeSAaron LI 	if (len < 4)
993411677aeSAaron LI 		goto invalid;
994411677aeSAaron LI 	/* vendor */
995*ed775ee7SAntonio Huete Jimenez 	vendor = GET_BE_U_4(cp);
996*ed775ee7SAntonio Huete Jimenez 	OF_FWD(4);
997*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(", vendor 0x%08x (%s)", vendor, of_vendor_name(vendor));
998411677aeSAaron LI 	/* data */
999*ed775ee7SAntonio Huete Jimenez 	of_data_print(ndo, cp, len);
1000*ed775ee7SAntonio Huete Jimenez 	return;
1001411677aeSAaron LI 
1002411677aeSAaron LI invalid: /* skip the undersized data */
1003*ed775ee7SAntonio Huete Jimenez 	nd_print_invalid(ndo);
1004*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_LEN(cp, len);
1005411677aeSAaron LI }
1006411677aeSAaron LI 
1007*ed775ee7SAntonio Huete Jimenez static void
of10_packet_data_print(netdissect_options * ndo,const u_char * cp,const u_int len)1008411677aeSAaron LI of10_packet_data_print(netdissect_options *ndo,
1009*ed775ee7SAntonio Huete Jimenez                        const u_char *cp, const u_int len)
1010411677aeSAaron LI {
1011411677aeSAaron LI 	if (len == 0)
1012*ed775ee7SAntonio Huete Jimenez 		return;
1013411677aeSAaron LI 	/* data */
1014*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("\n\t data (%u octets)", len);
1015*ed775ee7SAntonio Huete Jimenez 	if (ndo->ndo_vflag < 3) {
1016*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_LEN(cp, len);
1017*ed775ee7SAntonio Huete Jimenez 		return;
1018*ed775ee7SAntonio Huete Jimenez 	}
1019411677aeSAaron LI 	ndo->ndo_vflag -= 3;
1020*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(", frame decoding below\n");
1021*ed775ee7SAntonio Huete Jimenez 	/*
1022*ed775ee7SAntonio Huete Jimenez 	 * The encapsulated Ethernet frame is not necessarily the last
1023*ed775ee7SAntonio Huete Jimenez 	 * data of this packet (i.e. there may be more OpenFlow messages
1024*ed775ee7SAntonio Huete Jimenez 	 * after the current OFPT_PACKET_IN/OFPT_PACKET_OUT message, in
1025*ed775ee7SAntonio Huete Jimenez 	 * which case the current (outer) packet's snapshot end is not
1026*ed775ee7SAntonio Huete Jimenez 	 * what ether_print() needs to decode an Ethernet frame nested in
1027*ed775ee7SAntonio Huete Jimenez 	 * the middle of a TCP payload.
1028*ed775ee7SAntonio Huete Jimenez 	 */
1029*ed775ee7SAntonio Huete Jimenez 	const u_char *snapend_save = ndo->ndo_snapend;
1030*ed775ee7SAntonio Huete Jimenez 	ndo->ndo_snapend = ND_MIN(cp + len, ndo->ndo_snapend);
1031*ed775ee7SAntonio Huete Jimenez 	ether_print(ndo, cp, len, ND_BYTES_AVAILABLE_AFTER(cp), NULL, NULL);
1032*ed775ee7SAntonio Huete Jimenez 	ndo->ndo_snapend = snapend_save;
1033411677aeSAaron LI 	ndo->ndo_vflag += 3;
1034411677aeSAaron LI }
1035411677aeSAaron LI 
1036411677aeSAaron LI /* [OF10] Section 5.2.1 */
1037*ed775ee7SAntonio Huete Jimenez static void
of10_phy_port_print(netdissect_options * ndo,const u_char * cp)1038*ed775ee7SAntonio Huete Jimenez of10_phy_port_print(netdissect_options *ndo,
1039*ed775ee7SAntonio Huete Jimenez                     const u_char *cp)
1040411677aeSAaron LI {
1041*ed775ee7SAntonio Huete Jimenez 	uint32_t state;
1042411677aeSAaron LI 
1043411677aeSAaron LI 	/* port_no */
1044*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("\n\t  port_no %s",
1045*ed775ee7SAntonio Huete Jimenez 		 tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1046411677aeSAaron LI 	cp += 2;
1047411677aeSAaron LI 	/* hw_addr */
1048*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(", hw_addr %s", GET_ETHERADDR_STRING(cp));
1049*ed775ee7SAntonio Huete Jimenez 	cp += MAC_ADDR_LEN;
1050411677aeSAaron LI 	/* name */
1051*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(", name '");
1052*ed775ee7SAntonio Huete Jimenez 	nd_printjnp(ndo, cp, OFP_MAX_PORT_NAME_LEN);
1053*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("'");
1054411677aeSAaron LI 	cp += OFP_MAX_PORT_NAME_LEN;
1055411677aeSAaron LI 
1056411677aeSAaron LI 	if (ndo->ndo_vflag < 2) {
1057*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_LEN(cp, 24);
1058*ed775ee7SAntonio Huete Jimenez 		return;
1059411677aeSAaron LI 	}
1060411677aeSAaron LI 	/* config */
1061*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("\n\t   config 0x%08x", GET_BE_U_4(cp));
1062*ed775ee7SAntonio Huete Jimenez 	of_bitmap_print(ndo, ofppc_bm, GET_BE_U_4(cp), OFPPC_U);
1063411677aeSAaron LI 	cp += 4;
1064411677aeSAaron LI 	/* state */
1065*ed775ee7SAntonio Huete Jimenez 	state = GET_BE_U_4(cp);
1066*ed775ee7SAntonio Huete Jimenez 	/*
1067*ed775ee7SAntonio Huete Jimenez 	 * Decode the code point and the single bit separately, but
1068*ed775ee7SAntonio Huete Jimenez 	 * format the result as a single sequence of comma-separated
1069*ed775ee7SAntonio Huete Jimenez 	 * strings (see the comments at the OFPPS_ props).
1070*ed775ee7SAntonio Huete Jimenez 	 */
1071*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("\n\t   state 0x%08x (%s%s)%s", state,
1072*ed775ee7SAntonio Huete Jimenez 	         tok2str(ofpps_stp_str, "", state & OFPPS_STP_MASK),
1073*ed775ee7SAntonio Huete Jimenez 	         state & OFPPS_LINK_DOWN ? ", LINK_DOWN" : "",
1074*ed775ee7SAntonio Huete Jimenez 	         state & OFPPS_U ? " (bogus)" : "");
1075411677aeSAaron LI 	cp += 4;
1076411677aeSAaron LI 	/* curr */
1077*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("\n\t   curr 0x%08x", GET_BE_U_4(cp));
1078*ed775ee7SAntonio Huete Jimenez 	of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U);
1079411677aeSAaron LI 	cp += 4;
1080411677aeSAaron LI 	/* advertised */
1081*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("\n\t   advertised 0x%08x", GET_BE_U_4(cp));
1082*ed775ee7SAntonio Huete Jimenez 	of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U);
1083411677aeSAaron LI 	cp += 4;
1084411677aeSAaron LI 	/* supported */
1085*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("\n\t   supported 0x%08x", GET_BE_U_4(cp));
1086*ed775ee7SAntonio Huete Jimenez 	of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U);
1087411677aeSAaron LI 	cp += 4;
1088411677aeSAaron LI 	/* peer */
1089*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("\n\t   peer 0x%08x", GET_BE_U_4(cp));
1090*ed775ee7SAntonio Huete Jimenez 	of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U);
1091411677aeSAaron LI }
1092411677aeSAaron LI 
1093411677aeSAaron LI /* [OF10] Section 5.2.2 */
1094*ed775ee7SAntonio Huete Jimenez static void
of10_queue_props_print(netdissect_options * ndo,const u_char * cp,u_int len)1095411677aeSAaron LI of10_queue_props_print(netdissect_options *ndo,
1096*ed775ee7SAntonio Huete Jimenez                        const u_char *cp, u_int len)
1097411677aeSAaron LI {
1098411677aeSAaron LI 	while (len) {
1099*ed775ee7SAntonio Huete Jimenez 		uint16_t property, plen;
1100411677aeSAaron LI 		u_char plen_bogus = 0, skip = 0;
1101411677aeSAaron LI 
1102*ed775ee7SAntonio Huete Jimenez 		if (len < OF_QUEUE_PROP_MINLEN)
1103411677aeSAaron LI 			goto invalid;
1104411677aeSAaron LI 		/* property */
1105*ed775ee7SAntonio Huete Jimenez 		property = GET_BE_U_2(cp);
1106*ed775ee7SAntonio Huete Jimenez 		OF_FWD(2);
1107*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\n\t   property %s", tok2str(ofpqt_str, "invalid (0x%04x)", property));
1108411677aeSAaron LI 		/* len */
1109*ed775ee7SAntonio Huete Jimenez 		plen = GET_BE_U_2(cp);
1110*ed775ee7SAntonio Huete Jimenez 		OF_FWD(2);
1111*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", len %u", plen);
1112*ed775ee7SAntonio Huete Jimenez 		if (plen < OF_QUEUE_PROP_MINLEN || plen > len + 4)
1113411677aeSAaron LI 			goto invalid;
1114411677aeSAaron LI 		/* pad */
1115*ed775ee7SAntonio Huete Jimenez 		/* Sometimes the last field, check bounds. */
1116*ed775ee7SAntonio Huete Jimenez 		OF_CHK_FWD(4);
1117411677aeSAaron LI 		/* property-specific constraints and decoding */
1118411677aeSAaron LI 		switch (property) {
1119411677aeSAaron LI 		case OFPQT_NONE:
1120*ed775ee7SAntonio Huete Jimenez 			plen_bogus = plen != OF_QUEUE_PROP_MINLEN;
1121411677aeSAaron LI 			break;
1122411677aeSAaron LI 		case OFPQT_MIN_RATE:
1123*ed775ee7SAntonio Huete Jimenez 			plen_bogus = plen != OF_QUEUE_PROP_MIN_RATE_FIXLEN;
1124411677aeSAaron LI 			break;
1125411677aeSAaron LI 		default:
1126411677aeSAaron LI 			skip = 1;
1127411677aeSAaron LI 		}
1128411677aeSAaron LI 		if (plen_bogus) {
1129*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" (bogus)");
1130411677aeSAaron LI 			skip = 1;
1131411677aeSAaron LI 		}
1132411677aeSAaron LI 		if (skip) {
1133*ed775ee7SAntonio Huete Jimenez 			/*
1134*ed775ee7SAntonio Huete Jimenez 			 * plen >= OF_QUEUE_PROP_MINLEN
1135*ed775ee7SAntonio Huete Jimenez 			 * cp is OF_QUEUE_PROP_MINLEN bytes in
1136*ed775ee7SAntonio Huete Jimenez 			 */
1137*ed775ee7SAntonio Huete Jimenez 			OF_CHK_FWD(plen - OF_QUEUE_PROP_MINLEN);
1138*ed775ee7SAntonio Huete Jimenez 			continue;
1139411677aeSAaron LI 		}
1140411677aeSAaron LI 		if (property == OFPQT_MIN_RATE) { /* the only case of property decoding */
1141411677aeSAaron LI 			/* rate */
1142*ed775ee7SAntonio Huete Jimenez 			uint16_t rate = GET_BE_U_2(cp);
1143*ed775ee7SAntonio Huete Jimenez 			OF_FWD(2);
1144411677aeSAaron LI 			if (rate > 1000)
1145*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(", rate disabled");
1146411677aeSAaron LI 			else
1147*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(", rate %u.%u%%", rate / 10, rate % 10);
1148411677aeSAaron LI 			/* pad */
1149*ed775ee7SAntonio Huete Jimenez 			/* Sometimes the last field, check bounds. */
1150*ed775ee7SAntonio Huete Jimenez 			OF_CHK_FWD(6);
1151411677aeSAaron LI 		}
1152411677aeSAaron LI 	} /* while */
1153*ed775ee7SAntonio Huete Jimenez 	return;
1154411677aeSAaron LI 
1155411677aeSAaron LI invalid: /* skip the rest of queue properties */
1156*ed775ee7SAntonio Huete Jimenez 	nd_print_invalid(ndo);
1157*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_LEN(cp, len);
1158411677aeSAaron LI }
1159411677aeSAaron LI 
1160411677aeSAaron LI /* ibid */
1161*ed775ee7SAntonio Huete Jimenez static void
of10_queues_print(netdissect_options * ndo,const u_char * cp,u_int len)1162411677aeSAaron LI of10_queues_print(netdissect_options *ndo,
1163*ed775ee7SAntonio Huete Jimenez                   const u_char *cp, u_int len)
1164411677aeSAaron LI {
1165*ed775ee7SAntonio Huete Jimenez 	while (len) {
1166411677aeSAaron LI 		uint16_t desclen;
1167411677aeSAaron LI 
1168*ed775ee7SAntonio Huete Jimenez 		if (len < OF_PACKET_QUEUE_MINLEN)
1169411677aeSAaron LI 			goto invalid;
1170411677aeSAaron LI 		/* queue_id */
1171*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\n\t  queue_id %u", GET_BE_U_4(cp));
1172*ed775ee7SAntonio Huete Jimenez 		OF_FWD(4);
1173411677aeSAaron LI 		/* len */
1174*ed775ee7SAntonio Huete Jimenez 		desclen = GET_BE_U_2(cp);
1175*ed775ee7SAntonio Huete Jimenez 		OF_FWD(2);
1176*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", len %u", desclen);
1177*ed775ee7SAntonio Huete Jimenez 		if (desclen < OF_PACKET_QUEUE_MINLEN || desclen > len + 6)
1178411677aeSAaron LI 			goto invalid;
1179411677aeSAaron LI 		/* pad */
1180*ed775ee7SAntonio Huete Jimenez 		/* Sometimes the last field, check bounds. */
1181*ed775ee7SAntonio Huete Jimenez 		OF_CHK_FWD(2);
1182411677aeSAaron LI 		/* properties */
1183*ed775ee7SAntonio Huete Jimenez 		if (ndo->ndo_vflag >= 2)
1184*ed775ee7SAntonio Huete Jimenez 			of10_queue_props_print(ndo, cp, desclen - OF_PACKET_QUEUE_MINLEN);
1185*ed775ee7SAntonio Huete Jimenez 		else
1186*ed775ee7SAntonio Huete Jimenez 			ND_TCHECK_LEN(cp, desclen - OF_PACKET_QUEUE_MINLEN);
1187*ed775ee7SAntonio Huete Jimenez 		OF_FWD(desclen - OF_PACKET_QUEUE_MINLEN);
1188411677aeSAaron LI 	} /* while */
1189*ed775ee7SAntonio Huete Jimenez 	return;
1190411677aeSAaron LI 
1191411677aeSAaron LI invalid: /* skip the rest of queues */
1192*ed775ee7SAntonio Huete Jimenez 	nd_print_invalid(ndo);
1193*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_LEN(cp, len);
1194411677aeSAaron LI }
1195411677aeSAaron LI 
1196411677aeSAaron LI /* [OF10] Section 5.2.3 */
1197*ed775ee7SAntonio Huete Jimenez static void
of10_match_print(netdissect_options * ndo,const char * pfx,const u_char * cp)1198411677aeSAaron LI of10_match_print(netdissect_options *ndo,
1199*ed775ee7SAntonio Huete Jimenez                  const char *pfx, const u_char *cp)
1200411677aeSAaron LI {
1201411677aeSAaron LI 	uint32_t wildcards;
1202411677aeSAaron LI 	uint16_t dl_type;
1203411677aeSAaron LI 	uint8_t nw_proto;
1204*ed775ee7SAntonio Huete Jimenez 	u_int nw_bits;
1205411677aeSAaron LI 	const char *field_name;
1206411677aeSAaron LI 
1207411677aeSAaron LI 	/* wildcards */
1208*ed775ee7SAntonio Huete Jimenez 	wildcards = GET_BE_U_4(cp);
1209411677aeSAaron LI 	if (wildcards & OFPFW_U)
1210*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("%swildcards 0x%08x (bogus)", pfx, wildcards);
1211411677aeSAaron LI 	cp += 4;
1212411677aeSAaron LI 	/* in_port */
1213411677aeSAaron LI 	if (! (wildcards & OFPFW_IN_PORT))
1214*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("%smatch in_port %s", pfx,
1215*ed775ee7SAntonio Huete Jimenez 		         tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1216411677aeSAaron LI 	cp += 2;
1217411677aeSAaron LI 	/* dl_src */
1218411677aeSAaron LI 	if (! (wildcards & OFPFW_DL_SRC))
1219*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("%smatch dl_src %s", pfx, GET_ETHERADDR_STRING(cp));
1220*ed775ee7SAntonio Huete Jimenez 	cp += MAC_ADDR_LEN;
1221411677aeSAaron LI 	/* dl_dst */
1222411677aeSAaron LI 	if (! (wildcards & OFPFW_DL_DST))
1223*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("%smatch dl_dst %s", pfx, GET_ETHERADDR_STRING(cp));
1224*ed775ee7SAntonio Huete Jimenez 	cp += MAC_ADDR_LEN;
1225411677aeSAaron LI 	/* dl_vlan */
1226411677aeSAaron LI 	if (! (wildcards & OFPFW_DL_VLAN))
1227*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("%smatch dl_vlan %s", pfx, vlan_str(GET_BE_U_2(cp)));
1228411677aeSAaron LI 	cp += 2;
1229411677aeSAaron LI 	/* dl_vlan_pcp */
1230411677aeSAaron LI 	if (! (wildcards & OFPFW_DL_VLAN_PCP))
1231*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("%smatch dl_vlan_pcp %s", pfx, pcp_str(GET_U_1(cp)));
1232411677aeSAaron LI 	cp += 1;
1233411677aeSAaron LI 	/* pad1 */
1234411677aeSAaron LI 	cp += 1;
1235411677aeSAaron LI 	/* dl_type */
1236*ed775ee7SAntonio Huete Jimenez 	dl_type = GET_BE_U_2(cp);
1237411677aeSAaron LI 	cp += 2;
1238411677aeSAaron LI 	if (! (wildcards & OFPFW_DL_TYPE))
1239*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("%smatch dl_type 0x%04x", pfx, dl_type);
1240411677aeSAaron LI 	/* nw_tos */
1241411677aeSAaron LI 	if (! (wildcards & OFPFW_NW_TOS))
1242*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("%smatch nw_tos 0x%02x", pfx, GET_U_1(cp));
1243411677aeSAaron LI 	cp += 1;
1244411677aeSAaron LI 	/* nw_proto */
1245*ed775ee7SAntonio Huete Jimenez 	nw_proto = GET_U_1(cp);
1246411677aeSAaron LI 	cp += 1;
1247411677aeSAaron LI 	if (! (wildcards & OFPFW_NW_PROTO)) {
1248411677aeSAaron LI 		field_name = ! (wildcards & OFPFW_DL_TYPE) && dl_type == ETHERTYPE_ARP
1249411677aeSAaron LI 		  ? "arp_opcode" : "nw_proto";
1250*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("%smatch %s %u", pfx, field_name, nw_proto);
1251411677aeSAaron LI 	}
1252411677aeSAaron LI 	/* pad2 */
1253411677aeSAaron LI 	cp += 2;
1254411677aeSAaron LI 	/* nw_src */
1255411677aeSAaron LI 	nw_bits = (wildcards & OFPFW_NW_SRC_MASK) >> OFPFW_NW_SRC_SHIFT;
1256411677aeSAaron LI 	if (nw_bits < 32)
1257*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("%smatch nw_src %s/%u", pfx, GET_IPADDR_STRING(cp), 32 - nw_bits);
1258411677aeSAaron LI 	cp += 4;
1259411677aeSAaron LI 	/* nw_dst */
1260411677aeSAaron LI 	nw_bits = (wildcards & OFPFW_NW_DST_MASK) >> OFPFW_NW_DST_SHIFT;
1261411677aeSAaron LI 	if (nw_bits < 32)
1262*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("%smatch nw_dst %s/%u", pfx, GET_IPADDR_STRING(cp), 32 - nw_bits);
1263411677aeSAaron LI 	cp += 4;
1264411677aeSAaron LI 	/* tp_src */
1265411677aeSAaron LI 	if (! (wildcards & OFPFW_TP_SRC)) {
1266411677aeSAaron LI 		field_name = ! (wildcards & OFPFW_DL_TYPE) && dl_type == ETHERTYPE_IP
1267411677aeSAaron LI 		  && ! (wildcards & OFPFW_NW_PROTO) && nw_proto == IPPROTO_ICMP
1268411677aeSAaron LI 		  ? "icmp_type" : "tp_src";
1269*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("%smatch %s %u", pfx, field_name, GET_BE_U_2(cp));
1270411677aeSAaron LI 	}
1271411677aeSAaron LI 	cp += 2;
1272411677aeSAaron LI 	/* tp_dst */
1273*ed775ee7SAntonio Huete Jimenez 	/* The last unconditional check was at nw_proto, so have an "else" here. */
1274411677aeSAaron LI 	if (! (wildcards & OFPFW_TP_DST)) {
1275411677aeSAaron LI 		field_name = ! (wildcards & OFPFW_DL_TYPE) && dl_type == ETHERTYPE_IP
1276411677aeSAaron LI 		  && ! (wildcards & OFPFW_NW_PROTO) && nw_proto == IPPROTO_ICMP
1277411677aeSAaron LI 		  ? "icmp_code" : "tp_dst";
1278*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("%smatch %s %u", pfx, field_name, GET_BE_U_2(cp));
1279411677aeSAaron LI 	}
1280*ed775ee7SAntonio Huete Jimenez 	else
1281*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_2(cp);
1282411677aeSAaron LI }
1283411677aeSAaron LI 
1284411677aeSAaron LI /* [OF10] Section 5.2.4 */
1285*ed775ee7SAntonio Huete Jimenez static void
of10_actions_print(netdissect_options * ndo,const char * pfx,const u_char * cp,u_int len)1286411677aeSAaron LI of10_actions_print(netdissect_options *ndo,
1287*ed775ee7SAntonio Huete Jimenez                    const char *pfx, const u_char *cp, u_int len)
1288411677aeSAaron LI {
1289411677aeSAaron LI 	while (len) {
1290*ed775ee7SAntonio Huete Jimenez 		uint16_t type, alen, output_port;
1291411677aeSAaron LI 		u_char alen_bogus = 0, skip = 0;
1292411677aeSAaron LI 
1293*ed775ee7SAntonio Huete Jimenez 		if (len < OF_ACTION_MINLEN)
1294411677aeSAaron LI 			goto invalid;
1295411677aeSAaron LI 		/* type */
1296*ed775ee7SAntonio Huete Jimenez 		type = GET_BE_U_2(cp);
1297*ed775ee7SAntonio Huete Jimenez 		OF_FWD(2);
1298*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("%saction type %s", pfx, tok2str(ofpat_str, "invalid (0x%04x)", type));
1299411677aeSAaron LI 		/* length */
1300*ed775ee7SAntonio Huete Jimenez 		alen = GET_BE_U_2(cp);
1301*ed775ee7SAntonio Huete Jimenez 		OF_FWD(2);
1302*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", len %u", alen);
1303*ed775ee7SAntonio Huete Jimenez 		/*
1304*ed775ee7SAntonio Huete Jimenez 		 * The 4-byte "pad" in the specification is not a field of the
1305*ed775ee7SAntonio Huete Jimenez 		 * action header, but a placeholder to illustrate the 64-bit
1306*ed775ee7SAntonio Huete Jimenez 		 * alignment requirement. Action type specific case blocks
1307*ed775ee7SAntonio Huete Jimenez 		 * below fetch these 4 bytes.
1308*ed775ee7SAntonio Huete Jimenez 		 */
1309*ed775ee7SAntonio Huete Jimenez 
1310411677aeSAaron LI 		/* On action size underrun/overrun skip the rest of the action list. */
1311*ed775ee7SAntonio Huete Jimenez 		if (alen < OF_ACTION_MINLEN || alen > len + 4)
1312411677aeSAaron LI 			goto invalid;
1313*ed775ee7SAntonio Huete Jimenez 		/*
1314*ed775ee7SAntonio Huete Jimenez 		 * After validating the basic length constraint it will be safe
1315*ed775ee7SAntonio Huete Jimenez 		 * to skip the current action if the action size is not valid
1316*ed775ee7SAntonio Huete Jimenez 		 * for the type or the type is invalid.
1317*ed775ee7SAntonio Huete Jimenez 		 */
1318411677aeSAaron LI 		switch (type) {
1319411677aeSAaron LI 		case OFPAT_OUTPUT:
1320411677aeSAaron LI 		case OFPAT_SET_VLAN_VID:
1321411677aeSAaron LI 		case OFPAT_SET_VLAN_PCP:
1322411677aeSAaron LI 		case OFPAT_STRIP_VLAN:
1323411677aeSAaron LI 		case OFPAT_SET_NW_SRC:
1324411677aeSAaron LI 		case OFPAT_SET_NW_DST:
1325411677aeSAaron LI 		case OFPAT_SET_NW_TOS:
1326411677aeSAaron LI 		case OFPAT_SET_TP_SRC:
1327411677aeSAaron LI 		case OFPAT_SET_TP_DST:
1328411677aeSAaron LI 			alen_bogus = alen != 8;
1329411677aeSAaron LI 			break;
1330411677aeSAaron LI 		case OFPAT_SET_DL_SRC:
1331411677aeSAaron LI 		case OFPAT_SET_DL_DST:
1332411677aeSAaron LI 		case OFPAT_ENQUEUE:
1333411677aeSAaron LI 			alen_bogus = alen != 16;
1334411677aeSAaron LI 			break;
1335411677aeSAaron LI 		case OFPAT_VENDOR:
1336411677aeSAaron LI 			alen_bogus = alen % 8 != 0; /* already >= 8 so far */
1337411677aeSAaron LI 			break;
1338411677aeSAaron LI 		default:
1339411677aeSAaron LI 			skip = 1;
1340411677aeSAaron LI 		}
1341411677aeSAaron LI 		if (alen_bogus) {
1342*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" (bogus)");
1343411677aeSAaron LI 			skip = 1;
1344411677aeSAaron LI 		}
1345411677aeSAaron LI 		if (skip) {
1346*ed775ee7SAntonio Huete Jimenez 			/*
1347*ed775ee7SAntonio Huete Jimenez 			 * alen >= OF_ACTION_MINLEN
1348*ed775ee7SAntonio Huete Jimenez 			 * cp is 4 bytes in
1349*ed775ee7SAntonio Huete Jimenez 			 */
1350*ed775ee7SAntonio Huete Jimenez 			OF_CHK_FWD(alen - 4);
1351*ed775ee7SAntonio Huete Jimenez 			continue;
1352411677aeSAaron LI 		}
1353411677aeSAaron LI 		/* OK to decode the rest of the action structure */
1354411677aeSAaron LI 		switch (type) {
1355411677aeSAaron LI 		case OFPAT_OUTPUT:
1356411677aeSAaron LI 			/* port */
1357*ed775ee7SAntonio Huete Jimenez 			output_port = GET_BE_U_2(cp);
1358*ed775ee7SAntonio Huete Jimenez 			OF_FWD(2);
1359*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(", port %s", tok2str(ofpp_str, "%u", output_port));
1360411677aeSAaron LI 			/* max_len */
1361411677aeSAaron LI 			if (output_port == OFPP_CONTROLLER)
1362*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(", max_len %u", GET_BE_U_2(cp));
1363*ed775ee7SAntonio Huete Jimenez 			else
1364*ed775ee7SAntonio Huete Jimenez 				ND_TCHECK_2(cp);
1365*ed775ee7SAntonio Huete Jimenez 			OF_FWD(2);
1366411677aeSAaron LI 			break;
1367411677aeSAaron LI 		case OFPAT_SET_VLAN_VID:
1368411677aeSAaron LI 			/* vlan_vid */
1369*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(", vlan_vid %s", vlan_str(GET_BE_U_2(cp)));
1370*ed775ee7SAntonio Huete Jimenez 			OF_FWD(2);
1371411677aeSAaron LI 			/* pad */
1372*ed775ee7SAntonio Huete Jimenez 			/* Sometimes the last field, check bounds. */
1373*ed775ee7SAntonio Huete Jimenez 			OF_CHK_FWD(2);
1374411677aeSAaron LI 			break;
1375411677aeSAaron LI 		case OFPAT_SET_VLAN_PCP:
1376411677aeSAaron LI 			/* vlan_pcp */
1377*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(", vlan_pcp %s", pcp_str(GET_U_1(cp)));
1378*ed775ee7SAntonio Huete Jimenez 			OF_FWD(1);
1379411677aeSAaron LI 			/* pad */
1380*ed775ee7SAntonio Huete Jimenez 			/* Sometimes the last field, check bounds. */
1381*ed775ee7SAntonio Huete Jimenez 			OF_CHK_FWD(3);
1382411677aeSAaron LI 			break;
1383411677aeSAaron LI 		case OFPAT_SET_DL_SRC:
1384411677aeSAaron LI 		case OFPAT_SET_DL_DST:
1385411677aeSAaron LI 			/* dl_addr */
1386*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(", dl_addr %s", GET_ETHERADDR_STRING(cp));
1387*ed775ee7SAntonio Huete Jimenez 			OF_FWD(MAC_ADDR_LEN);
1388411677aeSAaron LI 			/* pad */
1389*ed775ee7SAntonio Huete Jimenez 			/* Sometimes the last field, check bounds. */
1390*ed775ee7SAntonio Huete Jimenez 			OF_CHK_FWD(6);
1391411677aeSAaron LI 			break;
1392411677aeSAaron LI 		case OFPAT_SET_NW_SRC:
1393411677aeSAaron LI 		case OFPAT_SET_NW_DST:
1394411677aeSAaron LI 			/* nw_addr */
1395*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(", nw_addr %s", GET_IPADDR_STRING(cp));
1396*ed775ee7SAntonio Huete Jimenez 			OF_FWD(4);
1397411677aeSAaron LI 			break;
1398411677aeSAaron LI 		case OFPAT_SET_NW_TOS:
1399411677aeSAaron LI 			/* nw_tos */
1400*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(", nw_tos 0x%02x", GET_U_1(cp));
1401*ed775ee7SAntonio Huete Jimenez 			OF_FWD(1);
1402411677aeSAaron LI 			/* pad */
1403*ed775ee7SAntonio Huete Jimenez 			/* Sometimes the last field, check bounds. */
1404*ed775ee7SAntonio Huete Jimenez 			OF_CHK_FWD(3);
1405411677aeSAaron LI 			break;
1406411677aeSAaron LI 		case OFPAT_SET_TP_SRC:
1407411677aeSAaron LI 		case OFPAT_SET_TP_DST:
1408411677aeSAaron LI 			/* nw_tos */
1409*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(", tp_port %u", GET_BE_U_2(cp));
1410*ed775ee7SAntonio Huete Jimenez 			OF_FWD(2);
1411411677aeSAaron LI 			/* pad */
1412*ed775ee7SAntonio Huete Jimenez 			/* Sometimes the last field, check bounds. */
1413*ed775ee7SAntonio Huete Jimenez 			OF_CHK_FWD(2);
1414411677aeSAaron LI 			break;
1415411677aeSAaron LI 		case OFPAT_ENQUEUE:
1416411677aeSAaron LI 			/* port */
1417*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(", port %s",
1418*ed775ee7SAntonio Huete Jimenez 				 tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1419*ed775ee7SAntonio Huete Jimenez 			OF_FWD(2);
1420411677aeSAaron LI 			/* pad */
1421*ed775ee7SAntonio Huete Jimenez 			OF_FWD(6);
1422411677aeSAaron LI 			/* queue_id */
1423*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(", queue_id %s",
1424*ed775ee7SAntonio Huete Jimenez 				 tok2str(ofpq_str, "%u", GET_BE_U_4(cp)));
1425*ed775ee7SAntonio Huete Jimenez 			OF_FWD(4);
1426411677aeSAaron LI 			break;
1427411677aeSAaron LI 		case OFPAT_VENDOR:
1428*ed775ee7SAntonio Huete Jimenez 			of10_vendor_action_print(ndo, cp, alen - 4);
1429*ed775ee7SAntonio Huete Jimenez 			OF_FWD(alen - 4);
1430411677aeSAaron LI 			break;
1431411677aeSAaron LI 		case OFPAT_STRIP_VLAN:
1432411677aeSAaron LI 			/* pad */
1433*ed775ee7SAntonio Huete Jimenez 			/* Sometimes the last field, check bounds. */
1434*ed775ee7SAntonio Huete Jimenez 			OF_CHK_FWD(4);
1435411677aeSAaron LI 			break;
1436411677aeSAaron LI 		} /* switch */
1437411677aeSAaron LI 	} /* while */
1438*ed775ee7SAntonio Huete Jimenez 	return;
1439411677aeSAaron LI 
1440411677aeSAaron LI invalid: /* skip the rest of actions */
1441*ed775ee7SAntonio Huete Jimenez 	nd_print_invalid(ndo);
1442*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_LEN(cp, len);
1443411677aeSAaron LI }
1444411677aeSAaron LI 
1445411677aeSAaron LI /* [OF10] Section 5.3.1 */
1446*ed775ee7SAntonio Huete Jimenez static void
of10_features_reply_print(netdissect_options * ndo,const u_char * cp,u_int len)1447411677aeSAaron LI of10_features_reply_print(netdissect_options *ndo,
1448*ed775ee7SAntonio Huete Jimenez                           const u_char *cp, u_int len)
1449411677aeSAaron LI {
1450411677aeSAaron LI 	/* datapath_id */
1451*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("\n\t dpid 0x%016" PRIx64, GET_BE_U_8(cp));
1452*ed775ee7SAntonio Huete Jimenez 	OF_FWD(8);
1453411677aeSAaron LI 	/* n_buffers */
1454*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(", n_buffers %u", GET_BE_U_4(cp));
1455*ed775ee7SAntonio Huete Jimenez 	OF_FWD(4);
1456411677aeSAaron LI 	/* n_tables */
1457*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(", n_tables %u", GET_U_1(cp));
1458*ed775ee7SAntonio Huete Jimenez 	OF_FWD(1);
1459411677aeSAaron LI 	/* pad */
1460*ed775ee7SAntonio Huete Jimenez 	OF_FWD(3);
1461411677aeSAaron LI 	/* capabilities */
1462*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("\n\t capabilities 0x%08x", GET_BE_U_4(cp));
1463*ed775ee7SAntonio Huete Jimenez 	of_bitmap_print(ndo, ofp_capabilities_bm, GET_BE_U_4(cp), OFPCAP_U);
1464*ed775ee7SAntonio Huete Jimenez 	OF_FWD(4);
1465411677aeSAaron LI 	/* actions */
1466*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("\n\t actions 0x%08x", GET_BE_U_4(cp));
1467*ed775ee7SAntonio Huete Jimenez 	of_bitmap_print(ndo, ofpat_bm, GET_BE_U_4(cp), OFPAT_U);
1468*ed775ee7SAntonio Huete Jimenez 	OF_FWD(4);
1469411677aeSAaron LI 	/* ports */
1470*ed775ee7SAntonio Huete Jimenez 	while (len) {
1471*ed775ee7SAntonio Huete Jimenez 		if (len < OF_PHY_PORT_FIXLEN)
1472*ed775ee7SAntonio Huete Jimenez 			goto invalid;
1473*ed775ee7SAntonio Huete Jimenez 		of10_phy_port_print(ndo, cp);
1474*ed775ee7SAntonio Huete Jimenez 		OF_FWD(OF_PHY_PORT_FIXLEN);
1475*ed775ee7SAntonio Huete Jimenez 	}
1476*ed775ee7SAntonio Huete Jimenez 	return;
1477411677aeSAaron LI 
1478*ed775ee7SAntonio Huete Jimenez invalid: /* skip the undersized trailing data */
1479*ed775ee7SAntonio Huete Jimenez 	nd_print_invalid(ndo);
1480*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_LEN(cp, len);
1481*ed775ee7SAntonio Huete Jimenez }
1482*ed775ee7SAntonio Huete Jimenez 
1483*ed775ee7SAntonio Huete Jimenez /* [OF10] Section 5.3.2 */
1484*ed775ee7SAntonio Huete Jimenez static void
of10_switch_config_msg_print(netdissect_options * ndo,const u_char * cp,u_int len _U_)1485*ed775ee7SAntonio Huete Jimenez of10_switch_config_msg_print(netdissect_options *ndo,
1486*ed775ee7SAntonio Huete Jimenez                              const u_char *cp, u_int len _U_)
1487*ed775ee7SAntonio Huete Jimenez {
1488*ed775ee7SAntonio Huete Jimenez 	/* flags */
1489*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("\n\t flags %s",
1490*ed775ee7SAntonio Huete Jimenez 	         tok2str(ofp_config_str, "invalid (0x%04x)", GET_BE_U_2(cp)));
1491*ed775ee7SAntonio Huete Jimenez 	cp += 2;
1492*ed775ee7SAntonio Huete Jimenez 	/* miss_send_len */
1493*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(", miss_send_len %u", GET_BE_U_2(cp));
1494411677aeSAaron LI }
1495411677aeSAaron LI 
1496411677aeSAaron LI /* [OF10] Section 5.3.3 */
1497*ed775ee7SAntonio Huete Jimenez static void
of10_flow_mod_print(netdissect_options * ndo,const u_char * cp,u_int len)1498411677aeSAaron LI of10_flow_mod_print(netdissect_options *ndo,
1499*ed775ee7SAntonio Huete Jimenez                     const u_char *cp, u_int len)
1500411677aeSAaron LI {
1501411677aeSAaron LI 	uint16_t command;
1502411677aeSAaron LI 
1503411677aeSAaron LI 	/* match */
1504*ed775ee7SAntonio Huete Jimenez 	of10_match_print(ndo, "\n\t ", cp);
1505*ed775ee7SAntonio Huete Jimenez 	OF_FWD(OF_MATCH_FIXLEN);
1506411677aeSAaron LI 	/* cookie */
1507*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("\n\t cookie 0x%016" PRIx64, GET_BE_U_8(cp));
1508*ed775ee7SAntonio Huete Jimenez 	OF_FWD(8);
1509411677aeSAaron LI 	/* command */
1510*ed775ee7SAntonio Huete Jimenez 	command = GET_BE_U_2(cp);
1511*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(", command %s", tok2str(ofpfc_str, "invalid (0x%04x)", command));
1512*ed775ee7SAntonio Huete Jimenez 	OF_FWD(2);
1513411677aeSAaron LI 	/* idle_timeout */
1514*ed775ee7SAntonio Huete Jimenez 	if (GET_BE_U_2(cp))
1515*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", idle_timeout %u", GET_BE_U_2(cp));
1516*ed775ee7SAntonio Huete Jimenez 	OF_FWD(2);
1517411677aeSAaron LI 	/* hard_timeout */
1518*ed775ee7SAntonio Huete Jimenez 	if (GET_BE_U_2(cp))
1519*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", hard_timeout %u", GET_BE_U_2(cp));
1520*ed775ee7SAntonio Huete Jimenez 	OF_FWD(2);
1521411677aeSAaron LI 	/* priority */
1522*ed775ee7SAntonio Huete Jimenez 	if (GET_BE_U_2(cp))
1523*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", priority %u", GET_BE_U_2(cp));
1524*ed775ee7SAntonio Huete Jimenez 	OF_FWD(2);
1525411677aeSAaron LI 	/* buffer_id */
1526411677aeSAaron LI 	if (command == OFPFC_ADD || command == OFPFC_MODIFY ||
1527411677aeSAaron LI 	    command == OFPFC_MODIFY_STRICT)
1528*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", buffer_id %s",
1529*ed775ee7SAntonio Huete Jimenez 		         tok2str(bufferid_str, "0x%08x", GET_BE_U_4(cp)));
1530*ed775ee7SAntonio Huete Jimenez 	OF_FWD(4);
1531411677aeSAaron LI 	/* out_port */
1532411677aeSAaron LI 	if (command == OFPFC_DELETE || command == OFPFC_DELETE_STRICT)
1533*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", out_port %s",
1534*ed775ee7SAntonio Huete Jimenez 		         tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1535*ed775ee7SAntonio Huete Jimenez 	OF_FWD(2);
1536411677aeSAaron LI 	/* flags */
1537*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(", flags 0x%04x", GET_BE_U_2(cp));
1538*ed775ee7SAntonio Huete Jimenez 	of_bitmap_print(ndo, ofpff_bm, GET_BE_U_2(cp), OFPFF_U);
1539*ed775ee7SAntonio Huete Jimenez 	OF_FWD(2);
1540411677aeSAaron LI 	/* actions */
1541*ed775ee7SAntonio Huete Jimenez 	of10_actions_print(ndo, "\n\t ", cp, len);
1542411677aeSAaron LI }
1543411677aeSAaron LI 
1544411677aeSAaron LI /* ibid */
1545*ed775ee7SAntonio Huete Jimenez static void
of10_port_mod_print(netdissect_options * ndo,const u_char * cp,u_int len _U_)1546411677aeSAaron LI of10_port_mod_print(netdissect_options *ndo,
1547*ed775ee7SAntonio Huete Jimenez                     const u_char *cp, u_int len _U_)
1548411677aeSAaron LI {
1549411677aeSAaron LI 	/* port_no */
1550*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("\n\t port_no %s", tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1551411677aeSAaron LI 	cp += 2;
1552411677aeSAaron LI 	/* hw_addr */
1553*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(", hw_addr %s", GET_ETHERADDR_STRING(cp));
1554*ed775ee7SAntonio Huete Jimenez 	cp += MAC_ADDR_LEN;
1555411677aeSAaron LI 	/* config */
1556*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("\n\t config 0x%08x", GET_BE_U_4(cp));
1557*ed775ee7SAntonio Huete Jimenez 	of_bitmap_print(ndo, ofppc_bm, GET_BE_U_4(cp), OFPPC_U);
1558411677aeSAaron LI 	cp += 4;
1559411677aeSAaron LI 	/* mask */
1560*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("\n\t mask 0x%08x", GET_BE_U_4(cp));
1561*ed775ee7SAntonio Huete Jimenez 	of_bitmap_print(ndo, ofppc_bm, GET_BE_U_4(cp), OFPPC_U);
1562411677aeSAaron LI 	cp += 4;
1563411677aeSAaron LI 	/* advertise */
1564*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("\n\t advertise 0x%08x", GET_BE_U_4(cp));
1565*ed775ee7SAntonio Huete Jimenez 	of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U);
1566411677aeSAaron LI 	cp += 4;
1567411677aeSAaron LI 	/* pad */
1568*ed775ee7SAntonio Huete Jimenez 	/* Always the last field, check bounds. */
1569*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_4(cp);
1570*ed775ee7SAntonio Huete Jimenez }
1571411677aeSAaron LI 
1572*ed775ee7SAntonio Huete Jimenez /* [OF10] Section 5.3.4 */
1573*ed775ee7SAntonio Huete Jimenez static void
of10_queue_get_config_request_print(netdissect_options * ndo,const u_char * cp,u_int len _U_)1574*ed775ee7SAntonio Huete Jimenez of10_queue_get_config_request_print(netdissect_options *ndo,
1575*ed775ee7SAntonio Huete Jimenez                                     const u_char *cp, u_int len _U_)
1576*ed775ee7SAntonio Huete Jimenez {
1577*ed775ee7SAntonio Huete Jimenez 	/* port */
1578*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("\n\t port %s", tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1579*ed775ee7SAntonio Huete Jimenez 	cp += 2;
1580*ed775ee7SAntonio Huete Jimenez 	/* pad */
1581*ed775ee7SAntonio Huete Jimenez 	/* Always the last field, check bounds. */
1582*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_2(cp);
1583*ed775ee7SAntonio Huete Jimenez }
1584*ed775ee7SAntonio Huete Jimenez 
1585*ed775ee7SAntonio Huete Jimenez /* ibid */
1586*ed775ee7SAntonio Huete Jimenez static void
of10_queue_get_config_reply_print(netdissect_options * ndo,const u_char * cp,u_int len)1587*ed775ee7SAntonio Huete Jimenez of10_queue_get_config_reply_print(netdissect_options *ndo,
1588*ed775ee7SAntonio Huete Jimenez                                   const u_char *cp, u_int len)
1589*ed775ee7SAntonio Huete Jimenez {
1590*ed775ee7SAntonio Huete Jimenez 	/* port */
1591*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("\n\t port %s", tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1592*ed775ee7SAntonio Huete Jimenez 	OF_FWD(2);
1593*ed775ee7SAntonio Huete Jimenez 	/* pad */
1594*ed775ee7SAntonio Huete Jimenez 	/* Sometimes the last field, check bounds. */
1595*ed775ee7SAntonio Huete Jimenez 	OF_CHK_FWD(6);
1596*ed775ee7SAntonio Huete Jimenez 	/* queues */
1597*ed775ee7SAntonio Huete Jimenez 	of10_queues_print(ndo, cp, len);
1598411677aeSAaron LI }
1599411677aeSAaron LI 
1600411677aeSAaron LI /* [OF10] Section 5.3.5 */
1601*ed775ee7SAntonio Huete Jimenez static void
of10_stats_request_print(netdissect_options * ndo,const u_char * cp,u_int len)1602411677aeSAaron LI of10_stats_request_print(netdissect_options *ndo,
1603*ed775ee7SAntonio Huete Jimenez                          const u_char *cp, u_int len)
1604411677aeSAaron LI {
1605411677aeSAaron LI 	uint16_t type;
1606411677aeSAaron LI 
1607411677aeSAaron LI 	/* type */
1608*ed775ee7SAntonio Huete Jimenez 	type = GET_BE_U_2(cp);
1609*ed775ee7SAntonio Huete Jimenez 	OF_FWD(2);
1610*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("\n\t type %s", tok2str(ofpst_str, "invalid (0x%04x)", type));
1611411677aeSAaron LI 	/* flags */
1612*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(", flags 0x%04x", GET_BE_U_2(cp));
1613*ed775ee7SAntonio Huete Jimenez 	if (GET_BE_U_2(cp))
1614*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(" (bogus)");
1615*ed775ee7SAntonio Huete Jimenez 	OF_FWD(2);
1616411677aeSAaron LI 	/* type-specific body of one of fixed lengths */
1617411677aeSAaron LI 	switch(type) {
1618411677aeSAaron LI 	case OFPST_DESC:
1619411677aeSAaron LI 	case OFPST_TABLE:
1620411677aeSAaron LI 		if (len)
1621411677aeSAaron LI 			goto invalid;
1622*ed775ee7SAntonio Huete Jimenez 		return;
1623411677aeSAaron LI 	case OFPST_FLOW:
1624411677aeSAaron LI 	case OFPST_AGGREGATE:
1625*ed775ee7SAntonio Huete Jimenez 		if (len != OF_FLOW_STATS_REQUEST_FIXLEN)
1626411677aeSAaron LI 			goto invalid;
1627411677aeSAaron LI 		/* match */
1628*ed775ee7SAntonio Huete Jimenez 		of10_match_print(ndo, "\n\t ", cp);
1629*ed775ee7SAntonio Huete Jimenez 		OF_FWD(OF_MATCH_FIXLEN);
1630411677aeSAaron LI 		/* table_id */
1631*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\n\t table_id %s",
1632*ed775ee7SAntonio Huete Jimenez 			 tok2str(tableid_str, "%u", GET_U_1(cp)));
1633*ed775ee7SAntonio Huete Jimenez 		OF_FWD(1);
1634411677aeSAaron LI 		/* pad */
1635*ed775ee7SAntonio Huete Jimenez 		OF_FWD(1);
1636411677aeSAaron LI 		/* out_port */
1637*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", out_port %s",
1638*ed775ee7SAntonio Huete Jimenez 			 tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1639*ed775ee7SAntonio Huete Jimenez 		return;
1640411677aeSAaron LI 	case OFPST_PORT:
1641*ed775ee7SAntonio Huete Jimenez 		if (len != OF_PORT_STATS_REQUEST_FIXLEN)
1642411677aeSAaron LI 			goto invalid;
1643411677aeSAaron LI 		/* port_no */
1644*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\n\t port_no %s",
1645*ed775ee7SAntonio Huete Jimenez 			 tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1646*ed775ee7SAntonio Huete Jimenez 		OF_FWD(2);
1647411677aeSAaron LI 		/* pad */
1648*ed775ee7SAntonio Huete Jimenez 		/* Always the last field, check bounds. */
1649*ed775ee7SAntonio Huete Jimenez 		OF_CHK_FWD(6);
1650*ed775ee7SAntonio Huete Jimenez 		return;
1651411677aeSAaron LI 	case OFPST_QUEUE:
1652*ed775ee7SAntonio Huete Jimenez 		if (len != OF_QUEUE_STATS_REQUEST_FIXLEN)
1653411677aeSAaron LI 			goto invalid;
1654411677aeSAaron LI 		/* port_no */
1655*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\n\t port_no %s",
1656*ed775ee7SAntonio Huete Jimenez 			 tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1657*ed775ee7SAntonio Huete Jimenez 		OF_FWD(2);
1658411677aeSAaron LI 		/* pad */
1659*ed775ee7SAntonio Huete Jimenez 		OF_FWD(2);
1660411677aeSAaron LI 		/* queue_id */
1661*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", queue_id %s",
1662*ed775ee7SAntonio Huete Jimenez 			 tok2str(ofpq_str, "%u", GET_BE_U_4(cp)));
1663*ed775ee7SAntonio Huete Jimenez 		return;
1664411677aeSAaron LI 	case OFPST_VENDOR:
1665*ed775ee7SAntonio Huete Jimenez 		of10_vendor_data_print(ndo, cp, len);
1666*ed775ee7SAntonio Huete Jimenez 		return;
1667411677aeSAaron LI 	}
1668*ed775ee7SAntonio Huete Jimenez 	return;
1669411677aeSAaron LI 
1670411677aeSAaron LI invalid: /* skip the message body */
1671*ed775ee7SAntonio Huete Jimenez 	nd_print_invalid(ndo);
1672*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_LEN(cp, len);
1673411677aeSAaron LI }
1674411677aeSAaron LI 
1675411677aeSAaron LI /* ibid */
1676*ed775ee7SAntonio Huete Jimenez static void
of10_desc_stats_reply_print(netdissect_options * ndo,const u_char * cp,u_int len)1677411677aeSAaron LI of10_desc_stats_reply_print(netdissect_options *ndo,
1678*ed775ee7SAntonio Huete Jimenez                             const u_char *cp, u_int len)
1679411677aeSAaron LI {
1680*ed775ee7SAntonio Huete Jimenez 	if (len != OF_DESC_STATS_REPLY_FIXLEN)
1681411677aeSAaron LI 		goto invalid;
1682411677aeSAaron LI 	/* mfr_desc */
1683*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("\n\t  mfr_desc '");
1684*ed775ee7SAntonio Huete Jimenez 	nd_printjnp(ndo, cp, DESC_STR_LEN);
1685*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("'");
1686*ed775ee7SAntonio Huete Jimenez 	OF_FWD(DESC_STR_LEN);
1687411677aeSAaron LI 	/* hw_desc */
1688*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("\n\t  hw_desc '");
1689*ed775ee7SAntonio Huete Jimenez 	nd_printjnp(ndo, cp, DESC_STR_LEN);
1690*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("'");
1691*ed775ee7SAntonio Huete Jimenez 	OF_FWD(DESC_STR_LEN);
1692411677aeSAaron LI 	/* sw_desc */
1693*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("\n\t  sw_desc '");
1694*ed775ee7SAntonio Huete Jimenez 	nd_printjnp(ndo, cp, DESC_STR_LEN);
1695*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("'");
1696*ed775ee7SAntonio Huete Jimenez 	OF_FWD(DESC_STR_LEN);
1697411677aeSAaron LI 	/* serial_num */
1698*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("\n\t  serial_num '");
1699*ed775ee7SAntonio Huete Jimenez 	nd_printjnp(ndo, cp, SERIAL_NUM_LEN);
1700*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("'");
1701*ed775ee7SAntonio Huete Jimenez 	OF_FWD(SERIAL_NUM_LEN);
1702411677aeSAaron LI 	/* dp_desc */
1703*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("\n\t  dp_desc '");
1704*ed775ee7SAntonio Huete Jimenez 	nd_printjnp(ndo, cp, DESC_STR_LEN);
1705*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("'");
1706*ed775ee7SAntonio Huete Jimenez 	return;
1707411677aeSAaron LI 
1708411677aeSAaron LI invalid: /* skip the message body */
1709*ed775ee7SAntonio Huete Jimenez 	nd_print_invalid(ndo);
1710*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_LEN(cp, len);
1711411677aeSAaron LI }
1712411677aeSAaron LI 
1713411677aeSAaron LI /* ibid */
1714*ed775ee7SAntonio Huete Jimenez static void
of10_flow_stats_reply_print(netdissect_options * ndo,const u_char * cp,u_int len)1715411677aeSAaron LI of10_flow_stats_reply_print(netdissect_options *ndo,
1716*ed775ee7SAntonio Huete Jimenez                             const u_char *cp, u_int len)
1717411677aeSAaron LI {
1718*ed775ee7SAntonio Huete Jimenez 	while (len) {
1719411677aeSAaron LI 		uint16_t entry_len;
1720411677aeSAaron LI 
1721*ed775ee7SAntonio Huete Jimenez 		if (len < OF_FLOW_STATS_REPLY_MINLEN)
1722411677aeSAaron LI 			goto invalid;
1723411677aeSAaron LI 		/* length */
1724*ed775ee7SAntonio Huete Jimenez 		entry_len = GET_BE_U_2(cp);
1725*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\n\t length %u", entry_len);
1726*ed775ee7SAntonio Huete Jimenez 		if (entry_len < OF_FLOW_STATS_REPLY_MINLEN || entry_len > len)
1727411677aeSAaron LI 			goto invalid;
1728*ed775ee7SAntonio Huete Jimenez 		OF_FWD(2);
1729411677aeSAaron LI 		/* table_id */
1730*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", table_id %s",
1731*ed775ee7SAntonio Huete Jimenez 			 tok2str(tableid_str, "%u", GET_U_1(cp)));
1732*ed775ee7SAntonio Huete Jimenez 		OF_FWD(1);
1733411677aeSAaron LI 		/* pad */
1734*ed775ee7SAntonio Huete Jimenez 		OF_FWD(1);
1735411677aeSAaron LI 		/* match */
1736*ed775ee7SAntonio Huete Jimenez 		of10_match_print(ndo, "\n\t  ", cp);
1737*ed775ee7SAntonio Huete Jimenez 		OF_FWD(OF_MATCH_FIXLEN);
1738411677aeSAaron LI 		/* duration_sec */
1739*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\n\t  duration_sec %u", GET_BE_U_4(cp));
1740*ed775ee7SAntonio Huete Jimenez 		OF_FWD(4);
1741411677aeSAaron LI 		/* duration_nsec */
1742*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", duration_nsec %u", GET_BE_U_4(cp));
1743*ed775ee7SAntonio Huete Jimenez 		OF_FWD(4);
1744411677aeSAaron LI 		/* priority */
1745*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", priority %u", GET_BE_U_2(cp));
1746*ed775ee7SAntonio Huete Jimenez 		OF_FWD(2);
1747411677aeSAaron LI 		/* idle_timeout */
1748*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", idle_timeout %u", GET_BE_U_2(cp));
1749*ed775ee7SAntonio Huete Jimenez 		OF_FWD(2);
1750411677aeSAaron LI 		/* hard_timeout */
1751*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", hard_timeout %u", GET_BE_U_2(cp));
1752*ed775ee7SAntonio Huete Jimenez 		OF_FWD(2);
1753411677aeSAaron LI 		/* pad2 */
1754*ed775ee7SAntonio Huete Jimenez 		OF_FWD(6);
1755411677aeSAaron LI 		/* cookie */
1756*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", cookie 0x%016" PRIx64, GET_BE_U_8(cp));
1757*ed775ee7SAntonio Huete Jimenez 		OF_FWD(8);
1758411677aeSAaron LI 		/* packet_count */
1759*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", packet_count %" PRIu64, GET_BE_U_8(cp));
1760*ed775ee7SAntonio Huete Jimenez 		OF_FWD(8);
1761411677aeSAaron LI 		/* byte_count */
1762*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", byte_count %" PRIu64, GET_BE_U_8(cp));
1763*ed775ee7SAntonio Huete Jimenez 		OF_FWD(8);
1764411677aeSAaron LI 		/* actions */
1765*ed775ee7SAntonio Huete Jimenez 		of10_actions_print(ndo, "\n\t  ", cp, entry_len - OF_FLOW_STATS_REPLY_MINLEN);
1766*ed775ee7SAntonio Huete Jimenez 		OF_FWD(entry_len - OF_FLOW_STATS_REPLY_MINLEN);
1767411677aeSAaron LI 	} /* while */
1768*ed775ee7SAntonio Huete Jimenez 	return;
1769411677aeSAaron LI 
1770411677aeSAaron LI invalid: /* skip the rest of flow statistics entries */
1771*ed775ee7SAntonio Huete Jimenez 	nd_print_invalid(ndo);
1772*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_LEN(cp, len);
1773411677aeSAaron LI }
1774411677aeSAaron LI 
1775411677aeSAaron LI /* ibid */
1776*ed775ee7SAntonio Huete Jimenez static void
of10_aggregate_stats_reply_print(netdissect_options * ndo,const u_char * cp,u_int len)1777411677aeSAaron LI of10_aggregate_stats_reply_print(netdissect_options *ndo,
1778*ed775ee7SAntonio Huete Jimenez                                  const u_char *cp, u_int len)
1779411677aeSAaron LI {
1780*ed775ee7SAntonio Huete Jimenez 	if (len != OF_AGGREGATE_STATS_REPLY_FIXLEN)
1781411677aeSAaron LI 		goto invalid;
1782411677aeSAaron LI 	/* packet_count */
1783*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("\n\t packet_count %" PRIu64, GET_BE_U_8(cp));
1784*ed775ee7SAntonio Huete Jimenez 	OF_FWD(8);
1785411677aeSAaron LI 	/* byte_count */
1786*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(", byte_count %" PRIu64, GET_BE_U_8(cp));
1787*ed775ee7SAntonio Huete Jimenez 	OF_FWD(8);
1788411677aeSAaron LI 	/* flow_count */
1789*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(", flow_count %u", GET_BE_U_4(cp));
1790*ed775ee7SAntonio Huete Jimenez 	OF_FWD(4);
1791411677aeSAaron LI 	/* pad */
1792*ed775ee7SAntonio Huete Jimenez 	/* Always the last field, check bounds. */
1793*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_4(cp);
1794*ed775ee7SAntonio Huete Jimenez 	return;
1795411677aeSAaron LI 
1796411677aeSAaron LI invalid: /* skip the message body */
1797*ed775ee7SAntonio Huete Jimenez 	nd_print_invalid(ndo);
1798*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_LEN(cp, len);
1799411677aeSAaron LI }
1800411677aeSAaron LI 
1801411677aeSAaron LI /* ibid */
1802*ed775ee7SAntonio Huete Jimenez static void
of10_table_stats_reply_print(netdissect_options * ndo,const u_char * cp,u_int len)1803411677aeSAaron LI of10_table_stats_reply_print(netdissect_options *ndo,
1804*ed775ee7SAntonio Huete Jimenez                              const u_char *cp, u_int len)
1805411677aeSAaron LI {
1806411677aeSAaron LI 	while (len) {
1807*ed775ee7SAntonio Huete Jimenez 		if (len < OF_TABLE_STATS_REPLY_FIXLEN)
1808411677aeSAaron LI 			goto invalid;
1809411677aeSAaron LI 		/* table_id */
1810*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\n\t table_id %s",
1811*ed775ee7SAntonio Huete Jimenez 		         tok2str(tableid_str, "%u", GET_U_1(cp)));
1812*ed775ee7SAntonio Huete Jimenez 		OF_FWD(1);
1813411677aeSAaron LI 		/* pad */
1814*ed775ee7SAntonio Huete Jimenez 		OF_FWD(3);
1815411677aeSAaron LI 		/* name */
1816*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", name '");
1817*ed775ee7SAntonio Huete Jimenez 		nd_printjnp(ndo, cp, OFP_MAX_TABLE_NAME_LEN);
1818*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("'");
1819*ed775ee7SAntonio Huete Jimenez 		OF_FWD(OFP_MAX_TABLE_NAME_LEN);
1820411677aeSAaron LI 		/* wildcards */
1821*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\n\t  wildcards 0x%08x", GET_BE_U_4(cp));
1822*ed775ee7SAntonio Huete Jimenez 		of_bitmap_print(ndo, ofpfw_bm, GET_BE_U_4(cp), OFPFW_U);
1823*ed775ee7SAntonio Huete Jimenez 		OF_FWD(4);
1824411677aeSAaron LI 		/* max_entries */
1825*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\n\t  max_entries %u", GET_BE_U_4(cp));
1826*ed775ee7SAntonio Huete Jimenez 		OF_FWD(4);
1827411677aeSAaron LI 		/* active_count */
1828*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", active_count %u", GET_BE_U_4(cp));
1829*ed775ee7SAntonio Huete Jimenez 		OF_FWD(4);
1830411677aeSAaron LI 		/* lookup_count */
1831*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", lookup_count %" PRIu64, GET_BE_U_8(cp));
1832*ed775ee7SAntonio Huete Jimenez 		OF_FWD(8);
1833411677aeSAaron LI 		/* matched_count */
1834*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", matched_count %" PRIu64, GET_BE_U_8(cp));
1835*ed775ee7SAntonio Huete Jimenez 		OF_FWD(8);
1836411677aeSAaron LI 	} /* while */
1837*ed775ee7SAntonio Huete Jimenez 	return;
1838411677aeSAaron LI 
1839411677aeSAaron LI invalid: /* skip the undersized trailing data */
1840*ed775ee7SAntonio Huete Jimenez 	nd_print_invalid(ndo);
1841*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_LEN(cp, len);
1842411677aeSAaron LI }
1843411677aeSAaron LI 
1844411677aeSAaron LI /* ibid */
1845*ed775ee7SAntonio Huete Jimenez static void
of10_port_stats_reply_print(netdissect_options * ndo,const u_char * cp,u_int len)1846411677aeSAaron LI of10_port_stats_reply_print(netdissect_options *ndo,
1847*ed775ee7SAntonio Huete Jimenez                             const u_char *cp, u_int len)
1848411677aeSAaron LI {
1849411677aeSAaron LI 	while (len) {
1850*ed775ee7SAntonio Huete Jimenez 		if (len < OF_PORT_STATS_REPLY_FIXLEN)
1851411677aeSAaron LI 			goto invalid;
1852411677aeSAaron LI 		/* port_no */
1853*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\n\t  port_no %s",
1854*ed775ee7SAntonio Huete Jimenez 			 tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1855*ed775ee7SAntonio Huete Jimenez 		OF_FWD(2);
1856411677aeSAaron LI 		if (ndo->ndo_vflag < 2) {
1857*ed775ee7SAntonio Huete Jimenez 			OF_CHK_FWD(OF_PORT_STATS_REPLY_FIXLEN - 2);
1858*ed775ee7SAntonio Huete Jimenez 			continue;
1859411677aeSAaron LI 		}
1860411677aeSAaron LI 		/* pad */
1861*ed775ee7SAntonio Huete Jimenez 		OF_FWD(6);
1862411677aeSAaron LI 		/* rx_packets */
1863*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", rx_packets %" PRIu64, GET_BE_U_8(cp));
1864*ed775ee7SAntonio Huete Jimenez 		OF_FWD(8);
1865411677aeSAaron LI 		/* tx_packets */
1866*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", tx_packets %" PRIu64, GET_BE_U_8(cp));
1867*ed775ee7SAntonio Huete Jimenez 		OF_FWD(8);
1868411677aeSAaron LI 		/* rx_bytes */
1869*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", rx_bytes %" PRIu64, GET_BE_U_8(cp));
1870*ed775ee7SAntonio Huete Jimenez 		OF_FWD(8);
1871411677aeSAaron LI 		/* tx_bytes */
1872*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", tx_bytes %" PRIu64, GET_BE_U_8(cp));
1873*ed775ee7SAntonio Huete Jimenez 		OF_FWD(8);
1874411677aeSAaron LI 		/* rx_dropped */
1875*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", rx_dropped %" PRIu64, GET_BE_U_8(cp));
1876*ed775ee7SAntonio Huete Jimenez 		OF_FWD(8);
1877411677aeSAaron LI 		/* tx_dropped */
1878*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", tx_dropped %" PRIu64, GET_BE_U_8(cp));
1879*ed775ee7SAntonio Huete Jimenez 		OF_FWD(8);
1880411677aeSAaron LI 		/* rx_errors */
1881*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", rx_errors %" PRIu64, GET_BE_U_8(cp));
1882*ed775ee7SAntonio Huete Jimenez 		OF_FWD(8);
1883411677aeSAaron LI 		/* tx_errors */
1884*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", tx_errors %" PRIu64, GET_BE_U_8(cp));
1885*ed775ee7SAntonio Huete Jimenez 		OF_FWD(8);
1886411677aeSAaron LI 		/* rx_frame_err */
1887*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", rx_frame_err %" PRIu64, GET_BE_U_8(cp));
1888*ed775ee7SAntonio Huete Jimenez 		OF_FWD(8);
1889411677aeSAaron LI 		/* rx_over_err */
1890*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", rx_over_err %" PRIu64, GET_BE_U_8(cp));
1891*ed775ee7SAntonio Huete Jimenez 		OF_FWD(8);
1892411677aeSAaron LI 		/* rx_crc_err */
1893*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", rx_crc_err %" PRIu64, GET_BE_U_8(cp));
1894*ed775ee7SAntonio Huete Jimenez 		OF_FWD(8);
1895411677aeSAaron LI 		/* collisions */
1896*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", collisions %" PRIu64, GET_BE_U_8(cp));
1897*ed775ee7SAntonio Huete Jimenez 		OF_FWD(8);
1898411677aeSAaron LI 	} /* while */
1899*ed775ee7SAntonio Huete Jimenez 	return;
1900411677aeSAaron LI 
1901411677aeSAaron LI invalid: /* skip the undersized trailing data */
1902*ed775ee7SAntonio Huete Jimenez 	nd_print_invalid(ndo);
1903*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_LEN(cp, len);
1904411677aeSAaron LI }
1905411677aeSAaron LI 
1906411677aeSAaron LI /* ibid */
1907*ed775ee7SAntonio Huete Jimenez static void
of10_queue_stats_reply_print(netdissect_options * ndo,const u_char * cp,u_int len)1908411677aeSAaron LI of10_queue_stats_reply_print(netdissect_options *ndo,
1909*ed775ee7SAntonio Huete Jimenez                              const u_char *cp, u_int len)
1910411677aeSAaron LI {
1911411677aeSAaron LI 	while (len) {
1912*ed775ee7SAntonio Huete Jimenez 		if (len < OF_QUEUE_STATS_REPLY_FIXLEN)
1913411677aeSAaron LI 			goto invalid;
1914411677aeSAaron LI 		/* port_no */
1915*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("\n\t  port_no %s",
1916*ed775ee7SAntonio Huete Jimenez 		         tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1917*ed775ee7SAntonio Huete Jimenez 		OF_FWD(2);
1918411677aeSAaron LI 		/* pad */
1919*ed775ee7SAntonio Huete Jimenez 		OF_FWD(2);
1920411677aeSAaron LI 		/* queue_id */
1921*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", queue_id %u", GET_BE_U_4(cp));
1922*ed775ee7SAntonio Huete Jimenez 		OF_FWD(4);
1923411677aeSAaron LI 		/* tx_bytes */
1924*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", tx_bytes %" PRIu64, GET_BE_U_8(cp));
1925*ed775ee7SAntonio Huete Jimenez 		OF_FWD(8);
1926411677aeSAaron LI 		/* tx_packets */
1927*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", tx_packets %" PRIu64, GET_BE_U_8(cp));
1928*ed775ee7SAntonio Huete Jimenez 		OF_FWD(8);
1929411677aeSAaron LI 		/* tx_errors */
1930*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", tx_errors %" PRIu64, GET_BE_U_8(cp));
1931*ed775ee7SAntonio Huete Jimenez 		OF_FWD(8);
1932411677aeSAaron LI 	} /* while */
1933*ed775ee7SAntonio Huete Jimenez 	return;
1934411677aeSAaron LI 
1935411677aeSAaron LI invalid: /* skip the undersized trailing data */
1936*ed775ee7SAntonio Huete Jimenez 	nd_print_invalid(ndo);
1937*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_LEN(cp, len);
1938411677aeSAaron LI }
1939411677aeSAaron LI 
1940411677aeSAaron LI /* ibid */
1941*ed775ee7SAntonio Huete Jimenez static void
of10_stats_reply_print(netdissect_options * ndo,const u_char * cp,u_int len)1942411677aeSAaron LI of10_stats_reply_print(netdissect_options *ndo,
1943*ed775ee7SAntonio Huete Jimenez                        const u_char *cp, u_int len)
1944411677aeSAaron LI {
1945411677aeSAaron LI 	uint16_t type;
1946411677aeSAaron LI 
1947411677aeSAaron LI 	/* type */
1948*ed775ee7SAntonio Huete Jimenez 	type = GET_BE_U_2(cp);
1949*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("\n\t type %s", tok2str(ofpst_str, "invalid (0x%04x)", type));
1950*ed775ee7SAntonio Huete Jimenez 	OF_FWD(2);
1951411677aeSAaron LI 	/* flags */
1952*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(", flags 0x%04x", GET_BE_U_2(cp));
1953*ed775ee7SAntonio Huete Jimenez 	of_bitmap_print(ndo, ofpsf_reply_bm, GET_BE_U_2(cp), OFPSF_REPLY_U);
1954*ed775ee7SAntonio Huete Jimenez 	OF_FWD(2);
1955411677aeSAaron LI 
1956411677aeSAaron LI 	if (ndo->ndo_vflag > 0) {
1957*ed775ee7SAntonio Huete Jimenez 		void (*decoder)(netdissect_options *, const u_char *, u_int) =
1958411677aeSAaron LI 			type == OFPST_DESC      ? of10_desc_stats_reply_print      :
1959411677aeSAaron LI 			type == OFPST_FLOW      ? of10_flow_stats_reply_print      :
1960411677aeSAaron LI 			type == OFPST_AGGREGATE ? of10_aggregate_stats_reply_print :
1961411677aeSAaron LI 			type == OFPST_TABLE     ? of10_table_stats_reply_print     :
1962411677aeSAaron LI 			type == OFPST_PORT      ? of10_port_stats_reply_print      :
1963411677aeSAaron LI 			type == OFPST_QUEUE     ? of10_queue_stats_reply_print     :
1964411677aeSAaron LI 			type == OFPST_VENDOR    ? of10_vendor_data_print           :
1965411677aeSAaron LI 			NULL;
1966*ed775ee7SAntonio Huete Jimenez 		if (decoder != NULL) {
1967*ed775ee7SAntonio Huete Jimenez 			decoder(ndo, cp, len);
1968*ed775ee7SAntonio Huete Jimenez 			return;
1969411677aeSAaron LI 		}
1970*ed775ee7SAntonio Huete Jimenez 	}
1971*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_LEN(cp, len);
1972411677aeSAaron LI }
1973411677aeSAaron LI 
1974411677aeSAaron LI /* [OF10] Section 5.3.6 */
1975*ed775ee7SAntonio Huete Jimenez static void
of10_packet_out_print(netdissect_options * ndo,const u_char * cp,u_int len)1976411677aeSAaron LI of10_packet_out_print(netdissect_options *ndo,
1977*ed775ee7SAntonio Huete Jimenez                       const u_char *cp, u_int len)
1978411677aeSAaron LI {
1979411677aeSAaron LI 	uint16_t actions_len;
1980411677aeSAaron LI 
1981411677aeSAaron LI 	/* buffer_id */
1982*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("\n\t buffer_id 0x%08x", GET_BE_U_4(cp));
1983*ed775ee7SAntonio Huete Jimenez 	OF_FWD(4);
1984411677aeSAaron LI 	/* in_port */
1985*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(", in_port %s", tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1986*ed775ee7SAntonio Huete Jimenez 	OF_FWD(2);
1987411677aeSAaron LI 	/* actions_len */
1988*ed775ee7SAntonio Huete Jimenez 	actions_len = GET_BE_U_2(cp);
1989*ed775ee7SAntonio Huete Jimenez 	OF_FWD(2);
1990*ed775ee7SAntonio Huete Jimenez 	if (actions_len > len)
1991411677aeSAaron LI 		goto invalid;
1992411677aeSAaron LI 	/* actions */
1993*ed775ee7SAntonio Huete Jimenez 	of10_actions_print(ndo, "\n\t ", cp, actions_len);
1994*ed775ee7SAntonio Huete Jimenez 	OF_FWD(actions_len);
1995411677aeSAaron LI 	/* data */
1996*ed775ee7SAntonio Huete Jimenez 	of10_packet_data_print(ndo, cp, len);
1997*ed775ee7SAntonio Huete Jimenez 	return;
1998411677aeSAaron LI 
1999411677aeSAaron LI invalid: /* skip the rest of the message body */
2000*ed775ee7SAntonio Huete Jimenez 	nd_print_invalid(ndo);
2001*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_LEN(cp, len);
2002411677aeSAaron LI }
2003411677aeSAaron LI 
2004411677aeSAaron LI /* [OF10] Section 5.4.1 */
2005*ed775ee7SAntonio Huete Jimenez static void
of10_packet_in_print(netdissect_options * ndo,const u_char * cp,u_int len)2006411677aeSAaron LI of10_packet_in_print(netdissect_options *ndo,
2007*ed775ee7SAntonio Huete Jimenez                      const u_char *cp, u_int len)
2008411677aeSAaron LI {
2009411677aeSAaron LI 	/* buffer_id */
2010*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("\n\t buffer_id %s",
2011*ed775ee7SAntonio Huete Jimenez 	         tok2str(bufferid_str, "0x%08x", GET_BE_U_4(cp)));
2012*ed775ee7SAntonio Huete Jimenez 	OF_FWD(4);
2013411677aeSAaron LI 	/* total_len */
2014*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(", total_len %u", GET_BE_U_2(cp));
2015*ed775ee7SAntonio Huete Jimenez 	OF_FWD(2);
2016411677aeSAaron LI 	/* in_port */
2017*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(", in_port %s", tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
2018*ed775ee7SAntonio Huete Jimenez 	OF_FWD(2);
2019411677aeSAaron LI 	/* reason */
2020*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(", reason %s",
2021*ed775ee7SAntonio Huete Jimenez 		 tok2str(ofpr_str, "invalid (0x%02x)", GET_U_1(cp)));
2022*ed775ee7SAntonio Huete Jimenez 	OF_FWD(1);
2023411677aeSAaron LI 	/* pad */
2024*ed775ee7SAntonio Huete Jimenez 	/* Sometimes the last field, check bounds. */
2025*ed775ee7SAntonio Huete Jimenez 	OF_CHK_FWD(1);
2026411677aeSAaron LI 	/* data */
2027*ed775ee7SAntonio Huete Jimenez 	of10_packet_data_print(ndo, cp, len);
2028411677aeSAaron LI }
2029411677aeSAaron LI 
2030411677aeSAaron LI /* [OF10] Section 5.4.2 */
2031*ed775ee7SAntonio Huete Jimenez static void
of10_flow_removed_print(netdissect_options * ndo,const u_char * cp,u_int len _U_)2032411677aeSAaron LI of10_flow_removed_print(netdissect_options *ndo,
2033*ed775ee7SAntonio Huete Jimenez                         const u_char *cp, u_int len _U_)
2034411677aeSAaron LI {
2035411677aeSAaron LI 	/* match */
2036*ed775ee7SAntonio Huete Jimenez 	of10_match_print(ndo, "\n\t ", cp);
2037*ed775ee7SAntonio Huete Jimenez 	cp += OF_MATCH_FIXLEN;
2038411677aeSAaron LI 	/* cookie */
2039*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("\n\t cookie 0x%016" PRIx64, GET_BE_U_8(cp));
2040411677aeSAaron LI 	cp += 8;
2041411677aeSAaron LI 	/* priority */
2042*ed775ee7SAntonio Huete Jimenez 	if (GET_BE_U_2(cp))
2043*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", priority %u", GET_BE_U_2(cp));
2044411677aeSAaron LI 	cp += 2;
2045411677aeSAaron LI 	/* reason */
2046*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(", reason %s",
2047*ed775ee7SAntonio Huete Jimenez 	         tok2str(ofprr_str, "unknown (0x%02x)", GET_U_1(cp)));
2048411677aeSAaron LI 	cp += 1;
2049411677aeSAaron LI 	/* pad */
2050411677aeSAaron LI 	cp += 1;
2051411677aeSAaron LI 	/* duration_sec */
2052*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(", duration_sec %u", GET_BE_U_4(cp));
2053411677aeSAaron LI 	cp += 4;
2054411677aeSAaron LI 	/* duration_nsec */
2055*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(", duration_nsec %u", GET_BE_U_4(cp));
2056411677aeSAaron LI 	cp += 4;
2057411677aeSAaron LI 	/* idle_timeout */
2058*ed775ee7SAntonio Huete Jimenez 	if (GET_BE_U_2(cp))
2059*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", idle_timeout %u", GET_BE_U_2(cp));
2060411677aeSAaron LI 	cp += 2;
2061411677aeSAaron LI 	/* pad2 */
2062411677aeSAaron LI 	cp += 2;
2063411677aeSAaron LI 	/* packet_count */
2064*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(", packet_count %" PRIu64, GET_BE_U_8(cp));
2065411677aeSAaron LI 	cp += 8;
2066411677aeSAaron LI 	/* byte_count */
2067*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(", byte_count %" PRIu64, GET_BE_U_8(cp));
2068*ed775ee7SAntonio Huete Jimenez }
2069411677aeSAaron LI 
2070*ed775ee7SAntonio Huete Jimenez /* [OF10] Section 5.4.3 */
2071*ed775ee7SAntonio Huete Jimenez static void
of10_port_status_print(netdissect_options * ndo,const u_char * cp,u_int len _U_)2072*ed775ee7SAntonio Huete Jimenez of10_port_status_print(netdissect_options *ndo,
2073*ed775ee7SAntonio Huete Jimenez                        const u_char *cp, u_int len _U_)
2074*ed775ee7SAntonio Huete Jimenez {
2075*ed775ee7SAntonio Huete Jimenez 	/* reason */
2076*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("\n\t reason %s",
2077*ed775ee7SAntonio Huete Jimenez 	         tok2str(ofppr_str, "invalid (0x%02x)", GET_U_1(cp)));
2078*ed775ee7SAntonio Huete Jimenez 	cp += 1;
2079*ed775ee7SAntonio Huete Jimenez 	/* pad */
2080*ed775ee7SAntonio Huete Jimenez 	/* No need to check bounds, more data follows. */
2081*ed775ee7SAntonio Huete Jimenez 	cp += 7;
2082*ed775ee7SAntonio Huete Jimenez 	/* desc */
2083*ed775ee7SAntonio Huete Jimenez 	of10_phy_port_print(ndo, cp);
2084411677aeSAaron LI }
2085411677aeSAaron LI 
2086411677aeSAaron LI /* [OF10] Section 5.4.4 */
2087*ed775ee7SAntonio Huete Jimenez static void
of10_error_print(netdissect_options * ndo,const u_char * cp,u_int len)2088411677aeSAaron LI of10_error_print(netdissect_options *ndo,
2089*ed775ee7SAntonio Huete Jimenez                  const u_char *cp, u_int len)
2090411677aeSAaron LI {
2091*ed775ee7SAntonio Huete Jimenez 	uint16_t type, code;
2092411677aeSAaron LI 	const struct tok *code_str;
2093411677aeSAaron LI 
2094411677aeSAaron LI 	/* type */
2095*ed775ee7SAntonio Huete Jimenez 	type = GET_BE_U_2(cp);
2096*ed775ee7SAntonio Huete Jimenez 	OF_FWD(2);
2097*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("\n\t type %s", tok2str(ofpet_str, "invalid (0x%04x)", type));
2098411677aeSAaron LI 	/* code */
2099*ed775ee7SAntonio Huete Jimenez 	code = GET_BE_U_2(cp);
2100*ed775ee7SAntonio Huete Jimenez 	OF_FWD(2);
2101*ed775ee7SAntonio Huete Jimenez 	code_str = uint2tokary(of10_ofpet2tokary, type);
2102*ed775ee7SAntonio Huete Jimenez 	if (code_str != NULL)
2103*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", code %s",
2104*ed775ee7SAntonio Huete Jimenez 		         tok2str(code_str, "invalid (0x%04x)", code));
2105*ed775ee7SAntonio Huete Jimenez 	else
2106*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", code invalid (0x%04x)", code);
2107411677aeSAaron LI 	/* data */
2108*ed775ee7SAntonio Huete Jimenez 	of_data_print(ndo, cp, len);
2109411677aeSAaron LI }
2110411677aeSAaron LI 
2111*ed775ee7SAntonio Huete Jimenez static const struct of_msgtypeinfo of10_msgtypeinfo[OFPT_MAX + 1] = {
2112*ed775ee7SAntonio Huete Jimenez 	/*
2113*ed775ee7SAntonio Huete Jimenez 	 * [OF10] Section 5.5.1
2114*ed775ee7SAntonio Huete Jimenez 	 * Variable-size data.
2115*ed775ee7SAntonio Huete Jimenez 	 */
2116411677aeSAaron LI 	{
2117*ed775ee7SAntonio Huete Jimenez 		"HELLO",                    of_data_print,
2118*ed775ee7SAntonio Huete Jimenez 		REQ_MINLEN,                 0
2119*ed775ee7SAntonio Huete Jimenez 	},
2120*ed775ee7SAntonio Huete Jimenez 	/*
2121*ed775ee7SAntonio Huete Jimenez 	 * [OF10] Section 5.4.4
2122*ed775ee7SAntonio Huete Jimenez 	 * A fixed-size message body and variable-size data.
2123*ed775ee7SAntonio Huete Jimenez 	 */
2124*ed775ee7SAntonio Huete Jimenez 	{
2125*ed775ee7SAntonio Huete Jimenez 		"ERROR",                    of10_error_print,
2126*ed775ee7SAntonio Huete Jimenez 		REQ_MINLEN,                 OF_ERROR_MSG_MINLEN
2127*ed775ee7SAntonio Huete Jimenez 	},
2128*ed775ee7SAntonio Huete Jimenez 	/*
2129*ed775ee7SAntonio Huete Jimenez 	 * [OF10] Section 5.5.2
2130*ed775ee7SAntonio Huete Jimenez 	 * Variable-size data.
2131*ed775ee7SAntonio Huete Jimenez 	 */
2132*ed775ee7SAntonio Huete Jimenez 	{
2133*ed775ee7SAntonio Huete Jimenez 		"ECHO_REQUEST",             of_data_print,
2134*ed775ee7SAntonio Huete Jimenez 		REQ_MINLEN,                 0
2135*ed775ee7SAntonio Huete Jimenez 	},
2136*ed775ee7SAntonio Huete Jimenez 	/*
2137*ed775ee7SAntonio Huete Jimenez 	 * [OF10] Section 5.5.3
2138*ed775ee7SAntonio Huete Jimenez 	 * Variable-size data.
2139*ed775ee7SAntonio Huete Jimenez 	 */
2140*ed775ee7SAntonio Huete Jimenez 	{
2141*ed775ee7SAntonio Huete Jimenez 		"ECHO_REPLY",               of_data_print,
2142*ed775ee7SAntonio Huete Jimenez 		REQ_MINLEN,                 0
2143*ed775ee7SAntonio Huete Jimenez 	},
2144*ed775ee7SAntonio Huete Jimenez 	/*
2145*ed775ee7SAntonio Huete Jimenez 	 * [OF10] Section 5.5.4
2146*ed775ee7SAntonio Huete Jimenez 	 * A fixed-size message body and variable-size data.
2147*ed775ee7SAntonio Huete Jimenez 	 */
2148*ed775ee7SAntonio Huete Jimenez 	{
2149*ed775ee7SAntonio Huete Jimenez 		"VENDOR",                   of10_vendor_message_print,
2150*ed775ee7SAntonio Huete Jimenez 		REQ_MINLEN,                 OF_VENDOR_MINLEN
2151*ed775ee7SAntonio Huete Jimenez 	},
2152*ed775ee7SAntonio Huete Jimenez 	/*
2153*ed775ee7SAntonio Huete Jimenez 	 * [OF10] Section 5.3.1
2154*ed775ee7SAntonio Huete Jimenez 	 * No message body.
2155*ed775ee7SAntonio Huete Jimenez 	 */
2156*ed775ee7SAntonio Huete Jimenez 	{
2157*ed775ee7SAntonio Huete Jimenez 		"FEATURES_REQUEST",         NULL,
2158*ed775ee7SAntonio Huete Jimenez 		REQ_FIXLEN,                 0
2159*ed775ee7SAntonio Huete Jimenez 	},
2160*ed775ee7SAntonio Huete Jimenez 	/*
2161*ed775ee7SAntonio Huete Jimenez 	 * [OF10] Section 5.3.1
2162*ed775ee7SAntonio Huete Jimenez 	 * A fixed-size message body and n * fixed-size data units.
2163*ed775ee7SAntonio Huete Jimenez 	 */
2164*ed775ee7SAntonio Huete Jimenez 	{
2165*ed775ee7SAntonio Huete Jimenez 		"FEATURES_REPLY",           of10_features_reply_print,
2166*ed775ee7SAntonio Huete Jimenez 		REQ_MINLEN,                 OF_FEATURES_REPLY_MINLEN
2167*ed775ee7SAntonio Huete Jimenez 	},
2168*ed775ee7SAntonio Huete Jimenez 	/*
2169*ed775ee7SAntonio Huete Jimenez 	 * [OF10] Section 5.3.2
2170*ed775ee7SAntonio Huete Jimenez 	 * No message body.
2171*ed775ee7SAntonio Huete Jimenez 	 */
2172*ed775ee7SAntonio Huete Jimenez 	{
2173*ed775ee7SAntonio Huete Jimenez 		"GET_CONFIG_REQUEST",       NULL,
2174*ed775ee7SAntonio Huete Jimenez 		REQ_FIXLEN,                 0
2175*ed775ee7SAntonio Huete Jimenez 	},
2176*ed775ee7SAntonio Huete Jimenez 	/*
2177*ed775ee7SAntonio Huete Jimenez 	 * [OF10] Section 5.3.2
2178*ed775ee7SAntonio Huete Jimenez 	 * A fixed-size message body.
2179*ed775ee7SAntonio Huete Jimenez 	 */
2180*ed775ee7SAntonio Huete Jimenez 	{
2181*ed775ee7SAntonio Huete Jimenez 		"GET_CONFIG_REPLY",         of10_switch_config_msg_print,
2182*ed775ee7SAntonio Huete Jimenez 		REQ_FIXLEN,                 OF_SWITCH_CONFIG_FIXLEN
2183*ed775ee7SAntonio Huete Jimenez 	},
2184*ed775ee7SAntonio Huete Jimenez 	/*
2185*ed775ee7SAntonio Huete Jimenez 	 * [OF10] Section 5.3.2
2186*ed775ee7SAntonio Huete Jimenez 	 * A fixed-size message body.
2187*ed775ee7SAntonio Huete Jimenez 	 */
2188*ed775ee7SAntonio Huete Jimenez 	{
2189*ed775ee7SAntonio Huete Jimenez 		"SET_CONFIG",               of10_switch_config_msg_print,
2190*ed775ee7SAntonio Huete Jimenez 		REQ_FIXLEN,                 OF_SWITCH_CONFIG_FIXLEN
2191*ed775ee7SAntonio Huete Jimenez 	},
2192*ed775ee7SAntonio Huete Jimenez 	/*
2193*ed775ee7SAntonio Huete Jimenez 	 * [OF10] Section 5.4.1
2194*ed775ee7SAntonio Huete Jimenez 	 * A fixed-size message body and variable-size data.
2195*ed775ee7SAntonio Huete Jimenez 	 * (The 2 mock octets count in OF_PACKET_IN_MINLEN only.)
2196*ed775ee7SAntonio Huete Jimenez 	 */
2197*ed775ee7SAntonio Huete Jimenez 	{
2198*ed775ee7SAntonio Huete Jimenez 		"PACKET_IN",                of10_packet_in_print,
2199*ed775ee7SAntonio Huete Jimenez 		REQ_MINLEN,                 OF_PACKET_IN_MINLEN - 2
2200*ed775ee7SAntonio Huete Jimenez 	},
2201*ed775ee7SAntonio Huete Jimenez 	/*
2202*ed775ee7SAntonio Huete Jimenez 	 * [OF10] Section 5.4.2
2203*ed775ee7SAntonio Huete Jimenez 	 * A fixed-size message body.
2204*ed775ee7SAntonio Huete Jimenez 	 */
2205*ed775ee7SAntonio Huete Jimenez 	{
2206*ed775ee7SAntonio Huete Jimenez 		"FLOW_REMOVED",             of10_flow_removed_print,
2207*ed775ee7SAntonio Huete Jimenez 		REQ_FIXLEN,                 OF_FLOW_REMOVED_FIXLEN
2208*ed775ee7SAntonio Huete Jimenez 	},
2209*ed775ee7SAntonio Huete Jimenez 	/*
2210*ed775ee7SAntonio Huete Jimenez 	 * [OF10] Section 5.4.3
2211*ed775ee7SAntonio Huete Jimenez 	 * A fixed-size message body.
2212*ed775ee7SAntonio Huete Jimenez 	 */
2213*ed775ee7SAntonio Huete Jimenez 	{
2214*ed775ee7SAntonio Huete Jimenez 		"PORT_STATUS",              of10_port_status_print,
2215*ed775ee7SAntonio Huete Jimenez 		REQ_FIXLEN,                 OF_PORT_STATUS_FIXLEN
2216*ed775ee7SAntonio Huete Jimenez 	},
2217*ed775ee7SAntonio Huete Jimenez 	/*
2218*ed775ee7SAntonio Huete Jimenez 	 * [OF10] Section 5.3.6
2219*ed775ee7SAntonio Huete Jimenez 	 * A fixed-size message body, n * variable-size data units and
2220*ed775ee7SAntonio Huete Jimenez 	 * variable-size data.
2221*ed775ee7SAntonio Huete Jimenez 	 */
2222*ed775ee7SAntonio Huete Jimenez 	{
2223*ed775ee7SAntonio Huete Jimenez 		"PACKET_OUT",               of10_packet_out_print,
2224*ed775ee7SAntonio Huete Jimenez 		REQ_MINLEN,                 OF_PACKET_OUT_MINLEN
2225*ed775ee7SAntonio Huete Jimenez 	},
2226*ed775ee7SAntonio Huete Jimenez 	/*
2227*ed775ee7SAntonio Huete Jimenez 	 * [OF10] Section 5.3.3
2228*ed775ee7SAntonio Huete Jimenez 	 * A fixed-size message body and n * variable-size data units.
2229*ed775ee7SAntonio Huete Jimenez 	 */
2230*ed775ee7SAntonio Huete Jimenez 	{
2231*ed775ee7SAntonio Huete Jimenez 		"FLOW_MOD",                 of10_flow_mod_print,
2232*ed775ee7SAntonio Huete Jimenez 		REQ_MINLEN,                 OF_FLOW_MOD_MINLEN
2233*ed775ee7SAntonio Huete Jimenez 	},
2234*ed775ee7SAntonio Huete Jimenez 	/*
2235*ed775ee7SAntonio Huete Jimenez 	 * [OF10] Section 5.3.3
2236*ed775ee7SAntonio Huete Jimenez 	 * A fixed-size message body.
2237*ed775ee7SAntonio Huete Jimenez 	 */
2238*ed775ee7SAntonio Huete Jimenez 	{
2239*ed775ee7SAntonio Huete Jimenez 		"PORT_MOD",                 of10_port_mod_print,
2240*ed775ee7SAntonio Huete Jimenez 		REQ_FIXLEN,                 OF_PORT_MOD_FIXLEN
2241*ed775ee7SAntonio Huete Jimenez 	},
2242*ed775ee7SAntonio Huete Jimenez 	/*
2243*ed775ee7SAntonio Huete Jimenez 	 * [OF10] Section 5.3.5
2244*ed775ee7SAntonio Huete Jimenez 	 * A fixed-size message body and possibly more data of varying size
2245*ed775ee7SAntonio Huete Jimenez 	 * and structure.
2246*ed775ee7SAntonio Huete Jimenez 	 */
2247*ed775ee7SAntonio Huete Jimenez 	{
2248*ed775ee7SAntonio Huete Jimenez 		"STATS_REQUEST",            of10_stats_request_print,
2249*ed775ee7SAntonio Huete Jimenez 		REQ_MINLEN,                 OF_STATS_REQUEST_MINLEN
2250*ed775ee7SAntonio Huete Jimenez 	},
2251*ed775ee7SAntonio Huete Jimenez 	/*
2252*ed775ee7SAntonio Huete Jimenez 	 * [OF10] Section 5.3.5
2253*ed775ee7SAntonio Huete Jimenez 	 * A fixed-size message body and possibly more data of varying size
2254*ed775ee7SAntonio Huete Jimenez 	 * and structure.
2255*ed775ee7SAntonio Huete Jimenez 	 */
2256*ed775ee7SAntonio Huete Jimenez 	{
2257*ed775ee7SAntonio Huete Jimenez 		"STATS_REPLY",              of10_stats_reply_print,
2258*ed775ee7SAntonio Huete Jimenez 		REQ_MINLEN,                 OF_STATS_REPLY_MINLEN
2259*ed775ee7SAntonio Huete Jimenez 	},
2260*ed775ee7SAntonio Huete Jimenez 	/*
2261*ed775ee7SAntonio Huete Jimenez 	 * [OF10] Section 5.3.7
2262*ed775ee7SAntonio Huete Jimenez 	 * No message body.
2263*ed775ee7SAntonio Huete Jimenez 	 */
2264*ed775ee7SAntonio Huete Jimenez 	{
2265*ed775ee7SAntonio Huete Jimenez 		"BARRIER_REQUEST",          NULL,
2266*ed775ee7SAntonio Huete Jimenez 		REQ_FIXLEN,                 0
2267*ed775ee7SAntonio Huete Jimenez 	},
2268*ed775ee7SAntonio Huete Jimenez 	/*
2269*ed775ee7SAntonio Huete Jimenez 	 * [OF10] Section 5.3.7
2270*ed775ee7SAntonio Huete Jimenez 	 * No message body.
2271*ed775ee7SAntonio Huete Jimenez 	 */
2272*ed775ee7SAntonio Huete Jimenez 	{
2273*ed775ee7SAntonio Huete Jimenez 		"BARRIER_REPLY",            NULL,
2274*ed775ee7SAntonio Huete Jimenez 		REQ_FIXLEN,                 0
2275*ed775ee7SAntonio Huete Jimenez 	},
2276*ed775ee7SAntonio Huete Jimenez 	/*
2277*ed775ee7SAntonio Huete Jimenez 	 * [OF10] Section 5.3.4
2278*ed775ee7SAntonio Huete Jimenez 	 * A fixed-size message body.
2279*ed775ee7SAntonio Huete Jimenez 	 */
2280*ed775ee7SAntonio Huete Jimenez 	{
2281*ed775ee7SAntonio Huete Jimenez 		"QUEUE_GET_CONFIG_REQUEST", of10_queue_get_config_request_print,
2282*ed775ee7SAntonio Huete Jimenez 		REQ_FIXLEN,                 OF_QUEUE_GET_CONFIG_REQUEST_FIXLEN
2283*ed775ee7SAntonio Huete Jimenez 	},
2284*ed775ee7SAntonio Huete Jimenez 	/*
2285*ed775ee7SAntonio Huete Jimenez 	 * [OF10] Section 5.3.4
2286*ed775ee7SAntonio Huete Jimenez 	 * A fixed-size message body and n * variable-size data units.
2287*ed775ee7SAntonio Huete Jimenez 	 */
2288*ed775ee7SAntonio Huete Jimenez 	{
2289*ed775ee7SAntonio Huete Jimenez 		"QUEUE_GET_CONFIG_REPLY",   of10_queue_get_config_reply_print,
2290*ed775ee7SAntonio Huete Jimenez 		REQ_MINLEN,                 OF_QUEUE_GET_CONFIG_REPLY_MINLEN
2291*ed775ee7SAntonio Huete Jimenez 	},
2292*ed775ee7SAntonio Huete Jimenez };
2293411677aeSAaron LI 
2294*ed775ee7SAntonio Huete Jimenez const struct of_msgtypeinfo *
of10_identify_msgtype(const uint8_t type)2295*ed775ee7SAntonio Huete Jimenez of10_identify_msgtype(const uint8_t type)
2296*ed775ee7SAntonio Huete Jimenez {
2297*ed775ee7SAntonio Huete Jimenez 	return type <= OFPT_MAX ? &of10_msgtypeinfo[type] : NULL;
2298411677aeSAaron LI }
2299