Replace minimum version with bitmap of allowed versions.

This is in preparation for allowing the range of allowed OpenFlow
versions to be configured.

Signed-off-by: Simon Horman <ho...@verge.net.au>
---
 lib/rconn.c                |    5 ++-
 lib/vconn-provider.h       |   26 ++++++-----
 lib/vconn-stream.c         |   17 ++++---
 lib/vconn.c                |  107 ++++++++++++++++++++++++++++++++------------
 lib/vconn.h                |   14 ++++--
 ofproto/connmgr.c          |   10 ++++-
 tests/test-vconn.c         |   24 ++++++----
 utilities/ovs-controller.c |    8 +++-
 utilities/ovs-ofctl.c      |   11 +++--
 9 files changed, 156 insertions(+), 66 deletions(-)

diff --git a/lib/rconn.c b/lib/rconn.c
index ddf578c..904e01f 100644
--- a/lib/rconn.c
+++ b/lib/rconn.c
@@ -349,12 +349,15 @@ static void
 reconnect(struct rconn *rc)
 {
     int retval;
+    struct ofputil_version_bitmap ovb = OFPUTIL_VERSION_BITMAP_INITIALIZER;
 
     if (rconn_logging_connection_attempts__(rc)) {
         VLOG_INFO("%s: connecting...", rc->name);
     }
     rc->n_attempted_connections++;
-    retval = vconn_open(rc->target, OFP10_VERSION, &rc->vconn, rc->dscp);
+    ofputil_version_bitmap_set1(&ovb, OFP10_VERSION);
+    retval = vconn_open(rc->target, &ovb, &rc->vconn, rc->dscp);
+    ofputil_version_bitmap_free_data(&ovb);
     if (!retval) {
         rc->remote_ip = vconn_get_remote_ip(rc->vconn);
         rc->local_ip = vconn_get_local_ip(rc->vconn);
diff --git a/lib/vconn-provider.h b/lib/vconn-provider.h
index e9dd441..d4b20bf 100644
--- a/lib/vconn-provider.h
+++ b/lib/vconn-provider.h
@@ -23,6 +23,7 @@
 #include <assert.h>
 #include "vconn.h"
 #include "openflow/openflow-common.h"
+#include "lib/ofp-util.h"
 
 /* Active virtual connection to an OpenFlow device. */
 
@@ -33,7 +34,7 @@ struct vconn {
     struct vconn_class *class;
     int state;
     int error;
-    enum ofp_version min_version;
+    struct ofputil_version_bitmap allowed_versions;
     enum ofp_version version;
     ovs_be32 remote_ip;
     ovs_be16 remote_port;
@@ -43,7 +44,9 @@ struct vconn {
 };
 
 void vconn_init(struct vconn *, struct vconn_class *, int connect_status,
-                const char *name, enum ofp_version min_version);
+                const char *name,
+                const struct ofputil_version_bitmap *allowed_versions);
+void vconn_free_data(struct vconn *vconn);
 void vconn_set_remote_ip(struct vconn *, ovs_be32 remote_ip);
 void vconn_set_remote_port(struct vconn *, ovs_be16 remote_port);
 void vconn_set_local_ip(struct vconn *, ovs_be32 local_ip);
@@ -62,7 +65,7 @@ struct vconn_class {
      * connection name provided by the user, e.g. "tcp:1.2.3.4".  This name is
      * useful for error messages but must not be modified.
      *
-     * 'min_version' is the minimum OpenFlow version that will be
+     * 'allowed_verions' is the OpenFlow versions that may be
      * negotiated for a connection.
      *
      * 'suffix' is a copy of 'name' following the colon and may be modified.
@@ -76,8 +79,9 @@ struct vconn_class {
      * If the connection cannot be completed immediately, it should return
      * EAGAIN (not EINPROGRESS, as returned by the connect system call) and
      * continue the connection in the background. */
-    int (*open)(const char *name, enum ofp_version min_version, char *suffix,
-                struct vconn **vconnp, uint8_t dscp);
+    int (*open)(const char *name,
+                const struct ofputil_version_bitmap *allowed_versions,
+                char *suffix, struct vconn **vconnp, uint8_t dscp);
 
     /* Closes 'vconn' and frees associated memory. */
     void (*close)(struct vconn *vconn);
@@ -138,11 +142,12 @@ struct vconn_class {
 struct pvconn {
     struct pvconn_class *class;
     char *name;
-    enum ofp_version min_version;
+    struct ofputil_version_bitmap allowed_versions;
 };
 
-void pvconn_init(struct pvconn *, struct pvconn_class *, const char *name,
-                 enum ofp_version min_version);
+void pvconn_init(struct pvconn *pvconn, struct pvconn_class *class,
+                 const char *name,
+                 const struct ofputil_version_bitmap *allowed_versions);
 static inline void pvconn_assert_class(const struct pvconn *pvconn,
                                        const struct pvconn_class *class)
 {
@@ -157,7 +162,7 @@ struct pvconn_class {
      * full connection name provided by the user, e.g. "ptcp:1234".  This name
      * is useful for error messages but must not be modified.
      *
-     * 'min_version' is the minimum OpenFlow protocol version that may
+     * 'allowed_versions' is the OpenFlow protocol versions that may
      * be negotiated for a session.
      *
      * 'suffix' is a copy of 'name' following the colon and may be modified.
@@ -171,7 +176,8 @@ struct pvconn_class {
      * completed immediately, it should return EAGAIN (not EINPROGRESS, as
      * returned by the connect system call) and continue the connection in the
      * background. */
-    int (*listen)(const char *name, enum ofp_version min_version,
+    int (*listen)(const char *name,
+                  const struct ofputil_version_bitmap *allowed_versions,
                   char *suffix, struct pvconn **pvconnp, uint8_t dscp);
 
     /* Closes 'pvconn' and frees associated memory. */
diff --git a/lib/vconn-stream.c b/lib/vconn-stream.c
index 361fcb4..4b6539d 100644
--- a/lib/vconn-stream.c
+++ b/lib/vconn-stream.c
@@ -55,13 +55,13 @@ static void vconn_stream_clear_txbuf(struct vconn_stream *);
 
 static struct vconn *
 vconn_stream_new(struct stream *stream, int connect_status,
-                 enum ofp_version min_version)
+                 const struct ofputil_version_bitmap *allowed_versions)
 {
     struct vconn_stream *s;
 
     s = xmalloc(sizeof *s);
     vconn_init(&s->vconn, &stream_vconn_class, connect_status,
-               stream_get_name(stream), min_version);
+               stream_get_name(stream), allowed_versions);
     s->stream = stream;
     s->txbuf = NULL;
     s->rxbuf = NULL;
@@ -78,7 +78,8 @@ vconn_stream_new(struct stream *stream, int connect_status,
  *
  * Returns 0 if successful, otherwise a positive errno value. */
 static int
-vconn_stream_open(const char *name, enum ofp_version min_version,
+vconn_stream_open(const char *name,
+                  const struct ofputil_version_bitmap *allowed_versions,
                   char *suffix OVS_UNUSED, struct vconn **vconnp, uint8_t dscp)
 {
     struct stream *stream;
@@ -89,7 +90,7 @@ vconn_stream_open(const char *name, enum ofp_version 
min_version,
     if (!error) {
         error = stream_connect(stream);
         if (!error || error == EAGAIN) {
-            *vconnp = vconn_stream_new(stream, error, min_version);
+            *vconnp = vconn_stream_new(stream, error, allowed_versions);
             return 0;
         }
     }
@@ -117,6 +118,7 @@ vconn_stream_close(struct vconn *vconn)
     stream_close(s->stream);
     vconn_stream_clear_txbuf(s);
     ofpbuf_delete(s->rxbuf);
+    vconn_free_data(&s->vconn);
     free(s);
 }
 
@@ -311,7 +313,8 @@ pvconn_pstream_cast(struct pvconn *pvconn)
  * Returns 0 if successful, otherwise a positive errno value.  (The current
  * implementation never fails.) */
 static int
-pvconn_pstream_listen(const char *name, enum ofp_version min_version,
+pvconn_pstream_listen(const char *name,
+                      const struct ofputil_version_bitmap *allowed_versions,
                       char *suffix OVS_UNUSED, struct pvconn **pvconnp,
                       uint8_t dscp)
 {
@@ -326,7 +329,7 @@ pvconn_pstream_listen(const char *name, enum ofp_version 
min_version,
     }
 
     ps = xmalloc(sizeof *ps);
-    pvconn_init(&ps->pvconn, &pstream_pvconn_class, name, min_version);
+    pvconn_init(&ps->pvconn, &pstream_pvconn_class, name, allowed_versions);
     ps->pstream = pstream;
     *pvconnp = &ps->pvconn;
     return 0;
@@ -356,7 +359,7 @@ pvconn_pstream_accept(struct pvconn *pvconn, struct vconn 
**new_vconnp)
         return error;
     }
 
-    *new_vconnp = vconn_stream_new(stream, 0, pvconn->min_version);
+    *new_vconnp = vconn_stream_new(stream, 0, &pvconn->allowed_versions);
     return 0;
 }
 
diff --git a/lib/vconn.c b/lib/vconn.c
index 2dd4654..8603ad1 100644
--- a/lib/vconn.c
+++ b/lib/vconn.c
@@ -215,13 +215,14 @@ vconn_verify_name(const char *name)
  *
  * The vconn will automatically negotiate an OpenFlow protocol version
  * acceptable to both peers on the connection.  The version negotiated will be
- * no lower than 'min_version' and no higher than OFP10_VERSION.
+ * no lower than 'min_version' and no higher than 'max_version'.
  *
  * Returns 0 if successful, otherwise a positive errno value.  If successful,
  * stores a pointer to the new connection in '*vconnp', otherwise a null
  * pointer.  */
 int
-vconn_open(const char *name, enum ofp_version min_version,
+vconn_open(const char *name,
+           const struct ofputil_version_bitmap *allowed_versions,
            struct vconn **vconnp, uint8_t dscp)
 {
     struct vconn_class *class;
@@ -240,7 +241,7 @@ vconn_open(const char *name, enum ofp_version min_version,
 
     /* Call class's "open" function. */
     suffix_copy = xstrdup(strchr(name, ':') + 1);
-    error = class->open(name, min_version, suffix_copy, &vconn, dscp);
+    error = class->open(name, allowed_versions, suffix_copy, &vconn, dscp);
     free(suffix_copy);
     if (error) {
         goto error;
@@ -289,7 +290,8 @@ vconn_run_wait(struct vconn *vconn)
 }
 
 int
-vconn_open_block(const char *name, enum ofp_version min_version,
+vconn_open_block(const char *name,
+                 const struct ofputil_version_bitmap *allowed_versions,
                  struct vconn **vconnp)
 {
     struct vconn *vconn;
@@ -297,7 +299,7 @@ vconn_open_block(const char *name, enum ofp_version 
min_version,
 
     fatal_signal_run();
 
-    error = vconn_open(name, min_version, &vconn, DSCP_DEFAULT);
+    error = vconn_open(name, allowed_versions, &vconn, DSCP_DEFAULT);
     if (!error) {
         error = vconn_connect_block(vconn);
     }
@@ -329,6 +331,14 @@ vconn_get_name(const struct vconn *vconn)
     return vconn->name;
 }
 
+/* Returns the allowed_versions of 'vconn', that is,
+ * the allowed_versions passed to vconn_open(). */
+const struct ofputil_version_bitmap *
+vconn_get_allowed_versions(const struct vconn *vconn)
+{
+    return &vconn->allowed_versions;
+}
+
 /* Returns the IP address of the peer, or 0 if the peer is not connected over
  * an IP-based protocol or if its IP address is not yet known. */
 ovs_be32
@@ -387,12 +397,12 @@ vcs_connecting(struct vconn *vconn)
 }
 
 static void
-vcs_send_hello(struct vconn *vconn)
+vcs_send_hello(struct vconn *vconn, enum ofp_version max_version)
 {
     struct ofpbuf *b;
     int retval;
 
-    b = ofpraw_alloc(OFPRAW_OFPT_HELLO, OFP10_VERSION, 0);
+    b = ofpraw_alloc(OFPRAW_OFPT_HELLO, max_version, 0);
     retval = do_send(vconn, b);
     if (!retval) {
         vconn->state = VCS_RECV_HELLO;
@@ -406,6 +416,24 @@ vcs_send_hello(struct vconn *vconn)
 }
 
 static void
+format_versions(struct ds *msg, struct ofputil_version_bitmap *ovb)
+{
+    size_t n = ofputil_version_bitmap_count_set(ovb);
+    if (!n) {
+        ds_put_cstr(msg, "no versions");
+        return;
+    }
+
+    if (n == 1) {
+        ds_put_cstr(msg, "version ");
+    } else {
+        ds_put_cstr(msg, "versions ");
+    }
+
+    ofputil_format_version_bitmap(msg, ovb);
+}
+
+static void
 vcs_recv_hello(struct vconn *vconn)
 {
     struct ofpbuf *b;
@@ -427,21 +455,26 @@ vcs_recv_hello(struct vconn *vconn)
                 ds_destroy(&msg);
             }
 
-            vconn->version = MIN(OFP10_VERSION, oh->version);
-            if (vconn->version < vconn->min_version) {
+            vconn->version =
+                ofputil_version_bitmap_scanr(&vconn->allowed_versions);
+            if (vconn->version == oh->version + 1) {
+                struct ds msg = DS_EMPTY_INITIALIZER;
+                format_versions(&msg, &vconn->allowed_versions);
                 VLOG_WARN_RL(&bad_ofmsg_rl,
                              "%s: version negotiation failed: we support "
-                             "versions 0x%02x to 0x%02x inclusive but peer "
-                             "supports no later than version 0x%02"PRIx8,
-                             vconn->name, vconn->min_version, OFP10_VERSION,
-                             oh->version);
+                             "%s but peer " "supports no later than "
+                             "version 0x%02"PRIx8, vconn->name,
+                             ds_cstr(&msg), oh->version);
+                ds_destroy(&msg);
                 vconn->state = VCS_SEND_ERROR;
             } else {
+                struct ds msg = DS_EMPTY_INITIALIZER;
+                format_versions(&msg, &vconn->allowed_versions);
                 VLOG_DBG("%s: negotiated OpenFlow version 0x%02x "
-                         "(we support versions 0x%02x to 0x%02x inclusive, "
-                         "peer no later than version 0x%02"PRIx8")",
-                         vconn->name, vconn->version, vconn->min_version,
-                         OFP10_VERSION, oh->version);
+                         "(we support %s, peer no later than "
+                         "version 0x%02"PRIx8")", vconn->name,
+                         vconn->version, ds_cstr(&msg), oh->version);
+                ds_destroy(&msg);
                 vconn->state = VCS_CONNECTED;
             }
             ofpbuf_delete(b);
@@ -469,10 +502,12 @@ vcs_send_error(struct vconn *vconn)
     struct ofpbuf *b;
     char s[128];
     int retval;
+    struct ds msg = DS_EMPTY_INITIALIZER;
 
-    snprintf(s, sizeof s, "We support versions 0x%02x to 0x%02x inclusive but "
-             "you support no later than version 0x%02"PRIx8".",
-             vconn->min_version, OFP12_VERSION, vconn->version);
+    format_versions(&msg, &vconn->allowed_versions);
+    snprintf(s, sizeof s, "We support %s but you support no later than "
+             "version 0x%02"PRIx8".", ds_cstr(&msg), vconn->version);
+    ds_destroy(&msg);
     b = ofperr_encode_hello(OFPERR_OFPHFC_INCOMPATIBLE, vconn->version, s);
     retval = do_send(vconn, b);
     if (retval) {
@@ -492,8 +527,11 @@ int
 vconn_connect(struct vconn *vconn)
 {
     enum vconn_state last_state;
+    enum ofp_version max_version;
+    struct ofputil_version_bitmap *versions = &vconn->allowed_versions;
 
-    assert(vconn->min_version > 0);
+    max_version = ofputil_version_bitmap_scanr(versions);
+    assert(max_version != versions->n_bits);
     do {
         last_state = vconn->state;
         switch (vconn->state) {
@@ -502,7 +540,7 @@ vconn_connect(struct vconn *vconn)
             break;
 
         case VCS_SEND_HELLO:
-            vcs_send_hello(vconn);
+            vcs_send_hello(vconn, max_version);
             break;
 
         case VCS_RECV_HELLO:
@@ -924,7 +962,8 @@ pvconn_verify_name(const char *name)
  * stores a pointer to the new connection in '*pvconnp', otherwise a null
  * pointer.  */
 int
-pvconn_open(const char *name, enum ofp_version min_version,
+pvconn_open(const char *name,
+            const struct ofputil_version_bitmap *allowed_versions,
             struct pvconn **pvconnp, uint8_t dscp)
 {
     struct pvconn_class *class;
@@ -942,7 +981,7 @@ pvconn_open(const char *name, enum ofp_version min_version,
 
     /* Call class's "open" function. */
     suffix_copy = xstrdup(strchr(name, ':') + 1);
-    error = class->listen(name, min_version, suffix_copy, &pvconn, dscp);
+    error = class->listen(name, allowed_versions, suffix_copy, &pvconn, dscp);
     free(suffix_copy);
     if (error) {
         goto error;
@@ -982,7 +1021,7 @@ pvconn_close(struct pvconn *pvconn)
  *
  * The new vconn will automatically negotiate an OpenFlow protocol version
  * acceptable to both peers on the connection.  The version negotiated will be
- * no lower than 'min_version' and no higher than OFP10_VERSION.
+ * no lower than 'min_version' and no higher than 'max_version'.
  *
  * pvconn_accept() will not block waiting for a connection.  If no connection
  * is ready to be accepted, it returns EAGAIN immediately. */
@@ -1024,7 +1063,8 @@ pvconn_wait(struct pvconn *pvconn)
  * The caller retains ownership of 'name'. */
 void
 vconn_init(struct vconn *vconn, struct vconn_class *class, int connect_status,
-           const char *name, enum ofp_version min_version)
+           const char *name,
+           const struct ofputil_version_bitmap *allowed_versions)
 {
     vconn->class = class;
     vconn->state = (connect_status == EAGAIN ? VCS_CONNECTING
@@ -1032,7 +1072,8 @@ vconn_init(struct vconn *vconn, struct vconn_class 
*class, int connect_status,
                     : VCS_DISCONNECTED);
     vconn->error = connect_status;
     vconn->version = 0;
-    vconn->min_version = min_version;
+    ofputil_version_bitmap_clone_data(allowed_versions,
+                                      &vconn->allowed_versions);
     vconn->remote_ip = 0;
     vconn->remote_port = 0;
     vconn->local_ip = 0;
@@ -1042,6 +1083,12 @@ vconn_init(struct vconn *vconn, struct vconn_class 
*class, int connect_status,
 }
 
 void
+vconn_free_data(struct vconn *vconn)
+{
+    ofputil_version_bitmap_free_data(&vconn->allowed_versions);
+}
+
+void
 vconn_set_remote_ip(struct vconn *vconn, ovs_be32 ip)
 {
     vconn->remote_ip = ip;
@@ -1067,9 +1114,11 @@ vconn_set_local_port(struct vconn *vconn, ovs_be16 port)
 
 void
 pvconn_init(struct pvconn *pvconn,  struct pvconn_class *class,
-            const char *name, enum ofp_version min_version)
+            const char *name,
+            const struct ofputil_version_bitmap *allowed_versions)
 {
     pvconn->class = class;
     pvconn->name = xstrdup(name);
-    pvconn->min_version = min_version;
+    ofputil_version_bitmap_clone_data(allowed_versions,
+                                      &pvconn->allowed_versions);
 }
diff --git a/lib/vconn.h b/lib/vconn.h
index 01d1c70..e4ab654 100644
--- a/lib/vconn.h
+++ b/lib/vconn.h
@@ -20,6 +20,7 @@
 #include <stdbool.h>
 #include "openvswitch/types.h"
 #include "openflow/openflow.h"
+#include "lib/ofp-util.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -34,10 +35,13 @@ void vconn_usage(bool active, bool passive, bool bootstrap);
 
 /* Active vconns: virtual connections to OpenFlow devices. */
 int vconn_verify_name(const char *name);
-int vconn_open(const char *name, enum ofp_version min_version,
-               struct vconn **, uint8_t dscp);
+int vconn_open(const char *name,
+               const struct ofputil_version_bitmap *allowed_versions,
+               struct vconn **vconnp, uint8_t dscp);
 void vconn_close(struct vconn *);
 const char *vconn_get_name(const struct vconn *);
+const struct ofputil_version_bitmap *
+vconn_get_allowed_versions(const struct vconn *vconn);
 ovs_be32 vconn_get_remote_ip(const struct vconn *);
 ovs_be16 vconn_get_remote_port(const struct vconn *);
 ovs_be32 vconn_get_local_ip(const struct vconn *);
@@ -55,7 +59,8 @@ int vconn_transact_multiple_noreply(struct vconn *, struct 
list *requests,
 void vconn_run(struct vconn *);
 void vconn_run_wait(struct vconn *);
 
-int vconn_open_block(const char *name, enum ofp_version min_version,
+int vconn_open_block(const char *name,
+                     const struct ofputil_version_bitmap *allowed_versions,
                      struct vconn **);
 int vconn_connect_block(struct vconn *);
 int vconn_send_block(struct vconn *, struct ofpbuf *);
@@ -73,7 +78,8 @@ void vconn_send_wait(struct vconn *);
 
 /* Passive vconns: virtual listeners for incoming OpenFlow connections. */
 int pvconn_verify_name(const char *name);
-int pvconn_open(const char *name, enum ofp_version min_version,
+int pvconn_open(const char *name,
+                const struct ofputil_version_bitmap *allowed_versions,
                 struct pvconn **pvconnp, uint8_t dscp);
 const char *pvconn_get_name(const struct pvconn *);
 void pvconn_close(struct pvconn *);
diff --git a/ofproto/connmgr.c b/ofproto/connmgr.c
index 0c2a165..d63a166 100644
--- a/ofproto/connmgr.c
+++ b/ofproto/connmgr.c
@@ -718,10 +718,13 @@ set_pvconns(struct pvconn ***pvconnsp, size_t *n_pvconnsp,
     pvconns = xmalloc(sset_count(sset) * sizeof *pvconns);
     n_pvconns = 0;
     SSET_FOR_EACH (name, sset) {
+        struct ofputil_version_bitmap ovb = OFPUTIL_VERSION_BITMAP_INITIALIZER;
         struct pvconn *pvconn;
         int error;
 
-        error = pvconn_open(name, OFP10_VERSION, &pvconn, 0);
+        ofputil_version_bitmap_set1(&ovb, OFP10_VERSION);
+        error = pvconn_open(name, &ovb, &pvconn, 0);
+        ofputil_version_bitmap_free_data(&ovb);
         if (!error) {
             pvconns[n_pvconns++] = pvconn;
         } else {
@@ -1621,11 +1624,14 @@ connmgr_flushed(struct connmgr *mgr)
 static int
 ofservice_create(struct connmgr *mgr, const char *target, uint8_t dscp)
 {
+    struct ofputil_version_bitmap ovb = OFPUTIL_VERSION_BITMAP_INITIALIZER;
     struct ofservice *ofservice;
     struct pvconn *pvconn;
     int error;
 
-    error = pvconn_open(target, OFP10_VERSION, &pvconn, dscp);
+    ofputil_version_bitmap_set1(&ovb, OFP10_VERSION);
+    error = pvconn_open(target, &ovb, &pvconn, dscp);
+    ofputil_version_bitmap_free_data(&ovb);
     if (error) {
         return error;
     }
diff --git a/tests/test-vconn.c b/tests/test-vconn.c
index 5dd38f0..6c21313 100644
--- a/tests/test-vconn.c
+++ b/tests/test-vconn.c
@@ -142,14 +142,16 @@ fpv_destroy(struct fake_pvconn *fpv)
 static void
 test_refuse_connection(int argc OVS_UNUSED, char *argv[])
 {
+    struct ofputil_version_bitmap ovb = OFPUTIL_VERSION_BITMAP_INITIALIZER;
     const char *type = argv[1];
     struct fake_pvconn fpv;
     struct vconn *vconn;
     int error;
 
     fpv_create(type, &fpv);
-    CHECK_ERRNO(vconn_open(fpv.vconn_name, OFP10_VERSION, &vconn,
-                           DSCP_DEFAULT), 0);
+    ofputil_version_bitmap_set1(&ovb, OFP10_VERSION);
+    CHECK_ERRNO(vconn_open(fpv.vconn_name, &ovb, &vconn, DSCP_DEFAULT), 0);
+    ofputil_version_bitmap_free_data(&ovb);
     fpv_close(&fpv);
     vconn_run(vconn);
 
@@ -173,14 +175,16 @@ test_refuse_connection(int argc OVS_UNUSED, char *argv[])
 static void
 test_accept_then_close(int argc OVS_UNUSED, char *argv[])
 {
+    struct ofputil_version_bitmap ovb = OFPUTIL_VERSION_BITMAP_INITIALIZER;
     const char *type = argv[1];
     struct fake_pvconn fpv;
     struct vconn *vconn;
     int error;
 
     fpv_create(type, &fpv);
-    CHECK_ERRNO(vconn_open(fpv.vconn_name, OFP10_VERSION, &vconn,
-                           DSCP_DEFAULT), 0);
+    ofputil_version_bitmap_set1(&ovb, OFP10_VERSION);
+    CHECK_ERRNO(vconn_open(fpv.vconn_name, &ovb, &vconn, DSCP_DEFAULT), 0);
+    ofputil_version_bitmap_free_data(&ovb);
     vconn_run(vconn);
     stream_close(fpv_accept(&fpv));
     fpv_close(&fpv);
@@ -205,6 +209,7 @@ test_accept_then_close(int argc OVS_UNUSED, char *argv[])
 static void
 test_read_hello(int argc OVS_UNUSED, char *argv[])
 {
+    struct ofputil_version_bitmap ovb = OFPUTIL_VERSION_BITMAP_INITIALIZER;
     const char *type = argv[1];
     struct fake_pvconn fpv;
     struct vconn *vconn;
@@ -212,8 +217,9 @@ test_read_hello(int argc OVS_UNUSED, char *argv[])
     int error;
 
     fpv_create(type, &fpv);
-    CHECK_ERRNO(vconn_open(fpv.vconn_name, OFP10_VERSION, &vconn,
-                           DSCP_DEFAULT), 0);
+    ofputil_version_bitmap_set1(&ovb, OFP10_VERSION);
+    CHECK_ERRNO(vconn_open(fpv.vconn_name, &ovb, &vconn, DSCP_DEFAULT), 0);
+    ofputil_version_bitmap_free_data(&ovb);
     vconn_run(vconn);
     stream = fpv_accept(&fpv);
     fpv_destroy(&fpv);
@@ -258,6 +264,7 @@ static void
 test_send_hello(const char *type, const void *out, size_t out_size,
                 int expect_connect_error)
 {
+    struct ofputil_version_bitmap ovb = OFPUTIL_VERSION_BITMAP_INITIALIZER;
     struct fake_pvconn fpv;
     struct vconn *vconn;
     bool read_hello, connected;
@@ -266,8 +273,9 @@ test_send_hello(const char *type, const void *out, size_t 
out_size,
     size_t n_sent;
 
     fpv_create(type, &fpv);
-    CHECK_ERRNO(vconn_open(fpv.vconn_name, OFP10_VERSION, &vconn,
-                           DSCP_DEFAULT), 0);
+    ofputil_version_bitmap_set1(&ovb, OFP10_VERSION);
+    CHECK_ERRNO(vconn_open(fpv.vconn_name, &ovb, &vconn, DSCP_DEFAULT), 0);
+    ofputil_version_bitmap_free_data(&ovb);
     vconn_run(vconn);
     stream = fpv_accept(&fpv);
     fpv_destroy(&fpv);
diff --git a/utilities/ovs-controller.c b/utilities/ovs-controller.c
index 2f812a6..4adf61f 100644
--- a/utilities/ovs-controller.c
+++ b/utilities/ovs-controller.c
@@ -92,6 +92,7 @@ static void usage(void) NO_RETURN;
 int
 main(int argc, char *argv[])
 {
+    struct ofputil_version_bitmap ovb = OFPUTIL_VERSION_BITMAP_INITIALIZER;
     struct unixctl_server *unixctl;
     struct switch_ switches[MAX_SWITCHES];
     struct pvconn *listeners[MAX_LISTENERS];
@@ -109,12 +110,14 @@ main(int argc, char *argv[])
                   "use --help for usage");
     }
 
+    ofputil_version_bitmap_set1(&ovb, OFP10_VERSION);
+
     n_switches = n_listeners = 0;
     for (i = optind; i < argc; i++) {
         const char *name = argv[i];
         struct vconn *vconn;
 
-        retval = vconn_open(name, OFP10_VERSION, &vconn, DSCP_DEFAULT);
+        retval = vconn_open(name, &ovb, &vconn, DSCP_DEFAULT);
         if (!retval) {
             if (n_switches >= MAX_SWITCHES) {
                 ovs_fatal(0, "max %d switch connections", n_switches);
@@ -123,7 +126,7 @@ main(int argc, char *argv[])
             continue;
         } else if (retval == EAFNOSUPPORT) {
             struct pvconn *pvconn;
-            retval = pvconn_open(name, OFP10_VERSION, &pvconn, DSCP_DEFAULT);
+            retval = pvconn_open(name, &ovb, &pvconn, DSCP_DEFAULT);
             if (!retval) {
                 if (n_listeners >= MAX_LISTENERS) {
                     ovs_fatal(0, "max %d passive connections", n_listeners);
@@ -139,6 +142,7 @@ main(int argc, char *argv[])
         ovs_fatal(0, "no active or passive switch connections");
     }
 
+    ofputil_version_bitmap_free_data(&ovb);
     daemonize_start();
 
     retval = unixctl_server_create(unixctl_path, &unixctl);
diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c
index a0b7079..4753d9e 100644
--- a/utilities/ovs-ofctl.c
+++ b/utilities/ovs-ofctl.c
@@ -334,10 +334,13 @@ static void run(int retval, const char *message, ...)
 static void
 open_vconn_socket(const char *name, struct vconn **vconnp)
 {
+    struct ofputil_version_bitmap ovb = OFPUTIL_VERSION_BITMAP_INITIALIZER;
     char *vconn_name = xasprintf("unix:%s", name);
     VLOG_DBG("connecting to %s", vconn_name);
-    run(vconn_open_block(vconn_name, OFP10_VERSION, vconnp),
+    ofputil_version_bitmap_set1(&ovb, OFP10_VERSION);
+    run(vconn_open_block(vconn_name, &ovb,  vconnp),
         "connecting to %s", vconn_name);
+    ofputil_version_bitmap_free_data(&ovb);
     free(vconn_name);
 }
 
@@ -360,8 +363,10 @@ open_vconn__(const char *name, const char *default_suffix,
     free(datapath_type);
 
     if (strchr(name, ':')) {
-        run(vconn_open_block(name, OFP10_VERSION, vconnp),
-            "connecting to %s", name);
+        struct ofputil_version_bitmap ovb = OFPUTIL_VERSION_BITMAP_INITIALIZER;
+        ofputil_version_bitmap_set1(&ovb, OFP10_VERSION);
+        run(vconn_open_block(name, &ovb, vconnp), "connecting to %s", name);
+        ofputil_version_bitmap_free_data(&ovb);
     } else if (!stat(name, &s) && S_ISSOCK(s.st_mode)) {
         open_vconn_socket(name, vconnp);
     } else if (!stat(bridge_path, &s) && S_ISSOCK(s.st_mode)) {
-- 
1.7.10.4

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to