1 /* 2 * This module implements decoding of OpenFlow protocol version 1.3 (wire 3 * protocol 0x04). It is based on the implementation conventions explained in 4 * print-openflow-1.0.c. 5 * 6 * [OF13] https://www.opennetworking.org/wp-content/uploads/2014/10/openflow-switch-v1.3.5.pdf 7 * 8 * Copyright (c) 2020 The TCPDUMP project 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 30 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /* \summary: OpenFlow protocol version 1.3 printer */ 35 36 #ifdef HAVE_CONFIG_H 37 #include <config.h> 38 #endif 39 40 #include "netdissect-stdinc.h" 41 42 #define ND_LONGJMP_FROM_TCHECK 43 #include "netdissect.h" 44 #include "extract.h" 45 #include "addrtoname.h" 46 #include "openflow.h" 47 48 #define OFPT_HELLO 0U 49 #define OFPT_ERROR 1U 50 #define OFPT_ECHO_REQUEST 2U 51 #define OFPT_ECHO_REPLY 3U 52 #define OFPT_EXPERIMENTER 4U 53 #define OFPT_FEATURES_REQUEST 5U 54 #define OFPT_FEATURES_REPLY 6U 55 #define OFPT_GET_CONFIG_REQUEST 7U 56 #define OFPT_GET_CONFIG_REPLY 8U 57 #define OFPT_SET_CONFIG 9U 58 #define OFPT_PACKET_IN 10U 59 #define OFPT_FLOW_REMOVED 11U 60 #define OFPT_PORT_STATUS 12U 61 #define OFPT_PACKET_OUT 13U 62 #define OFPT_FLOW_MOD 14U 63 #define OFPT_GROUP_MOD 15U 64 #define OFPT_PORT_MOD 16U 65 #define OFPT_TABLE_MOD 17U 66 #define OFPT_MULTIPART_REQUEST 18U 67 #define OFPT_MULTIPART_REPLY 19U 68 #define OFPT_BARRIER_REQUEST 20U 69 #define OFPT_BARRIER_REPLY 21U 70 #define OFPT_QUEUE_GET_CONFIG_REQUEST 22U 71 #define OFPT_QUEUE_GET_CONFIG_REPLY 23U 72 #define OFPT_ROLE_REQUEST 24U 73 #define OFPT_ROLE_REPLY 25U 74 #define OFPT_GET_ASYNC_REQUEST 26U 75 #define OFPT_GET_ASYNC_REPLY 27U 76 #define OFPT_SET_ASYNC 28U 77 #define OFPT_METER_MOD 29U 78 #define OFPT_MAX OFPT_METER_MOD 79 80 #define OFPC_FLOW_STATS (1U <<0) 81 #define OFPC_TABLE_STATS (1U <<1) 82 #define OFPC_PORT_STATS (1U <<2) 83 #define OFPC_GROUP_STATS (1U <<3) 84 #define OFPC_IP_REASM (1U <<5) 85 #define OFPC_QUEUE_STATS (1U <<6) 86 #define OFPC_PORT_BLOCKED (1U <<8) 87 static const struct tok ofp_capabilities_bm[] = { 88 { OFPC_FLOW_STATS, "FLOW_STATS" }, 89 { OFPC_TABLE_STATS, "TABLE_STATS" }, 90 { OFPC_PORT_STATS, "PORT_STATS" }, 91 { OFPC_GROUP_STATS, "GROUP_STATS" }, 92 { OFPC_IP_REASM, "IP_REASM" }, 93 { OFPC_QUEUE_STATS, "QUEUE_STATS" }, 94 { OFPC_PORT_BLOCKED, "PORT_BLOCKED" }, 95 { 0, NULL } 96 }; 97 #define OFPCAP_U (~(OFPC_FLOW_STATS | OFPC_TABLE_STATS | OFPC_PORT_STATS | \ 98 OFPC_GROUP_STATS | OFPC_IP_REASM | OFPC_QUEUE_STATS | \ 99 OFPC_PORT_BLOCKED)) 100 101 #define OFPC_FRAG_NORMAL 0U 102 #define OFPC_FRAG_DROP 1U 103 #define OFPC_FRAG_REASM 2U 104 static const struct tok ofp_config_str[] = { 105 { OFPC_FRAG_NORMAL, "FRAG_NORMAL" }, 106 { OFPC_FRAG_DROP, "FRAG_DROP" }, 107 { OFPC_FRAG_REASM, "FRAG_REASM" }, 108 { 0, NULL } 109 }; 110 111 #define OFPTT_MAX 0xfeU 112 #define OFPTT_ALL 0xffU 113 static const struct tok ofptt_str[] = { 114 { OFPTT_MAX, "MAX" }, 115 { OFPTT_ALL, "ALL" }, 116 { 0, NULL }, 117 }; 118 119 #define OFPCML_MAX 0xffe5U 120 #define OFPCML_NO_BUFFER 0xffffU 121 static const struct tok ofpcml_str[] = { 122 { OFPCML_MAX, "MAX" }, 123 { OFPCML_NO_BUFFER, "NO_BUFFER" }, 124 { 0, NULL } 125 }; 126 127 #define OFPPC_PORT_DOWN (1U <<0) 128 #define OFPPC_NO_RECV (1U <<2) 129 #define OFPPC_NO_FWD (1U <<5) 130 #define OFPPC_NO_PACKET_IN (1U <<6) 131 static const struct tok ofppc_bm[] = { 132 { OFPPC_PORT_DOWN, "PORT_DOWN" }, 133 { OFPPC_NO_RECV, "NO_RECV" }, 134 { OFPPC_NO_FWD, "NO_FWD" }, 135 { OFPPC_NO_PACKET_IN, "NO_PACKET_IN" }, 136 { 0, NULL } 137 }; 138 #define OFPPC_U (~(OFPPC_PORT_DOWN | OFPPC_NO_RECV | OFPPC_NO_FWD | \ 139 OFPPC_NO_PACKET_IN)) 140 141 #define OFPPS_LINK_DOWN (1U << 0) 142 #define OFPPS_BLOCKED (1U << 1) 143 #define OFPPS_LIVE (1U << 2) 144 static const struct tok ofpps_bm[] = { 145 { OFPPS_LINK_DOWN, "LINK_DOWN" }, 146 { OFPPS_BLOCKED, "BLOCKED" }, 147 { OFPPS_LIVE, "LIVE" }, 148 { 0, NULL } 149 }; 150 #define OFPPS_U (~(OFPPS_LINK_DOWN | OFPPS_BLOCKED | OFPPS_LIVE)) 151 152 #define OFPPF_10MB_HD (1U << 0) 153 #define OFPPF_10MB_FD (1U << 1) 154 #define OFPPF_100MB_HD (1U << 2) 155 #define OFPPF_100MB_FD (1U << 3) 156 #define OFPPF_1GB_HD (1U << 4) 157 #define OFPPF_1GB_FD (1U << 5) 158 #define OFPPF_10GB_FD (1U << 6) 159 #define OFPPF_40GB_FD (1U << 7) 160 #define OFPPF_100GB_FD (1U << 8) 161 #define OFPPF_1TB_FD (1U << 9) 162 #define OFPPF_OTHER (1U << 10) 163 #define OFPPF_COPPER (1U << 11) 164 #define OFPPF_FIBER (1U << 12) 165 #define OFPPF_AUTONEG (1U << 13) 166 #define OFPPF_PAUSE (1U << 14) 167 #define OFPPF_PAUSE_ASYM (1U << 15) 168 static const struct tok ofppf_bm[] = { 169 { OFPPF_10MB_HD, "10MB_HD" }, 170 { OFPPF_10MB_FD, "10MB_FD" }, 171 { OFPPF_100MB_HD, "100MB_HD" }, 172 { OFPPF_100MB_FD, "100MB_FD" }, 173 { OFPPF_1GB_HD, "1GB_HD" }, 174 { OFPPF_1GB_FD, "1GB_FD" }, 175 { OFPPF_10GB_FD, "10GB_FD" }, 176 { OFPPF_40GB_FD, "40GB_FD" }, 177 { OFPPF_100GB_FD, "100GB_FD" }, 178 { OFPPF_1TB_FD, "1TB_FD" }, 179 { OFPPF_OTHER, "OTHER" }, 180 { OFPPF_COPPER, "COPPER" }, 181 { OFPPF_FIBER, "FIBER" }, 182 { OFPPF_AUTONEG, "AUTONEG" }, 183 { OFPPF_PAUSE, "PAUSE" }, 184 { OFPPF_PAUSE_ASYM, "PAUSE_ASYM" }, 185 { 0, NULL } 186 }; 187 #define OFPPF_U (~(OFPPF_10MB_HD | OFPPF_10MB_FD | OFPPF_100MB_HD | \ 188 OFPPF_100MB_FD | OFPPF_1GB_HD | OFPPF_1GB_FD | \ 189 OFPPF_10GB_FD | OFPPF_40GB_FD | OFPPF_100GB_FD | \ 190 OFPPF_1TB_FD | OFPPF_OTHER | OFPPF_COPPER | OFPPF_FIBER | \ 191 OFPPF_AUTONEG | OFPPF_PAUSE | OFPPF_PAUSE_ASYM)) 192 193 #define OFPHET_VERSIONBITMAP 1U 194 static const struct tok ofphet_str[] = { 195 { OFPHET_VERSIONBITMAP, "VERSIONBITMAP" }, 196 { 0, NULL } 197 }; 198 199 #define OFPP_MAX 0xffffff00U 200 #define OFPP_IN_PORT 0xfffffff8U 201 #define OFPP_TABLE 0xfffffff9U 202 #define OFPP_NORMAL 0xfffffffaU 203 #define OFPP_FLOOD 0xfffffffbU 204 #define OFPP_ALL 0xfffffffcU 205 #define OFPP_CONTROLLER 0xfffffffdU 206 #define OFPP_LOCAL 0xfffffffeU 207 #define OFPP_ANY 0xffffffffU 208 static const struct tok ofpp_str[] = { 209 { OFPP_MAX, "MAX" }, 210 { OFPP_IN_PORT, "IN_PORT" }, 211 { OFPP_TABLE, "TABLE" }, 212 { OFPP_NORMAL, "NORMAL" }, 213 { OFPP_FLOOD, "FLOOD" }, 214 { OFPP_ALL, "ALL" }, 215 { OFPP_CONTROLLER, "CONTROLLER" }, 216 { OFPP_LOCAL, "LOCAL" }, 217 { OFPP_ANY, "ANY" }, 218 { 0, NULL } 219 }; 220 221 #define OFPCR_ROLE_NOCHANGE 0U 222 #define OFPCR_ROLE_EQUAL 1U 223 #define OFPCR_ROLE_MASTER 2U 224 #define OFPCR_ROLE_SLAVE 3U 225 static const struct tok ofpcr_str[] = { 226 { OFPCR_ROLE_NOCHANGE, "NOCHANGE" }, 227 { OFPCR_ROLE_EQUAL, "EQUAL" }, 228 { OFPCR_ROLE_MASTER, "MASTER" }, 229 { OFPCR_ROLE_SLAVE, "SLAVE" }, 230 { 0, NULL } 231 }; 232 233 #define OF_BIT_VER_1_0 (1U << (OF_VER_1_0 - 1)) 234 #define OF_BIT_VER_1_1 (1U << (OF_VER_1_1 - 1)) 235 #define OF_BIT_VER_1_2 (1U << (OF_VER_1_2 - 1)) 236 #define OF_BIT_VER_1_3 (1U << (OF_VER_1_3 - 1)) 237 #define OF_BIT_VER_1_4 (1U << (OF_VER_1_4 - 1)) 238 #define OF_BIT_VER_1_5 (1U << (OF_VER_1_5 - 1)) 239 static const struct tok ofverbm_str[] = { 240 { OF_BIT_VER_1_0, "1.0" }, 241 { OF_BIT_VER_1_1, "1.1" }, 242 { OF_BIT_VER_1_2, "1.2" }, 243 { OF_BIT_VER_1_3, "1.3" }, 244 { OF_BIT_VER_1_4, "1.4" }, 245 { OF_BIT_VER_1_5, "1.5" }, 246 { 0, NULL } 247 }; 248 #define OF_BIT_VER_U (~(OF_BIT_VER_1_0 | OF_BIT_VER_1_1 | OF_BIT_VER_1_2 | \ 249 OF_BIT_VER_1_3 | OF_BIT_VER_1_4 | OF_BIT_VER_1_5)) 250 251 #define OFPR_NO_MATCH 0U 252 #define OFPR_ACTION 1U 253 #define OFPR_INVALID_TTL 2U 254 #if 0 /* for OFPT_PACKET_IN */ 255 static const struct tok ofpr_str[] = { 256 { OFPR_NO_MATCH, "NO_MATCH" }, 257 { OFPR_ACTION, "ACTION" }, 258 { OFPR_INVALID_TTL, "OFPR_INVALID_TTL" }, 259 { 0, NULL } 260 }; 261 #endif 262 263 #define ASYNC_OFPR_NO_MATCH (1U << OFPR_NO_MATCH ) 264 #define ASYNC_OFPR_ACTION (1U << OFPR_ACTION ) 265 #define ASYNC_OFPR_INVALID_TTL (1U << OFPR_INVALID_TTL) 266 static const struct tok async_ofpr_bm[] = { 267 { ASYNC_OFPR_NO_MATCH, "NO_MATCH" }, 268 { ASYNC_OFPR_ACTION, "ACTION" }, 269 { ASYNC_OFPR_INVALID_TTL, "INVALID_TTL" }, 270 { 0, NULL } 271 }; 272 #define ASYNC_OFPR_U (~(ASYNC_OFPR_NO_MATCH | ASYNC_OFPR_ACTION | \ 273 ASYNC_OFPR_INVALID_TTL)) 274 275 #define OFPPR_ADD 0U 276 #define OFPPR_DELETE 1U 277 #define OFPPR_MODIFY 2U 278 static const struct tok ofppr_str[] = { 279 { OFPPR_ADD, "ADD" }, 280 { OFPPR_DELETE, "DELETE" }, 281 { OFPPR_MODIFY, "MODIFY" }, 282 { 0, NULL } 283 }; 284 285 #define ASYNC_OFPPR_ADD (1U << OFPPR_ADD ) 286 #define ASYNC_OFPPR_DELETE (1U << OFPPR_DELETE) 287 #define ASYNC_OFPPR_MODIFY (1U << OFPPR_MODIFY) 288 static const struct tok async_ofppr_bm[] = { 289 { ASYNC_OFPPR_ADD, "ADD" }, 290 { ASYNC_OFPPR_DELETE, "DELETE" }, 291 { ASYNC_OFPPR_MODIFY, "MODIFY" }, 292 { 0, NULL } 293 }; 294 #define ASYNC_OFPPR_U (~(ASYNC_OFPPR_ADD | ASYNC_OFPPR_DELETE | \ 295 ASYNC_OFPPR_MODIFY)) 296 297 #define OFPET_HELLO_FAILED 0U 298 #define OFPET_BAD_REQUEST 1U 299 #define OFPET_BAD_ACTION 2U 300 #define OFPET_BAD_INSTRUCTION 3U 301 #define OFPET_BAD_MATCH 4U 302 #define OFPET_FLOW_MOD_FAILED 5U 303 #define OFPET_GROUP_MOD_FAILED 6U 304 #define OFPET_PORT_MOD_FAILED 7U 305 #define OFPET_TABLE_MOD_FAILED 8U 306 #define OFPET_QUEUE_OP_FAILED 9U 307 #define OFPET_SWITCH_CONFIG_FAILED 10U 308 #define OFPET_ROLE_REQUEST_FAILED 11U 309 #define OFPET_METER_MOD_FAILED 12U 310 #define OFPET_TABLE_FEATURES_FAILED 13U 311 #define OFPET_EXPERIMENTER 0xffffU /* a special case */ 312 static const struct tok ofpet_str[] = { 313 { OFPET_HELLO_FAILED, "HELLO_FAILED" }, 314 { OFPET_BAD_REQUEST, "BAD_REQUEST" }, 315 { OFPET_BAD_ACTION, "BAD_ACTION" }, 316 { OFPET_BAD_INSTRUCTION, "BAD_INSTRUCTION" }, 317 { OFPET_BAD_MATCH, "BAD_MATCH" }, 318 { OFPET_FLOW_MOD_FAILED, "FLOW_MOD_FAILED" }, 319 { OFPET_GROUP_MOD_FAILED, "GROUP_MOD_FAILED" }, 320 { OFPET_PORT_MOD_FAILED, "PORT_MOD_FAILED" }, 321 { OFPET_TABLE_MOD_FAILED, "TABLE_MOD_FAILED" }, 322 { OFPET_QUEUE_OP_FAILED, "QUEUE_OP_FAILED" }, 323 { OFPET_SWITCH_CONFIG_FAILED, "SWITCH_CONFIG_FAILED" }, 324 { OFPET_ROLE_REQUEST_FAILED, "ROLE_REQUEST_FAILED" }, 325 { OFPET_METER_MOD_FAILED, "METER_MOD_FAILED" }, 326 { OFPET_TABLE_FEATURES_FAILED, "TABLE_FEATURES_FAILED" }, 327 { OFPET_EXPERIMENTER, "EXPERIMENTER" }, 328 { 0, NULL } 329 }; 330 331 #define OFPHFC_INCOMPATIBLE 0U 332 #define OFPHFC_EPERM 1U 333 static const struct tok ofphfc_str[] = { 334 { OFPHFC_INCOMPATIBLE, "INCOMPATIBLE" }, 335 { OFPHFC_EPERM, "EPERM" }, 336 { 0, NULL } 337 }; 338 339 #define OFPBRC_BAD_VERSION 0U 340 #define OFPBRC_BAD_TYPE 1U 341 #define OFPBRC_BAD_MULTIPART 2U 342 #define OFPBRC_BAD_EXPERIMENTER 3U 343 #define OFPBRC_BAD_EXP_TYPE 4U 344 #define OFPBRC_EPERM 5U 345 #define OFPBRC_BAD_LEN 6U 346 #define OFPBRC_BUFFER_EMPTY 7U 347 #define OFPBRC_BUFFER_UNKNOWN 8U 348 #define OFPBRC_BAD_TABLE_ID 9U 349 #define OFPBRC_IS_SLAVE 10U 350 #define OFPBRC_BAD_PORT 11U 351 #define OFPBRC_BAD_PACKET 12U 352 #define OFPBRC_MULTIPART_BUFFER_OVERFLOW 13U 353 static const struct tok ofpbrc_str[] = { 354 { OFPBRC_BAD_VERSION, "BAD_VERSION" }, 355 { OFPBRC_BAD_TYPE, "BAD_TYPE" }, 356 { OFPBRC_BAD_MULTIPART, "BAD_MULTIPART" }, 357 { OFPBRC_BAD_EXPERIMENTER, "BAD_EXPERIMENTER" }, 358 { OFPBRC_BAD_EXP_TYPE, "BAD_EXP_TYPE" }, 359 { OFPBRC_EPERM, "EPERM" }, 360 { OFPBRC_BAD_LEN, "BAD_LEN" }, 361 { OFPBRC_BUFFER_EMPTY, "BUFFER_EMPTY" }, 362 { OFPBRC_BUFFER_UNKNOWN, "BUFFER_UNKNOWN" }, 363 { OFPBRC_BAD_TABLE_ID, "BAD_TABLE_ID" }, 364 { OFPBRC_IS_SLAVE, "IS_SLAVE" }, 365 { OFPBRC_BAD_PORT, "BAD_PORT" }, 366 { OFPBRC_BAD_PACKET, "BAD_PACKET" }, 367 { OFPBRC_MULTIPART_BUFFER_OVERFLOW, "MULTIPART_BUFFER_OVERFLOW" }, 368 { 0, NULL } 369 }; 370 371 #define OFPBAC_BAD_TYPE 0U 372 #define OFPBAC_BAD_LEN 1U 373 #define OFPBAC_BAD_EXPERIMENTER 2U 374 #define OFPBAC_BAD_EXP_TYPE 3U 375 #define OFPBAC_BAD_OUT_PORT 4U 376 #define OFPBAC_BAD_ARGUMENT 5U 377 #define OFPBAC_EPERM 6U 378 #define OFPBAC_TOO_MANY 7U 379 #define OFPBAC_BAD_QUEUE 8U 380 #define OFPBAC_BAD_OUT_GROUP 9U 381 #define OFPBAC_MATCH_INCONSISTENT 10U 382 #define OFPBAC_UNSUPPORTED_ORDER 11U 383 #define OFPBAC_BAD_TAG 12U 384 #define OFPBAC_BAD_SET_TYPE 13U 385 #define OFPBAC_BAD_SET_LEN 14U 386 #define OFPBAC_BAD_SET_ARGUMENT 15U 387 static const struct tok ofpbac_str[] = { 388 { OFPBAC_BAD_TYPE, "BAD_TYPE" }, 389 { OFPBAC_BAD_LEN, "BAD_LEN" }, 390 { OFPBAC_BAD_EXPERIMENTER, "BAD_EXPERIMENTER" }, 391 { OFPBAC_BAD_EXP_TYPE, "BAD_EXP_TYPE" }, 392 { OFPBAC_BAD_OUT_PORT, "BAD_OUT_PORT" }, 393 { OFPBAC_BAD_ARGUMENT, "BAD_ARGUMENT" }, 394 { OFPBAC_EPERM, "EPERM" }, 395 { OFPBAC_TOO_MANY, "TOO_MANY" }, 396 { OFPBAC_BAD_QUEUE, "BAD_QUEUE" }, 397 { OFPBAC_BAD_OUT_GROUP, "BAD_OUT_GROUP" }, 398 { OFPBAC_MATCH_INCONSISTENT, "MATCH_INCONSISTENT" }, 399 { OFPBAC_UNSUPPORTED_ORDER, "UNSUPPORTED_ORDER" }, 400 { OFPBAC_BAD_TAG, "BAD_TAG" }, 401 { OFPBAC_BAD_SET_TYPE, "BAD_SET_TYPE" }, 402 { OFPBAC_BAD_SET_LEN, "BAD_SET_LEN" }, 403 { OFPBAC_BAD_SET_ARGUMENT, "BAD_SET_ARGUMENT" }, 404 { 0, NULL } 405 }; 406 407 #define OFPBIC_UNKNOWN_INST 0U 408 #define OFPBIC_UNSUP_INST 1U 409 #define OFPBIC_BAD_TABLE_ID 2U 410 #define OFPBIC_UNSUP_METADATA 3U 411 #define OFPBIC_UNSUP_METADATA_MASK 4U 412 #define OFPBIC_BAD_EXPERIMENTER 5U 413 #define OFPBIC_BAD_EXP_TYPE 6U 414 #define OFPBIC_BAD_LEN 7U 415 #define OFPBIC_EPERM 8U 416 static const struct tok ofpbic_str[] = { 417 { OFPBIC_UNKNOWN_INST, "UNKNOWN_INST" }, 418 { OFPBIC_UNSUP_INST, "UNSUP_INST" }, 419 { OFPBIC_BAD_TABLE_ID, "BAD_TABLE_ID" }, 420 { OFPBIC_UNSUP_METADATA, "UNSUP_METADATA" }, 421 { OFPBIC_UNSUP_METADATA_MASK, "UNSUP_METADATA_MASK" }, 422 { OFPBIC_BAD_EXPERIMENTER, "BAD_EXPERIMENTER" }, 423 { OFPBIC_BAD_EXP_TYPE, "BAD_EXP_TYPE" }, 424 { OFPBIC_BAD_LEN, "BAD_LEN" }, 425 { OFPBIC_EPERM, "EPERM" }, 426 { 0, NULL } 427 }; 428 429 #define OFPBMC_BAD_TYPE 0U 430 #define OFPBMC_BAD_LEN 1U 431 #define OFPBMC_BAD_TAG 2U 432 #define OFPBMC_BAD_DL_ADDR_MASK 3U 433 #define OFPBMC_BAD_NW_ADDR_MASK 4U 434 #define OFPBMC_BAD_WILDCARDS 5U 435 #define OFPBMC_BAD_FIELD 6U 436 #define OFPBMC_BAD_VALUE 7U 437 #define OFPBMC_BAD_MASK 8U 438 #define OFPBMC_BAD_PREREQ 9U 439 #define OFPBMC_DUP_FIELD 10U 440 #define OFPBMC_EPERM 11U 441 static const struct tok ofpbmc_str[] = { 442 { OFPBMC_BAD_TYPE, "BAD_TYPE" }, 443 { OFPBMC_BAD_LEN, "BAD_LEN" }, 444 { OFPBMC_BAD_TAG, "BAD_TAG" }, 445 { OFPBMC_BAD_DL_ADDR_MASK, "BAD_DL_ADDR_MASK" }, 446 { OFPBMC_BAD_NW_ADDR_MASK, "BAD_NW_ADDR_MASK" }, 447 { OFPBMC_BAD_WILDCARDS, "BAD_WILDCARDS" }, 448 { OFPBMC_BAD_FIELD, "BAD_FIELD" }, 449 { OFPBMC_BAD_VALUE, "BAD_VALUE" }, 450 { OFPBMC_BAD_MASK, "BAD_MASK" }, 451 { OFPBMC_BAD_PREREQ, "BAD_PREREQ" }, 452 { OFPBMC_DUP_FIELD, "DUP_FIELD" }, 453 { OFPBMC_EPERM, "EPERM" }, 454 { 0, NULL } 455 }; 456 457 #define OFPFMFC_UNKNOWN 0U 458 #define OFPFMFC_TABLE_FULL 1U 459 #define OFPFMFC_BAD_TABLE_ID 2U 460 #define OFPFMFC_OVERLAP 3U 461 #define OFPFMFC_EPERM 4U 462 #define OFPFMFC_BAD_TIMEOUT 5U 463 #define OFPFMFC_BAD_COMMAND 6U 464 #define OFPFMFC_BAD_FLAGS 7U 465 static const struct tok ofpfmfc_str[] = { 466 { OFPFMFC_UNKNOWN, "UNKNOWN" }, 467 { OFPFMFC_TABLE_FULL, "TABLE_FULL" }, 468 { OFPFMFC_BAD_TABLE_ID, "BAD_TABLE_ID" }, 469 { OFPFMFC_OVERLAP, "OVERLAP" }, 470 { OFPFMFC_EPERM, "EPERM" }, 471 { OFPFMFC_BAD_TIMEOUT, "BAD_TIMEOUT" }, 472 { OFPFMFC_BAD_COMMAND, "BAD_COMMAND" }, 473 { OFPFMFC_BAD_FLAGS, "BAD_FLAGS" }, 474 { 0, NULL } 475 }; 476 477 #define OFPGMFC_GROUP_EXISTS 0U 478 #define OFPGMFC_INVALID_GROUP 1U 479 #define OFPGMFC_WEIGHT_UNSUPPORTED 2U 480 #define OFPGMFC_OUT_OF_GROUPS 3U 481 #define OFPGMFC_OUT_OF_BUCKETS 4U 482 #define OFPGMFC_CHAINING_UNSUPPORTED 5U 483 #define OFPGMFC_WATCH_UNSUPPORTED 6U 484 #define OFPGMFC_LOOP 7U 485 #define OFPGMFC_UNKNOWN_GROUP 8U 486 #define OFPGMFC_CHAINED_GROUP 9U 487 #define OFPGMFC_BAD_TYPE 10U 488 #define OFPGMFC_BAD_COMMAND 11U 489 #define OFPGMFC_BAD_BUCKET 12U 490 #define OFPGMFC_BAD_MATCH 13U 491 #define OFPGMFC_EPERM 14U 492 static const struct tok ofpgmfc_str[] = { 493 { OFPGMFC_GROUP_EXISTS, "GROUP_EXISTS" }, 494 { OFPGMFC_INVALID_GROUP, "INVALID_GROUP" }, 495 { OFPGMFC_WEIGHT_UNSUPPORTED, "WEIGHT_UNSUPPORTED" }, 496 { OFPGMFC_OUT_OF_GROUPS, "OUT_OF_GROUPS" }, 497 { OFPGMFC_OUT_OF_BUCKETS, "OUT_OF_BUCKETS" }, 498 { OFPGMFC_CHAINING_UNSUPPORTED, "CHAINING_UNSUPPORTED" }, 499 { OFPGMFC_WATCH_UNSUPPORTED, "WATCH_UNSUPPORTED" }, 500 { OFPGMFC_LOOP, "LOOP" }, 501 { OFPGMFC_UNKNOWN_GROUP, "UNKNOWN_GROUP" }, 502 { OFPGMFC_CHAINED_GROUP, "CHAINED_GROUP" }, 503 { OFPGMFC_BAD_TYPE, "BAD_TYPE" }, 504 { OFPGMFC_BAD_COMMAND, "BAD_COMMAND" }, 505 { OFPGMFC_BAD_BUCKET, "BAD_BUCKET" }, 506 { OFPGMFC_BAD_MATCH, "BAD_MATCH" }, 507 { OFPGMFC_EPERM, "EPERM" }, 508 { 0, NULL } 509 }; 510 511 #define OFPPMFC_BAD_PORT 0U 512 #define OFPPMFC_BAD_HW_ADDR 1U 513 #define OFPPMFC_BAD_CONFIG 2U 514 #define OFPPMFC_BAD_ADVERTISE 3U 515 #define OFPPMFC_EPERM 4U 516 static const struct tok ofppmfc_str[] = { 517 { OFPPMFC_BAD_PORT, "BAD_PORT" }, 518 { OFPPMFC_BAD_HW_ADDR, "BAD_HW_ADDR" }, 519 { OFPPMFC_BAD_CONFIG, "BAD_CONFIG" }, 520 { OFPPMFC_BAD_ADVERTISE, "BAD_ADVERTISE" }, 521 { OFPPMFC_EPERM, "EPERM" }, 522 { 0, NULL } 523 }; 524 525 #define OFPTMFC_BAD_TABLE 0U 526 #define OFPTMFC_BAD_CONFIG 1U 527 #define OFPTMFC_EPERM 2U 528 static const struct tok ofptmfc_str[] = { 529 { OFPTMFC_BAD_TABLE, "BAD_TABLE" }, 530 { OFPTMFC_BAD_CONFIG, "BAD_CONFIG" }, 531 { OFPTMFC_EPERM, "EPERM" }, 532 { 0, NULL } 533 }; 534 535 #define OFPQOFC_BAD_PORT 0U 536 #define OFPQOFC_BAD_QUEUE 1U 537 #define OFPQOFC_EPERM 2U 538 static const struct tok ofpqofc_str[] = { 539 { OFPQOFC_BAD_PORT, "BAD_PORT" }, 540 { OFPQOFC_BAD_QUEUE, "BAD_QUEUE" }, 541 { OFPQOFC_EPERM, "EPERM" }, 542 { 0, NULL } 543 }; 544 545 #define OFPSCFC_BAD_FLAGS 0U 546 #define OFPSCFC_BAD_LEN 1U 547 #define OFPSCFC_EPERM 2U 548 static const struct tok ofpscfc_str[] = { 549 { OFPSCFC_BAD_FLAGS, "BAD_FLAGS" }, 550 { OFPSCFC_BAD_LEN, "BAD_LEN" }, 551 { OFPSCFC_EPERM, "EPERM" }, 552 { 0, NULL } 553 }; 554 555 #define OFPRRFC_STALE 0U 556 #define OFPRRFC_UNSUP 1U 557 #define OFPRRFC_BAD_ROLE 2U 558 static const struct tok ofprrfc_str[] = { 559 { OFPRRFC_STALE, "STALE" }, 560 { OFPRRFC_UNSUP, "UNSUP" }, 561 { OFPRRFC_BAD_ROLE, "BAD_ROLE" }, 562 { 0, NULL } 563 }; 564 565 #define OFPMMFC_UNKNOWN 0U 566 #define OFPMMFC_METER_EXISTS 1U 567 #define OFPMMFC_INVALID_METER 2U 568 #define OFPMMFC_UNKNOWN_METER 3U 569 #define OFPMMFC_BAD_COMMAND 4U 570 #define OFPMMFC_BAD_FLAGS 5U 571 #define OFPMMFC_BAD_RATE 6U 572 #define OFPMMFC_BAD_BURST 7U 573 #define OFPMMFC_BAD_BAND 8U 574 #define OFPMMFC_BAD_BAND_VALUE 9U 575 #define OFPMMFC_OUT_OF_METERS 10U 576 #define OFPMMFC_OUT_OF_BANDS 11U 577 static const struct tok ofpmmfc_str[] = { 578 { OFPMMFC_UNKNOWN, "UNKNOWN" }, 579 { OFPMMFC_METER_EXISTS, "METER_EXISTS" }, 580 { OFPMMFC_INVALID_METER, "INVALID_METER" }, 581 { OFPMMFC_UNKNOWN_METER, "UNKNOWN_METER" }, 582 { OFPMMFC_BAD_COMMAND, "BAD_COMMAND" }, 583 { OFPMMFC_BAD_FLAGS, "BAD_FLAGS" }, 584 { OFPMMFC_BAD_RATE, "BAD_RATE" }, 585 { OFPMMFC_BAD_BURST, "BAD_BURST" }, 586 { OFPMMFC_BAD_BAND, "BAD_BAND" }, 587 { OFPMMFC_BAD_BAND_VALUE, "BAD_BAND_VALUE" }, 588 { OFPMMFC_OUT_OF_METERS, "OUT_OF_METERS" }, 589 { OFPMMFC_OUT_OF_BANDS, "OUT_OF_BANDS" }, 590 { 0, NULL } 591 }; 592 593 #define OFPTFFC_BAD_TABLE 0U 594 #define OFPTFFC_BAD_METADATA 1U 595 #define OFPTFFC_BAD_TYPE 2U 596 #define OFPTFFC_BAD_LEN 3U 597 #define OFPTFFC_BAD_ARGUMENT 4U 598 #define OFPTFFC_EPERM 5U 599 static const struct tok ofptffc_str[] = { 600 { OFPTFFC_BAD_TABLE, "BAD_TABLE" }, 601 { OFPTFFC_BAD_METADATA, "BAD_METADATA" }, 602 { OFPTFFC_BAD_TYPE, "BAD_TYPE" }, 603 { OFPTFFC_BAD_LEN, "BAD_LEN" }, 604 { OFPTFFC_BAD_ARGUMENT, "BAD_ARGUMENT" }, 605 { OFPTFFC_EPERM, "EPERM" }, 606 { 0, NULL } 607 }; 608 609 static const struct uint_tokary of13_ofpet2tokary[] = { 610 { OFPET_HELLO_FAILED, ofphfc_str }, 611 { OFPET_BAD_REQUEST, ofpbrc_str }, 612 { OFPET_BAD_ACTION, ofpbac_str }, 613 { OFPET_BAD_INSTRUCTION, ofpbic_str }, 614 { OFPET_BAD_MATCH, ofpbmc_str }, 615 { OFPET_FLOW_MOD_FAILED, ofpfmfc_str }, 616 { OFPET_GROUP_MOD_FAILED, ofpgmfc_str }, 617 { OFPET_PORT_MOD_FAILED, ofppmfc_str }, 618 { OFPET_TABLE_MOD_FAILED, ofptmfc_str }, 619 { OFPET_QUEUE_OP_FAILED, ofpqofc_str }, 620 { OFPET_SWITCH_CONFIG_FAILED, ofpscfc_str }, 621 { OFPET_ROLE_REQUEST_FAILED, ofprrfc_str }, 622 { OFPET_METER_MOD_FAILED, ofpmmfc_str }, 623 { OFPET_TABLE_FEATURES_FAILED, ofptffc_str }, 624 { OFPET_EXPERIMENTER, NULL }, /* defines no codes */ 625 /* uint2tokary() does not use array termination. */ 626 }; 627 628 /* lengths (fixed or minimal) of particular message types, where not 0 */ 629 #define OF_ERROR_MSG_MINLEN (12U - OF_HEADER_FIXLEN) 630 #define OF_FEATURES_REPLY_FIXLEN (32U - OF_HEADER_FIXLEN) 631 #define OF_PORT_MOD_FIXLEN (40U - OF_HEADER_FIXLEN) 632 #define OF_SWITCH_CONFIG_MSG_FIXLEN (12U - OF_HEADER_FIXLEN) 633 #define OF_TABLE_MOD_FIXLEN (16U - OF_HEADER_FIXLEN) 634 #define OF_QUEUE_GET_CONFIG_REQUEST_FIXLEN (16U - OF_HEADER_FIXLEN) 635 #define OF_ROLE_MSG_FIXLEN (24U - OF_HEADER_FIXLEN) 636 #define OF_ASYNC_MSG_FIXLEN (32U - OF_HEADER_FIXLEN) 637 #define OF_PORT_STATUS_FIXLEN (80U - OF_HEADER_FIXLEN) 638 #define OF_EXPERIMENTER_MSG_MINLEN (16U - OF_HEADER_FIXLEN) 639 640 /* lengths (fixed or minimal) of particular protocol structures */ 641 #define OF_HELLO_ELEM_MINSIZE 4U 642 643 /* miscellaneous constants from [OF13] */ 644 #define OFP_MAX_PORT_NAME_LEN 16U 645 646 /* [OF13] Section 7.2.1 */ 647 static void 648 of13_port_print(netdissect_options *ndo, 649 const u_char *cp) 650 { 651 /* port_no */ 652 ND_PRINT("\n\t port_no %s", 653 tok2str(ofpp_str, "%u", GET_BE_U_4(cp))); 654 cp += 4; 655 /* pad */ 656 cp += 4; 657 /* hw_addr */ 658 ND_PRINT(", hw_addr %s", GET_ETHERADDR_STRING(cp)); 659 cp += MAC_ADDR_LEN; 660 /* pad2 */ 661 cp += 2; 662 /* name */ 663 ND_PRINT(", name '"); 664 nd_printjnp(ndo, cp, OFP_MAX_PORT_NAME_LEN); 665 ND_PRINT("'"); 666 cp += OFP_MAX_PORT_NAME_LEN; 667 668 if (ndo->ndo_vflag < 2) { 669 ND_TCHECK_LEN(cp, 32); 670 return; 671 } 672 673 /* config */ 674 ND_PRINT("\n\t config 0x%08x", GET_BE_U_4(cp)); 675 of_bitmap_print(ndo, ofppc_bm, GET_BE_U_4(cp), OFPPC_U); 676 cp += 4; 677 /* state */ 678 ND_PRINT("\n\t state 0x%08x", GET_BE_U_4(cp)); 679 of_bitmap_print(ndo, ofpps_bm, GET_BE_U_4(cp), OFPPS_U);; 680 cp += 4; 681 /* curr */ 682 ND_PRINT("\n\t curr 0x%08x", GET_BE_U_4(cp)); 683 of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U); 684 cp += 4; 685 /* advertised */ 686 ND_PRINT("\n\t advertised 0x%08x", GET_BE_U_4(cp)); 687 of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U); 688 cp += 4; 689 /* supported */ 690 ND_PRINT("\n\t supported 0x%08x", GET_BE_U_4(cp)); 691 of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U); 692 cp += 4; 693 /* peer */ 694 ND_PRINT("\n\t peer 0x%08x", GET_BE_U_4(cp)); 695 of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U); 696 cp += 4; 697 /* curr_speed */ 698 ND_PRINT("\n\t curr_speed %ukbps", GET_BE_U_4(cp)); 699 cp += 4; 700 /* max_speed */ 701 ND_PRINT("\n\t max_speed %ukbps", GET_BE_U_4(cp)); 702 } 703 704 /* [OF13] Section 7.3.1 */ 705 static void 706 of13_features_reply_print(netdissect_options *ndo, 707 const u_char *cp, u_int len _U_) 708 { 709 /* datapath_id */ 710 ND_PRINT("\n\t dpid 0x%016" PRIx64, GET_BE_U_8(cp)); 711 cp += 8; 712 /* n_buffers */ 713 ND_PRINT(", n_buffers %u", GET_BE_U_4(cp)); 714 cp += 4; 715 /* n_tables */ 716 ND_PRINT(", n_tables %u", GET_U_1(cp)); 717 cp += 1; 718 /* auxiliary_id */ 719 ND_PRINT(", auxiliary_id %u", GET_U_1(cp)); 720 cp += 1; 721 /* pad */ 722 cp += 2; 723 /* capabilities */ 724 ND_PRINT("\n\t capabilities 0x%08x", GET_BE_U_4(cp)); 725 of_bitmap_print(ndo, ofp_capabilities_bm, GET_BE_U_4(cp), OFPCAP_U); 726 cp += 4; 727 /* reserved */ 728 ND_TCHECK_4(cp); 729 } 730 731 /* [OF13] Section 7.3.2 */ 732 static void 733 of13_switch_config_msg_print(netdissect_options *ndo, 734 const u_char *cp, u_int len _U_) 735 { 736 /* flags */ 737 ND_PRINT("\n\t flags %s", 738 tok2str(ofp_config_str, "invalid (0x%04x)", GET_BE_U_2(cp))); 739 cp += 2; 740 /* miss_send_len */ 741 ND_PRINT(", miss_send_len %s", 742 tok2str(ofpcml_str, "%u", GET_BE_U_2(cp))); 743 } 744 745 /* [OF13] Section 7.3.3 */ 746 static void 747 of13_table_mod_print(netdissect_options *ndo, 748 const u_char *cp, u_int len _U_) 749 { 750 /* table_id */ 751 ND_PRINT("\n\t table_id %s", tok2str(ofptt_str, "%u", GET_U_1(cp))); 752 cp += 1; 753 /* pad */ 754 cp += 3; 755 /* config */ 756 ND_PRINT(", config 0x%08x", GET_BE_U_4(cp)); 757 } 758 759 /* [OF13] Section 7.3.9 */ 760 static void 761 of13_role_msg_print(netdissect_options *ndo, 762 const u_char *cp, u_int len _U_) 763 { 764 /* role */ 765 ND_PRINT("\n\t role %s", 766 tok2str(ofpcr_str, "invalid (0x%08x)", GET_BE_U_4(cp))); 767 cp += 4; 768 /* pad */ 769 cp += 4; 770 /* generation_id */ 771 ND_PRINT(", generation_id 0x%016" PRIx64, GET_BE_U_8(cp)); 772 } 773 774 /* [OF13] Section 7.3.10 */ 775 static void 776 of13_async_msg_print(netdissect_options *ndo, 777 const u_char *cp, u_int len _U_) 778 { 779 /* packet_in_mask[0] */ 780 ND_PRINT("\n\t packet_in_mask[EM] 0x%08x", GET_BE_U_4(cp)); 781 of_bitmap_print(ndo, async_ofpr_bm, GET_BE_U_4(cp), ASYNC_OFPR_U); 782 cp += 4; 783 /* packet_in_mask[1] */ 784 ND_PRINT("\n\t packet_in_mask[S] 0x%08x", GET_BE_U_4(cp)); 785 of_bitmap_print(ndo, async_ofpr_bm, GET_BE_U_4(cp), ASYNC_OFPR_U); 786 cp += 4; 787 /* port_status_mask[0] */ 788 ND_PRINT("\n\t port_status_mask[EM] 0x%08x", GET_BE_U_4(cp)); 789 of_bitmap_print(ndo, async_ofppr_bm, GET_BE_U_4(cp), ASYNC_OFPPR_U); 790 cp += 4; 791 /* port_status_mask[1] */ 792 ND_PRINT("\n\t port_status_mask[S] 0x%08x", GET_BE_U_4(cp)); 793 of_bitmap_print(ndo, async_ofppr_bm, GET_BE_U_4(cp), ASYNC_OFPPR_U); 794 cp += 4; 795 /* flow_removed_mask[0] */ 796 ND_PRINT("\n\t flow_removed_mask[EM] 0x%08x", GET_BE_U_4(cp)); 797 of_bitmap_print(ndo, async_ofppr_bm, GET_BE_U_4(cp), ASYNC_OFPPR_U); 798 cp += 4; 799 /* flow_removed_mask[1] */ 800 ND_PRINT("\n\t flow_removed_mask[S] 0x%08x", GET_BE_U_4(cp)); 801 of_bitmap_print(ndo, async_ofppr_bm, GET_BE_U_4(cp), ASYNC_OFPPR_U); 802 } 803 804 /* [OF13] Section 7.3.4.3 */ 805 static void 806 of13_port_mod_print(netdissect_options *ndo, 807 const u_char *cp, u_int len _U_) 808 { 809 /* port_no */ 810 ND_PRINT("\n\t port_no %s", tok2str(ofpp_str, "%u", GET_BE_U_4(cp))); 811 cp += 4; 812 /* pad */ 813 cp += 4; 814 /* hw_addr */ 815 ND_PRINT(", hw_addr %s", GET_ETHERADDR_STRING(cp)); 816 cp += MAC_ADDR_LEN; 817 /* pad2 */ 818 cp += 2; 819 /* config */ 820 ND_PRINT("\n\t config 0x%08x", GET_BE_U_4(cp)); 821 of_bitmap_print(ndo, ofppc_bm, GET_BE_U_4(cp), OFPPC_U); 822 cp += 4; 823 /* mask */ 824 ND_PRINT("\n\t mask 0x%08x", GET_BE_U_4(cp)); 825 of_bitmap_print(ndo, ofppc_bm, GET_BE_U_4(cp), OFPPC_U); 826 cp += 4; 827 /* advertise */ 828 ND_PRINT("\n\t advertise 0x%08x", GET_BE_U_4(cp)); 829 of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U); 830 cp += 4; 831 /* pad3 */ 832 /* Always the last field, check bounds. */ 833 ND_TCHECK_4(cp); 834 } 835 836 /* [OF13] Section 7.4.3 */ 837 static void 838 of13_port_status_print(netdissect_options *ndo, 839 const u_char *cp, u_int len _U_) 840 { 841 /* reason */ 842 ND_PRINT("\n\t reason %s", 843 tok2str(ofppr_str, "invalid (0x02x)", GET_U_1(cp))); 844 cp += 1; 845 /* pad */ 846 cp += 7; 847 /* desc */ 848 of13_port_print(ndo, cp); 849 } 850 851 /* [OF13] Section 7.5.1 */ 852 static void 853 of13_hello_elements_print(netdissect_options *ndo, 854 const u_char *cp, u_int len) 855 { 856 while (len) { 857 uint16_t type, bmlen; 858 859 if (len < OF_HELLO_ELEM_MINSIZE) 860 goto invalid; 861 /* type */ 862 type = GET_BE_U_2(cp); 863 OF_FWD(2); 864 ND_PRINT("\n\t type %s", 865 tok2str(ofphet_str, "unknown (0x%04x)", type)); 866 /* length */ 867 bmlen = GET_BE_U_2(cp); 868 OF_FWD(2); 869 ND_PRINT(", length %u", bmlen); 870 /* cp is OF_HELLO_ELEM_MINSIZE bytes in */ 871 if (bmlen < OF_HELLO_ELEM_MINSIZE || 872 bmlen > OF_HELLO_ELEM_MINSIZE + len) 873 goto invalid; 874 switch (type) { 875 case OFPHET_VERSIONBITMAP: 876 /* 877 * The specification obviously overprovisions the space 878 * for version bitmaps in this element ("ofp versions 879 * 32 to 63 are encoded in the second bitmap and so 880 * on"). Keep this code simple for now and recognize 881 * only a single bitmap with no padding. 882 */ 883 if (bmlen == OF_HELLO_ELEM_MINSIZE + 4) { 884 uint32_t bitmap = GET_BE_U_4(cp); 885 ND_PRINT(", bitmap 0x%08x", bitmap); 886 of_bitmap_print(ndo, ofverbm_str, bitmap, 887 OF_BIT_VER_U); 888 } else { 889 ND_PRINT(" (bogus)"); 890 ND_TCHECK_LEN(cp, bmlen - OF_HELLO_ELEM_MINSIZE); 891 } 892 break; 893 default: 894 ND_TCHECK_LEN(cp, bmlen - OF_HELLO_ELEM_MINSIZE); 895 } 896 OF_FWD(bmlen - OF_HELLO_ELEM_MINSIZE); 897 } 898 return; 899 900 invalid: 901 nd_print_invalid(ndo); 902 ND_TCHECK_LEN(cp, len); 903 } 904 905 /* [OF13] Section 7.5.4 */ 906 static void 907 of13_experimenter_message_print(netdissect_options *ndo, 908 const u_char *cp, u_int len) 909 { 910 uint32_t experimenter; 911 912 /* experimenter */ 913 experimenter = GET_BE_U_4(cp); 914 OF_FWD(4); 915 ND_PRINT("\n\t experimenter 0x%08x (%s)", experimenter, 916 of_vendor_name(experimenter)); 917 /* exp_type */ 918 ND_PRINT(", exp_type 0x%08x", GET_BE_U_4(cp)); 919 OF_FWD(4); 920 /* data */ 921 of_data_print(ndo, cp, len); 922 } 923 924 /* [OF13] Section 7.3.6 */ 925 static void 926 of13_queue_get_config_request_print(netdissect_options *ndo, 927 const u_char *cp, u_int len _U_) 928 { 929 /* port */ 930 ND_PRINT("\n\t port %s", tok2str(ofpp_str, "%u", GET_BE_U_4(cp))); 931 cp += 4; 932 /* pad */ 933 /* Always the last field, check bounds. */ 934 ND_TCHECK_4(cp); 935 } 936 937 /* [OF13] Section 7.4.4 */ 938 static void 939 of13_error_print(netdissect_options *ndo, 940 const u_char *cp, u_int len) 941 { 942 uint16_t type, code; 943 const struct tok *code_str; 944 945 /* type */ 946 type = GET_BE_U_2(cp); 947 OF_FWD(2); 948 ND_PRINT("\n\t type %s", tok2str(ofpet_str, "invalid (0x%04x)", type)); 949 /* code */ 950 code = GET_BE_U_2(cp); 951 OF_FWD(2); 952 code_str = uint2tokary(of13_ofpet2tokary, type); 953 if (code_str != NULL) 954 ND_PRINT(", code %s", 955 tok2str(code_str, "invalid (0x%04x)", code)); 956 else 957 ND_PRINT(", code invalid (0x%04x)", code); 958 /* data */ 959 of_data_print(ndo, cp, len); 960 } 961 962 static const struct of_msgtypeinfo of13_msgtypeinfo[OFPT_MAX + 1] = { 963 /* 964 * [OF13] Section 7.5.1 965 * n * variable-size data units. 966 */ 967 { 968 "HELLO", of13_hello_elements_print, 969 REQ_MINLEN, 0 970 }, 971 /* 972 * [OF13] Section 7.4.4 973 * A fixed-size message body and variable-size data. 974 */ 975 { 976 "ERROR", of13_error_print, 977 REQ_MINLEN, OF_ERROR_MSG_MINLEN 978 }, 979 /* 980 * [OF13] Section 7.5.2 981 * Variable-size data. 982 */ 983 { 984 "ECHO_REQUEST", of_data_print, 985 REQ_MINLEN, 0 986 }, 987 /* 988 * [OF13] Section 7.5.3 989 * Variable-size data. 990 */ 991 { 992 "ECHO_REPLY", of_data_print, 993 REQ_MINLEN, 0 994 }, 995 /* 996 * [OF13] Section 7.5.4 997 * A fixed-size message body and variable-size data. 998 */ 999 { 1000 "EXPERIMENTER", of13_experimenter_message_print, 1001 REQ_MINLEN, OF_EXPERIMENTER_MSG_MINLEN 1002 }, 1003 /* 1004 * [OF13] Section 7.3.1 1005 * No message body. 1006 */ 1007 { 1008 "FEATURES_REQUEST", NULL, 1009 REQ_FIXLEN, 0 1010 }, 1011 /* 1012 * [OF13] Section 7.3.1 1013 * A fixed-size message body. 1014 */ 1015 { 1016 "FEATURES_REPLY", of13_features_reply_print, 1017 REQ_FIXLEN, OF_FEATURES_REPLY_FIXLEN 1018 }, 1019 /* 1020 * [OF13] Section 7.3.2 1021 * No message body. 1022 */ 1023 { 1024 "GET_CONFIG_REQUEST", NULL, 1025 REQ_FIXLEN, 0 1026 }, 1027 /* 1028 * [OF13] Section 7.3.2 1029 * A fixed-size message body. 1030 */ 1031 { 1032 "GET_CONFIG_REPLY", of13_switch_config_msg_print, 1033 REQ_FIXLEN, OF_SWITCH_CONFIG_MSG_FIXLEN 1034 }, 1035 /* 1036 * [OF13] Section 7.3.2 1037 * A fixed-size message body. 1038 */ 1039 { 1040 "SET_CONFIG", of13_switch_config_msg_print, 1041 REQ_FIXLEN, OF_SWITCH_CONFIG_MSG_FIXLEN 1042 }, 1043 /* 1044 * [OF13] Section 7.4.1 1045 * (to be done) 1046 */ 1047 { 1048 "PACKET_IN", NULL, 1049 REQ_NONE, 0 1050 }, 1051 /* 1052 * [OF13] Section 7.4.2 1053 * (to be done) 1054 */ 1055 { 1056 "FLOW_REMOVED", NULL, 1057 REQ_NONE, 0 1058 }, 1059 /* 1060 * [OF13] Section 7.4.3 1061 * A fixed-size message body. 1062 */ 1063 { 1064 "PORT_STATUS", of13_port_status_print, 1065 REQ_FIXLEN, OF_PORT_STATUS_FIXLEN 1066 }, 1067 /* 1068 * [OF13] Section 7.3.7 1069 * (to be done) 1070 */ 1071 { 1072 "PACKET_OUT", NULL, 1073 REQ_NONE, 0 1074 }, 1075 /* 1076 * [OF13] Section 7.3.4.1 1077 * (to be done) 1078 */ 1079 { 1080 "FLOW_MOD", NULL, 1081 REQ_NONE, 0 1082 }, 1083 /* 1084 * [OF13] Section 7.3.4.2 1085 * (to be done) 1086 */ 1087 { 1088 "GROUP_MOD", NULL, 1089 REQ_NONE, 0 1090 }, 1091 /* 1092 * [OF13] Section 7.3.4.3 1093 * A fixed-size message body. 1094 */ 1095 { 1096 "PORT_MOD", of13_port_mod_print, 1097 REQ_FIXLEN, OF_PORT_MOD_FIXLEN 1098 }, 1099 /* 1100 * [OF13] Section 7.3.3 1101 * A fixed-size message body. 1102 */ 1103 { 1104 "TABLE_MOD", of13_table_mod_print, 1105 REQ_FIXLEN, OF_TABLE_MOD_FIXLEN 1106 }, 1107 /* 1108 * [OF13] Section 7.3.5 1109 * (to be done) 1110 */ 1111 { 1112 "MULTIPART_REQUEST", NULL, 1113 REQ_NONE, 0 1114 }, 1115 /* 1116 * [OF13] Section 7.3.5 1117 * (to be done) 1118 */ 1119 { 1120 "MULTIPART_REPLY", NULL, 1121 REQ_NONE, 0 1122 }, 1123 /* 1124 * [OF13] Section 7.3.8 1125 * No message body. 1126 */ 1127 { 1128 "BARRIER_REQUEST", NULL, 1129 REQ_FIXLEN, 0 1130 }, 1131 /* 1132 * [OF13] Section 7.3.8 1133 * No message body. 1134 */ 1135 { 1136 "BARRIER_REPLY", NULL, 1137 REQ_FIXLEN, 0 1138 }, 1139 /* 1140 * [OF13] Section 7.3.6 1141 * A fixed-size message body. 1142 */ 1143 { 1144 "QUEUE_GET_CONFIG_REQUEST", of13_queue_get_config_request_print, 1145 REQ_FIXLEN, OF_QUEUE_GET_CONFIG_REQUEST_FIXLEN 1146 }, 1147 /* 1148 * [OF13] Section 7.3.6 1149 * (to be done) 1150 */ 1151 { 1152 "QUEUE_GET_CONFIG_REPLY", NULL, 1153 REQ_NONE, 0 1154 }, 1155 /* 1156 * [OF13] Section 7.3.9 1157 * A fixed-size message body. 1158 */ 1159 { 1160 "ROLE_REQUEST", of13_role_msg_print, 1161 REQ_FIXLEN, OF_ROLE_MSG_FIXLEN 1162 }, 1163 /* 1164 * [OF13] Section 7.3.9 1165 * A fixed-size message body. 1166 */ 1167 { 1168 "ROLE_REPLY", of13_role_msg_print, 1169 REQ_FIXLEN, OF_ROLE_MSG_FIXLEN 1170 }, 1171 /* 1172 * [OF13] Section 7.3.10 1173 * No message body. 1174 */ 1175 { 1176 "GET_ASYNC_REQUEST", NULL, 1177 REQ_FIXLEN, 0 1178 }, 1179 /* 1180 * [OF13] Section 7.3.10 1181 * A fixed-size message body. 1182 */ 1183 { 1184 "GET_ASYNC_REPLY", of13_async_msg_print, 1185 REQ_FIXLEN, OF_ASYNC_MSG_FIXLEN 1186 }, 1187 /* 1188 * [OF13] Section 7.3.10 1189 * A fixed-size message body. 1190 */ 1191 { 1192 "SET_ASYNC", of13_async_msg_print, 1193 REQ_FIXLEN, OF_ASYNC_MSG_FIXLEN 1194 }, 1195 /* 1196 * [OF13] Section 7.3.4.4 1197 * (to be done) 1198 */ 1199 { 1200 "METER_MOD", NULL, 1201 REQ_NONE, 0 1202 }, 1203 }; 1204 1205 const struct of_msgtypeinfo * 1206 of13_identify_msgtype(const uint8_t type) 1207 { 1208 return type <= OFPT_MAX ? &of13_msgtypeinfo[type] : NULL; 1209 } 1210