"1.0-1.1": (OFP10_VERSION, OFP11_VERSION),
"1.0-1.2": (OFP10_VERSION, OFP12_VERSION),
"1.1-1.2": (OFP11_VERSION, OFP12_VERSION),
+ "1.1-1.3": (OFP11_VERSION, OFP13_VERSION),
"<all>": (0x01, 0xff)}
def get_line():
-/* Copyright (c) 2008 The Board of Trustees of The Leland Stanford
+/* Copyright (c) 2008, 2014 The Board of Trustees of The Leland Stanford
* Junior University
* Copyright (c) 2011, 2012 Open Networking Foundation
*
* OpenFlow 1.4 is more extensible by using TLV structures
*/
+/* Port description property types. */
+enum ofp_port_desc_prop_type {
+ OFPPDPT14_ETHERNET = 0, /* Ethernet property. */
+ OFPPDPT14_OPTICAL = 1, /* Optical property. */
+ OFPPDPT14_EXPERIMENTER = 0xFFFF, /* Experimenter property. */
+};
+
+/* Ethernet port description property. */
+struct ofp14_port_desc_prop_ethernet {
+ ovs_be16 type; /* OFPPDPT14_ETHERNET. */
+ ovs_be16 length; /* Length in bytes of this property. */
+ uint8_t pad[4]; /* Align to 64 bits. */
+ /* Bitmaps of OFPPF_* that describe features. All bits zeroed if
+ * unsupported or unavailable. */
+ ovs_be32 curr; /* Current features. */
+ ovs_be32 advertised; /* Features being advertised by the port. */
+ ovs_be32 supported; /* Features supported by the port. */
+ ovs_be32 peer; /* Features advertised by peer. */
+
+ ovs_be32 curr_speed; /* Current port bitrate in kbps. */
+ ovs_be32 max_speed; /* Max port bitrate in kbps */
+};
+OFP_ASSERT(sizeof(struct ofp14_port_desc_prop_ethernet) == 32);
+
+struct ofp14_port {
+ ovs_be32 port_no;
+ ovs_be16 length;
+ uint8_t pad[2];
+ uint8_t hw_addr[OFP_ETH_ALEN];
+ uint8_t pad2[2]; /* Align to 64 bits. */
+ char name[OFP_MAX_PORT_NAME_LEN]; /* Null-terminated */
+
+ ovs_be32 config; /* Bitmap of OFPPC_* flags. */
+ ovs_be32 state; /* Bitmap of OFPPS_* flags. */
+
+ /* Followed by 0 or more OFPPDPT14_* properties. */
+};
+OFP_ASSERT(sizeof(struct ofp14_port) == 40);
+
/* Common header for all async config Properties */
struct ofp14_async_config_prop_header {
ovs_be16 type; /* One of OFPACPT_*. */
struct ofp_port_status {
uint8_t reason; /* One of OFPPR_*. */
uint8_t pad[7]; /* Align to 64-bits. */
- /* Followed by struct ofp10_phy_port or struct ofp11_port. */
+ /* Followed by struct ofp10_phy_port, struct ofp11_port, or struct
+ * ofp14_port. */
};
OFP_ASSERT(sizeof(struct ofp_port_status) == 8);
/* OFPT 1.0 (12): struct ofp_port_status, struct ofp10_phy_port. */
OFPRAW_OFPT10_PORT_STATUS,
- /* OFPT 1.1+ (12): struct ofp_port_status, struct ofp11_port. */
+ /* OFPT 1.1-1.3 (12): struct ofp_port_status, struct ofp11_port. */
OFPRAW_OFPT11_PORT_STATUS,
+ /* OFPT 1.4+ (12): struct ofp_port_status, struct ofp14_port, uint8_t[8][]. */
+ OFPRAW_OFPT14_PORT_STATUS,
/* OFPT 1.0 (13): struct ofp10_packet_out, uint8_t[]. */
OFPRAW_OFPT10_PACKET_OUT,
/* OFPST 1.0 (13): struct ofp10_phy_port[]. */
OFPRAW_OFPST10_PORT_DESC_REPLY,
- /* OFPST 1.1+ (13): struct ofp11_port[]. */
+ /* OFPST 1.1-1.3 (13): struct ofp11_port[]. */
OFPRAW_OFPST11_PORT_DESC_REPLY,
+ /* OFPST 1.4+ (13): uint8_t[8][]. */
+ OFPRAW_OFPST14_PORT_DESC_REPLY,
/* Nicira extension messages.
*
* OFPRAW_OFPT11_FLOW_REMOVED.
* OFPRAW_NXT_FLOW_REMOVED. */
OFPTYPE_PORT_STATUS, /* OFPRAW_OFPT10_PORT_STATUS.
- * OFPRAW_OFPT11_PORT_STATUS. */
+ * OFPRAW_OFPT11_PORT_STATUS.
+ * OFPRAW_OFPT14_PORT_STATUS. */
/* Controller command messages. */
OFPTYPE_PACKET_OUT, /* OFPRAW_OFPT10_PACKET_OUT.
OFPTYPE_PORT_DESC_STATS_REQUEST, /* OFPRAW_OFPST_PORT_DESC_REQUEST. */
OFPTYPE_PORT_DESC_STATS_REPLY, /* OFPRAW_OFPST10_PORT_DESC_REPLY.
- * OFPRAW_OFPST11_PORT_DESC_REPLY. */
+ * OFPRAW_OFPST11_PORT_DESC_REPLY.
+ * OFPRAW_OFPST14_PORT_DESC_REPLY. */
/* Nicira extensions. */
OFPTYPE_SET_FLOW_FORMAT, /* OFPRAW_NXT_SET_FLOW_FORMAT. */
return 0;
}
-
static void PRINTF_FORMAT(2, 3)
log_property(bool loose, const char *message, ...)
{
va_end(args);
}
}
+
/* Given the wildcard bit count in the least-significant 6 of 'wcbits', returns
* an IP netmask with a 1 in each bit that must match and a 0 in each bit that
* is wildcarded.
ofputil_decode_ofp10_phy_port(struct ofputil_phy_port *pp,
const struct ofp10_phy_port *opp)
{
- memset(pp, 0, sizeof *pp);
-
pp->port_no = u16_to_ofp(ntohs(opp->port_no));
memcpy(pp->hw_addr, opp->hw_addr, OFP_ETH_ALEN);
ovs_strlcpy(pp->name, opp->name, OFP_MAX_PORT_NAME_LEN);
{
enum ofperr error;
- memset(pp, 0, sizeof *pp);
-
error = ofputil_port_from_ofp11(op->port_no, &pp->port_no);
if (error) {
return error;
return 0;
}
+static enum ofperr
+parse_ofp14_port_ethernet_property(const struct ofpbuf *payload,
+ struct ofputil_phy_port *pp)
+{
+ struct ofp14_port_desc_prop_ethernet *eth = ofpbuf_data(payload);
+
+ if (ofpbuf_size(payload) != sizeof *eth) {
+ return OFPERR_OFPBPC_BAD_LEN;
+ }
+
+ pp->curr = netdev_port_features_from_ofp11(eth->curr);
+ pp->advertised = netdev_port_features_from_ofp11(eth->advertised);
+ pp->supported = netdev_port_features_from_ofp11(eth->supported);
+ pp->peer = netdev_port_features_from_ofp11(eth->peer);
+
+ pp->curr_speed = ntohl(eth->curr_speed);
+ pp->max_speed = ntohl(eth->max_speed);
+
+ return 0;
+}
+
+static enum ofperr
+ofputil_pull_ofp14_port(struct ofputil_phy_port *pp, struct ofpbuf *msg)
+{
+ struct ofpbuf properties;
+ struct ofp14_port *op;
+ enum ofperr error;
+ size_t len;
+
+ op = ofpbuf_try_pull(msg, sizeof *op);
+ if (!op) {
+ return OFPERR_OFPBRC_BAD_LEN;
+ }
+
+ len = ntohs(op->length);
+ if (len < sizeof *op || len - sizeof *op > ofpbuf_size(msg)) {
+ return OFPERR_OFPBRC_BAD_LEN;
+ }
+ len -= sizeof *op;
+ ofpbuf_use_const(&properties, ofpbuf_pull(msg, len), len);
+
+ error = ofputil_port_from_ofp11(op->port_no, &pp->port_no);
+ if (error) {
+ return error;
+ }
+ memcpy(pp->hw_addr, op->hw_addr, OFP_ETH_ALEN);
+ ovs_strlcpy(pp->name, op->name, OFP_MAX_PORT_NAME_LEN);
+
+ pp->config = ntohl(op->config) & OFPPC11_ALL;
+ pp->state = ntohl(op->state) & OFPPS11_ALL;
+
+ while (ofpbuf_size(&properties) > 0) {
+ struct ofpbuf payload;
+ enum ofperr error;
+ uint16_t type;
+
+ error = ofputil_pull_property(&properties, &payload, &type);
+ if (error) {
+ return error;
+ }
+
+ switch (type) {
+ case OFPPDPT14_ETHERNET:
+ error = parse_ofp14_port_ethernet_property(&payload, pp);
+ break;
+
+ default:
+ log_property(true, "unknown port property %"PRIu16, type);
+ error = 0;
+ break;
+ }
+
+ if (error) {
+ return error;
+ }
+ }
+
+ return 0;
+}
+
static size_t
ofputil_get_phy_port_size(enum ofp_version ofp_version)
{
op->max_speed = htonl(pp->max_speed);
}
+static void
+ofputil_put_ofp14_port(const struct ofputil_phy_port *pp,
+ struct ofpbuf *b)
+{
+ struct ofp14_port *op;
+ struct ofp14_port_desc_prop_ethernet *eth;
+
+ ofpbuf_prealloc_tailroom(b, sizeof *op + sizeof *eth);
+
+ op = ofpbuf_put_zeros(b, sizeof *op);
+ op->port_no = ofputil_port_to_ofp11(pp->port_no);
+ op->length = htons(sizeof *op + sizeof *eth);
+ memcpy(op->hw_addr, pp->hw_addr, ETH_ADDR_LEN);
+ ovs_strlcpy(op->name, pp->name, sizeof op->name);
+ op->config = htonl(pp->config & OFPPC11_ALL);
+ op->state = htonl(pp->state & OFPPS11_ALL);
+
+ eth = ofpbuf_put_zeros(b, sizeof *eth);
+ eth->type = htons(OFPPDPT14_ETHERNET);
+ eth->length = htons(sizeof *eth);
+ eth->curr = netdev_port_features_to_ofp11(pp->curr);
+ eth->advertised = netdev_port_features_to_ofp11(pp->advertised);
+ eth->supported = netdev_port_features_to_ofp11(pp->supported);
+ eth->peer = netdev_port_features_to_ofp11(pp->peer);
+ eth->curr_speed = htonl(pp->curr_speed);
+ eth->max_speed = htonl(pp->max_speed);
+}
+
static void
ofputil_put_phy_port(enum ofp_version ofp_version,
const struct ofputil_phy_port *pp, struct ofpbuf *b)
}
case OFP14_VERSION:
- OVS_NOT_REACHED();
+ ofputil_put_ofp14_port(pp, b);
break;
default:
case OFP11_VERSION:
case OFP12_VERSION:
case OFP13_VERSION:
- case OFP14_VERSION:
raw = OFPRAW_OFPT11_PORT_STATUS;
break;
+ case OFP14_VERSION:
+ raw = OFPRAW_OFPT14_PORT_STATUS;
+ break;
+
default:
OVS_NOT_REACHED();
}
ofputil_pull_phy_port(enum ofp_version ofp_version, struct ofpbuf *b,
struct ofputil_phy_port *pp)
{
+ memset(pp, 0, sizeof *pp);
+
switch (ofp_version) {
case OFP10_VERSION: {
const struct ofp10_phy_port *opp = ofpbuf_try_pull(b, sizeof *opp);
return op ? ofputil_decode_ofp11_port(pp, op) : EOF;
}
case OFP14_VERSION:
- OVS_NOT_REACHED();
- break;
+ return ofpbuf_size(b) ? ofputil_pull_ofp14_port(pp, b) : EOF;
default:
OVS_NOT_REACHED();
}
])
AT_CLEANUP
+AT_SETUP([OFPT_PORT_STATUS - OF1.4])
+AT_KEYWORDS([ofp-print])
+AT_CHECK([ovs-ofctl ofp-print "\
+05 0c 00 58 00 00 00 00 02 00 00 00 00 00 00 00 \
+00 00 00 03 00 48 00 00 50 54 00 00 00 01 00 00 \
+65 74 68 30 00 00 00 00 00 00 00 00 00 00 00 00 \
+00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 \
+00 00 20 08 00 00 28 0f 00 00 28 0f 00 00 00 00 \
+00 01 86 a0 00 01 86 a0 \
+"], [0], [dnl
+OFPT_PORT_STATUS (OF1.4) (xid=0x0): MOD: 3(eth0): addr:50:54:00:00:00:01
+ config: 0
+ state: 0
+ current: 100MB-FD AUTO_NEG
+ advertised: 10MB-HD 10MB-FD 100MB-HD 100MB-FD COPPER AUTO_NEG
+ supported: 10MB-HD 10MB-FD 100MB-HD 100MB-FD COPPER AUTO_NEG
+ speed: 100 Mbps now, 100 Mbps max
+])
+AT_CLEANUP
+
AT_SETUP([OFPT_PACKET_OUT - OF1.0])
AT_KEYWORDS([ofp-print])
AT_CHECK([ovs-ofctl ofp-print "\
])
AT_CLEANUP
+AT_SETUP([OFPST_PORT_DESC reply - OF1.4])
+AT_KEYWORDS([ofp-print OFPT_STATS_REPLY])
+AT_CHECK([ovs-ofctl ofp-print "\
+05 13 00 58 00 00 00 02 00 0d 00 00 00 00 00 00 \
+00 00 00 03 00 48 00 00 50 54 00 00 00 01 00 00 \
+65 74 68 30 00 00 00 00 00 00 00 00 00 00 00 00 \
+00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 \
+00 00 20 08 00 00 28 0f 00 00 28 0f 00 00 00 00 \
+00 01 86 a0 00 01 86 a0 \
+"], [0], [dnl
+OFPST_PORT_DESC reply (OF1.4) (xid=0x2):
+ 3(eth0): addr:50:54:00:00:00:01
+ config: 0
+ state: 0
+ current: 100MB-FD AUTO_NEG
+ advertised: 10MB-HD 10MB-FD 100MB-HD 100MB-FD COPPER AUTO_NEG
+ supported: 10MB-HD 10MB-FD 100MB-HD 100MB-FD COPPER AUTO_NEG
+ speed: 100 Mbps now, 100 Mbps max
+])
+AT_CLEANUP
+
AT_SETUP([OFPT_METER_MOD request - OF1.3])
AT_KEYWORDS([ofp-print])
AT_CHECK([ovs-ofctl ofp-print "\