1026d7285Schristos /* 2026d7285Schristos * This module implements decoding of OpenFlow protocol version 1.0 (wire 3026d7285Schristos * protocol 0x01). The decoder implements terse (default), detailed (-v) and 4026d7285Schristos * full (-vv) output formats and, as much as each format implies, detects and 5026d7285Schristos * tries to work around sizing anomalies inside the messages. The decoder marks 6026d7285Schristos * up bogus values of selected message fields and decodes partially captured 7026d7285Schristos * messages up to the snapshot end. It is based on the specification below: 8026d7285Schristos * 9c74ad251Schristos * [OF10] https://www.opennetworking.org/wp-content/uploads/2013/04/openflow-spec-v1.0.0.pdf 10026d7285Schristos * 11c74ad251Schristos * Most functions in this file take the following arguments: 123d25ea14Schristos * * cp -- the pointer to the first octet to decode 13c74ad251Schristos * * len -- the declared length of the structure to decode 14c74ad251Schristos * The convention is that a printer function returns iff the given structure is 15c74ad251Schristos * completely within the packet buffer; otherwise it processes the part that is 16c74ad251Schristos * within the buffer, sooner of later takes the "truncated packet" shortcut via 17c74ad251Schristos * longjmp() and never returns. With that in mind, the function may return 18c74ad251Schristos * without printing the structure completely if it is invalid or the ndo_vflag 19c74ad251Schristos * value is not high enough. This way the calling function can try to decode 20c74ad251Schristos * the next data item. 213d25ea14Schristos * 22026d7285Schristos * Decoding of Ethernet frames nested in OFPT_PACKET_IN and OFPT_PACKET_OUT 23026d7285Schristos * messages is done only when the verbosity level set by command-line argument 24026d7285Schristos * is "-vvv" or higher. In that case the verbosity level is temporarily 25026d7285Schristos * decremented by 3 during the nested frame decoding. For example, running 26026d7285Schristos * tcpdump with "-vvvv" will do full decoding of OpenFlow and "-v" decoding of 27026d7285Schristos * the nested frames. 28026d7285Schristos * 293d25ea14Schristos * Partial decoding of Big Switch Networks vendor extensions is done after the 303d25ea14Schristos * oftest (OpenFlow Testing Framework) and Loxigen (library generator) source 313d25ea14Schristos * code. 323d25ea14Schristos * 33026d7285Schristos * 34026d7285Schristos * Copyright (c) 2013 The TCPDUMP project 35026d7285Schristos * All rights reserved. 36026d7285Schristos * 37026d7285Schristos * Redistribution and use in source and binary forms, with or without 38026d7285Schristos * modification, are permitted provided that the following conditions 39026d7285Schristos * are met: 40026d7285Schristos * 1. Redistributions of source code must retain the above copyright 41026d7285Schristos * notice, this list of conditions and the following disclaimer. 42026d7285Schristos * 2. Redistributions in binary form must reproduce the above copyright 43026d7285Schristos * notice, this list of conditions and the following disclaimer in the 44026d7285Schristos * documentation and/or other materials provided with the distribution. 45026d7285Schristos * 46026d7285Schristos * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 47026d7285Schristos * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 48026d7285Schristos * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 49026d7285Schristos * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 50026d7285Schristos * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 51026d7285Schristos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 52026d7285Schristos * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 53026d7285Schristos * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 54026d7285Schristos * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 55026d7285Schristos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 56026d7285Schristos * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 57026d7285Schristos * POSSIBILITY OF SUCH DAMAGE. 58026d7285Schristos */ 59026d7285Schristos 60fdccd7e4Schristos #include <sys/cdefs.h> 61fdccd7e4Schristos #ifndef lint 62*26ba0b50Schristos __RCSID("$NetBSD: print-openflow-1.0.c,v 1.5 2024/09/02 16:15:32 christos Exp $"); 63fdccd7e4Schristos #endif 64fdccd7e4Schristos 65dc860a36Sspz /* \summary: OpenFlow protocol version 1.0 printer */ 66dc860a36Sspz 67c74ad251Schristos #include <config.h> 68026d7285Schristos 69c74ad251Schristos #include "netdissect-stdinc.h" 70026d7285Schristos 71c74ad251Schristos #define ND_LONGJMP_FROM_TCHECK 72784088dfSchristos #include "netdissect.h" 73026d7285Schristos #include "extract.h" 74026d7285Schristos #include "addrtoname.h" 75026d7285Schristos #include "ethertype.h" 76026d7285Schristos #include "ipproto.h" 773d25ea14Schristos #include "oui.h" 78026d7285Schristos #include "openflow.h" 79026d7285Schristos 80c47fd378Schristos 81026d7285Schristos #define OFPT_HELLO 0x00 82026d7285Schristos #define OFPT_ERROR 0x01 83026d7285Schristos #define OFPT_ECHO_REQUEST 0x02 84026d7285Schristos #define OFPT_ECHO_REPLY 0x03 85026d7285Schristos #define OFPT_VENDOR 0x04 86026d7285Schristos #define OFPT_FEATURES_REQUEST 0x05 87026d7285Schristos #define OFPT_FEATURES_REPLY 0x06 88026d7285Schristos #define OFPT_GET_CONFIG_REQUEST 0x07 89026d7285Schristos #define OFPT_GET_CONFIG_REPLY 0x08 90026d7285Schristos #define OFPT_SET_CONFIG 0x09 91026d7285Schristos #define OFPT_PACKET_IN 0x0a 92026d7285Schristos #define OFPT_FLOW_REMOVED 0x0b 93026d7285Schristos #define OFPT_PORT_STATUS 0x0c 94026d7285Schristos #define OFPT_PACKET_OUT 0x0d 95026d7285Schristos #define OFPT_FLOW_MOD 0x0e 96026d7285Schristos #define OFPT_PORT_MOD 0x0f 97026d7285Schristos #define OFPT_STATS_REQUEST 0x10 98026d7285Schristos #define OFPT_STATS_REPLY 0x11 99026d7285Schristos #define OFPT_BARRIER_REQUEST 0x12 100026d7285Schristos #define OFPT_BARRIER_REPLY 0x13 101026d7285Schristos #define OFPT_QUEUE_GET_CONFIG_REQUEST 0x14 102026d7285Schristos #define OFPT_QUEUE_GET_CONFIG_REPLY 0x15 103c74ad251Schristos #define OFPT_MAX OFPT_QUEUE_GET_CONFIG_REPLY 104026d7285Schristos 105c74ad251Schristos #define OFPPC_PORT_DOWN (1U <<0) 106c74ad251Schristos #define OFPPC_NO_STP (1U <<1) 107c74ad251Schristos #define OFPPC_NO_RECV (1U <<2) 108c74ad251Schristos #define OFPPC_NO_RECV_STP (1U <<3) 109c74ad251Schristos #define OFPPC_NO_FLOOD (1U <<4) 110c74ad251Schristos #define OFPPC_NO_FWD (1U <<5) 111c74ad251Schristos #define OFPPC_NO_PACKET_IN (1U <<6) 112026d7285Schristos static const struct tok ofppc_bm[] = { 113026d7285Schristos { OFPPC_PORT_DOWN, "PORT_DOWN" }, 114026d7285Schristos { OFPPC_NO_STP, "NO_STP" }, 115026d7285Schristos { OFPPC_NO_RECV, "NO_RECV" }, 116026d7285Schristos { OFPPC_NO_RECV_STP, "NO_RECV_STP" }, 117026d7285Schristos { OFPPC_NO_FLOOD, "NO_FLOOD" }, 118026d7285Schristos { OFPPC_NO_FWD, "NO_FWD" }, 119026d7285Schristos { OFPPC_NO_PACKET_IN, "NO_PACKET_IN" }, 120026d7285Schristos { 0, NULL } 121026d7285Schristos }; 122026d7285Schristos #define OFPPC_U (~(OFPPC_PORT_DOWN | OFPPC_NO_STP | OFPPC_NO_RECV | \ 123026d7285Schristos OFPPC_NO_RECV_STP | OFPPC_NO_FLOOD | OFPPC_NO_FWD | \ 124026d7285Schristos OFPPC_NO_PACKET_IN)) 125026d7285Schristos 126c74ad251Schristos /* 127c74ad251Schristos * [OF10] lists all FPPS_ constants in one enum, but they mean a 1-bit bitmap 128c74ad251Schristos * in the least significant octet and a 2-bit code point in the next octet. 129c74ad251Schristos * Remember to mix or to separate these two parts as the context requires. 130c74ad251Schristos */ 131c74ad251Schristos #define OFPPS_LINK_DOWN (1U << 0) /* bitmap */ 132c74ad251Schristos #define OFPPS_STP_LISTEN (0U << 8) /* code point */ 133c74ad251Schristos #define OFPPS_STP_LEARN (1U << 8) /* code point */ 134c74ad251Schristos #define OFPPS_STP_FORWARD (2U << 8) /* code point */ 135c74ad251Schristos #define OFPPS_STP_BLOCK (3U << 8) /* code point */ 136c74ad251Schristos #define OFPPS_STP_MASK (3U << 8) /* code point bitmask */ 137c74ad251Schristos static const struct tok ofpps_stp_str[] = { 138026d7285Schristos { OFPPS_STP_LISTEN, "STP_LISTEN" }, 139026d7285Schristos { OFPPS_STP_LEARN, "STP_LEARN" }, 140026d7285Schristos { OFPPS_STP_FORWARD, "STP_FORWARD" }, 141026d7285Schristos { OFPPS_STP_BLOCK, "STP_BLOCK" }, 142026d7285Schristos { 0, NULL } 143026d7285Schristos }; 144026d7285Schristos #define OFPPS_U (~(OFPPS_LINK_DOWN | OFPPS_STP_LISTEN | OFPPS_STP_LEARN | \ 145026d7285Schristos OFPPS_STP_FORWARD | OFPPS_STP_BLOCK)) 146026d7285Schristos 147c74ad251Schristos #define OFPP_MAX 0xff00U 148c74ad251Schristos #define OFPP_IN_PORT 0xfff8U 149c74ad251Schristos #define OFPP_TABLE 0xfff9U 150c74ad251Schristos #define OFPP_NORMAL 0xfffaU 151c74ad251Schristos #define OFPP_FLOOD 0xfffbU 152c74ad251Schristos #define OFPP_ALL 0xfffcU 153c74ad251Schristos #define OFPP_CONTROLLER 0xfffdU 154c74ad251Schristos #define OFPP_LOCAL 0xfffeU 155c74ad251Schristos #define OFPP_NONE 0xffffU 156026d7285Schristos static const struct tok ofpp_str[] = { 157026d7285Schristos { OFPP_MAX, "MAX" }, 158026d7285Schristos { OFPP_IN_PORT, "IN_PORT" }, 159026d7285Schristos { OFPP_TABLE, "TABLE" }, 160026d7285Schristos { OFPP_NORMAL, "NORMAL" }, 161026d7285Schristos { OFPP_FLOOD, "FLOOD" }, 162026d7285Schristos { OFPP_ALL, "ALL" }, 163026d7285Schristos { OFPP_CONTROLLER, "CONTROLLER" }, 164026d7285Schristos { OFPP_LOCAL, "LOCAL" }, 165026d7285Schristos { OFPP_NONE, "NONE" }, 166026d7285Schristos { 0, NULL } 167026d7285Schristos }; 168026d7285Schristos 169c74ad251Schristos #define OFPPF_10MB_HD (1U << 0) 170c74ad251Schristos #define OFPPF_10MB_FD (1U << 1) 171c74ad251Schristos #define OFPPF_100MB_HD (1U << 2) 172c74ad251Schristos #define OFPPF_100MB_FD (1U << 3) 173c74ad251Schristos #define OFPPF_1GB_HD (1U << 4) 174c74ad251Schristos #define OFPPF_1GB_FD (1U << 5) 175c74ad251Schristos #define OFPPF_10GB_FD (1U << 6) 176c74ad251Schristos #define OFPPF_COPPER (1U << 7) 177c74ad251Schristos #define OFPPF_FIBER (1U << 8) 178c74ad251Schristos #define OFPPF_AUTONEG (1U << 9) 179c74ad251Schristos #define OFPPF_PAUSE (1U <<10) 180c74ad251Schristos #define OFPPF_PAUSE_ASYM (1U <<11) 181026d7285Schristos static const struct tok ofppf_bm[] = { 182026d7285Schristos { OFPPF_10MB_HD, "10MB_HD" }, 183026d7285Schristos { OFPPF_10MB_FD, "10MB_FD" }, 184026d7285Schristos { OFPPF_100MB_HD, "100MB_HD" }, 185026d7285Schristos { OFPPF_100MB_FD, "100MB_FD" }, 186026d7285Schristos { OFPPF_1GB_HD, "1GB_HD" }, 187026d7285Schristos { OFPPF_1GB_FD, "1GB_FD" }, 188026d7285Schristos { OFPPF_10GB_FD, "10GB_FD" }, 189026d7285Schristos { OFPPF_COPPER, "COPPER" }, 190026d7285Schristos { OFPPF_FIBER, "FIBER" }, 191026d7285Schristos { OFPPF_AUTONEG, "AUTONEG" }, 192026d7285Schristos { OFPPF_PAUSE, "PAUSE" }, 193026d7285Schristos { OFPPF_PAUSE_ASYM, "PAUSE_ASYM" }, 194026d7285Schristos { 0, NULL } 195026d7285Schristos }; 196026d7285Schristos #define OFPPF_U (~(OFPPF_10MB_HD | OFPPF_10MB_FD | OFPPF_100MB_HD | \ 197026d7285Schristos OFPPF_100MB_FD | OFPPF_1GB_HD | OFPPF_1GB_FD | \ 198026d7285Schristos OFPPF_10GB_FD | OFPPF_COPPER | OFPPF_FIBER | \ 199026d7285Schristos OFPPF_AUTONEG | OFPPF_PAUSE | OFPPF_PAUSE_ASYM)) 200026d7285Schristos 201026d7285Schristos #define OFPQT_NONE 0x0000 202026d7285Schristos #define OFPQT_MIN_RATE 0x0001 203026d7285Schristos static const struct tok ofpqt_str[] = { 204026d7285Schristos { OFPQT_NONE, "NONE" }, 205026d7285Schristos { OFPQT_MIN_RATE, "MIN_RATE" }, 206026d7285Schristos { 0, NULL } 207026d7285Schristos }; 208026d7285Schristos 209c74ad251Schristos #define OFPFW_IN_PORT (1U <<0) 210c74ad251Schristos #define OFPFW_DL_VLAN (1U <<1) 211c74ad251Schristos #define OFPFW_DL_SRC (1U <<2) 212c74ad251Schristos #define OFPFW_DL_DST (1U <<3) 213c74ad251Schristos #define OFPFW_DL_TYPE (1U <<4) 214c74ad251Schristos #define OFPFW_NW_PROTO (1U <<5) 215c74ad251Schristos #define OFPFW_TP_SRC (1U <<6) 216c74ad251Schristos #define OFPFW_TP_DST (1U <<7) 217026d7285Schristos #define OFPFW_NW_SRC_SHIFT 8 218026d7285Schristos #define OFPFW_NW_SRC_BITS 6 219c74ad251Schristos #define OFPFW_NW_SRC_MASK (((1U <<OFPFW_NW_SRC_BITS) - 1) << OFPFW_NW_SRC_SHIFT) 220026d7285Schristos #define OFPFW_NW_DST_SHIFT 14 221026d7285Schristos #define OFPFW_NW_DST_BITS 6 222c74ad251Schristos #define OFPFW_NW_DST_MASK (((1U <<OFPFW_NW_DST_BITS) - 1) << OFPFW_NW_DST_SHIFT) 223c74ad251Schristos #define OFPFW_DL_VLAN_PCP (1U <<20) 224c74ad251Schristos #define OFPFW_NW_TOS (1U <<21) 225c74ad251Schristos #define OFPFW_ALL ((1U <<22) - 1) 226026d7285Schristos static const struct tok ofpfw_bm[] = { 227026d7285Schristos { OFPFW_IN_PORT, "IN_PORT" }, 228026d7285Schristos { OFPFW_DL_VLAN, "DL_VLAN" }, 229026d7285Schristos { OFPFW_DL_SRC, "DL_SRC" }, 230026d7285Schristos { OFPFW_DL_DST, "DL_DST" }, 231026d7285Schristos { OFPFW_DL_TYPE, "DL_TYPE" }, 232026d7285Schristos { OFPFW_NW_PROTO, "NW_PROTO" }, 233026d7285Schristos { OFPFW_TP_SRC, "TP_SRC" }, 234026d7285Schristos { OFPFW_TP_DST, "TP_DST" }, 235026d7285Schristos { OFPFW_DL_VLAN_PCP, "DL_VLAN_PCP" }, 236026d7285Schristos { OFPFW_NW_TOS, "NW_TOS" }, 237026d7285Schristos { 0, NULL } 238026d7285Schristos }; 239026d7285Schristos /* The above array does not include bits 8~13 (OFPFW_NW_SRC_*) and 14~19 240026d7285Schristos * (OFPFW_NW_DST_*), which are not a part of the bitmap and require decoding 241026d7285Schristos * other than that of tok2str(). The macro below includes these bits such that 242026d7285Schristos * they are not reported as bogus in the decoding. */ 243026d7285Schristos #define OFPFW_U (~(OFPFW_ALL)) 244026d7285Schristos 245c74ad251Schristos #define OFPAT_OUTPUT 0x0000U 246c74ad251Schristos #define OFPAT_SET_VLAN_VID 0x0001U 247c74ad251Schristos #define OFPAT_SET_VLAN_PCP 0x0002U 248c74ad251Schristos #define OFPAT_STRIP_VLAN 0x0003U 249c74ad251Schristos #define OFPAT_SET_DL_SRC 0x0004U 250c74ad251Schristos #define OFPAT_SET_DL_DST 0x0005U 251c74ad251Schristos #define OFPAT_SET_NW_SRC 0x0006U 252c74ad251Schristos #define OFPAT_SET_NW_DST 0x0007U 253c74ad251Schristos #define OFPAT_SET_NW_TOS 0x0008U 254c74ad251Schristos #define OFPAT_SET_TP_SRC 0x0009U 255c74ad251Schristos #define OFPAT_SET_TP_DST 0x000aU 256c74ad251Schristos #define OFPAT_ENQUEUE 0x000bU 257c74ad251Schristos #define OFPAT_VENDOR 0xffffU 258026d7285Schristos static const struct tok ofpat_str[] = { 259026d7285Schristos { OFPAT_OUTPUT, "OUTPUT" }, 260026d7285Schristos { OFPAT_SET_VLAN_VID, "SET_VLAN_VID" }, 261026d7285Schristos { OFPAT_SET_VLAN_PCP, "SET_VLAN_PCP" }, 262026d7285Schristos { OFPAT_STRIP_VLAN, "STRIP_VLAN" }, 263026d7285Schristos { OFPAT_SET_DL_SRC, "SET_DL_SRC" }, 264026d7285Schristos { OFPAT_SET_DL_DST, "SET_DL_DST" }, 265026d7285Schristos { OFPAT_SET_NW_SRC, "SET_NW_SRC" }, 266026d7285Schristos { OFPAT_SET_NW_DST, "SET_NW_DST" }, 267026d7285Schristos { OFPAT_SET_NW_TOS, "SET_NW_TOS" }, 268026d7285Schristos { OFPAT_SET_TP_SRC, "SET_TP_SRC" }, 269026d7285Schristos { OFPAT_SET_TP_DST, "SET_TP_DST" }, 270026d7285Schristos { OFPAT_ENQUEUE, "ENQUEUE" }, 271026d7285Schristos { OFPAT_VENDOR, "VENDOR" }, 272026d7285Schristos { 0, NULL } 273026d7285Schristos }; 274026d7285Schristos 275026d7285Schristos /* bit-shifted, w/o vendor action */ 276026d7285Schristos static const struct tok ofpat_bm[] = { 277c74ad251Schristos { 1U <<OFPAT_OUTPUT, "OUTPUT" }, 278c74ad251Schristos { 1U <<OFPAT_SET_VLAN_VID, "SET_VLAN_VID" }, 279c74ad251Schristos { 1U <<OFPAT_SET_VLAN_PCP, "SET_VLAN_PCP" }, 280c74ad251Schristos { 1U <<OFPAT_STRIP_VLAN, "STRIP_VLAN" }, 281c74ad251Schristos { 1U <<OFPAT_SET_DL_SRC, "SET_DL_SRC" }, 282c74ad251Schristos { 1U <<OFPAT_SET_DL_DST, "SET_DL_DST" }, 283c74ad251Schristos { 1U <<OFPAT_SET_NW_SRC, "SET_NW_SRC" }, 284c74ad251Schristos { 1U <<OFPAT_SET_NW_DST, "SET_NW_DST" }, 285c74ad251Schristos { 1U <<OFPAT_SET_NW_TOS, "SET_NW_TOS" }, 286c74ad251Schristos { 1U <<OFPAT_SET_TP_SRC, "SET_TP_SRC" }, 287c74ad251Schristos { 1U <<OFPAT_SET_TP_DST, "SET_TP_DST" }, 288c74ad251Schristos { 1U <<OFPAT_ENQUEUE, "ENQUEUE" }, 289026d7285Schristos { 0, NULL } 290026d7285Schristos }; 291c74ad251Schristos #define OFPAT_U (~(1U <<OFPAT_OUTPUT | 1U <<OFPAT_SET_VLAN_VID | \ 292c74ad251Schristos 1U <<OFPAT_SET_VLAN_PCP | 1U <<OFPAT_STRIP_VLAN | \ 293c74ad251Schristos 1U <<OFPAT_SET_DL_SRC | 1U <<OFPAT_SET_DL_DST | \ 294c74ad251Schristos 1U <<OFPAT_SET_NW_SRC | 1U <<OFPAT_SET_NW_DST | \ 295c74ad251Schristos 1U <<OFPAT_SET_NW_TOS | 1U <<OFPAT_SET_TP_SRC | \ 296c74ad251Schristos 1U <<OFPAT_SET_TP_DST | 1U <<OFPAT_ENQUEUE)) 297026d7285Schristos 298c74ad251Schristos #define OFPC_FLOW_STATS (1U <<0) 299c74ad251Schristos #define OFPC_TABLE_STATS (1U <<1) 300c74ad251Schristos #define OFPC_PORT_STATS (1U <<2) 301c74ad251Schristos #define OFPC_STP (1U <<3) 302c74ad251Schristos #define OFPC_RESERVED (1U <<4) 303c74ad251Schristos #define OFPC_IP_REASM (1U <<5) 304c74ad251Schristos #define OFPC_QUEUE_STATS (1U <<6) 305c74ad251Schristos #define OFPC_ARP_MATCH_IP (1U <<7) 306026d7285Schristos static const struct tok ofp_capabilities_bm[] = { 307026d7285Schristos { OFPC_FLOW_STATS, "FLOW_STATS" }, 308026d7285Schristos { OFPC_TABLE_STATS, "TABLE_STATS" }, 309026d7285Schristos { OFPC_PORT_STATS, "PORT_STATS" }, 310026d7285Schristos { OFPC_STP, "STP" }, 311026d7285Schristos { OFPC_RESERVED, "RESERVED" }, /* not in the mask below */ 312026d7285Schristos { OFPC_IP_REASM, "IP_REASM" }, 313026d7285Schristos { OFPC_QUEUE_STATS, "QUEUE_STATS" }, 314026d7285Schristos { OFPC_ARP_MATCH_IP, "ARP_MATCH_IP" }, 315026d7285Schristos { 0, NULL } 316026d7285Schristos }; 317026d7285Schristos #define OFPCAP_U (~(OFPC_FLOW_STATS | OFPC_TABLE_STATS | OFPC_PORT_STATS | \ 318026d7285Schristos OFPC_STP | OFPC_IP_REASM | OFPC_QUEUE_STATS | \ 319026d7285Schristos OFPC_ARP_MATCH_IP)) 320026d7285Schristos 321c74ad251Schristos #define OFPC_FRAG_NORMAL 0x0000U 322c74ad251Schristos #define OFPC_FRAG_DROP 0x0001U 323c74ad251Schristos #define OFPC_FRAG_REASM 0x0002U 324026d7285Schristos static const struct tok ofp_config_str[] = { 325026d7285Schristos { OFPC_FRAG_NORMAL, "FRAG_NORMAL" }, 326026d7285Schristos { OFPC_FRAG_DROP, "FRAG_DROP" }, 327026d7285Schristos { OFPC_FRAG_REASM, "FRAG_REASM" }, 328026d7285Schristos { 0, NULL } 329026d7285Schristos }; 330026d7285Schristos 331c74ad251Schristos #define OFPFC_ADD 0x0000U 332c74ad251Schristos #define OFPFC_MODIFY 0x0001U 333c74ad251Schristos #define OFPFC_MODIFY_STRICT 0x0002U 334c74ad251Schristos #define OFPFC_DELETE 0x0003U 335c74ad251Schristos #define OFPFC_DELETE_STRICT 0x0004U 336026d7285Schristos static const struct tok ofpfc_str[] = { 337026d7285Schristos { OFPFC_ADD, "ADD" }, 338026d7285Schristos { OFPFC_MODIFY, "MODIFY" }, 339026d7285Schristos { OFPFC_MODIFY_STRICT, "MODIFY_STRICT" }, 340026d7285Schristos { OFPFC_DELETE, "DELETE" }, 341026d7285Schristos { OFPFC_DELETE_STRICT, "DELETE_STRICT" }, 342026d7285Schristos { 0, NULL } 343026d7285Schristos }; 344026d7285Schristos 345026d7285Schristos static const struct tok bufferid_str[] = { 346026d7285Schristos { 0xffffffff, "NONE" }, 347026d7285Schristos { 0, NULL } 348026d7285Schristos }; 349026d7285Schristos 350c74ad251Schristos #define OFPFF_SEND_FLOW_REM (1U <<0) 351c74ad251Schristos #define OFPFF_CHECK_OVERLAP (1U <<1) 352c74ad251Schristos #define OFPFF_EMERG (1U <<2) 353026d7285Schristos static const struct tok ofpff_bm[] = { 354026d7285Schristos { OFPFF_SEND_FLOW_REM, "SEND_FLOW_REM" }, 355026d7285Schristos { OFPFF_CHECK_OVERLAP, "CHECK_OVERLAP" }, 356026d7285Schristos { OFPFF_EMERG, "EMERG" }, 357026d7285Schristos { 0, NULL } 358026d7285Schristos }; 359026d7285Schristos #define OFPFF_U (~(OFPFF_SEND_FLOW_REM | OFPFF_CHECK_OVERLAP | OFPFF_EMERG)) 360026d7285Schristos 361c74ad251Schristos #define OFPST_DESC 0x0000U 362c74ad251Schristos #define OFPST_FLOW 0x0001U 363c74ad251Schristos #define OFPST_AGGREGATE 0x0002U 364c74ad251Schristos #define OFPST_TABLE 0x0003U 365c74ad251Schristos #define OFPST_PORT 0x0004U 366c74ad251Schristos #define OFPST_QUEUE 0x0005U 367c74ad251Schristos #define OFPST_VENDOR 0xffffU 368026d7285Schristos static const struct tok ofpst_str[] = { 369026d7285Schristos { OFPST_DESC, "DESC" }, 370026d7285Schristos { OFPST_FLOW, "FLOW" }, 371026d7285Schristos { OFPST_AGGREGATE, "AGGREGATE" }, 372026d7285Schristos { OFPST_TABLE, "TABLE" }, 373026d7285Schristos { OFPST_PORT, "PORT" }, 374026d7285Schristos { OFPST_QUEUE, "QUEUE" }, 375026d7285Schristos { OFPST_VENDOR, "VENDOR" }, 376026d7285Schristos { 0, NULL } 377026d7285Schristos }; 378026d7285Schristos 379026d7285Schristos static const struct tok tableid_str[] = { 380c74ad251Schristos { 0xfeU, "EMERG" }, 381c74ad251Schristos { 0xffU, "ALL" }, 382026d7285Schristos { 0, NULL } 383026d7285Schristos }; 384026d7285Schristos 385c74ad251Schristos #define OFPQ_ALL 0xffffffffU 386026d7285Schristos static const struct tok ofpq_str[] = { 387026d7285Schristos { OFPQ_ALL, "ALL" }, 388026d7285Schristos { 0, NULL } 389026d7285Schristos }; 390026d7285Schristos 391c74ad251Schristos #define OFPSF_REPLY_MORE 0x0001U 392026d7285Schristos static const struct tok ofpsf_reply_bm[] = { 393026d7285Schristos { OFPSF_REPLY_MORE, "MORE" }, 394026d7285Schristos { 0, NULL } 395026d7285Schristos }; 396026d7285Schristos #define OFPSF_REPLY_U (~(OFPSF_REPLY_MORE)) 397026d7285Schristos 398c74ad251Schristos #define OFPR_NO_MATCH 0x00U 399c74ad251Schristos #define OFPR_ACTION 0x01U 400026d7285Schristos static const struct tok ofpr_str[] = { 401026d7285Schristos { OFPR_NO_MATCH, "NO_MATCH" }, 402026d7285Schristos { OFPR_ACTION, "ACTION" }, 403026d7285Schristos { 0, NULL } 404026d7285Schristos }; 405026d7285Schristos 406c74ad251Schristos #define OFPRR_IDLE_TIMEOUT 0x00U 407c74ad251Schristos #define OFPRR_HARD_TIMEOUT 0x01U 408c74ad251Schristos #define OFPRR_DELETE 0x02U 409026d7285Schristos static const struct tok ofprr_str[] = { 410026d7285Schristos { OFPRR_IDLE_TIMEOUT, "IDLE_TIMEOUT" }, 411026d7285Schristos { OFPRR_HARD_TIMEOUT, "HARD_TIMEOUT" }, 412026d7285Schristos { OFPRR_DELETE, "DELETE" }, 413026d7285Schristos { 0, NULL } 414026d7285Schristos }; 415026d7285Schristos 416c74ad251Schristos #define OFPPR_ADD 0x00U 417c74ad251Schristos #define OFPPR_DELETE 0x01U 418c74ad251Schristos #define OFPPR_MODIFY 0x02U 419026d7285Schristos static const struct tok ofppr_str[] = { 420026d7285Schristos { OFPPR_ADD, "ADD" }, 421026d7285Schristos { OFPPR_DELETE, "DELETE" }, 422026d7285Schristos { OFPPR_MODIFY, "MODIFY" }, 423026d7285Schristos { 0, NULL } 424026d7285Schristos }; 425026d7285Schristos 426c74ad251Schristos #define OFPET_HELLO_FAILED 0x0000U 427c74ad251Schristos #define OFPET_BAD_REQUEST 0x0001U 428c74ad251Schristos #define OFPET_BAD_ACTION 0x0002U 429c74ad251Schristos #define OFPET_FLOW_MOD_FAILED 0x0003U 430c74ad251Schristos #define OFPET_PORT_MOD_FAILED 0x0004U 431c74ad251Schristos #define OFPET_QUEUE_OP_FAILED 0x0005U 432026d7285Schristos static const struct tok ofpet_str[] = { 433026d7285Schristos { OFPET_HELLO_FAILED, "HELLO_FAILED" }, 434026d7285Schristos { OFPET_BAD_REQUEST, "BAD_REQUEST" }, 435026d7285Schristos { OFPET_BAD_ACTION, "BAD_ACTION" }, 436026d7285Schristos { OFPET_FLOW_MOD_FAILED, "FLOW_MOD_FAILED" }, 437026d7285Schristos { OFPET_PORT_MOD_FAILED, "PORT_MOD_FAILED" }, 438026d7285Schristos { OFPET_QUEUE_OP_FAILED, "QUEUE_OP_FAILED" }, 439026d7285Schristos { 0, NULL } 440026d7285Schristos }; 441026d7285Schristos 442c74ad251Schristos #define OFPHFC_INCOMPATIBLE 0x0000U 443c74ad251Schristos #define OFPHFC_EPERM 0x0001U 444026d7285Schristos static const struct tok ofphfc_str[] = { 445026d7285Schristos { OFPHFC_INCOMPATIBLE, "INCOMPATIBLE" }, 446026d7285Schristos { OFPHFC_EPERM, "EPERM" }, 447026d7285Schristos { 0, NULL } 448026d7285Schristos }; 449026d7285Schristos 450c74ad251Schristos #define OFPBRC_BAD_VERSION 0x0000U 451c74ad251Schristos #define OFPBRC_BAD_TYPE 0x0001U 452c74ad251Schristos #define OFPBRC_BAD_STAT 0x0002U 453c74ad251Schristos #define OFPBRC_BAD_VENDOR 0x0003U 454c74ad251Schristos #define OFPBRC_BAD_SUBTYPE 0x0004U 455c74ad251Schristos #define OFPBRC_EPERM 0x0005U 456c74ad251Schristos #define OFPBRC_BAD_LEN 0x0006U 457c74ad251Schristos #define OFPBRC_BUFFER_EMPTY 0x0007U 458c74ad251Schristos #define OFPBRC_BUFFER_UNKNOWN 0x0008U 459026d7285Schristos static const struct tok ofpbrc_str[] = { 460026d7285Schristos { OFPBRC_BAD_VERSION, "BAD_VERSION" }, 461026d7285Schristos { OFPBRC_BAD_TYPE, "BAD_TYPE" }, 462026d7285Schristos { OFPBRC_BAD_STAT, "BAD_STAT" }, 463026d7285Schristos { OFPBRC_BAD_VENDOR, "BAD_VENDOR" }, 464026d7285Schristos { OFPBRC_BAD_SUBTYPE, "BAD_SUBTYPE" }, 465026d7285Schristos { OFPBRC_EPERM, "EPERM" }, 466026d7285Schristos { OFPBRC_BAD_LEN, "BAD_LEN" }, 467026d7285Schristos { OFPBRC_BUFFER_EMPTY, "BUFFER_EMPTY" }, 468026d7285Schristos { OFPBRC_BUFFER_UNKNOWN, "BUFFER_UNKNOWN" }, 469026d7285Schristos { 0, NULL } 470026d7285Schristos }; 471026d7285Schristos 472c74ad251Schristos #define OFPBAC_BAD_TYPE 0x0000U 473c74ad251Schristos #define OFPBAC_BAD_LEN 0x0001U 474c74ad251Schristos #define OFPBAC_BAD_VENDOR 0x0002U 475c74ad251Schristos #define OFPBAC_BAD_VENDOR_TYPE 0x0003U 476c74ad251Schristos #define OFPBAC_BAD_OUT_PORT 0x0004U 477c74ad251Schristos #define OFPBAC_BAD_ARGUMENT 0x0005U 478c74ad251Schristos #define OFPBAC_EPERM 0x0006U 479c74ad251Schristos #define OFPBAC_TOO_MANY 0x0007U 480c74ad251Schristos #define OFPBAC_BAD_QUEUE 0x0008U 481026d7285Schristos static const struct tok ofpbac_str[] = { 482026d7285Schristos { OFPBAC_BAD_TYPE, "BAD_TYPE" }, 483026d7285Schristos { OFPBAC_BAD_LEN, "BAD_LEN" }, 484026d7285Schristos { OFPBAC_BAD_VENDOR, "BAD_VENDOR" }, 485026d7285Schristos { OFPBAC_BAD_VENDOR_TYPE, "BAD_VENDOR_TYPE" }, 486026d7285Schristos { OFPBAC_BAD_OUT_PORT, "BAD_OUT_PORT" }, 487026d7285Schristos { OFPBAC_BAD_ARGUMENT, "BAD_ARGUMENT" }, 488026d7285Schristos { OFPBAC_EPERM, "EPERM" }, 489026d7285Schristos { OFPBAC_TOO_MANY, "TOO_MANY" }, 490026d7285Schristos { OFPBAC_BAD_QUEUE, "BAD_QUEUE" }, 491026d7285Schristos { 0, NULL } 492026d7285Schristos }; 493026d7285Schristos 494c74ad251Schristos #define OFPFMFC_ALL_TABLES_FULL 0x0000U 495c74ad251Schristos #define OFPFMFC_OVERLAP 0x0001U 496c74ad251Schristos #define OFPFMFC_EPERM 0x0002U 497c74ad251Schristos #define OFPFMFC_BAD_EMERG_TIMEOUT 0x0003U 498c74ad251Schristos #define OFPFMFC_BAD_COMMAND 0x0004U 499c74ad251Schristos #define OFPFMFC_UNSUPPORTED 0x0005U 500026d7285Schristos static const struct tok ofpfmfc_str[] = { 501026d7285Schristos { OFPFMFC_ALL_TABLES_FULL, "ALL_TABLES_FULL" }, 502026d7285Schristos { OFPFMFC_OVERLAP, "OVERLAP" }, 503026d7285Schristos { OFPFMFC_EPERM, "EPERM" }, 504026d7285Schristos { OFPFMFC_BAD_EMERG_TIMEOUT, "BAD_EMERG_TIMEOUT" }, 505026d7285Schristos { OFPFMFC_BAD_COMMAND, "BAD_COMMAND" }, 506026d7285Schristos { OFPFMFC_UNSUPPORTED, "UNSUPPORTED" }, 507026d7285Schristos { 0, NULL } 508026d7285Schristos }; 509026d7285Schristos 510c74ad251Schristos #define OFPPMFC_BAD_PORT 0x0000U 511c74ad251Schristos #define OFPPMFC_BAD_HW_ADDR 0x0001U 512026d7285Schristos static const struct tok ofppmfc_str[] = { 513026d7285Schristos { OFPPMFC_BAD_PORT, "BAD_PORT" }, 514026d7285Schristos { OFPPMFC_BAD_HW_ADDR, "BAD_HW_ADDR" }, 515026d7285Schristos { 0, NULL } 516026d7285Schristos }; 517026d7285Schristos 518c74ad251Schristos #define OFPQOFC_BAD_PORT 0x0000U 519c74ad251Schristos #define OFPQOFC_BAD_QUEUE 0x0001U 520c74ad251Schristos #define OFPQOFC_EPERM 0x0002U 521026d7285Schristos static const struct tok ofpqofc_str[] = { 522026d7285Schristos { OFPQOFC_BAD_PORT, "BAD_PORT" }, 523026d7285Schristos { OFPQOFC_BAD_QUEUE, "BAD_QUEUE" }, 524026d7285Schristos { OFPQOFC_EPERM, "EPERM" }, 525026d7285Schristos { 0, NULL } 526026d7285Schristos }; 527026d7285Schristos 528c74ad251Schristos static const struct uint_tokary of10_ofpet2tokary[] = { 529c74ad251Schristos { OFPET_HELLO_FAILED, ofphfc_str }, 530c74ad251Schristos { OFPET_BAD_REQUEST, ofpbrc_str }, 531c74ad251Schristos { OFPET_BAD_ACTION, ofpbac_str }, 532c74ad251Schristos { OFPET_FLOW_MOD_FAILED, ofpfmfc_str }, 533c74ad251Schristos { OFPET_PORT_MOD_FAILED, ofppmfc_str }, 534c74ad251Schristos { OFPET_QUEUE_OP_FAILED, ofpqofc_str }, 535c74ad251Schristos /* uint2tokary() does not use array termination. */ 536026d7285Schristos }; 537026d7285Schristos 538c74ad251Schristos /* lengths (fixed or minimal) of particular message types, where not 0 */ 539c74ad251Schristos #define OF_SWITCH_CONFIG_FIXLEN (12U - OF_HEADER_FIXLEN) 540c74ad251Schristos #define OF_FEATURES_REPLY_MINLEN (32U - OF_HEADER_FIXLEN) 541c74ad251Schristos #define OF_PORT_STATUS_FIXLEN (64U - OF_HEADER_FIXLEN) 542c74ad251Schristos #define OF_PORT_MOD_FIXLEN (32U - OF_HEADER_FIXLEN) 543c74ad251Schristos #define OF_PACKET_IN_MINLEN (20U - OF_HEADER_FIXLEN) /* with 2 mock octets */ 544c74ad251Schristos #define OF_PACKET_OUT_MINLEN (16U - OF_HEADER_FIXLEN) 545c74ad251Schristos #define OF_FLOW_MOD_MINLEN (72U - OF_HEADER_FIXLEN) 546c74ad251Schristos #define OF_FLOW_REMOVED_FIXLEN (88U - OF_HEADER_FIXLEN) 547c74ad251Schristos #define OF_ERROR_MSG_MINLEN (12U - OF_HEADER_FIXLEN) 548c74ad251Schristos #define OF_STATS_REQUEST_MINLEN (12U - OF_HEADER_FIXLEN) 549c74ad251Schristos #define OF_STATS_REPLY_MINLEN (12U - OF_HEADER_FIXLEN) 550c74ad251Schristos #define OF_VENDOR_MINLEN (12U - OF_HEADER_FIXLEN) 551c74ad251Schristos #define OF_QUEUE_GET_CONFIG_REQUEST_FIXLEN (12U - OF_HEADER_FIXLEN) 552c74ad251Schristos #define OF_QUEUE_GET_CONFIG_REPLY_MINLEN (16U - OF_HEADER_FIXLEN) 553c74ad251Schristos 554026d7285Schristos /* lengths (fixed or minimal) of particular protocol structures */ 555c74ad251Schristos #define OF_PHY_PORT_FIXLEN 48 556c74ad251Schristos #define OF_ACTION_MINLEN 8 557c74ad251Schristos #define OF_MATCH_FIXLEN 40 558c74ad251Schristos #define OF_DESC_STATS_REPLY_FIXLEN 1056 559c74ad251Schristos #define OF_FLOW_STATS_REQUEST_FIXLEN 44 560c74ad251Schristos #define OF_FLOW_STATS_REPLY_MINLEN 88 561c74ad251Schristos #define OF_AGGREGATE_STATS_REPLY_FIXLEN 24 562c74ad251Schristos #define OF_TABLE_STATS_REPLY_FIXLEN 64 563c74ad251Schristos #define OF_PORT_STATS_REQUEST_FIXLEN 8 564c74ad251Schristos #define OF_PORT_STATS_REPLY_FIXLEN 104 565c74ad251Schristos #define OF_QUEUE_PROP_MINLEN 8 566c74ad251Schristos #define OF_QUEUE_PROP_MIN_RATE_FIXLEN 16 567c74ad251Schristos #define OF_PACKET_QUEUE_MINLEN 8 568c74ad251Schristos #define OF_QUEUE_STATS_REQUEST_FIXLEN 8 569c74ad251Schristos #define OF_QUEUE_STATS_REPLY_FIXLEN 32 570026d7285Schristos 571026d7285Schristos /* miscellaneous constants from [OF10] */ 572026d7285Schristos #define OFP_MAX_TABLE_NAME_LEN 32 573026d7285Schristos #define OFP_MAX_PORT_NAME_LEN 16 574026d7285Schristos #define DESC_STR_LEN 256 575026d7285Schristos #define SERIAL_NUM_LEN 32 576c74ad251Schristos #define OFP_VLAN_NONE 0xffffU 577026d7285Schristos 5783d25ea14Schristos /* vendor extensions */ 5793d25ea14Schristos #define BSN_SET_IP_MASK 0 5803d25ea14Schristos #define BSN_GET_IP_MASK_REQUEST 1 5813d25ea14Schristos #define BSN_GET_IP_MASK_REPLY 2 5823d25ea14Schristos #define BSN_SET_MIRRORING 3 5833d25ea14Schristos #define BSN_GET_MIRRORING_REQUEST 4 5843d25ea14Schristos #define BSN_GET_MIRRORING_REPLY 5 5853d25ea14Schristos #define BSN_SHELL_COMMAND 6 5863d25ea14Schristos #define BSN_SHELL_OUTPUT 7 5873d25ea14Schristos #define BSN_SHELL_STATUS 8 5883d25ea14Schristos #define BSN_GET_INTERFACES_REQUEST 9 5893d25ea14Schristos #define BSN_GET_INTERFACES_REPLY 10 5903d25ea14Schristos #define BSN_SET_PKTIN_SUPPRESSION_REQUEST 11 5913d25ea14Schristos #define BSN_SET_L2_TABLE_REQUEST 12 5923d25ea14Schristos #define BSN_GET_L2_TABLE_REQUEST 13 5933d25ea14Schristos #define BSN_GET_L2_TABLE_REPLY 14 5943d25ea14Schristos #define BSN_VIRTUAL_PORT_CREATE_REQUEST 15 5953d25ea14Schristos #define BSN_VIRTUAL_PORT_CREATE_REPLY 16 5963d25ea14Schristos #define BSN_VIRTUAL_PORT_REMOVE_REQUEST 17 5973d25ea14Schristos #define BSN_BW_ENABLE_SET_REQUEST 18 5983d25ea14Schristos #define BSN_BW_ENABLE_GET_REQUEST 19 5993d25ea14Schristos #define BSN_BW_ENABLE_GET_REPLY 20 6003d25ea14Schristos #define BSN_BW_CLEAR_DATA_REQUEST 21 6013d25ea14Schristos #define BSN_BW_CLEAR_DATA_REPLY 22 6023d25ea14Schristos #define BSN_BW_ENABLE_SET_REPLY 23 6033d25ea14Schristos #define BSN_SET_L2_TABLE_REPLY 24 6043d25ea14Schristos #define BSN_SET_PKTIN_SUPPRESSION_REPLY 25 6053d25ea14Schristos #define BSN_VIRTUAL_PORT_REMOVE_REPLY 26 6063d25ea14Schristos #define BSN_HYBRID_GET_REQUEST 27 6073d25ea14Schristos #define BSN_HYBRID_GET_REPLY 28 6083d25ea14Schristos /* 29 */ 6093d25ea14Schristos /* 30 */ 6103d25ea14Schristos #define BSN_PDU_TX_REQUEST 31 6113d25ea14Schristos #define BSN_PDU_TX_REPLY 32 6123d25ea14Schristos #define BSN_PDU_RX_REQUEST 33 6133d25ea14Schristos #define BSN_PDU_RX_REPLY 34 6143d25ea14Schristos #define BSN_PDU_RX_TIMEOUT 35 6153d25ea14Schristos 6163d25ea14Schristos static const struct tok bsn_subtype_str[] = { 6173d25ea14Schristos { BSN_SET_IP_MASK, "SET_IP_MASK" }, 6183d25ea14Schristos { BSN_GET_IP_MASK_REQUEST, "GET_IP_MASK_REQUEST" }, 6193d25ea14Schristos { BSN_GET_IP_MASK_REPLY, "GET_IP_MASK_REPLY" }, 6203d25ea14Schristos { BSN_SET_MIRRORING, "SET_MIRRORING" }, 6213d25ea14Schristos { BSN_GET_MIRRORING_REQUEST, "GET_MIRRORING_REQUEST" }, 6223d25ea14Schristos { BSN_GET_MIRRORING_REPLY, "GET_MIRRORING_REPLY" }, 6233d25ea14Schristos { BSN_SHELL_COMMAND, "SHELL_COMMAND" }, 6243d25ea14Schristos { BSN_SHELL_OUTPUT, "SHELL_OUTPUT" }, 6253d25ea14Schristos { BSN_SHELL_STATUS, "SHELL_STATUS" }, 6263d25ea14Schristos { BSN_GET_INTERFACES_REQUEST, "GET_INTERFACES_REQUEST" }, 6273d25ea14Schristos { BSN_GET_INTERFACES_REPLY, "GET_INTERFACES_REPLY" }, 6283d25ea14Schristos { BSN_SET_PKTIN_SUPPRESSION_REQUEST, "SET_PKTIN_SUPPRESSION_REQUEST" }, 6293d25ea14Schristos { BSN_SET_L2_TABLE_REQUEST, "SET_L2_TABLE_REQUEST" }, 6303d25ea14Schristos { BSN_GET_L2_TABLE_REQUEST, "GET_L2_TABLE_REQUEST" }, 6313d25ea14Schristos { BSN_GET_L2_TABLE_REPLY, "GET_L2_TABLE_REPLY" }, 6323d25ea14Schristos { BSN_VIRTUAL_PORT_CREATE_REQUEST, "VIRTUAL_PORT_CREATE_REQUEST" }, 6333d25ea14Schristos { BSN_VIRTUAL_PORT_CREATE_REPLY, "VIRTUAL_PORT_CREATE_REPLY" }, 6343d25ea14Schristos { BSN_VIRTUAL_PORT_REMOVE_REQUEST, "VIRTUAL_PORT_REMOVE_REQUEST" }, 6353d25ea14Schristos { BSN_BW_ENABLE_SET_REQUEST, "BW_ENABLE_SET_REQUEST" }, 6363d25ea14Schristos { BSN_BW_ENABLE_GET_REQUEST, "BW_ENABLE_GET_REQUEST" }, 6373d25ea14Schristos { BSN_BW_ENABLE_GET_REPLY, "BW_ENABLE_GET_REPLY" }, 6383d25ea14Schristos { BSN_BW_CLEAR_DATA_REQUEST, "BW_CLEAR_DATA_REQUEST" }, 6393d25ea14Schristos { BSN_BW_CLEAR_DATA_REPLY, "BW_CLEAR_DATA_REPLY" }, 6403d25ea14Schristos { BSN_BW_ENABLE_SET_REPLY, "BW_ENABLE_SET_REPLY" }, 6413d25ea14Schristos { BSN_SET_L2_TABLE_REPLY, "SET_L2_TABLE_REPLY" }, 6423d25ea14Schristos { BSN_SET_PKTIN_SUPPRESSION_REPLY, "SET_PKTIN_SUPPRESSION_REPLY" }, 6433d25ea14Schristos { BSN_VIRTUAL_PORT_REMOVE_REPLY, "VIRTUAL_PORT_REMOVE_REPLY" }, 6443d25ea14Schristos { BSN_HYBRID_GET_REQUEST, "HYBRID_GET_REQUEST" }, 6453d25ea14Schristos { BSN_HYBRID_GET_REPLY, "HYBRID_GET_REPLY" }, 6463d25ea14Schristos { BSN_PDU_TX_REQUEST, "PDU_TX_REQUEST" }, 6473d25ea14Schristos { BSN_PDU_TX_REPLY, "PDU_TX_REPLY" }, 6483d25ea14Schristos { BSN_PDU_RX_REQUEST, "PDU_RX_REQUEST" }, 6493d25ea14Schristos { BSN_PDU_RX_REPLY, "PDU_RX_REPLY" }, 6503d25ea14Schristos { BSN_PDU_RX_TIMEOUT, "PDU_RX_TIMEOUT" }, 6513d25ea14Schristos { 0, NULL } 6523d25ea14Schristos }; 6533d25ea14Schristos 6543d25ea14Schristos #define BSN_ACTION_MIRROR 1 6553d25ea14Schristos #define BSN_ACTION_SET_TUNNEL_DST 2 6563d25ea14Schristos /* 3 */ 6573d25ea14Schristos #define BSN_ACTION_CHECKSUM 4 6583d25ea14Schristos 6593d25ea14Schristos static const struct tok bsn_action_subtype_str[] = { 6603d25ea14Schristos { BSN_ACTION_MIRROR, "MIRROR" }, 6613d25ea14Schristos { BSN_ACTION_SET_TUNNEL_DST, "SET_TUNNEL_DST" }, 6623d25ea14Schristos { BSN_ACTION_CHECKSUM, "CHECKSUM" }, 6633d25ea14Schristos { 0, NULL } 6643d25ea14Schristos }; 6653d25ea14Schristos 6663d25ea14Schristos static const struct tok bsn_mirror_copy_stage_str[] = { 6673d25ea14Schristos { 0, "INGRESS" }, 6683d25ea14Schristos { 1, "EGRESS" }, 6693d25ea14Schristos { 0, NULL }, 6703d25ea14Schristos }; 6713d25ea14Schristos 6723d25ea14Schristos static const struct tok bsn_onoff_str[] = { 6733d25ea14Schristos { 0, "OFF" }, 6743d25ea14Schristos { 1, "ON" }, 6753d25ea14Schristos { 0, NULL }, 6763d25ea14Schristos }; 6773d25ea14Schristos 678026d7285Schristos static const char * 6793d25ea14Schristos vlan_str(const uint16_t vid) 6803d25ea14Schristos { 681026d7285Schristos static char buf[sizeof("65535 (bogus)")]; 682026d7285Schristos 683026d7285Schristos if (vid == OFP_VLAN_NONE) 684026d7285Schristos return "NONE"; 685c74ad251Schristos snprintf(buf, sizeof(buf), "%u%s", vid, 686c74ad251Schristos (vid > 0 && vid < 0x0fff) ? "" : " (bogus)"); 687026d7285Schristos return buf; 688026d7285Schristos } 689026d7285Schristos 690026d7285Schristos static const char * 6913d25ea14Schristos pcp_str(const uint8_t pcp) 6923d25ea14Schristos { 693026d7285Schristos static char buf[sizeof("255 (bogus)")]; 694c74ad251Schristos snprintf(buf, sizeof(buf), "%u%s", pcp, 695c74ad251Schristos pcp <= 7 ? "" : " (bogus)"); 696026d7285Schristos return buf; 697026d7285Schristos } 698026d7285Schristos 699026d7285Schristos static void 7003d25ea14Schristos of10_bsn_message_print(netdissect_options *ndo, 701c74ad251Schristos const u_char *cp, u_int len) 7023d25ea14Schristos { 7033d25ea14Schristos uint32_t subtype; 7043d25ea14Schristos 705*26ba0b50Schristos ND_PRINT("\n\t"); 706*26ba0b50Schristos ND_ICHECK_U(len, <, 4); 7073d25ea14Schristos /* subtype */ 708c74ad251Schristos subtype = GET_BE_U_4(cp); 709c74ad251Schristos OF_FWD(4); 710*26ba0b50Schristos ND_PRINT(" subtype %s", tok2str(bsn_subtype_str, "unknown (0x%08x)", subtype)); 7113d25ea14Schristos switch (subtype) { 7123d25ea14Schristos case BSN_GET_IP_MASK_REQUEST: 7133d25ea14Schristos /* 7143d25ea14Schristos * 0 1 2 3 7153d25ea14Schristos * 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 7163d25ea14Schristos * +---------------+---------------+---------------+---------------+ 7173d25ea14Schristos * | subtype | 7183d25ea14Schristos * +---------------+---------------+---------------+---------------+ 7193d25ea14Schristos * | index | pad | 7203d25ea14Schristos * +---------------+---------------+---------------+---------------+ 7213d25ea14Schristos * | pad | 7223d25ea14Schristos * +---------------+---------------+---------------+---------------+ 7233d25ea14Schristos * 7243d25ea14Schristos */ 725*26ba0b50Schristos ND_ICHECK_U(len, !=, 8); 7263d25ea14Schristos /* index */ 727c74ad251Schristos ND_PRINT(", index %u", GET_U_1(cp)); 728c74ad251Schristos OF_FWD(1); 7293d25ea14Schristos /* pad */ 730c74ad251Schristos /* Always the last field, check bounds. */ 731c74ad251Schristos ND_TCHECK_7(cp); 7323d25ea14Schristos break; 7333d25ea14Schristos case BSN_SET_IP_MASK: 7343d25ea14Schristos case BSN_GET_IP_MASK_REPLY: 7353d25ea14Schristos /* 7363d25ea14Schristos * 0 1 2 3 7373d25ea14Schristos * 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 7383d25ea14Schristos * +---------------+---------------+---------------+---------------+ 7393d25ea14Schristos * | subtype | 7403d25ea14Schristos * +---------------+---------------+---------------+---------------+ 7413d25ea14Schristos * | index | pad | 7423d25ea14Schristos * +---------------+---------------+---------------+---------------+ 7433d25ea14Schristos * | mask | 7443d25ea14Schristos * +---------------+---------------+---------------+---------------+ 7453d25ea14Schristos * 7463d25ea14Schristos */ 747*26ba0b50Schristos ND_ICHECK_U(len, !=, 8); 7483d25ea14Schristos /* index */ 749c74ad251Schristos ND_PRINT(", index %u", GET_U_1(cp)); 750c74ad251Schristos OF_FWD(1); 7513d25ea14Schristos /* pad */ 752c74ad251Schristos OF_FWD(3); 7533d25ea14Schristos /* mask */ 754c74ad251Schristos ND_PRINT(", mask %s", GET_IPADDR_STRING(cp)); 7553d25ea14Schristos break; 7563d25ea14Schristos case BSN_SET_MIRRORING: 7573d25ea14Schristos case BSN_GET_MIRRORING_REQUEST: 7583d25ea14Schristos case BSN_GET_MIRRORING_REPLY: 7593d25ea14Schristos /* 7603d25ea14Schristos * 0 1 2 3 7613d25ea14Schristos * 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 7623d25ea14Schristos * +---------------+---------------+---------------+---------------+ 7633d25ea14Schristos * | subtype | 7643d25ea14Schristos * +---------------+---------------+---------------+---------------+ 7653d25ea14Schristos * | report m. p. | pad | 7663d25ea14Schristos * +---------------+---------------+---------------+---------------+ 7673d25ea14Schristos * 7683d25ea14Schristos */ 769*26ba0b50Schristos ND_ICHECK_U(len, !=, 4); 7703d25ea14Schristos /* report_mirror_ports */ 771c74ad251Schristos ND_PRINT(", report_mirror_ports %s", 772c74ad251Schristos tok2str(bsn_onoff_str, "bogus (%u)", GET_U_1(cp))); 773c74ad251Schristos OF_FWD(1); 7743d25ea14Schristos /* pad */ 775c74ad251Schristos /* Always the last field, check bounds. */ 776c74ad251Schristos ND_TCHECK_3(cp); 7773d25ea14Schristos break; 7783d25ea14Schristos case BSN_GET_INTERFACES_REQUEST: 7793d25ea14Schristos case BSN_GET_L2_TABLE_REQUEST: 7803d25ea14Schristos case BSN_BW_ENABLE_GET_REQUEST: 7813d25ea14Schristos case BSN_BW_CLEAR_DATA_REQUEST: 7823d25ea14Schristos case BSN_HYBRID_GET_REQUEST: 7833d25ea14Schristos /* 7843d25ea14Schristos * 0 1 2 3 7853d25ea14Schristos * 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 7863d25ea14Schristos * +---------------+---------------+---------------+---------------+ 7873d25ea14Schristos * | subtype | 7883d25ea14Schristos * +---------------+---------------+---------------+---------------+ 7893d25ea14Schristos * 7903d25ea14Schristos */ 791*26ba0b50Schristos ND_ICHECK_U(len, !=, 0); 7923d25ea14Schristos break; 7933d25ea14Schristos case BSN_VIRTUAL_PORT_REMOVE_REQUEST: 7943d25ea14Schristos /* 7953d25ea14Schristos * 0 1 2 3 7963d25ea14Schristos * 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 7973d25ea14Schristos * +---------------+---------------+---------------+---------------+ 7983d25ea14Schristos * | subtype | 7993d25ea14Schristos * +---------------+---------------+---------------+---------------+ 8003d25ea14Schristos * | vport_no | 8013d25ea14Schristos * +---------------+---------------+---------------+---------------+ 8023d25ea14Schristos * 8033d25ea14Schristos */ 804*26ba0b50Schristos ND_ICHECK_U(len, !=, 4); 8053d25ea14Schristos /* vport_no */ 806c74ad251Schristos ND_PRINT(", vport_no %u", GET_BE_U_4(cp)); 8073d25ea14Schristos break; 8083d25ea14Schristos case BSN_SHELL_COMMAND: 8093d25ea14Schristos /* 8103d25ea14Schristos * 0 1 2 3 8113d25ea14Schristos * 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 8123d25ea14Schristos * +---------------+---------------+---------------+---------------+ 8133d25ea14Schristos * | subtype | 8143d25ea14Schristos * +---------------+---------------+---------------+---------------+ 8153d25ea14Schristos * | service | 8163d25ea14Schristos * +---------------+---------------+---------------+---------------+ 8173d25ea14Schristos * | data ... 8183d25ea14Schristos * +---------------+---------------+-------- 8193d25ea14Schristos * 8203d25ea14Schristos */ 821*26ba0b50Schristos ND_ICHECK_U(len, <, 4); 8223d25ea14Schristos /* service */ 823c74ad251Schristos ND_PRINT(", service %u", GET_BE_U_4(cp)); 824c74ad251Schristos OF_FWD(4); 8253d25ea14Schristos /* data */ 826c74ad251Schristos ND_PRINT(", data '"); 827c74ad251Schristos (void)nd_printn(ndo, cp, len, NULL); 828c74ad251Schristos ND_PRINT("'"); 8293d25ea14Schristos break; 8303d25ea14Schristos case BSN_SHELL_OUTPUT: 8313d25ea14Schristos /* 8323d25ea14Schristos * 0 1 2 3 8333d25ea14Schristos * 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 8343d25ea14Schristos * +---------------+---------------+---------------+---------------+ 8353d25ea14Schristos * | subtype | 8363d25ea14Schristos * +---------------+---------------+---------------+---------------+ 8373d25ea14Schristos * | data ... 8383d25ea14Schristos * +---------------+---------------+-------- 8393d25ea14Schristos * 8403d25ea14Schristos */ 8413d25ea14Schristos /* already checked that len >= 4 */ 8423d25ea14Schristos /* data */ 843c74ad251Schristos ND_PRINT(", data '"); 844c74ad251Schristos (void)nd_printn(ndo, cp, len, NULL); 845c74ad251Schristos ND_PRINT("'"); 8463d25ea14Schristos break; 8473d25ea14Schristos case BSN_SHELL_STATUS: 8483d25ea14Schristos /* 8493d25ea14Schristos * 0 1 2 3 8503d25ea14Schristos * 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 8513d25ea14Schristos * +---------------+---------------+---------------+---------------+ 8523d25ea14Schristos * | subtype | 8533d25ea14Schristos * +---------------+---------------+---------------+---------------+ 8543d25ea14Schristos * | status | 8553d25ea14Schristos * +---------------+---------------+---------------+---------------+ 8563d25ea14Schristos * 8573d25ea14Schristos */ 858*26ba0b50Schristos ND_ICHECK_U(len, !=, 4); 8593d25ea14Schristos /* status */ 860c74ad251Schristos ND_PRINT(", status 0x%08x", GET_BE_U_4(cp)); 8613d25ea14Schristos break; 8623d25ea14Schristos default: 863c74ad251Schristos ND_TCHECK_LEN(cp, len); 8643d25ea14Schristos } 865c74ad251Schristos return; 8663d25ea14Schristos 867784088dfSchristos invalid: /* skip the undersized data */ 868c74ad251Schristos nd_print_invalid(ndo); 869c74ad251Schristos ND_TCHECK_LEN(cp, len); 8703d25ea14Schristos } 8713d25ea14Schristos 872c74ad251Schristos static void 8733d25ea14Schristos of10_bsn_actions_print(netdissect_options *ndo, 874c74ad251Schristos const u_char *cp, u_int len) 8753d25ea14Schristos { 8763d25ea14Schristos uint32_t subtype, vlan_tag; 8773d25ea14Schristos 878*26ba0b50Schristos ND_PRINT("\n\t "); 879*26ba0b50Schristos ND_ICHECK_U(len, <, 4); 8803d25ea14Schristos /* subtype */ 881c74ad251Schristos subtype = GET_BE_U_4(cp); 882c74ad251Schristos OF_FWD(4); 883*26ba0b50Schristos ND_PRINT(" subtype %s", tok2str(bsn_action_subtype_str, "unknown (0x%08x)", subtype)); 8843d25ea14Schristos switch (subtype) { 8853d25ea14Schristos case BSN_ACTION_MIRROR: 8863d25ea14Schristos /* 8873d25ea14Schristos * 0 1 2 3 8883d25ea14Schristos * 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 8893d25ea14Schristos * +---------------+---------------+---------------+---------------+ 8903d25ea14Schristos * | subtype | 8913d25ea14Schristos * +---------------+---------------+---------------+---------------+ 8923d25ea14Schristos * | dest_port | 8933d25ea14Schristos * +---------------+---------------+---------------+---------------+ 8943d25ea14Schristos * | vlan_tag | 8953d25ea14Schristos * +---------------+---------------+---------------+---------------+ 8963d25ea14Schristos * | copy_stage | pad | 8973d25ea14Schristos * +---------------+---------------+---------------+---------------+ 8983d25ea14Schristos * 8993d25ea14Schristos */ 900*26ba0b50Schristos ND_ICHECK_U(len, !=, 12); 9013d25ea14Schristos /* dest_port */ 902c74ad251Schristos ND_PRINT(", dest_port %u", GET_BE_U_4(cp)); 903c74ad251Schristos OF_FWD(4); 9043d25ea14Schristos /* vlan_tag */ 905c74ad251Schristos vlan_tag = GET_BE_U_4(cp); 906c74ad251Schristos OF_FWD(4); 9073d25ea14Schristos switch (vlan_tag >> 16) { 9083d25ea14Schristos case 0: 909c74ad251Schristos ND_PRINT(", vlan_tag none"); 9103d25ea14Schristos break; 9113d25ea14Schristos case ETHERTYPE_8021Q: 912c74ad251Schristos ND_PRINT(", vlan_tag 802.1Q (%s)", ieee8021q_tci_string(vlan_tag & 0xffff)); 9133d25ea14Schristos break; 9143d25ea14Schristos default: 915c74ad251Schristos ND_PRINT(", vlan_tag unknown (0x%04x)", vlan_tag >> 16); 9163d25ea14Schristos } 9173d25ea14Schristos /* copy_stage */ 918c74ad251Schristos ND_PRINT(", copy_stage %s", 919c74ad251Schristos tok2str(bsn_mirror_copy_stage_str, "unknown (%u)", GET_U_1(cp))); 920c74ad251Schristos OF_FWD(1); 9213d25ea14Schristos /* pad */ 922c74ad251Schristos /* Always the last field, check bounds. */ 923c74ad251Schristos ND_TCHECK_3(cp); 9243d25ea14Schristos break; 9253d25ea14Schristos default: 926c74ad251Schristos ND_TCHECK_LEN(cp, len); 9273d25ea14Schristos } 928c74ad251Schristos return; 9293d25ea14Schristos 930784088dfSchristos invalid: 931c74ad251Schristos nd_print_invalid(ndo); 932c74ad251Schristos ND_TCHECK_LEN(cp, len); 9333d25ea14Schristos } 9343d25ea14Schristos 935c74ad251Schristos static void 9363d25ea14Schristos of10_vendor_action_print(netdissect_options *ndo, 937c74ad251Schristos const u_char *cp, u_int len) 9383d25ea14Schristos { 9393d25ea14Schristos uint32_t vendor; 940c74ad251Schristos void (*decoder)(netdissect_options *, const u_char *, u_int); 9413d25ea14Schristos 942*26ba0b50Schristos ND_ICHECK_U(len, <, 4); 943026d7285Schristos /* vendor */ 944c74ad251Schristos vendor = GET_BE_U_4(cp); 945c74ad251Schristos OF_FWD(4); 946c74ad251Schristos ND_PRINT(", vendor 0x%08x (%s)", vendor, of_vendor_name(vendor)); 9473d25ea14Schristos /* data */ 9483d25ea14Schristos decoder = 9493d25ea14Schristos vendor == OUI_BSN ? of10_bsn_actions_print : 950c74ad251Schristos of_data_print; 951c74ad251Schristos decoder(ndo, cp, len); 952c74ad251Schristos return; 9533d25ea14Schristos 954784088dfSchristos invalid: /* skip the undersized data */ 955c74ad251Schristos nd_print_invalid(ndo); 956c74ad251Schristos ND_TCHECK_LEN(cp, len); 9573d25ea14Schristos } 9583d25ea14Schristos 959c74ad251Schristos /* [OF10] Section 5.5.4 */ 960c74ad251Schristos static void 9613d25ea14Schristos of10_vendor_message_print(netdissect_options *ndo, 962c74ad251Schristos const u_char *cp, u_int len) 9633d25ea14Schristos { 9643d25ea14Schristos uint32_t vendor; 965c74ad251Schristos void (*decoder)(netdissect_options *, const u_char *, u_int); 9663d25ea14Schristos 9673d25ea14Schristos /* vendor */ 968c74ad251Schristos vendor = GET_BE_U_4(cp); 969c74ad251Schristos OF_FWD(4); 970c74ad251Schristos ND_PRINT(", vendor 0x%08x (%s)", vendor, of_vendor_name(vendor)); 9713d25ea14Schristos /* data */ 9723d25ea14Schristos decoder = 9733d25ea14Schristos vendor == OUI_BSN ? of10_bsn_message_print : 974c74ad251Schristos of_data_print; 975c74ad251Schristos decoder(ndo, cp, len); 9763d25ea14Schristos } 9773d25ea14Schristos 9783d25ea14Schristos /* Vendor ID is mandatory, data is optional. */ 979c74ad251Schristos static void 9803d25ea14Schristos of10_vendor_data_print(netdissect_options *ndo, 981c74ad251Schristos const u_char *cp, u_int len) 9823d25ea14Schristos { 9833d25ea14Schristos uint32_t vendor; 9843d25ea14Schristos 985*26ba0b50Schristos ND_ICHECK_U(len, <, 4); 9863d25ea14Schristos /* vendor */ 987c74ad251Schristos vendor = GET_BE_U_4(cp); 988c74ad251Schristos OF_FWD(4); 989c74ad251Schristos ND_PRINT(", vendor 0x%08x (%s)", vendor, of_vendor_name(vendor)); 990026d7285Schristos /* data */ 991c74ad251Schristos of_data_print(ndo, cp, len); 992c74ad251Schristos return; 993026d7285Schristos 994784088dfSchristos invalid: /* skip the undersized data */ 995c74ad251Schristos nd_print_invalid(ndo); 996c74ad251Schristos ND_TCHECK_LEN(cp, len); 997026d7285Schristos } 998026d7285Schristos 999c74ad251Schristos static void 1000c47fd378Schristos of10_packet_data_print(netdissect_options *ndo, 1001c74ad251Schristos const u_char *cp, const u_int len) 10023d25ea14Schristos { 1003026d7285Schristos if (len == 0) 1004c74ad251Schristos return; 1005026d7285Schristos /* data */ 1006c74ad251Schristos ND_PRINT("\n\t data (%u octets)", len); 1007c74ad251Schristos if (ndo->ndo_vflag < 3) { 1008c74ad251Schristos ND_TCHECK_LEN(cp, len); 1009c74ad251Schristos return; 1010c74ad251Schristos } 1011c47fd378Schristos ndo->ndo_vflag -= 3; 1012c74ad251Schristos ND_PRINT(", frame decoding below\n"); 1013c74ad251Schristos /* 1014c74ad251Schristos * The encapsulated Ethernet frame is not necessarily the last 1015c74ad251Schristos * data of this packet (i.e. there may be more OpenFlow messages 1016c74ad251Schristos * after the current OFPT_PACKET_IN/OFPT_PACKET_OUT message, in 1017c74ad251Schristos * which case the current (outer) packet's snapshot end is not 1018c74ad251Schristos * what ether_print() needs to decode an Ethernet frame nested in 1019c74ad251Schristos * the middle of a TCP payload. 1020c74ad251Schristos */ 1021c74ad251Schristos const u_char *snapend_save = ndo->ndo_snapend; 1022c74ad251Schristos ndo->ndo_snapend = ND_MIN(cp + len, ndo->ndo_snapend); 1023c74ad251Schristos ether_print(ndo, cp, len, ND_BYTES_AVAILABLE_AFTER(cp), NULL, NULL); 1024c74ad251Schristos ndo->ndo_snapend = snapend_save; 1025c47fd378Schristos ndo->ndo_vflag += 3; 1026026d7285Schristos } 1027026d7285Schristos 1028026d7285Schristos /* [OF10] Section 5.2.1 */ 1029c74ad251Schristos static void 1030c74ad251Schristos of10_phy_port_print(netdissect_options *ndo, 1031c74ad251Schristos const u_char *cp) 10323d25ea14Schristos { 1033c74ad251Schristos uint32_t state; 1034026d7285Schristos 1035026d7285Schristos /* port_no */ 1036c74ad251Schristos ND_PRINT("\n\t port_no %s", 1037c74ad251Schristos tok2str(ofpp_str, "%u", GET_BE_U_2(cp))); 1038026d7285Schristos cp += 2; 1039026d7285Schristos /* hw_addr */ 1040c74ad251Schristos ND_PRINT(", hw_addr %s", GET_ETHERADDR_STRING(cp)); 1041c74ad251Schristos cp += MAC_ADDR_LEN; 1042026d7285Schristos /* name */ 1043c74ad251Schristos ND_PRINT(", name '"); 1044c74ad251Schristos nd_printjnp(ndo, cp, OFP_MAX_PORT_NAME_LEN); 1045c74ad251Schristos ND_PRINT("'"); 1046026d7285Schristos cp += OFP_MAX_PORT_NAME_LEN; 1047026d7285Schristos 1048c47fd378Schristos if (ndo->ndo_vflag < 2) { 1049c74ad251Schristos ND_TCHECK_LEN(cp, 24); 1050c74ad251Schristos return; 1051026d7285Schristos } 1052026d7285Schristos /* config */ 1053c74ad251Schristos ND_PRINT("\n\t config 0x%08x", GET_BE_U_4(cp)); 1054c74ad251Schristos of_bitmap_print(ndo, ofppc_bm, GET_BE_U_4(cp), OFPPC_U); 1055026d7285Schristos cp += 4; 1056026d7285Schristos /* state */ 1057c74ad251Schristos state = GET_BE_U_4(cp); 1058c74ad251Schristos /* 1059c74ad251Schristos * Decode the code point and the single bit separately, but 1060c74ad251Schristos * format the result as a single sequence of comma-separated 1061c74ad251Schristos * strings (see the comments at the OFPPS_ props). 1062c74ad251Schristos */ 1063c74ad251Schristos ND_PRINT("\n\t state 0x%08x (%s%s)%s", state, 1064c74ad251Schristos tok2str(ofpps_stp_str, "", state & OFPPS_STP_MASK), 1065c74ad251Schristos state & OFPPS_LINK_DOWN ? ", LINK_DOWN" : "", 1066c74ad251Schristos state & OFPPS_U ? " (bogus)" : ""); 1067026d7285Schristos cp += 4; 1068026d7285Schristos /* curr */ 1069c74ad251Schristos ND_PRINT("\n\t curr 0x%08x", GET_BE_U_4(cp)); 1070c74ad251Schristos of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U); 1071026d7285Schristos cp += 4; 1072026d7285Schristos /* advertised */ 1073c74ad251Schristos ND_PRINT("\n\t advertised 0x%08x", GET_BE_U_4(cp)); 1074c74ad251Schristos of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U); 1075026d7285Schristos cp += 4; 1076026d7285Schristos /* supported */ 1077c74ad251Schristos ND_PRINT("\n\t supported 0x%08x", GET_BE_U_4(cp)); 1078c74ad251Schristos of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U); 1079026d7285Schristos cp += 4; 1080026d7285Schristos /* peer */ 1081c74ad251Schristos ND_PRINT("\n\t peer 0x%08x", GET_BE_U_4(cp)); 1082c74ad251Schristos of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U); 1083026d7285Schristos } 1084026d7285Schristos 1085026d7285Schristos /* [OF10] Section 5.2.2 */ 1086c74ad251Schristos static void 1087c47fd378Schristos of10_queue_props_print(netdissect_options *ndo, 1088c74ad251Schristos const u_char *cp, u_int len) 10893d25ea14Schristos { 1090026d7285Schristos while (len) { 1091c74ad251Schristos uint16_t property, plen; 1092026d7285Schristos u_char plen_bogus = 0, skip = 0; 1093026d7285Schristos 1094*26ba0b50Schristos ND_PRINT("\n\t "); 1095*26ba0b50Schristos ND_ICHECKMSG_U("remaining length", len, <, OF_QUEUE_PROP_MINLEN); 1096026d7285Schristos /* property */ 1097c74ad251Schristos property = GET_BE_U_2(cp); 1098c74ad251Schristos OF_FWD(2); 1099*26ba0b50Schristos ND_PRINT(" property %s", tok2str(ofpqt_str, "invalid (0x%04x)", property)); 1100026d7285Schristos /* len */ 1101c74ad251Schristos plen = GET_BE_U_2(cp); 1102c74ad251Schristos OF_FWD(2); 1103c74ad251Schristos ND_PRINT(", len %u", plen); 1104*26ba0b50Schristos ND_ICHECKMSG_U("property length", plen, <, OF_QUEUE_PROP_MINLEN); 1105*26ba0b50Schristos ND_ICHECKMSG_U("property length", plen, >, len + 4); 1106026d7285Schristos /* pad */ 1107c74ad251Schristos /* Sometimes the last field, check bounds. */ 1108c74ad251Schristos OF_CHK_FWD(4); 1109026d7285Schristos /* property-specific constraints and decoding */ 1110026d7285Schristos switch (property) { 1111026d7285Schristos case OFPQT_NONE: 1112c74ad251Schristos plen_bogus = plen != OF_QUEUE_PROP_MINLEN; 1113026d7285Schristos break; 1114026d7285Schristos case OFPQT_MIN_RATE: 1115c74ad251Schristos plen_bogus = plen != OF_QUEUE_PROP_MIN_RATE_FIXLEN; 1116026d7285Schristos break; 1117026d7285Schristos default: 1118026d7285Schristos skip = 1; 1119026d7285Schristos } 1120026d7285Schristos if (plen_bogus) { 1121c74ad251Schristos ND_PRINT(" (bogus)"); 1122026d7285Schristos skip = 1; 1123026d7285Schristos } 1124026d7285Schristos if (skip) { 1125c74ad251Schristos /* 1126c74ad251Schristos * plen >= OF_QUEUE_PROP_MINLEN 1127c74ad251Schristos * cp is OF_QUEUE_PROP_MINLEN bytes in 1128c74ad251Schristos */ 1129c74ad251Schristos OF_CHK_FWD(plen - OF_QUEUE_PROP_MINLEN); 1130c74ad251Schristos continue; 1131026d7285Schristos } 1132026d7285Schristos if (property == OFPQT_MIN_RATE) { /* the only case of property decoding */ 1133026d7285Schristos /* rate */ 1134c74ad251Schristos uint16_t rate = GET_BE_U_2(cp); 1135c74ad251Schristos OF_FWD(2); 1136026d7285Schristos if (rate > 1000) 1137c74ad251Schristos ND_PRINT(", rate disabled"); 1138026d7285Schristos else 1139c74ad251Schristos ND_PRINT(", rate %u.%u%%", rate / 10, rate % 10); 1140026d7285Schristos /* pad */ 1141c74ad251Schristos /* Sometimes the last field, check bounds. */ 1142c74ad251Schristos OF_CHK_FWD(6); 1143026d7285Schristos } 1144026d7285Schristos } /* while */ 1145c74ad251Schristos return; 1146026d7285Schristos 1147784088dfSchristos invalid: /* skip the rest of queue properties */ 1148c74ad251Schristos nd_print_invalid(ndo); 1149c74ad251Schristos ND_TCHECK_LEN(cp, len); 1150026d7285Schristos } 1151026d7285Schristos 1152026d7285Schristos /* ibid */ 1153c74ad251Schristos static void 1154c47fd378Schristos of10_queues_print(netdissect_options *ndo, 1155c74ad251Schristos const u_char *cp, u_int len) 11563d25ea14Schristos { 1157c74ad251Schristos while (len) { 1158026d7285Schristos uint16_t desclen; 1159026d7285Schristos 1160*26ba0b50Schristos ND_PRINT("\n\t "); 1161*26ba0b50Schristos ND_ICHECKMSG_U("remaining length", len, <, OF_PACKET_QUEUE_MINLEN); 1162026d7285Schristos /* queue_id */ 1163*26ba0b50Schristos ND_PRINT(" queue_id %u", GET_BE_U_4(cp)); 1164c74ad251Schristos OF_FWD(4); 1165026d7285Schristos /* len */ 1166c74ad251Schristos desclen = GET_BE_U_2(cp); 1167c74ad251Schristos OF_FWD(2); 1168c74ad251Schristos ND_PRINT(", len %u", desclen); 1169*26ba0b50Schristos ND_ICHECKMSG_U("prop. desc. length", desclen, <, OF_PACKET_QUEUE_MINLEN); 1170*26ba0b50Schristos ND_ICHECKMSG_U("prop. desc. length", desclen, >, len + 6); 1171026d7285Schristos /* pad */ 1172c74ad251Schristos /* Sometimes the last field, check bounds. */ 1173c74ad251Schristos OF_CHK_FWD(2); 1174026d7285Schristos /* properties */ 1175c74ad251Schristos if (ndo->ndo_vflag >= 2) 1176c74ad251Schristos of10_queue_props_print(ndo, cp, desclen - OF_PACKET_QUEUE_MINLEN); 1177c74ad251Schristos else 1178c74ad251Schristos ND_TCHECK_LEN(cp, desclen - OF_PACKET_QUEUE_MINLEN); 1179c74ad251Schristos OF_FWD(desclen - OF_PACKET_QUEUE_MINLEN); 1180026d7285Schristos } /* while */ 1181c74ad251Schristos return; 1182026d7285Schristos 1183784088dfSchristos invalid: /* skip the rest of queues */ 1184c74ad251Schristos nd_print_invalid(ndo); 1185c74ad251Schristos ND_TCHECK_LEN(cp, len); 1186026d7285Schristos } 1187026d7285Schristos 1188026d7285Schristos /* [OF10] Section 5.2.3 */ 1189c74ad251Schristos static void 1190c47fd378Schristos of10_match_print(netdissect_options *ndo, 1191c74ad251Schristos const char *pfx, const u_char *cp) 11923d25ea14Schristos { 1193026d7285Schristos uint32_t wildcards; 1194026d7285Schristos uint16_t dl_type; 1195026d7285Schristos uint8_t nw_proto; 1196c74ad251Schristos u_int nw_bits; 1197026d7285Schristos const char *field_name; 1198026d7285Schristos 1199026d7285Schristos /* wildcards */ 1200c74ad251Schristos wildcards = GET_BE_U_4(cp); 1201026d7285Schristos if (wildcards & OFPFW_U) 1202c74ad251Schristos ND_PRINT("%swildcards 0x%08x (bogus)", pfx, wildcards); 1203026d7285Schristos cp += 4; 1204026d7285Schristos /* in_port */ 1205026d7285Schristos if (! (wildcards & OFPFW_IN_PORT)) 1206c74ad251Schristos ND_PRINT("%smatch in_port %s", pfx, 1207c74ad251Schristos tok2str(ofpp_str, "%u", GET_BE_U_2(cp))); 1208026d7285Schristos cp += 2; 1209026d7285Schristos /* dl_src */ 1210026d7285Schristos if (! (wildcards & OFPFW_DL_SRC)) 1211c74ad251Schristos ND_PRINT("%smatch dl_src %s", pfx, GET_ETHERADDR_STRING(cp)); 1212c74ad251Schristos cp += MAC_ADDR_LEN; 1213026d7285Schristos /* dl_dst */ 1214026d7285Schristos if (! (wildcards & OFPFW_DL_DST)) 1215c74ad251Schristos ND_PRINT("%smatch dl_dst %s", pfx, GET_ETHERADDR_STRING(cp)); 1216c74ad251Schristos cp += MAC_ADDR_LEN; 1217026d7285Schristos /* dl_vlan */ 1218026d7285Schristos if (! (wildcards & OFPFW_DL_VLAN)) 1219c74ad251Schristos ND_PRINT("%smatch dl_vlan %s", pfx, vlan_str(GET_BE_U_2(cp))); 1220026d7285Schristos cp += 2; 1221026d7285Schristos /* dl_vlan_pcp */ 1222026d7285Schristos if (! (wildcards & OFPFW_DL_VLAN_PCP)) 1223c74ad251Schristos ND_PRINT("%smatch dl_vlan_pcp %s", pfx, pcp_str(GET_U_1(cp))); 1224026d7285Schristos cp += 1; 1225026d7285Schristos /* pad1 */ 1226026d7285Schristos cp += 1; 1227026d7285Schristos /* dl_type */ 1228c74ad251Schristos dl_type = GET_BE_U_2(cp); 1229026d7285Schristos cp += 2; 1230026d7285Schristos if (! (wildcards & OFPFW_DL_TYPE)) 1231c74ad251Schristos ND_PRINT("%smatch dl_type 0x%04x", pfx, dl_type); 1232026d7285Schristos /* nw_tos */ 1233026d7285Schristos if (! (wildcards & OFPFW_NW_TOS)) 1234c74ad251Schristos ND_PRINT("%smatch nw_tos 0x%02x", pfx, GET_U_1(cp)); 1235026d7285Schristos cp += 1; 1236026d7285Schristos /* nw_proto */ 1237c74ad251Schristos nw_proto = GET_U_1(cp); 1238026d7285Schristos cp += 1; 1239026d7285Schristos if (! (wildcards & OFPFW_NW_PROTO)) { 1240026d7285Schristos field_name = ! (wildcards & OFPFW_DL_TYPE) && dl_type == ETHERTYPE_ARP 1241026d7285Schristos ? "arp_opcode" : "nw_proto"; 1242c74ad251Schristos ND_PRINT("%smatch %s %u", pfx, field_name, nw_proto); 1243026d7285Schristos } 1244026d7285Schristos /* pad2 */ 1245026d7285Schristos cp += 2; 1246026d7285Schristos /* nw_src */ 1247026d7285Schristos nw_bits = (wildcards & OFPFW_NW_SRC_MASK) >> OFPFW_NW_SRC_SHIFT; 1248026d7285Schristos if (nw_bits < 32) 1249c74ad251Schristos ND_PRINT("%smatch nw_src %s/%u", pfx, GET_IPADDR_STRING(cp), 32 - nw_bits); 1250026d7285Schristos cp += 4; 1251026d7285Schristos /* nw_dst */ 1252026d7285Schristos nw_bits = (wildcards & OFPFW_NW_DST_MASK) >> OFPFW_NW_DST_SHIFT; 1253026d7285Schristos if (nw_bits < 32) 1254c74ad251Schristos ND_PRINT("%smatch nw_dst %s/%u", pfx, GET_IPADDR_STRING(cp), 32 - nw_bits); 1255026d7285Schristos cp += 4; 1256026d7285Schristos /* tp_src */ 1257026d7285Schristos if (! (wildcards & OFPFW_TP_SRC)) { 1258026d7285Schristos field_name = ! (wildcards & OFPFW_DL_TYPE) && dl_type == ETHERTYPE_IP 1259026d7285Schristos && ! (wildcards & OFPFW_NW_PROTO) && nw_proto == IPPROTO_ICMP 1260026d7285Schristos ? "icmp_type" : "tp_src"; 1261c74ad251Schristos ND_PRINT("%smatch %s %u", pfx, field_name, GET_BE_U_2(cp)); 1262026d7285Schristos } 1263026d7285Schristos cp += 2; 1264026d7285Schristos /* tp_dst */ 1265c74ad251Schristos /* The last unconditional check was at nw_proto, so have an "else" here. */ 1266026d7285Schristos if (! (wildcards & OFPFW_TP_DST)) { 1267026d7285Schristos field_name = ! (wildcards & OFPFW_DL_TYPE) && dl_type == ETHERTYPE_IP 1268026d7285Schristos && ! (wildcards & OFPFW_NW_PROTO) && nw_proto == IPPROTO_ICMP 1269026d7285Schristos ? "icmp_code" : "tp_dst"; 1270c74ad251Schristos ND_PRINT("%smatch %s %u", pfx, field_name, GET_BE_U_2(cp)); 1271*26ba0b50Schristos } else 1272c74ad251Schristos ND_TCHECK_2(cp); 1273026d7285Schristos } 1274026d7285Schristos 1275026d7285Schristos /* [OF10] Section 5.2.4 */ 1276c74ad251Schristos static void 1277c47fd378Schristos of10_actions_print(netdissect_options *ndo, 1278c74ad251Schristos const char *pfx, const u_char *cp, u_int len) 12793d25ea14Schristos { 1280026d7285Schristos while (len) { 1281c74ad251Schristos uint16_t type, alen, output_port; 1282026d7285Schristos u_char alen_bogus = 0, skip = 0; 1283026d7285Schristos 1284*26ba0b50Schristos ND_PRINT("%saction", pfx); 1285*26ba0b50Schristos ND_ICHECKMSG_U("remaining length", len, <, OF_ACTION_MINLEN); 1286026d7285Schristos /* type */ 1287c74ad251Schristos type = GET_BE_U_2(cp); 1288c74ad251Schristos OF_FWD(2); 1289*26ba0b50Schristos ND_PRINT(" type %s", tok2str(ofpat_str, "invalid (0x%04x)", type)); 1290026d7285Schristos /* length */ 1291c74ad251Schristos alen = GET_BE_U_2(cp); 1292c74ad251Schristos OF_FWD(2); 1293c74ad251Schristos ND_PRINT(", len %u", alen); 1294c74ad251Schristos /* 1295c74ad251Schristos * The 4-byte "pad" in the specification is not a field of the 1296c74ad251Schristos * action header, but a placeholder to illustrate the 64-bit 1297c74ad251Schristos * alignment requirement. Action type specific case blocks 1298c74ad251Schristos * below fetch these 4 bytes. 1299c74ad251Schristos */ 1300c74ad251Schristos 1301026d7285Schristos /* On action size underrun/overrun skip the rest of the action list. */ 1302*26ba0b50Schristos ND_ICHECK_U(alen, <, OF_ACTION_MINLEN); 1303*26ba0b50Schristos ND_ICHECK_U(alen, >, len + 4); 1304c74ad251Schristos /* 1305c74ad251Schristos * After validating the basic length constraint it will be safe 1306c74ad251Schristos * to skip the current action if the action size is not valid 1307c74ad251Schristos * for the type or the type is invalid. 1308c74ad251Schristos */ 1309026d7285Schristos switch (type) { 1310026d7285Schristos case OFPAT_OUTPUT: 1311026d7285Schristos case OFPAT_SET_VLAN_VID: 1312026d7285Schristos case OFPAT_SET_VLAN_PCP: 1313026d7285Schristos case OFPAT_STRIP_VLAN: 1314026d7285Schristos case OFPAT_SET_NW_SRC: 1315026d7285Schristos case OFPAT_SET_NW_DST: 1316026d7285Schristos case OFPAT_SET_NW_TOS: 1317026d7285Schristos case OFPAT_SET_TP_SRC: 1318026d7285Schristos case OFPAT_SET_TP_DST: 1319026d7285Schristos alen_bogus = alen != 8; 1320026d7285Schristos break; 1321026d7285Schristos case OFPAT_SET_DL_SRC: 1322026d7285Schristos case OFPAT_SET_DL_DST: 1323026d7285Schristos case OFPAT_ENQUEUE: 1324026d7285Schristos alen_bogus = alen != 16; 1325026d7285Schristos break; 1326026d7285Schristos case OFPAT_VENDOR: 1327026d7285Schristos alen_bogus = alen % 8 != 0; /* already >= 8 so far */ 1328026d7285Schristos break; 1329026d7285Schristos default: 1330026d7285Schristos skip = 1; 1331026d7285Schristos } 1332026d7285Schristos if (alen_bogus) { 1333c74ad251Schristos ND_PRINT(" (bogus)"); 1334026d7285Schristos skip = 1; 1335026d7285Schristos } 1336026d7285Schristos if (skip) { 1337c74ad251Schristos /* 1338c74ad251Schristos * alen >= OF_ACTION_MINLEN 1339c74ad251Schristos * cp is 4 bytes in 1340c74ad251Schristos */ 1341c74ad251Schristos OF_CHK_FWD(alen - 4); 1342c74ad251Schristos continue; 1343026d7285Schristos } 1344026d7285Schristos /* OK to decode the rest of the action structure */ 1345026d7285Schristos switch (type) { 1346026d7285Schristos case OFPAT_OUTPUT: 1347026d7285Schristos /* port */ 1348c74ad251Schristos output_port = GET_BE_U_2(cp); 1349c74ad251Schristos OF_FWD(2); 1350c74ad251Schristos ND_PRINT(", port %s", tok2str(ofpp_str, "%u", output_port)); 1351026d7285Schristos /* max_len */ 1352026d7285Schristos if (output_port == OFPP_CONTROLLER) 1353c74ad251Schristos ND_PRINT(", max_len %u", GET_BE_U_2(cp)); 1354c74ad251Schristos else 1355c74ad251Schristos ND_TCHECK_2(cp); 1356c74ad251Schristos OF_FWD(2); 1357026d7285Schristos break; 1358026d7285Schristos case OFPAT_SET_VLAN_VID: 1359026d7285Schristos /* vlan_vid */ 1360c74ad251Schristos ND_PRINT(", vlan_vid %s", vlan_str(GET_BE_U_2(cp))); 1361c74ad251Schristos OF_FWD(2); 1362026d7285Schristos /* pad */ 1363c74ad251Schristos /* Sometimes the last field, check bounds. */ 1364c74ad251Schristos OF_CHK_FWD(2); 1365026d7285Schristos break; 1366026d7285Schristos case OFPAT_SET_VLAN_PCP: 1367026d7285Schristos /* vlan_pcp */ 1368c74ad251Schristos ND_PRINT(", vlan_pcp %s", pcp_str(GET_U_1(cp))); 1369c74ad251Schristos OF_FWD(1); 1370026d7285Schristos /* pad */ 1371c74ad251Schristos /* Sometimes the last field, check bounds. */ 1372c74ad251Schristos OF_CHK_FWD(3); 1373026d7285Schristos break; 1374026d7285Schristos case OFPAT_SET_DL_SRC: 1375026d7285Schristos case OFPAT_SET_DL_DST: 1376026d7285Schristos /* dl_addr */ 1377c74ad251Schristos ND_PRINT(", dl_addr %s", GET_ETHERADDR_STRING(cp)); 1378c74ad251Schristos OF_FWD(MAC_ADDR_LEN); 1379026d7285Schristos /* pad */ 1380c74ad251Schristos /* Sometimes the last field, check bounds. */ 1381c74ad251Schristos OF_CHK_FWD(6); 1382026d7285Schristos break; 1383026d7285Schristos case OFPAT_SET_NW_SRC: 1384026d7285Schristos case OFPAT_SET_NW_DST: 1385026d7285Schristos /* nw_addr */ 1386c74ad251Schristos ND_PRINT(", nw_addr %s", GET_IPADDR_STRING(cp)); 1387c74ad251Schristos OF_FWD(4); 1388026d7285Schristos break; 1389026d7285Schristos case OFPAT_SET_NW_TOS: 1390026d7285Schristos /* nw_tos */ 1391c74ad251Schristos ND_PRINT(", nw_tos 0x%02x", GET_U_1(cp)); 1392c74ad251Schristos OF_FWD(1); 1393026d7285Schristos /* pad */ 1394c74ad251Schristos /* Sometimes the last field, check bounds. */ 1395c74ad251Schristos OF_CHK_FWD(3); 1396026d7285Schristos break; 1397026d7285Schristos case OFPAT_SET_TP_SRC: 1398026d7285Schristos case OFPAT_SET_TP_DST: 1399026d7285Schristos /* nw_tos */ 1400c74ad251Schristos ND_PRINT(", tp_port %u", GET_BE_U_2(cp)); 1401c74ad251Schristos OF_FWD(2); 1402026d7285Schristos /* pad */ 1403c74ad251Schristos /* Sometimes the last field, check bounds. */ 1404c74ad251Schristos OF_CHK_FWD(2); 1405026d7285Schristos break; 1406026d7285Schristos case OFPAT_ENQUEUE: 1407026d7285Schristos /* port */ 1408c74ad251Schristos ND_PRINT(", port %s", 1409c74ad251Schristos tok2str(ofpp_str, "%u", GET_BE_U_2(cp))); 1410c74ad251Schristos OF_FWD(2); 1411026d7285Schristos /* pad */ 1412c74ad251Schristos OF_FWD(6); 1413026d7285Schristos /* queue_id */ 1414c74ad251Schristos ND_PRINT(", queue_id %s", 1415c74ad251Schristos tok2str(ofpq_str, "%u", GET_BE_U_4(cp))); 1416c74ad251Schristos OF_FWD(4); 1417026d7285Schristos break; 1418026d7285Schristos case OFPAT_VENDOR: 1419c74ad251Schristos of10_vendor_action_print(ndo, cp, alen - 4); 1420c74ad251Schristos OF_FWD(alen - 4); 1421026d7285Schristos break; 1422026d7285Schristos case OFPAT_STRIP_VLAN: 1423026d7285Schristos /* pad */ 1424c74ad251Schristos /* Sometimes the last field, check bounds. */ 1425c74ad251Schristos OF_CHK_FWD(4); 1426026d7285Schristos break; 1427026d7285Schristos } /* switch */ 1428026d7285Schristos } /* while */ 1429c74ad251Schristos return; 1430026d7285Schristos 1431784088dfSchristos invalid: /* skip the rest of actions */ 1432c74ad251Schristos nd_print_invalid(ndo); 1433c74ad251Schristos ND_TCHECK_LEN(cp, len); 1434026d7285Schristos } 1435026d7285Schristos 1436026d7285Schristos /* [OF10] Section 5.3.1 */ 1437c74ad251Schristos static void 1438c47fd378Schristos of10_features_reply_print(netdissect_options *ndo, 1439c74ad251Schristos const u_char *cp, u_int len) 14403d25ea14Schristos { 1441026d7285Schristos /* datapath_id */ 1442c74ad251Schristos ND_PRINT("\n\t dpid 0x%016" PRIx64, GET_BE_U_8(cp)); 1443c74ad251Schristos OF_FWD(8); 1444026d7285Schristos /* n_buffers */ 1445c74ad251Schristos ND_PRINT(", n_buffers %u", GET_BE_U_4(cp)); 1446c74ad251Schristos OF_FWD(4); 1447026d7285Schristos /* n_tables */ 1448c74ad251Schristos ND_PRINT(", n_tables %u", GET_U_1(cp)); 1449c74ad251Schristos OF_FWD(1); 1450026d7285Schristos /* pad */ 1451c74ad251Schristos OF_FWD(3); 1452026d7285Schristos /* capabilities */ 1453c74ad251Schristos ND_PRINT("\n\t capabilities 0x%08x", GET_BE_U_4(cp)); 1454c74ad251Schristos of_bitmap_print(ndo, ofp_capabilities_bm, GET_BE_U_4(cp), OFPCAP_U); 1455c74ad251Schristos OF_FWD(4); 1456026d7285Schristos /* actions */ 1457c74ad251Schristos ND_PRINT("\n\t actions 0x%08x", GET_BE_U_4(cp)); 1458c74ad251Schristos of_bitmap_print(ndo, ofpat_bm, GET_BE_U_4(cp), OFPAT_U); 1459c74ad251Schristos OF_FWD(4); 1460026d7285Schristos /* ports */ 1461c74ad251Schristos while (len) { 1462*26ba0b50Schristos ND_ICHECKMSG_U("\n\t port def. length", len, <, OF_PHY_PORT_FIXLEN); 1463c74ad251Schristos of10_phy_port_print(ndo, cp); 1464c74ad251Schristos OF_FWD(OF_PHY_PORT_FIXLEN); 1465c74ad251Schristos } 1466c74ad251Schristos return; 1467026d7285Schristos 1468c74ad251Schristos invalid: /* skip the undersized trailing data */ 1469c74ad251Schristos nd_print_invalid(ndo); 1470c74ad251Schristos ND_TCHECK_LEN(cp, len); 1471c74ad251Schristos } 1472c74ad251Schristos 1473c74ad251Schristos /* [OF10] Section 5.3.2 */ 1474c74ad251Schristos static void 1475c74ad251Schristos of10_switch_config_msg_print(netdissect_options *ndo, 1476c74ad251Schristos const u_char *cp, u_int len _U_) 1477c74ad251Schristos { 1478c74ad251Schristos /* flags */ 1479c74ad251Schristos ND_PRINT("\n\t flags %s", 1480c74ad251Schristos tok2str(ofp_config_str, "invalid (0x%04x)", GET_BE_U_2(cp))); 1481c74ad251Schristos cp += 2; 1482c74ad251Schristos /* miss_send_len */ 1483c74ad251Schristos ND_PRINT(", miss_send_len %u", GET_BE_U_2(cp)); 1484026d7285Schristos } 1485026d7285Schristos 1486026d7285Schristos /* [OF10] Section 5.3.3 */ 1487c74ad251Schristos static void 1488c47fd378Schristos of10_flow_mod_print(netdissect_options *ndo, 1489c74ad251Schristos const u_char *cp, u_int len) 14903d25ea14Schristos { 1491026d7285Schristos uint16_t command; 1492026d7285Schristos 1493026d7285Schristos /* match */ 1494c74ad251Schristos of10_match_print(ndo, "\n\t ", cp); 1495c74ad251Schristos OF_FWD(OF_MATCH_FIXLEN); 1496026d7285Schristos /* cookie */ 1497c74ad251Schristos ND_PRINT("\n\t cookie 0x%016" PRIx64, GET_BE_U_8(cp)); 1498c74ad251Schristos OF_FWD(8); 1499026d7285Schristos /* command */ 1500c74ad251Schristos command = GET_BE_U_2(cp); 1501c74ad251Schristos ND_PRINT(", command %s", tok2str(ofpfc_str, "invalid (0x%04x)", command)); 1502c74ad251Schristos OF_FWD(2); 1503026d7285Schristos /* idle_timeout */ 1504c74ad251Schristos if (GET_BE_U_2(cp)) 1505c74ad251Schristos ND_PRINT(", idle_timeout %u", GET_BE_U_2(cp)); 1506c74ad251Schristos OF_FWD(2); 1507026d7285Schristos /* hard_timeout */ 1508c74ad251Schristos if (GET_BE_U_2(cp)) 1509c74ad251Schristos ND_PRINT(", hard_timeout %u", GET_BE_U_2(cp)); 1510c74ad251Schristos OF_FWD(2); 1511026d7285Schristos /* priority */ 1512c74ad251Schristos if (GET_BE_U_2(cp)) 1513c74ad251Schristos ND_PRINT(", priority %u", GET_BE_U_2(cp)); 1514c74ad251Schristos OF_FWD(2); 1515026d7285Schristos /* buffer_id */ 1516026d7285Schristos if (command == OFPFC_ADD || command == OFPFC_MODIFY || 1517026d7285Schristos command == OFPFC_MODIFY_STRICT) 1518c74ad251Schristos ND_PRINT(", buffer_id %s", 1519c74ad251Schristos tok2str(bufferid_str, "0x%08x", GET_BE_U_4(cp))); 1520c74ad251Schristos OF_FWD(4); 1521026d7285Schristos /* out_port */ 1522026d7285Schristos if (command == OFPFC_DELETE || command == OFPFC_DELETE_STRICT) 1523c74ad251Schristos ND_PRINT(", out_port %s", 1524c74ad251Schristos tok2str(ofpp_str, "%u", GET_BE_U_2(cp))); 1525c74ad251Schristos OF_FWD(2); 1526026d7285Schristos /* flags */ 1527c74ad251Schristos ND_PRINT(", flags 0x%04x", GET_BE_U_2(cp)); 1528c74ad251Schristos of_bitmap_print(ndo, ofpff_bm, GET_BE_U_2(cp), OFPFF_U); 1529c74ad251Schristos OF_FWD(2); 1530026d7285Schristos /* actions */ 1531c74ad251Schristos of10_actions_print(ndo, "\n\t ", cp, len); 1532026d7285Schristos } 1533026d7285Schristos 1534026d7285Schristos /* ibid */ 1535c74ad251Schristos static void 1536c47fd378Schristos of10_port_mod_print(netdissect_options *ndo, 1537c74ad251Schristos const u_char *cp, u_int len _U_) 15383d25ea14Schristos { 1539026d7285Schristos /* port_no */ 1540c74ad251Schristos ND_PRINT("\n\t port_no %s", tok2str(ofpp_str, "%u", GET_BE_U_2(cp))); 1541026d7285Schristos cp += 2; 1542026d7285Schristos /* hw_addr */ 1543c74ad251Schristos ND_PRINT(", hw_addr %s", GET_ETHERADDR_STRING(cp)); 1544c74ad251Schristos cp += MAC_ADDR_LEN; 1545026d7285Schristos /* config */ 1546c74ad251Schristos ND_PRINT("\n\t config 0x%08x", GET_BE_U_4(cp)); 1547c74ad251Schristos of_bitmap_print(ndo, ofppc_bm, GET_BE_U_4(cp), OFPPC_U); 1548026d7285Schristos cp += 4; 1549026d7285Schristos /* mask */ 1550c74ad251Schristos ND_PRINT("\n\t mask 0x%08x", GET_BE_U_4(cp)); 1551c74ad251Schristos of_bitmap_print(ndo, ofppc_bm, GET_BE_U_4(cp), OFPPC_U); 1552026d7285Schristos cp += 4; 1553026d7285Schristos /* advertise */ 1554c74ad251Schristos ND_PRINT("\n\t advertise 0x%08x", GET_BE_U_4(cp)); 1555c74ad251Schristos of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U); 1556026d7285Schristos cp += 4; 1557026d7285Schristos /* pad */ 1558c74ad251Schristos /* Always the last field, check bounds. */ 1559c74ad251Schristos ND_TCHECK_4(cp); 1560c74ad251Schristos } 1561026d7285Schristos 1562c74ad251Schristos /* [OF10] Section 5.3.4 */ 1563c74ad251Schristos static void 1564c74ad251Schristos of10_queue_get_config_request_print(netdissect_options *ndo, 1565c74ad251Schristos const u_char *cp, u_int len _U_) 1566c74ad251Schristos { 1567c74ad251Schristos /* port */ 1568c74ad251Schristos ND_PRINT("\n\t port %s", tok2str(ofpp_str, "%u", GET_BE_U_2(cp))); 1569c74ad251Schristos cp += 2; 1570c74ad251Schristos /* pad */ 1571c74ad251Schristos /* Always the last field, check bounds. */ 1572c74ad251Schristos ND_TCHECK_2(cp); 1573c74ad251Schristos } 1574c74ad251Schristos 1575c74ad251Schristos /* ibid */ 1576c74ad251Schristos static void 1577c74ad251Schristos of10_queue_get_config_reply_print(netdissect_options *ndo, 1578c74ad251Schristos const u_char *cp, u_int len) 1579c74ad251Schristos { 1580c74ad251Schristos /* port */ 1581c74ad251Schristos ND_PRINT("\n\t port %s", tok2str(ofpp_str, "%u", GET_BE_U_2(cp))); 1582c74ad251Schristos OF_FWD(2); 1583c74ad251Schristos /* pad */ 1584c74ad251Schristos /* Sometimes the last field, check bounds. */ 1585c74ad251Schristos OF_CHK_FWD(6); 1586c74ad251Schristos /* queues */ 1587c74ad251Schristos of10_queues_print(ndo, cp, len); 1588026d7285Schristos } 1589026d7285Schristos 1590026d7285Schristos /* [OF10] Section 5.3.5 */ 1591c74ad251Schristos static void 1592c47fd378Schristos of10_stats_request_print(netdissect_options *ndo, 1593c74ad251Schristos const u_char *cp, u_int len) 15943d25ea14Schristos { 1595026d7285Schristos uint16_t type; 1596026d7285Schristos 1597026d7285Schristos /* type */ 1598c74ad251Schristos type = GET_BE_U_2(cp); 1599c74ad251Schristos OF_FWD(2); 1600c74ad251Schristos ND_PRINT("\n\t type %s", tok2str(ofpst_str, "invalid (0x%04x)", type)); 1601026d7285Schristos /* flags */ 1602c74ad251Schristos ND_PRINT(", flags 0x%04x", GET_BE_U_2(cp)); 1603c74ad251Schristos if (GET_BE_U_2(cp)) 1604c74ad251Schristos ND_PRINT(" (bogus)"); 1605c74ad251Schristos OF_FWD(2); 1606026d7285Schristos /* type-specific body of one of fixed lengths */ 1607026d7285Schristos switch(type) { 1608026d7285Schristos case OFPST_DESC: 1609026d7285Schristos case OFPST_TABLE: 1610*26ba0b50Schristos ND_ICHECK_U(len, !=, 0); 1611c74ad251Schristos return; 1612026d7285Schristos case OFPST_FLOW: 1613026d7285Schristos case OFPST_AGGREGATE: 1614*26ba0b50Schristos ND_ICHECK_U(len, !=, OF_FLOW_STATS_REQUEST_FIXLEN); 1615026d7285Schristos /* match */ 1616c74ad251Schristos of10_match_print(ndo, "\n\t ", cp); 1617c74ad251Schristos OF_FWD(OF_MATCH_FIXLEN); 1618026d7285Schristos /* table_id */ 1619c74ad251Schristos ND_PRINT("\n\t table_id %s", 1620c74ad251Schristos tok2str(tableid_str, "%u", GET_U_1(cp))); 1621c74ad251Schristos OF_FWD(1); 1622026d7285Schristos /* pad */ 1623c74ad251Schristos OF_FWD(1); 1624026d7285Schristos /* out_port */ 1625c74ad251Schristos ND_PRINT(", out_port %s", 1626c74ad251Schristos tok2str(ofpp_str, "%u", GET_BE_U_2(cp))); 1627c74ad251Schristos return; 1628026d7285Schristos case OFPST_PORT: 1629*26ba0b50Schristos ND_ICHECK_U(len, !=, OF_PORT_STATS_REQUEST_FIXLEN); 1630026d7285Schristos /* port_no */ 1631c74ad251Schristos ND_PRINT("\n\t port_no %s", 1632c74ad251Schristos tok2str(ofpp_str, "%u", GET_BE_U_2(cp))); 1633c74ad251Schristos OF_FWD(2); 1634026d7285Schristos /* pad */ 1635c74ad251Schristos /* Always the last field, check bounds. */ 1636c74ad251Schristos OF_CHK_FWD(6); 1637c74ad251Schristos return; 1638026d7285Schristos case OFPST_QUEUE: 1639*26ba0b50Schristos ND_ICHECK_U(len, !=, OF_QUEUE_STATS_REQUEST_FIXLEN); 1640026d7285Schristos /* port_no */ 1641c74ad251Schristos ND_PRINT("\n\t port_no %s", 1642c74ad251Schristos tok2str(ofpp_str, "%u", GET_BE_U_2(cp))); 1643c74ad251Schristos OF_FWD(2); 1644026d7285Schristos /* pad */ 1645c74ad251Schristos OF_FWD(2); 1646026d7285Schristos /* queue_id */ 1647c74ad251Schristos ND_PRINT(", queue_id %s", 1648c74ad251Schristos tok2str(ofpq_str, "%u", GET_BE_U_4(cp))); 1649c74ad251Schristos return; 1650026d7285Schristos case OFPST_VENDOR: 1651c74ad251Schristos of10_vendor_data_print(ndo, cp, len); 1652c74ad251Schristos return; 1653026d7285Schristos } 1654c74ad251Schristos return; 1655026d7285Schristos 1656784088dfSchristos invalid: /* skip the message body */ 1657c74ad251Schristos nd_print_invalid(ndo); 1658c74ad251Schristos ND_TCHECK_LEN(cp, len); 1659026d7285Schristos } 1660026d7285Schristos 1661026d7285Schristos /* ibid */ 1662c74ad251Schristos static void 1663c47fd378Schristos of10_desc_stats_reply_print(netdissect_options *ndo, 1664c74ad251Schristos const u_char *cp, u_int len) 16653d25ea14Schristos { 1666*26ba0b50Schristos ND_PRINT("\n\t "); 1667*26ba0b50Schristos ND_ICHECK_U(len, !=, OF_DESC_STATS_REPLY_FIXLEN); 1668026d7285Schristos /* mfr_desc */ 1669*26ba0b50Schristos ND_PRINT(" mfr_desc '"); 1670c74ad251Schristos nd_printjnp(ndo, cp, DESC_STR_LEN); 1671c74ad251Schristos ND_PRINT("'"); 1672c74ad251Schristos OF_FWD(DESC_STR_LEN); 1673026d7285Schristos /* hw_desc */ 1674c74ad251Schristos ND_PRINT("\n\t hw_desc '"); 1675c74ad251Schristos nd_printjnp(ndo, cp, DESC_STR_LEN); 1676c74ad251Schristos ND_PRINT("'"); 1677c74ad251Schristos OF_FWD(DESC_STR_LEN); 1678026d7285Schristos /* sw_desc */ 1679c74ad251Schristos ND_PRINT("\n\t sw_desc '"); 1680c74ad251Schristos nd_printjnp(ndo, cp, DESC_STR_LEN); 1681c74ad251Schristos ND_PRINT("'"); 1682c74ad251Schristos OF_FWD(DESC_STR_LEN); 1683026d7285Schristos /* serial_num */ 1684c74ad251Schristos ND_PRINT("\n\t serial_num '"); 1685c74ad251Schristos nd_printjnp(ndo, cp, SERIAL_NUM_LEN); 1686c74ad251Schristos ND_PRINT("'"); 1687c74ad251Schristos OF_FWD(SERIAL_NUM_LEN); 1688026d7285Schristos /* dp_desc */ 1689c74ad251Schristos ND_PRINT("\n\t dp_desc '"); 1690c74ad251Schristos nd_printjnp(ndo, cp, DESC_STR_LEN); 1691c74ad251Schristos ND_PRINT("'"); 1692c74ad251Schristos return; 1693026d7285Schristos 1694784088dfSchristos invalid: /* skip the message body */ 1695c74ad251Schristos nd_print_invalid(ndo); 1696c74ad251Schristos ND_TCHECK_LEN(cp, len); 1697026d7285Schristos } 1698026d7285Schristos 1699026d7285Schristos /* ibid */ 1700c74ad251Schristos static void 1701c47fd378Schristos of10_flow_stats_reply_print(netdissect_options *ndo, 1702c74ad251Schristos const u_char *cp, u_int len) 17033d25ea14Schristos { 1704c74ad251Schristos while (len) { 1705026d7285Schristos uint16_t entry_len; 1706026d7285Schristos 1707*26ba0b50Schristos ND_PRINT("\n\t"); 1708*26ba0b50Schristos ND_ICHECKMSG_U("remaining length", len, <, OF_FLOW_STATS_REPLY_MINLEN); 1709026d7285Schristos /* length */ 1710c74ad251Schristos entry_len = GET_BE_U_2(cp); 1711*26ba0b50Schristos ND_PRINT(" length %u", entry_len); 1712*26ba0b50Schristos ND_ICHECK_U(entry_len, <, OF_FLOW_STATS_REPLY_MINLEN); 1713*26ba0b50Schristos ND_ICHECK_U(entry_len, >, len); 1714c74ad251Schristos OF_FWD(2); 1715026d7285Schristos /* table_id */ 1716c74ad251Schristos ND_PRINT(", table_id %s", 1717c74ad251Schristos tok2str(tableid_str, "%u", GET_U_1(cp))); 1718c74ad251Schristos OF_FWD(1); 1719026d7285Schristos /* pad */ 1720c74ad251Schristos OF_FWD(1); 1721026d7285Schristos /* match */ 1722c74ad251Schristos of10_match_print(ndo, "\n\t ", cp); 1723c74ad251Schristos OF_FWD(OF_MATCH_FIXLEN); 1724026d7285Schristos /* duration_sec */ 1725c74ad251Schristos ND_PRINT("\n\t duration_sec %u", GET_BE_U_4(cp)); 1726c74ad251Schristos OF_FWD(4); 1727026d7285Schristos /* duration_nsec */ 1728c74ad251Schristos ND_PRINT(", duration_nsec %u", GET_BE_U_4(cp)); 1729c74ad251Schristos OF_FWD(4); 1730026d7285Schristos /* priority */ 1731c74ad251Schristos ND_PRINT(", priority %u", GET_BE_U_2(cp)); 1732c74ad251Schristos OF_FWD(2); 1733026d7285Schristos /* idle_timeout */ 1734c74ad251Schristos ND_PRINT(", idle_timeout %u", GET_BE_U_2(cp)); 1735c74ad251Schristos OF_FWD(2); 1736026d7285Schristos /* hard_timeout */ 1737c74ad251Schristos ND_PRINT(", hard_timeout %u", GET_BE_U_2(cp)); 1738c74ad251Schristos OF_FWD(2); 1739026d7285Schristos /* pad2 */ 1740c74ad251Schristos OF_FWD(6); 1741026d7285Schristos /* cookie */ 1742c74ad251Schristos ND_PRINT(", cookie 0x%016" PRIx64, GET_BE_U_8(cp)); 1743c74ad251Schristos OF_FWD(8); 1744026d7285Schristos /* packet_count */ 1745c74ad251Schristos ND_PRINT(", packet_count %" PRIu64, GET_BE_U_8(cp)); 1746c74ad251Schristos OF_FWD(8); 1747026d7285Schristos /* byte_count */ 1748c74ad251Schristos ND_PRINT(", byte_count %" PRIu64, GET_BE_U_8(cp)); 1749c74ad251Schristos OF_FWD(8); 1750026d7285Schristos /* actions */ 1751c74ad251Schristos of10_actions_print(ndo, "\n\t ", cp, entry_len - OF_FLOW_STATS_REPLY_MINLEN); 1752c74ad251Schristos OF_FWD(entry_len - OF_FLOW_STATS_REPLY_MINLEN); 1753026d7285Schristos } /* while */ 1754c74ad251Schristos return; 1755026d7285Schristos 1756784088dfSchristos invalid: /* skip the rest of flow statistics entries */ 1757c74ad251Schristos nd_print_invalid(ndo); 1758c74ad251Schristos ND_TCHECK_LEN(cp, len); 1759026d7285Schristos } 1760026d7285Schristos 1761026d7285Schristos /* ibid */ 1762c74ad251Schristos static void 1763c47fd378Schristos of10_aggregate_stats_reply_print(netdissect_options *ndo, 1764c74ad251Schristos const u_char *cp, u_int len) 17653d25ea14Schristos { 1766*26ba0b50Schristos ND_PRINT("\n\t"); 1767*26ba0b50Schristos ND_ICHECKMSG_U("remaining length", len, !=, OF_AGGREGATE_STATS_REPLY_FIXLEN); 1768026d7285Schristos /* packet_count */ 1769*26ba0b50Schristos ND_PRINT(" packet_count %" PRIu64, GET_BE_U_8(cp)); 1770c74ad251Schristos OF_FWD(8); 1771026d7285Schristos /* byte_count */ 1772c74ad251Schristos ND_PRINT(", byte_count %" PRIu64, GET_BE_U_8(cp)); 1773c74ad251Schristos OF_FWD(8); 1774026d7285Schristos /* flow_count */ 1775c74ad251Schristos ND_PRINT(", flow_count %u", GET_BE_U_4(cp)); 1776c74ad251Schristos OF_FWD(4); 1777026d7285Schristos /* pad */ 1778c74ad251Schristos /* Always the last field, check bounds. */ 1779c74ad251Schristos ND_TCHECK_4(cp); 1780c74ad251Schristos return; 1781026d7285Schristos 1782784088dfSchristos invalid: /* skip the message body */ 1783c74ad251Schristos nd_print_invalid(ndo); 1784c74ad251Schristos ND_TCHECK_LEN(cp, len); 1785026d7285Schristos } 1786026d7285Schristos 1787026d7285Schristos /* ibid */ 1788c74ad251Schristos static void 1789c47fd378Schristos of10_table_stats_reply_print(netdissect_options *ndo, 1790c74ad251Schristos const u_char *cp, u_int len) 17913d25ea14Schristos { 1792026d7285Schristos while (len) { 1793*26ba0b50Schristos ND_PRINT("\n\t"); 1794*26ba0b50Schristos ND_ICHECKMSG_U("remaining length", len, <, OF_TABLE_STATS_REPLY_FIXLEN); 1795026d7285Schristos /* table_id */ 1796*26ba0b50Schristos ND_PRINT(" table_id %s", 1797c74ad251Schristos tok2str(tableid_str, "%u", GET_U_1(cp))); 1798c74ad251Schristos OF_FWD(1); 1799026d7285Schristos /* pad */ 1800c74ad251Schristos OF_FWD(3); 1801026d7285Schristos /* name */ 1802c74ad251Schristos ND_PRINT(", name '"); 1803c74ad251Schristos nd_printjnp(ndo, cp, OFP_MAX_TABLE_NAME_LEN); 1804c74ad251Schristos ND_PRINT("'"); 1805c74ad251Schristos OF_FWD(OFP_MAX_TABLE_NAME_LEN); 1806026d7285Schristos /* wildcards */ 1807c74ad251Schristos ND_PRINT("\n\t wildcards 0x%08x", GET_BE_U_4(cp)); 1808c74ad251Schristos of_bitmap_print(ndo, ofpfw_bm, GET_BE_U_4(cp), OFPFW_U); 1809c74ad251Schristos OF_FWD(4); 1810026d7285Schristos /* max_entries */ 1811c74ad251Schristos ND_PRINT("\n\t max_entries %u", GET_BE_U_4(cp)); 1812c74ad251Schristos OF_FWD(4); 1813026d7285Schristos /* active_count */ 1814c74ad251Schristos ND_PRINT(", active_count %u", GET_BE_U_4(cp)); 1815c74ad251Schristos OF_FWD(4); 1816026d7285Schristos /* lookup_count */ 1817c74ad251Schristos ND_PRINT(", lookup_count %" PRIu64, GET_BE_U_8(cp)); 1818c74ad251Schristos OF_FWD(8); 1819026d7285Schristos /* matched_count */ 1820c74ad251Schristos ND_PRINT(", matched_count %" PRIu64, GET_BE_U_8(cp)); 1821c74ad251Schristos OF_FWD(8); 1822026d7285Schristos } /* while */ 1823c74ad251Schristos return; 1824026d7285Schristos 1825784088dfSchristos invalid: /* skip the undersized trailing data */ 1826c74ad251Schristos nd_print_invalid(ndo); 1827c74ad251Schristos ND_TCHECK_LEN(cp, len); 1828026d7285Schristos } 1829026d7285Schristos 1830026d7285Schristos /* ibid */ 1831c74ad251Schristos static void 1832c47fd378Schristos of10_port_stats_reply_print(netdissect_options *ndo, 1833c74ad251Schristos const u_char *cp, u_int len) 18343d25ea14Schristos { 1835026d7285Schristos while (len) { 1836*26ba0b50Schristos ND_PRINT("\n\t "); 1837*26ba0b50Schristos ND_ICHECKMSG_U("remaining length", len, <, OF_PORT_STATS_REPLY_FIXLEN); 1838026d7285Schristos /* port_no */ 1839*26ba0b50Schristos ND_PRINT(" port_no %s", 1840c74ad251Schristos tok2str(ofpp_str, "%u", GET_BE_U_2(cp))); 1841c74ad251Schristos OF_FWD(2); 1842c47fd378Schristos if (ndo->ndo_vflag < 2) { 1843c74ad251Schristos OF_CHK_FWD(OF_PORT_STATS_REPLY_FIXLEN - 2); 1844c74ad251Schristos continue; 1845026d7285Schristos } 1846026d7285Schristos /* pad */ 1847c74ad251Schristos OF_FWD(6); 1848026d7285Schristos /* rx_packets */ 1849c74ad251Schristos ND_PRINT(", rx_packets %" PRIu64, GET_BE_U_8(cp)); 1850c74ad251Schristos OF_FWD(8); 1851026d7285Schristos /* tx_packets */ 1852c74ad251Schristos ND_PRINT(", tx_packets %" PRIu64, GET_BE_U_8(cp)); 1853c74ad251Schristos OF_FWD(8); 1854026d7285Schristos /* rx_bytes */ 1855c74ad251Schristos ND_PRINT(", rx_bytes %" PRIu64, GET_BE_U_8(cp)); 1856c74ad251Schristos OF_FWD(8); 1857026d7285Schristos /* tx_bytes */ 1858c74ad251Schristos ND_PRINT(", tx_bytes %" PRIu64, GET_BE_U_8(cp)); 1859c74ad251Schristos OF_FWD(8); 1860026d7285Schristos /* rx_dropped */ 1861c74ad251Schristos ND_PRINT(", rx_dropped %" PRIu64, GET_BE_U_8(cp)); 1862c74ad251Schristos OF_FWD(8); 1863026d7285Schristos /* tx_dropped */ 1864c74ad251Schristos ND_PRINT(", tx_dropped %" PRIu64, GET_BE_U_8(cp)); 1865c74ad251Schristos OF_FWD(8); 1866026d7285Schristos /* rx_errors */ 1867c74ad251Schristos ND_PRINT(", rx_errors %" PRIu64, GET_BE_U_8(cp)); 1868c74ad251Schristos OF_FWD(8); 1869026d7285Schristos /* tx_errors */ 1870c74ad251Schristos ND_PRINT(", tx_errors %" PRIu64, GET_BE_U_8(cp)); 1871c74ad251Schristos OF_FWD(8); 1872026d7285Schristos /* rx_frame_err */ 1873c74ad251Schristos ND_PRINT(", rx_frame_err %" PRIu64, GET_BE_U_8(cp)); 1874c74ad251Schristos OF_FWD(8); 1875026d7285Schristos /* rx_over_err */ 1876c74ad251Schristos ND_PRINT(", rx_over_err %" PRIu64, GET_BE_U_8(cp)); 1877c74ad251Schristos OF_FWD(8); 1878026d7285Schristos /* rx_crc_err */ 1879c74ad251Schristos ND_PRINT(", rx_crc_err %" PRIu64, GET_BE_U_8(cp)); 1880c74ad251Schristos OF_FWD(8); 1881026d7285Schristos /* collisions */ 1882c74ad251Schristos ND_PRINT(", collisions %" PRIu64, GET_BE_U_8(cp)); 1883c74ad251Schristos OF_FWD(8); 1884026d7285Schristos } /* while */ 1885c74ad251Schristos return; 1886026d7285Schristos 1887784088dfSchristos invalid: /* skip the undersized trailing data */ 1888c74ad251Schristos nd_print_invalid(ndo); 1889c74ad251Schristos ND_TCHECK_LEN(cp, len); 1890026d7285Schristos } 1891026d7285Schristos 1892026d7285Schristos /* ibid */ 1893c74ad251Schristos static void 1894c47fd378Schristos of10_queue_stats_reply_print(netdissect_options *ndo, 1895c74ad251Schristos const u_char *cp, u_int len) 18963d25ea14Schristos { 1897026d7285Schristos while (len) { 1898*26ba0b50Schristos ND_PRINT("\n\t "); 1899*26ba0b50Schristos ND_ICHECKMSG_U("remaining length", len, <, OF_QUEUE_STATS_REPLY_FIXLEN); 1900026d7285Schristos /* port_no */ 1901*26ba0b50Schristos ND_PRINT(" port_no %s", 1902c74ad251Schristos tok2str(ofpp_str, "%u", GET_BE_U_2(cp))); 1903c74ad251Schristos OF_FWD(2); 1904026d7285Schristos /* pad */ 1905c74ad251Schristos OF_FWD(2); 1906026d7285Schristos /* queue_id */ 1907c74ad251Schristos ND_PRINT(", queue_id %u", GET_BE_U_4(cp)); 1908c74ad251Schristos OF_FWD(4); 1909026d7285Schristos /* tx_bytes */ 1910c74ad251Schristos ND_PRINT(", tx_bytes %" PRIu64, GET_BE_U_8(cp)); 1911c74ad251Schristos OF_FWD(8); 1912026d7285Schristos /* tx_packets */ 1913c74ad251Schristos ND_PRINT(", tx_packets %" PRIu64, GET_BE_U_8(cp)); 1914c74ad251Schristos OF_FWD(8); 1915026d7285Schristos /* tx_errors */ 1916c74ad251Schristos ND_PRINT(", tx_errors %" PRIu64, GET_BE_U_8(cp)); 1917c74ad251Schristos OF_FWD(8); 1918026d7285Schristos } /* while */ 1919c74ad251Schristos return; 1920026d7285Schristos 1921784088dfSchristos invalid: /* skip the undersized trailing data */ 1922c74ad251Schristos nd_print_invalid(ndo); 1923c74ad251Schristos ND_TCHECK_LEN(cp, len); 1924026d7285Schristos } 1925026d7285Schristos 1926026d7285Schristos /* ibid */ 1927c74ad251Schristos static void 1928c47fd378Schristos of10_stats_reply_print(netdissect_options *ndo, 1929c74ad251Schristos const u_char *cp, u_int len) 19303d25ea14Schristos { 1931026d7285Schristos uint16_t type; 1932026d7285Schristos 1933026d7285Schristos /* type */ 1934c74ad251Schristos type = GET_BE_U_2(cp); 1935c74ad251Schristos ND_PRINT("\n\t type %s", tok2str(ofpst_str, "invalid (0x%04x)", type)); 1936c74ad251Schristos OF_FWD(2); 1937026d7285Schristos /* flags */ 1938c74ad251Schristos ND_PRINT(", flags 0x%04x", GET_BE_U_2(cp)); 1939c74ad251Schristos of_bitmap_print(ndo, ofpsf_reply_bm, GET_BE_U_2(cp), OFPSF_REPLY_U); 1940c74ad251Schristos OF_FWD(2); 1941026d7285Schristos 1942c47fd378Schristos if (ndo->ndo_vflag > 0) { 1943c74ad251Schristos void (*decoder)(netdissect_options *, const u_char *, u_int) = 1944026d7285Schristos type == OFPST_DESC ? of10_desc_stats_reply_print : 1945026d7285Schristos type == OFPST_FLOW ? of10_flow_stats_reply_print : 1946026d7285Schristos type == OFPST_AGGREGATE ? of10_aggregate_stats_reply_print : 1947026d7285Schristos type == OFPST_TABLE ? of10_table_stats_reply_print : 1948026d7285Schristos type == OFPST_PORT ? of10_port_stats_reply_print : 1949026d7285Schristos type == OFPST_QUEUE ? of10_queue_stats_reply_print : 1950026d7285Schristos type == OFPST_VENDOR ? of10_vendor_data_print : 1951026d7285Schristos NULL; 1952c74ad251Schristos if (decoder != NULL) { 1953c74ad251Schristos decoder(ndo, cp, len); 1954c74ad251Schristos return; 1955026d7285Schristos } 1956c74ad251Schristos } 1957c74ad251Schristos ND_TCHECK_LEN(cp, len); 1958026d7285Schristos } 1959026d7285Schristos 1960026d7285Schristos /* [OF10] Section 5.3.6 */ 1961c74ad251Schristos static void 1962c47fd378Schristos of10_packet_out_print(netdissect_options *ndo, 1963c74ad251Schristos const u_char *cp, u_int len) 19643d25ea14Schristos { 1965026d7285Schristos uint16_t actions_len; 1966026d7285Schristos 1967026d7285Schristos /* buffer_id */ 1968c74ad251Schristos ND_PRINT("\n\t buffer_id 0x%08x", GET_BE_U_4(cp)); 1969c74ad251Schristos OF_FWD(4); 1970026d7285Schristos /* in_port */ 1971c74ad251Schristos ND_PRINT(", in_port %s", tok2str(ofpp_str, "%u", GET_BE_U_2(cp))); 1972c74ad251Schristos OF_FWD(2); 1973026d7285Schristos /* actions_len */ 1974c74ad251Schristos actions_len = GET_BE_U_2(cp); 1975*26ba0b50Schristos ND_PRINT(", actions_len %u", actions_len); 1976c74ad251Schristos OF_FWD(2); 1977*26ba0b50Schristos ND_ICHECK_U(actions_len, >, len); 1978026d7285Schristos /* actions */ 1979c74ad251Schristos of10_actions_print(ndo, "\n\t ", cp, actions_len); 1980c74ad251Schristos OF_FWD(actions_len); 1981026d7285Schristos /* data */ 1982c74ad251Schristos of10_packet_data_print(ndo, cp, len); 1983c74ad251Schristos return; 1984026d7285Schristos 1985784088dfSchristos invalid: /* skip the rest of the message body */ 1986c74ad251Schristos nd_print_invalid(ndo); 1987c74ad251Schristos ND_TCHECK_LEN(cp, len); 1988026d7285Schristos } 1989026d7285Schristos 1990026d7285Schristos /* [OF10] Section 5.4.1 */ 1991c74ad251Schristos static void 1992c47fd378Schristos of10_packet_in_print(netdissect_options *ndo, 1993c74ad251Schristos const u_char *cp, u_int len) 19943d25ea14Schristos { 1995026d7285Schristos /* buffer_id */ 1996c74ad251Schristos ND_PRINT("\n\t buffer_id %s", 1997c74ad251Schristos tok2str(bufferid_str, "0x%08x", GET_BE_U_4(cp))); 1998c74ad251Schristos OF_FWD(4); 1999026d7285Schristos /* total_len */ 2000c74ad251Schristos ND_PRINT(", total_len %u", GET_BE_U_2(cp)); 2001c74ad251Schristos OF_FWD(2); 2002026d7285Schristos /* in_port */ 2003c74ad251Schristos ND_PRINT(", in_port %s", tok2str(ofpp_str, "%u", GET_BE_U_2(cp))); 2004c74ad251Schristos OF_FWD(2); 2005026d7285Schristos /* reason */ 2006c74ad251Schristos ND_PRINT(", reason %s", 2007c74ad251Schristos tok2str(ofpr_str, "invalid (0x%02x)", GET_U_1(cp))); 2008c74ad251Schristos OF_FWD(1); 2009026d7285Schristos /* pad */ 2010c74ad251Schristos /* Sometimes the last field, check bounds. */ 2011c74ad251Schristos OF_CHK_FWD(1); 2012026d7285Schristos /* data */ 2013c74ad251Schristos of10_packet_data_print(ndo, cp, len); 2014026d7285Schristos } 2015026d7285Schristos 2016026d7285Schristos /* [OF10] Section 5.4.2 */ 2017c74ad251Schristos static void 2018c47fd378Schristos of10_flow_removed_print(netdissect_options *ndo, 2019c74ad251Schristos const u_char *cp, u_int len _U_) 20203d25ea14Schristos { 2021026d7285Schristos /* match */ 2022c74ad251Schristos of10_match_print(ndo, "\n\t ", cp); 2023c74ad251Schristos cp += OF_MATCH_FIXLEN; 2024026d7285Schristos /* cookie */ 2025c74ad251Schristos ND_PRINT("\n\t cookie 0x%016" PRIx64, GET_BE_U_8(cp)); 2026026d7285Schristos cp += 8; 2027026d7285Schristos /* priority */ 2028c74ad251Schristos if (GET_BE_U_2(cp)) 2029c74ad251Schristos ND_PRINT(", priority %u", GET_BE_U_2(cp)); 2030026d7285Schristos cp += 2; 2031026d7285Schristos /* reason */ 2032c74ad251Schristos ND_PRINT(", reason %s", 2033c74ad251Schristos tok2str(ofprr_str, "unknown (0x%02x)", GET_U_1(cp))); 2034026d7285Schristos cp += 1; 2035026d7285Schristos /* pad */ 2036026d7285Schristos cp += 1; 2037026d7285Schristos /* duration_sec */ 2038c74ad251Schristos ND_PRINT(", duration_sec %u", GET_BE_U_4(cp)); 2039026d7285Schristos cp += 4; 2040026d7285Schristos /* duration_nsec */ 2041c74ad251Schristos ND_PRINT(", duration_nsec %u", GET_BE_U_4(cp)); 2042026d7285Schristos cp += 4; 2043026d7285Schristos /* idle_timeout */ 2044c74ad251Schristos if (GET_BE_U_2(cp)) 2045c74ad251Schristos ND_PRINT(", idle_timeout %u", GET_BE_U_2(cp)); 2046026d7285Schristos cp += 2; 2047026d7285Schristos /* pad2 */ 2048026d7285Schristos cp += 2; 2049026d7285Schristos /* packet_count */ 2050c74ad251Schristos ND_PRINT(", packet_count %" PRIu64, GET_BE_U_8(cp)); 2051026d7285Schristos cp += 8; 2052026d7285Schristos /* byte_count */ 2053c74ad251Schristos ND_PRINT(", byte_count %" PRIu64, GET_BE_U_8(cp)); 2054c74ad251Schristos } 2055026d7285Schristos 2056c74ad251Schristos /* [OF10] Section 5.4.3 */ 2057c74ad251Schristos static void 2058c74ad251Schristos of10_port_status_print(netdissect_options *ndo, 2059c74ad251Schristos const u_char *cp, u_int len _U_) 2060c74ad251Schristos { 2061c74ad251Schristos /* reason */ 2062c74ad251Schristos ND_PRINT("\n\t reason %s", 2063c74ad251Schristos tok2str(ofppr_str, "invalid (0x%02x)", GET_U_1(cp))); 2064c74ad251Schristos cp += 1; 2065c74ad251Schristos /* pad */ 2066c74ad251Schristos /* No need to check bounds, more data follows. */ 2067c74ad251Schristos cp += 7; 2068c74ad251Schristos /* desc */ 2069c74ad251Schristos of10_phy_port_print(ndo, cp); 2070026d7285Schristos } 2071026d7285Schristos 2072026d7285Schristos /* [OF10] Section 5.4.4 */ 2073c74ad251Schristos static void 2074c47fd378Schristos of10_error_print(netdissect_options *ndo, 2075c74ad251Schristos const u_char *cp, u_int len) 20763d25ea14Schristos { 2077c74ad251Schristos uint16_t type, code; 2078026d7285Schristos const struct tok *code_str; 2079026d7285Schristos 2080026d7285Schristos /* type */ 2081c74ad251Schristos type = GET_BE_U_2(cp); 2082c74ad251Schristos OF_FWD(2); 2083c74ad251Schristos ND_PRINT("\n\t type %s", tok2str(ofpet_str, "invalid (0x%04x)", type)); 2084026d7285Schristos /* code */ 2085c74ad251Schristos code = GET_BE_U_2(cp); 2086c74ad251Schristos OF_FWD(2); 2087c74ad251Schristos code_str = uint2tokary(of10_ofpet2tokary, type); 2088c74ad251Schristos if (code_str != NULL) 2089c74ad251Schristos ND_PRINT(", code %s", 2090c74ad251Schristos tok2str(code_str, "invalid (0x%04x)", code)); 2091c74ad251Schristos else 2092c74ad251Schristos ND_PRINT(", code invalid (0x%04x)", code); 2093026d7285Schristos /* data */ 2094c74ad251Schristos of_data_print(ndo, cp, len); 2095026d7285Schristos } 2096026d7285Schristos 2097c74ad251Schristos static const struct of_msgtypeinfo of10_msgtypeinfo[OFPT_MAX + 1] = { 2098c74ad251Schristos /* 2099c74ad251Schristos * [OF10] Section 5.5.1 2100c74ad251Schristos * Variable-size data. 2101c74ad251Schristos */ 21023d25ea14Schristos { 2103c74ad251Schristos "HELLO", of_data_print, 2104c74ad251Schristos REQ_MINLEN, 0 2105c74ad251Schristos }, 2106c74ad251Schristos /* 2107c74ad251Schristos * [OF10] Section 5.4.4 2108c74ad251Schristos * A fixed-size message body and variable-size data. 2109c74ad251Schristos */ 2110c74ad251Schristos { 2111c74ad251Schristos "ERROR", of10_error_print, 2112c74ad251Schristos REQ_MINLEN, OF_ERROR_MSG_MINLEN 2113c74ad251Schristos }, 2114c74ad251Schristos /* 2115c74ad251Schristos * [OF10] Section 5.5.2 2116c74ad251Schristos * Variable-size data. 2117c74ad251Schristos */ 2118c74ad251Schristos { 2119c74ad251Schristos "ECHO_REQUEST", of_data_print, 2120c74ad251Schristos REQ_MINLEN, 0 2121c74ad251Schristos }, 2122c74ad251Schristos /* 2123c74ad251Schristos * [OF10] Section 5.5.3 2124c74ad251Schristos * Variable-size data. 2125c74ad251Schristos */ 2126c74ad251Schristos { 2127c74ad251Schristos "ECHO_REPLY", of_data_print, 2128c74ad251Schristos REQ_MINLEN, 0 2129c74ad251Schristos }, 2130c74ad251Schristos /* 2131c74ad251Schristos * [OF10] Section 5.5.4 2132c74ad251Schristos * A fixed-size message body and variable-size data. 2133c74ad251Schristos */ 2134c74ad251Schristos { 2135c74ad251Schristos "VENDOR", of10_vendor_message_print, 2136c74ad251Schristos REQ_MINLEN, OF_VENDOR_MINLEN 2137c74ad251Schristos }, 2138c74ad251Schristos /* 2139c74ad251Schristos * [OF10] Section 5.3.1 2140c74ad251Schristos * No message body. 2141c74ad251Schristos */ 2142c74ad251Schristos { 2143c74ad251Schristos "FEATURES_REQUEST", NULL, 2144c74ad251Schristos REQ_FIXLEN, 0 2145c74ad251Schristos }, 2146c74ad251Schristos /* 2147c74ad251Schristos * [OF10] Section 5.3.1 2148c74ad251Schristos * A fixed-size message body and n * fixed-size data units. 2149c74ad251Schristos */ 2150c74ad251Schristos { 2151c74ad251Schristos "FEATURES_REPLY", of10_features_reply_print, 2152c74ad251Schristos REQ_MINLEN, OF_FEATURES_REPLY_MINLEN 2153c74ad251Schristos }, 2154c74ad251Schristos /* 2155c74ad251Schristos * [OF10] Section 5.3.2 2156c74ad251Schristos * No message body. 2157c74ad251Schristos */ 2158c74ad251Schristos { 2159c74ad251Schristos "GET_CONFIG_REQUEST", NULL, 2160c74ad251Schristos REQ_FIXLEN, 0 2161c74ad251Schristos }, 2162c74ad251Schristos /* 2163c74ad251Schristos * [OF10] Section 5.3.2 2164c74ad251Schristos * A fixed-size message body. 2165c74ad251Schristos */ 2166c74ad251Schristos { 2167c74ad251Schristos "GET_CONFIG_REPLY", of10_switch_config_msg_print, 2168c74ad251Schristos REQ_FIXLEN, OF_SWITCH_CONFIG_FIXLEN 2169c74ad251Schristos }, 2170c74ad251Schristos /* 2171c74ad251Schristos * [OF10] Section 5.3.2 2172c74ad251Schristos * A fixed-size message body. 2173c74ad251Schristos */ 2174c74ad251Schristos { 2175c74ad251Schristos "SET_CONFIG", of10_switch_config_msg_print, 2176c74ad251Schristos REQ_FIXLEN, OF_SWITCH_CONFIG_FIXLEN 2177c74ad251Schristos }, 2178c74ad251Schristos /* 2179c74ad251Schristos * [OF10] Section 5.4.1 2180c74ad251Schristos * A fixed-size message body and variable-size data. 2181c74ad251Schristos * (The 2 mock octets count in OF_PACKET_IN_MINLEN only.) 2182c74ad251Schristos */ 2183c74ad251Schristos { 2184c74ad251Schristos "PACKET_IN", of10_packet_in_print, 2185c74ad251Schristos REQ_MINLEN, OF_PACKET_IN_MINLEN - 2 2186c74ad251Schristos }, 2187c74ad251Schristos /* 2188c74ad251Schristos * [OF10] Section 5.4.2 2189c74ad251Schristos * A fixed-size message body. 2190c74ad251Schristos */ 2191c74ad251Schristos { 2192c74ad251Schristos "FLOW_REMOVED", of10_flow_removed_print, 2193c74ad251Schristos REQ_FIXLEN, OF_FLOW_REMOVED_FIXLEN 2194c74ad251Schristos }, 2195c74ad251Schristos /* 2196c74ad251Schristos * [OF10] Section 5.4.3 2197c74ad251Schristos * A fixed-size message body. 2198c74ad251Schristos */ 2199c74ad251Schristos { 2200c74ad251Schristos "PORT_STATUS", of10_port_status_print, 2201c74ad251Schristos REQ_FIXLEN, OF_PORT_STATUS_FIXLEN 2202c74ad251Schristos }, 2203c74ad251Schristos /* 2204c74ad251Schristos * [OF10] Section 5.3.6 2205c74ad251Schristos * A fixed-size message body, n * variable-size data units and 2206c74ad251Schristos * variable-size data. 2207c74ad251Schristos */ 2208c74ad251Schristos { 2209c74ad251Schristos "PACKET_OUT", of10_packet_out_print, 2210c74ad251Schristos REQ_MINLEN, OF_PACKET_OUT_MINLEN 2211c74ad251Schristos }, 2212c74ad251Schristos /* 2213c74ad251Schristos * [OF10] Section 5.3.3 2214c74ad251Schristos * A fixed-size message body and n * variable-size data units. 2215c74ad251Schristos */ 2216c74ad251Schristos { 2217c74ad251Schristos "FLOW_MOD", of10_flow_mod_print, 2218c74ad251Schristos REQ_MINLEN, OF_FLOW_MOD_MINLEN 2219c74ad251Schristos }, 2220c74ad251Schristos /* 2221c74ad251Schristos * [OF10] Section 5.3.3 2222c74ad251Schristos * A fixed-size message body. 2223c74ad251Schristos */ 2224c74ad251Schristos { 2225c74ad251Schristos "PORT_MOD", of10_port_mod_print, 2226c74ad251Schristos REQ_FIXLEN, OF_PORT_MOD_FIXLEN 2227c74ad251Schristos }, 2228c74ad251Schristos /* 2229c74ad251Schristos * [OF10] Section 5.3.5 2230c74ad251Schristos * A fixed-size message body and possibly more data of varying size 2231c74ad251Schristos * and structure. 2232c74ad251Schristos */ 2233c74ad251Schristos { 2234c74ad251Schristos "STATS_REQUEST", of10_stats_request_print, 2235c74ad251Schristos REQ_MINLEN, OF_STATS_REQUEST_MINLEN 2236c74ad251Schristos }, 2237c74ad251Schristos /* 2238c74ad251Schristos * [OF10] Section 5.3.5 2239c74ad251Schristos * A fixed-size message body and possibly more data of varying size 2240c74ad251Schristos * and structure. 2241c74ad251Schristos */ 2242c74ad251Schristos { 2243c74ad251Schristos "STATS_REPLY", of10_stats_reply_print, 2244c74ad251Schristos REQ_MINLEN, OF_STATS_REPLY_MINLEN 2245c74ad251Schristos }, 2246c74ad251Schristos /* 2247c74ad251Schristos * [OF10] Section 5.3.7 2248c74ad251Schristos * No message body. 2249c74ad251Schristos */ 2250c74ad251Schristos { 2251c74ad251Schristos "BARRIER_REQUEST", NULL, 2252c74ad251Schristos REQ_FIXLEN, 0 2253c74ad251Schristos }, 2254c74ad251Schristos /* 2255c74ad251Schristos * [OF10] Section 5.3.7 2256c74ad251Schristos * No message body. 2257c74ad251Schristos */ 2258c74ad251Schristos { 2259c74ad251Schristos "BARRIER_REPLY", NULL, 2260c74ad251Schristos REQ_FIXLEN, 0 2261c74ad251Schristos }, 2262c74ad251Schristos /* 2263c74ad251Schristos * [OF10] Section 5.3.4 2264c74ad251Schristos * A fixed-size message body. 2265c74ad251Schristos */ 2266c74ad251Schristos { 2267c74ad251Schristos "QUEUE_GET_CONFIG_REQUEST", of10_queue_get_config_request_print, 2268c74ad251Schristos REQ_FIXLEN, OF_QUEUE_GET_CONFIG_REQUEST_FIXLEN 2269c74ad251Schristos }, 2270c74ad251Schristos /* 2271c74ad251Schristos * [OF10] Section 5.3.4 2272c74ad251Schristos * A fixed-size message body and n * variable-size data units. 2273c74ad251Schristos */ 2274c74ad251Schristos { 2275c74ad251Schristos "QUEUE_GET_CONFIG_REPLY", of10_queue_get_config_reply_print, 2276c74ad251Schristos REQ_MINLEN, OF_QUEUE_GET_CONFIG_REPLY_MINLEN 2277c74ad251Schristos }, 2278c74ad251Schristos }; 2279026d7285Schristos 2280c74ad251Schristos const struct of_msgtypeinfo * 2281c74ad251Schristos of10_identify_msgtype(const uint8_t type) 2282c74ad251Schristos { 2283c74ad251Schristos return type <= OFPT_MAX ? &of10_msgtypeinfo[type] : NULL; 2284026d7285Schristos } 2285