Global replace of Nicira Networks.
[sliver-openvswitch.git] / lib / vconn.c
index 5da5026..5cd708d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira Networks.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -38,6 +38,7 @@
 #include "random.h"
 #include "util.h"
 #include "vlog.h"
+#include "socket-util.h"
 
 VLOG_DEFINE_THIS_MODULE(vconn);
 
@@ -213,13 +214,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 OFP_VERSION.
+ * no lower than 'min_version' and no higher than OFP10_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, int min_version, struct vconn **vconnp)
+vconn_open(const char *name, int min_version, struct vconn **vconnp,
+           uint8_t dscp)
 {
     struct vconn_class *class;
     struct vconn *vconn;
@@ -237,7 +239,7 @@ vconn_open(const char *name, int min_version, struct vconn **vconnp)
 
     /* Call class's "open" function. */
     suffix_copy = xstrdup(strchr(name, ':') + 1);
-    error = class->open(name, suffix_copy, &vconn);
+    error = class->open(name, suffix_copy, &vconn, dscp);
     free(suffix_copy);
     if (error) {
         goto error;
@@ -282,7 +284,7 @@ vconn_open_block(const char *name, int min_version, struct vconn **vconnp)
 
     fatal_signal_run();
 
-    error = vconn_open(name, min_version, &vconn);
+    error = vconn_open(name, min_version, &vconn, DSCP_DEFAULT);
     if (!error) {
         while ((error = vconn_connect(vconn)) == EAGAIN) {
             vconn_run(vconn);
@@ -353,6 +355,17 @@ vconn_get_local_port(const struct vconn *vconn)
     return vconn->local_port;
 }
 
+/* Returns the OpenFlow version negotiated with the peer, or -1 if version
+ * negotiation is not yet complete.
+ *
+ * A vconn that has successfully connected (that is, vconn_connect() or
+ * vconn_send() or vconn_recv() has returned 0) always negotiated a version. */
+int
+vconn_get_version(const struct vconn *vconn)
+{
+    return vconn->version;
+}
+
 static void
 vcs_connecting(struct vconn *vconn)
 {
@@ -404,13 +417,13 @@ vcs_recv_hello(struct vconn *vconn)
                 ds_destroy(&msg);
             }
 
-            vconn->version = MIN(OFP_VERSION, oh->version);
+            vconn->version = MIN(OFP10_VERSION, oh->version);
             if (vconn->version < vconn->min_version) {
                 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, OFP_VERSION,
+                             vconn->name, vconn->min_version, OFP10_VERSION,
                              oh->version);
                 vconn->state = VCS_SEND_ERROR;
             } else {
@@ -418,7 +431,7 @@ vcs_recv_hello(struct vconn *vconn)
                          "(we support versions 0x%02x to 0x%02x inclusive, "
                          "peer no later than version 0x%02"PRIx8")",
                          vconn->name, vconn->version, vconn->min_version,
-                         OFP_VERSION, oh->version);
+                         OFP10_VERSION, oh->version);
                 vconn->state = VCS_CONNECTED;
             }
             ofpbuf_delete(b);
@@ -449,7 +462,7 @@ vcs_send_error(struct vconn *vconn)
 
     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, OFP_VERSION, vconn->version);
+             vconn->min_version, OFP10_VERSION, vconn->version);
     b = ofperr_encode_hello(OFPERR_OFPHFC_INCOMPATIBLE,
                             ofperr_domain_from_version(vconn->version), s);
     retval = do_send(vconn, b);
@@ -471,7 +484,7 @@ vconn_connect(struct vconn *vconn)
 {
     enum vconn_state last_state;
 
-    assert(vconn->min_version >= 0);
+    assert(vconn->min_version > 0);
     do {
         last_state = vconn->state;
         switch (vconn->state) {
@@ -538,14 +551,14 @@ do_recv(struct vconn *vconn, struct ofpbuf **msgp)
         }
 
         oh = ofpbuf_at_assert(*msgp, 0, sizeof *oh);
-        if (oh->version != vconn->version
+        if ((oh->version != vconn->version || oh->version == 0)
             && oh->type != OFPT_HELLO
             && oh->type != OFPT_ERROR
             && oh->type != OFPT_ECHO_REQUEST
             && oh->type != OFPT_ECHO_REPLY
             && oh->type != OFPT_VENDOR)
         {
-            if (vconn->version < 0) {
+            if (vconn->version == 0) {
                 VLOG_ERR_RL(&bad_ofmsg_rl,
                             "%s: received OpenFlow message type %"PRIu8" "
                             "before version negotiation complete",
@@ -888,7 +901,7 @@ 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, struct pvconn **pvconnp)
+pvconn_open(const char *name, struct pvconn **pvconnp, uint8_t dscp)
 {
     struct pvconn_class *class;
     struct pvconn *pvconn;
@@ -905,7 +918,7 @@ pvconn_open(const char *name, struct pvconn **pvconnp)
 
     /* Call class's "open" function. */
     suffix_copy = xstrdup(strchr(name, ':') + 1);
-    error = class->listen(name, suffix_copy, &pvconn);
+    error = class->listen(name, suffix_copy, &pvconn, dscp);
     free(suffix_copy);
     if (error) {
         goto error;
@@ -945,7 +958,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 OFP_VERSION.
+ * no lower than 'min_version' and no higher than OFP10_VERSION.
  *
  * pvconn_accept() will not block waiting for a connection.  If no connection
  * is ready to be accepted, it returns EAGAIN immediately. */
@@ -995,8 +1008,8 @@ vconn_init(struct vconn *vconn, struct vconn_class *class, int connect_status,
                     : !connect_status ? VCS_SEND_HELLO
                     : VCS_DISCONNECTED);
     vconn->error = connect_status;
-    vconn->version = -1;
-    vconn->min_version = -1;
+    vconn->version = 0;
+    vconn->min_version = 0;
     vconn->remote_ip = 0;
     vconn->remote_port = 0;
     vconn->local_ip = 0;