1*05b00f60SXin Li /*
2*05b00f60SXin Li * This module implements decoding of OpenFlow protocol version 1.0 (wire
3*05b00f60SXin Li * protocol 0x01). The decoder implements terse (default), detailed (-v) and
4*05b00f60SXin Li * full (-vv) output formats and, as much as each format implies, detects and
5*05b00f60SXin Li * tries to work around sizing anomalies inside the messages. The decoder marks
6*05b00f60SXin Li * up bogus values of selected message fields and decodes partially captured
7*05b00f60SXin Li * messages up to the snapshot end. It is based on the specification below:
8*05b00f60SXin Li *
9*05b00f60SXin Li * [OF10] https://www.opennetworking.org/wp-content/uploads/2013/04/openflow-spec-v1.0.0.pdf
10*05b00f60SXin Li *
11*05b00f60SXin Li * Most functions in this file take the following arguments:
12*05b00f60SXin Li * * cp -- the pointer to the first octet to decode
13*05b00f60SXin Li * * len -- the declared length of the structure to decode
14*05b00f60SXin Li * The convention is that a printer function returns iff the given structure is
15*05b00f60SXin Li * completely within the packet buffer; otherwise it processes the part that is
16*05b00f60SXin Li * within the buffer, sooner of later takes the "truncated packet" shortcut via
17*05b00f60SXin Li * longjmp() and never returns. With that in mind, the function may return
18*05b00f60SXin Li * without printing the structure completely if it is invalid or the ndo_vflag
19*05b00f60SXin Li * value is not high enough. This way the calling function can try to decode
20*05b00f60SXin Li * the next data item.
21*05b00f60SXin Li *
22*05b00f60SXin Li * Decoding of Ethernet frames nested in OFPT_PACKET_IN and OFPT_PACKET_OUT
23*05b00f60SXin Li * messages is done only when the verbosity level set by command-line argument
24*05b00f60SXin Li * is "-vvv" or higher. In that case the verbosity level is temporarily
25*05b00f60SXin Li * decremented by 3 during the nested frame decoding. For example, running
26*05b00f60SXin Li * tcpdump with "-vvvv" will do full decoding of OpenFlow and "-v" decoding of
27*05b00f60SXin Li * the nested frames.
28*05b00f60SXin Li *
29*05b00f60SXin Li * Partial decoding of Big Switch Networks vendor extensions is done after the
30*05b00f60SXin Li * oftest (OpenFlow Testing Framework) and Loxigen (library generator) source
31*05b00f60SXin Li * code.
32*05b00f60SXin Li *
33*05b00f60SXin Li *
34*05b00f60SXin Li * Copyright (c) 2013 The TCPDUMP project
35*05b00f60SXin Li * All rights reserved.
36*05b00f60SXin Li *
37*05b00f60SXin Li * Redistribution and use in source and binary forms, with or without
38*05b00f60SXin Li * modification, are permitted provided that the following conditions
39*05b00f60SXin Li * are met:
40*05b00f60SXin Li * 1. Redistributions of source code must retain the above copyright
41*05b00f60SXin Li * notice, this list of conditions and the following disclaimer.
42*05b00f60SXin Li * 2. Redistributions in binary form must reproduce the above copyright
43*05b00f60SXin Li * notice, this list of conditions and the following disclaimer in the
44*05b00f60SXin Li * documentation and/or other materials provided with the distribution.
45*05b00f60SXin Li *
46*05b00f60SXin Li * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
47*05b00f60SXin Li * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
48*05b00f60SXin Li * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
49*05b00f60SXin Li * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
50*05b00f60SXin Li * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
51*05b00f60SXin Li * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
52*05b00f60SXin Li * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
53*05b00f60SXin Li * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
54*05b00f60SXin Li * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55*05b00f60SXin Li * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
56*05b00f60SXin Li * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
57*05b00f60SXin Li * POSSIBILITY OF SUCH DAMAGE.
58*05b00f60SXin Li */
59*05b00f60SXin Li
60*05b00f60SXin Li /* \summary: OpenFlow protocol version 1.0 printer */
61*05b00f60SXin Li
62*05b00f60SXin Li #ifdef HAVE_CONFIG_H
63*05b00f60SXin Li #include <config.h>
64*05b00f60SXin Li #endif
65*05b00f60SXin Li
66*05b00f60SXin Li #include "netdissect-stdinc.h"
67*05b00f60SXin Li
68*05b00f60SXin Li #define ND_LONGJMP_FROM_TCHECK
69*05b00f60SXin Li #include "netdissect.h"
70*05b00f60SXin Li #include "extract.h"
71*05b00f60SXin Li #include "addrtoname.h"
72*05b00f60SXin Li #include "ethertype.h"
73*05b00f60SXin Li #include "ipproto.h"
74*05b00f60SXin Li #include "oui.h"
75*05b00f60SXin Li #include "openflow.h"
76*05b00f60SXin Li
77*05b00f60SXin Li
78*05b00f60SXin Li #define OFPT_HELLO 0x00
79*05b00f60SXin Li #define OFPT_ERROR 0x01
80*05b00f60SXin Li #define OFPT_ECHO_REQUEST 0x02
81*05b00f60SXin Li #define OFPT_ECHO_REPLY 0x03
82*05b00f60SXin Li #define OFPT_VENDOR 0x04
83*05b00f60SXin Li #define OFPT_FEATURES_REQUEST 0x05
84*05b00f60SXin Li #define OFPT_FEATURES_REPLY 0x06
85*05b00f60SXin Li #define OFPT_GET_CONFIG_REQUEST 0x07
86*05b00f60SXin Li #define OFPT_GET_CONFIG_REPLY 0x08
87*05b00f60SXin Li #define OFPT_SET_CONFIG 0x09
88*05b00f60SXin Li #define OFPT_PACKET_IN 0x0a
89*05b00f60SXin Li #define OFPT_FLOW_REMOVED 0x0b
90*05b00f60SXin Li #define OFPT_PORT_STATUS 0x0c
91*05b00f60SXin Li #define OFPT_PACKET_OUT 0x0d
92*05b00f60SXin Li #define OFPT_FLOW_MOD 0x0e
93*05b00f60SXin Li #define OFPT_PORT_MOD 0x0f
94*05b00f60SXin Li #define OFPT_STATS_REQUEST 0x10
95*05b00f60SXin Li #define OFPT_STATS_REPLY 0x11
96*05b00f60SXin Li #define OFPT_BARRIER_REQUEST 0x12
97*05b00f60SXin Li #define OFPT_BARRIER_REPLY 0x13
98*05b00f60SXin Li #define OFPT_QUEUE_GET_CONFIG_REQUEST 0x14
99*05b00f60SXin Li #define OFPT_QUEUE_GET_CONFIG_REPLY 0x15
100*05b00f60SXin Li #define OFPT_MAX OFPT_QUEUE_GET_CONFIG_REPLY
101*05b00f60SXin Li
102*05b00f60SXin Li #define OFPPC_PORT_DOWN (1U <<0)
103*05b00f60SXin Li #define OFPPC_NO_STP (1U <<1)
104*05b00f60SXin Li #define OFPPC_NO_RECV (1U <<2)
105*05b00f60SXin Li #define OFPPC_NO_RECV_STP (1U <<3)
106*05b00f60SXin Li #define OFPPC_NO_FLOOD (1U <<4)
107*05b00f60SXin Li #define OFPPC_NO_FWD (1U <<5)
108*05b00f60SXin Li #define OFPPC_NO_PACKET_IN (1U <<6)
109*05b00f60SXin Li static const struct tok ofppc_bm[] = {
110*05b00f60SXin Li { OFPPC_PORT_DOWN, "PORT_DOWN" },
111*05b00f60SXin Li { OFPPC_NO_STP, "NO_STP" },
112*05b00f60SXin Li { OFPPC_NO_RECV, "NO_RECV" },
113*05b00f60SXin Li { OFPPC_NO_RECV_STP, "NO_RECV_STP" },
114*05b00f60SXin Li { OFPPC_NO_FLOOD, "NO_FLOOD" },
115*05b00f60SXin Li { OFPPC_NO_FWD, "NO_FWD" },
116*05b00f60SXin Li { OFPPC_NO_PACKET_IN, "NO_PACKET_IN" },
117*05b00f60SXin Li { 0, NULL }
118*05b00f60SXin Li };
119*05b00f60SXin Li #define OFPPC_U (~(OFPPC_PORT_DOWN | OFPPC_NO_STP | OFPPC_NO_RECV | \
120*05b00f60SXin Li OFPPC_NO_RECV_STP | OFPPC_NO_FLOOD | OFPPC_NO_FWD | \
121*05b00f60SXin Li OFPPC_NO_PACKET_IN))
122*05b00f60SXin Li
123*05b00f60SXin Li /*
124*05b00f60SXin Li * [OF10] lists all FPPS_ constants in one enum, but they mean a 1-bit bitmap
125*05b00f60SXin Li * in the least significant octet and a 2-bit code point in the next octet.
126*05b00f60SXin Li * Remember to mix or to separate these two parts as the context requires.
127*05b00f60SXin Li */
128*05b00f60SXin Li #define OFPPS_LINK_DOWN (1U << 0) /* bitmap */
129*05b00f60SXin Li #define OFPPS_STP_LISTEN (0U << 8) /* code point */
130*05b00f60SXin Li #define OFPPS_STP_LEARN (1U << 8) /* code point */
131*05b00f60SXin Li #define OFPPS_STP_FORWARD (2U << 8) /* code point */
132*05b00f60SXin Li #define OFPPS_STP_BLOCK (3U << 8) /* code point */
133*05b00f60SXin Li #define OFPPS_STP_MASK (3U << 8) /* code point bitmask */
134*05b00f60SXin Li static const struct tok ofpps_stp_str[] = {
135*05b00f60SXin Li { OFPPS_STP_LISTEN, "STP_LISTEN" },
136*05b00f60SXin Li { OFPPS_STP_LEARN, "STP_LEARN" },
137*05b00f60SXin Li { OFPPS_STP_FORWARD, "STP_FORWARD" },
138*05b00f60SXin Li { OFPPS_STP_BLOCK, "STP_BLOCK" },
139*05b00f60SXin Li { 0, NULL }
140*05b00f60SXin Li };
141*05b00f60SXin Li #define OFPPS_U (~(OFPPS_LINK_DOWN | OFPPS_STP_LISTEN | OFPPS_STP_LEARN | \
142*05b00f60SXin Li OFPPS_STP_FORWARD | OFPPS_STP_BLOCK))
143*05b00f60SXin Li
144*05b00f60SXin Li #define OFPP_MAX 0xff00U
145*05b00f60SXin Li #define OFPP_IN_PORT 0xfff8U
146*05b00f60SXin Li #define OFPP_TABLE 0xfff9U
147*05b00f60SXin Li #define OFPP_NORMAL 0xfffaU
148*05b00f60SXin Li #define OFPP_FLOOD 0xfffbU
149*05b00f60SXin Li #define OFPP_ALL 0xfffcU
150*05b00f60SXin Li #define OFPP_CONTROLLER 0xfffdU
151*05b00f60SXin Li #define OFPP_LOCAL 0xfffeU
152*05b00f60SXin Li #define OFPP_NONE 0xffffU
153*05b00f60SXin Li static const struct tok ofpp_str[] = {
154*05b00f60SXin Li { OFPP_MAX, "MAX" },
155*05b00f60SXin Li { OFPP_IN_PORT, "IN_PORT" },
156*05b00f60SXin Li { OFPP_TABLE, "TABLE" },
157*05b00f60SXin Li { OFPP_NORMAL, "NORMAL" },
158*05b00f60SXin Li { OFPP_FLOOD, "FLOOD" },
159*05b00f60SXin Li { OFPP_ALL, "ALL" },
160*05b00f60SXin Li { OFPP_CONTROLLER, "CONTROLLER" },
161*05b00f60SXin Li { OFPP_LOCAL, "LOCAL" },
162*05b00f60SXin Li { OFPP_NONE, "NONE" },
163*05b00f60SXin Li { 0, NULL }
164*05b00f60SXin Li };
165*05b00f60SXin Li
166*05b00f60SXin Li #define OFPPF_10MB_HD (1U << 0)
167*05b00f60SXin Li #define OFPPF_10MB_FD (1U << 1)
168*05b00f60SXin Li #define OFPPF_100MB_HD (1U << 2)
169*05b00f60SXin Li #define OFPPF_100MB_FD (1U << 3)
170*05b00f60SXin Li #define OFPPF_1GB_HD (1U << 4)
171*05b00f60SXin Li #define OFPPF_1GB_FD (1U << 5)
172*05b00f60SXin Li #define OFPPF_10GB_FD (1U << 6)
173*05b00f60SXin Li #define OFPPF_COPPER (1U << 7)
174*05b00f60SXin Li #define OFPPF_FIBER (1U << 8)
175*05b00f60SXin Li #define OFPPF_AUTONEG (1U << 9)
176*05b00f60SXin Li #define OFPPF_PAUSE (1U <<10)
177*05b00f60SXin Li #define OFPPF_PAUSE_ASYM (1U <<11)
178*05b00f60SXin Li static const struct tok ofppf_bm[] = {
179*05b00f60SXin Li { OFPPF_10MB_HD, "10MB_HD" },
180*05b00f60SXin Li { OFPPF_10MB_FD, "10MB_FD" },
181*05b00f60SXin Li { OFPPF_100MB_HD, "100MB_HD" },
182*05b00f60SXin Li { OFPPF_100MB_FD, "100MB_FD" },
183*05b00f60SXin Li { OFPPF_1GB_HD, "1GB_HD" },
184*05b00f60SXin Li { OFPPF_1GB_FD, "1GB_FD" },
185*05b00f60SXin Li { OFPPF_10GB_FD, "10GB_FD" },
186*05b00f60SXin Li { OFPPF_COPPER, "COPPER" },
187*05b00f60SXin Li { OFPPF_FIBER, "FIBER" },
188*05b00f60SXin Li { OFPPF_AUTONEG, "AUTONEG" },
189*05b00f60SXin Li { OFPPF_PAUSE, "PAUSE" },
190*05b00f60SXin Li { OFPPF_PAUSE_ASYM, "PAUSE_ASYM" },
191*05b00f60SXin Li { 0, NULL }
192*05b00f60SXin Li };
193*05b00f60SXin Li #define OFPPF_U (~(OFPPF_10MB_HD | OFPPF_10MB_FD | OFPPF_100MB_HD | \
194*05b00f60SXin Li OFPPF_100MB_FD | OFPPF_1GB_HD | OFPPF_1GB_FD | \
195*05b00f60SXin Li OFPPF_10GB_FD | OFPPF_COPPER | OFPPF_FIBER | \
196*05b00f60SXin Li OFPPF_AUTONEG | OFPPF_PAUSE | OFPPF_PAUSE_ASYM))
197*05b00f60SXin Li
198*05b00f60SXin Li #define OFPQT_NONE 0x0000
199*05b00f60SXin Li #define OFPQT_MIN_RATE 0x0001
200*05b00f60SXin Li static const struct tok ofpqt_str[] = {
201*05b00f60SXin Li { OFPQT_NONE, "NONE" },
202*05b00f60SXin Li { OFPQT_MIN_RATE, "MIN_RATE" },
203*05b00f60SXin Li { 0, NULL }
204*05b00f60SXin Li };
205*05b00f60SXin Li
206*05b00f60SXin Li #define OFPFW_IN_PORT (1U <<0)
207*05b00f60SXin Li #define OFPFW_DL_VLAN (1U <<1)
208*05b00f60SXin Li #define OFPFW_DL_SRC (1U <<2)
209*05b00f60SXin Li #define OFPFW_DL_DST (1U <<3)
210*05b00f60SXin Li #define OFPFW_DL_TYPE (1U <<4)
211*05b00f60SXin Li #define OFPFW_NW_PROTO (1U <<5)
212*05b00f60SXin Li #define OFPFW_TP_SRC (1U <<6)
213*05b00f60SXin Li #define OFPFW_TP_DST (1U <<7)
214*05b00f60SXin Li #define OFPFW_NW_SRC_SHIFT 8
215*05b00f60SXin Li #define OFPFW_NW_SRC_BITS 6
216*05b00f60SXin Li #define OFPFW_NW_SRC_MASK (((1U <<OFPFW_NW_SRC_BITS) - 1) << OFPFW_NW_SRC_SHIFT)
217*05b00f60SXin Li #define OFPFW_NW_DST_SHIFT 14
218*05b00f60SXin Li #define OFPFW_NW_DST_BITS 6
219*05b00f60SXin Li #define OFPFW_NW_DST_MASK (((1U <<OFPFW_NW_DST_BITS) - 1) << OFPFW_NW_DST_SHIFT)
220*05b00f60SXin Li #define OFPFW_DL_VLAN_PCP (1U <<20)
221*05b00f60SXin Li #define OFPFW_NW_TOS (1U <<21)
222*05b00f60SXin Li #define OFPFW_ALL ((1U <<22) - 1)
223*05b00f60SXin Li static const struct tok ofpfw_bm[] = {
224*05b00f60SXin Li { OFPFW_IN_PORT, "IN_PORT" },
225*05b00f60SXin Li { OFPFW_DL_VLAN, "DL_VLAN" },
226*05b00f60SXin Li { OFPFW_DL_SRC, "DL_SRC" },
227*05b00f60SXin Li { OFPFW_DL_DST, "DL_DST" },
228*05b00f60SXin Li { OFPFW_DL_TYPE, "DL_TYPE" },
229*05b00f60SXin Li { OFPFW_NW_PROTO, "NW_PROTO" },
230*05b00f60SXin Li { OFPFW_TP_SRC, "TP_SRC" },
231*05b00f60SXin Li { OFPFW_TP_DST, "TP_DST" },
232*05b00f60SXin Li { OFPFW_DL_VLAN_PCP, "DL_VLAN_PCP" },
233*05b00f60SXin Li { OFPFW_NW_TOS, "NW_TOS" },
234*05b00f60SXin Li { 0, NULL }
235*05b00f60SXin Li };
236*05b00f60SXin Li /* The above array does not include bits 8~13 (OFPFW_NW_SRC_*) and 14~19
237*05b00f60SXin Li * (OFPFW_NW_DST_*), which are not a part of the bitmap and require decoding
238*05b00f60SXin Li * other than that of tok2str(). The macro below includes these bits such that
239*05b00f60SXin Li * they are not reported as bogus in the decoding. */
240*05b00f60SXin Li #define OFPFW_U (~(OFPFW_ALL))
241*05b00f60SXin Li
242*05b00f60SXin Li #define OFPAT_OUTPUT 0x0000U
243*05b00f60SXin Li #define OFPAT_SET_VLAN_VID 0x0001U
244*05b00f60SXin Li #define OFPAT_SET_VLAN_PCP 0x0002U
245*05b00f60SXin Li #define OFPAT_STRIP_VLAN 0x0003U
246*05b00f60SXin Li #define OFPAT_SET_DL_SRC 0x0004U
247*05b00f60SXin Li #define OFPAT_SET_DL_DST 0x0005U
248*05b00f60SXin Li #define OFPAT_SET_NW_SRC 0x0006U
249*05b00f60SXin Li #define OFPAT_SET_NW_DST 0x0007U
250*05b00f60SXin Li #define OFPAT_SET_NW_TOS 0x0008U
251*05b00f60SXin Li #define OFPAT_SET_TP_SRC 0x0009U
252*05b00f60SXin Li #define OFPAT_SET_TP_DST 0x000aU
253*05b00f60SXin Li #define OFPAT_ENQUEUE 0x000bU
254*05b00f60SXin Li #define OFPAT_VENDOR 0xffffU
255*05b00f60SXin Li static const struct tok ofpat_str[] = {
256*05b00f60SXin Li { OFPAT_OUTPUT, "OUTPUT" },
257*05b00f60SXin Li { OFPAT_SET_VLAN_VID, "SET_VLAN_VID" },
258*05b00f60SXin Li { OFPAT_SET_VLAN_PCP, "SET_VLAN_PCP" },
259*05b00f60SXin Li { OFPAT_STRIP_VLAN, "STRIP_VLAN" },
260*05b00f60SXin Li { OFPAT_SET_DL_SRC, "SET_DL_SRC" },
261*05b00f60SXin Li { OFPAT_SET_DL_DST, "SET_DL_DST" },
262*05b00f60SXin Li { OFPAT_SET_NW_SRC, "SET_NW_SRC" },
263*05b00f60SXin Li { OFPAT_SET_NW_DST, "SET_NW_DST" },
264*05b00f60SXin Li { OFPAT_SET_NW_TOS, "SET_NW_TOS" },
265*05b00f60SXin Li { OFPAT_SET_TP_SRC, "SET_TP_SRC" },
266*05b00f60SXin Li { OFPAT_SET_TP_DST, "SET_TP_DST" },
267*05b00f60SXin Li { OFPAT_ENQUEUE, "ENQUEUE" },
268*05b00f60SXin Li { OFPAT_VENDOR, "VENDOR" },
269*05b00f60SXin Li { 0, NULL }
270*05b00f60SXin Li };
271*05b00f60SXin Li
272*05b00f60SXin Li /* bit-shifted, w/o vendor action */
273*05b00f60SXin Li static const struct tok ofpat_bm[] = {
274*05b00f60SXin Li { 1U <<OFPAT_OUTPUT, "OUTPUT" },
275*05b00f60SXin Li { 1U <<OFPAT_SET_VLAN_VID, "SET_VLAN_VID" },
276*05b00f60SXin Li { 1U <<OFPAT_SET_VLAN_PCP, "SET_VLAN_PCP" },
277*05b00f60SXin Li { 1U <<OFPAT_STRIP_VLAN, "STRIP_VLAN" },
278*05b00f60SXin Li { 1U <<OFPAT_SET_DL_SRC, "SET_DL_SRC" },
279*05b00f60SXin Li { 1U <<OFPAT_SET_DL_DST, "SET_DL_DST" },
280*05b00f60SXin Li { 1U <<OFPAT_SET_NW_SRC, "SET_NW_SRC" },
281*05b00f60SXin Li { 1U <<OFPAT_SET_NW_DST, "SET_NW_DST" },
282*05b00f60SXin Li { 1U <<OFPAT_SET_NW_TOS, "SET_NW_TOS" },
283*05b00f60SXin Li { 1U <<OFPAT_SET_TP_SRC, "SET_TP_SRC" },
284*05b00f60SXin Li { 1U <<OFPAT_SET_TP_DST, "SET_TP_DST" },
285*05b00f60SXin Li { 1U <<OFPAT_ENQUEUE, "ENQUEUE" },
286*05b00f60SXin Li { 0, NULL }
287*05b00f60SXin Li };
288*05b00f60SXin Li #define OFPAT_U (~(1U <<OFPAT_OUTPUT | 1U <<OFPAT_SET_VLAN_VID | \
289*05b00f60SXin Li 1U <<OFPAT_SET_VLAN_PCP | 1U <<OFPAT_STRIP_VLAN | \
290*05b00f60SXin Li 1U <<OFPAT_SET_DL_SRC | 1U <<OFPAT_SET_DL_DST | \
291*05b00f60SXin Li 1U <<OFPAT_SET_NW_SRC | 1U <<OFPAT_SET_NW_DST | \
292*05b00f60SXin Li 1U <<OFPAT_SET_NW_TOS | 1U <<OFPAT_SET_TP_SRC | \
293*05b00f60SXin Li 1U <<OFPAT_SET_TP_DST | 1U <<OFPAT_ENQUEUE))
294*05b00f60SXin Li
295*05b00f60SXin Li #define OFPC_FLOW_STATS (1U <<0)
296*05b00f60SXin Li #define OFPC_TABLE_STATS (1U <<1)
297*05b00f60SXin Li #define OFPC_PORT_STATS (1U <<2)
298*05b00f60SXin Li #define OFPC_STP (1U <<3)
299*05b00f60SXin Li #define OFPC_RESERVED (1U <<4)
300*05b00f60SXin Li #define OFPC_IP_REASM (1U <<5)
301*05b00f60SXin Li #define OFPC_QUEUE_STATS (1U <<6)
302*05b00f60SXin Li #define OFPC_ARP_MATCH_IP (1U <<7)
303*05b00f60SXin Li static const struct tok ofp_capabilities_bm[] = {
304*05b00f60SXin Li { OFPC_FLOW_STATS, "FLOW_STATS" },
305*05b00f60SXin Li { OFPC_TABLE_STATS, "TABLE_STATS" },
306*05b00f60SXin Li { OFPC_PORT_STATS, "PORT_STATS" },
307*05b00f60SXin Li { OFPC_STP, "STP" },
308*05b00f60SXin Li { OFPC_RESERVED, "RESERVED" }, /* not in the mask below */
309*05b00f60SXin Li { OFPC_IP_REASM, "IP_REASM" },
310*05b00f60SXin Li { OFPC_QUEUE_STATS, "QUEUE_STATS" },
311*05b00f60SXin Li { OFPC_ARP_MATCH_IP, "ARP_MATCH_IP" },
312*05b00f60SXin Li { 0, NULL }
313*05b00f60SXin Li };
314*05b00f60SXin Li #define OFPCAP_U (~(OFPC_FLOW_STATS | OFPC_TABLE_STATS | OFPC_PORT_STATS | \
315*05b00f60SXin Li OFPC_STP | OFPC_IP_REASM | OFPC_QUEUE_STATS | \
316*05b00f60SXin Li OFPC_ARP_MATCH_IP))
317*05b00f60SXin Li
318*05b00f60SXin Li #define OFPC_FRAG_NORMAL 0x0000U
319*05b00f60SXin Li #define OFPC_FRAG_DROP 0x0001U
320*05b00f60SXin Li #define OFPC_FRAG_REASM 0x0002U
321*05b00f60SXin Li #define OFPC_FRAG_MASK 0x0003U
322*05b00f60SXin Li static const struct tok ofp_config_str[] = {
323*05b00f60SXin Li { OFPC_FRAG_NORMAL, "FRAG_NORMAL" },
324*05b00f60SXin Li { OFPC_FRAG_DROP, "FRAG_DROP" },
325*05b00f60SXin Li { OFPC_FRAG_REASM, "FRAG_REASM" },
326*05b00f60SXin Li { 0, NULL }
327*05b00f60SXin Li };
328*05b00f60SXin Li
329*05b00f60SXin Li #define OFPFC_ADD 0x0000U
330*05b00f60SXin Li #define OFPFC_MODIFY 0x0001U
331*05b00f60SXin Li #define OFPFC_MODIFY_STRICT 0x0002U
332*05b00f60SXin Li #define OFPFC_DELETE 0x0003U
333*05b00f60SXin Li #define OFPFC_DELETE_STRICT 0x0004U
334*05b00f60SXin Li static const struct tok ofpfc_str[] = {
335*05b00f60SXin Li { OFPFC_ADD, "ADD" },
336*05b00f60SXin Li { OFPFC_MODIFY, "MODIFY" },
337*05b00f60SXin Li { OFPFC_MODIFY_STRICT, "MODIFY_STRICT" },
338*05b00f60SXin Li { OFPFC_DELETE, "DELETE" },
339*05b00f60SXin Li { OFPFC_DELETE_STRICT, "DELETE_STRICT" },
340*05b00f60SXin Li { 0, NULL }
341*05b00f60SXin Li };
342*05b00f60SXin Li
343*05b00f60SXin Li static const struct tok bufferid_str[] = {
344*05b00f60SXin Li { 0xffffffff, "NONE" },
345*05b00f60SXin Li { 0, NULL }
346*05b00f60SXin Li };
347*05b00f60SXin Li
348*05b00f60SXin Li #define OFPFF_SEND_FLOW_REM (1U <<0)
349*05b00f60SXin Li #define OFPFF_CHECK_OVERLAP (1U <<1)
350*05b00f60SXin Li #define OFPFF_EMERG (1U <<2)
351*05b00f60SXin Li static const struct tok ofpff_bm[] = {
352*05b00f60SXin Li { OFPFF_SEND_FLOW_REM, "SEND_FLOW_REM" },
353*05b00f60SXin Li { OFPFF_CHECK_OVERLAP, "CHECK_OVERLAP" },
354*05b00f60SXin Li { OFPFF_EMERG, "EMERG" },
355*05b00f60SXin Li { 0, NULL }
356*05b00f60SXin Li };
357*05b00f60SXin Li #define OFPFF_U (~(OFPFF_SEND_FLOW_REM | OFPFF_CHECK_OVERLAP | OFPFF_EMERG))
358*05b00f60SXin Li
359*05b00f60SXin Li #define OFPST_DESC 0x0000U
360*05b00f60SXin Li #define OFPST_FLOW 0x0001U
361*05b00f60SXin Li #define OFPST_AGGREGATE 0x0002U
362*05b00f60SXin Li #define OFPST_TABLE 0x0003U
363*05b00f60SXin Li #define OFPST_PORT 0x0004U
364*05b00f60SXin Li #define OFPST_QUEUE 0x0005U
365*05b00f60SXin Li #define OFPST_VENDOR 0xffffU
366*05b00f60SXin Li static const struct tok ofpst_str[] = {
367*05b00f60SXin Li { OFPST_DESC, "DESC" },
368*05b00f60SXin Li { OFPST_FLOW, "FLOW" },
369*05b00f60SXin Li { OFPST_AGGREGATE, "AGGREGATE" },
370*05b00f60SXin Li { OFPST_TABLE, "TABLE" },
371*05b00f60SXin Li { OFPST_PORT, "PORT" },
372*05b00f60SXin Li { OFPST_QUEUE, "QUEUE" },
373*05b00f60SXin Li { OFPST_VENDOR, "VENDOR" },
374*05b00f60SXin Li { 0, NULL }
375*05b00f60SXin Li };
376*05b00f60SXin Li
377*05b00f60SXin Li static const struct tok tableid_str[] = {
378*05b00f60SXin Li { 0xfeU, "EMERG" },
379*05b00f60SXin Li { 0xffU, "ALL" },
380*05b00f60SXin Li { 0, NULL }
381*05b00f60SXin Li };
382*05b00f60SXin Li
383*05b00f60SXin Li #define OFPQ_ALL 0xffffffffU
384*05b00f60SXin Li static const struct tok ofpq_str[] = {
385*05b00f60SXin Li { OFPQ_ALL, "ALL" },
386*05b00f60SXin Li { 0, NULL }
387*05b00f60SXin Li };
388*05b00f60SXin Li
389*05b00f60SXin Li #define OFPSF_REPLY_MORE 0x0001U
390*05b00f60SXin Li static const struct tok ofpsf_reply_bm[] = {
391*05b00f60SXin Li { OFPSF_REPLY_MORE, "MORE" },
392*05b00f60SXin Li { 0, NULL }
393*05b00f60SXin Li };
394*05b00f60SXin Li #define OFPSF_REPLY_U (~(OFPSF_REPLY_MORE))
395*05b00f60SXin Li
396*05b00f60SXin Li #define OFPR_NO_MATCH 0x00U
397*05b00f60SXin Li #define OFPR_ACTION 0x01U
398*05b00f60SXin Li static const struct tok ofpr_str[] = {
399*05b00f60SXin Li { OFPR_NO_MATCH, "NO_MATCH" },
400*05b00f60SXin Li { OFPR_ACTION, "ACTION" },
401*05b00f60SXin Li { 0, NULL }
402*05b00f60SXin Li };
403*05b00f60SXin Li
404*05b00f60SXin Li #define OFPRR_IDLE_TIMEOUT 0x00U
405*05b00f60SXin Li #define OFPRR_HARD_TIMEOUT 0x01U
406*05b00f60SXin Li #define OFPRR_DELETE 0x02U
407*05b00f60SXin Li static const struct tok ofprr_str[] = {
408*05b00f60SXin Li { OFPRR_IDLE_TIMEOUT, "IDLE_TIMEOUT" },
409*05b00f60SXin Li { OFPRR_HARD_TIMEOUT, "HARD_TIMEOUT" },
410*05b00f60SXin Li { OFPRR_DELETE, "DELETE" },
411*05b00f60SXin Li { 0, NULL }
412*05b00f60SXin Li };
413*05b00f60SXin Li
414*05b00f60SXin Li #define OFPPR_ADD 0x00U
415*05b00f60SXin Li #define OFPPR_DELETE 0x01U
416*05b00f60SXin Li #define OFPPR_MODIFY 0x02U
417*05b00f60SXin Li static const struct tok ofppr_str[] = {
418*05b00f60SXin Li { OFPPR_ADD, "ADD" },
419*05b00f60SXin Li { OFPPR_DELETE, "DELETE" },
420*05b00f60SXin Li { OFPPR_MODIFY, "MODIFY" },
421*05b00f60SXin Li { 0, NULL }
422*05b00f60SXin Li };
423*05b00f60SXin Li
424*05b00f60SXin Li #define OFPET_HELLO_FAILED 0x0000U
425*05b00f60SXin Li #define OFPET_BAD_REQUEST 0x0001U
426*05b00f60SXin Li #define OFPET_BAD_ACTION 0x0002U
427*05b00f60SXin Li #define OFPET_FLOW_MOD_FAILED 0x0003U
428*05b00f60SXin Li #define OFPET_PORT_MOD_FAILED 0x0004U
429*05b00f60SXin Li #define OFPET_QUEUE_OP_FAILED 0x0005U
430*05b00f60SXin Li static const struct tok ofpet_str[] = {
431*05b00f60SXin Li { OFPET_HELLO_FAILED, "HELLO_FAILED" },
432*05b00f60SXin Li { OFPET_BAD_REQUEST, "BAD_REQUEST" },
433*05b00f60SXin Li { OFPET_BAD_ACTION, "BAD_ACTION" },
434*05b00f60SXin Li { OFPET_FLOW_MOD_FAILED, "FLOW_MOD_FAILED" },
435*05b00f60SXin Li { OFPET_PORT_MOD_FAILED, "PORT_MOD_FAILED" },
436*05b00f60SXin Li { OFPET_QUEUE_OP_FAILED, "QUEUE_OP_FAILED" },
437*05b00f60SXin Li { 0, NULL }
438*05b00f60SXin Li };
439*05b00f60SXin Li
440*05b00f60SXin Li #define OFPHFC_INCOMPATIBLE 0x0000U
441*05b00f60SXin Li #define OFPHFC_EPERM 0x0001U
442*05b00f60SXin Li static const struct tok ofphfc_str[] = {
443*05b00f60SXin Li { OFPHFC_INCOMPATIBLE, "INCOMPATIBLE" },
444*05b00f60SXin Li { OFPHFC_EPERM, "EPERM" },
445*05b00f60SXin Li { 0, NULL }
446*05b00f60SXin Li };
447*05b00f60SXin Li
448*05b00f60SXin Li #define OFPBRC_BAD_VERSION 0x0000U
449*05b00f60SXin Li #define OFPBRC_BAD_TYPE 0x0001U
450*05b00f60SXin Li #define OFPBRC_BAD_STAT 0x0002U
451*05b00f60SXin Li #define OFPBRC_BAD_VENDOR 0x0003U
452*05b00f60SXin Li #define OFPBRC_BAD_SUBTYPE 0x0004U
453*05b00f60SXin Li #define OFPBRC_EPERM 0x0005U
454*05b00f60SXin Li #define OFPBRC_BAD_LEN 0x0006U
455*05b00f60SXin Li #define OFPBRC_BUFFER_EMPTY 0x0007U
456*05b00f60SXin Li #define OFPBRC_BUFFER_UNKNOWN 0x0008U
457*05b00f60SXin Li static const struct tok ofpbrc_str[] = {
458*05b00f60SXin Li { OFPBRC_BAD_VERSION, "BAD_VERSION" },
459*05b00f60SXin Li { OFPBRC_BAD_TYPE, "BAD_TYPE" },
460*05b00f60SXin Li { OFPBRC_BAD_STAT, "BAD_STAT" },
461*05b00f60SXin Li { OFPBRC_BAD_VENDOR, "BAD_VENDOR" },
462*05b00f60SXin Li { OFPBRC_BAD_SUBTYPE, "BAD_SUBTYPE" },
463*05b00f60SXin Li { OFPBRC_EPERM, "EPERM" },
464*05b00f60SXin Li { OFPBRC_BAD_LEN, "BAD_LEN" },
465*05b00f60SXin Li { OFPBRC_BUFFER_EMPTY, "BUFFER_EMPTY" },
466*05b00f60SXin Li { OFPBRC_BUFFER_UNKNOWN, "BUFFER_UNKNOWN" },
467*05b00f60SXin Li { 0, NULL }
468*05b00f60SXin Li };
469*05b00f60SXin Li
470*05b00f60SXin Li #define OFPBAC_BAD_TYPE 0x0000U
471*05b00f60SXin Li #define OFPBAC_BAD_LEN 0x0001U
472*05b00f60SXin Li #define OFPBAC_BAD_VENDOR 0x0002U
473*05b00f60SXin Li #define OFPBAC_BAD_VENDOR_TYPE 0x0003U
474*05b00f60SXin Li #define OFPBAC_BAD_OUT_PORT 0x0004U
475*05b00f60SXin Li #define OFPBAC_BAD_ARGUMENT 0x0005U
476*05b00f60SXin Li #define OFPBAC_EPERM 0x0006U
477*05b00f60SXin Li #define OFPBAC_TOO_MANY 0x0007U
478*05b00f60SXin Li #define OFPBAC_BAD_QUEUE 0x0008U
479*05b00f60SXin Li static const struct tok ofpbac_str[] = {
480*05b00f60SXin Li { OFPBAC_BAD_TYPE, "BAD_TYPE" },
481*05b00f60SXin Li { OFPBAC_BAD_LEN, "BAD_LEN" },
482*05b00f60SXin Li { OFPBAC_BAD_VENDOR, "BAD_VENDOR" },
483*05b00f60SXin Li { OFPBAC_BAD_VENDOR_TYPE, "BAD_VENDOR_TYPE" },
484*05b00f60SXin Li { OFPBAC_BAD_OUT_PORT, "BAD_OUT_PORT" },
485*05b00f60SXin Li { OFPBAC_BAD_ARGUMENT, "BAD_ARGUMENT" },
486*05b00f60SXin Li { OFPBAC_EPERM, "EPERM" },
487*05b00f60SXin Li { OFPBAC_TOO_MANY, "TOO_MANY" },
488*05b00f60SXin Li { OFPBAC_BAD_QUEUE, "BAD_QUEUE" },
489*05b00f60SXin Li { 0, NULL }
490*05b00f60SXin Li };
491*05b00f60SXin Li
492*05b00f60SXin Li #define OFPFMFC_ALL_TABLES_FULL 0x0000U
493*05b00f60SXin Li #define OFPFMFC_OVERLAP 0x0001U
494*05b00f60SXin Li #define OFPFMFC_EPERM 0x0002U
495*05b00f60SXin Li #define OFPFMFC_BAD_EMERG_TIMEOUT 0x0003U
496*05b00f60SXin Li #define OFPFMFC_BAD_COMMAND 0x0004U
497*05b00f60SXin Li #define OFPFMFC_UNSUPPORTED 0x0005U
498*05b00f60SXin Li static const struct tok ofpfmfc_str[] = {
499*05b00f60SXin Li { OFPFMFC_ALL_TABLES_FULL, "ALL_TABLES_FULL" },
500*05b00f60SXin Li { OFPFMFC_OVERLAP, "OVERLAP" },
501*05b00f60SXin Li { OFPFMFC_EPERM, "EPERM" },
502*05b00f60SXin Li { OFPFMFC_BAD_EMERG_TIMEOUT, "BAD_EMERG_TIMEOUT" },
503*05b00f60SXin Li { OFPFMFC_BAD_COMMAND, "BAD_COMMAND" },
504*05b00f60SXin Li { OFPFMFC_UNSUPPORTED, "UNSUPPORTED" },
505*05b00f60SXin Li { 0, NULL }
506*05b00f60SXin Li };
507*05b00f60SXin Li
508*05b00f60SXin Li #define OFPPMFC_BAD_PORT 0x0000U
509*05b00f60SXin Li #define OFPPMFC_BAD_HW_ADDR 0x0001U
510*05b00f60SXin Li static const struct tok ofppmfc_str[] = {
511*05b00f60SXin Li { OFPPMFC_BAD_PORT, "BAD_PORT" },
512*05b00f60SXin Li { OFPPMFC_BAD_HW_ADDR, "BAD_HW_ADDR" },
513*05b00f60SXin Li { 0, NULL }
514*05b00f60SXin Li };
515*05b00f60SXin Li
516*05b00f60SXin Li #define OFPQOFC_BAD_PORT 0x0000U
517*05b00f60SXin Li #define OFPQOFC_BAD_QUEUE 0x0001U
518*05b00f60SXin Li #define OFPQOFC_EPERM 0x0002U
519*05b00f60SXin Li static const struct tok ofpqofc_str[] = {
520*05b00f60SXin Li { OFPQOFC_BAD_PORT, "BAD_PORT" },
521*05b00f60SXin Li { OFPQOFC_BAD_QUEUE, "BAD_QUEUE" },
522*05b00f60SXin Li { OFPQOFC_EPERM, "EPERM" },
523*05b00f60SXin Li { 0, NULL }
524*05b00f60SXin Li };
525*05b00f60SXin Li
526*05b00f60SXin Li static const struct uint_tokary of10_ofpet2tokary[] = {
527*05b00f60SXin Li { OFPET_HELLO_FAILED, ofphfc_str },
528*05b00f60SXin Li { OFPET_BAD_REQUEST, ofpbrc_str },
529*05b00f60SXin Li { OFPET_BAD_ACTION, ofpbac_str },
530*05b00f60SXin Li { OFPET_FLOW_MOD_FAILED, ofpfmfc_str },
531*05b00f60SXin Li { OFPET_PORT_MOD_FAILED, ofppmfc_str },
532*05b00f60SXin Li { OFPET_QUEUE_OP_FAILED, ofpqofc_str },
533*05b00f60SXin Li /* uint2tokary() does not use array termination. */
534*05b00f60SXin Li };
535*05b00f60SXin Li
536*05b00f60SXin Li /* lengths (fixed or minimal) of particular message types, where not 0 */
537*05b00f60SXin Li #define OF_SWITCH_CONFIG_FIXLEN (12U - OF_HEADER_FIXLEN)
538*05b00f60SXin Li #define OF_FEATURES_REPLY_MINLEN (32U - OF_HEADER_FIXLEN)
539*05b00f60SXin Li #define OF_PORT_STATUS_FIXLEN (64U - OF_HEADER_FIXLEN)
540*05b00f60SXin Li #define OF_PORT_MOD_FIXLEN (32U - OF_HEADER_FIXLEN)
541*05b00f60SXin Li #define OF_PACKET_IN_MINLEN (20U - OF_HEADER_FIXLEN) /* with 2 mock octets */
542*05b00f60SXin Li #define OF_PACKET_OUT_MINLEN (16U - OF_HEADER_FIXLEN)
543*05b00f60SXin Li #define OF_FLOW_MOD_MINLEN (72U - OF_HEADER_FIXLEN)
544*05b00f60SXin Li #define OF_FLOW_REMOVED_FIXLEN (88U - OF_HEADER_FIXLEN)
545*05b00f60SXin Li #define OF_ERROR_MSG_MINLEN (12U - OF_HEADER_FIXLEN)
546*05b00f60SXin Li #define OF_STATS_REQUEST_MINLEN (12U - OF_HEADER_FIXLEN)
547*05b00f60SXin Li #define OF_STATS_REPLY_MINLEN (12U - OF_HEADER_FIXLEN)
548*05b00f60SXin Li #define OF_VENDOR_MINLEN (12U - OF_HEADER_FIXLEN)
549*05b00f60SXin Li #define OF_QUEUE_GET_CONFIG_REQUEST_FIXLEN (12U - OF_HEADER_FIXLEN)
550*05b00f60SXin Li #define OF_QUEUE_GET_CONFIG_REPLY_MINLEN (16U - OF_HEADER_FIXLEN)
551*05b00f60SXin Li
552*05b00f60SXin Li /* lengths (fixed or minimal) of particular protocol structures */
553*05b00f60SXin Li #define OF_PHY_PORT_FIXLEN 48
554*05b00f60SXin Li #define OF_ACTION_MINLEN 8
555*05b00f60SXin Li #define OF_MATCH_FIXLEN 40
556*05b00f60SXin Li #define OF_DESC_STATS_REPLY_FIXLEN 1056
557*05b00f60SXin Li #define OF_FLOW_STATS_REQUEST_FIXLEN 44
558*05b00f60SXin Li #define OF_FLOW_STATS_REPLY_MINLEN 88
559*05b00f60SXin Li #define OF_AGGREGATE_STATS_REPLY_FIXLEN 24
560*05b00f60SXin Li #define OF_TABLE_STATS_REPLY_FIXLEN 64
561*05b00f60SXin Li #define OF_PORT_STATS_REQUEST_FIXLEN 8
562*05b00f60SXin Li #define OF_PORT_STATS_REPLY_FIXLEN 104
563*05b00f60SXin Li #define OF_QUEUE_PROP_MINLEN 8
564*05b00f60SXin Li #define OF_QUEUE_PROP_MIN_RATE_FIXLEN 16
565*05b00f60SXin Li #define OF_PACKET_QUEUE_MINLEN 8
566*05b00f60SXin Li #define OF_QUEUE_STATS_REQUEST_FIXLEN 8
567*05b00f60SXin Li #define OF_QUEUE_STATS_REPLY_FIXLEN 32
568*05b00f60SXin Li
569*05b00f60SXin Li /* miscellaneous constants from [OF10] */
570*05b00f60SXin Li #define OFP_MAX_TABLE_NAME_LEN 32
571*05b00f60SXin Li #define OFP_MAX_PORT_NAME_LEN 16
572*05b00f60SXin Li #define DESC_STR_LEN 256
573*05b00f60SXin Li #define SERIAL_NUM_LEN 32
574*05b00f60SXin Li #define OFP_VLAN_NONE 0xffffU
575*05b00f60SXin Li
576*05b00f60SXin Li /* vendor extensions */
577*05b00f60SXin Li #define BSN_SET_IP_MASK 0
578*05b00f60SXin Li #define BSN_GET_IP_MASK_REQUEST 1
579*05b00f60SXin Li #define BSN_GET_IP_MASK_REPLY 2
580*05b00f60SXin Li #define BSN_SET_MIRRORING 3
581*05b00f60SXin Li #define BSN_GET_MIRRORING_REQUEST 4
582*05b00f60SXin Li #define BSN_GET_MIRRORING_REPLY 5
583*05b00f60SXin Li #define BSN_SHELL_COMMAND 6
584*05b00f60SXin Li #define BSN_SHELL_OUTPUT 7
585*05b00f60SXin Li #define BSN_SHELL_STATUS 8
586*05b00f60SXin Li #define BSN_GET_INTERFACES_REQUEST 9
587*05b00f60SXin Li #define BSN_GET_INTERFACES_REPLY 10
588*05b00f60SXin Li #define BSN_SET_PKTIN_SUPPRESSION_REQUEST 11
589*05b00f60SXin Li #define BSN_SET_L2_TABLE_REQUEST 12
590*05b00f60SXin Li #define BSN_GET_L2_TABLE_REQUEST 13
591*05b00f60SXin Li #define BSN_GET_L2_TABLE_REPLY 14
592*05b00f60SXin Li #define BSN_VIRTUAL_PORT_CREATE_REQUEST 15
593*05b00f60SXin Li #define BSN_VIRTUAL_PORT_CREATE_REPLY 16
594*05b00f60SXin Li #define BSN_VIRTUAL_PORT_REMOVE_REQUEST 17
595*05b00f60SXin Li #define BSN_BW_ENABLE_SET_REQUEST 18
596*05b00f60SXin Li #define BSN_BW_ENABLE_GET_REQUEST 19
597*05b00f60SXin Li #define BSN_BW_ENABLE_GET_REPLY 20
598*05b00f60SXin Li #define BSN_BW_CLEAR_DATA_REQUEST 21
599*05b00f60SXin Li #define BSN_BW_CLEAR_DATA_REPLY 22
600*05b00f60SXin Li #define BSN_BW_ENABLE_SET_REPLY 23
601*05b00f60SXin Li #define BSN_SET_L2_TABLE_REPLY 24
602*05b00f60SXin Li #define BSN_SET_PKTIN_SUPPRESSION_REPLY 25
603*05b00f60SXin Li #define BSN_VIRTUAL_PORT_REMOVE_REPLY 26
604*05b00f60SXin Li #define BSN_HYBRID_GET_REQUEST 27
605*05b00f60SXin Li #define BSN_HYBRID_GET_REPLY 28
606*05b00f60SXin Li /* 29 */
607*05b00f60SXin Li /* 30 */
608*05b00f60SXin Li #define BSN_PDU_TX_REQUEST 31
609*05b00f60SXin Li #define BSN_PDU_TX_REPLY 32
610*05b00f60SXin Li #define BSN_PDU_RX_REQUEST 33
611*05b00f60SXin Li #define BSN_PDU_RX_REPLY 34
612*05b00f60SXin Li #define BSN_PDU_RX_TIMEOUT 35
613*05b00f60SXin Li
614*05b00f60SXin Li static const struct tok bsn_subtype_str[] = {
615*05b00f60SXin Li { BSN_SET_IP_MASK, "SET_IP_MASK" },
616*05b00f60SXin Li { BSN_GET_IP_MASK_REQUEST, "GET_IP_MASK_REQUEST" },
617*05b00f60SXin Li { BSN_GET_IP_MASK_REPLY, "GET_IP_MASK_REPLY" },
618*05b00f60SXin Li { BSN_SET_MIRRORING, "SET_MIRRORING" },
619*05b00f60SXin Li { BSN_GET_MIRRORING_REQUEST, "GET_MIRRORING_REQUEST" },
620*05b00f60SXin Li { BSN_GET_MIRRORING_REPLY, "GET_MIRRORING_REPLY" },
621*05b00f60SXin Li { BSN_SHELL_COMMAND, "SHELL_COMMAND" },
622*05b00f60SXin Li { BSN_SHELL_OUTPUT, "SHELL_OUTPUT" },
623*05b00f60SXin Li { BSN_SHELL_STATUS, "SHELL_STATUS" },
624*05b00f60SXin Li { BSN_GET_INTERFACES_REQUEST, "GET_INTERFACES_REQUEST" },
625*05b00f60SXin Li { BSN_GET_INTERFACES_REPLY, "GET_INTERFACES_REPLY" },
626*05b00f60SXin Li { BSN_SET_PKTIN_SUPPRESSION_REQUEST, "SET_PKTIN_SUPPRESSION_REQUEST" },
627*05b00f60SXin Li { BSN_SET_L2_TABLE_REQUEST, "SET_L2_TABLE_REQUEST" },
628*05b00f60SXin Li { BSN_GET_L2_TABLE_REQUEST, "GET_L2_TABLE_REQUEST" },
629*05b00f60SXin Li { BSN_GET_L2_TABLE_REPLY, "GET_L2_TABLE_REPLY" },
630*05b00f60SXin Li { BSN_VIRTUAL_PORT_CREATE_REQUEST, "VIRTUAL_PORT_CREATE_REQUEST" },
631*05b00f60SXin Li { BSN_VIRTUAL_PORT_CREATE_REPLY, "VIRTUAL_PORT_CREATE_REPLY" },
632*05b00f60SXin Li { BSN_VIRTUAL_PORT_REMOVE_REQUEST, "VIRTUAL_PORT_REMOVE_REQUEST" },
633*05b00f60SXin Li { BSN_BW_ENABLE_SET_REQUEST, "BW_ENABLE_SET_REQUEST" },
634*05b00f60SXin Li { BSN_BW_ENABLE_GET_REQUEST, "BW_ENABLE_GET_REQUEST" },
635*05b00f60SXin Li { BSN_BW_ENABLE_GET_REPLY, "BW_ENABLE_GET_REPLY" },
636*05b00f60SXin Li { BSN_BW_CLEAR_DATA_REQUEST, "BW_CLEAR_DATA_REQUEST" },
637*05b00f60SXin Li { BSN_BW_CLEAR_DATA_REPLY, "BW_CLEAR_DATA_REPLY" },
638*05b00f60SXin Li { BSN_BW_ENABLE_SET_REPLY, "BW_ENABLE_SET_REPLY" },
639*05b00f60SXin Li { BSN_SET_L2_TABLE_REPLY, "SET_L2_TABLE_REPLY" },
640*05b00f60SXin Li { BSN_SET_PKTIN_SUPPRESSION_REPLY, "SET_PKTIN_SUPPRESSION_REPLY" },
641*05b00f60SXin Li { BSN_VIRTUAL_PORT_REMOVE_REPLY, "VIRTUAL_PORT_REMOVE_REPLY" },
642*05b00f60SXin Li { BSN_HYBRID_GET_REQUEST, "HYBRID_GET_REQUEST" },
643*05b00f60SXin Li { BSN_HYBRID_GET_REPLY, "HYBRID_GET_REPLY" },
644*05b00f60SXin Li { BSN_PDU_TX_REQUEST, "PDU_TX_REQUEST" },
645*05b00f60SXin Li { BSN_PDU_TX_REPLY, "PDU_TX_REPLY" },
646*05b00f60SXin Li { BSN_PDU_RX_REQUEST, "PDU_RX_REQUEST" },
647*05b00f60SXin Li { BSN_PDU_RX_REPLY, "PDU_RX_REPLY" },
648*05b00f60SXin Li { BSN_PDU_RX_TIMEOUT, "PDU_RX_TIMEOUT" },
649*05b00f60SXin Li { 0, NULL }
650*05b00f60SXin Li };
651*05b00f60SXin Li
652*05b00f60SXin Li #define BSN_ACTION_MIRROR 1
653*05b00f60SXin Li #define BSN_ACTION_SET_TUNNEL_DST 2
654*05b00f60SXin Li /* 3 */
655*05b00f60SXin Li #define BSN_ACTION_CHECKSUM 4
656*05b00f60SXin Li
657*05b00f60SXin Li static const struct tok bsn_action_subtype_str[] = {
658*05b00f60SXin Li { BSN_ACTION_MIRROR, "MIRROR" },
659*05b00f60SXin Li { BSN_ACTION_SET_TUNNEL_DST, "SET_TUNNEL_DST" },
660*05b00f60SXin Li { BSN_ACTION_CHECKSUM, "CHECKSUM" },
661*05b00f60SXin Li { 0, NULL }
662*05b00f60SXin Li };
663*05b00f60SXin Li
664*05b00f60SXin Li static const struct tok bsn_mirror_copy_stage_str[] = {
665*05b00f60SXin Li { 0, "INGRESS" },
666*05b00f60SXin Li { 1, "EGRESS" },
667*05b00f60SXin Li { 0, NULL },
668*05b00f60SXin Li };
669*05b00f60SXin Li
670*05b00f60SXin Li static const struct tok bsn_onoff_str[] = {
671*05b00f60SXin Li { 0, "OFF" },
672*05b00f60SXin Li { 1, "ON" },
673*05b00f60SXin Li { 0, NULL },
674*05b00f60SXin Li };
675*05b00f60SXin Li
676*05b00f60SXin Li static const char *
vlan_str(const uint16_t vid)677*05b00f60SXin Li vlan_str(const uint16_t vid)
678*05b00f60SXin Li {
679*05b00f60SXin Li static char buf[sizeof("65535 (bogus)")];
680*05b00f60SXin Li
681*05b00f60SXin Li if (vid == OFP_VLAN_NONE)
682*05b00f60SXin Li return "NONE";
683*05b00f60SXin Li snprintf(buf, sizeof(buf), "%u%s", vid,
684*05b00f60SXin Li (vid > 0 && vid < 0x0fff) ? "" : " (bogus)");
685*05b00f60SXin Li return buf;
686*05b00f60SXin Li }
687*05b00f60SXin Li
688*05b00f60SXin Li static const char *
pcp_str(const uint8_t pcp)689*05b00f60SXin Li pcp_str(const uint8_t pcp)
690*05b00f60SXin Li {
691*05b00f60SXin Li static char buf[sizeof("255 (bogus)")];
692*05b00f60SXin Li snprintf(buf, sizeof(buf), "%u%s", pcp,
693*05b00f60SXin Li pcp <= 7 ? "" : " (bogus)");
694*05b00f60SXin Li return buf;
695*05b00f60SXin Li }
696*05b00f60SXin Li
697*05b00f60SXin Li static void
of10_bsn_message_print(netdissect_options * ndo,const u_char * cp,u_int len)698*05b00f60SXin Li of10_bsn_message_print(netdissect_options *ndo,
699*05b00f60SXin Li const u_char *cp, u_int len)
700*05b00f60SXin Li {
701*05b00f60SXin Li uint32_t subtype;
702*05b00f60SXin Li
703*05b00f60SXin Li if (len < 4)
704*05b00f60SXin Li goto invalid;
705*05b00f60SXin Li /* subtype */
706*05b00f60SXin Li subtype = GET_BE_U_4(cp);
707*05b00f60SXin Li OF_FWD(4);
708*05b00f60SXin Li ND_PRINT("\n\t subtype %s", tok2str(bsn_subtype_str, "unknown (0x%08x)", subtype));
709*05b00f60SXin Li switch (subtype) {
710*05b00f60SXin Li case BSN_GET_IP_MASK_REQUEST:
711*05b00f60SXin Li /*
712*05b00f60SXin Li * 0 1 2 3
713*05b00f60SXin 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
714*05b00f60SXin Li * +---------------+---------------+---------------+---------------+
715*05b00f60SXin Li * | subtype |
716*05b00f60SXin Li * +---------------+---------------+---------------+---------------+
717*05b00f60SXin Li * | index | pad |
718*05b00f60SXin Li * +---------------+---------------+---------------+---------------+
719*05b00f60SXin Li * | pad |
720*05b00f60SXin Li * +---------------+---------------+---------------+---------------+
721*05b00f60SXin Li *
722*05b00f60SXin Li */
723*05b00f60SXin Li if (len != 8)
724*05b00f60SXin Li goto invalid;
725*05b00f60SXin Li /* index */
726*05b00f60SXin Li ND_PRINT(", index %u", GET_U_1(cp));
727*05b00f60SXin Li OF_FWD(1);
728*05b00f60SXin Li /* pad */
729*05b00f60SXin Li /* Always the last field, check bounds. */
730*05b00f60SXin Li ND_TCHECK_7(cp);
731*05b00f60SXin Li break;
732*05b00f60SXin Li case BSN_SET_IP_MASK:
733*05b00f60SXin Li case BSN_GET_IP_MASK_REPLY:
734*05b00f60SXin Li /*
735*05b00f60SXin Li * 0 1 2 3
736*05b00f60SXin 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
737*05b00f60SXin Li * +---------------+---------------+---------------+---------------+
738*05b00f60SXin Li * | subtype |
739*05b00f60SXin Li * +---------------+---------------+---------------+---------------+
740*05b00f60SXin Li * | index | pad |
741*05b00f60SXin Li * +---------------+---------------+---------------+---------------+
742*05b00f60SXin Li * | mask |
743*05b00f60SXin Li * +---------------+---------------+---------------+---------------+
744*05b00f60SXin Li *
745*05b00f60SXin Li */
746*05b00f60SXin Li if (len != 8)
747*05b00f60SXin Li goto invalid;
748*05b00f60SXin Li /* index */
749*05b00f60SXin Li ND_PRINT(", index %u", GET_U_1(cp));
750*05b00f60SXin Li OF_FWD(1);
751*05b00f60SXin Li /* pad */
752*05b00f60SXin Li OF_FWD(3);
753*05b00f60SXin Li /* mask */
754*05b00f60SXin Li ND_PRINT(", mask %s", GET_IPADDR_STRING(cp));
755*05b00f60SXin Li break;
756*05b00f60SXin Li case BSN_SET_MIRRORING:
757*05b00f60SXin Li case BSN_GET_MIRRORING_REQUEST:
758*05b00f60SXin Li case BSN_GET_MIRRORING_REPLY:
759*05b00f60SXin Li /*
760*05b00f60SXin Li * 0 1 2 3
761*05b00f60SXin 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
762*05b00f60SXin Li * +---------------+---------------+---------------+---------------+
763*05b00f60SXin Li * | subtype |
764*05b00f60SXin Li * +---------------+---------------+---------------+---------------+
765*05b00f60SXin Li * | report m. p. | pad |
766*05b00f60SXin Li * +---------------+---------------+---------------+---------------+
767*05b00f60SXin Li *
768*05b00f60SXin Li */
769*05b00f60SXin Li if (len != 4)
770*05b00f60SXin Li goto invalid;
771*05b00f60SXin Li /* report_mirror_ports */
772*05b00f60SXin Li ND_PRINT(", report_mirror_ports %s",
773*05b00f60SXin Li tok2str(bsn_onoff_str, "bogus (%u)", GET_U_1(cp)));
774*05b00f60SXin Li OF_FWD(1);
775*05b00f60SXin Li /* pad */
776*05b00f60SXin Li /* Always the last field, check bounds. */
777*05b00f60SXin Li ND_TCHECK_3(cp);
778*05b00f60SXin Li break;
779*05b00f60SXin Li case BSN_GET_INTERFACES_REQUEST:
780*05b00f60SXin Li case BSN_GET_L2_TABLE_REQUEST:
781*05b00f60SXin Li case BSN_BW_ENABLE_GET_REQUEST:
782*05b00f60SXin Li case BSN_BW_CLEAR_DATA_REQUEST:
783*05b00f60SXin Li case BSN_HYBRID_GET_REQUEST:
784*05b00f60SXin Li /*
785*05b00f60SXin Li * 0 1 2 3
786*05b00f60SXin 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
787*05b00f60SXin Li * +---------------+---------------+---------------+---------------+
788*05b00f60SXin Li * | subtype |
789*05b00f60SXin Li * +---------------+---------------+---------------+---------------+
790*05b00f60SXin Li *
791*05b00f60SXin Li */
792*05b00f60SXin Li if (len)
793*05b00f60SXin Li goto invalid;
794*05b00f60SXin Li break;
795*05b00f60SXin Li case BSN_VIRTUAL_PORT_REMOVE_REQUEST:
796*05b00f60SXin Li /*
797*05b00f60SXin Li * 0 1 2 3
798*05b00f60SXin 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
799*05b00f60SXin Li * +---------------+---------------+---------------+---------------+
800*05b00f60SXin Li * | subtype |
801*05b00f60SXin Li * +---------------+---------------+---------------+---------------+
802*05b00f60SXin Li * | vport_no |
803*05b00f60SXin Li * +---------------+---------------+---------------+---------------+
804*05b00f60SXin Li *
805*05b00f60SXin Li */
806*05b00f60SXin Li if (len != 4)
807*05b00f60SXin Li goto invalid;
808*05b00f60SXin Li /* vport_no */
809*05b00f60SXin Li ND_PRINT(", vport_no %u", GET_BE_U_4(cp));
810*05b00f60SXin Li break;
811*05b00f60SXin Li case BSN_SHELL_COMMAND:
812*05b00f60SXin Li /*
813*05b00f60SXin Li * 0 1 2 3
814*05b00f60SXin 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
815*05b00f60SXin Li * +---------------+---------------+---------------+---------------+
816*05b00f60SXin Li * | subtype |
817*05b00f60SXin Li * +---------------+---------------+---------------+---------------+
818*05b00f60SXin Li * | service |
819*05b00f60SXin Li * +---------------+---------------+---------------+---------------+
820*05b00f60SXin Li * | data ...
821*05b00f60SXin Li * +---------------+---------------+--------
822*05b00f60SXin Li *
823*05b00f60SXin Li */
824*05b00f60SXin Li if (len < 4)
825*05b00f60SXin Li goto invalid;
826*05b00f60SXin Li /* service */
827*05b00f60SXin Li ND_PRINT(", service %u", GET_BE_U_4(cp));
828*05b00f60SXin Li OF_FWD(4);
829*05b00f60SXin Li /* data */
830*05b00f60SXin Li ND_PRINT(", data '");
831*05b00f60SXin Li (void)nd_printn(ndo, cp, len, NULL);
832*05b00f60SXin Li ND_PRINT("'");
833*05b00f60SXin Li break;
834*05b00f60SXin Li case BSN_SHELL_OUTPUT:
835*05b00f60SXin Li /*
836*05b00f60SXin Li * 0 1 2 3
837*05b00f60SXin 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
838*05b00f60SXin Li * +---------------+---------------+---------------+---------------+
839*05b00f60SXin Li * | subtype |
840*05b00f60SXin Li * +---------------+---------------+---------------+---------------+
841*05b00f60SXin Li * | data ...
842*05b00f60SXin Li * +---------------+---------------+--------
843*05b00f60SXin Li *
844*05b00f60SXin Li */
845*05b00f60SXin Li /* already checked that len >= 4 */
846*05b00f60SXin Li /* data */
847*05b00f60SXin Li ND_PRINT(", data '");
848*05b00f60SXin Li (void)nd_printn(ndo, cp, len, NULL);
849*05b00f60SXin Li ND_PRINT("'");
850*05b00f60SXin Li break;
851*05b00f60SXin Li case BSN_SHELL_STATUS:
852*05b00f60SXin Li /*
853*05b00f60SXin Li * 0 1 2 3
854*05b00f60SXin 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
855*05b00f60SXin Li * +---------------+---------------+---------------+---------------+
856*05b00f60SXin Li * | subtype |
857*05b00f60SXin Li * +---------------+---------------+---------------+---------------+
858*05b00f60SXin Li * | status |
859*05b00f60SXin Li * +---------------+---------------+---------------+---------------+
860*05b00f60SXin Li *
861*05b00f60SXin Li */
862*05b00f60SXin Li if (len != 4)
863*05b00f60SXin Li goto invalid;
864*05b00f60SXin Li /* status */
865*05b00f60SXin Li ND_PRINT(", status 0x%08x", GET_BE_U_4(cp));
866*05b00f60SXin Li break;
867*05b00f60SXin Li default:
868*05b00f60SXin Li ND_TCHECK_LEN(cp, len);
869*05b00f60SXin Li }
870*05b00f60SXin Li return;
871*05b00f60SXin Li
872*05b00f60SXin Li invalid: /* skip the undersized data */
873*05b00f60SXin Li nd_print_invalid(ndo);
874*05b00f60SXin Li ND_TCHECK_LEN(cp, len);
875*05b00f60SXin Li }
876*05b00f60SXin Li
877*05b00f60SXin Li static void
of10_bsn_actions_print(netdissect_options * ndo,const u_char * cp,u_int len)878*05b00f60SXin Li of10_bsn_actions_print(netdissect_options *ndo,
879*05b00f60SXin Li const u_char *cp, u_int len)
880*05b00f60SXin Li {
881*05b00f60SXin Li uint32_t subtype, vlan_tag;
882*05b00f60SXin Li
883*05b00f60SXin Li if (len < 4)
884*05b00f60SXin Li goto invalid;
885*05b00f60SXin Li /* subtype */
886*05b00f60SXin Li subtype = GET_BE_U_4(cp);
887*05b00f60SXin Li OF_FWD(4);
888*05b00f60SXin Li ND_PRINT("\n\t subtype %s", tok2str(bsn_action_subtype_str, "unknown (0x%08x)", subtype));
889*05b00f60SXin Li switch (subtype) {
890*05b00f60SXin Li case BSN_ACTION_MIRROR:
891*05b00f60SXin Li /*
892*05b00f60SXin Li * 0 1 2 3
893*05b00f60SXin 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
894*05b00f60SXin Li * +---------------+---------------+---------------+---------------+
895*05b00f60SXin Li * | subtype |
896*05b00f60SXin Li * +---------------+---------------+---------------+---------------+
897*05b00f60SXin Li * | dest_port |
898*05b00f60SXin Li * +---------------+---------------+---------------+---------------+
899*05b00f60SXin Li * | vlan_tag |
900*05b00f60SXin Li * +---------------+---------------+---------------+---------------+
901*05b00f60SXin Li * | copy_stage | pad |
902*05b00f60SXin Li * +---------------+---------------+---------------+---------------+
903*05b00f60SXin Li *
904*05b00f60SXin Li */
905*05b00f60SXin Li if (len != 12)
906*05b00f60SXin Li goto invalid;
907*05b00f60SXin Li /* dest_port */
908*05b00f60SXin Li ND_PRINT(", dest_port %u", GET_BE_U_4(cp));
909*05b00f60SXin Li OF_FWD(4);
910*05b00f60SXin Li /* vlan_tag */
911*05b00f60SXin Li vlan_tag = GET_BE_U_4(cp);
912*05b00f60SXin Li OF_FWD(4);
913*05b00f60SXin Li switch (vlan_tag >> 16) {
914*05b00f60SXin Li case 0:
915*05b00f60SXin Li ND_PRINT(", vlan_tag none");
916*05b00f60SXin Li break;
917*05b00f60SXin Li case ETHERTYPE_8021Q:
918*05b00f60SXin Li ND_PRINT(", vlan_tag 802.1Q (%s)", ieee8021q_tci_string(vlan_tag & 0xffff));
919*05b00f60SXin Li break;
920*05b00f60SXin Li default:
921*05b00f60SXin Li ND_PRINT(", vlan_tag unknown (0x%04x)", vlan_tag >> 16);
922*05b00f60SXin Li }
923*05b00f60SXin Li /* copy_stage */
924*05b00f60SXin Li ND_PRINT(", copy_stage %s",
925*05b00f60SXin Li tok2str(bsn_mirror_copy_stage_str, "unknown (%u)", GET_U_1(cp)));
926*05b00f60SXin Li OF_FWD(1);
927*05b00f60SXin Li /* pad */
928*05b00f60SXin Li /* Always the last field, check bounds. */
929*05b00f60SXin Li ND_TCHECK_3(cp);
930*05b00f60SXin Li break;
931*05b00f60SXin Li default:
932*05b00f60SXin Li ND_TCHECK_LEN(cp, len);
933*05b00f60SXin Li }
934*05b00f60SXin Li return;
935*05b00f60SXin Li
936*05b00f60SXin Li invalid:
937*05b00f60SXin Li nd_print_invalid(ndo);
938*05b00f60SXin Li ND_TCHECK_LEN(cp, len);
939*05b00f60SXin Li }
940*05b00f60SXin Li
941*05b00f60SXin Li static void
of10_vendor_action_print(netdissect_options * ndo,const u_char * cp,u_int len)942*05b00f60SXin Li of10_vendor_action_print(netdissect_options *ndo,
943*05b00f60SXin Li const u_char *cp, u_int len)
944*05b00f60SXin Li {
945*05b00f60SXin Li uint32_t vendor;
946*05b00f60SXin Li void (*decoder)(netdissect_options *, const u_char *, u_int);
947*05b00f60SXin Li
948*05b00f60SXin Li if (len < 4)
949*05b00f60SXin Li goto invalid;
950*05b00f60SXin Li /* vendor */
951*05b00f60SXin Li vendor = GET_BE_U_4(cp);
952*05b00f60SXin Li OF_FWD(4);
953*05b00f60SXin Li ND_PRINT(", vendor 0x%08x (%s)", vendor, of_vendor_name(vendor));
954*05b00f60SXin Li /* data */
955*05b00f60SXin Li decoder =
956*05b00f60SXin Li vendor == OUI_BSN ? of10_bsn_actions_print :
957*05b00f60SXin Li of_data_print;
958*05b00f60SXin Li decoder(ndo, cp, len);
959*05b00f60SXin Li return;
960*05b00f60SXin Li
961*05b00f60SXin Li invalid: /* skip the undersized data */
962*05b00f60SXin Li nd_print_invalid(ndo);
963*05b00f60SXin Li ND_TCHECK_LEN(cp, len);
964*05b00f60SXin Li }
965*05b00f60SXin Li
966*05b00f60SXin Li /* [OF10] Section 5.5.4 */
967*05b00f60SXin Li static void
of10_vendor_message_print(netdissect_options * ndo,const u_char * cp,u_int len)968*05b00f60SXin Li of10_vendor_message_print(netdissect_options *ndo,
969*05b00f60SXin Li const u_char *cp, u_int len)
970*05b00f60SXin Li {
971*05b00f60SXin Li uint32_t vendor;
972*05b00f60SXin Li void (*decoder)(netdissect_options *, const u_char *, u_int);
973*05b00f60SXin Li
974*05b00f60SXin Li /* vendor */
975*05b00f60SXin Li vendor = GET_BE_U_4(cp);
976*05b00f60SXin Li OF_FWD(4);
977*05b00f60SXin Li ND_PRINT(", vendor 0x%08x (%s)", vendor, of_vendor_name(vendor));
978*05b00f60SXin Li /* data */
979*05b00f60SXin Li decoder =
980*05b00f60SXin Li vendor == OUI_BSN ? of10_bsn_message_print :
981*05b00f60SXin Li of_data_print;
982*05b00f60SXin Li decoder(ndo, cp, len);
983*05b00f60SXin Li }
984*05b00f60SXin Li
985*05b00f60SXin Li /* Vendor ID is mandatory, data is optional. */
986*05b00f60SXin Li static void
of10_vendor_data_print(netdissect_options * ndo,const u_char * cp,u_int len)987*05b00f60SXin Li of10_vendor_data_print(netdissect_options *ndo,
988*05b00f60SXin Li const u_char *cp, u_int len)
989*05b00f60SXin Li {
990*05b00f60SXin Li uint32_t vendor;
991*05b00f60SXin Li
992*05b00f60SXin Li if (len < 4)
993*05b00f60SXin Li goto invalid;
994*05b00f60SXin Li /* vendor */
995*05b00f60SXin Li vendor = GET_BE_U_4(cp);
996*05b00f60SXin Li OF_FWD(4);
997*05b00f60SXin Li ND_PRINT(", vendor 0x%08x (%s)", vendor, of_vendor_name(vendor));
998*05b00f60SXin Li /* data */
999*05b00f60SXin Li of_data_print(ndo, cp, len);
1000*05b00f60SXin Li return;
1001*05b00f60SXin Li
1002*05b00f60SXin Li invalid: /* skip the undersized data */
1003*05b00f60SXin Li nd_print_invalid(ndo);
1004*05b00f60SXin Li ND_TCHECK_LEN(cp, len);
1005*05b00f60SXin Li }
1006*05b00f60SXin Li
1007*05b00f60SXin Li static void
of10_packet_data_print(netdissect_options * ndo,const u_char * cp,const u_int len)1008*05b00f60SXin Li of10_packet_data_print(netdissect_options *ndo,
1009*05b00f60SXin Li const u_char *cp, const u_int len)
1010*05b00f60SXin Li {
1011*05b00f60SXin Li if (len == 0)
1012*05b00f60SXin Li return;
1013*05b00f60SXin Li /* data */
1014*05b00f60SXin Li ND_PRINT("\n\t data (%u octets)", len);
1015*05b00f60SXin Li if (ndo->ndo_vflag < 3) {
1016*05b00f60SXin Li ND_TCHECK_LEN(cp, len);
1017*05b00f60SXin Li return;
1018*05b00f60SXin Li }
1019*05b00f60SXin Li ndo->ndo_vflag -= 3;
1020*05b00f60SXin Li ND_PRINT(", frame decoding below\n");
1021*05b00f60SXin Li /*
1022*05b00f60SXin Li * The encapsulated Ethernet frame is not necessarily the last
1023*05b00f60SXin Li * data of this packet (i.e. there may be more OpenFlow messages
1024*05b00f60SXin Li * after the current OFPT_PACKET_IN/OFPT_PACKET_OUT message, in
1025*05b00f60SXin Li * which case the current (outer) packet's snapshot end is not
1026*05b00f60SXin Li * what ether_print() needs to decode an Ethernet frame nested in
1027*05b00f60SXin Li * the middle of a TCP payload.
1028*05b00f60SXin Li */
1029*05b00f60SXin Li const u_char *snapend_save = ndo->ndo_snapend;
1030*05b00f60SXin Li ndo->ndo_snapend = ND_MIN(cp + len, ndo->ndo_snapend);
1031*05b00f60SXin Li ether_print(ndo, cp, len, ND_BYTES_AVAILABLE_AFTER(cp), NULL, NULL);
1032*05b00f60SXin Li ndo->ndo_snapend = snapend_save;
1033*05b00f60SXin Li ndo->ndo_vflag += 3;
1034*05b00f60SXin Li }
1035*05b00f60SXin Li
1036*05b00f60SXin Li /* [OF10] Section 5.2.1 */
1037*05b00f60SXin Li static void
of10_phy_port_print(netdissect_options * ndo,const u_char * cp)1038*05b00f60SXin Li of10_phy_port_print(netdissect_options *ndo,
1039*05b00f60SXin Li const u_char *cp)
1040*05b00f60SXin Li {
1041*05b00f60SXin Li uint32_t state;
1042*05b00f60SXin Li
1043*05b00f60SXin Li /* port_no */
1044*05b00f60SXin Li ND_PRINT("\n\t port_no %s",
1045*05b00f60SXin Li tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1046*05b00f60SXin Li cp += 2;
1047*05b00f60SXin Li /* hw_addr */
1048*05b00f60SXin Li ND_PRINT(", hw_addr %s", GET_ETHERADDR_STRING(cp));
1049*05b00f60SXin Li cp += MAC_ADDR_LEN;
1050*05b00f60SXin Li /* name */
1051*05b00f60SXin Li ND_PRINT(", name '");
1052*05b00f60SXin Li nd_printjnp(ndo, cp, OFP_MAX_PORT_NAME_LEN);
1053*05b00f60SXin Li ND_PRINT("'");
1054*05b00f60SXin Li cp += OFP_MAX_PORT_NAME_LEN;
1055*05b00f60SXin Li
1056*05b00f60SXin Li if (ndo->ndo_vflag < 2) {
1057*05b00f60SXin Li ND_TCHECK_LEN(cp, 24);
1058*05b00f60SXin Li return;
1059*05b00f60SXin Li }
1060*05b00f60SXin Li /* config */
1061*05b00f60SXin Li ND_PRINT("\n\t config 0x%08x", GET_BE_U_4(cp));
1062*05b00f60SXin Li of_bitmap_print(ndo, ofppc_bm, GET_BE_U_4(cp), OFPPC_U);
1063*05b00f60SXin Li cp += 4;
1064*05b00f60SXin Li /* state */
1065*05b00f60SXin Li state = GET_BE_U_4(cp);
1066*05b00f60SXin Li /*
1067*05b00f60SXin Li * Decode the code point and the single bit separately, but
1068*05b00f60SXin Li * format the result as a single sequence of comma-separated
1069*05b00f60SXin Li * strings (see the comments at the OFPPS_ props).
1070*05b00f60SXin Li */
1071*05b00f60SXin Li ND_PRINT("\n\t state 0x%08x (%s%s)%s", state,
1072*05b00f60SXin Li tok2str(ofpps_stp_str, "", state & OFPPS_STP_MASK),
1073*05b00f60SXin Li state & OFPPS_LINK_DOWN ? ", LINK_DOWN" : "",
1074*05b00f60SXin Li state & OFPPS_U ? " (bogus)" : "");
1075*05b00f60SXin Li cp += 4;
1076*05b00f60SXin Li /* curr */
1077*05b00f60SXin Li ND_PRINT("\n\t curr 0x%08x", GET_BE_U_4(cp));
1078*05b00f60SXin Li of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U);
1079*05b00f60SXin Li cp += 4;
1080*05b00f60SXin Li /* advertised */
1081*05b00f60SXin Li ND_PRINT("\n\t advertised 0x%08x", GET_BE_U_4(cp));
1082*05b00f60SXin Li of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U);
1083*05b00f60SXin Li cp += 4;
1084*05b00f60SXin Li /* supported */
1085*05b00f60SXin Li ND_PRINT("\n\t supported 0x%08x", GET_BE_U_4(cp));
1086*05b00f60SXin Li of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U);
1087*05b00f60SXin Li cp += 4;
1088*05b00f60SXin Li /* peer */
1089*05b00f60SXin Li ND_PRINT("\n\t peer 0x%08x", GET_BE_U_4(cp));
1090*05b00f60SXin Li of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U);
1091*05b00f60SXin Li }
1092*05b00f60SXin Li
1093*05b00f60SXin Li /* [OF10] Section 5.2.2 */
1094*05b00f60SXin Li static void
of10_queue_props_print(netdissect_options * ndo,const u_char * cp,u_int len)1095*05b00f60SXin Li of10_queue_props_print(netdissect_options *ndo,
1096*05b00f60SXin Li const u_char *cp, u_int len)
1097*05b00f60SXin Li {
1098*05b00f60SXin Li while (len) {
1099*05b00f60SXin Li uint16_t property, plen;
1100*05b00f60SXin Li u_char plen_bogus = 0, skip = 0;
1101*05b00f60SXin Li
1102*05b00f60SXin Li if (len < OF_QUEUE_PROP_MINLEN)
1103*05b00f60SXin Li goto invalid;
1104*05b00f60SXin Li /* property */
1105*05b00f60SXin Li property = GET_BE_U_2(cp);
1106*05b00f60SXin Li OF_FWD(2);
1107*05b00f60SXin Li ND_PRINT("\n\t property %s", tok2str(ofpqt_str, "invalid (0x%04x)", property));
1108*05b00f60SXin Li /* len */
1109*05b00f60SXin Li plen = GET_BE_U_2(cp);
1110*05b00f60SXin Li OF_FWD(2);
1111*05b00f60SXin Li ND_PRINT(", len %u", plen);
1112*05b00f60SXin Li if (plen < OF_QUEUE_PROP_MINLEN || plen > len + 4)
1113*05b00f60SXin Li goto invalid;
1114*05b00f60SXin Li /* pad */
1115*05b00f60SXin Li /* Sometimes the last field, check bounds. */
1116*05b00f60SXin Li OF_CHK_FWD(4);
1117*05b00f60SXin Li /* property-specific constraints and decoding */
1118*05b00f60SXin Li switch (property) {
1119*05b00f60SXin Li case OFPQT_NONE:
1120*05b00f60SXin Li plen_bogus = plen != OF_QUEUE_PROP_MINLEN;
1121*05b00f60SXin Li break;
1122*05b00f60SXin Li case OFPQT_MIN_RATE:
1123*05b00f60SXin Li plen_bogus = plen != OF_QUEUE_PROP_MIN_RATE_FIXLEN;
1124*05b00f60SXin Li break;
1125*05b00f60SXin Li default:
1126*05b00f60SXin Li skip = 1;
1127*05b00f60SXin Li }
1128*05b00f60SXin Li if (plen_bogus) {
1129*05b00f60SXin Li ND_PRINT(" (bogus)");
1130*05b00f60SXin Li skip = 1;
1131*05b00f60SXin Li }
1132*05b00f60SXin Li if (skip) {
1133*05b00f60SXin Li /*
1134*05b00f60SXin Li * plen >= OF_QUEUE_PROP_MINLEN
1135*05b00f60SXin Li * cp is OF_QUEUE_PROP_MINLEN bytes in
1136*05b00f60SXin Li */
1137*05b00f60SXin Li OF_CHK_FWD(plen - OF_QUEUE_PROP_MINLEN);
1138*05b00f60SXin Li continue;
1139*05b00f60SXin Li }
1140*05b00f60SXin Li if (property == OFPQT_MIN_RATE) { /* the only case of property decoding */
1141*05b00f60SXin Li /* rate */
1142*05b00f60SXin Li uint16_t rate = GET_BE_U_2(cp);
1143*05b00f60SXin Li OF_FWD(2);
1144*05b00f60SXin Li if (rate > 1000)
1145*05b00f60SXin Li ND_PRINT(", rate disabled");
1146*05b00f60SXin Li else
1147*05b00f60SXin Li ND_PRINT(", rate %u.%u%%", rate / 10, rate % 10);
1148*05b00f60SXin Li /* pad */
1149*05b00f60SXin Li /* Sometimes the last field, check bounds. */
1150*05b00f60SXin Li OF_CHK_FWD(6);
1151*05b00f60SXin Li }
1152*05b00f60SXin Li } /* while */
1153*05b00f60SXin Li return;
1154*05b00f60SXin Li
1155*05b00f60SXin Li invalid: /* skip the rest of queue properties */
1156*05b00f60SXin Li nd_print_invalid(ndo);
1157*05b00f60SXin Li ND_TCHECK_LEN(cp, len);
1158*05b00f60SXin Li }
1159*05b00f60SXin Li
1160*05b00f60SXin Li /* ibid */
1161*05b00f60SXin Li static void
of10_queues_print(netdissect_options * ndo,const u_char * cp,u_int len)1162*05b00f60SXin Li of10_queues_print(netdissect_options *ndo,
1163*05b00f60SXin Li const u_char *cp, u_int len)
1164*05b00f60SXin Li {
1165*05b00f60SXin Li while (len) {
1166*05b00f60SXin Li uint16_t desclen;
1167*05b00f60SXin Li
1168*05b00f60SXin Li if (len < OF_PACKET_QUEUE_MINLEN)
1169*05b00f60SXin Li goto invalid;
1170*05b00f60SXin Li /* queue_id */
1171*05b00f60SXin Li ND_PRINT("\n\t queue_id %u", GET_BE_U_4(cp));
1172*05b00f60SXin Li OF_FWD(4);
1173*05b00f60SXin Li /* len */
1174*05b00f60SXin Li desclen = GET_BE_U_2(cp);
1175*05b00f60SXin Li OF_FWD(2);
1176*05b00f60SXin Li ND_PRINT(", len %u", desclen);
1177*05b00f60SXin Li if (desclen < OF_PACKET_QUEUE_MINLEN || desclen > len + 6)
1178*05b00f60SXin Li goto invalid;
1179*05b00f60SXin Li /* pad */
1180*05b00f60SXin Li /* Sometimes the last field, check bounds. */
1181*05b00f60SXin Li OF_CHK_FWD(2);
1182*05b00f60SXin Li /* properties */
1183*05b00f60SXin Li if (ndo->ndo_vflag >= 2)
1184*05b00f60SXin Li of10_queue_props_print(ndo, cp, desclen - OF_PACKET_QUEUE_MINLEN);
1185*05b00f60SXin Li else
1186*05b00f60SXin Li ND_TCHECK_LEN(cp, desclen - OF_PACKET_QUEUE_MINLEN);
1187*05b00f60SXin Li OF_FWD(desclen - OF_PACKET_QUEUE_MINLEN);
1188*05b00f60SXin Li } /* while */
1189*05b00f60SXin Li return;
1190*05b00f60SXin Li
1191*05b00f60SXin Li invalid: /* skip the rest of queues */
1192*05b00f60SXin Li nd_print_invalid(ndo);
1193*05b00f60SXin Li ND_TCHECK_LEN(cp, len);
1194*05b00f60SXin Li }
1195*05b00f60SXin Li
1196*05b00f60SXin Li /* [OF10] Section 5.2.3 */
1197*05b00f60SXin Li static void
of10_match_print(netdissect_options * ndo,const char * pfx,const u_char * cp)1198*05b00f60SXin Li of10_match_print(netdissect_options *ndo,
1199*05b00f60SXin Li const char *pfx, const u_char *cp)
1200*05b00f60SXin Li {
1201*05b00f60SXin Li uint32_t wildcards;
1202*05b00f60SXin Li uint16_t dl_type;
1203*05b00f60SXin Li uint8_t nw_proto;
1204*05b00f60SXin Li u_int nw_bits;
1205*05b00f60SXin Li const char *field_name;
1206*05b00f60SXin Li
1207*05b00f60SXin Li /* wildcards */
1208*05b00f60SXin Li wildcards = GET_BE_U_4(cp);
1209*05b00f60SXin Li if (wildcards & OFPFW_U)
1210*05b00f60SXin Li ND_PRINT("%swildcards 0x%08x (bogus)", pfx, wildcards);
1211*05b00f60SXin Li cp += 4;
1212*05b00f60SXin Li /* in_port */
1213*05b00f60SXin Li if (! (wildcards & OFPFW_IN_PORT))
1214*05b00f60SXin Li ND_PRINT("%smatch in_port %s", pfx,
1215*05b00f60SXin Li tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1216*05b00f60SXin Li cp += 2;
1217*05b00f60SXin Li /* dl_src */
1218*05b00f60SXin Li if (! (wildcards & OFPFW_DL_SRC))
1219*05b00f60SXin Li ND_PRINT("%smatch dl_src %s", pfx, GET_ETHERADDR_STRING(cp));
1220*05b00f60SXin Li cp += MAC_ADDR_LEN;
1221*05b00f60SXin Li /* dl_dst */
1222*05b00f60SXin Li if (! (wildcards & OFPFW_DL_DST))
1223*05b00f60SXin Li ND_PRINT("%smatch dl_dst %s", pfx, GET_ETHERADDR_STRING(cp));
1224*05b00f60SXin Li cp += MAC_ADDR_LEN;
1225*05b00f60SXin Li /* dl_vlan */
1226*05b00f60SXin Li if (! (wildcards & OFPFW_DL_VLAN))
1227*05b00f60SXin Li ND_PRINT("%smatch dl_vlan %s", pfx, vlan_str(GET_BE_U_2(cp)));
1228*05b00f60SXin Li cp += 2;
1229*05b00f60SXin Li /* dl_vlan_pcp */
1230*05b00f60SXin Li if (! (wildcards & OFPFW_DL_VLAN_PCP))
1231*05b00f60SXin Li ND_PRINT("%smatch dl_vlan_pcp %s", pfx, pcp_str(GET_U_1(cp)));
1232*05b00f60SXin Li cp += 1;
1233*05b00f60SXin Li /* pad1 */
1234*05b00f60SXin Li cp += 1;
1235*05b00f60SXin Li /* dl_type */
1236*05b00f60SXin Li dl_type = GET_BE_U_2(cp);
1237*05b00f60SXin Li cp += 2;
1238*05b00f60SXin Li if (! (wildcards & OFPFW_DL_TYPE))
1239*05b00f60SXin Li ND_PRINT("%smatch dl_type 0x%04x", pfx, dl_type);
1240*05b00f60SXin Li /* nw_tos */
1241*05b00f60SXin Li if (! (wildcards & OFPFW_NW_TOS))
1242*05b00f60SXin Li ND_PRINT("%smatch nw_tos 0x%02x", pfx, GET_U_1(cp));
1243*05b00f60SXin Li cp += 1;
1244*05b00f60SXin Li /* nw_proto */
1245*05b00f60SXin Li nw_proto = GET_U_1(cp);
1246*05b00f60SXin Li cp += 1;
1247*05b00f60SXin Li if (! (wildcards & OFPFW_NW_PROTO)) {
1248*05b00f60SXin Li field_name = ! (wildcards & OFPFW_DL_TYPE) && dl_type == ETHERTYPE_ARP
1249*05b00f60SXin Li ? "arp_opcode" : "nw_proto";
1250*05b00f60SXin Li ND_PRINT("%smatch %s %u", pfx, field_name, nw_proto);
1251*05b00f60SXin Li }
1252*05b00f60SXin Li /* pad2 */
1253*05b00f60SXin Li cp += 2;
1254*05b00f60SXin Li /* nw_src */
1255*05b00f60SXin Li nw_bits = (wildcards & OFPFW_NW_SRC_MASK) >> OFPFW_NW_SRC_SHIFT;
1256*05b00f60SXin Li if (nw_bits < 32)
1257*05b00f60SXin Li ND_PRINT("%smatch nw_src %s/%u", pfx, GET_IPADDR_STRING(cp), 32 - nw_bits);
1258*05b00f60SXin Li cp += 4;
1259*05b00f60SXin Li /* nw_dst */
1260*05b00f60SXin Li nw_bits = (wildcards & OFPFW_NW_DST_MASK) >> OFPFW_NW_DST_SHIFT;
1261*05b00f60SXin Li if (nw_bits < 32)
1262*05b00f60SXin Li ND_PRINT("%smatch nw_dst %s/%u", pfx, GET_IPADDR_STRING(cp), 32 - nw_bits);
1263*05b00f60SXin Li cp += 4;
1264*05b00f60SXin Li /* tp_src */
1265*05b00f60SXin Li if (! (wildcards & OFPFW_TP_SRC)) {
1266*05b00f60SXin Li field_name = ! (wildcards & OFPFW_DL_TYPE) && dl_type == ETHERTYPE_IP
1267*05b00f60SXin Li && ! (wildcards & OFPFW_NW_PROTO) && nw_proto == IPPROTO_ICMP
1268*05b00f60SXin Li ? "icmp_type" : "tp_src";
1269*05b00f60SXin Li ND_PRINT("%smatch %s %u", pfx, field_name, GET_BE_U_2(cp));
1270*05b00f60SXin Li }
1271*05b00f60SXin Li cp += 2;
1272*05b00f60SXin Li /* tp_dst */
1273*05b00f60SXin Li /* The last unconditional check was at nw_proto, so have an "else" here. */
1274*05b00f60SXin Li if (! (wildcards & OFPFW_TP_DST)) {
1275*05b00f60SXin Li field_name = ! (wildcards & OFPFW_DL_TYPE) && dl_type == ETHERTYPE_IP
1276*05b00f60SXin Li && ! (wildcards & OFPFW_NW_PROTO) && nw_proto == IPPROTO_ICMP
1277*05b00f60SXin Li ? "icmp_code" : "tp_dst";
1278*05b00f60SXin Li ND_PRINT("%smatch %s %u", pfx, field_name, GET_BE_U_2(cp));
1279*05b00f60SXin Li }
1280*05b00f60SXin Li else
1281*05b00f60SXin Li ND_TCHECK_2(cp);
1282*05b00f60SXin Li }
1283*05b00f60SXin Li
1284*05b00f60SXin Li /* [OF10] Section 5.2.4 */
1285*05b00f60SXin Li static void
of10_actions_print(netdissect_options * ndo,const char * pfx,const u_char * cp,u_int len)1286*05b00f60SXin Li of10_actions_print(netdissect_options *ndo,
1287*05b00f60SXin Li const char *pfx, const u_char *cp, u_int len)
1288*05b00f60SXin Li {
1289*05b00f60SXin Li while (len) {
1290*05b00f60SXin Li uint16_t type, alen, output_port;
1291*05b00f60SXin Li u_char alen_bogus = 0, skip = 0;
1292*05b00f60SXin Li
1293*05b00f60SXin Li if (len < OF_ACTION_MINLEN)
1294*05b00f60SXin Li goto invalid;
1295*05b00f60SXin Li /* type */
1296*05b00f60SXin Li type = GET_BE_U_2(cp);
1297*05b00f60SXin Li OF_FWD(2);
1298*05b00f60SXin Li ND_PRINT("%saction type %s", pfx, tok2str(ofpat_str, "invalid (0x%04x)", type));
1299*05b00f60SXin Li /* length */
1300*05b00f60SXin Li alen = GET_BE_U_2(cp);
1301*05b00f60SXin Li OF_FWD(2);
1302*05b00f60SXin Li ND_PRINT(", len %u", alen);
1303*05b00f60SXin Li /*
1304*05b00f60SXin Li * The 4-byte "pad" in the specification is not a field of the
1305*05b00f60SXin Li * action header, but a placeholder to illustrate the 64-bit
1306*05b00f60SXin Li * alignment requirement. Action type specific case blocks
1307*05b00f60SXin Li * below fetch these 4 bytes.
1308*05b00f60SXin Li */
1309*05b00f60SXin Li
1310*05b00f60SXin Li /* On action size underrun/overrun skip the rest of the action list. */
1311*05b00f60SXin Li if (alen < OF_ACTION_MINLEN || alen > len + 4)
1312*05b00f60SXin Li goto invalid;
1313*05b00f60SXin Li /*
1314*05b00f60SXin Li * After validating the basic length constraint it will be safe
1315*05b00f60SXin Li * to skip the current action if the action size is not valid
1316*05b00f60SXin Li * for the type or the type is invalid.
1317*05b00f60SXin Li */
1318*05b00f60SXin Li switch (type) {
1319*05b00f60SXin Li case OFPAT_OUTPUT:
1320*05b00f60SXin Li case OFPAT_SET_VLAN_VID:
1321*05b00f60SXin Li case OFPAT_SET_VLAN_PCP:
1322*05b00f60SXin Li case OFPAT_STRIP_VLAN:
1323*05b00f60SXin Li case OFPAT_SET_NW_SRC:
1324*05b00f60SXin Li case OFPAT_SET_NW_DST:
1325*05b00f60SXin Li case OFPAT_SET_NW_TOS:
1326*05b00f60SXin Li case OFPAT_SET_TP_SRC:
1327*05b00f60SXin Li case OFPAT_SET_TP_DST:
1328*05b00f60SXin Li alen_bogus = alen != 8;
1329*05b00f60SXin Li break;
1330*05b00f60SXin Li case OFPAT_SET_DL_SRC:
1331*05b00f60SXin Li case OFPAT_SET_DL_DST:
1332*05b00f60SXin Li case OFPAT_ENQUEUE:
1333*05b00f60SXin Li alen_bogus = alen != 16;
1334*05b00f60SXin Li break;
1335*05b00f60SXin Li case OFPAT_VENDOR:
1336*05b00f60SXin Li alen_bogus = alen % 8 != 0; /* already >= 8 so far */
1337*05b00f60SXin Li break;
1338*05b00f60SXin Li default:
1339*05b00f60SXin Li skip = 1;
1340*05b00f60SXin Li }
1341*05b00f60SXin Li if (alen_bogus) {
1342*05b00f60SXin Li ND_PRINT(" (bogus)");
1343*05b00f60SXin Li skip = 1;
1344*05b00f60SXin Li }
1345*05b00f60SXin Li if (skip) {
1346*05b00f60SXin Li /*
1347*05b00f60SXin Li * alen >= OF_ACTION_MINLEN
1348*05b00f60SXin Li * cp is 4 bytes in
1349*05b00f60SXin Li */
1350*05b00f60SXin Li OF_CHK_FWD(alen - 4);
1351*05b00f60SXin Li continue;
1352*05b00f60SXin Li }
1353*05b00f60SXin Li /* OK to decode the rest of the action structure */
1354*05b00f60SXin Li switch (type) {
1355*05b00f60SXin Li case OFPAT_OUTPUT:
1356*05b00f60SXin Li /* port */
1357*05b00f60SXin Li output_port = GET_BE_U_2(cp);
1358*05b00f60SXin Li OF_FWD(2);
1359*05b00f60SXin Li ND_PRINT(", port %s", tok2str(ofpp_str, "%u", output_port));
1360*05b00f60SXin Li /* max_len */
1361*05b00f60SXin Li if (output_port == OFPP_CONTROLLER)
1362*05b00f60SXin Li ND_PRINT(", max_len %u", GET_BE_U_2(cp));
1363*05b00f60SXin Li else
1364*05b00f60SXin Li ND_TCHECK_2(cp);
1365*05b00f60SXin Li OF_FWD(2);
1366*05b00f60SXin Li break;
1367*05b00f60SXin Li case OFPAT_SET_VLAN_VID:
1368*05b00f60SXin Li /* vlan_vid */
1369*05b00f60SXin Li ND_PRINT(", vlan_vid %s", vlan_str(GET_BE_U_2(cp)));
1370*05b00f60SXin Li OF_FWD(2);
1371*05b00f60SXin Li /* pad */
1372*05b00f60SXin Li /* Sometimes the last field, check bounds. */
1373*05b00f60SXin Li OF_CHK_FWD(2);
1374*05b00f60SXin Li break;
1375*05b00f60SXin Li case OFPAT_SET_VLAN_PCP:
1376*05b00f60SXin Li /* vlan_pcp */
1377*05b00f60SXin Li ND_PRINT(", vlan_pcp %s", pcp_str(GET_U_1(cp)));
1378*05b00f60SXin Li OF_FWD(1);
1379*05b00f60SXin Li /* pad */
1380*05b00f60SXin Li /* Sometimes the last field, check bounds. */
1381*05b00f60SXin Li OF_CHK_FWD(3);
1382*05b00f60SXin Li break;
1383*05b00f60SXin Li case OFPAT_SET_DL_SRC:
1384*05b00f60SXin Li case OFPAT_SET_DL_DST:
1385*05b00f60SXin Li /* dl_addr */
1386*05b00f60SXin Li ND_PRINT(", dl_addr %s", GET_ETHERADDR_STRING(cp));
1387*05b00f60SXin Li OF_FWD(MAC_ADDR_LEN);
1388*05b00f60SXin Li /* pad */
1389*05b00f60SXin Li /* Sometimes the last field, check bounds. */
1390*05b00f60SXin Li OF_CHK_FWD(6);
1391*05b00f60SXin Li break;
1392*05b00f60SXin Li case OFPAT_SET_NW_SRC:
1393*05b00f60SXin Li case OFPAT_SET_NW_DST:
1394*05b00f60SXin Li /* nw_addr */
1395*05b00f60SXin Li ND_PRINT(", nw_addr %s", GET_IPADDR_STRING(cp));
1396*05b00f60SXin Li OF_FWD(4);
1397*05b00f60SXin Li break;
1398*05b00f60SXin Li case OFPAT_SET_NW_TOS:
1399*05b00f60SXin Li /* nw_tos */
1400*05b00f60SXin Li ND_PRINT(", nw_tos 0x%02x", GET_U_1(cp));
1401*05b00f60SXin Li OF_FWD(1);
1402*05b00f60SXin Li /* pad */
1403*05b00f60SXin Li /* Sometimes the last field, check bounds. */
1404*05b00f60SXin Li OF_CHK_FWD(3);
1405*05b00f60SXin Li break;
1406*05b00f60SXin Li case OFPAT_SET_TP_SRC:
1407*05b00f60SXin Li case OFPAT_SET_TP_DST:
1408*05b00f60SXin Li /* nw_tos */
1409*05b00f60SXin Li ND_PRINT(", tp_port %u", GET_BE_U_2(cp));
1410*05b00f60SXin Li OF_FWD(2);
1411*05b00f60SXin Li /* pad */
1412*05b00f60SXin Li /* Sometimes the last field, check bounds. */
1413*05b00f60SXin Li OF_CHK_FWD(2);
1414*05b00f60SXin Li break;
1415*05b00f60SXin Li case OFPAT_ENQUEUE:
1416*05b00f60SXin Li /* port */
1417*05b00f60SXin Li ND_PRINT(", port %s",
1418*05b00f60SXin Li tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1419*05b00f60SXin Li OF_FWD(2);
1420*05b00f60SXin Li /* pad */
1421*05b00f60SXin Li OF_FWD(6);
1422*05b00f60SXin Li /* queue_id */
1423*05b00f60SXin Li ND_PRINT(", queue_id %s",
1424*05b00f60SXin Li tok2str(ofpq_str, "%u", GET_BE_U_4(cp)));
1425*05b00f60SXin Li OF_FWD(4);
1426*05b00f60SXin Li break;
1427*05b00f60SXin Li case OFPAT_VENDOR:
1428*05b00f60SXin Li of10_vendor_action_print(ndo, cp, alen - 4);
1429*05b00f60SXin Li OF_FWD(alen - 4);
1430*05b00f60SXin Li break;
1431*05b00f60SXin Li case OFPAT_STRIP_VLAN:
1432*05b00f60SXin Li /* pad */
1433*05b00f60SXin Li /* Sometimes the last field, check bounds. */
1434*05b00f60SXin Li OF_CHK_FWD(4);
1435*05b00f60SXin Li break;
1436*05b00f60SXin Li } /* switch */
1437*05b00f60SXin Li } /* while */
1438*05b00f60SXin Li return;
1439*05b00f60SXin Li
1440*05b00f60SXin Li invalid: /* skip the rest of actions */
1441*05b00f60SXin Li nd_print_invalid(ndo);
1442*05b00f60SXin Li ND_TCHECK_LEN(cp, len);
1443*05b00f60SXin Li }
1444*05b00f60SXin Li
1445*05b00f60SXin Li /* [OF10] Section 5.3.1 */
1446*05b00f60SXin Li static void
of10_features_reply_print(netdissect_options * ndo,const u_char * cp,u_int len)1447*05b00f60SXin Li of10_features_reply_print(netdissect_options *ndo,
1448*05b00f60SXin Li const u_char *cp, u_int len)
1449*05b00f60SXin Li {
1450*05b00f60SXin Li /* datapath_id */
1451*05b00f60SXin Li ND_PRINT("\n\t dpid 0x%016" PRIx64, GET_BE_U_8(cp));
1452*05b00f60SXin Li OF_FWD(8);
1453*05b00f60SXin Li /* n_buffers */
1454*05b00f60SXin Li ND_PRINT(", n_buffers %u", GET_BE_U_4(cp));
1455*05b00f60SXin Li OF_FWD(4);
1456*05b00f60SXin Li /* n_tables */
1457*05b00f60SXin Li ND_PRINT(", n_tables %u", GET_U_1(cp));
1458*05b00f60SXin Li OF_FWD(1);
1459*05b00f60SXin Li /* pad */
1460*05b00f60SXin Li OF_FWD(3);
1461*05b00f60SXin Li /* capabilities */
1462*05b00f60SXin Li ND_PRINT("\n\t capabilities 0x%08x", GET_BE_U_4(cp));
1463*05b00f60SXin Li of_bitmap_print(ndo, ofp_capabilities_bm, GET_BE_U_4(cp), OFPCAP_U);
1464*05b00f60SXin Li OF_FWD(4);
1465*05b00f60SXin Li /* actions */
1466*05b00f60SXin Li ND_PRINT("\n\t actions 0x%08x", GET_BE_U_4(cp));
1467*05b00f60SXin Li of_bitmap_print(ndo, ofpat_bm, GET_BE_U_4(cp), OFPAT_U);
1468*05b00f60SXin Li OF_FWD(4);
1469*05b00f60SXin Li /* ports */
1470*05b00f60SXin Li while (len) {
1471*05b00f60SXin Li if (len < OF_PHY_PORT_FIXLEN)
1472*05b00f60SXin Li goto invalid;
1473*05b00f60SXin Li of10_phy_port_print(ndo, cp);
1474*05b00f60SXin Li OF_FWD(OF_PHY_PORT_FIXLEN);
1475*05b00f60SXin Li }
1476*05b00f60SXin Li return;
1477*05b00f60SXin Li
1478*05b00f60SXin Li invalid: /* skip the undersized trailing data */
1479*05b00f60SXin Li nd_print_invalid(ndo);
1480*05b00f60SXin Li ND_TCHECK_LEN(cp, len);
1481*05b00f60SXin Li }
1482*05b00f60SXin Li
1483*05b00f60SXin Li /* [OF10] Section 5.3.2 */
1484*05b00f60SXin Li static void
of10_switch_config_msg_print(netdissect_options * ndo,const u_char * cp,u_int len _U_)1485*05b00f60SXin Li of10_switch_config_msg_print(netdissect_options *ndo,
1486*05b00f60SXin Li const u_char *cp, u_int len _U_)
1487*05b00f60SXin Li {
1488*05b00f60SXin Li /* flags */
1489*05b00f60SXin Li ND_PRINT("\n\t flags %s",
1490*05b00f60SXin Li tok2str(ofp_config_str, "invalid (0x%04x)", GET_BE_U_2(cp)));
1491*05b00f60SXin Li cp += 2;
1492*05b00f60SXin Li /* miss_send_len */
1493*05b00f60SXin Li ND_PRINT(", miss_send_len %u", GET_BE_U_2(cp));
1494*05b00f60SXin Li }
1495*05b00f60SXin Li
1496*05b00f60SXin Li /* [OF10] Section 5.3.3 */
1497*05b00f60SXin Li static void
of10_flow_mod_print(netdissect_options * ndo,const u_char * cp,u_int len)1498*05b00f60SXin Li of10_flow_mod_print(netdissect_options *ndo,
1499*05b00f60SXin Li const u_char *cp, u_int len)
1500*05b00f60SXin Li {
1501*05b00f60SXin Li uint16_t command;
1502*05b00f60SXin Li
1503*05b00f60SXin Li /* match */
1504*05b00f60SXin Li of10_match_print(ndo, "\n\t ", cp);
1505*05b00f60SXin Li OF_FWD(OF_MATCH_FIXLEN);
1506*05b00f60SXin Li /* cookie */
1507*05b00f60SXin Li ND_PRINT("\n\t cookie 0x%016" PRIx64, GET_BE_U_8(cp));
1508*05b00f60SXin Li OF_FWD(8);
1509*05b00f60SXin Li /* command */
1510*05b00f60SXin Li command = GET_BE_U_2(cp);
1511*05b00f60SXin Li ND_PRINT(", command %s", tok2str(ofpfc_str, "invalid (0x%04x)", command));
1512*05b00f60SXin Li OF_FWD(2);
1513*05b00f60SXin Li /* idle_timeout */
1514*05b00f60SXin Li if (GET_BE_U_2(cp))
1515*05b00f60SXin Li ND_PRINT(", idle_timeout %u", GET_BE_U_2(cp));
1516*05b00f60SXin Li OF_FWD(2);
1517*05b00f60SXin Li /* hard_timeout */
1518*05b00f60SXin Li if (GET_BE_U_2(cp))
1519*05b00f60SXin Li ND_PRINT(", hard_timeout %u", GET_BE_U_2(cp));
1520*05b00f60SXin Li OF_FWD(2);
1521*05b00f60SXin Li /* priority */
1522*05b00f60SXin Li if (GET_BE_U_2(cp))
1523*05b00f60SXin Li ND_PRINT(", priority %u", GET_BE_U_2(cp));
1524*05b00f60SXin Li OF_FWD(2);
1525*05b00f60SXin Li /* buffer_id */
1526*05b00f60SXin Li if (command == OFPFC_ADD || command == OFPFC_MODIFY ||
1527*05b00f60SXin Li command == OFPFC_MODIFY_STRICT)
1528*05b00f60SXin Li ND_PRINT(", buffer_id %s",
1529*05b00f60SXin Li tok2str(bufferid_str, "0x%08x", GET_BE_U_4(cp)));
1530*05b00f60SXin Li OF_FWD(4);
1531*05b00f60SXin Li /* out_port */
1532*05b00f60SXin Li if (command == OFPFC_DELETE || command == OFPFC_DELETE_STRICT)
1533*05b00f60SXin Li ND_PRINT(", out_port %s",
1534*05b00f60SXin Li tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1535*05b00f60SXin Li OF_FWD(2);
1536*05b00f60SXin Li /* flags */
1537*05b00f60SXin Li ND_PRINT(", flags 0x%04x", GET_BE_U_2(cp));
1538*05b00f60SXin Li of_bitmap_print(ndo, ofpff_bm, GET_BE_U_2(cp), OFPFF_U);
1539*05b00f60SXin Li OF_FWD(2);
1540*05b00f60SXin Li /* actions */
1541*05b00f60SXin Li of10_actions_print(ndo, "\n\t ", cp, len);
1542*05b00f60SXin Li }
1543*05b00f60SXin Li
1544*05b00f60SXin Li /* ibid */
1545*05b00f60SXin Li static void
of10_port_mod_print(netdissect_options * ndo,const u_char * cp,u_int len _U_)1546*05b00f60SXin Li of10_port_mod_print(netdissect_options *ndo,
1547*05b00f60SXin Li const u_char *cp, u_int len _U_)
1548*05b00f60SXin Li {
1549*05b00f60SXin Li /* port_no */
1550*05b00f60SXin Li ND_PRINT("\n\t port_no %s", tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1551*05b00f60SXin Li cp += 2;
1552*05b00f60SXin Li /* hw_addr */
1553*05b00f60SXin Li ND_PRINT(", hw_addr %s", GET_ETHERADDR_STRING(cp));
1554*05b00f60SXin Li cp += MAC_ADDR_LEN;
1555*05b00f60SXin Li /* config */
1556*05b00f60SXin Li ND_PRINT("\n\t config 0x%08x", GET_BE_U_4(cp));
1557*05b00f60SXin Li of_bitmap_print(ndo, ofppc_bm, GET_BE_U_4(cp), OFPPC_U);
1558*05b00f60SXin Li cp += 4;
1559*05b00f60SXin Li /* mask */
1560*05b00f60SXin Li ND_PRINT("\n\t mask 0x%08x", GET_BE_U_4(cp));
1561*05b00f60SXin Li of_bitmap_print(ndo, ofppc_bm, GET_BE_U_4(cp), OFPPC_U);
1562*05b00f60SXin Li cp += 4;
1563*05b00f60SXin Li /* advertise */
1564*05b00f60SXin Li ND_PRINT("\n\t advertise 0x%08x", GET_BE_U_4(cp));
1565*05b00f60SXin Li of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U);
1566*05b00f60SXin Li cp += 4;
1567*05b00f60SXin Li /* pad */
1568*05b00f60SXin Li /* Always the last field, check bounds. */
1569*05b00f60SXin Li ND_TCHECK_4(cp);
1570*05b00f60SXin Li }
1571*05b00f60SXin Li
1572*05b00f60SXin Li /* [OF10] Section 5.3.4 */
1573*05b00f60SXin Li static void
of10_queue_get_config_request_print(netdissect_options * ndo,const u_char * cp,u_int len _U_)1574*05b00f60SXin Li of10_queue_get_config_request_print(netdissect_options *ndo,
1575*05b00f60SXin Li const u_char *cp, u_int len _U_)
1576*05b00f60SXin Li {
1577*05b00f60SXin Li /* port */
1578*05b00f60SXin Li ND_PRINT("\n\t port %s", tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1579*05b00f60SXin Li cp += 2;
1580*05b00f60SXin Li /* pad */
1581*05b00f60SXin Li /* Always the last field, check bounds. */
1582*05b00f60SXin Li ND_TCHECK_2(cp);
1583*05b00f60SXin Li }
1584*05b00f60SXin Li
1585*05b00f60SXin Li /* ibid */
1586*05b00f60SXin Li static void
of10_queue_get_config_reply_print(netdissect_options * ndo,const u_char * cp,u_int len)1587*05b00f60SXin Li of10_queue_get_config_reply_print(netdissect_options *ndo,
1588*05b00f60SXin Li const u_char *cp, u_int len)
1589*05b00f60SXin Li {
1590*05b00f60SXin Li /* port */
1591*05b00f60SXin Li ND_PRINT("\n\t port %s", tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1592*05b00f60SXin Li OF_FWD(2);
1593*05b00f60SXin Li /* pad */
1594*05b00f60SXin Li /* Sometimes the last field, check bounds. */
1595*05b00f60SXin Li OF_CHK_FWD(6);
1596*05b00f60SXin Li /* queues */
1597*05b00f60SXin Li of10_queues_print(ndo, cp, len);
1598*05b00f60SXin Li }
1599*05b00f60SXin Li
1600*05b00f60SXin Li /* [OF10] Section 5.3.5 */
1601*05b00f60SXin Li static void
of10_stats_request_print(netdissect_options * ndo,const u_char * cp,u_int len)1602*05b00f60SXin Li of10_stats_request_print(netdissect_options *ndo,
1603*05b00f60SXin Li const u_char *cp, u_int len)
1604*05b00f60SXin Li {
1605*05b00f60SXin Li uint16_t type;
1606*05b00f60SXin Li
1607*05b00f60SXin Li /* type */
1608*05b00f60SXin Li type = GET_BE_U_2(cp);
1609*05b00f60SXin Li OF_FWD(2);
1610*05b00f60SXin Li ND_PRINT("\n\t type %s", tok2str(ofpst_str, "invalid (0x%04x)", type));
1611*05b00f60SXin Li /* flags */
1612*05b00f60SXin Li ND_PRINT(", flags 0x%04x", GET_BE_U_2(cp));
1613*05b00f60SXin Li if (GET_BE_U_2(cp))
1614*05b00f60SXin Li ND_PRINT(" (bogus)");
1615*05b00f60SXin Li OF_FWD(2);
1616*05b00f60SXin Li /* type-specific body of one of fixed lengths */
1617*05b00f60SXin Li switch(type) {
1618*05b00f60SXin Li case OFPST_DESC:
1619*05b00f60SXin Li case OFPST_TABLE:
1620*05b00f60SXin Li if (len)
1621*05b00f60SXin Li goto invalid;
1622*05b00f60SXin Li return;
1623*05b00f60SXin Li case OFPST_FLOW:
1624*05b00f60SXin Li case OFPST_AGGREGATE:
1625*05b00f60SXin Li if (len != OF_FLOW_STATS_REQUEST_FIXLEN)
1626*05b00f60SXin Li goto invalid;
1627*05b00f60SXin Li /* match */
1628*05b00f60SXin Li of10_match_print(ndo, "\n\t ", cp);
1629*05b00f60SXin Li OF_FWD(OF_MATCH_FIXLEN);
1630*05b00f60SXin Li /* table_id */
1631*05b00f60SXin Li ND_PRINT("\n\t table_id %s",
1632*05b00f60SXin Li tok2str(tableid_str, "%u", GET_U_1(cp)));
1633*05b00f60SXin Li OF_FWD(1);
1634*05b00f60SXin Li /* pad */
1635*05b00f60SXin Li OF_FWD(1);
1636*05b00f60SXin Li /* out_port */
1637*05b00f60SXin Li ND_PRINT(", out_port %s",
1638*05b00f60SXin Li tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1639*05b00f60SXin Li return;
1640*05b00f60SXin Li case OFPST_PORT:
1641*05b00f60SXin Li if (len != OF_PORT_STATS_REQUEST_FIXLEN)
1642*05b00f60SXin Li goto invalid;
1643*05b00f60SXin Li /* port_no */
1644*05b00f60SXin Li ND_PRINT("\n\t port_no %s",
1645*05b00f60SXin Li tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1646*05b00f60SXin Li OF_FWD(2);
1647*05b00f60SXin Li /* pad */
1648*05b00f60SXin Li /* Always the last field, check bounds. */
1649*05b00f60SXin Li OF_CHK_FWD(6);
1650*05b00f60SXin Li return;
1651*05b00f60SXin Li case OFPST_QUEUE:
1652*05b00f60SXin Li if (len != OF_QUEUE_STATS_REQUEST_FIXLEN)
1653*05b00f60SXin Li goto invalid;
1654*05b00f60SXin Li /* port_no */
1655*05b00f60SXin Li ND_PRINT("\n\t port_no %s",
1656*05b00f60SXin Li tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1657*05b00f60SXin Li OF_FWD(2);
1658*05b00f60SXin Li /* pad */
1659*05b00f60SXin Li OF_FWD(2);
1660*05b00f60SXin Li /* queue_id */
1661*05b00f60SXin Li ND_PRINT(", queue_id %s",
1662*05b00f60SXin Li tok2str(ofpq_str, "%u", GET_BE_U_4(cp)));
1663*05b00f60SXin Li return;
1664*05b00f60SXin Li case OFPST_VENDOR:
1665*05b00f60SXin Li of10_vendor_data_print(ndo, cp, len);
1666*05b00f60SXin Li return;
1667*05b00f60SXin Li }
1668*05b00f60SXin Li return;
1669*05b00f60SXin Li
1670*05b00f60SXin Li invalid: /* skip the message body */
1671*05b00f60SXin Li nd_print_invalid(ndo);
1672*05b00f60SXin Li ND_TCHECK_LEN(cp, len);
1673*05b00f60SXin Li }
1674*05b00f60SXin Li
1675*05b00f60SXin Li /* ibid */
1676*05b00f60SXin Li static void
of10_desc_stats_reply_print(netdissect_options * ndo,const u_char * cp,u_int len)1677*05b00f60SXin Li of10_desc_stats_reply_print(netdissect_options *ndo,
1678*05b00f60SXin Li const u_char *cp, u_int len)
1679*05b00f60SXin Li {
1680*05b00f60SXin Li if (len != OF_DESC_STATS_REPLY_FIXLEN)
1681*05b00f60SXin Li goto invalid;
1682*05b00f60SXin Li /* mfr_desc */
1683*05b00f60SXin Li ND_PRINT("\n\t mfr_desc '");
1684*05b00f60SXin Li nd_printjnp(ndo, cp, DESC_STR_LEN);
1685*05b00f60SXin Li ND_PRINT("'");
1686*05b00f60SXin Li OF_FWD(DESC_STR_LEN);
1687*05b00f60SXin Li /* hw_desc */
1688*05b00f60SXin Li ND_PRINT("\n\t hw_desc '");
1689*05b00f60SXin Li nd_printjnp(ndo, cp, DESC_STR_LEN);
1690*05b00f60SXin Li ND_PRINT("'");
1691*05b00f60SXin Li OF_FWD(DESC_STR_LEN);
1692*05b00f60SXin Li /* sw_desc */
1693*05b00f60SXin Li ND_PRINT("\n\t sw_desc '");
1694*05b00f60SXin Li nd_printjnp(ndo, cp, DESC_STR_LEN);
1695*05b00f60SXin Li ND_PRINT("'");
1696*05b00f60SXin Li OF_FWD(DESC_STR_LEN);
1697*05b00f60SXin Li /* serial_num */
1698*05b00f60SXin Li ND_PRINT("\n\t serial_num '");
1699*05b00f60SXin Li nd_printjnp(ndo, cp, SERIAL_NUM_LEN);
1700*05b00f60SXin Li ND_PRINT("'");
1701*05b00f60SXin Li OF_FWD(SERIAL_NUM_LEN);
1702*05b00f60SXin Li /* dp_desc */
1703*05b00f60SXin Li ND_PRINT("\n\t dp_desc '");
1704*05b00f60SXin Li nd_printjnp(ndo, cp, DESC_STR_LEN);
1705*05b00f60SXin Li ND_PRINT("'");
1706*05b00f60SXin Li return;
1707*05b00f60SXin Li
1708*05b00f60SXin Li invalid: /* skip the message body */
1709*05b00f60SXin Li nd_print_invalid(ndo);
1710*05b00f60SXin Li ND_TCHECK_LEN(cp, len);
1711*05b00f60SXin Li }
1712*05b00f60SXin Li
1713*05b00f60SXin Li /* ibid */
1714*05b00f60SXin Li static void
of10_flow_stats_reply_print(netdissect_options * ndo,const u_char * cp,u_int len)1715*05b00f60SXin Li of10_flow_stats_reply_print(netdissect_options *ndo,
1716*05b00f60SXin Li const u_char *cp, u_int len)
1717*05b00f60SXin Li {
1718*05b00f60SXin Li while (len) {
1719*05b00f60SXin Li uint16_t entry_len;
1720*05b00f60SXin Li
1721*05b00f60SXin Li if (len < OF_FLOW_STATS_REPLY_MINLEN)
1722*05b00f60SXin Li goto invalid;
1723*05b00f60SXin Li /* length */
1724*05b00f60SXin Li entry_len = GET_BE_U_2(cp);
1725*05b00f60SXin Li ND_PRINT("\n\t length %u", entry_len);
1726*05b00f60SXin Li if (entry_len < OF_FLOW_STATS_REPLY_MINLEN || entry_len > len)
1727*05b00f60SXin Li goto invalid;
1728*05b00f60SXin Li OF_FWD(2);
1729*05b00f60SXin Li /* table_id */
1730*05b00f60SXin Li ND_PRINT(", table_id %s",
1731*05b00f60SXin Li tok2str(tableid_str, "%u", GET_U_1(cp)));
1732*05b00f60SXin Li OF_FWD(1);
1733*05b00f60SXin Li /* pad */
1734*05b00f60SXin Li OF_FWD(1);
1735*05b00f60SXin Li /* match */
1736*05b00f60SXin Li of10_match_print(ndo, "\n\t ", cp);
1737*05b00f60SXin Li OF_FWD(OF_MATCH_FIXLEN);
1738*05b00f60SXin Li /* duration_sec */
1739*05b00f60SXin Li ND_PRINT("\n\t duration_sec %u", GET_BE_U_4(cp));
1740*05b00f60SXin Li OF_FWD(4);
1741*05b00f60SXin Li /* duration_nsec */
1742*05b00f60SXin Li ND_PRINT(", duration_nsec %u", GET_BE_U_4(cp));
1743*05b00f60SXin Li OF_FWD(4);
1744*05b00f60SXin Li /* priority */
1745*05b00f60SXin Li ND_PRINT(", priority %u", GET_BE_U_2(cp));
1746*05b00f60SXin Li OF_FWD(2);
1747*05b00f60SXin Li /* idle_timeout */
1748*05b00f60SXin Li ND_PRINT(", idle_timeout %u", GET_BE_U_2(cp));
1749*05b00f60SXin Li OF_FWD(2);
1750*05b00f60SXin Li /* hard_timeout */
1751*05b00f60SXin Li ND_PRINT(", hard_timeout %u", GET_BE_U_2(cp));
1752*05b00f60SXin Li OF_FWD(2);
1753*05b00f60SXin Li /* pad2 */
1754*05b00f60SXin Li OF_FWD(6);
1755*05b00f60SXin Li /* cookie */
1756*05b00f60SXin Li ND_PRINT(", cookie 0x%016" PRIx64, GET_BE_U_8(cp));
1757*05b00f60SXin Li OF_FWD(8);
1758*05b00f60SXin Li /* packet_count */
1759*05b00f60SXin Li ND_PRINT(", packet_count %" PRIu64, GET_BE_U_8(cp));
1760*05b00f60SXin Li OF_FWD(8);
1761*05b00f60SXin Li /* byte_count */
1762*05b00f60SXin Li ND_PRINT(", byte_count %" PRIu64, GET_BE_U_8(cp));
1763*05b00f60SXin Li OF_FWD(8);
1764*05b00f60SXin Li /* actions */
1765*05b00f60SXin Li of10_actions_print(ndo, "\n\t ", cp, entry_len - OF_FLOW_STATS_REPLY_MINLEN);
1766*05b00f60SXin Li OF_FWD(entry_len - OF_FLOW_STATS_REPLY_MINLEN);
1767*05b00f60SXin Li } /* while */
1768*05b00f60SXin Li return;
1769*05b00f60SXin Li
1770*05b00f60SXin Li invalid: /* skip the rest of flow statistics entries */
1771*05b00f60SXin Li nd_print_invalid(ndo);
1772*05b00f60SXin Li ND_TCHECK_LEN(cp, len);
1773*05b00f60SXin Li }
1774*05b00f60SXin Li
1775*05b00f60SXin Li /* ibid */
1776*05b00f60SXin Li static void
of10_aggregate_stats_reply_print(netdissect_options * ndo,const u_char * cp,u_int len)1777*05b00f60SXin Li of10_aggregate_stats_reply_print(netdissect_options *ndo,
1778*05b00f60SXin Li const u_char *cp, u_int len)
1779*05b00f60SXin Li {
1780*05b00f60SXin Li if (len != OF_AGGREGATE_STATS_REPLY_FIXLEN)
1781*05b00f60SXin Li goto invalid;
1782*05b00f60SXin Li /* packet_count */
1783*05b00f60SXin Li ND_PRINT("\n\t packet_count %" PRIu64, GET_BE_U_8(cp));
1784*05b00f60SXin Li OF_FWD(8);
1785*05b00f60SXin Li /* byte_count */
1786*05b00f60SXin Li ND_PRINT(", byte_count %" PRIu64, GET_BE_U_8(cp));
1787*05b00f60SXin Li OF_FWD(8);
1788*05b00f60SXin Li /* flow_count */
1789*05b00f60SXin Li ND_PRINT(", flow_count %u", GET_BE_U_4(cp));
1790*05b00f60SXin Li OF_FWD(4);
1791*05b00f60SXin Li /* pad */
1792*05b00f60SXin Li /* Always the last field, check bounds. */
1793*05b00f60SXin Li ND_TCHECK_4(cp);
1794*05b00f60SXin Li return;
1795*05b00f60SXin Li
1796*05b00f60SXin Li invalid: /* skip the message body */
1797*05b00f60SXin Li nd_print_invalid(ndo);
1798*05b00f60SXin Li ND_TCHECK_LEN(cp, len);
1799*05b00f60SXin Li }
1800*05b00f60SXin Li
1801*05b00f60SXin Li /* ibid */
1802*05b00f60SXin Li static void
of10_table_stats_reply_print(netdissect_options * ndo,const u_char * cp,u_int len)1803*05b00f60SXin Li of10_table_stats_reply_print(netdissect_options *ndo,
1804*05b00f60SXin Li const u_char *cp, u_int len)
1805*05b00f60SXin Li {
1806*05b00f60SXin Li while (len) {
1807*05b00f60SXin Li if (len < OF_TABLE_STATS_REPLY_FIXLEN)
1808*05b00f60SXin Li goto invalid;
1809*05b00f60SXin Li /* table_id */
1810*05b00f60SXin Li ND_PRINT("\n\t table_id %s",
1811*05b00f60SXin Li tok2str(tableid_str, "%u", GET_U_1(cp)));
1812*05b00f60SXin Li OF_FWD(1);
1813*05b00f60SXin Li /* pad */
1814*05b00f60SXin Li OF_FWD(3);
1815*05b00f60SXin Li /* name */
1816*05b00f60SXin Li ND_PRINT(", name '");
1817*05b00f60SXin Li nd_printjnp(ndo, cp, OFP_MAX_TABLE_NAME_LEN);
1818*05b00f60SXin Li ND_PRINT("'");
1819*05b00f60SXin Li OF_FWD(OFP_MAX_TABLE_NAME_LEN);
1820*05b00f60SXin Li /* wildcards */
1821*05b00f60SXin Li ND_PRINT("\n\t wildcards 0x%08x", GET_BE_U_4(cp));
1822*05b00f60SXin Li of_bitmap_print(ndo, ofpfw_bm, GET_BE_U_4(cp), OFPFW_U);
1823*05b00f60SXin Li OF_FWD(4);
1824*05b00f60SXin Li /* max_entries */
1825*05b00f60SXin Li ND_PRINT("\n\t max_entries %u", GET_BE_U_4(cp));
1826*05b00f60SXin Li OF_FWD(4);
1827*05b00f60SXin Li /* active_count */
1828*05b00f60SXin Li ND_PRINT(", active_count %u", GET_BE_U_4(cp));
1829*05b00f60SXin Li OF_FWD(4);
1830*05b00f60SXin Li /* lookup_count */
1831*05b00f60SXin Li ND_PRINT(", lookup_count %" PRIu64, GET_BE_U_8(cp));
1832*05b00f60SXin Li OF_FWD(8);
1833*05b00f60SXin Li /* matched_count */
1834*05b00f60SXin Li ND_PRINT(", matched_count %" PRIu64, GET_BE_U_8(cp));
1835*05b00f60SXin Li OF_FWD(8);
1836*05b00f60SXin Li } /* while */
1837*05b00f60SXin Li return;
1838*05b00f60SXin Li
1839*05b00f60SXin Li invalid: /* skip the undersized trailing data */
1840*05b00f60SXin Li nd_print_invalid(ndo);
1841*05b00f60SXin Li ND_TCHECK_LEN(cp, len);
1842*05b00f60SXin Li }
1843*05b00f60SXin Li
1844*05b00f60SXin Li /* ibid */
1845*05b00f60SXin Li static void
of10_port_stats_reply_print(netdissect_options * ndo,const u_char * cp,u_int len)1846*05b00f60SXin Li of10_port_stats_reply_print(netdissect_options *ndo,
1847*05b00f60SXin Li const u_char *cp, u_int len)
1848*05b00f60SXin Li {
1849*05b00f60SXin Li while (len) {
1850*05b00f60SXin Li if (len < OF_PORT_STATS_REPLY_FIXLEN)
1851*05b00f60SXin Li goto invalid;
1852*05b00f60SXin Li /* port_no */
1853*05b00f60SXin Li ND_PRINT("\n\t port_no %s",
1854*05b00f60SXin Li tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1855*05b00f60SXin Li OF_FWD(2);
1856*05b00f60SXin Li if (ndo->ndo_vflag < 2) {
1857*05b00f60SXin Li OF_CHK_FWD(OF_PORT_STATS_REPLY_FIXLEN - 2);
1858*05b00f60SXin Li continue;
1859*05b00f60SXin Li }
1860*05b00f60SXin Li /* pad */
1861*05b00f60SXin Li OF_FWD(6);
1862*05b00f60SXin Li /* rx_packets */
1863*05b00f60SXin Li ND_PRINT(", rx_packets %" PRIu64, GET_BE_U_8(cp));
1864*05b00f60SXin Li OF_FWD(8);
1865*05b00f60SXin Li /* tx_packets */
1866*05b00f60SXin Li ND_PRINT(", tx_packets %" PRIu64, GET_BE_U_8(cp));
1867*05b00f60SXin Li OF_FWD(8);
1868*05b00f60SXin Li /* rx_bytes */
1869*05b00f60SXin Li ND_PRINT(", rx_bytes %" PRIu64, GET_BE_U_8(cp));
1870*05b00f60SXin Li OF_FWD(8);
1871*05b00f60SXin Li /* tx_bytes */
1872*05b00f60SXin Li ND_PRINT(", tx_bytes %" PRIu64, GET_BE_U_8(cp));
1873*05b00f60SXin Li OF_FWD(8);
1874*05b00f60SXin Li /* rx_dropped */
1875*05b00f60SXin Li ND_PRINT(", rx_dropped %" PRIu64, GET_BE_U_8(cp));
1876*05b00f60SXin Li OF_FWD(8);
1877*05b00f60SXin Li /* tx_dropped */
1878*05b00f60SXin Li ND_PRINT(", tx_dropped %" PRIu64, GET_BE_U_8(cp));
1879*05b00f60SXin Li OF_FWD(8);
1880*05b00f60SXin Li /* rx_errors */
1881*05b00f60SXin Li ND_PRINT(", rx_errors %" PRIu64, GET_BE_U_8(cp));
1882*05b00f60SXin Li OF_FWD(8);
1883*05b00f60SXin Li /* tx_errors */
1884*05b00f60SXin Li ND_PRINT(", tx_errors %" PRIu64, GET_BE_U_8(cp));
1885*05b00f60SXin Li OF_FWD(8);
1886*05b00f60SXin Li /* rx_frame_err */
1887*05b00f60SXin Li ND_PRINT(", rx_frame_err %" PRIu64, GET_BE_U_8(cp));
1888*05b00f60SXin Li OF_FWD(8);
1889*05b00f60SXin Li /* rx_over_err */
1890*05b00f60SXin Li ND_PRINT(", rx_over_err %" PRIu64, GET_BE_U_8(cp));
1891*05b00f60SXin Li OF_FWD(8);
1892*05b00f60SXin Li /* rx_crc_err */
1893*05b00f60SXin Li ND_PRINT(", rx_crc_err %" PRIu64, GET_BE_U_8(cp));
1894*05b00f60SXin Li OF_FWD(8);
1895*05b00f60SXin Li /* collisions */
1896*05b00f60SXin Li ND_PRINT(", collisions %" PRIu64, GET_BE_U_8(cp));
1897*05b00f60SXin Li OF_FWD(8);
1898*05b00f60SXin Li } /* while */
1899*05b00f60SXin Li return;
1900*05b00f60SXin Li
1901*05b00f60SXin Li invalid: /* skip the undersized trailing data */
1902*05b00f60SXin Li nd_print_invalid(ndo);
1903*05b00f60SXin Li ND_TCHECK_LEN(cp, len);
1904*05b00f60SXin Li }
1905*05b00f60SXin Li
1906*05b00f60SXin Li /* ibid */
1907*05b00f60SXin Li static void
of10_queue_stats_reply_print(netdissect_options * ndo,const u_char * cp,u_int len)1908*05b00f60SXin Li of10_queue_stats_reply_print(netdissect_options *ndo,
1909*05b00f60SXin Li const u_char *cp, u_int len)
1910*05b00f60SXin Li {
1911*05b00f60SXin Li while (len) {
1912*05b00f60SXin Li if (len < OF_QUEUE_STATS_REPLY_FIXLEN)
1913*05b00f60SXin Li goto invalid;
1914*05b00f60SXin Li /* port_no */
1915*05b00f60SXin Li ND_PRINT("\n\t port_no %s",
1916*05b00f60SXin Li tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1917*05b00f60SXin Li OF_FWD(2);
1918*05b00f60SXin Li /* pad */
1919*05b00f60SXin Li OF_FWD(2);
1920*05b00f60SXin Li /* queue_id */
1921*05b00f60SXin Li ND_PRINT(", queue_id %u", GET_BE_U_4(cp));
1922*05b00f60SXin Li OF_FWD(4);
1923*05b00f60SXin Li /* tx_bytes */
1924*05b00f60SXin Li ND_PRINT(", tx_bytes %" PRIu64, GET_BE_U_8(cp));
1925*05b00f60SXin Li OF_FWD(8);
1926*05b00f60SXin Li /* tx_packets */
1927*05b00f60SXin Li ND_PRINT(", tx_packets %" PRIu64, GET_BE_U_8(cp));
1928*05b00f60SXin Li OF_FWD(8);
1929*05b00f60SXin Li /* tx_errors */
1930*05b00f60SXin Li ND_PRINT(", tx_errors %" PRIu64, GET_BE_U_8(cp));
1931*05b00f60SXin Li OF_FWD(8);
1932*05b00f60SXin Li } /* while */
1933*05b00f60SXin Li return;
1934*05b00f60SXin Li
1935*05b00f60SXin Li invalid: /* skip the undersized trailing data */
1936*05b00f60SXin Li nd_print_invalid(ndo);
1937*05b00f60SXin Li ND_TCHECK_LEN(cp, len);
1938*05b00f60SXin Li }
1939*05b00f60SXin Li
1940*05b00f60SXin Li /* ibid */
1941*05b00f60SXin Li static void
of10_stats_reply_print(netdissect_options * ndo,const u_char * cp,u_int len)1942*05b00f60SXin Li of10_stats_reply_print(netdissect_options *ndo,
1943*05b00f60SXin Li const u_char *cp, u_int len)
1944*05b00f60SXin Li {
1945*05b00f60SXin Li uint16_t type;
1946*05b00f60SXin Li
1947*05b00f60SXin Li /* type */
1948*05b00f60SXin Li type = GET_BE_U_2(cp);
1949*05b00f60SXin Li ND_PRINT("\n\t type %s", tok2str(ofpst_str, "invalid (0x%04x)", type));
1950*05b00f60SXin Li OF_FWD(2);
1951*05b00f60SXin Li /* flags */
1952*05b00f60SXin Li ND_PRINT(", flags 0x%04x", GET_BE_U_2(cp));
1953*05b00f60SXin Li of_bitmap_print(ndo, ofpsf_reply_bm, GET_BE_U_2(cp), OFPSF_REPLY_U);
1954*05b00f60SXin Li OF_FWD(2);
1955*05b00f60SXin Li
1956*05b00f60SXin Li if (ndo->ndo_vflag > 0) {
1957*05b00f60SXin Li void (*decoder)(netdissect_options *, const u_char *, u_int) =
1958*05b00f60SXin Li type == OFPST_DESC ? of10_desc_stats_reply_print :
1959*05b00f60SXin Li type == OFPST_FLOW ? of10_flow_stats_reply_print :
1960*05b00f60SXin Li type == OFPST_AGGREGATE ? of10_aggregate_stats_reply_print :
1961*05b00f60SXin Li type == OFPST_TABLE ? of10_table_stats_reply_print :
1962*05b00f60SXin Li type == OFPST_PORT ? of10_port_stats_reply_print :
1963*05b00f60SXin Li type == OFPST_QUEUE ? of10_queue_stats_reply_print :
1964*05b00f60SXin Li type == OFPST_VENDOR ? of10_vendor_data_print :
1965*05b00f60SXin Li NULL;
1966*05b00f60SXin Li if (decoder != NULL) {
1967*05b00f60SXin Li decoder(ndo, cp, len);
1968*05b00f60SXin Li return;
1969*05b00f60SXin Li }
1970*05b00f60SXin Li }
1971*05b00f60SXin Li ND_TCHECK_LEN(cp, len);
1972*05b00f60SXin Li }
1973*05b00f60SXin Li
1974*05b00f60SXin Li /* [OF10] Section 5.3.6 */
1975*05b00f60SXin Li static void
of10_packet_out_print(netdissect_options * ndo,const u_char * cp,u_int len)1976*05b00f60SXin Li of10_packet_out_print(netdissect_options *ndo,
1977*05b00f60SXin Li const u_char *cp, u_int len)
1978*05b00f60SXin Li {
1979*05b00f60SXin Li uint16_t actions_len;
1980*05b00f60SXin Li
1981*05b00f60SXin Li /* buffer_id */
1982*05b00f60SXin Li ND_PRINT("\n\t buffer_id 0x%08x", GET_BE_U_4(cp));
1983*05b00f60SXin Li OF_FWD(4);
1984*05b00f60SXin Li /* in_port */
1985*05b00f60SXin Li ND_PRINT(", in_port %s", tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
1986*05b00f60SXin Li OF_FWD(2);
1987*05b00f60SXin Li /* actions_len */
1988*05b00f60SXin Li actions_len = GET_BE_U_2(cp);
1989*05b00f60SXin Li OF_FWD(2);
1990*05b00f60SXin Li if (actions_len > len)
1991*05b00f60SXin Li goto invalid;
1992*05b00f60SXin Li /* actions */
1993*05b00f60SXin Li of10_actions_print(ndo, "\n\t ", cp, actions_len);
1994*05b00f60SXin Li OF_FWD(actions_len);
1995*05b00f60SXin Li /* data */
1996*05b00f60SXin Li of10_packet_data_print(ndo, cp, len);
1997*05b00f60SXin Li return;
1998*05b00f60SXin Li
1999*05b00f60SXin Li invalid: /* skip the rest of the message body */
2000*05b00f60SXin Li nd_print_invalid(ndo);
2001*05b00f60SXin Li ND_TCHECK_LEN(cp, len);
2002*05b00f60SXin Li }
2003*05b00f60SXin Li
2004*05b00f60SXin Li /* [OF10] Section 5.4.1 */
2005*05b00f60SXin Li static void
of10_packet_in_print(netdissect_options * ndo,const u_char * cp,u_int len)2006*05b00f60SXin Li of10_packet_in_print(netdissect_options *ndo,
2007*05b00f60SXin Li const u_char *cp, u_int len)
2008*05b00f60SXin Li {
2009*05b00f60SXin Li /* buffer_id */
2010*05b00f60SXin Li ND_PRINT("\n\t buffer_id %s",
2011*05b00f60SXin Li tok2str(bufferid_str, "0x%08x", GET_BE_U_4(cp)));
2012*05b00f60SXin Li OF_FWD(4);
2013*05b00f60SXin Li /* total_len */
2014*05b00f60SXin Li ND_PRINT(", total_len %u", GET_BE_U_2(cp));
2015*05b00f60SXin Li OF_FWD(2);
2016*05b00f60SXin Li /* in_port */
2017*05b00f60SXin Li ND_PRINT(", in_port %s", tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
2018*05b00f60SXin Li OF_FWD(2);
2019*05b00f60SXin Li /* reason */
2020*05b00f60SXin Li ND_PRINT(", reason %s",
2021*05b00f60SXin Li tok2str(ofpr_str, "invalid (0x%02x)", GET_U_1(cp)));
2022*05b00f60SXin Li OF_FWD(1);
2023*05b00f60SXin Li /* pad */
2024*05b00f60SXin Li /* Sometimes the last field, check bounds. */
2025*05b00f60SXin Li OF_CHK_FWD(1);
2026*05b00f60SXin Li /* data */
2027*05b00f60SXin Li of10_packet_data_print(ndo, cp, len);
2028*05b00f60SXin Li }
2029*05b00f60SXin Li
2030*05b00f60SXin Li /* [OF10] Section 5.4.2 */
2031*05b00f60SXin Li static void
of10_flow_removed_print(netdissect_options * ndo,const u_char * cp,u_int len _U_)2032*05b00f60SXin Li of10_flow_removed_print(netdissect_options *ndo,
2033*05b00f60SXin Li const u_char *cp, u_int len _U_)
2034*05b00f60SXin Li {
2035*05b00f60SXin Li /* match */
2036*05b00f60SXin Li of10_match_print(ndo, "\n\t ", cp);
2037*05b00f60SXin Li cp += OF_MATCH_FIXLEN;
2038*05b00f60SXin Li /* cookie */
2039*05b00f60SXin Li ND_PRINT("\n\t cookie 0x%016" PRIx64, GET_BE_U_8(cp));
2040*05b00f60SXin Li cp += 8;
2041*05b00f60SXin Li /* priority */
2042*05b00f60SXin Li if (GET_BE_U_2(cp))
2043*05b00f60SXin Li ND_PRINT(", priority %u", GET_BE_U_2(cp));
2044*05b00f60SXin Li cp += 2;
2045*05b00f60SXin Li /* reason */
2046*05b00f60SXin Li ND_PRINT(", reason %s",
2047*05b00f60SXin Li tok2str(ofprr_str, "unknown (0x%02x)", GET_U_1(cp)));
2048*05b00f60SXin Li cp += 1;
2049*05b00f60SXin Li /* pad */
2050*05b00f60SXin Li cp += 1;
2051*05b00f60SXin Li /* duration_sec */
2052*05b00f60SXin Li ND_PRINT(", duration_sec %u", GET_BE_U_4(cp));
2053*05b00f60SXin Li cp += 4;
2054*05b00f60SXin Li /* duration_nsec */
2055*05b00f60SXin Li ND_PRINT(", duration_nsec %u", GET_BE_U_4(cp));
2056*05b00f60SXin Li cp += 4;
2057*05b00f60SXin Li /* idle_timeout */
2058*05b00f60SXin Li if (GET_BE_U_2(cp))
2059*05b00f60SXin Li ND_PRINT(", idle_timeout %u", GET_BE_U_2(cp));
2060*05b00f60SXin Li cp += 2;
2061*05b00f60SXin Li /* pad2 */
2062*05b00f60SXin Li cp += 2;
2063*05b00f60SXin Li /* packet_count */
2064*05b00f60SXin Li ND_PRINT(", packet_count %" PRIu64, GET_BE_U_8(cp));
2065*05b00f60SXin Li cp += 8;
2066*05b00f60SXin Li /* byte_count */
2067*05b00f60SXin Li ND_PRINT(", byte_count %" PRIu64, GET_BE_U_8(cp));
2068*05b00f60SXin Li }
2069*05b00f60SXin Li
2070*05b00f60SXin Li /* [OF10] Section 5.4.3 */
2071*05b00f60SXin Li static void
of10_port_status_print(netdissect_options * ndo,const u_char * cp,u_int len _U_)2072*05b00f60SXin Li of10_port_status_print(netdissect_options *ndo,
2073*05b00f60SXin Li const u_char *cp, u_int len _U_)
2074*05b00f60SXin Li {
2075*05b00f60SXin Li /* reason */
2076*05b00f60SXin Li ND_PRINT("\n\t reason %s",
2077*05b00f60SXin Li tok2str(ofppr_str, "invalid (0x%02x)", GET_U_1(cp)));
2078*05b00f60SXin Li cp += 1;
2079*05b00f60SXin Li /* pad */
2080*05b00f60SXin Li /* No need to check bounds, more data follows. */
2081*05b00f60SXin Li cp += 7;
2082*05b00f60SXin Li /* desc */
2083*05b00f60SXin Li of10_phy_port_print(ndo, cp);
2084*05b00f60SXin Li }
2085*05b00f60SXin Li
2086*05b00f60SXin Li /* [OF10] Section 5.4.4 */
2087*05b00f60SXin Li static void
of10_error_print(netdissect_options * ndo,const u_char * cp,u_int len)2088*05b00f60SXin Li of10_error_print(netdissect_options *ndo,
2089*05b00f60SXin Li const u_char *cp, u_int len)
2090*05b00f60SXin Li {
2091*05b00f60SXin Li uint16_t type, code;
2092*05b00f60SXin Li const struct tok *code_str;
2093*05b00f60SXin Li
2094*05b00f60SXin Li /* type */
2095*05b00f60SXin Li type = GET_BE_U_2(cp);
2096*05b00f60SXin Li OF_FWD(2);
2097*05b00f60SXin Li ND_PRINT("\n\t type %s", tok2str(ofpet_str, "invalid (0x%04x)", type));
2098*05b00f60SXin Li /* code */
2099*05b00f60SXin Li code = GET_BE_U_2(cp);
2100*05b00f60SXin Li OF_FWD(2);
2101*05b00f60SXin Li code_str = uint2tokary(of10_ofpet2tokary, type);
2102*05b00f60SXin Li if (code_str != NULL)
2103*05b00f60SXin Li ND_PRINT(", code %s",
2104*05b00f60SXin Li tok2str(code_str, "invalid (0x%04x)", code));
2105*05b00f60SXin Li else
2106*05b00f60SXin Li ND_PRINT(", code invalid (0x%04x)", code);
2107*05b00f60SXin Li /* data */
2108*05b00f60SXin Li of_data_print(ndo, cp, len);
2109*05b00f60SXin Li }
2110*05b00f60SXin Li
2111*05b00f60SXin Li static const struct of_msgtypeinfo of10_msgtypeinfo[OFPT_MAX + 1] = {
2112*05b00f60SXin Li /*
2113*05b00f60SXin Li * [OF10] Section 5.5.1
2114*05b00f60SXin Li * Variable-size data.
2115*05b00f60SXin Li */
2116*05b00f60SXin Li {
2117*05b00f60SXin Li "HELLO", of_data_print,
2118*05b00f60SXin Li REQ_MINLEN, 0
2119*05b00f60SXin Li },
2120*05b00f60SXin Li /*
2121*05b00f60SXin Li * [OF10] Section 5.4.4
2122*05b00f60SXin Li * A fixed-size message body and variable-size data.
2123*05b00f60SXin Li */
2124*05b00f60SXin Li {
2125*05b00f60SXin Li "ERROR", of10_error_print,
2126*05b00f60SXin Li REQ_MINLEN, OF_ERROR_MSG_MINLEN
2127*05b00f60SXin Li },
2128*05b00f60SXin Li /*
2129*05b00f60SXin Li * [OF10] Section 5.5.2
2130*05b00f60SXin Li * Variable-size data.
2131*05b00f60SXin Li */
2132*05b00f60SXin Li {
2133*05b00f60SXin Li "ECHO_REQUEST", of_data_print,
2134*05b00f60SXin Li REQ_MINLEN, 0
2135*05b00f60SXin Li },
2136*05b00f60SXin Li /*
2137*05b00f60SXin Li * [OF10] Section 5.5.3
2138*05b00f60SXin Li * Variable-size data.
2139*05b00f60SXin Li */
2140*05b00f60SXin Li {
2141*05b00f60SXin Li "ECHO_REPLY", of_data_print,
2142*05b00f60SXin Li REQ_MINLEN, 0
2143*05b00f60SXin Li },
2144*05b00f60SXin Li /*
2145*05b00f60SXin Li * [OF10] Section 5.5.4
2146*05b00f60SXin Li * A fixed-size message body and variable-size data.
2147*05b00f60SXin Li */
2148*05b00f60SXin Li {
2149*05b00f60SXin Li "VENDOR", of10_vendor_message_print,
2150*05b00f60SXin Li REQ_MINLEN, OF_VENDOR_MINLEN
2151*05b00f60SXin Li },
2152*05b00f60SXin Li /*
2153*05b00f60SXin Li * [OF10] Section 5.3.1
2154*05b00f60SXin Li * No message body.
2155*05b00f60SXin Li */
2156*05b00f60SXin Li {
2157*05b00f60SXin Li "FEATURES_REQUEST", NULL,
2158*05b00f60SXin Li REQ_FIXLEN, 0
2159*05b00f60SXin Li },
2160*05b00f60SXin Li /*
2161*05b00f60SXin Li * [OF10] Section 5.3.1
2162*05b00f60SXin Li * A fixed-size message body and n * fixed-size data units.
2163*05b00f60SXin Li */
2164*05b00f60SXin Li {
2165*05b00f60SXin Li "FEATURES_REPLY", of10_features_reply_print,
2166*05b00f60SXin Li REQ_MINLEN, OF_FEATURES_REPLY_MINLEN
2167*05b00f60SXin Li },
2168*05b00f60SXin Li /*
2169*05b00f60SXin Li * [OF10] Section 5.3.2
2170*05b00f60SXin Li * No message body.
2171*05b00f60SXin Li */
2172*05b00f60SXin Li {
2173*05b00f60SXin Li "GET_CONFIG_REQUEST", NULL,
2174*05b00f60SXin Li REQ_FIXLEN, 0
2175*05b00f60SXin Li },
2176*05b00f60SXin Li /*
2177*05b00f60SXin Li * [OF10] Section 5.3.2
2178*05b00f60SXin Li * A fixed-size message body.
2179*05b00f60SXin Li */
2180*05b00f60SXin Li {
2181*05b00f60SXin Li "GET_CONFIG_REPLY", of10_switch_config_msg_print,
2182*05b00f60SXin Li REQ_FIXLEN, OF_SWITCH_CONFIG_FIXLEN
2183*05b00f60SXin Li },
2184*05b00f60SXin Li /*
2185*05b00f60SXin Li * [OF10] Section 5.3.2
2186*05b00f60SXin Li * A fixed-size message body.
2187*05b00f60SXin Li */
2188*05b00f60SXin Li {
2189*05b00f60SXin Li "SET_CONFIG", of10_switch_config_msg_print,
2190*05b00f60SXin Li REQ_FIXLEN, OF_SWITCH_CONFIG_FIXLEN
2191*05b00f60SXin Li },
2192*05b00f60SXin Li /*
2193*05b00f60SXin Li * [OF10] Section 5.4.1
2194*05b00f60SXin Li * A fixed-size message body and variable-size data.
2195*05b00f60SXin Li * (The 2 mock octets count in OF_PACKET_IN_MINLEN only.)
2196*05b00f60SXin Li */
2197*05b00f60SXin Li {
2198*05b00f60SXin Li "PACKET_IN", of10_packet_in_print,
2199*05b00f60SXin Li REQ_MINLEN, OF_PACKET_IN_MINLEN - 2
2200*05b00f60SXin Li },
2201*05b00f60SXin Li /*
2202*05b00f60SXin Li * [OF10] Section 5.4.2
2203*05b00f60SXin Li * A fixed-size message body.
2204*05b00f60SXin Li */
2205*05b00f60SXin Li {
2206*05b00f60SXin Li "FLOW_REMOVED", of10_flow_removed_print,
2207*05b00f60SXin Li REQ_FIXLEN, OF_FLOW_REMOVED_FIXLEN
2208*05b00f60SXin Li },
2209*05b00f60SXin Li /*
2210*05b00f60SXin Li * [OF10] Section 5.4.3
2211*05b00f60SXin Li * A fixed-size message body.
2212*05b00f60SXin Li */
2213*05b00f60SXin Li {
2214*05b00f60SXin Li "PORT_STATUS", of10_port_status_print,
2215*05b00f60SXin Li REQ_FIXLEN, OF_PORT_STATUS_FIXLEN
2216*05b00f60SXin Li },
2217*05b00f60SXin Li /*
2218*05b00f60SXin Li * [OF10] Section 5.3.6
2219*05b00f60SXin Li * A fixed-size message body, n * variable-size data units and
2220*05b00f60SXin Li * variable-size data.
2221*05b00f60SXin Li */
2222*05b00f60SXin Li {
2223*05b00f60SXin Li "PACKET_OUT", of10_packet_out_print,
2224*05b00f60SXin Li REQ_MINLEN, OF_PACKET_OUT_MINLEN
2225*05b00f60SXin Li },
2226*05b00f60SXin Li /*
2227*05b00f60SXin Li * [OF10] Section 5.3.3
2228*05b00f60SXin Li * A fixed-size message body and n * variable-size data units.
2229*05b00f60SXin Li */
2230*05b00f60SXin Li {
2231*05b00f60SXin Li "FLOW_MOD", of10_flow_mod_print,
2232*05b00f60SXin Li REQ_MINLEN, OF_FLOW_MOD_MINLEN
2233*05b00f60SXin Li },
2234*05b00f60SXin Li /*
2235*05b00f60SXin Li * [OF10] Section 5.3.3
2236*05b00f60SXin Li * A fixed-size message body.
2237*05b00f60SXin Li */
2238*05b00f60SXin Li {
2239*05b00f60SXin Li "PORT_MOD", of10_port_mod_print,
2240*05b00f60SXin Li REQ_FIXLEN, OF_PORT_MOD_FIXLEN
2241*05b00f60SXin Li },
2242*05b00f60SXin Li /*
2243*05b00f60SXin Li * [OF10] Section 5.3.5
2244*05b00f60SXin Li * A fixed-size message body and possibly more data of varying size
2245*05b00f60SXin Li * and structure.
2246*05b00f60SXin Li */
2247*05b00f60SXin Li {
2248*05b00f60SXin Li "STATS_REQUEST", of10_stats_request_print,
2249*05b00f60SXin Li REQ_MINLEN, OF_STATS_REQUEST_MINLEN
2250*05b00f60SXin Li },
2251*05b00f60SXin Li /*
2252*05b00f60SXin Li * [OF10] Section 5.3.5
2253*05b00f60SXin Li * A fixed-size message body and possibly more data of varying size
2254*05b00f60SXin Li * and structure.
2255*05b00f60SXin Li */
2256*05b00f60SXin Li {
2257*05b00f60SXin Li "STATS_REPLY", of10_stats_reply_print,
2258*05b00f60SXin Li REQ_MINLEN, OF_STATS_REPLY_MINLEN
2259*05b00f60SXin Li },
2260*05b00f60SXin Li /*
2261*05b00f60SXin Li * [OF10] Section 5.3.7
2262*05b00f60SXin Li * No message body.
2263*05b00f60SXin Li */
2264*05b00f60SXin Li {
2265*05b00f60SXin Li "BARRIER_REQUEST", NULL,
2266*05b00f60SXin Li REQ_FIXLEN, 0
2267*05b00f60SXin Li },
2268*05b00f60SXin Li /*
2269*05b00f60SXin Li * [OF10] Section 5.3.7
2270*05b00f60SXin Li * No message body.
2271*05b00f60SXin Li */
2272*05b00f60SXin Li {
2273*05b00f60SXin Li "BARRIER_REPLY", NULL,
2274*05b00f60SXin Li REQ_FIXLEN, 0
2275*05b00f60SXin Li },
2276*05b00f60SXin Li /*
2277*05b00f60SXin Li * [OF10] Section 5.3.4
2278*05b00f60SXin Li * A fixed-size message body.
2279*05b00f60SXin Li */
2280*05b00f60SXin Li {
2281*05b00f60SXin Li "QUEUE_GET_CONFIG_REQUEST", of10_queue_get_config_request_print,
2282*05b00f60SXin Li REQ_FIXLEN, OF_QUEUE_GET_CONFIG_REQUEST_FIXLEN
2283*05b00f60SXin Li },
2284*05b00f60SXin Li /*
2285*05b00f60SXin Li * [OF10] Section 5.3.4
2286*05b00f60SXin Li * A fixed-size message body and n * variable-size data units.
2287*05b00f60SXin Li */
2288*05b00f60SXin Li {
2289*05b00f60SXin Li "QUEUE_GET_CONFIG_REPLY", of10_queue_get_config_reply_print,
2290*05b00f60SXin Li REQ_MINLEN, OF_QUEUE_GET_CONFIG_REPLY_MINLEN
2291*05b00f60SXin Li },
2292*05b00f60SXin Li };
2293*05b00f60SXin Li
2294*05b00f60SXin Li const struct of_msgtypeinfo *
of10_identify_msgtype(const uint8_t type)2295*05b00f60SXin Li of10_identify_msgtype(const uint8_t type)
2296*05b00f60SXin Li {
2297*05b00f60SXin Li return type <= OFPT_MAX ? &of10_msgtypeinfo[type] : NULL;
2298*05b00f60SXin Li }
2299