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