[ovs-dev] [PATCH 14/15] jsonrpc: Add support for passive connections.

Ben Pfaff blp at nicira.com
Wed Mar 24 20:18:17 UTC 2010


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              |   61 +++++++++++++++++++++++++++++++++++++++----
 utilities/ovs-vsctl.8.in   |    1 +
 vswitchd/ovs-vswitchd.8.in |    1 +
 3 files changed, 57 insertions(+), 6 deletions(-)

diff --git a/lib/jsonrpc.c b/lib/jsonrpc.c
index 5e05480..f0ac27b 100644
--- a/lib/jsonrpc.c
+++ b/lib/jsonrpc.c
@@ -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());
 }
 
diff --git a/utilities/ovs-vsctl.8.in b/utilities/ovs-vsctl.8.in
index 19ef558..33a808a 100644
--- a/utilities/ovs-vsctl.8.in
+++ b/utilities/ovs-vsctl.8.in
@@ -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"
diff --git a/vswitchd/ovs-vswitchd.8.in b/vswitchd/ovs-vswitchd.8.in
index cbfea13..9c95ed8 100644
--- a/vswitchd/ovs-vswitchd.8.in
+++ b/vswitchd/ovs-vswitchd.8.in
@@ -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
-- 
1.6.6.1





More information about the dev mailing list