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