ofp-util: Implement OpenFlow 1.4 port status and port desc reply messages.
authorBen Pfaff <blp@nicira.com>
Tue, 13 May 2014 01:15:28 +0000 (18:15 -0700)
committerBen Pfaff <blp@nicira.com>
Wed, 14 May 2014 17:31:42 +0000 (10:31 -0700)
Signed-off-by: Ben Pfaff <blp@nicira.com>
build-aux/extract-ofp-msgs
include/openflow/openflow-1.4.h
include/openflow/openflow-common.h
lib/ofp-msgs.h
lib/ofp-util.c
tests/ofp-print.at

index 9571192..3cefb2b 100755 (executable)
@@ -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():
index cf83c61..9c03cf4 100644 (file)
@@ -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
 *
  * 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_*. */
index 33df02b..76b18f2 100644 (file)
@@ -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);
 
index df7569e..b548f6b 100644 (file)
@@ -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. */
index 6124903..faddcd0 100644 (file)
@@ -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)
 {
@@ -3789,6 +3865,34 @@ ofputil_encode_ofp11_port(const struct ofputil_phy_port *pp,
     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)
@@ -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:
@@ -4128,10 +4232,13 @@ ofputil_encode_port_status(const struct ofputil_port_status *ps,
     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();
     }
@@ -5548,6 +5655,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 +5669,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();
     }
index ba1abf1..640d114 100644 (file)
@@ -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 "\