jsonrpc: Add support for passive connections.
authorBen Pfaff <blp@nicira.com>
Wed, 24 Mar 2010 17:14:39 +0000 (10:14 -0700)
committerBen Pfaff <blp@nicira.com>
Mon, 12 Apr 2010 18:03:32 +0000 (11:03 -0700)
This allows ovs-vsctl to work as a simple Open vSwitch "manager" if the
XenServer host is configured to connect to it remotely.

lib/jsonrpc.c
utilities/ovs-vsctl.8.in
vswitchd/ovs-vswitchd.8.in

index 5e054802f785b2af53a61c31e8da0c32bdfac996..f0ac27bc94045d4f04623587e764a50a7521b034 100644 (file)
@@ -637,12 +637,20 @@ struct jsonrpc_session {
     struct reconnect *reconnect;
     struct jsonrpc *rpc;
     struct stream *stream;
+    struct pstream *pstream;
     unsigned int seqno;
 };
 
-/* Creates and returns a jsonrpc_session that connects and reconnects, with
- * back-off, to 'name', which should be a string acceptable to
- * stream_open(). */
+/* Creates and returns a jsonrpc_session to 'name', which should be a string
+ * acceptable to stream_open() or pstream_open().
+ *
+ * If 'name' is an active connection method, e.g. "tcp:127.1.2.3", the new
+ * jsonrpc_session connects and reconnects, with back-off, to 'name'.
+ *
+ * If 'name' is a passive connection method, e.g. "ptcp:", the new
+ * jsonrpc_session listens for connections to 'name'.  It maintains at most one
+ * connection at any given time.  Any new connection causes the previous one
+ * (if any) to be dropped. */
 struct jsonrpc_session *
 jsonrpc_session_open(const char *name)
 {
@@ -654,8 +662,13 @@ jsonrpc_session_open(const char *name)
     reconnect_enable(s->reconnect, time_msec());
     s->rpc = NULL;
     s->stream = NULL;
+    s->pstream = NULL;
     s->seqno = 0;
 
+    if (!pstream_verify_name(name)) {
+        reconnect_set_passive(s->reconnect, true, time_msec());
+    }
+
     return s;
 }
 
@@ -673,6 +686,7 @@ jsonrpc_session_open_unreliably(struct jsonrpc *jsonrpc)
     reconnect_connected(s->reconnect, time_msec());
     s->rpc = jsonrpc;
     s->stream = NULL;
+    s->pstream = NULL;
     s->seqno = 0;
 
     return s;
@@ -685,6 +699,7 @@ jsonrpc_session_close(struct jsonrpc_session *s)
         jsonrpc_close(s->rpc);
         reconnect_destroy(s->reconnect);
         stream_close(s->stream);
+        pstream_close(s->pstream);
         free(s);
     }
 }
@@ -707,14 +722,24 @@ jsonrpc_session_disconnect(struct jsonrpc_session *s)
 static void
 jsonrpc_session_connect(struct jsonrpc_session *s)
 {
+    const char *name = reconnect_get_name(s->reconnect);
     int error;
 
     jsonrpc_session_disconnect(s);
-    error = stream_open(reconnect_get_name(s->reconnect), &s->stream);
+    if (!reconnect_is_passive(s->reconnect)) {
+        error = stream_open(name, &s->stream);
+        if (!error) {
+            reconnect_connecting(s->reconnect, time_msec());
+        }
+    } else {
+        error = s->pstream ? 0 : pstream_open(name, &s->pstream);
+        if (!error) {
+            reconnect_listening(s->reconnect, time_msec());
+        }
+    }
+
     if (error) {
         reconnect_connect_failed(s->reconnect, time_msec(), error);
-    } else {
-        reconnect_connecting(s->reconnect, time_msec());
     }
     s->seqno++;
 }
@@ -722,6 +747,27 @@ jsonrpc_session_connect(struct jsonrpc_session *s)
 void
 jsonrpc_session_run(struct jsonrpc_session *s)
 {
+    if (s->pstream) {
+        struct stream *stream;
+        int error;
+
+        error = pstream_accept(s->pstream, &stream);
+        if (!error) {
+            if (s->rpc || s->stream) {
+                VLOG_INFO_RL(&rl,
+                             "%s: new connection replacing active connection",
+                             reconnect_get_name(s->reconnect));
+                jsonrpc_session_disconnect(s);
+            }
+            reconnect_connected(s->reconnect, time_msec());
+            s->rpc = jsonrpc_open(stream);
+        } else if (error != EAGAIN) {
+            reconnect_listen_error(s->reconnect, time_msec(), error);
+            pstream_close(s->pstream);
+            s->pstream = NULL;
+        }
+    }
+
     if (s->rpc) {
         int error;
 
@@ -781,6 +827,9 @@ jsonrpc_session_wait(struct jsonrpc_session *s)
         stream_run_wait(s->stream);
         stream_connect_wait(s->stream);
     }
+    if (s->pstream) {
+        pstream_wait(s->pstream);
+    }
     reconnect_wait(s->reconnect, time_msec());
 }
 
index 031615cee470c938561a0e6dd1f39f6a8e9a1614..d88399da0fae2bdae915c376a480eafcafa2b01a 100644 (file)
@@ -83,6 +83,7 @@ contacts to query or modify configuration.  The default is
 following forms:
 .RS
 .so ovsdb/remote-active.man
+.so ovsdb/remote-passive.man
 .RE
 .
 .IP "\fB\-\-no\-wait\fR"
index 0ec1ecda05cb4cb2dc17b76f192db2c6e40447b2..b7c99404c73fff51e6fcf5e8102fa7d553acf23e 100644 (file)
@@ -22,6 +22,7 @@ The mandatory \fIdatabase\fR argument specifies the
 \fBovsdb\-server\fR from which \fBovs\-vswitchd\fR's configuration
 should be retrieved.  It takes one of the following forms:
 .so ovsdb/remote-active.man
+.so ovsdb/remote-passive.man
 .PP
 \fBovs\-vswitchd\fR retrieves its configuration from \fIdatabase\fR at
 startup.  It sets up Open vSwitch datapaths and then operates