From c9f3f37a9d3eeac3740122569ec96c3658b615df Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Wed, 24 Mar 2010 10:14:39 -0700 Subject: [PATCH] jsonrpc: Add support for passive connections. 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 5e054802..f0ac27bc 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 031615ce..d88399da 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 0ec1ecda..b7c99404 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 -- 2.30.2