Merge commit 'origin/citrix'
[sliver-openvswitch.git] / lib / vconn.c
index a006efb..3210923 100644 (file)
@@ -128,23 +128,23 @@ vconn_usage(bool active, bool passive, bool bootstrap UNUSED)
     printf("\n");
     if (active) {
         printf("Active OpenFlow connection methods:\n");
-        printf("  tcp:HOST[:PORT]         "
-               "PORT (default: %d) on remote TCP HOST\n", OFP_TCP_PORT);
+        printf("  tcp:IP[:PORT]         "
+               "PORT (default: %d) at remote IP\n", OFP_TCP_PORT);
 #ifdef HAVE_OPENSSL
-        printf("  ssl:HOST[:PORT]         "
-               "SSL PORT (default: %d) on remote HOST\n", OFP_SSL_PORT);
+        printf("  ssl:IP[:PORT]         "
+               "SSL PORT (default: %d) at remote IP\n", OFP_SSL_PORT);
 #endif
         printf("  unix:FILE               Unix domain socket named FILE\n");
     }
 
     if (passive) {
         printf("Passive OpenFlow connection methods:\n");
-        printf("  ptcp:[PORT]             "
-               "listen to TCP PORT (default: %d)\n",
+        printf("  ptcp:[PORT][:IP]        "
+               "listen to TCP PORT (default: %d) on IP\n",
                OFP_TCP_PORT);
 #ifdef HAVE_OPENSSL
-        printf("  pssl:[PORT]             "
-               "listen for SSL on PORT (default: %d)\n",
+        printf("  pssl:[PORT][:IP]        "
+               "listen for SSL on PORT (default: %d) on IP\n",
                OFP_SSL_PORT);
 #endif
         printf("  punix:FILE              "
@@ -251,9 +251,34 @@ vconn_get_name(const struct vconn *vconn)
 /* 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. */
 uint32_t
-vconn_get_ip(const struct vconn *vconn) 
+vconn_get_remote_ip(const struct vconn *vconn) 
 {
-    return vconn->ip;
+    return vconn->remote_ip;
+}
+
+/* Returns the transport port of the peer, or 0 if the connection does not 
+ * contain a port or if the port is not yet known. */
+uint16_t
+vconn_get_remote_port(const struct vconn *vconn) 
+{
+    return vconn->remote_port;
+}
+
+/* Returns the IP address used to connect to the peer, or 0 if the 
+ * connection is not an IP-based protocol or if its IP address is not 
+ * yet known. */
+uint32_t
+vconn_get_local_ip(const struct vconn *vconn) 
+{
+    return vconn->local_ip;
+}
+
+/* Returns the transport port used to connect to the peer, or 0 if the 
+ * connection does not contain a port or if the port is not yet known. */
+uint16_t
+vconn_get_local_port(const struct vconn *vconn) 
+{
+    return vconn->local_port;
 }
 
 static void
@@ -339,7 +364,7 @@ vcs_recv_hello(struct vconn *vconn)
 
     if (retval != EAGAIN) {
         vconn->state = VCS_DISCONNECTED;
-        vconn->error = retval;
+        vconn->error = retval == EOF ? ECONNRESET : retval;
     }
 }
 
@@ -433,10 +458,7 @@ vconn_recv(struct vconn *vconn, struct ofpbuf **msgp)
 static int
 do_recv(struct vconn *vconn, struct ofpbuf **msgp)
 {
-    int retval;
-
-again:
-    retval = (vconn->class->recv)(vconn, msgp);
+    int retval = (vconn->class->recv)(vconn, msgp);
     if (!retval) {
         struct ofp_header *oh;
 
@@ -456,20 +478,6 @@ again:
             && oh->type != OFPT_VENDOR)
         {
             if (vconn->version < 0) {
-                if (oh->type == OFPT_PACKET_IN
-                    || oh->type == OFPT_FLOW_EXPIRED
-                    || oh->type == OFPT_PORT_STATUS) {
-                    /* The kernel datapath is stateless and doesn't really
-                     * support version negotiation, so it can end up sending
-                     * these asynchronous message before version negotiation
-                     * is complete.  Just ignore them.
-                     *
-                     * (After we move OFPT_PORT_STATUS messages from the kernel
-                     * into secchan, we won't get those here, since secchan
-                     * does proper version negotiation.) */
-                    ofpbuf_delete(*msgp);
-                    goto again;
-                }
                 VLOG_ERR_RL(&bad_ofmsg_rl,
                             "%s: received OpenFlow message type %"PRIu8" "
                             "before version negotiation complete",
@@ -1382,7 +1390,7 @@ normalize_match(struct ofp_match *m)
 
 void
 vconn_init(struct vconn *vconn, struct vconn_class *class, int connect_status,
-           uint32_t ip, const char *name, bool reconnectable)
+           const char *name, bool reconnectable)
 {
     vconn->class = class;
     vconn->state = (connect_status == EAGAIN ? VCS_CONNECTING
@@ -1391,11 +1399,38 @@ vconn_init(struct vconn *vconn, struct vconn_class *class, int connect_status,
     vconn->error = connect_status;
     vconn->version = -1;
     vconn->min_version = -1;
-    vconn->ip = ip;
+    vconn->remote_ip = 0;
+    vconn->remote_port = 0;
+    vconn->local_ip = 0;
+    vconn->local_port = 0;
     vconn->name = xstrdup(name);
     vconn->reconnectable = reconnectable;
 }
 
+void
+vconn_set_remote_ip(struct vconn *vconn, uint32_t ip)
+{
+    vconn->remote_ip = ip;
+}
+
+void
+vconn_set_remote_port(struct vconn *vconn, uint16_t port)
+{
+    vconn->remote_port = port;
+}
+
+void 
+vconn_set_local_ip(struct vconn *vconn, uint32_t ip)
+{
+    vconn->local_ip = ip;
+}
+
+void 
+vconn_set_local_port(struct vconn *vconn, uint16_t port)
+{
+    vconn->local_port = port;
+}
+
 void
 pvconn_init(struct pvconn *pvconn, struct pvconn_class *class,
             const char *name)