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