diff --git a/Makefile.in b/Makefile.in index 36561a3d..2b5f8ad6 100644 --- a/Makefile.in +++ b/Makefile.in @@ -88,7 +88,7 @@ CSRC = addrtoname.c af.c checksum.c cpack.c gmpls.c oui.c gmt2local.c ipproto.c print-lmp.c print-lspping.c print-lwapp.c \ print-lwres.c print-mobile.c print-mpcp.c print-mpls.c print-mptcp.c print-msdp.c \ print-msnlb.c print-nfs.c print-ntp.c print-null.c print-olsr.c \ - print-openflow.c print-ospf.c \ + print-openflow.c print-openflow-1.0.c print-ospf.c \ print-pgm.c print-pim.c \ print-ppi.c print-ppp.c print-pppoe.c print-pptp.c \ print-radius.c print-raw.c print-rip.c print-rpki-rtr.c print-rrcp.c print-rsvp.c \ @@ -167,6 +167,7 @@ HDR = \ nlpid.h \ ntp.h \ oakley.h \ + openflow-1.0.h \ ospf.h \ ospf6.h \ oui.h \ diff --git a/interface.h b/interface.h index 5c598e6c..1d461244 100644 --- a/interface.h +++ b/interface.h @@ -224,6 +224,8 @@ extern const u_char * ns_nprint (register const u_char *, register const u_char extern void ntp_print(const u_char *, u_int); extern u_int null_if_print(const struct pcap_pkthdr *, const u_char *); extern void openflow_print(const u_char *, u_int); +extern const u_char *of10_header_body_print(const u_char *, const u_char *, + const uint8_t, const uint16_t, const uint32_t); extern void ospf_print(const u_char *, u_int, const u_char *); extern void olsr_print (const u_char *, u_int, int); extern void pimv1_print(const u_char *, u_int); diff --git a/openflow-1.0.h b/openflow-1.0.h new file mode 100644 index 00000000..c0b5090d --- /dev/null +++ b/openflow-1.0.h @@ -0,0 +1,970 @@ +/* Copyright (c) 2008 The Board of Trustees of The Leland Stanford + * Junior University + * + * We are making the OpenFlow specification and associated documentation + * (Software) available for public use and benefit with the expectation + * that others will use, modify and enhance the Software and contribute + * those enhancements back to the community. However, since we would + * like to make the Software available for broadest use, with as few + * restrictions as possible permission is hereby granted, free of + * charge, to any person obtaining a copy of this Software to deal in + * the Software under the copyrights without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * The name and trademarks of copyright holder(s) may NOT be used in + * advertising or publicity pertaining to the Software or any + * derivatives without specific, written prior permission. + */ + +/* OpenFlow: protocol between controller and datapath. */ + +#ifndef OPENFLOW_OPENFLOW_H +#define OPENFLOW_OPENFLOW_H 1 + +#ifdef __KERNEL__ +#include +#else +#include +#endif + +#ifdef SWIG +#define OFP_ASSERT(EXPR) /* SWIG can't handle OFP_ASSERT. */ +#elif !defined(__cplusplus) +/* Build-time assertion for use in a declaration context. */ +#define OFP_ASSERT(EXPR) \ + extern int (*build_assert(void))[ sizeof(struct { \ + unsigned int build_assert_failed : (EXPR) ? 1 : -1; })] +#else /* __cplusplus */ +#define OFP_ASSERT(_EXPR) typedef int build_assert_failed[(_EXPR) ? 1 : -1] +#endif /* __cplusplus */ + +#ifndef SWIG +#define OFP_PACKED __attribute__((packed)) +#else +#define OFP_PACKED /* SWIG doesn't understand __attribute. */ +#endif + +/* Version number: + * Non-experimental versions released: 0x01 + * Experimental versions released: 0x81 -- 0x99 + */ +/* The most significant bit being set in the version field indicates an + * experimental OpenFlow version. + */ +#define OFP_VERSION 0x01 + +#define OFP_MAX_TABLE_NAME_LEN 32 +#define OFP_MAX_PORT_NAME_LEN 16 + +#define OFP_TCP_PORT 6633 +#define OFP_SSL_PORT 6633 + +#define OFP_ETH_ALEN 6 /* Bytes in an Ethernet address. */ + +/* Port numbering. Physical ports are numbered starting from 1. */ +enum ofp_port { + /* Maximum number of physical switch ports. */ + OFPP_MAX = 0xff00, + + /* Fake output "ports". */ + OFPP_IN_PORT = 0xfff8, /* Send the packet out the input port. This + virtual port must be explicitly used + in order to send back out of the input + port. */ + OFPP_TABLE = 0xfff9, /* Perform actions in flow table. + NB: This can only be the destination + port for packet-out messages. */ + OFPP_NORMAL = 0xfffa, /* Process with normal L2/L3 switching. */ + OFPP_FLOOD = 0xfffb, /* All physical ports except input port and + those disabled by STP. */ + OFPP_ALL = 0xfffc, /* All physical ports except input port. */ + OFPP_CONTROLLER = 0xfffd, /* Send to controller. */ + OFPP_LOCAL = 0xfffe, /* Local openflow "port". */ + OFPP_NONE = 0xffff /* Not associated with a physical port. */ +}; + +enum ofp_type { + /* Immutable messages. */ + OFPT_HELLO, /* Symmetric message */ + OFPT_ERROR, /* Symmetric message */ + OFPT_ECHO_REQUEST, /* Symmetric message */ + OFPT_ECHO_REPLY, /* Symmetric message */ + OFPT_VENDOR, /* Symmetric message */ + + /* Switch configuration messages. */ + OFPT_FEATURES_REQUEST, /* Controller/switch message */ + OFPT_FEATURES_REPLY, /* Controller/switch message */ + OFPT_GET_CONFIG_REQUEST, /* Controller/switch message */ + OFPT_GET_CONFIG_REPLY, /* Controller/switch message */ + OFPT_SET_CONFIG, /* Controller/switch message */ + + /* Asynchronous messages. */ + OFPT_PACKET_IN, /* Async message */ + OFPT_FLOW_REMOVED, /* Async message */ + OFPT_PORT_STATUS, /* Async message */ + + /* Controller command messages. */ + OFPT_PACKET_OUT, /* Controller/switch message */ + OFPT_FLOW_MOD, /* Controller/switch message */ + OFPT_PORT_MOD, /* Controller/switch message */ + + /* Statistics messages. */ + OFPT_STATS_REQUEST, /* Controller/switch message */ + OFPT_STATS_REPLY, /* Controller/switch message */ + + /* Barrier messages. */ + OFPT_BARRIER_REQUEST, /* Controller/switch message */ + OFPT_BARRIER_REPLY, /* Controller/switch message */ + + /* Queue Configuration messages. */ + OFPT_QUEUE_GET_CONFIG_REQUEST, /* Controller/switch message */ + OFPT_QUEUE_GET_CONFIG_REPLY /* Controller/switch message */ + +}; + +/* Header on all OpenFlow packets. */ +struct ofp_header { + uint8_t version; /* OFP_VERSION. */ + uint8_t type; /* One of the OFPT_ constants. */ + uint16_t length; /* Length including this ofp_header. */ + uint32_t xid; /* Transaction id associated with this packet. + Replies use the same id as was in the request + to facilitate pairing. */ +}; +OFP_ASSERT(sizeof(struct ofp_header) == 8); + +/* OFPT_HELLO. This message has an empty body, but implementations must + * ignore any data included in the body, to allow for future extensions. */ +struct ofp_hello { + struct ofp_header header; +}; + +#define OFP_DEFAULT_MISS_SEND_LEN 128 + +enum ofp_config_flags { + /* Handling of IP fragments. */ + OFPC_FRAG_NORMAL = 0, /* No special handling for fragments. */ + OFPC_FRAG_DROP = 1, /* Drop fragments. */ + OFPC_FRAG_REASM = 2, /* Reassemble (only if OFPC_IP_REASM set). */ + OFPC_FRAG_MASK = 3 +}; + +/* Switch configuration. */ +struct ofp_switch_config { + struct ofp_header header; + uint16_t flags; /* OFPC_* flags. */ + uint16_t miss_send_len; /* Max bytes of new flow that datapath should + send to the controller. */ +}; +OFP_ASSERT(sizeof(struct ofp_switch_config) == 12); + +/* Capabilities supported by the datapath. */ +enum ofp_capabilities { + OFPC_FLOW_STATS = 1 << 0, /* Flow statistics. */ + OFPC_TABLE_STATS = 1 << 1, /* Table statistics. */ + OFPC_PORT_STATS = 1 << 2, /* Port statistics. */ + OFPC_STP = 1 << 3, /* 802.1d spanning tree. */ + OFPC_RESERVED = 1 << 4, /* Reserved, must be zero. */ + OFPC_IP_REASM = 1 << 5, /* Can reassemble IP fragments. */ + OFPC_QUEUE_STATS = 1 << 6, /* Queue statistics. */ + OFPC_ARP_MATCH_IP = 1 << 7 /* Match IP addresses in ARP pkts. */ +}; + +/* Flags to indicate behavior of the physical port. These flags are + * used in ofp_phy_port to describe the current configuration. They are + * used in the ofp_port_mod message to configure the port's behavior. + */ +enum ofp_port_config { + OFPPC_PORT_DOWN = 1 << 0, /* Port is administratively down. */ + + OFPPC_NO_STP = 1 << 1, /* Disable 802.1D spanning tree on port. */ + OFPPC_NO_RECV = 1 << 2, /* Drop all packets except 802.1D spanning + tree packets. */ + OFPPC_NO_RECV_STP = 1 << 3, /* Drop received 802.1D STP packets. */ + OFPPC_NO_FLOOD = 1 << 4, /* Do not include this port when flooding. */ + OFPPC_NO_FWD = 1 << 5, /* Drop packets forwarded to port. */ + OFPPC_NO_PACKET_IN = 1 << 6 /* Do not send packet-in msgs for port. */ +}; + +/* Current state of the physical port. These are not configurable from + * the controller. + */ +enum ofp_port_state { + OFPPS_LINK_DOWN = 1 << 0, /* No physical link present. */ + + /* The OFPPS_STP_* bits have no effect on switch operation. The + * controller must adjust OFPPC_NO_RECV, OFPPC_NO_FWD, and + * OFPPC_NO_PACKET_IN appropriately to fully implement an 802.1D spanning + * tree. */ + OFPPS_STP_LISTEN = 0 << 8, /* Not learning or relaying frames. */ + OFPPS_STP_LEARN = 1 << 8, /* Learning but not relaying frames. */ + OFPPS_STP_FORWARD = 2 << 8, /* Learning and relaying frames. */ + OFPPS_STP_BLOCK = 3 << 8, /* Not part of spanning tree. */ + OFPPS_STP_MASK = 3 << 8 /* Bit mask for OFPPS_STP_* values. */ +}; + +/* Features of physical ports available in a datapath. */ +enum ofp_port_features { + OFPPF_10MB_HD = 1 << 0, /* 10 Mb half-duplex rate support. */ + OFPPF_10MB_FD = 1 << 1, /* 10 Mb full-duplex rate support. */ + OFPPF_100MB_HD = 1 << 2, /* 100 Mb half-duplex rate support. */ + OFPPF_100MB_FD = 1 << 3, /* 100 Mb full-duplex rate support. */ + OFPPF_1GB_HD = 1 << 4, /* 1 Gb half-duplex rate support. */ + OFPPF_1GB_FD = 1 << 5, /* 1 Gb full-duplex rate support. */ + OFPPF_10GB_FD = 1 << 6, /* 10 Gb full-duplex rate support. */ + OFPPF_COPPER = 1 << 7, /* Copper medium. */ + OFPPF_FIBER = 1 << 8, /* Fiber medium. */ + OFPPF_AUTONEG = 1 << 9, /* Auto-negotiation. */ + OFPPF_PAUSE = 1 << 10, /* Pause. */ + OFPPF_PAUSE_ASYM = 1 << 11 /* Asymmetric pause. */ +}; + +/* Description of a physical port */ +struct ofp_phy_port { + uint16_t port_no; + uint8_t hw_addr[OFP_ETH_ALEN]; + char name[OFP_MAX_PORT_NAME_LEN]; /* Null-terminated */ + + uint32_t config; /* Bitmap of OFPPC_* flags. */ + uint32_t state; /* Bitmap of OFPPS_* flags. */ + + /* Bitmaps of OFPPF_* that describe features. All bits zeroed if + * unsupported or unavailable. */ + uint32_t curr; /* Current features. */ + uint32_t advertised; /* Features being advertised by the port. */ + uint32_t supported; /* Features supported by the port. */ + uint32_t peer; /* Features advertised by peer. */ +}; +OFP_ASSERT(sizeof(struct ofp_phy_port) == 48); + +/* Switch features. */ +struct ofp_switch_features { + struct ofp_header header; + uint64_t datapath_id; /* Datapath unique ID. The lower 48-bits are for + a MAC address, while the upper 16-bits are + implementer-defined. */ + + uint32_t n_buffers; /* Max packets buffered at once. */ + + uint8_t n_tables; /* Number of tables supported by datapath. */ + uint8_t pad[3]; /* Align to 64-bits. */ + + /* Features. */ + uint32_t capabilities; /* Bitmap of support "ofp_capabilities". */ + uint32_t actions; /* Bitmap of supported "ofp_action_type"s. */ + + /* Port info.*/ + struct ofp_phy_port ports[0]; /* Port definitions. The number of ports + is inferred from the length field in + the header. */ +}; +OFP_ASSERT(sizeof(struct ofp_switch_features) == 32); + +/* What changed about the physical port */ +enum ofp_port_reason { + OFPPR_ADD, /* The port was added. */ + OFPPR_DELETE, /* The port was removed. */ + OFPPR_MODIFY /* Some attribute of the port has changed. */ +}; + +/* A physical port has changed in the datapath */ +struct ofp_port_status { + struct ofp_header header; + uint8_t reason; /* One of OFPPR_*. */ + uint8_t pad[7]; /* Align to 64-bits. */ + struct ofp_phy_port desc; +}; +OFP_ASSERT(sizeof(struct ofp_port_status) == 64); + +/* Modify behavior of the physical port */ +struct ofp_port_mod { + struct ofp_header header; + uint16_t port_no; + uint8_t hw_addr[OFP_ETH_ALEN]; /* The hardware address is not + configurable. This is used to + sanity-check the request, so it must + be the same as returned in an + ofp_phy_port struct. */ + + uint32_t config; /* Bitmap of OFPPC_* flags. */ + uint32_t mask; /* Bitmap of OFPPC_* flags to be changed. */ + + uint32_t advertise; /* Bitmap of "ofp_port_features"s. Zero all + bits to prevent any action taking place. */ + uint8_t pad[4]; /* Pad to 64-bits. */ +}; +OFP_ASSERT(sizeof(struct ofp_port_mod) == 32); + +/* Why is this packet being sent to the controller? */ +enum ofp_packet_in_reason { + OFPR_NO_MATCH, /* No matching flow. */ + OFPR_ACTION /* Action explicitly output to controller. */ +}; + +/* Packet received on port (datapath -> controller). */ +struct ofp_packet_in { + struct ofp_header header; + uint32_t buffer_id; /* ID assigned by datapath. */ + uint16_t total_len; /* Full length of frame. */ + uint16_t in_port; /* Port on which frame was received. */ + uint8_t reason; /* Reason packet is being sent (one of OFPR_*) */ + uint8_t pad; + uint8_t data[0]; /* Ethernet frame, halfway through 32-bit word, + so the IP header is 32-bit aligned. The + amount of data is inferred from the length + field in the header. Because of padding, + offsetof(struct ofp_packet_in, data) == + sizeof(struct ofp_packet_in) - 2. */ +}; +OFP_ASSERT(sizeof(struct ofp_packet_in) == 20); + +enum ofp_action_type { + OFPAT_OUTPUT, /* Output to switch port. */ + OFPAT_SET_VLAN_VID, /* Set the 802.1q VLAN id. */ + OFPAT_SET_VLAN_PCP, /* Set the 802.1q priority. */ + OFPAT_STRIP_VLAN, /* Strip the 802.1q header. */ + OFPAT_SET_DL_SRC, /* Ethernet source address. */ + OFPAT_SET_DL_DST, /* Ethernet destination address. */ + OFPAT_SET_NW_SRC, /* IP source address. */ + OFPAT_SET_NW_DST, /* IP destination address. */ + OFPAT_SET_NW_TOS, /* IP ToS (DSCP field, 6 bits). */ + OFPAT_SET_TP_SRC, /* TCP/UDP source port. */ + OFPAT_SET_TP_DST, /* TCP/UDP destination port. */ + OFPAT_ENQUEUE, /* Output to queue. */ + OFPAT_VENDOR = 0xffff +}; + +/* Action structure for OFPAT_OUTPUT, which sends packets out 'port'. + * When the 'port' is the OFPP_CONTROLLER, 'max_len' indicates the max + * number of bytes to send. A 'max_len' of zero means no bytes of the + * packet should be sent.*/ +struct ofp_action_output { + uint16_t type; /* OFPAT_OUTPUT. */ + uint16_t len; /* Length is 8. */ + uint16_t port; /* Output port. */ + uint16_t max_len; /* Max length to send to controller. */ +}; +OFP_ASSERT(sizeof(struct ofp_action_output) == 8); + +/* The VLAN id is 12 bits, so we can use the entire 16 bits to indicate + * special conditions. All ones is used to match that no VLAN id was + * set. */ +#define OFP_VLAN_NONE 0xffff + +/* Action structure for OFPAT_SET_VLAN_VID. */ +struct ofp_action_vlan_vid { + uint16_t type; /* OFPAT_SET_VLAN_VID. */ + uint16_t len; /* Length is 8. */ + uint16_t vlan_vid; /* VLAN id. */ + uint8_t pad[2]; +}; +OFP_ASSERT(sizeof(struct ofp_action_vlan_vid) == 8); + +/* Action structure for OFPAT_SET_VLAN_PCP. */ +struct ofp_action_vlan_pcp { + uint16_t type; /* OFPAT_SET_VLAN_PCP. */ + uint16_t len; /* Length is 8. */ + uint8_t vlan_pcp; /* VLAN priority. */ + uint8_t pad[3]; +}; +OFP_ASSERT(sizeof(struct ofp_action_vlan_pcp) == 8); + +/* Action structure for OFPAT_SET_DL_SRC/DST. */ +struct ofp_action_dl_addr { + uint16_t type; /* OFPAT_SET_DL_SRC/DST. */ + uint16_t len; /* Length is 16. */ + uint8_t dl_addr[OFP_ETH_ALEN]; /* Ethernet address. */ + uint8_t pad[6]; +}; +OFP_ASSERT(sizeof(struct ofp_action_dl_addr) == 16); + +/* Action structure for OFPAT_SET_NW_SRC/DST. */ +struct ofp_action_nw_addr { + uint16_t type; /* OFPAT_SET_TW_SRC/DST. */ + uint16_t len; /* Length is 8. */ + uint32_t nw_addr; /* IP address. */ +}; +OFP_ASSERT(sizeof(struct ofp_action_nw_addr) == 8); + +/* Action structure for OFPAT_SET_TP_SRC/DST. */ +struct ofp_action_tp_port { + uint16_t type; /* OFPAT_SET_TP_SRC/DST. */ + uint16_t len; /* Length is 8. */ + uint16_t tp_port; /* TCP/UDP port. */ + uint8_t pad[2]; +}; +OFP_ASSERT(sizeof(struct ofp_action_tp_port) == 8); + +/* Action structure for OFPAT_SET_NW_TOS. */ +struct ofp_action_nw_tos { + uint16_t type; /* OFPAT_SET_TW_SRC/DST. */ + uint16_t len; /* Length is 8. */ + uint8_t nw_tos; /* IP ToS (DSCP field, 6 bits). */ + uint8_t pad[3]; +}; +OFP_ASSERT(sizeof(struct ofp_action_nw_tos) == 8); + +/* Action header for OFPAT_VENDOR. The rest of the body is vendor-defined. */ +struct ofp_action_vendor_header { + uint16_t type; /* OFPAT_VENDOR. */ + uint16_t len; /* Length is a multiple of 8. */ + uint32_t vendor; /* Vendor ID, which takes the same form + as in "struct ofp_vendor_header". */ +}; +OFP_ASSERT(sizeof(struct ofp_action_vendor_header) == 8); + +/* Action header that is common to all actions. The length includes the + * header and any padding used to make the action 64-bit aligned. + * NB: The length of an action *must* always be a multiple of eight. */ +struct ofp_action_header { + uint16_t type; /* One of OFPAT_*. */ + uint16_t len; /* Length of action, including this + header. This is the length of action, + including any padding to make it + 64-bit aligned. */ + uint8_t pad[4]; +}; +OFP_ASSERT(sizeof(struct ofp_action_header) == 8); + +/* Send packet (controller -> datapath). */ +struct ofp_packet_out { + struct ofp_header header; + uint32_t buffer_id; /* ID assigned by datapath (-1 if none). */ + uint16_t in_port; /* Packet's input port (OFPP_NONE if none). */ + uint16_t actions_len; /* Size of action array in bytes. */ + struct ofp_action_header actions[0]; /* Actions. */ + /* uint8_t data[0]; */ /* Packet data. The length is inferred + from the length field in the header. + (Only meaningful if buffer_id == -1.) */ +}; +OFP_ASSERT(sizeof(struct ofp_packet_out) == 16); + +enum ofp_flow_mod_command { + OFPFC_ADD, /* New flow. */ + OFPFC_MODIFY, /* Modify all matching flows. */ + OFPFC_MODIFY_STRICT, /* Modify entry strictly matching wildcards */ + OFPFC_DELETE, /* Delete all matching flows. */ + OFPFC_DELETE_STRICT /* Strictly match wildcards and priority. */ +}; + +/* Flow wildcards. */ +enum ofp_flow_wildcards { + OFPFW_IN_PORT = 1 << 0, /* Switch input port. */ + OFPFW_DL_VLAN = 1 << 1, /* VLAN id. */ + OFPFW_DL_SRC = 1 << 2, /* Ethernet source address. */ + OFPFW_DL_DST = 1 << 3, /* Ethernet destination address. */ + OFPFW_DL_TYPE = 1 << 4, /* Ethernet frame type. */ + OFPFW_NW_PROTO = 1 << 5, /* IP protocol. */ + OFPFW_TP_SRC = 1 << 6, /* TCP/UDP source port. */ + OFPFW_TP_DST = 1 << 7, /* TCP/UDP destination port. */ + + /* IP source address wildcard bit count. 0 is exact match, 1 ignores the + * LSB, 2 ignores the 2 least-significant bits, ..., 32 and higher wildcard + * the entire field. This is the *opposite* of the usual convention where + * e.g. /24 indicates that 8 bits (not 24 bits) are wildcarded. */ + OFPFW_NW_SRC_SHIFT = 8, + OFPFW_NW_SRC_BITS = 6, + OFPFW_NW_SRC_MASK = ((1 << OFPFW_NW_SRC_BITS) - 1) << OFPFW_NW_SRC_SHIFT, + OFPFW_NW_SRC_ALL = 32 << OFPFW_NW_SRC_SHIFT, + + /* IP destination address wildcard bit count. Same format as source. */ + OFPFW_NW_DST_SHIFT = 14, + OFPFW_NW_DST_BITS = 6, + OFPFW_NW_DST_MASK = ((1 << OFPFW_NW_DST_BITS) - 1) << OFPFW_NW_DST_SHIFT, + OFPFW_NW_DST_ALL = 32 << OFPFW_NW_DST_SHIFT, + + OFPFW_DL_VLAN_PCP = 1 << 20, /* VLAN priority. */ + OFPFW_NW_TOS = 1 << 21, /* IP ToS (DSCP field, 6 bits). */ + + /* Wildcard all fields. */ + OFPFW_ALL = ((1 << 22) - 1) +}; + +/* The wildcards for ICMP type and code fields use the transport source + * and destination port fields, respectively. */ +#define OFPFW_ICMP_TYPE OFPFW_TP_SRC +#define OFPFW_ICMP_CODE OFPFW_TP_DST + +/* Values below this cutoff are 802.3 packets and the two bytes + * following MAC addresses are used as a frame length. Otherwise, the + * two bytes are used as the Ethernet type. + */ +#define OFP_DL_TYPE_ETH2_CUTOFF 0x0600 + +/* Value of dl_type to indicate that the frame does not include an + * Ethernet type. + */ +#define OFP_DL_TYPE_NOT_ETH_TYPE 0x05ff + +/* The VLAN id is 12-bits, so we can use the entire 16 bits to indicate + * special conditions. All ones indicates that no VLAN id was set. + */ +#define OFP_VLAN_NONE 0xffff + +/* Fields to match against flows */ +struct ofp_match { + uint32_t wildcards; /* Wildcard fields. */ + uint16_t in_port; /* Input switch port. */ + uint8_t dl_src[OFP_ETH_ALEN]; /* Ethernet source address. */ + uint8_t dl_dst[OFP_ETH_ALEN]; /* Ethernet destination address. */ + uint16_t dl_vlan; /* Input VLAN id. */ + uint8_t dl_vlan_pcp; /* Input VLAN priority. */ + uint8_t pad1[1]; /* Align to 64-bits */ + uint16_t dl_type; /* Ethernet frame type. */ + uint8_t nw_tos; /* IP ToS (actually DSCP field, 6 bits). */ + uint8_t nw_proto; /* IP protocol or lower 8 bits of + * ARP opcode. */ + uint8_t pad2[2]; /* Align to 64-bits */ + uint32_t nw_src; /* IP source address. */ + uint32_t nw_dst; /* IP destination address. */ + uint16_t tp_src; /* TCP/UDP source port. */ + uint16_t tp_dst; /* TCP/UDP destination port. */ +}; +OFP_ASSERT(sizeof(struct ofp_match) == 40); + +/* The match fields for ICMP type and code use the transport source and + * destination port fields, respectively. */ +#define icmp_type tp_src +#define icmp_code tp_dst + +/* Value used in "idle_timeout" and "hard_timeout" to indicate that the entry + * is permanent. */ +#define OFP_FLOW_PERMANENT 0 + +/* By default, choose a priority in the middle. */ +#define OFP_DEFAULT_PRIORITY 0x8000 + +enum ofp_flow_mod_flags { + OFPFF_SEND_FLOW_REM = 1 << 0, /* Send flow removed message when flow + * expires or is deleted. */ + OFPFF_CHECK_OVERLAP = 1 << 1, /* Check for overlapping entries first. */ + OFPFF_EMERG = 1 << 2 /* Remark this is for emergency. */ +}; + +/* Flow setup and teardown (controller -> datapath). */ +struct ofp_flow_mod { + struct ofp_header header; + struct ofp_match match; /* Fields to match */ + uint64_t cookie; /* Opaque controller-issued identifier. */ + + /* Flow actions. */ + uint16_t command; /* One of OFPFC_*. */ + uint16_t idle_timeout; /* Idle time before discarding (seconds). */ + uint16_t hard_timeout; /* Max time before discarding (seconds). */ + uint16_t priority; /* Priority level of flow entry. */ + uint32_t buffer_id; /* Buffered packet to apply to (or -1). + Not meaningful for OFPFC_DELETE*. */ + uint16_t out_port; /* For OFPFC_DELETE* commands, require + matching entries to include this as an + output port. A value of OFPP_NONE + indicates no restriction. */ + uint16_t flags; /* One of OFPFF_*. */ + struct ofp_action_header actions[0]; /* The action length is inferred + from the length field in the + header. */ +}; +OFP_ASSERT(sizeof(struct ofp_flow_mod) == 72); + +/* Why was this flow removed? */ +enum ofp_flow_removed_reason { + OFPRR_IDLE_TIMEOUT, /* Flow idle time exceeded idle_timeout. */ + OFPRR_HARD_TIMEOUT, /* Time exceeded hard_timeout. */ + OFPRR_DELETE /* Evicted by a DELETE flow mod. */ +}; + +/* Flow removed (datapath -> controller). */ +struct ofp_flow_removed { + struct ofp_header header; + struct ofp_match match; /* Description of fields. */ + uint64_t cookie; /* Opaque controller-issued identifier. */ + + uint16_t priority; /* Priority level of flow entry. */ + uint8_t reason; /* One of OFPRR_*. */ + uint8_t pad[1]; /* Align to 32-bits. */ + + uint32_t duration_sec; /* Time flow was alive in seconds. */ + uint32_t duration_nsec; /* Time flow was alive in nanoseconds beyond + duration_sec. */ + uint16_t idle_timeout; /* Idle timeout from original flow mod. */ + uint8_t pad2[2]; /* Align to 64-bits. */ + uint64_t packet_count; + uint64_t byte_count; +}; +OFP_ASSERT(sizeof(struct ofp_flow_removed) == 88); + +/* Values for 'type' in ofp_error_message. These values are immutable: they + * will not change in future versions of the protocol (although new values may + * be added). */ +enum ofp_error_type { + OFPET_HELLO_FAILED, /* Hello protocol failed. */ + OFPET_BAD_REQUEST, /* Request was not understood. */ + OFPET_BAD_ACTION, /* Error in action description. */ + OFPET_FLOW_MOD_FAILED, /* Problem modifying flow entry. */ + OFPET_PORT_MOD_FAILED, /* Port mod request failed. */ + OFPET_QUEUE_OP_FAILED /* Queue operation failed. */ +}; + +/* ofp_error_msg 'code' values for OFPET_HELLO_FAILED. 'data' contains an + * ASCII text string that may give failure details. */ +enum ofp_hello_failed_code { + OFPHFC_INCOMPATIBLE, /* No compatible version. */ + OFPHFC_EPERM /* Permissions error. */ +}; + +/* ofp_error_msg 'code' values for OFPET_BAD_REQUEST. 'data' contains at least + * the first 64 bytes of the failed request. */ +enum ofp_bad_request_code { + OFPBRC_BAD_VERSION, /* ofp_header.version not supported. */ + OFPBRC_BAD_TYPE, /* ofp_header.type not supported. */ + OFPBRC_BAD_STAT, /* ofp_stats_request.type not supported. */ + OFPBRC_BAD_VENDOR, /* Vendor not supported (in ofp_vendor_header + * or ofp_stats_request or ofp_stats_reply). */ + OFPBRC_BAD_SUBTYPE, /* Vendor subtype not supported. */ + OFPBRC_EPERM, /* Permissions error. */ + OFPBRC_BAD_LEN, /* Wrong request length for type. */ + OFPBRC_BUFFER_EMPTY, /* Specified buffer has already been used. */ + OFPBRC_BUFFER_UNKNOWN /* Specified buffer does not exist. */ +}; + +/* ofp_error_msg 'code' values for OFPET_BAD_ACTION. 'data' contains at least + * the first 64 bytes of the failed request. */ +enum ofp_bad_action_code { + OFPBAC_BAD_TYPE, /* Unknown action type. */ + OFPBAC_BAD_LEN, /* Length problem in actions. */ + OFPBAC_BAD_VENDOR, /* Unknown vendor id specified. */ + OFPBAC_BAD_VENDOR_TYPE, /* Unknown action type for vendor id. */ + OFPBAC_BAD_OUT_PORT, /* Problem validating output action. */ + OFPBAC_BAD_ARGUMENT, /* Bad action argument. */ + OFPBAC_EPERM, /* Permissions error. */ + OFPBAC_TOO_MANY, /* Can't handle this many actions. */ + OFPBAC_BAD_QUEUE /* Problem validating output queue. */ +}; + +/* ofp_error_msg 'code' values for OFPET_FLOW_MOD_FAILED. 'data' contains + * at least the first 64 bytes of the failed request. */ +enum ofp_flow_mod_failed_code { + OFPFMFC_ALL_TABLES_FULL, /* Flow not added because of full tables. */ + OFPFMFC_OVERLAP, /* Attempted to add overlapping flow with + * CHECK_OVERLAP flag set. */ + OFPFMFC_EPERM, /* Permissions error. */ + OFPFMFC_BAD_EMERG_TIMEOUT, /* Flow not added because of non-zero idle/hard + * timeout. */ + OFPFMFC_BAD_COMMAND, /* Unknown command. */ + OFPFMFC_UNSUPPORTED /* Unsupported action list - cannot process in + * the order specified. */ +}; + +/* ofp_error_msg 'code' values for OFPET_PORT_MOD_FAILED. 'data' contains + * at least the first 64 bytes of the failed request. */ +enum ofp_port_mod_failed_code { + OFPPMFC_BAD_PORT, /* Specified port does not exist. */ + OFPPMFC_BAD_HW_ADDR, /* Specified hardware address is wrong. */ +}; + +/* ofp_error msg 'code' values for OFPET_QUEUE_OP_FAILED. 'data' contains + * at least the first 64 bytes of the failed request */ +enum ofp_queue_op_failed_code { + OFPQOFC_BAD_PORT, /* Invalid port (or port does not exist). */ + OFPQOFC_BAD_QUEUE, /* Queue does not exist. */ + OFPQOFC_EPERM /* Permissions error. */ +}; + +/* OFPT_ERROR: Error message (datapath -> controller). */ +struct ofp_error_msg { + struct ofp_header header; + + uint16_t type; + uint16_t code; + uint8_t data[0]; /* Variable-length data. Interpreted based + on the type and code. */ +}; +OFP_ASSERT(sizeof(struct ofp_error_msg) == 12); + +enum ofp_stats_types { + /* Description of this OpenFlow switch. + * The request body is empty. + * The reply body is struct ofp_desc_stats. */ + OFPST_DESC, + + /* Individual flow statistics. + * The request body is struct ofp_flow_stats_request. + * The reply body is an array of struct ofp_flow_stats. */ + OFPST_FLOW, + + /* Aggregate flow statistics. + * The request body is struct ofp_aggregate_stats_request. + * The reply body is struct ofp_aggregate_stats_reply. */ + OFPST_AGGREGATE, + + /* Flow table statistics. + * The request body is empty. + * The reply body is an array of struct ofp_table_stats. */ + OFPST_TABLE, + + /* Physical port statistics. + * The request body is struct ofp_port_stats_request. + * The reply body is an array of struct ofp_port_stats. */ + OFPST_PORT, + + /* Queue statistics for a port + * The request body defines the port + * The reply body is an array of struct ofp_queue_stats */ + OFPST_QUEUE, + + /* Vendor extension. + * The request and reply bodies begin with a 32-bit vendor ID, which takes + * the same form as in "struct ofp_vendor_header". The request and reply + * bodies are otherwise vendor-defined. */ + OFPST_VENDOR = 0xffff +}; + +struct ofp_stats_request { + struct ofp_header header; + uint16_t type; /* One of the OFPST_* constants. */ + uint16_t flags; /* OFPSF_REQ_* flags (none yet defined). */ + uint8_t body[0]; /* Body of the request. */ +}; +OFP_ASSERT(sizeof(struct ofp_stats_request) == 12); + +enum ofp_stats_reply_flags { + OFPSF_REPLY_MORE = 1 << 0 /* More replies to follow. */ +}; + +struct ofp_stats_reply { + struct ofp_header header; + uint16_t type; /* One of the OFPST_* constants. */ + uint16_t flags; /* OFPSF_REPLY_* flags. */ + uint8_t body[0]; /* Body of the reply. */ +}; +OFP_ASSERT(sizeof(struct ofp_stats_reply) == 12); + +#define DESC_STR_LEN 256 +#define SERIAL_NUM_LEN 32 +/* Body of reply to OFPST_DESC request. Each entry is a NULL-terminated + * ASCII string. */ +struct ofp_desc_stats { + char mfr_desc[DESC_STR_LEN]; /* Manufacturer description. */ + char hw_desc[DESC_STR_LEN]; /* Hardware description. */ + char sw_desc[DESC_STR_LEN]; /* Software description. */ + char serial_num[SERIAL_NUM_LEN]; /* Serial number. */ + char dp_desc[DESC_STR_LEN]; /* Human readable description of datapath. */ +}; +OFP_ASSERT(sizeof(struct ofp_desc_stats) == 1056); + +/* Body for ofp_stats_request of type OFPST_FLOW. */ +struct ofp_flow_stats_request { + struct ofp_match match; /* Fields to match. */ + uint8_t table_id; /* ID of table to read (from ofp_table_stats), + 0xff for all tables or 0xfe for emergency. */ + uint8_t pad; /* Align to 32 bits. */ + uint16_t out_port; /* Require matching entries to include this + as an output port. A value of OFPP_NONE + indicates no restriction. */ +}; +OFP_ASSERT(sizeof(struct ofp_flow_stats_request) == 44); + +/* Body of reply to OFPST_FLOW request. */ +struct ofp_flow_stats { + uint16_t length; /* Length of this entry. */ + uint8_t table_id; /* ID of table flow came from. */ + uint8_t pad; + struct ofp_match match; /* Description of fields. */ + uint32_t duration_sec; /* Time flow has been alive in seconds. */ + uint32_t duration_nsec; /* Time flow has been alive in nanoseconds beyond + duration_sec. */ + uint16_t priority; /* Priority of the entry. Only meaningful + when this is not an exact-match entry. */ + uint16_t idle_timeout; /* Number of seconds idle before expiration. */ + uint16_t hard_timeout; /* Number of seconds before expiration. */ + uint8_t pad2[6]; /* Align to 64-bits. */ + uint64_t cookie; /* Opaque controller-issued identifier. */ + uint64_t packet_count; /* Number of packets in flow. */ + uint64_t byte_count; /* Number of bytes in flow. */ + struct ofp_action_header actions[0]; /* Actions. */ +}; +OFP_ASSERT(sizeof(struct ofp_flow_stats) == 88); + +/* Body for ofp_stats_request of type OFPST_AGGREGATE. */ +struct ofp_aggregate_stats_request { + struct ofp_match match; /* Fields to match. */ + uint8_t table_id; /* ID of table to read (from ofp_table_stats) + 0xff for all tables or 0xfe for emergency. */ + uint8_t pad; /* Align to 32 bits. */ + uint16_t out_port; /* Require matching entries to include this + as an output port. A value of OFPP_NONE + indicates no restriction. */ +}; +OFP_ASSERT(sizeof(struct ofp_aggregate_stats_request) == 44); + +/* Body of reply to OFPST_AGGREGATE request. */ +struct ofp_aggregate_stats_reply { + uint64_t packet_count; /* Number of packets in flows. */ + uint64_t byte_count; /* Number of bytes in flows. */ + uint32_t flow_count; /* Number of flows. */ + uint8_t pad[4]; /* Align to 64 bits. */ +}; +OFP_ASSERT(sizeof(struct ofp_aggregate_stats_reply) == 24); + +/* Body of reply to OFPST_TABLE request. */ +struct ofp_table_stats { + uint8_t table_id; /* Identifier of table. Lower numbered tables + are consulted first. */ + uint8_t pad[3]; /* Align to 32-bits. */ + char name[OFP_MAX_TABLE_NAME_LEN]; + uint32_t wildcards; /* Bitmap of OFPFW_* wildcards that are + supported by the table. */ + uint32_t max_entries; /* Max number of entries supported. */ + uint32_t active_count; /* Number of active entries. */ + uint64_t lookup_count; /* Number of packets looked up in table. */ + uint64_t matched_count; /* Number of packets that hit table. */ +}; +OFP_ASSERT(sizeof(struct ofp_table_stats) == 64); + +/* Body for ofp_stats_request of type OFPST_PORT. */ +struct ofp_port_stats_request { + uint16_t port_no; /* OFPST_PORT message must request statistics + * either for a single port (specified in + * port_no) or for all ports (if port_no == + * OFPP_NONE). */ + uint8_t pad[6]; +}; +OFP_ASSERT(sizeof(struct ofp_port_stats_request) == 8); + +/* Body of reply to OFPST_PORT request. If a counter is unsupported, set + * the field to all ones. */ +struct ofp_port_stats { + uint16_t port_no; + uint8_t pad[6]; /* Align to 64-bits. */ + uint64_t rx_packets; /* Number of received packets. */ + uint64_t tx_packets; /* Number of transmitted packets. */ + uint64_t rx_bytes; /* Number of received bytes. */ + uint64_t tx_bytes; /* Number of transmitted bytes. */ + uint64_t rx_dropped; /* Number of packets dropped by RX. */ + uint64_t tx_dropped; /* Number of packets dropped by TX. */ + uint64_t rx_errors; /* Number of receive errors. This is a super-set + of more specific receive errors and should be + greater than or equal to the sum of all + rx_*_err values. */ + uint64_t tx_errors; /* Number of transmit errors. This is a super-set + of more specific transmit errors and should be + greater than or equal to the sum of all + tx_*_err values (none currently defined.) */ + uint64_t rx_frame_err; /* Number of frame alignment errors. */ + uint64_t rx_over_err; /* Number of packets with RX overrun. */ + uint64_t rx_crc_err; /* Number of CRC errors. */ + uint64_t collisions; /* Number of collisions. */ +}; +OFP_ASSERT(sizeof(struct ofp_port_stats) == 104); + +/* Vendor extension. */ +struct ofp_vendor_header { + struct ofp_header header; /* Type OFPT_VENDOR. */ + uint32_t vendor; /* Vendor ID: + * - MSB 0: low-order bytes are IEEE OUI. + * - MSB != 0: defined by OpenFlow + * consortium. */ + /* Vendor-defined arbitrary additional data. */ +}; +OFP_ASSERT(sizeof(struct ofp_vendor_header) == 12); + +/* All ones is used to indicate all queues in a port (for stats retrieval). */ +#define OFPQ_ALL 0xffffffff + +/* Min rate > 1000 means not configured. */ +#define OFPQ_MIN_RATE_UNCFG 0xffff + +enum ofp_queue_properties { + OFPQT_NONE = 0, /* No property defined for queue (default). */ + OFPQT_MIN_RATE, /* Minimum datarate guaranteed. */ + /* Other types should be added here + * (i.e. max rate, precedence, etc). */ +}; + +/* Common description for a queue. */ +struct ofp_queue_prop_header { + uint16_t property; /* One of OFPQT_. */ + uint16_t len; /* Length of property, including this header. */ + uint8_t pad[4]; /* 64-bit alignemnt. */ +}; +OFP_ASSERT(sizeof(struct ofp_queue_prop_header) == 8); + +/* Min-Rate queue property description. */ +struct ofp_queue_prop_min_rate { + struct ofp_queue_prop_header prop_header; /* prop: OFPQT_MIN, len: 16. */ + uint16_t rate; /* In 1/10 of a percent; >1000 -> disabled. */ + uint8_t pad[6]; /* 64-bit alignment */ +}; +OFP_ASSERT(sizeof(struct ofp_queue_prop_min_rate) == 16); + +/* Full description for a queue. */ +struct ofp_packet_queue { + uint32_t queue_id; /* id for the specific queue. */ + uint16_t len; /* Length in bytes of this queue desc. */ + uint8_t pad[2]; /* 64-bit alignment. */ + struct ofp_queue_prop_header properties[0]; /* List of properties. */ +}; +OFP_ASSERT(sizeof(struct ofp_packet_queue) == 8); + +/* Query for port queue configuration. */ +struct ofp_queue_get_config_request { + struct ofp_header header; + uint16_t port; /* Port to be queried. Should refer + to a valid physical port (i.e. < OFPP_MAX) */ + uint8_t pad[2]; /* 32-bit alignment. */ +}; +OFP_ASSERT(sizeof(struct ofp_queue_get_config_request) == 12); + +/* Queue configuration for a given port. */ +struct ofp_queue_get_config_reply { + struct ofp_header header; + uint16_t port; + uint8_t pad[6]; + struct ofp_packet_queue queues[0]; /* List of configured queues. */ +}; +OFP_ASSERT(sizeof(struct ofp_queue_get_config_reply) == 16); + +/* OFPAT_ENQUEUE action struct: send packets to given queue on port. */ +struct ofp_action_enqueue { + uint16_t type; /* OFPAT_ENQUEUE. */ + uint16_t len; /* Len is 16. */ + uint16_t port; /* Port that queue belongs. Should + refer to a valid physical port + (i.e. < OFPP_MAX) or OFPP_IN_PORT. */ + uint8_t pad[6]; /* Pad for 64-bit alignment. */ + uint32_t queue_id; /* Where to enqueue the packets. */ +}; +OFP_ASSERT(sizeof(struct ofp_action_enqueue) == 16); + +struct ofp_queue_stats_request { + uint16_t port_no; /* All ports if OFPT_ALL. */ + uint8_t pad[2]; /* Align to 32-bits. */ + uint32_t queue_id; /* All queues if OFPQ_ALL. */ +}; +OFP_ASSERT(sizeof(struct ofp_queue_stats_request) == 8); + +struct ofp_queue_stats { + uint16_t port_no; + uint8_t pad[2]; /* Align to 32-bits. */ + uint32_t queue_id; /* Queue i.d */ + uint64_t tx_bytes; /* Number of transmitted bytes. */ + uint64_t tx_packets; /* Number of transmitted packets. */ + uint64_t tx_errors; /* Number of packets dropped due to overrun. */ +}; +OFP_ASSERT(sizeof(struct ofp_queue_stats) == 32); + +#endif /* openflow/openflow.h */ diff --git a/print-openflow-1.0.c b/print-openflow-1.0.c new file mode 100644 index 00000000..3f6b77f9 --- /dev/null +++ b/print-openflow-1.0.c @@ -0,0 +1,1812 @@ +/* + * This module implements decoding of OpenFlow protocol version 1.0 (wire + * protocol 0x01). The decoder implements terse (default), detailed (-v) and + * full (-vv) output formats and, as much as each format implies, detects and + * tries to work around sizing anomalies inside the messages. The decoder marks + * up bogus values of selected message fields and decodes partially captured + * messages up to the snapshot end. It is based on the specification below: + * + * [OF10] http://www.openflow.org/documents/openflow-spec-v1.0.0.pdf + * + * + * Copyright (c) 2013 The TCPDUMP project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "interface.h" +#include "extract.h" +#include "addrtoname.h" +#include "ethertype.h" +#include "ipproto.h" +#include "openflow-1.0.h" + +static const struct tok ofpt_str[] = { + { OFPT_HELLO, "HELLO" }, + { OFPT_ERROR, "ERROR" }, + { OFPT_ECHO_REQUEST, "ECHO_REQUEST" }, + { OFPT_ECHO_REPLY, "ECHO_REPLY" }, + { OFPT_VENDOR, "VENDOR" }, + { OFPT_FEATURES_REQUEST, "FEATURES_REQUEST" }, + { OFPT_FEATURES_REPLY, "FEATURES_REPLY" }, + { OFPT_GET_CONFIG_REQUEST, "GET_CONFIG_REQUEST" }, + { OFPT_GET_CONFIG_REPLY, "GET_CONFIG_REPLY" }, + { OFPT_SET_CONFIG, "SET_CONFIG" }, + { OFPT_PACKET_IN, "PACKET_IN" }, + { OFPT_FLOW_REMOVED, "FLOW_REMOVED" }, + { OFPT_PORT_STATUS, "PORT_STATUS" }, + { OFPT_PACKET_OUT, "PACKET_OUT" }, + { OFPT_FLOW_MOD, "FLOW_MOD" }, + { OFPT_PORT_MOD, "PORT_MOD" }, + { OFPT_STATS_REQUEST, "STATS_REQUEST" }, + { OFPT_STATS_REPLY, "STATS_REPLY" }, + { OFPT_BARRIER_REQUEST, "BARRIER_REQUEST" }, + { OFPT_BARRIER_REPLY, "BARRIER_REPLY" }, + { OFPT_QUEUE_GET_CONFIG_REQUEST, "QUEUE_GET_CONFIG_REQUEST" }, + { OFPT_QUEUE_GET_CONFIG_REPLY, "QUEUE_GET_CONFIG_REPLY" }, + { 0, NULL } +}; + +static const struct tok ofppc_bm[] = { + { OFPPC_PORT_DOWN, "PORT_DOWN" }, + { OFPPC_NO_STP, "NO_STP" }, + { OFPPC_NO_RECV, "NO_RECV" }, + { OFPPC_NO_RECV_STP, "NO_RECV_STP" }, + { OFPPC_NO_FLOOD, "NO_FLOOD" }, + { OFPPC_NO_FWD, "NO_FWD" }, + { OFPPC_NO_PACKET_IN, "NO_PACKET_IN" }, + { 0, NULL } +}; +#define OFPPC_U (~(OFPPC_PORT_DOWN | OFPPC_NO_STP | OFPPC_NO_RECV | \ + OFPPC_NO_RECV_STP | OFPPC_NO_FLOOD | OFPPC_NO_FWD | \ + OFPPC_NO_PACKET_IN)) + +static const struct tok ofpps_bm[] = { + { OFPPS_LINK_DOWN, "LINK_DOWN" }, + { OFPPS_STP_LISTEN, "STP_LISTEN" }, + { OFPPS_STP_LEARN, "STP_LEARN" }, + { OFPPS_STP_FORWARD, "STP_FORWARD" }, + { OFPPS_STP_BLOCK, "STP_BLOCK" }, + { 0, NULL } +}; +#define OFPPS_U (~(OFPPS_LINK_DOWN | OFPPS_STP_LISTEN | OFPPS_STP_LEARN | \ + OFPPS_STP_FORWARD | OFPPS_STP_BLOCK)) + +static const struct tok ofpp_str[] = { + { OFPP_MAX, "MAX" }, + { OFPP_IN_PORT, "IN_PORT" }, + { OFPP_TABLE, "TABLE" }, + { OFPP_NORMAL, "NORMAL" }, + { OFPP_FLOOD, "FLOOD" }, + { OFPP_ALL, "ALL" }, + { OFPP_CONTROLLER, "CONTROLLER" }, + { OFPP_LOCAL, "LOCAL" }, + { OFPP_NONE, "NONE" }, + { 0, NULL } +}; + +static const struct tok ofppf_bm[] = { + { OFPPF_10MB_HD, "10MB_HD" }, + { OFPPF_10MB_FD, "10MB_FD" }, + { OFPPF_100MB_HD, "100MB_HD" }, + { OFPPF_100MB_FD, "100MB_FD" }, + { OFPPF_1GB_HD, "1GB_HD" }, + { OFPPF_1GB_FD, "1GB_FD" }, + { OFPPF_10GB_FD, "10GB_FD" }, + { OFPPF_COPPER, "COPPER" }, + { OFPPF_FIBER, "FIBER" }, + { OFPPF_AUTONEG, "AUTONEG" }, + { OFPPF_PAUSE, "PAUSE" }, + { OFPPF_PAUSE_ASYM, "PAUSE_ASYM" }, + { 0, NULL } +}; +#define OFPPF_U (~(OFPPF_10MB_HD | OFPPF_10MB_FD | OFPPF_100MB_HD | \ + OFPPF_100MB_FD | OFPPF_1GB_HD | OFPPF_1GB_FD | \ + OFPPF_10GB_FD | OFPPF_COPPER | OFPPF_FIBER | \ + OFPPF_AUTONEG | OFPPF_PAUSE | OFPPF_PAUSE_ASYM)) + +static const struct tok ofpqt_str[] = { + { OFPQT_NONE, "NONE" }, + { OFPQT_MIN_RATE, "MIN_RATE" }, + { 0, NULL } +}; + +static const struct tok ofpfw_bm[] = { + { OFPFW_IN_PORT, "IN_PORT" }, + { OFPFW_DL_VLAN, "DL_VLAN" }, + { OFPFW_DL_SRC, "DL_SRC" }, + { OFPFW_DL_DST, "DL_DST" }, + { OFPFW_DL_TYPE, "DL_TYPE" }, + { OFPFW_NW_PROTO, "NW_PROTO" }, + { OFPFW_TP_SRC, "TP_SRC" }, + { OFPFW_TP_DST, "TP_DST" }, + { OFPFW_DL_VLAN_PCP, "DL_VLAN_PCP" }, + { OFPFW_NW_TOS, "NW_TOS" }, + { 0, NULL } +}; +/* The above array does not include bits 8~13 (OFPFW_NW_SRC_*) and 14~19 + * (OFPFW_NW_DST_*), which are not a part of the bitmap and require decoding + * other than that of tok2str(). The macro below includes these bits such that + * they are not reported as bogus in the decoding. */ +#define OFPFW_U (~(OFPFW_ALL)) + +static const struct tok ofpat_str[] = { + { OFPAT_OUTPUT, "OUTPUT" }, + { OFPAT_SET_VLAN_VID, "SET_VLAN_VID" }, + { OFPAT_SET_VLAN_PCP, "SET_VLAN_PCP" }, + { OFPAT_STRIP_VLAN, "STRIP_VLAN" }, + { OFPAT_SET_DL_SRC, "SET_DL_SRC" }, + { OFPAT_SET_DL_DST, "SET_DL_DST" }, + { OFPAT_SET_NW_SRC, "SET_NW_SRC" }, + { OFPAT_SET_NW_DST, "SET_NW_DST" }, + { OFPAT_SET_NW_TOS, "SET_NW_TOS" }, + { OFPAT_SET_TP_SRC, "SET_TP_SRC" }, + { OFPAT_SET_TP_DST, "SET_TP_DST" }, + { OFPAT_ENQUEUE, "ENQUEUE" }, + { OFPAT_VENDOR, "VENDOR" }, + { 0, NULL } +}; + +/* bit-shifted, w/o vendor action */ +static const struct tok ofpat_bm[] = { + { 1 << OFPAT_OUTPUT, "OUTPUT" }, + { 1 << OFPAT_SET_VLAN_VID, "SET_VLAN_VID" }, + { 1 << OFPAT_SET_VLAN_PCP, "SET_VLAN_PCP" }, + { 1 << OFPAT_STRIP_VLAN, "STRIP_VLAN" }, + { 1 << OFPAT_SET_DL_SRC, "SET_DL_SRC" }, + { 1 << OFPAT_SET_DL_DST, "SET_DL_DST" }, + { 1 << OFPAT_SET_NW_SRC, "SET_NW_SRC" }, + { 1 << OFPAT_SET_NW_DST, "SET_NW_DST" }, + { 1 << OFPAT_SET_NW_TOS, "SET_NW_TOS" }, + { 1 << OFPAT_SET_TP_SRC, "SET_TP_SRC" }, + { 1 << OFPAT_SET_TP_DST, "SET_TP_DST" }, + { 1 << OFPAT_ENQUEUE, "ENQUEUE" }, + { 0, NULL } +}; +#define OFPAT_U (~(1 << OFPAT_OUTPUT | 1 << OFPAT_SET_VLAN_VID | \ + 1 << OFPAT_SET_VLAN_PCP | 1 << OFPAT_STRIP_VLAN | \ + 1 << OFPAT_SET_DL_SRC | 1 << OFPAT_SET_DL_DST | \ + 1 << OFPAT_SET_NW_SRC | 1 << OFPAT_SET_NW_DST | \ + 1 << OFPAT_SET_NW_TOS | 1 << OFPAT_SET_TP_SRC | \ + 1 << OFPAT_SET_TP_DST | 1 << OFPAT_ENQUEUE)) + +static const struct tok ofp_capabilities_bm[] = { + { OFPC_FLOW_STATS, "FLOW_STATS" }, + { OFPC_TABLE_STATS, "TABLE_STATS" }, + { OFPC_PORT_STATS, "PORT_STATS" }, + { OFPC_STP, "STP" }, + { OFPC_RESERVED, "RESERVED" }, /* not in the mask below */ + { OFPC_IP_REASM, "IP_REASM" }, + { OFPC_QUEUE_STATS, "QUEUE_STATS" }, + { OFPC_ARP_MATCH_IP, "ARP_MATCH_IP" }, + { 0, NULL } +}; +#define OFPCAP_U (~(OFPC_FLOW_STATS | OFPC_TABLE_STATS | OFPC_PORT_STATS | \ + OFPC_STP | OFPC_IP_REASM | OFPC_QUEUE_STATS | \ + OFPC_ARP_MATCH_IP)) + +static const struct tok ofp_config_str[] = { + { OFPC_FRAG_NORMAL, "FRAG_NORMAL" }, + { OFPC_FRAG_DROP, "FRAG_DROP" }, + { OFPC_FRAG_REASM, "FRAG_REASM" }, + { 0, NULL } +}; + +static const struct tok ofpfc_str[] = { + { OFPFC_ADD, "ADD" }, + { OFPFC_MODIFY, "MODIFY" }, + { OFPFC_MODIFY_STRICT, "MODIFY_STRICT" }, + { OFPFC_DELETE, "DELETE" }, + { OFPFC_DELETE_STRICT, "DELETE_STRICT" }, + { 0, NULL } +}; + +static const struct tok bufferid_str[] = { + { 0xffffffff, "NONE" }, + { 0, NULL } +}; + +static const struct tok ofpff_bm[] = { + { OFPFF_SEND_FLOW_REM, "SEND_FLOW_REM" }, + { OFPFF_CHECK_OVERLAP, "CHECK_OVERLAP" }, + { OFPFF_EMERG, "EMERG" }, + { 0, NULL } +}; +#define OFPFF_U (~(OFPFF_SEND_FLOW_REM | OFPFF_CHECK_OVERLAP | OFPFF_EMERG)) + +static const struct tok ofpst_str[] = { + { OFPST_DESC, "DESC" }, + { OFPST_FLOW, "FLOW" }, + { OFPST_AGGREGATE, "AGGREGATE" }, + { OFPST_TABLE, "TABLE" }, + { OFPST_PORT, "PORT" }, + { OFPST_QUEUE, "QUEUE" }, + { OFPST_VENDOR, "VENDOR" }, + { 0, NULL } +}; + +static const struct tok tableid_str[] = { + { 0xfe, "EMERG" }, + { 0xff, "ALL" }, + { 0, NULL } +}; + +static const struct tok ofpq_str[] = { + { OFPQ_ALL, "ALL" }, + { 0, NULL } +}; + +static const struct tok ofpsf_reply_bm[] = { + { OFPSF_REPLY_MORE, "MORE" }, + { 0, NULL } +}; +#define OFPSF_REPLY_U (~(OFPSF_REPLY_MORE)) + +static const struct tok ofpr_str[] = { + { OFPR_NO_MATCH, "NO_MATCH" }, + { OFPR_ACTION, "ACTION" }, + { 0, NULL } +}; + +static const struct tok ofprr_str[] = { + { OFPRR_IDLE_TIMEOUT, "IDLE_TIMEOUT" }, + { OFPRR_HARD_TIMEOUT, "HARD_TIMEOUT" }, + { OFPRR_DELETE, "DELETE" }, + { 0, NULL } +}; + +static const struct tok ofppr_str[] = { + { OFPPR_ADD, "ADD" }, + { OFPPR_DELETE, "DELETE" }, + { OFPPR_MODIFY, "MODIFY" }, + { 0, NULL } +}; + +static const struct tok ofpet_str[] = { + { OFPET_HELLO_FAILED, "HELLO_FAILED" }, + { OFPET_BAD_REQUEST, "BAD_REQUEST" }, + { OFPET_BAD_ACTION, "BAD_ACTION" }, + { OFPET_FLOW_MOD_FAILED, "FLOW_MOD_FAILED" }, + { OFPET_PORT_MOD_FAILED, "PORT_MOD_FAILED" }, + { OFPET_QUEUE_OP_FAILED, "QUEUE_OP_FAILED" }, + { 0, NULL } +}; + +static const struct tok ofphfc_str[] = { + { OFPHFC_INCOMPATIBLE, "INCOMPATIBLE" }, + { OFPHFC_EPERM, "EPERM" }, + { 0, NULL } +}; + +static const struct tok ofpbrc_str[] = { + { OFPBRC_BAD_VERSION, "BAD_VERSION" }, + { OFPBRC_BAD_TYPE, "BAD_TYPE" }, + { OFPBRC_BAD_STAT, "BAD_STAT" }, + { OFPBRC_BAD_VENDOR, "BAD_VENDOR" }, + { OFPBRC_BAD_SUBTYPE, "BAD_SUBTYPE" }, + { OFPBRC_EPERM, "EPERM" }, + { OFPBRC_BAD_LEN, "BAD_LEN" }, + { OFPBRC_BUFFER_EMPTY, "BUFFER_EMPTY" }, + { OFPBRC_BUFFER_UNKNOWN, "BUFFER_UNKNOWN" }, + { 0, NULL } +}; + +static const struct tok ofpbac_str[] = { + { OFPBAC_BAD_TYPE, "BAD_TYPE" }, + { OFPBAC_BAD_LEN, "BAD_LEN" }, + { OFPBAC_BAD_VENDOR, "BAD_VENDOR" }, + { OFPBAC_BAD_VENDOR_TYPE, "BAD_VENDOR_TYPE" }, + { OFPBAC_BAD_OUT_PORT, "BAD_OUT_PORT" }, + { OFPBAC_BAD_ARGUMENT, "BAD_ARGUMENT" }, + { OFPBAC_EPERM, "EPERM" }, + { OFPBAC_TOO_MANY, "TOO_MANY" }, + { OFPBAC_BAD_QUEUE, "BAD_QUEUE" }, + { 0, NULL } +}; + +static const struct tok ofpfmfc_str[] = { + { OFPFMFC_ALL_TABLES_FULL, "ALL_TABLES_FULL" }, + { OFPFMFC_OVERLAP, "OVERLAP" }, + { OFPFMFC_EPERM, "EPERM" }, + { OFPFMFC_BAD_EMERG_TIMEOUT, "BAD_EMERG_TIMEOUT" }, + { OFPFMFC_BAD_COMMAND, "BAD_COMMAND" }, + { OFPFMFC_UNSUPPORTED, "UNSUPPORTED" }, + { 0, NULL } +}; + +static const struct tok ofppmfc_str[] = { + { OFPPMFC_BAD_PORT, "BAD_PORT" }, + { OFPPMFC_BAD_HW_ADDR, "BAD_HW_ADDR" }, + { 0, NULL } +}; + +static const struct tok ofpqofc_str[] = { + { OFPQOFC_BAD_PORT, "BAD_PORT" }, + { OFPQOFC_BAD_QUEUE, "BAD_QUEUE" }, + { OFPQOFC_EPERM, "EPERM" }, + { 0, NULL } +}; + +static const struct tok empty_str[] = { + { 0, NULL } +}; + + +static const char * +vlan_str(const uint16_t vid) { + static char buf[sizeof("65535 (bogus)")]; + const char *fmt; + + if (vid == OFP_VLAN_NONE) + return "NONE"; + fmt = (vid > 0 && vid < 0x0fff) ? "%u" : "%u (bogus)"; + snprintf(buf, sizeof(buf), fmt, vid); + return buf; +} + +static const char * +pcp_str(const uint8_t pcp) { + static char buf[sizeof("255 (bogus)")]; + snprintf(buf, sizeof(buf), pcp <= 7 ? "%u" : "%u (bogus)", pcp); + return buf; +} + +static void +of10_bitmap_print(const struct tok *t, const uint32_t v, const uint32_t u) { + const char *sep = " ("; + + if (v == 0) + return; + /* assigned bits */ + for (; t->s != NULL; t++) + if (v & t->v) { + printf("%s%s", sep, t->s); + sep = ", "; + } + /* unassigned bits? */ + printf(v & u ? ") (bogus)" : ")"); +} + +static const u_char * +of10_data_print(const u_char *cp, const u_char *ep, const u_int len) { + if (len == 0) + return cp; + /* data */ + printf("\n\t data (%u octets)", len); + TCHECK2(*cp, len); + if (vflag >= 2) + hex_and_ascii_print("\n\t ", cp, len); + return cp + len; + +trunc: + printf(" [|openflow]"); + return ep; +} + +/* Vendor ID is mandatory, data is optional. */ +static const u_char * +of10_vendor_data_print(const u_char *cp, const u_char *ep, const u_int len) { + if (len < 4) + goto corrupt; + /* vendor */ + TCHECK2(*cp, 4); + printf(", vendor 0x%08x", EXTRACT_32BITS(cp)); + cp += 4; + /* data */ + return of10_data_print(cp, ep, len - 4); + +corrupt: /* skip the undersized data */ + printf(" (corrupt)"); + TCHECK2(*cp, len); + return cp + len; +trunc: + printf(" [|openflow]"); + return ep; +} + +/* [OF10] Section 5.2.1 */ +static const u_char * +of10_phy_ports_print(const u_char *cp, const u_char *ep, u_int len) { + const u_char *cp0 = cp; + const u_int len0 = len; + + while (len) { + if (len < sizeof(struct ofp_phy_port)) + goto corrupt; + /* port_no */ + TCHECK2(*cp, 2); + printf("\n\t port_no %s", tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp))); + cp += 2; + /* hw_addr */ + TCHECK2(*cp, OFP_ETH_ALEN); + printf(", hw_addr %s", etheraddr_string(cp)); + cp += OFP_ETH_ALEN; + /* name */ + TCHECK2(*cp, OFP_MAX_PORT_NAME_LEN); + printf(", name '"); + fn_print(cp, cp + OFP_MAX_PORT_NAME_LEN); + printf("'"); + cp += OFP_MAX_PORT_NAME_LEN; + + if (vflag < 2) { + TCHECK2(*cp, 24); + cp += 24; + goto next_port; + } + /* config */ + TCHECK2(*cp, 4); + printf("\n\t config 0x%08x", EXTRACT_32BITS(cp)); + of10_bitmap_print(ofppc_bm, EXTRACT_32BITS(cp), OFPPC_U); + cp += 4; + /* state */ + TCHECK2(*cp, 4); + printf("\n\t state 0x%08x", EXTRACT_32BITS(cp)); + of10_bitmap_print(ofpps_bm, EXTRACT_32BITS(cp), OFPPS_U); + cp += 4; + /* curr */ + TCHECK2(*cp, 4); + printf("\n\t curr 0x%08x", EXTRACT_32BITS(cp)); + of10_bitmap_print(ofppf_bm, EXTRACT_32BITS(cp), OFPPF_U); + cp += 4; + /* advertised */ + TCHECK2(*cp, 4); + printf("\n\t advertised 0x%08x", EXTRACT_32BITS(cp)); + of10_bitmap_print(ofppf_bm, EXTRACT_32BITS(cp), OFPPF_U); + cp += 4; + /* supported */ + TCHECK2(*cp, 4); + printf("\n\t supported 0x%08x", EXTRACT_32BITS(cp)); + of10_bitmap_print(ofppf_bm, EXTRACT_32BITS(cp), OFPPF_U); + cp += 4; + /* peer */ + TCHECK2(*cp, 4); + printf("\n\t peer 0x%08x", EXTRACT_32BITS(cp)); + of10_bitmap_print(ofppf_bm, EXTRACT_32BITS(cp), OFPPF_U); + cp += 4; +next_port: + len -= sizeof(struct ofp_phy_port); + } /* while */ + return cp; + +corrupt: /* skip the undersized trailing data */ + printf(" (corrupt)"); + TCHECK2(*cp0, len0); + return cp0 + len0; +trunc: + printf(" [|openflow]"); + return ep; +} + +/* [OF10] Section 5.2.2 */ +static const u_char * +of10_queue_props_print(const u_char *cp, const u_char *ep, u_int len) { + const u_char *cp0 = cp; + const u_int len0 = len; + uint16_t property, plen, rate; + + while (len) { + u_char plen_bogus = 0, skip = 0; + + if (len < sizeof(struct ofp_queue_prop_header)) + goto corrupt; + /* property */ + TCHECK2(*cp, 2); + property = EXTRACT_16BITS(cp); + cp += 2; + printf("\n\t property %s", tok2str(ofpqt_str, "invalid (0x%04x)", property)); + /* len */ + TCHECK2(*cp, 2); + plen = EXTRACT_16BITS(cp); + cp += 2; + printf(", len %u", plen); + if (plen < sizeof(struct ofp_queue_prop_header) || plen > len) + goto corrupt; + /* pad */ + TCHECK2(*cp, 4); + cp += 4; + /* property-specific constraints and decoding */ + switch (property) { + case OFPQT_NONE: + plen_bogus = plen != sizeof(struct ofp_queue_prop_header); + break; + case OFPQT_MIN_RATE: + plen_bogus = plen != sizeof(struct ofp_queue_prop_min_rate); + break; + default: + skip = 1; + } + if (plen_bogus) { + printf(" (bogus)"); + skip = 1; + } + if (skip) { + TCHECK2(*cp, plen - 4); + cp += plen - 4; + goto next_property; + } + if (property == OFPQT_MIN_RATE) { /* the only case of property decoding */ + /* rate */ + TCHECK2(*cp, 2); + rate = EXTRACT_16BITS(cp); + cp += 2; + if (rate > 1000) + printf(", rate disabled"); + else + printf(", rate %u.%u%%", rate / 10, rate % 10); + /* pad */ + TCHECK2(*cp, 6); + cp += 6; + } +next_property: + len -= plen; + } /* while */ + return cp; + +corrupt: /* skip the rest of queue properties */ + printf(" (corrupt)"); + TCHECK2(*cp0, len0); + return cp0 + len0; +trunc: + printf(" [|openflow]"); + return ep; +} + +/* ibid */ +static const u_char * +of10_queues_print(const u_char *cp, const u_char *ep, u_int len) { + const u_char *cp0 = cp; + const u_int len0 = len; + uint16_t desclen; + + while (len) { + if (len < sizeof(struct ofp_packet_queue)) + goto corrupt; + /* queue_id */ + TCHECK2(*cp, 4); + printf("\n\t queue_id %u", EXTRACT_32BITS(cp)); + cp += 4; + /* len */ + TCHECK2(*cp, 2); + desclen = EXTRACT_16BITS(cp); + cp += 2; + printf(", len %u", desclen); + if (desclen < sizeof(struct ofp_packet_queue) || desclen > len) + goto corrupt; + /* pad */ + TCHECK2(*cp, 2); + cp += 2; + /* properties */ + if (vflag < 2) { + TCHECK2(*cp, desclen - sizeof(struct ofp_packet_queue)); + cp += desclen - sizeof(struct ofp_packet_queue); + goto next_queue; + } + if (ep == (cp = of10_queue_props_print(cp, ep, desclen - sizeof(struct ofp_packet_queue)))) + return ep; /* end of snapshot */ +next_queue: + len -= desclen; + } /* while */ + return cp; + +corrupt: /* skip the rest of queues */ + printf(" (corrupt)"); + TCHECK2(*cp0, len0); + return cp0 + len0; +trunc: + printf(" [|openflow]"); + return ep; +} + +/* [OF10] Section 5.2.3 */ +static const u_char * +of10_match_print(const char *pfx, const u_char *cp, const u_char *ep) { + uint32_t wildcards; + uint16_t dl_type; + uint8_t nw_proto; + u_char nw_bits; + const char *field_name; + + /* wildcards */ + TCHECK2(*cp, 4); + wildcards = EXTRACT_32BITS(cp); + if (wildcards & OFPFW_U) + printf("%swildcards 0x%08x (bogus)", pfx, wildcards); + cp += 4; + /* in_port */ + TCHECK2(*cp, 2); + if (! (wildcards & OFPFW_IN_PORT)) + printf("%smatch in_port %s", pfx, tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp))); + cp += 2; + /* dl_src */ + TCHECK2(*cp, OFP_ETH_ALEN); + if (! (wildcards & OFPFW_DL_SRC)) + printf("%smatch dl_src %s", pfx, etheraddr_string(cp)); + cp += OFP_ETH_ALEN; + /* dl_dst */ + TCHECK2(*cp, OFP_ETH_ALEN); + if (! (wildcards & OFPFW_DL_DST)) + printf("%smatch dl_dst %s", pfx, etheraddr_string(cp)); + cp += OFP_ETH_ALEN; + /* dl_vlan */ + TCHECK2(*cp, 2); + if (! (wildcards & OFPFW_DL_VLAN)) + printf("%smatch dl_vlan %s", pfx, vlan_str(EXTRACT_16BITS(cp))); + cp += 2; + /* dl_vlan_pcp */ + TCHECK2(*cp, 1); + if (! (wildcards & OFPFW_DL_VLAN_PCP)) + printf("%smatch dl_vlan_pcp %s", pfx, pcp_str(*cp)); + cp += 1; + /* pad1 */ + TCHECK2(*cp, 1); + cp += 1; + /* dl_type */ + TCHECK2(*cp, 2); + dl_type = EXTRACT_16BITS(cp); + cp += 2; + if (! (wildcards & OFPFW_DL_TYPE)) + printf("%smatch dl_type 0x%04x", pfx, dl_type); + /* nw_tos */ + TCHECK2(*cp, 1); + if (! (wildcards & OFPFW_NW_TOS)) + printf("%smatch nw_tos 0x%02x", pfx, *cp); + cp += 1; + /* nw_proto */ + TCHECK2(*cp, 1); + nw_proto = *cp; + cp += 1; + if (! (wildcards & OFPFW_NW_PROTO)) { + field_name = ! (wildcards & OFPFW_DL_TYPE) && dl_type == ETHERTYPE_ARP + ? "arp_opcode" : "nw_proto"; + printf("%smatch %s %u", pfx, field_name, nw_proto); + } + /* pad2 */ + TCHECK2(*cp, 2); + cp += 2; + /* nw_src */ + TCHECK2(*cp, 4); + nw_bits = (wildcards & OFPFW_NW_SRC_MASK) >> OFPFW_NW_SRC_SHIFT; + if (nw_bits < 32) + printf("%smatch nw_src %s/%u", pfx, ipaddr_string(cp), 32 - nw_bits); + cp += 4; + /* nw_dst */ + TCHECK2(*cp, 4); + nw_bits = (wildcards & OFPFW_NW_DST_MASK) >> OFPFW_NW_DST_SHIFT; + if (nw_bits < 32) + printf("%smatch nw_dst %s/%u", pfx, ipaddr_string(cp), 32 - nw_bits); + cp += 4; + /* tp_src */ + TCHECK2(*cp, 2); + if (! (wildcards & OFPFW_TP_SRC)) { + field_name = ! (wildcards & OFPFW_DL_TYPE) && dl_type == ETHERTYPE_IP + && ! (wildcards & OFPFW_NW_PROTO) && nw_proto == IPPROTO_ICMP + ? "icmp_type" : "tp_src"; + printf("%smatch %s %u", pfx, field_name, EXTRACT_16BITS(cp)); + } + cp += 2; + /* tp_dst */ + TCHECK2(*cp, 2); + if (! (wildcards & OFPFW_TP_DST)) { + field_name = ! (wildcards & OFPFW_DL_TYPE) && dl_type == ETHERTYPE_IP + && ! (wildcards & OFPFW_NW_PROTO) && nw_proto == IPPROTO_ICMP + ? "icmp_code" : "tp_dst"; + printf("%smatch %s %u", pfx, field_name, EXTRACT_16BITS(cp)); + } + return cp + 2; + +trunc: + printf(" [|openflow]"); + return ep; +} + +/* [OF10] Section 5.2.4 */ +static const u_char * +of10_actions_print(const char *pfx, const u_char *cp, const u_char *ep, + u_int len) { + const u_char *cp0 = cp; + const u_int len0 = len; + uint16_t type, alen, output_port; + + while (len) { + u_char alen_bogus = 0, skip = 0; + + if (len < sizeof(struct ofp_action_header)) + goto corrupt; + /* type */ + TCHECK2(*cp, 2); + type = EXTRACT_16BITS(cp); + cp += 2; + printf("%saction type %s", pfx, tok2str(ofpat_str, "invalid (0x%04x)", type)); + /* length */ + TCHECK2(*cp, 2); + alen = EXTRACT_16BITS(cp); + cp += 2; + printf(", len %u", alen); + /* On action size underrun/overrun skip the rest of the action list. */ + if (alen < sizeof(struct ofp_action_header) || alen > len) + goto corrupt; + /* On action size inappropriate for the given type or invalid type just skip + * the current action, as the basic length constraint has been met. */ + switch (type) { + case OFPAT_OUTPUT: + case OFPAT_SET_VLAN_VID: + case OFPAT_SET_VLAN_PCP: + case OFPAT_STRIP_VLAN: + case OFPAT_SET_NW_SRC: + case OFPAT_SET_NW_DST: + case OFPAT_SET_NW_TOS: + case OFPAT_SET_TP_SRC: + case OFPAT_SET_TP_DST: + alen_bogus = alen != 8; + break; + case OFPAT_SET_DL_SRC: + case OFPAT_SET_DL_DST: + case OFPAT_ENQUEUE: + alen_bogus = alen != 16; + break; + case OFPAT_VENDOR: + alen_bogus = alen % 8 != 0; /* already >= 8 so far */ + break; + default: + skip = 1; + } + if (alen_bogus) { + printf(" (bogus)"); + skip = 1; + } + if (skip) { + TCHECK2(*cp, alen - 4); + cp += alen - 4; + goto next_action; + } + /* OK to decode the rest of the action structure */ + switch (type) { + case OFPAT_OUTPUT: + /* port */ + TCHECK2(*cp, 2); + output_port = EXTRACT_16BITS(cp); + cp += 2; + printf(", port %s", tok2str(ofpp_str, "%u", output_port)); + /* max_len */ + TCHECK2(*cp, 2); + if (output_port == OFPP_CONTROLLER) + printf(", max_len %u", EXTRACT_16BITS(cp)); + cp += 2; + break; + case OFPAT_SET_VLAN_VID: + /* vlan_vid */ + TCHECK2(*cp, 2); + printf(", vlan_vid %s", vlan_str(EXTRACT_16BITS(cp))); + cp += 2; + /* pad */ + TCHECK2(*cp, 2); + cp += 2; + break; + case OFPAT_SET_VLAN_PCP: + /* vlan_pcp */ + TCHECK2(*cp, 1); + printf(", vlan_pcp %s", pcp_str(*cp)); + cp += 1; + /* pad */ + TCHECK2(*cp, 3); + cp += 3; + break; + case OFPAT_SET_DL_SRC: + case OFPAT_SET_DL_DST: + /* dl_addr */ + TCHECK2(*cp, OFP_ETH_ALEN); + printf(", dl_addr %s", etheraddr_string(cp)); + cp += OFP_ETH_ALEN; + /* pad */ + TCHECK2(*cp, 6); + cp += 6; + break; + case OFPAT_SET_NW_SRC: + case OFPAT_SET_NW_DST: + /* nw_addr */ + TCHECK2(*cp, 4); + printf(", nw_addr %s", ipaddr_string(cp)); + cp += 4; + break; + case OFPAT_SET_NW_TOS: + /* nw_tos */ + TCHECK2(*cp, 1); + printf(", nw_tos 0x%02x", *cp); + cp += 1; + /* pad */ + TCHECK2(*cp, 3); + cp += 3; + break; + case OFPAT_SET_TP_SRC: + case OFPAT_SET_TP_DST: + /* nw_tos */ + TCHECK2(*cp, 2); + printf(", tp_port %u", EXTRACT_16BITS(cp)); + cp += 2; + /* pad */ + TCHECK2(*cp, 2); + cp += 2; + break; + case OFPAT_ENQUEUE: + /* port */ + TCHECK2(*cp, 2); + printf(", port %s", tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp))); + cp += 2; + /* pad */ + TCHECK2(*cp, 6); + cp += 6; + /* queue_id */ + TCHECK2(*cp, 4); + printf(", queue_id %s", tok2str(ofpq_str, "%u", EXTRACT_32BITS(cp))); + cp += 4; + break; + case OFPAT_VENDOR: + if (ep == (cp = of10_vendor_data_print(cp, ep, alen - 4))) + return ep; /* end of snapshot */ + break; + case OFPAT_STRIP_VLAN: + /* pad */ + TCHECK2(*cp, 4); + cp += 4; + break; + } /* switch */ +next_action: + len -= alen; + } /* while */ + return cp; + +corrupt: /* skip the rest of actions */ + printf(" (corrupt)"); + TCHECK2(*cp0, len0); + return cp0 + len0; +trunc: + printf(" [|openflow]"); + return ep; +} + +/* [OF10] Section 5.3.1 */ +static const u_char * +of10_features_reply_print(const u_char *cp, const u_char *ep, const u_int len) { + /* datapath_id */ + TCHECK2(*cp, 8); + printf("\n\t dpid 0x%016" PRIx64, EXTRACT_64BITS(cp)); + cp += 8; + /* n_buffers */ + TCHECK2(*cp, 4); + printf(", n_buffers %u", EXTRACT_32BITS(cp)); + cp += 4; + /* n_tables */ + TCHECK2(*cp, 1); + printf(", n_tables %u", *cp); + cp += 1; + /* pad */ + TCHECK2(*cp, 3); + cp += 3; + /* capabilities */ + TCHECK2(*cp, 4); + printf("\n\t capabilities 0x%08x", EXTRACT_32BITS(cp)); + of10_bitmap_print(ofp_capabilities_bm, EXTRACT_32BITS(cp), OFPCAP_U); + cp += 4; + /* actions */ + TCHECK2(*cp, 4); + printf("\n\t actions 0x%08x", EXTRACT_32BITS(cp)); + of10_bitmap_print(ofpat_bm, EXTRACT_32BITS(cp), OFPAT_U); + cp += 4; + /* ports */ + return of10_phy_ports_print(cp, ep, len - sizeof(struct ofp_switch_features)); + +trunc: + printf(" [|openflow]"); + return ep; +} + +/* [OF10] Section 5.3.3 */ +static const u_char * +of10_flow_mod_print(const u_char *cp, const u_char *ep, const u_int len) { + uint16_t command; + + /* match */ + if (ep == (cp = of10_match_print("\n\t ", cp, ep))) + return ep; /* end of snapshot */ + /* cookie */ + TCHECK2(*cp, 8); + printf("\n\t cookie 0x%016" PRIx64, EXTRACT_64BITS(cp)); + cp += 8; + /* command */ + TCHECK2(*cp, 2); + command = EXTRACT_16BITS(cp); + printf(", command %s", tok2str(ofpfc_str, "invalid (0x%04x)", command)); + cp += 2; + /* idle_timeout */ + TCHECK2(*cp, 2); + if (EXTRACT_16BITS(cp)) + printf(", idle_timeout %u", EXTRACT_16BITS(cp)); + cp += 2; + /* hard_timeout */ + TCHECK2(*cp, 2); + if (EXTRACT_16BITS(cp)) + printf(", hard_timeout %u", EXTRACT_16BITS(cp)); + cp += 2; + /* priority */ + TCHECK2(*cp, 2); + if (EXTRACT_16BITS(cp)) + printf(", priority %u", EXTRACT_16BITS(cp)); + cp += 2; + /* buffer_id */ + TCHECK2(*cp, 4); + if (command == OFPFC_ADD || command == OFPFC_MODIFY || + command == OFPFC_MODIFY_STRICT) + printf(", buffer_id %s", tok2str(bufferid_str, "0x%08x", EXTRACT_32BITS(cp))); + cp += 4; + /* out_port */ + TCHECK2(*cp, 2); + if (command == OFPFC_DELETE || command == OFPFC_DELETE_STRICT) + printf(", out_port %s", tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp))); + cp += 2; + /* flags */ + TCHECK2(*cp, 2); + printf(", flags 0x%04x", EXTRACT_16BITS(cp)); + of10_bitmap_print(ofpff_bm, EXTRACT_16BITS(cp), OFPFF_U); + cp += 2; + /* actions */ + return of10_actions_print("\n\t ", cp, ep, len - sizeof(struct ofp_flow_mod)); + +trunc: + printf(" [|openflow]"); + return ep; +} + +/* ibid */ +static const u_char * +of10_port_mod_print(const u_char *cp, const u_char *ep) { + /* port_no */ + TCHECK2(*cp, 2); + printf("\n\t port_no %s", tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp))); + cp += 2; + /* hw_addr */ + TCHECK2(*cp, OFP_ETH_ALEN); + printf(", hw_addr %s", etheraddr_string(cp)); + cp += OFP_ETH_ALEN; + /* config */ + TCHECK2(*cp, 4); + printf("\n\t config 0x%08x", EXTRACT_32BITS(cp)); + of10_bitmap_print(ofppc_bm, EXTRACT_32BITS(cp), OFPPC_U); + cp += 4; + /* mask */ + TCHECK2(*cp, 4); + printf("\n\t mask 0x%08x", EXTRACT_32BITS(cp)); + of10_bitmap_print(ofppc_bm, EXTRACT_32BITS(cp), OFPPC_U); + cp += 4; + /* advertise */ + TCHECK2(*cp, 4); + printf("\n\t advertise 0x%08x", EXTRACT_32BITS(cp)); + of10_bitmap_print(ofppf_bm, EXTRACT_32BITS(cp), OFPPF_U); + cp += 4; + /* pad */ + TCHECK2(*cp, 4); + return cp + 4; + +trunc: + printf(" [|openflow]"); + return ep; +} + +/* [OF10] Section 5.3.5 */ +static const u_char * +of10_stats_request_print(const u_char *cp, const u_char *ep, u_int len) { + const u_char *cp0 = cp; + const u_int len0 = len; + uint16_t type; + + /* type */ + TCHECK2(*cp, 2); + type = EXTRACT_16BITS(cp); + cp += 2; + printf("\n\t type %s", tok2str(ofpst_str, "invalid (0x%04x)", type)); + /* flags */ + TCHECK2(*cp, 2); + printf(", flags 0x%04x", EXTRACT_16BITS(cp)); + if (EXTRACT_16BITS(cp)) + printf(" (bogus)"); + cp += 2; + /* type-specific body of one of fixed lengths */ + len -= sizeof(struct ofp_stats_request); + switch(type) { + case OFPST_DESC: + case OFPST_TABLE: + if (len) + goto corrupt; + return cp; + case OFPST_FLOW: + case OFPST_AGGREGATE: + if (len != sizeof(struct ofp_flow_stats_request)) + goto corrupt; + /* match */ + if (ep == (cp = of10_match_print("\n\t ", cp, ep))) + return ep; /* end of snapshot */ + /* table_id */ + TCHECK2(*cp, 1); + printf("\n\t table_id %s", tok2str(tableid_str, "%u", *cp)); + cp += 1; + /* pad */ + TCHECK2(*cp, 1); + cp += 1; + /* out_port */ + TCHECK2(*cp, 2); + printf(", out_port %s", tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp))); + return cp + 2; + case OFPST_PORT: + if (len != sizeof(struct ofp_port_stats_request)) + goto corrupt; + /* port_no */ + TCHECK2(*cp, 2); + printf("\n\t port_no %s", tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp))); + cp += 2; + /* pad */ + TCHECK2(*cp, 6); + return cp + 6; + case OFPST_QUEUE: + if (len != sizeof(struct ofp_queue_stats_request)) + goto corrupt; + /* port_no */ + TCHECK2(*cp, 2); + printf("\n\t port_no %s", tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp))); + cp += 2; + /* pad */ + TCHECK2(*cp, 2); + cp += 2; + /* queue_id */ + TCHECK2(*cp, 4); + printf(", queue_id %s", tok2str(ofpq_str, "%u", EXTRACT_32BITS(cp))); + return cp + 4; + case OFPST_VENDOR: + return of10_vendor_data_print(cp, ep, len); + } + return cp; + +corrupt: /* skip the message body */ + printf(" (corrupt)"); + TCHECK2(*cp0, len0); + return cp0 + len0; +trunc: + printf(" [|openflow]"); + return ep; +} + +/* ibid */ +static const u_char * +of10_desc_stats_reply_print(const u_char *cp, const u_char *ep, const u_int len) { + if (len != sizeof(struct ofp_desc_stats)) + goto corrupt; + /* mfr_desc */ + TCHECK2(*cp, DESC_STR_LEN); + printf("\n\t mfr_desc '"); + fn_print(cp, cp + DESC_STR_LEN); + printf("'"); + cp += DESC_STR_LEN; + /* hw_desc */ + TCHECK2(*cp, DESC_STR_LEN); + printf("\n\t hw_desc '"); + fn_print(cp, cp + DESC_STR_LEN); + printf("'"); + cp += DESC_STR_LEN; + /* sw_desc */ + TCHECK2(*cp, DESC_STR_LEN); + printf("\n\t sw_desc '"); + fn_print(cp, cp + DESC_STR_LEN); + printf("'"); + cp += DESC_STR_LEN; + /* serial_num */ + TCHECK2(*cp, SERIAL_NUM_LEN); + printf("\n\t serial_num '"); + fn_print(cp, cp + SERIAL_NUM_LEN); + printf("'"); + cp += SERIAL_NUM_LEN; + /* dp_desc */ + TCHECK2(*cp, DESC_STR_LEN); + printf("\n\t dp_desc '"); + fn_print(cp, cp + DESC_STR_LEN); + printf("'"); + return cp + DESC_STR_LEN; + +corrupt: /* skip the message body */ + printf(" (corrupt)"); + TCHECK2(*cp, len); + return cp + len; +trunc: + printf(" [|openflow]"); + return ep; +} + +/* ibid */ +static const u_char * +of10_flow_stats_reply_print(const u_char *cp, const u_char *ep, u_int len) { + const u_char *cp0 = cp; + const u_int len0 = len; + uint16_t entry_len; + + while (len) { + if (len < sizeof(struct ofp_flow_stats)) + goto corrupt; + /* length */ + TCHECK2(*cp, 2); + entry_len = EXTRACT_16BITS(cp); + printf("\n\t length %u", entry_len); + if (entry_len < sizeof(struct ofp_flow_stats) || entry_len > len) + goto corrupt; + cp += 2; + /* table_id */ + TCHECK2(*cp, 1); + printf(", table_id %s", tok2str(tableid_str, "%u", *cp)); + cp += 1; + /* pad */ + TCHECK2(*cp, 1); + cp += 1; + /* match */ + if (ep == (cp = of10_match_print("\n\t ", cp, ep))) + return ep; /* end of snapshot */ + /* duration_sec */ + TCHECK2(*cp, 4); + printf("\n\t duration_sec %u", EXTRACT_32BITS(cp)); + cp += 4; + /* duration_nsec */ + TCHECK2(*cp, 4); + printf(", duration_nsec %u", EXTRACT_32BITS(cp)); + cp += 4; + /* priority */ + TCHECK2(*cp, 2); + printf(", priority %u", EXTRACT_16BITS(cp)); + cp += 2; + /* idle_timeout */ + TCHECK2(*cp, 2); + printf(", idle_timeout %u", EXTRACT_16BITS(cp)); + cp += 2; + /* hard_timeout */ + TCHECK2(*cp, 2); + printf(", hard_timeout %u", EXTRACT_16BITS(cp)); + cp += 2; + /* pad2 */ + TCHECK2(*cp, 6); + cp += 6; + /* cookie */ + TCHECK2(*cp, 8); + printf(", cookie 0x%016" PRIx64, EXTRACT_64BITS(cp)); + cp += 8; + /* packet_count */ + TCHECK2(*cp, 8); + printf(", packet_count %" PRIu64, EXTRACT_64BITS(cp)); + cp += 8; + /* byte_count */ + TCHECK2(*cp, 8); + printf(", byte_count %" PRIu64, EXTRACT_64BITS(cp)); + cp += 8; + /* actions */ + if (ep == (cp = of10_actions_print("\n\t ", cp, ep, entry_len - sizeof(struct ofp_flow_stats)))) + return ep; /* end of snapshot */ + + len -= entry_len; + } /* while */ + return cp; + +corrupt: /* skip the rest of flow statistics entries */ + printf(" (corrupt)"); + TCHECK2(*cp0, len0); + return cp0 + len0; +trunc: + printf(" [|openflow]"); + return ep; +} + +/* ibid */ +static const u_char * +of10_aggregate_stats_reply_print(const u_char *cp, const u_char *ep, + const u_int len) { + if (len != sizeof(struct ofp_aggregate_stats_reply)) + goto corrupt; + /* packet_count */ + TCHECK2(*cp, 8); + printf("\n\t packet_count %" PRIu64, EXTRACT_64BITS(cp)); + cp += 8; + /* byte_count */ + TCHECK2(*cp, 8); + printf(", byte_count %" PRIu64, EXTRACT_64BITS(cp)); + cp += 8; + /* flow_count */ + TCHECK2(*cp, 4); + printf(", flow_count %u", EXTRACT_32BITS(cp)); + cp += 4; + /* pad */ + TCHECK2(*cp, 4); + return cp + 4; + +corrupt: /* skip the message body */ + printf(" (corrupt)"); + TCHECK2(*cp, len); + return cp + len; +trunc: + printf(" [|openflow]"); + return ep; +} + +/* ibid */ +static const u_char * +of10_table_stats_reply_print(const u_char *cp, const u_char *ep, u_int len) { + const u_char *cp0 = cp; + const u_int len0 = len; + + while (len) { + if (len < sizeof(struct ofp_table_stats)) + goto corrupt; + /* table_id */ + TCHECK2(*cp, 1); + printf("\n\t table_id %s", tok2str(tableid_str, "%u", *cp)); + cp += 1; + /* pad */ + TCHECK2(*cp, 3); + cp += 3; + /* name */ + TCHECK2(*cp, OFP_MAX_TABLE_NAME_LEN); + printf(", name '"); + fn_print(cp, cp + OFP_MAX_TABLE_NAME_LEN); + printf("'"); + cp += OFP_MAX_TABLE_NAME_LEN; + /* wildcards */ + TCHECK2(*cp, 4); + printf("\n\t wildcards 0x%08x", EXTRACT_32BITS(cp)); + of10_bitmap_print(ofpfw_bm, EXTRACT_32BITS(cp), OFPFW_U); + cp += 4; + /* max_entries */ + TCHECK2(*cp, 4); + printf("\n\t max_entries %u", EXTRACT_32BITS(cp)); + cp += 4; + /* active_count */ + TCHECK2(*cp, 4); + printf(", active_count %u", EXTRACT_32BITS(cp)); + cp += 4; + /* lookup_count */ + TCHECK2(*cp, 8); + printf(", lookup_count %" PRIu64, EXTRACT_64BITS(cp)); + cp += 8; + /* matched_count */ + TCHECK2(*cp, 8); + printf(", matched_count %" PRIu64, EXTRACT_64BITS(cp)); + cp += 8; + + len -= sizeof(struct ofp_table_stats); + } /* while */ + return cp; + +corrupt: /* skip the undersized trailing data */ + printf(" (corrupt)"); + TCHECK2(*cp0, len0); + return cp0 + len0; +trunc: + printf(" [|openflow]"); + return ep; +} + +/* ibid */ +static const u_char * +of10_port_stats_reply_print(const u_char *cp, const u_char *ep, u_int len) { + const u_char *cp0 = cp; + const u_int len0 = len; + + while (len) { + if (len < sizeof(struct ofp_port_stats)) + goto corrupt; + /* port_no */ + TCHECK2(*cp, 2); + printf("\n\t port_no %s", tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp))); + cp += 2; + if (vflag < 2) { + TCHECK2(*cp, sizeof(struct ofp_port_stats) - 2); + cp += sizeof(struct ofp_port_stats) - 2; + goto next_port; + } + /* pad */ + TCHECK2(*cp, 6); + cp += 6; + /* rx_packets */ + TCHECK2(*cp, 8); + printf(", rx_packets %" PRIu64, EXTRACT_64BITS(cp)); + cp += 8; + /* tx_packets */ + TCHECK2(*cp, 8); + printf(", tx_packets %" PRIu64, EXTRACT_64BITS(cp)); + cp += 8; + /* rx_bytes */ + TCHECK2(*cp, 8); + printf(", rx_bytes %" PRIu64, EXTRACT_64BITS(cp)); + cp += 8; + /* tx_bytes */ + TCHECK2(*cp, 8); + printf(", tx_bytes %" PRIu64, EXTRACT_64BITS(cp)); + cp += 8; + /* rx_dropped */ + TCHECK2(*cp, 8); + printf(", rx_dropped %" PRIu64, EXTRACT_64BITS(cp)); + cp += 8; + /* tx_dropped */ + TCHECK2(*cp, 8); + printf(", tx_dropped %" PRIu64, EXTRACT_64BITS(cp)); + cp += 8; + /* rx_errors */ + TCHECK2(*cp, 8); + printf(", rx_errors %" PRIu64, EXTRACT_64BITS(cp)); + cp += 8; + /* tx_errors */ + TCHECK2(*cp, 8); + printf(", tx_errors %" PRIu64, EXTRACT_64BITS(cp)); + cp += 8; + /* rx_frame_err */ + TCHECK2(*cp, 8); + printf(", rx_frame_err %" PRIu64, EXTRACT_64BITS(cp)); + cp += 8; + /* rx_over_err */ + TCHECK2(*cp, 8); + printf(", rx_over_err %" PRIu64, EXTRACT_64BITS(cp)); + cp += 8; + /* rx_crc_err */ + TCHECK2(*cp, 8); + printf(", rx_crc_err %" PRIu64, EXTRACT_64BITS(cp)); + cp += 8; + /* collisions */ + TCHECK2(*cp, 8); + printf(", collisions %" PRIu64, EXTRACT_64BITS(cp)); + cp += 8; +next_port: + len -= sizeof(struct ofp_port_stats); + } /* while */ + return cp; + +corrupt: /* skip the undersized trailing data */ + printf(" (corrupt)"); + TCHECK2(*cp0, len0); + return cp0 + len0; +trunc: + printf(" [|openflow]"); + return ep; +} + +/* ibid */ +static const u_char * +of10_queue_stats_reply_print(const u_char *cp, const u_char *ep, u_int len) { + const u_char *cp0 = cp; + const u_int len0 = len; + + while (len) { + if (len < sizeof(struct ofp_queue_stats)) + goto corrupt; + /* port_no */ + TCHECK2(*cp, 2); + printf("\n\t port_no %s", tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp))); + cp += 2; + /* pad */ + TCHECK2(*cp, 2); + cp += 2; + /* queue_id */ + TCHECK2(*cp, 4); + printf(", queue_id %u", EXTRACT_32BITS(cp)); + cp += 4; + /* tx_bytes */ + TCHECK2(*cp, 8); + printf(", tx_bytes %" PRIu64, EXTRACT_64BITS(cp)); + cp += 8; + /* tx_packets */ + TCHECK2(*cp, 8); + printf(", tx_packets %" PRIu64, EXTRACT_64BITS(cp)); + cp += 8; + /* tx_errors */ + TCHECK2(*cp, 8); + printf(", tx_errors %" PRIu64, EXTRACT_64BITS(cp)); + cp += 8; + + len -= sizeof(struct ofp_port_stats); + } /* while */ + return cp; + +corrupt: /* skip the undersized trailing data */ + printf(" (corrupt)"); + TCHECK2(*cp0, len0); + return cp0 + len0; +trunc: + printf(" [|openflow]"); + return ep; +} + +/* ibid */ +static const u_char * +of10_stats_reply_print(const u_char *cp, const u_char *ep, const u_int len) { + const u_char *cp0 = cp; + uint16_t type; + + /* type */ + TCHECK2(*cp, 2); + type = EXTRACT_16BITS(cp); + printf("\n\t type %s", tok2str(ofpst_str, "invalid (0x%04x)", type)); + cp += 2; + /* flags */ + TCHECK2(*cp, 2); + printf(", flags 0x%04x", EXTRACT_16BITS(cp)); + of10_bitmap_print(ofpsf_reply_bm, EXTRACT_16BITS(cp), OFPSF_REPLY_U); + cp += 2; + + if (vflag > 0) { + const u_char *(*decoder)(const u_char *, const u_char *, u_int) = + type == OFPST_DESC ? of10_desc_stats_reply_print : + type == OFPST_FLOW ? of10_flow_stats_reply_print : + type == OFPST_AGGREGATE ? of10_aggregate_stats_reply_print : + type == OFPST_TABLE ? of10_table_stats_reply_print : + type == OFPST_PORT ? of10_port_stats_reply_print : + type == OFPST_QUEUE ? of10_queue_stats_reply_print : + type == OFPST_VENDOR ? of10_vendor_data_print : + NULL; + if (decoder != NULL) + return decoder(cp, ep, len - sizeof(struct ofp_stats_reply)); + } + TCHECK2(*cp0, len); + return cp0 + len; + +trunc: + printf(" [|openflow]"); + return ep; +} + +/* [OF10] Section 5.3.6 */ +static const u_char * +of10_packet_out_print(const u_char *cp, const u_char *ep, const u_int len) { + const u_char *cp0 = cp; + const u_int len0 = len; + uint16_t actions_len; + + /* buffer_id */ + TCHECK2(*cp, 4); + printf("\n\t buffer_id 0x%08x", EXTRACT_32BITS(cp)); + cp += 4; + /* in_port */ + TCHECK2(*cp, 2); + printf(", in_port %s", tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp))); + cp += 2; + /* actions_len */ + TCHECK2(*cp, 2); + actions_len = EXTRACT_16BITS(cp); + cp += 2; + if (actions_len > len - sizeof(struct ofp_packet_out)) + goto corrupt; + /* actions */ + if (ep == (cp = of10_actions_print("\n\t ", cp, ep, actions_len))) + return ep; /* end of snapshot */ + /* data */ + return of10_data_print(cp, ep, len - sizeof(struct ofp_packet_out) - actions_len); + +corrupt: /* skip the rest of the message body */ + printf(" (corrupt)"); + TCHECK2(*cp0, len0); + return cp0 + len0; +trunc: + printf(" [|openflow]"); + return ep; +} + +/* [OF10] Section 5.4.1 */ +static const u_char * +of10_packet_in_print(const u_char *cp, const u_char *ep, const u_int len) { + /* buffer_id */ + TCHECK2(*cp, 4); + printf("\n\t buffer_id %s", tok2str(bufferid_str, "0x%08x", EXTRACT_32BITS(cp))); + cp += 4; + /* total_len */ + TCHECK2(*cp, 2); + printf(", total_len %u", EXTRACT_16BITS(cp)); + cp += 2; + /* in_port */ + TCHECK2(*cp, 2); + printf(", in_port %s", tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp))); + cp += 2; + /* reason */ + TCHECK2(*cp, 1); + printf(", reason %s", tok2str(ofpr_str, "invalid (0x%02x)", *cp)); + cp += 1; + /* pad */ + TCHECK2(*cp, 1); + cp += 1; + /* data */ + /* 2 mock octets count in sizeof() but not in len */ + return of10_data_print(cp, ep, len - (sizeof(struct ofp_packet_in) - 2)); + +trunc: + printf(" [|openflow]"); + return ep; +} + +/* [OF10] Section 5.4.2 */ +static const u_char * +of10_flow_removed_print(const u_char *cp, const u_char *ep) { + /* match */ + if (ep == (cp = of10_match_print("\n\t ", cp, ep))) + return ep; /* end of snapshot */ + /* cookie */ + TCHECK2(*cp, 8); + printf("\n\t cookie 0x%016" PRIx64, EXTRACT_64BITS(cp)); + cp += 8; + /* priority */ + TCHECK2(*cp, 2); + if (EXTRACT_16BITS(cp)) + printf(", priority %u", EXTRACT_16BITS(cp)); + cp += 2; + /* reason */ + TCHECK2(*cp, 1); + printf(", reason %s", tok2str(ofprr_str, "unknown (0x%02x)", *cp)); + cp += 1; + /* pad */ + TCHECK2(*cp, 1); + cp += 1; + /* duration_sec */ + TCHECK2(*cp, 4); + printf(", duration_sec %u", EXTRACT_32BITS(cp)); + cp += 4; + /* duration_nsec */ + TCHECK2(*cp, 4); + printf(", duration_nsec %u", EXTRACT_32BITS(cp)); + cp += 4; + /* idle_timeout */ + TCHECK2(*cp, 2); + if (EXTRACT_16BITS(cp)) + printf(", idle_timeout %u", EXTRACT_16BITS(cp)); + cp += 2; + /* pad2 */ + TCHECK2(*cp, 2); + cp += 2; + /* packet_count */ + TCHECK2(*cp, 8); + printf(", packet_count %" PRIu64, EXTRACT_64BITS(cp)); + cp += 8; + /* byte_count */ + TCHECK2(*cp, 8); + printf(", byte_count %" PRIu64, EXTRACT_64BITS(cp)); + return cp + 8; + +trunc: + printf(" [|openflow]"); + return ep; +} + +/* [OF10] Section 5.4.4 */ +static const u_char * +of10_error_print(const u_char *cp, const u_char *ep, const u_int len) { + uint16_t type; + const struct tok *code_str; + + /* type */ + TCHECK2(*cp, 2); + type = EXTRACT_16BITS(cp); + cp += 2; + printf("\n\t type %s", tok2str(ofpet_str, "invalid (0x%04x)", type)); + /* code */ + TCHECK2(*cp, 2); + code_str = + type == OFPET_HELLO_FAILED ? ofphfc_str : + type == OFPET_BAD_REQUEST ? ofpbrc_str : + type == OFPET_BAD_ACTION ? ofpbac_str : + type == OFPET_FLOW_MOD_FAILED ? ofpfmfc_str : + type == OFPET_PORT_MOD_FAILED ? ofppmfc_str : + type == OFPET_QUEUE_OP_FAILED ? ofpqofc_str : + empty_str; + printf(", code %s", tok2str(code_str, "invalid (0x%04x)", EXTRACT_16BITS(cp))); + cp += 2; + /* data */ + return of10_data_print(cp, ep, len - sizeof(struct ofp_error_msg)); + +trunc: + printf(" [|openflow]"); + return ep; +} + +const u_char * +of10_header_body_print(const u_char *cp, const u_char *ep, const uint8_t type, + const uint16_t len, const uint32_t xid) { + const u_char *cp0 = cp; + const u_int len0 = len; + /* Thus far message length is not less than the basic header size, but most + * message types have additional assorted constraints on the length. Wherever + * possible, check that message length meets the constraint, in remaining + * cases check that the length is OK to begin decoding and leave any final + * verification up to a lower-layer function. When the current message is + * corrupt, proceed to the next message. */ + + /* [OF10] Section 5.1 */ + printf("\n\tversion 1.0, type %s, length %u, xid 0x%08x", + tok2str(ofpt_str, "invalid (0x%02x)", type), len, xid); + switch (type) { + /* OpenFlow header only. */ + case OFPT_FEATURES_REQUEST: /* [OF10] Section 5.3.1 */ + case OFPT_GET_CONFIG_REQUEST: /* [OF10] Section 5.3.2 */ + case OFPT_BARRIER_REQUEST: /* [OF10] Section 5.3.7 */ + case OFPT_BARRIER_REPLY: /* ibid */ + if (len != sizeof(struct ofp_header)) + goto corrupt; + break; + + /* OpenFlow header and fixed-size message body. */ + case OFPT_SET_CONFIG: /* [OF10] Section 5.3.2 */ + case OFPT_GET_CONFIG_REPLY: /* ibid */ + if (len != sizeof(struct ofp_switch_config)) + goto corrupt; + if (vflag < 1) + goto next_message; + /* flags */ + TCHECK2(*cp, 2); + printf("\n\t flags %s", tok2str(ofp_config_str, "invalid (0x%04x)", EXTRACT_16BITS(cp))); + cp += 2; + /* miss_send_len */ + TCHECK2(*cp, 2); + printf(", miss_send_len %u", EXTRACT_16BITS(cp)); + return cp + 2; + case OFPT_PORT_MOD: + if (len != sizeof(struct ofp_port_mod)) + goto corrupt; + if (vflag < 1) + goto next_message; + return of10_port_mod_print(cp, ep); + case OFPT_QUEUE_GET_CONFIG_REQUEST: /* [OF10] Section 5.3.4 */ + if (len != sizeof(struct ofp_queue_get_config_request)) + goto corrupt; + if (vflag < 1) + goto next_message; + /* port */ + TCHECK2(*cp, 2); + printf("\n\t port_no %s", tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp))); + cp += 2; + /* pad */ + TCHECK2(*cp, 2); + return cp + 2; + case OFPT_FLOW_REMOVED: + if (len != sizeof(struct ofp_flow_removed)) + goto corrupt; + if (vflag < 1) + goto next_message; + return of10_flow_removed_print(cp, ep); + case OFPT_PORT_STATUS: /* [OF10] Section 5.4.3 */ + if (len != sizeof(struct ofp_port_status)) + goto corrupt; + if (vflag < 1) + goto next_message; + /* reason */ + TCHECK2(*cp, 1); + printf("\n\t reason %s", tok2str(ofppr_str, "invalid (0x%02x)", *cp)); + cp += 1; + /* pad */ + TCHECK2(*cp, 7); + cp += 7; + /* desc */ + return of10_phy_ports_print(cp, ep, sizeof(struct ofp_phy_port)); + + /* OpenFlow header, fixed-size message body and n * fixed-size data units. */ + case OFPT_FEATURES_REPLY: + if (len < sizeof(struct ofp_switch_features)) + goto corrupt; + if (vflag < 1) + goto next_message; + return of10_features_reply_print(cp, ep, len); + + /* OpenFlow header and variable-size data. */ + case OFPT_HELLO: /* [OF10] Section 5.5.1 */ + case OFPT_ECHO_REQUEST: /* [OF10] Section 5.5.2 */ + case OFPT_ECHO_REPLY: /* [OF10] Section 5.5.3 */ + if (vflag < 1) + goto next_message; + return of10_data_print(cp, ep, len - sizeof(struct ofp_header)); + + /* OpenFlow header, fixed-size message body and variable-size data. */ + case OFPT_ERROR: + if (len < sizeof(struct ofp_error_msg)) + goto corrupt; + if (vflag < 1) + goto next_message; + return of10_error_print(cp, ep, len); + case OFPT_VENDOR: + /* [OF10] Section 5.5.4 */ + if (len < sizeof(struct ofp_vendor_header)) + goto corrupt; + if (vflag < 1) + goto next_message; + return of10_vendor_data_print(cp, ep, len - sizeof(struct ofp_header)); + case OFPT_PACKET_IN: + /* 2 mock octets count in sizeof() but not in len */ + if (len < sizeof(struct ofp_packet_in) - 2) + goto corrupt; + if (vflag < 1) + goto next_message; + return of10_packet_in_print(cp, ep, len); + + /* a. OpenFlow header. */ + /* b. OpenFlow header and one of the fixed-size message bodies. */ + /* c. OpenFlow header, fixed-size message body and variable-size data. */ + case OFPT_STATS_REQUEST: + if (len < sizeof(struct ofp_stats_request)) + goto corrupt; + if (vflag < 1) + goto next_message; + return of10_stats_request_print(cp, ep, len); + + /* a. OpenFlow header and fixed-size message body. */ + /* b. OpenFlow header and n * fixed-size data units. */ + /* c. OpenFlow header and n * variable-size data units. */ + /* d. OpenFlow header, fixed-size message body and variable-size data. */ + case OFPT_STATS_REPLY: + if (len < sizeof(struct ofp_stats_reply)) + goto corrupt; + if (vflag < 1) + goto next_message; + return of10_stats_reply_print(cp, ep, len); + + /* OpenFlow header and n * variable-size data units and variable-size data. */ + case OFPT_PACKET_OUT: + if (len < sizeof(struct ofp_packet_out)) + goto corrupt; + if (vflag < 1) + goto next_message; + return of10_packet_out_print(cp, ep, len); + + /* OpenFlow header, fixed-size message body and n * variable-size data units. */ + case OFPT_FLOW_MOD: + if (len < sizeof(struct ofp_flow_mod)) + goto corrupt; + if (vflag < 1) + goto next_message; + return of10_flow_mod_print(cp, ep, len); + + /* OpenFlow header, fixed-size message body and n * variable-size data units. */ + case OFPT_QUEUE_GET_CONFIG_REPLY: /* [OF10] Section 5.3.4 */ + if (len < sizeof(struct ofp_queue_get_config_reply)) + goto corrupt; + if (vflag < 1) + goto next_message; + /* port */ + TCHECK2(*cp, 2); + printf("\n\t port_no %s", tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp))); + cp += 2; + /* pad */ + TCHECK2(*cp, 6); + cp += 6; + /* queues */ + return of10_queues_print(cp, ep, len - sizeof(struct ofp_queue_get_config_reply)); + } /* switch (type) */ + goto next_message; + +corrupt: /* skip the message body */ + printf(" (corrupt)"); +next_message: + TCHECK2(*cp0, len0 - sizeof(struct ofp_header)); + return cp0 + len0 - sizeof(struct ofp_header); +trunc: + printf(" [|openflow]"); + return ep; +} diff --git a/print-openflow.c b/print-openflow.c index 9da3597f..2a702dd0 100644 --- a/print-openflow.c +++ b/print-openflow.c @@ -40,6 +40,7 @@ #include "extract.h" #define OF_HEADER_LEN 8 +#define OF_VER_1_0 0x01 static void of_header_print(const uint8_t version, const uint8_t type, @@ -85,6 +86,8 @@ of_header_body_print(const u_char *cp, const u_char *ep) { /* Decode known protocol versions further without printing the header (the * type decoding is version-specific. */ switch (version) { + case OF_VER_1_0: + return of10_header_body_print(cp, ep, type, length, xid); default: of_header_print(version, type, length, xid); TCHECK2(*cp, length - OF_HEADER_LEN); diff --git a/tests/TESTLIST b/tests/TESTLIST index 00e579aa..74cbd053 100644 --- a/tests/TESTLIST +++ b/tests/TESTLIST @@ -117,3 +117,6 @@ mptcp-fclose mptcp-fclose.pcap mptcp-fclose.out -t # IEEE 802.11 tests 80211_exthdr ieee802.11_exthdr.pcap ieee802.11_exthdr.out -t -v + +# OpenFlow tests +of10_p3295-vv of10_p3295.pcap of10_p3295-vv.out -t -vv diff --git a/tests/of10_p3295-vv.out b/tests/of10_p3295-vv.out new file mode 100644 index 00000000..824595d1 --- /dev/null +++ b/tests/of10_p3295-vv.out @@ -0,0 +1,798 @@ +IP (tos 0x0, ttl 64, id 55495, offset 0, flags [DF], proto TCP (6), length 60) + 10.0.0.50.35256 > 10.0.0.20.6633: Flags [S], cksum 0xa230 (correct), seq 3930397949, win 5840, options [sackOK,TS val 194888762 ecr 0,mss 1460,nop,wscale 5], length 0 +IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60) + 10.0.0.20.6633 > 10.0.0.50.35256: Flags [S.], cksum 0x1474 (incorrect -> 0x4253), seq 491620419, ack 3930397950, win 14480, options [mss 1460,sackOK,TS val 220957518 ecr 194888762,nop,wscale 7], length 0 +IP (tos 0x0, ttl 64, id 55496, offset 0, flags [DF], proto TCP (6), length 52) + 10.0.0.50.35256 > 10.0.0.20.6633: Flags [.], cksum 0xa8f8 (correct), seq 1, ack 1, win 183, options [nop,nop,TS val 194888762 ecr 220957518], length 0 +IP (tos 0x0, ttl 64, id 778, offset 0, flags [DF], proto TCP (6), length 60) + 10.0.0.20.6633 > 10.0.0.50.35256: Flags [P.], cksum 0x1474 (incorrect -> 0xa818), seq 1:9, ack 1, win 114, options [nop,nop,TS val 220957530 ecr 194888762], length 8: OpenFlow + version 1.0, type HELLO, length 8, xid 0x00000001 +IP (tos 0x0, ttl 64, id 55497, offset 0, flags [DF], proto TCP (6), length 52) + 10.0.0.50.35256 > 10.0.0.20.6633: Flags [.], cksum 0xa8e1 (correct), seq 1, ack 9, win 183, options [nop,nop,TS val 194888765 ecr 220957530], length 0 +IP (tos 0x0, ttl 64, id 55498, offset 0, flags [DF], proto TCP (6), length 60) + 10.0.0.50.35256 > 10.0.0.20.6633: Flags [P.], cksum 0xa74f (correct), seq 1:9, ack 9, win 183, options [nop,nop,TS val 194888811 ecr 220957530], length 8: OpenFlow + version 1.0, type HELLO, length 8, xid 0x0000004c +IP (tos 0x0, ttl 64, id 779, offset 0, flags [DF], proto TCP (6), length 52) + 10.0.0.20.6633 > 10.0.0.50.35256: Flags [.], cksum 0x146c (incorrect -> 0xa839), seq 9, ack 9, win 114, options [nop,nop,TS val 220957713 ecr 194888811], length 0 +IP (tos 0x0, ttl 64, id 780, offset 0, flags [DF], proto TCP (6), length 60) + 10.0.0.20.6633 > 10.0.0.50.35256: Flags [P.], cksum 0x1474 (incorrect -> 0xa719), seq 9:17, ack 9, win 114, options [nop,nop,TS val 220957714 ecr 194888811], length 8: OpenFlow + version 1.0, type FEATURES_REQUEST, length 8, xid 0x00000002 +IP (tos 0x0, ttl 64, id 55499, offset 0, flags [DF], proto TCP (6), length 52) + 10.0.0.50.35256 > 10.0.0.20.6633: Flags [.], cksum 0xa7eb (correct), seq 9, ack 17, win 183, options [nop,nop,TS val 194888811 ecr 220957714], length 0 +IP (tos 0x0, ttl 64, id 55500, offset 0, flags [DF], proto TCP (6), length 2628) + 10.0.0.50.35256 > 10.0.0.20.6633: Flags [P.], cksum 0x1e7c (incorrect -> 0xae92), seq 9:2585, ack 17, win 183, options [nop,nop,TS val 194889013 ecr 220957714], length 2576: OpenFlow + version 1.0, type FEATURES_REPLY, length 2576, xid 0x00000002 + dpid 0x0000089e0162d5f4, n_buffers 256, n_tables 1 + capabilities 0x00000087 (FLOW_STATS, TABLE_STATS, PORT_STATS, ARP_MATCH_IP) + actions 0x0000003f (OUTPUT, SET_VLAN_VID, SET_VLAN_PCP, STRIP_VLAN, SET_DL_SRC, SET_DL_DST) + port_no 42, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/42' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 33, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/33' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 36, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/36' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 31, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/31' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 48, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/48' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 40, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/40' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 1, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/1' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 28, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/28' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 20, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/20' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 10, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/10' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 22, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/22' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 29, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/29' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 44, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/44' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 41, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/41' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 21, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/21' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 16, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/16' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 45, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/45' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 49, hw_addr 08:9e:01:62:d5:f4, name 'te-1/1/49' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x00000020 (1GB_FD) + supported 0x00000e60 (1GB_FD, 10GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 38, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/38' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 17, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/17' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 27, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/27' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 51, hw_addr 08:9e:01:62:d5:f4, name 'te-1/1/51' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x00000020 (1GB_FD) + supported 0x00000e60 (1GB_FD, 10GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 46, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/46' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 6, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/6' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 50, hw_addr 08:9e:01:62:d5:f4, name 'te-1/1/50' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x00000020 (1GB_FD) + supported 0x00000e60 (1GB_FD, 10GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 43, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/43' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 35, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/35' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 19, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/19' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 47, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/47' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 23, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/23' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 25, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/25' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 37, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/37' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 7, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/7' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 26, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/26' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 32, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/32' + config 0x00000020 (NO_FWD) + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 4, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/4' + config 0x00000000 + state 0x00000000 + curr 0x00000020 (1GB_FD) + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + port_no 3, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/3' + config 0x00000000 + state 0x00000000 + curr 0x00000020 (1GB_FD) + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + port_no 18, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/18' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 39, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/39' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 8, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/8' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 2, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/2' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 14, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/14' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 5, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/5' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 30, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/30' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 11, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/11' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 15, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/15' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 52, hw_addr 08:9e:01:62:d5:f4, name 'te-1/1/52' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x00000020 (1GB_FD) + supported 0x00000e60 (1GB_FD, 10GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 34, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/34' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 13, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/13' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 12, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/12' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 24, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/24' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no 9, hw_addr 08:9e:01:62:d5:f4, name 'ge-1/1/9' + config 0x00000000 + state 0x00000001 (LINK_DOWN) + curr 0x00000000 + advertised 0x0000042f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, PAUSE) + supported 0x00000e2f (10MB_HD, 10MB_FD, 100MB_HD, 100MB_FD, 1GB_FD, AUTONEG, PAUSE, PAUSE_ASYM) + peer 0x00000000 + port_no LOCAL, hw_addr 08:9e:01:62:d5:f4, name 'br0' + config 0x00000001 (PORT_DOWN) + state 0x00000001 (LINK_DOWN) + curr 0x00000082 (10MB_FD, COPPER) + advertised 0x00000000 + supported 0x00000000 + peer 0x00000000 +IP (tos 0x0, ttl 64, id 781, offset 0, flags [DF], proto TCP (6), length 52) + 10.0.0.20.6633 > 10.0.0.50.35256: Flags [.], cksum 0x146c (incorrect -> 0x9a07), seq 17, ack 2585, win 154, options [nop,nop,TS val 220958521 ecr 194889013], length 0 +IP (tos 0x0, ttl 64, id 782, offset 0, flags [DF], proto TCP (6), length 136) + 10.0.0.20.6633 > 10.0.0.50.35256: Flags [P.], cksum 0x14c0 (incorrect -> 0x96f3), seq 17:101, ack 2585, win 154, options [nop,nop,TS val 220958525 ecr 194889013], length 84: OpenFlow + version 1.0, type SET_CONFIG, length 12, xid 0x00000003 + flags FRAG_NORMAL, miss_send_len 65535 + version 1.0, type FLOW_MOD, length 72, xid 0x00000004 + cookie 0x0000000000000000, command DELETE, out_port NONE, flags 0x0000 +IP (tos 0x0, ttl 64, id 55502, offset 0, flags [DF], proto TCP (6), length 52) + 10.0.0.50.35256 > 10.0.0.20.6633: Flags [.], cksum 0x9991 (correct), seq 2585, ack 101, win 183, options [nop,nop,TS val 194889014 ecr 220958525], length 0 +IP (tos 0x0, ttl 64, id 783, offset 0, flags [DF], proto TCP (6), length 1500) + 10.0.0.20.6633 > 10.0.0.50.35256: Flags [.], cksum 0x1a14 (incorrect -> 0xcf68), seq 101:1549, ack 2585, win 154, options [nop,nop,TS val 220958532 ecr 194889014], length 1448: OpenFlow + version 1.0, type GET_CONFIG_REQUEST, length 8, xid 0x00000005 + version 1.0, type FLOW_MOD, length 80, xid 0x00000006 + match in_port 4 + cookie 0x0000000000000001, command ADD, priority 54321, buffer_id NONE, flags 0x0001 (SEND_FLOW_REM) + action type OUTPUT, len 8, port 1 + version 1.0, type FLOW_MOD, length 80, xid 0x00000007 + match in_port 4 + cookie 0x0000000000000002, command ADD, priority 54320, buffer_id NONE, flags 0x0001 (SEND_FLOW_REM) + action type OUTPUT, len 8, port LOCAL + version 1.0, type FLOW_MOD, length 80, xid 0x00000008 + match in_port 4 + cookie 0x0000000000000003, command ADD, priority 54319, buffer_id NONE, flags 0x0001 (SEND_FLOW_REM) + action type OUTPUT, len 8, port CONTROLLER, max_len 65535 + version 1.0, type FLOW_MOD, length 88, xid 0x00000009 + match in_port 4 + cookie 0x0000000000000004, command ADD, priority 54318, buffer_id NONE, flags 0x0001 (SEND_FLOW_REM) + action type SET_VLAN_VID, len 8, vlan_vid 2 + action type SET_TP_SRC, len 8, tp_port 23 + version 1.0, type FLOW_MOD, length 80, xid 0x0000000a + match in_port 4 + cookie 0x0000000000000005, command ADD, priority 54317, buffer_id NONE, flags 0x0001 (SEND_FLOW_REM) + action type SET_VLAN_PCP, len 8, vlan_pcp 5 + version 1.0, type FLOW_MOD, length 80, xid 0x0000000b + match in_port 4 + cookie 0x0000000000000006, command ADD, priority 54316, buffer_id NONE, flags 0x0001 (SEND_FLOW_REM) + action type STRIP_VLAN, len 8 + version 1.0, type FLOW_MOD, length 96, xid 0x0000000c + match in_port 4 + cookie 0x0000000000000007, command ADD, priority 54315, buffer_id NONE, flags 0x0001 (SEND_FLOW_REM) + action type SET_DL_SRC, len 16, dl_addr 11:22:33:44:55:66 + action type SET_NW_SRC, len 8, nw_addr 192.168.72.143 + version 1.0, type FLOW_MOD, length 96, xid 0x0000000d + match in_port 4 + cookie 0x0000000000000008, command ADD, priority 54314, buffer_id NONE, flags 0x0001 (SEND_FLOW_REM) + action type SET_DL_DST, len 16, dl_addr 77:88:99:aa:bb:cc + action type SET_NW_DST, len 8, nw_addr 192.168.98.55 + version 1.0, type FLOW_MOD, length 88, xid 0x0000000e + match in_port 4 + cookie 0x0000000000000009, command ADD, priority 54313, buffer_id NONE, flags 0x0001 (SEND_FLOW_REM) + action type SET_NW_TOS, len 8, nw_tos 0x2c + action type SET_TP_DST, len 8, tp_port 80 + version 1.0, type FLOW_MOD, length 88, xid 0x0000000f + match in_port 4 + cookie 0x000000000000000a, command ADD, priority 54312, buffer_id NONE, flags 0x0001 (SEND_FLOW_REM) + action type ENQUEUE, len 16, port 1, queue_id 2 + version 1.0, type FLOW_MOD, length 144, xid 0x00000010 + match in_port 4 + cookie 0x000000000000000b, command ADD, priority 54311, buffer_id NONE, flags 0x0001 (SEND_FLOW_REM) + action type VENDOR, len 72, vendor 0x00001234 + data (64 octets) + 0x0000: 4469 6420 796f 7520 6b6e 6f77 2076 656e Did.you.know.ven + 0x0010: 646f 7220 6163 7469 6f6e 2064 6174 6120 dor.action.data. + 0x0020: 6c65 6e67 7468 206d 7573 7420 6265 2061 length.must.be.a + 0x0030: 206d 756c 7469 706c 6520 6f66 2020 383f .multiple.of..8? + version 1.0, type FLOW_MOD, length 80, xid 0x00000011 + match in_port 1 + match dl_src 00:00:00:00:00:01 + cookie 0x000000000000000c, command ADD, priority 43210, buffer_id NONE, flags 0x0001 (SEND_FLOW_REM) + action type OUTPUT, len 8, port 5 + version 1.0, type FLOW_MOD, length 80, xid 0x00000012 + match dl_vlan 100 + match dl_vlan_pcp 4 + match dl_type 0x8100 + cookie 0x000000000000000d, command ADD, priority 43209, buffer_id NONE, flags 0x0001 (SEND_FLOW_REM) + action type OUTPUT, len 8, port 5 + version 1.0, type FLOW_MOD, length 80, xid 0x00000013 + match dl_type 0x0800 + match nw_src 10.11.12.0/24 + match nw_dst 10.13.14.0/24 + cookie 0x000000000000000e, command ADD, priority 43208, buffer_id NONE, flags 0x0001 (SEND_FLOW_REM) + action type OUTPUT, len 8, port 5 + version 1.0, type FLOW_MOD, length 80, xid 0x00000014 + match dl_type 0x0800 + match nw_proto 17 + match tp_src 68 + match tp_dst 67 + cookie 0x000000000000000f, command ADD, priority 43207, buffer_id NONE, flags 0x0001 (SEND_FLOW_REM) + action type OUTPUT, len 8, port 5 + version 1.0, type FLOW_MOD, length 80, xid 0x00000015 + match dl_type 0x0800 + match nw_proto 1 + match icmp_type 8 + cookie 0x0000000000000010, command ADD, priority 43206, buffer_id NONE, flags 0x0001 (SEND_FLOW_REM) + action type OUTPUT, len 8, port 5 + version 1.0, type FLOW_MOD, length 80, xid 0x00000016 + match dl_type 0x0800 + match nw_proto 1 [|openflow] +IP (tos 0x0, ttl 64, id 784, offset 0, flags [DF], proto TCP (6), length 740) + 10.0.0.20.6633 > 10.0.0.50.35256: Flags [P.], cksum 0x171c (incorrect -> 0xdfee), seq 1549:2237, ack 2585, win 154, options [nop,nop,TS val 220958532 ecr 194889014], length 688: OpenFlow + version unknown (0x00), type 0x00, length 0, xid 0x0003000d (corrupt) +IP (tos 0x0, ttl 64, id 55503, offset 0, flags [DF], proto TCP (6), length 52) + 10.0.0.50.35256 > 10.0.0.20.6633: Flags [.], cksum 0x9386 (correct), seq 2585, ack 1549, win 273, options [nop,nop,TS val 194889016 ecr 220958532], length 0 +IP (tos 0x0, ttl 64, id 55504, offset 0, flags [DF], proto TCP (6), length 52) + 10.0.0.50.35256 > 10.0.0.20.6633: Flags [.], cksum 0x907b (correct), seq 2585, ack 2237, win 364, options [nop,nop,TS val 194889016 ecr 220958532], length 0 +IP (tos 0x0, ttl 64, id 55505, offset 0, flags [DF], proto TCP (6), length 140) + 10.0.0.50.35256 > 10.0.0.20.6633: Flags [P.], cksum 0xba5c (correct), seq 2585:2673, ack 2237, win 364, options [nop,nop,TS val 194889060 ecr 220958532], length 88: OpenFlow + version 1.0, type FLOW_REMOVED, length 88, xid 0x00000000 + match dl_type 0x0800 + match nw_proto 17 + match tp_src 68 + match tp_dst 67 + cookie 0x000000000000000f, priority 43207, reason DELETE, duration_sec 122, duration_nsec 0, packet_count 0, byte_count 0 +IP (tos 0x0, ttl 64, id 55506, offset 0, flags [DF], proto TCP (6), length 140) + 10.0.0.50.35256 > 10.0.0.20.6633: Flags [P.], cksum 0x3c6a (correct), seq 2673:2761, ack 2237, win 364, options [nop,nop,TS val 194889060 ecr 220958532], length 88: OpenFlow + version 1.0, type FLOW_REMOVED, length 88, xid 0x00000000 + match dl_vlan 100 + match dl_vlan_pcp 4 + match dl_type 0x8100 + cookie 0x000000000000000d, priority 43209, reason DELETE, duration_sec 122, duration_nsec 0, packet_count 0, byte_count 0 +IP (tos 0x0, ttl 64, id 785, offset 0, flags [DF], proto TCP (6), length 52) + 10.0.0.20.6633 > 10.0.0.50.35256: Flags [.], cksum 0x146c (incorrect -> 0x8fbf), seq 2237, ack 2761, win 154, options [nop,nop,TS val 220958710 ecr 194889060], length 0 +IP (tos 0x0, ttl 64, id 55507, offset 0, flags [DF], proto TCP (6), length 140) + 10.0.0.50.35256 > 10.0.0.20.6633: Flags [P.], cksum 0xc154 (correct), seq 2761:2849, ack 2237, win 364, options [nop,nop,TS val 194889060 ecr 220958532], length 88: OpenFlow + version 1.0, type FLOW_REMOVED, length 88, xid 0x00000000 + cookie 0x0000000000000014, priority 43202, reason DELETE, duration_sec 122, duration_nsec 0, packet_count 0, byte_count 0 +IP (tos 0x0, ttl 64, id 55508, offset 0, flags [DF], proto TCP (6), length 140) + 10.0.0.50.35256 > 10.0.0.20.6633: Flags [P.], cksum 0xc04a (correct), seq 2849:2937, ack 2237, win 364, options [nop,nop,TS val 194889060 ecr 220958710], length 88: OpenFlow + version 1.0, type FLOW_REMOVED, length 88, xid 0x00000000 + cookie 0x0000000000000015, priority 43201, reason DELETE, duration_sec 122, duration_nsec 0, packet_count 0, byte_count 0 +IP (tos 0x0, ttl 64, id 55509, offset 0, flags [DF], proto TCP (6), length 140) + 10.0.0.50.35256 > 10.0.0.20.6633: Flags [P.], cksum 0xa1f0 (correct), seq 2937:3025, ack 2237, win 364, options [nop,nop,TS val 194889060 ecr 220958710], length 88: OpenFlow + version 1.0, type FLOW_REMOVED, length 88, xid 0x00000000 + match dl_type 0x0800 + match nw_src 10.11.12.0/24 + match nw_dst 10.13.14.0/24 + cookie 0x000000000000000e, priority 43208, reason DELETE, duration_sec 122, duration_nsec 0, packet_count 0, byte_count 0 +IP (tos 0x0, ttl 64, id 786, offset 0, flags [DF], proto TCP (6), length 52) + 10.0.0.20.6633 > 10.0.0.50.35256: Flags [.], cksum 0x146c (incorrect -> 0x8eb7), seq 2237, ack 3025, win 154, options [nop,nop,TS val 220958710 ecr 194889060], length 0 +IP (tos 0x0, ttl 64, id 55510, offset 0, flags [DF], proto TCP (6), length 140) + 10.0.0.50.35256 > 10.0.0.20.6633: Flags [P.], cksum 0xbf9d (correct), seq 3025:3113, ack 2237, win 364, options [nop,nop,TS val 194889060 ecr 220958710], length 88: OpenFlow + version 1.0, type FLOW_REMOVED, length 88, xid 0x00000000 + match in_port 1 + match dl_src 00:00:00:00:00:01 + cookie 0x000000000000000c, priority 43210, reason DELETE, duration_sec 122, duration_nsec 0, packet_count 0, byte_count 0 +IP (tos 0x0, ttl 64, id 55511, offset 0, flags [DF], proto TCP (6), length 140) + 10.0.0.50.35256 > 10.0.0.20.6633: Flags [P.], cksum 0x54e2 (correct), seq 3113:3201, ack 2237, win 364, options [nop,nop,TS val 194889060 ecr 220958710], length 88: OpenFlow + version 1.0, type FLOW_REMOVED, length 88, xid 0x00000000 + match dl_src aa:00:00:00:00:11 + match dl_dst bb:00:00:00:00:22 + cookie 0x0000000000000013, priority 43203, reason DELETE, duration_sec 122, duration_nsec 0, packet_count 13, byte_count 1323 +IP (tos 0x0, ttl 64, id 55512, offset 0, flags [DF], proto TCP (6), length 140) + 10.0.0.50.35256 > 10.0.0.20.6633: Flags [P.], cksum 0x6bfc (correct), seq 3201:3289, ack 2237, win 364, options [nop,nop,TS val 194889060 ecr 220958710], length 88: OpenFlow + version 1.0, type FLOW_REMOVED, length 88, xid 0x00000000 + match in_port 4 + cookie 0x0000000000000001, priority 54321, reason DELETE, duration_sec 122, duration_nsec 0, packet_count 100, byte_count 10027 +IP (tos 0x0, ttl 64, id 787, offset 0, flags [DF], proto TCP (6), length 52) + 10.0.0.20.6633 > 10.0.0.50.35256: Flags [.], cksum 0x146c (incorrect -> 0x8dae), seq 2237, ack 3289, win 154, options [nop,nop,TS val 220958711 ecr 194889060], length 0 +IP (tos 0x0, ttl 64, id 55513, offset 0, flags [DF], proto TCP (6), length 140) + 10.0.0.50.35256 > 10.0.0.20.6633: Flags [P.], cksum 0x9333 (correct), seq 3289:3377, ack 2237, win 364, options [nop,nop,TS val 194889060 ecr 220958710], length 88: OpenFlow + version 1.0, type FLOW_REMOVED, length 88, xid 0x00000000 + match in_port 4 + cookie 0x0000000000000002, priority 54320, reason DELETE, duration_sec 122, duration_nsec 0, packet_count 0, byte_count 0 +IP (tos 0x0, ttl 64, id 55514, offset 0, flags [DF], proto TCP (6), length 140) + 10.0.0.50.35256 > 10.0.0.20.6633: Flags [P.], cksum 0x92da (correct), seq 3377:3465, ack 2237, win 364, options [nop,nop,TS val 194889060 ecr 220958711], length 88: OpenFlow + version 1.0, type FLOW_REMOVED, length 88, xid 0x00000000 + match in_port 4 + cookie 0x0000000000000003, priority 54319, reason DELETE, duration_sec 122, duration_nsec 0, packet_count 0, byte_count 0 +IP (tos 0x0, ttl 64, id 55515, offset 0, flags [DF], proto TCP (6), length 140) + 10.0.0.50.35256 > 10.0.0.20.6633: Flags [P.], cksum 0x9282 (correct), seq 3465:3553, ack 2237, win 364, options [nop,nop,TS val 194889060 ecr 220958711], length 88: OpenFlow + version 1.0, type FLOW_REMOVED, length 88, xid 0x00000000 + match in_port 4 + cookie 0x0000000000000004, priority 54318, reason DELETE, duration_sec 122, duration_nsec 0, packet_count 0, byte_count 0 +IP (tos 0x0, ttl 64, id 788, offset 0, flags [DF], proto TCP (6), length 52) + 10.0.0.20.6633 > 10.0.0.50.35256: Flags [.], cksum 0x146c (incorrect -> 0x8ca5), seq 2237, ack 3553, win 154, options [nop,nop,TS val 220958712 ecr 194889060], length 0 +IP (tos 0x0, ttl 64, id 55516, offset 0, flags [DF], proto TCP (6), length 140) + 10.0.0.50.35256 > 10.0.0.20.6633: Flags [P.], cksum 0x922a (correct), seq 3553:3641, ack 2237, win 364, options [nop,nop,TS val 194889060 ecr 220958711], length 88: OpenFlow + version 1.0, type FLOW_REMOVED, length 88, xid 0x00000000 + match in_port 4 + cookie 0x0000000000000005, priority 54317, reason DELETE, duration_sec 122, duration_nsec 0, packet_count 0, byte_count 0 +IP (tos 0x0, ttl 64, id 55517, offset 0, flags [DF], proto TCP (6), length 140) + 10.0.0.50.35256 > 10.0.0.20.6633: Flags [P.], cksum 0x91d1 (correct), seq 3641:3729, ack 2237, win 364, options [nop,nop,TS val 194889060 ecr 220958712], length 88: OpenFlow + version 1.0, type FLOW_REMOVED, length 88, xid 0x00000000 + match in_port 4 + cookie 0x0000000000000006, priority 54316, reason DELETE, duration_sec 122, duration_nsec 0, packet_count 0, byte_count 0 +IP (tos 0x0, ttl 64, id 789, offset 0, flags [DF], proto TCP (6), length 52) + 10.0.0.20.6633 > 10.0.0.50.35256: Flags [.], cksum 0x146c (incorrect -> 0x8bf5), seq 2237, ack 3729, win 154, options [nop,nop,TS val 220958712 ecr 194889060], length 0 +IP (tos 0x0, ttl 64, id 55518, offset 0, flags [DF], proto TCP (6), length 140) + 10.0.0.50.35256 > 10.0.0.20.6633: Flags [P.], cksum 0x9179 (correct), seq 3729:3817, ack 2237, win 364, options [nop,nop,TS val 194889060 ecr 220958712], length 88: OpenFlow + version 1.0, type FLOW_REMOVED, length 88, xid 0x00000000 + match in_port 4 + cookie 0x0000000000000007, priority 54315, reason DELETE, duration_sec 122, duration_nsec 0, packet_count 0, byte_count 0 +IP (tos 0x0, ttl 64, id 55519, offset 0, flags [DF], proto TCP (6), length 140) + 10.0.0.50.35256 > 10.0.0.20.6633: Flags [P.], cksum 0x9120 (correct), seq 3817:3905, ack 2237, win 364, options [nop,nop,TS val 194889061 ecr 220958712], length 88: OpenFlow + version 1.0, type FLOW_REMOVED, length 88, xid 0x00000000 + match in_port 4 + cookie 0x0000000000000008, priority 54314, reason DELETE, duration_sec 122, duration_nsec 0, packet_count 0, byte_count 0 +IP (tos 0x0, ttl 64, id 55520, offset 0, flags [DF], proto TCP (6), length 140) + 10.0.0.50.35256 > 10.0.0.20.6633: Flags [P.], cksum 0x90c8 (correct), seq 3905:3993, ack 2237, win 364, options [nop,nop,TS val 194889061 ecr 220958712], length 88: OpenFlow + version 1.0, type FLOW_REMOVED, length 88, xid 0x00000000 + match in_port 4 + cookie 0x0000000000000009, priority 54313, reason DELETE, duration_sec 122, duration_nsec 0, packet_count 0, byte_count 0 +IP (tos 0x0, ttl 64, id 790, offset 0, flags [DF], proto TCP (6), length 52) + 10.0.0.20.6633 > 10.0.0.50.35256: Flags [.], cksum 0x146c (incorrect -> 0x8aec), seq 2237, ack 3993, win 154, options [nop,nop,TS val 220958713 ecr 194889060], length 0 +IP (tos 0x0, ttl 64, id 55521, offset 0, flags [DF], proto TCP (6), length 140) + 10.0.0.50.35256 > 10.0.0.20.6633: Flags [P.], cksum 0x9070 (correct), seq 3993:4081, ack 2237, win 364, options [nop,nop,TS val 194889061 ecr 220958712], length 88: OpenFlow + version 1.0, type FLOW_REMOVED, length 88, xid 0x00000000 + match in_port 4 + cookie 0x000000000000000a, priority 54312, reason DELETE, duration_sec 122, duration_nsec 0, packet_count 0, byte_count 0 +IP (tos 0x0, ttl 64, id 55522, offset 0, flags [DF], proto TCP (6), length 64) + 10.0.0.50.35256 > 10.0.0.20.6633: Flags [P.], cksum 0x8894 (correct), seq 4081:4093, ack 2237, win 364, options [nop,nop,TS val 194889061 ecr 220958713], length 12: OpenFlow + version 1.0, type GET_CONFIG_REPLY, length 12, xid 0x00000005 + flags FRAG_NORMAL, miss_send_len 65535 +IP (tos 0x0, ttl 64, id 791, offset 0, flags [DF], proto TCP (6), length 52) + 10.0.0.20.6633 > 10.0.0.50.35256: Flags [.], cksum 0x146c (incorrect -> 0x8a87), seq 2237, ack 4093, win 154, options [nop,nop,TS val 220958713 ecr 194889061], length 0 +IP (tos 0x0, ttl 64, id 55523, offset 0, flags [DF], proto TCP (6), length 128) + 10.0.0.50.35256 > 10.0.0.20.6633: Flags [P.], cksum 0x90e5 (correct), seq 4093:4169, ack 2237, win 364, options [nop,nop,TS val 194889061 ecr 220958713], length 76: OpenFlow + version 1.0, type ERROR, length 76, xid 0x00000010 + type BAD_ACTION, code BAD_VENDOR + data (64 octets) + 0x0000: 010e 0090 0000 0010 0038 20fe 0004 0000 .........8...... + 0x0010: 0000 0000 0000 0000 0000 0000 0000 0000 ................ + 0x0020: 0000 0000 0000 0000 0000 0000 0000 0000 ................ + 0x0030: 0000 0000 0000 000b 0000 0000 0000 d427 ...............' +IP (tos 0x0, ttl 64, id 55524, offset 0, flags [DF], proto TCP (6), length 60) + 10.0.0.50.35256 > 10.0.0.20.6633: Flags [P.], cksum 0x8821 (correct), seq 4169:4177, ack 2237, win 364, options [nop,nop,TS val 194889063 ecr 220958713], length 8: OpenFlow + version 1.0, type BARRIER_REPLY, length 8, xid 0x0000001b +IP (tos 0x0, ttl 64, id 55525, offset 0, flags [DF], proto TCP (6), length 1120) + 10.0.0.50.35256 > 10.0.0.20.6633: Flags [P.], cksum 0xb778 (correct), seq 4177:5245, ack 2237, win 364, options [nop,nop,TS val 194889063 ecr 220958713], length 1068: OpenFlow + version 1.0, type STATS_REPLY, length 1068, xid 0x0000001c + type DESC, flags 0x0000 + mfr_desc 'Nicira Networks, Inc.' + hw_desc 'Open vSwitch' + sw_desc '1.2.2' + serial_num 'None' + dp_desc 'None' +IP (tos 0x0, ttl 64, id 792, offset 0, flags [DF], proto TCP (6), length 52) + 10.0.0.20.6633 > 10.0.0.50.35256: Flags [.], cksum 0x146c (incorrect -> 0x85e9), seq 2237, ack 5245, win 176, options [nop,nop,TS val 220958721 ecr 194889061], length 0 +IP (tos 0x0, ttl 64, id 55526, offset 0, flags [DF], proto TCP (6), length 1752) + 10.0.0.50.35256 > 10.0.0.20.6633: Flags [P.], cksum 0x1b10 (incorrect -> 0x7df4), seq 5245:6945, ack 2237, win 364, options [nop,nop,TS val 194889063 ecr 220958713], length 1700: OpenFlow + version 1.0, type STATS_REPLY, length 1700, xid 0x0000001d + type FLOW, flags 0x0000 + length 96, table_id 0 + match dl_type 0x0800 + match nw_proto 17 + match tp_src 68 + match tp_dst 67 + duration_sec 0, duration_nsec 0, priority 43207, idle_timeout 0, hard_timeout 0, cookie 0x000000000000000f, packet_count 0, byte_count 0 + action type OUTPUT, len 8, port 5 + length 96, table_id 0 + match dl_vlan 100 + match dl_vlan_pcp 4 + match dl_type 0x8100 + duration_sec 0, duration_nsec 0, priority 43209, idle_timeout 0, hard_timeout 0, cookie 0x000000000000000d, packet_count 0, byte_count 0 + action type OUTPUT, len 8, port 5 + length 96, table_id 0 + duration_sec 0, duration_nsec 0, priority 43202, idle_timeout 0, hard_timeout 0, cookie 0x0000000000000014, packet_count 0, byte_count 0 + action type OUTPUT, len 8, port 5 + length 96, table_id 0 + duration_sec 0, duration_nsec 0, priority 43201, idle_timeout 0, hard_timeout 0, cookie 0x0000000000000015, packet_count 0, byte_count 0 + action type OUTPUT, len 8, port 5 + length 96, table_id 0 + match dl_type 0x0800 + match nw_src 10.11.12.0/24 + match nw_dst 10.13.14.0/24 + duration_sec 0, duration_nsec 0, priority 43208, idle_timeout 0, hard_timeout 0, cookie 0x000000000000000e, packet_count 0, byte_count 0 + action type OUTPUT, len 8, port 5 + length 96, table_id 0 + match in_port 1 + match dl_src 00:00:00:00:00:01 + duration_sec 0, duration_nsec 0, priority 43210, idle_timeout 0, hard_timeout 0, cookie 0x000000000000000c, packet_count 0, byte_count 0 + action type OUTPUT, len 8, port 5 + length 96, table_id 0 + match dl_src aa:00:00:00:00:11 + match dl_dst bb:00:00:00:00:22 + duration_sec 0, duration_nsec 0, priority 43203, idle_timeout 0, hard_timeout 0, cookie 0x0000000000000013, packet_count 0, byte_count 0 + action type OUTPUT, len 8, port 5 + length 96, table_id 0 + match in_port 4 + duration_sec 0, duration_nsec 0, priority 54321, idle_timeout 0, hard_timeout 0, cookie 0x0000000000000001, packet_count 0, byte_count 0 + action type OUTPUT, len 8, port 1 + length 96, table_id 0 + match in_port 4 + duration_sec 0, duration_nsec 0, priority 54320, idle_timeout 0, hard_timeout 0, cookie 0x0000000000000002, packet_count 0, byte_count 0 + action type OUTPUT, len 8, port LOCAL + length 96, table_id 0 + match in_port 4 + duration_sec 0, duration_nsec 0, priority 54319, idle_timeout 0, hard_timeout 0, cookie 0x0000000000000003, packet_count 0, byte_count 0 + action type OUTPUT, len 8, port CONTROLLER, max_len 65535 + length 104, table_id 0 + match in_port 4 + duration_sec 0, duration_nsec 0, priority 54318, idle_timeout 0, hard_timeout 0, cookie 0x0000000000000004, packet_count 0, byte_count 0 + action type SET_VLAN_VID, len 8, vlan_vid 2 + action type SET_TP_SRC, len 8, tp_port 23 + length 96, table_id 0 + match in_port 4 + duration_sec 0, duration_nsec 0, priority 54317, idle_timeout 0, hard_timeout 0, cookie 0x0000000000000005, packet_count 0, byte_count 0 + action type SET_VLAN_PCP, len 8, vlan_pcp 5 + length 96, table_id 0 + match in_port 4 + duration_sec 0, duration_nsec 0, priority 54316, idle_timeout 0, hard_timeout 0, cookie 0x0000000000000006, packet_count 0, byte_count 0 + action type STRIP_VLAN, len 8 + length 112, table_id 0 + match in_port 4 + duration_sec 0, duration_nsec 0, priority 54315, idle_timeout 0, hard_timeout 0, cookie 0x0000000000000007, packet_count 0, byte_count 0 + action type SET_DL_SRC, len 16, dl_addr 11:22:33:44:55:66 + action type SET_NW_SRC, len 8, nw_addr 192.168.72.143 + length 112, table_id 0 + match in_port 4 + duration_sec 0, duration_nsec 0, priority 54314, idle_timeout 0, hard_timeout 0, cookie 0x0000000000000008, packet_count 0, byte_count 0 + action type SET_DL_DST, len 16, dl_addr 77:88:99:aa:bb:cc + action type SET_NW_DST, len 8, nw_addr 192.168.98.55 + length 104, table_id 0 + match in_port 4 + duration_sec 0, duration_nsec 0, priority 54313, idle_timeout 0, hard_timeout 0, cookie 0x0000000000000009, packet_count 0, byte_count 0 + action type SET_NW_TOS, len 8, nw_tos 0x2c + action type SET_TP_DST, len 8, tp_port 80 + length 104, table_id 0 + match in_port 4 + duration_sec 0, duration_nsec 0, priority 54312, idle_timeout 0, hard_timeout 0, cookie 0x000000000000000a, packet_count 0, byte_count 0 + action type ENQUEUE, len 16, port 1, queue_id 2 +IP (tos 0x0, ttl 64, id 793, offset 0, flags [DF], proto TCP (6), length 52) + 10.0.0.20.6633 > 10.0.0.50.35256: Flags [.], cksum 0x146c (incorrect -> 0x7f28), seq 2237, ack 6945, win 203, options [nop,nop,TS val 220958721 ecr 194889063], length 0 +IP (tos 0x0, ttl 64, id 55528, offset 0, flags [DF], proto TCP (6), length 88) + 10.0.0.50.35256 > 10.0.0.20.6633: Flags [P.], cksum 0x7cfd (correct), seq 6945:6981, ack 2237, win 364, options [nop,nop,TS val 194889063 ecr 220958713], length 36: OpenFlow + version 1.0, type STATS_REPLY, length 36, xid 0x0000001e + type AGGREGATE, flags 0x0000 + packet_count 0, byte_count 0, flow_count 17 +IP (tos 0x0, ttl 64, id 55529, offset 0, flags [DF], proto TCP (6), length 128) + 10.0.0.50.35256 > 10.0.0.20.6633: Flags [P.], cksum 0xeac4 (correct), seq 6981:7057, ack 2237, win 364, options [nop,nop,TS val 194889063 ecr 220958713], length 76: OpenFlow + version 1.0, type STATS_REPLY, length 76, xid 0x0000001f + type TABLE, flags 0x0000 + table_id 0, name 'classifier' + wildcards 0x003fffff (IN_PORT, DL_VLAN, DL_SRC, DL_DST, DL_TYPE, NW_PROTO, TP_SRC, TP_DST, DL_VLAN_PCP, NW_TOS) + max_entries 1000000, active_count 26, lookup_count 1158498983736653433, matched_count 1158498983736653433 +IP (tos 0x0, ttl 64, id 794, offset 0, flags [DF], proto TCP (6), length 52) + 10.0.0.20.6633 > 10.0.0.50.35256: Flags [.], cksum 0x146c (incorrect -> 0x7eb8), seq 2237, ack 7057, win 203, options [nop,nop,TS val 220958721 ecr 194889063], length 0 +IP (tos 0x0, ttl 64, id 55530, offset 0, flags [DF], proto TCP (6), length 2948) + 10.0.0.50.35256 > 10.0.0.20.6633: Flags [.], cksum 0x1fbc (incorrect -> 0x5886), seq 7057:9953, ack 2237, win 364, options [nop,nop,TS val 194889063 ecr 220958721], length 2896: OpenFlow + version 1.0, type STATS_REPLY, length 5524, xid 0x00000020 + type PORT, flags 0x0000 + port_no 42, rx_packets 0, tx_packets 0, rx_bytes 0, tx_bytes 0, rx_dropped 0, tx_dropped 0, rx_errors 0, tx_errors 0, rx_frame_err 0, rx_over_err 0, rx_crc_err 0, collisions 0 + port_no 33, rx_packets 0, tx_packets 0, rx_bytes 0, tx_bytes 0, rx_dropped 0, tx_dropped 0, rx_errors 0, tx_errors 0, rx_frame_err 0, rx_over_err 0, rx_crc_err 0, collisions 0 + port_no 36, rx_packets 0, tx_packets 0, rx_bytes 0, tx_bytes 0, rx_dropped 0, tx_dropped 0, rx_errors 0, tx_errors 0, rx_frame_err 0, rx_over_err 0, rx_crc_err 0, collisions 0 + port_no 31, rx_packets 0, tx_packets 0, rx_bytes 0, tx_bytes 0, rx_dropped 0, tx_dropped 0, rx_errors 0, tx_errors 0, rx_frame_err 0, rx_over_err 0, rx_crc_err 0, collisions 0 + port_no 48, rx_packets 0, tx_packets 0, rx_bytes 0, tx_bytes 0, rx_dropped 0, tx_dropped 0, rx_errors 0, tx_errors 0, rx_frame_err 0, rx_over_err 0, rx_crc_err 0, collisions 0 + port_no 40, rx_packets 0, tx_packets 0, rx_bytes 0, tx_bytes 0, rx_dropped 0, tx_dropped 0, rx_errors 0, tx_errors 0, rx_frame_err 0, rx_over_err 0, rx_crc_err 0, collisions 0 + port_no 1, rx_packets 0, tx_packets 0, rx_bytes 0, tx_bytes 0, rx_dropped 0, tx_dropped 0, rx_errors 0, tx_errors 0, rx_frame_err 0, rx_over_err 0, rx_crc_err 0, collisions 0 + port_no 28, rx_packets 0, tx_packets 0, rx_bytes 0, tx_bytes 0, rx_dropped 0, tx_dropped 0, rx_errors 0, tx_errors 0, rx_frame_err 0, rx_over_err 0, rx_crc_err 0, collisions 0 + port_no 20, rx_packets 0, tx_packets 0, rx_bytes 0, tx_bytes 0, rx_dropped 0, tx_dropped 0, rx_errors 0, tx_errors 0, rx_frame_err 0, rx_over_err 0, rx_crc_err 0, collisions 0 + port_no 10, rx_packets 0, tx_packets 0, rx_bytes 0, tx_bytes 0, rx_dropped 0, tx_dropped 0, rx_errors 0, tx_errors 0, rx_frame_err 0, rx_over_err 0, rx_crc_err 0, collisions 0 + port_no 22, rx_packets 0, tx_packets 0, rx_bytes 0, tx_bytes 0, rx_dropped 0, tx_dropped 0, rx_errors 0, tx_errors 0, rx_frame_err 0, rx_over_err 0, rx_crc_err 0, collisions 0 + port_no 29, rx_packets 0, tx_packets 0, rx_bytes 0, tx_bytes 0, rx_dropped 0, tx_dropped 0, rx_errors 0, tx_errors 0, rx_frame_err 0, rx_over_err 0, rx_crc_err 0, collisions 0 + port_no 44, rx_packets 0, tx_packets 0, rx_bytes 0, tx_bytes 0, rx_dropped 0, tx_dropped 0, rx_errors 0, tx_errors 0, rx_frame_err 0, rx_over_err 0, rx_crc_err 0, collisions 0 + port_no 41, rx_packets 0, tx_packets 0, rx_bytes 0, tx_bytes 0, rx_dropped 0, tx_dropped 0, rx_errors 0, tx_errors 0, rx_frame_err 0, rx_over_err 0, rx_crc_err 0, collisions 0 + port_no 21, rx_packets 0, tx_packets 0, rx_bytes 0, tx_bytes 0, rx_dropped 0, tx_dropped 0, rx_errors 0, tx_errors 0, rx_frame_err 0, rx_over_err 0, rx_crc_err 0, collisions 0 + port_no 16, rx_packets 0, tx_packets 0, rx_bytes 0, tx_bytes 0, rx_dropped 0, tx_dropped 0, rx_errors 0, tx_errors 0, rx_frame_err 0, rx_over_err 0, rx_crc_err 0, collisions 0 + port_no 45, rx_packets 0, tx_packets 0, rx_bytes 0, tx_bytes 0, rx_dropped 0, tx_dropped 0, rx_errors 0, tx_errors 0, rx_frame_err 0, rx_over_err 0, rx_crc_err 0, collisions 0 + port_no 49, rx_packets 0, tx_packets 0, rx_bytes 0, tx_bytes 0, rx_dropped 0, tx_dropped 0, rx_errors 0, tx_errors 0, rx_frame_err 0, rx_over_err 0, rx_crc_err 0, collisions 0 + port_no 38, rx_packets 0, tx_packets 0, rx_bytes 0, tx_bytes 0, rx_dropped 0, tx_dropped 0, rx_errors 0, tx_errors 0, rx_frame_err 0, rx_over_err 0, rx_crc_err 0, collisions 0 + port_no 17, rx_packets 0, tx_packets 0, rx_bytes 0, tx_bytes 0, rx_dropped 0, tx_dropped 0, rx_errors 0, tx_errors 0, rx_frame_err 0, rx_over_err 0, rx_crc_err 0, collisions 0 + port_no 27, rx_packets 0, tx_packets 0, rx_bytes 0, tx_bytes 0, rx_dropped 0, tx_dropped 0, rx_errors 0, tx_errors 0, rx_frame_err 0, rx_over_err 0, rx_crc_err 0, collisions 0 + port_no 51, rx_packets 0, tx_packets 0, rx_bytes 0, tx_bytes 0, rx_dropped 0, tx_dropped 0, rx_errors 0, tx_errors 0, rx_frame_err 0, rx_over_err 0, rx_crc_err 0, collisions 0 + port_no 46, rx_packets 0, tx_packets 0, rx_bytes 0, tx_bytes 0, rx_dropped 0, tx_dropped 0, rx_errors 0, tx_errors 0, rx_frame_err 0, rx_over_err 0, rx_crc_err 0, collisions 0 + port_no 6, rx_packets 0, tx_packets 0, rx_bytes 0, tx_bytes 0, rx_dropped 0, tx_dropped 0, rx_errors 0, tx_errors 0, rx_frame_err 0, rx_over_err 0, rx_crc_err 0, collisions 0 + port_no 50, rx_packets 0, tx_packets 0, rx_bytes 0, tx_bytes 0, rx_dropped 0, tx_dropped 0, rx_errors 0, tx_errors 0, rx_frame_err 0, rx_over_err 0, rx_crc_err 0, collisions 0 + port_no 43, rx_packets 0, tx_packets 0, rx_bytes 0, tx_bytes 0, rx_dropped 0, tx_dropped 0, rx_errors 0, tx_errors 0, rx_frame_err 0, rx_over_err 0, rx_crc_err 0, collisions 0 + port_no 35, rx_packets 0, tx_packets 0, rx_bytes 0, tx_bytes 0, rx_dropped 0, tx_dropped 0, rx_errors 0, tx_errors 0, rx_frame_err 0, rx_over_err 0, rx_crc_err 0, collisions 0 + port_no 19, rx_packets 0, tx_packets 0, rx_bytes 0, tx_bytes 0, rx_dropped 0, tx_dropped 0, rx_errors 0, tx_errors 0 [|openflow] +IP (tos 0x0, ttl 64, id 795, offset 0, flags [DF], proto TCP (6), length 52) + 10.0.0.20.6633 > 10.0.0.50.35256: Flags [.], cksum 0x146c (incorrect -> 0x733a), seq 2237, ack 9953, win 248, options [nop,nop,TS val 220958722 ecr 194889063], length 0 +IP (tos 0x0, ttl 64, id 55532, offset 0, flags [DF], proto TCP (6), length 2680) + 10.0.0.50.35256 > 10.0.0.20.6633: Flags [P.], cksum 0x1eb0 (incorrect -> 0x561b), seq 9953:12581, ack 2237, win 364, options [nop,nop,TS val 194889063 ecr 220958721], length 2628: OpenFlow + version unknown (0x00), type 0x00, length 0, xid 0x00000000 (corrupt) +IP (tos 0x0, ttl 64, id 796, offset 0, flags [DF], proto TCP (6), length 52) + 10.0.0.20.6633 > 10.0.0.50.35256: Flags [.], cksum 0x146c (incorrect -> 0x68cd), seq 2237, ack 12581, win 289, options [nop,nop,TS val 220958722 ecr 194889063], length 0 +IP (tos 0x0, ttl 64, id 55534, offset 0, flags [DF], proto TCP (6), length 64) + 10.0.0.50.35256 > 10.0.0.20.6633: Flags [P.], cksum 0x672c (correct), seq 12581:12593, ack 2237, win 364, options [nop,nop,TS val 194889063 ecr 220958721], length 12: OpenFlow + version 1.0, type STATS_REPLY, length 12, xid 0x00000021 + type QUEUE, flags 0x0000 +IP (tos 0x0, ttl 64, id 55535, offset 0, flags [DF], proto TCP (6), length 128) + 10.0.0.50.35256 > 10.0.0.20.6633: Flags [P.], cksum 0xda41 (correct), seq 12593:12669, ack 2237, win 364, options [nop,nop,TS val 194889063 ecr 220958721], length 76: OpenFlow + version 1.0, type ERROR, length 76, xid 0x00000022 + type BAD_REQUEST, code BAD_VENDOR + data (64 octets) + 0x0000: 0110 0090 0000 0022 ffff 0000 0000 1234 .......".......4 + 0x0010: afaf afaf afaf afaf afaf afaf afaf afaf ................ + 0x0020: afaf afaf afaf afaf afaf afaf afaf afaf ................ + 0x0030: afaf afaf afaf afaf afaf afaf afaf afaf ................ +IP (tos 0x0, ttl 64, id 797, offset 0, flags [DF], proto TCP (6), length 52) + 10.0.0.20.6633 > 10.0.0.50.35256: Flags [.], cksum 0x146c (incorrect -> 0x6875), seq 2237, ack 12669, win 289, options [nop,nop,TS val 220958722 ecr 194889063], length 0 +IP (tos 0x0, ttl 64, id 798, offset 0, flags [DF], proto TCP (6), length 52) + 10.0.0.20.6633 > 10.0.0.50.35256: Flags [F.], cksum 0x146c (incorrect -> 0x5a63), seq 2237, ack 12669, win 289, options [nop,nop,TS val 220962323 ecr 194889063], length 0 +IP (tos 0x0, ttl 64, id 55536, offset 0, flags [DF], proto TCP (6), length 52) + 10.0.0.50.35256 > 10.0.0.20.6633: Flags [.], cksum 0x568a (correct), seq 12669, ack 2238, win 364, options [nop,nop,TS val 194889973 ecr 220962323], length 0 +IP (tos 0x0, ttl 64, id 55537, offset 0, flags [DF], proto TCP (6), length 52) + 10.0.0.50.35256 > 10.0.0.20.6633: Flags [F.], cksum 0x5664 (correct), seq 12669, ack 2238, win 364, options [nop,nop,TS val 194890010 ecr 220962323], length 0 +IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 52) + 10.0.0.20.6633 > 10.0.0.50.35256: Flags [.], cksum 0x55f5 (correct), seq 2238, ack 12670, win 289, options [nop,nop,TS val 220962509 ecr 194890010], length 0 diff --git a/tests/of10_p3295.pcap b/tests/of10_p3295.pcap new file mode 100644 index 00000000..85f1b27e Binary files /dev/null and b/tests/of10_p3295.pcap differ