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