Signed-off-by: Ben Pfaff <b...@nicira.com> --- build-aux/extract-ofp-msgs | 1 + include/openflow/openflow-1.4.h | 41 ++++++++++++- include/openflow/openflow-common.h | 3 +- lib/ofp-msgs.h | 14 +++-- lib/ofp-util.c | 121 ++++++++++++++++++++++++++++++++++--- tests/ofp-print.at | 41 +++++++++++++ 6 files changed, 207 insertions(+), 14 deletions(-)
diff --git a/build-aux/extract-ofp-msgs b/build-aux/extract-ofp-msgs index 9571192..3cefb2b 100755 --- a/build-aux/extract-ofp-msgs +++ b/build-aux/extract-ofp-msgs @@ -34,6 +34,7 @@ version_map = {"1.0": (OFP10_VERSION, OFP10_VERSION), "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(): diff --git a/include/openflow/openflow-1.4.h b/include/openflow/openflow-1.4.h index cf83c61..9c03cf4 100644 --- a/include/openflow/openflow-1.4.h +++ b/include/openflow/openflow-1.4.h @@ -1,4 +1,4 @@ -/* 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 * @@ -42,6 +42,45 @@ * 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_*. */ diff --git a/include/openflow/openflow-common.h b/include/openflow/openflow-common.h index 33df02b..76b18f2 100644 --- a/include/openflow/openflow-common.h +++ b/include/openflow/openflow-common.h @@ -387,7 +387,8 @@ enum ofp_port_reason { 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); diff --git a/lib/ofp-msgs.h b/lib/ofp-msgs.h index df7569e..b548f6b 100644 --- a/lib/ofp-msgs.h +++ b/lib/ofp-msgs.h @@ -162,8 +162,10 @@ enum ofpraw { /* 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, @@ -360,8 +362,10 @@ enum ofpraw { /* 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. * @@ -471,7 +475,8 @@ enum ofptype { * 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. @@ -581,7 +586,8 @@ enum ofptype { 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. */ diff --git a/lib/ofp-util.c b/lib/ofp-util.c index 6124903..33d1728 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -84,7 +84,6 @@ ofputil_pull_property(struct ofpbuf *msg, struct ofpbuf *property, return 0; } - static void PRINTF_FORMAT(2, 3) log_property(bool loose, const char *message, ...) { @@ -97,6 +96,7 @@ 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. @@ -3683,8 +3683,6 @@ static enum ofperr 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); @@ -3709,8 +3707,6 @@ ofputil_decode_ofp11_port(struct ofputil_phy_port *pp, { enum ofperr error; - memset(pp, 0, sizeof *pp); - error = ofputil_port_from_ofp11(op->port_no, &pp->port_no); if (error) { return error; @@ -3732,6 +3728,86 @@ ofputil_decode_ofp11_port(struct ofputil_phy_port *pp, 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) { @@ -3790,6 +3866,34 @@ ofputil_encode_ofp11_port(const struct ofputil_phy_port *pp, } 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) { @@ -3809,7 +3913,7 @@ ofputil_put_phy_port(enum ofp_version ofp_version, } case OFP14_VERSION: - OVS_NOT_REACHED(); + ofputil_put_ofp14_port(pp, b); break; default: @@ -5548,6 +5652,8 @@ int 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); @@ -5560,8 +5666,7 @@ ofputil_pull_phy_port(enum ofp_version ofp_version, struct ofpbuf *b, 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(); } diff --git a/tests/ofp-print.at b/tests/ofp-print.at index ba1abf1..640d114 100644 --- a/tests/ofp-print.at +++ b/tests/ofp-print.at @@ -621,6 +621,26 @@ OFPT_PORT_STATUS (OF1.1) (xid=0x0): MOD: 3(eth0): addr:50:54:00:00:00:01 ]) 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 "\ @@ -1860,6 +1880,27 @@ OFPST_PORT_DESC reply (xid=0x0): ]) 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 "\ -- 1.9.1 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev