[ovs-dev] [PATCH] rconn: Speed up in-band control connections, by caching the remote address.
Justin Pettit
jpettit at nicira.com
Wed Sep 2 21:54:08 UTC 2009
Looks good. Thanks for tracking this down!
--Justin
On Sep 2, 2009, at 12:53 PM, Ben Pfaff <blp at nicira.com> wrote:
> In-band control needs to know the IP and port of the controller, so
> that
> it can set up the correct flows to talk to that controller. Until
> now,
> the rconn code has only made this available when a connection was
> actually
> in progress. This means that, say, ARP packets will not be allowed
> through
> when the rconn backs off. The same is true of packets sent by
> switches
> that access the controller through this one.
>
> This commit makes the rconn cache the remote IP and port and local IP
> across connection attempts, improving the situation. In particular,
> it
> reduces the overall amount of time that it takes to connect in my own
> simple test case from over 10 seconds to about 2 seconds.
> ---
> lib/rconn.c | 52 ++++++++++++++++++++++++++++++++++++++
> +-------------
> 1 files changed, 39 insertions(+), 13 deletions(-)
>
> diff --git a/lib/rconn.c b/lib/rconn.c
> index 09c0e9d..be030d4 100644
> --- a/lib/rconn.c
> +++ b/lib/rconn.c
> @@ -111,6 +111,18 @@ struct rconn {
> * a response. */
> int probe_interval; /* Secs of inactivity before sending
> probe. */
>
> + /* When we create a vconn we obtain these values, to save them
> past the end
> + * of the vconn's lifetime. Otherwise, in-band control will
> only allow
> + * traffic when a vconn is actually open, but it is nice to
> allow ARP to
> + * complete even between connection attempts, and it is also
> polite to
> + * allow traffic from other switches to go through to the
> controller
> + * whether or not we are connected.
> + *
> + * We don't cache the local port, because that changes from one
> connection
> + * attempt to the next. */
> + uint32_t local_ip, remote_ip;
> + uint16_t remote_port;
> +
> /* Messages sent or received are copied to the monitor
> connections. */
> #define MAX_MONITORS 8
> struct vconn *monitors[8];
> @@ -121,6 +133,7 @@ static unsigned int elapsed_in_this_state(const
> struct rconn *);
> static unsigned int timeout(const struct rconn *);
> static bool timed_out(const struct rconn *);
> static void state_transition(struct rconn *, enum state);
> +static void set_vconn_name(struct rconn *, const char *name);
> static int try_send(struct rconn *);
> static int reconnect(struct rconn *);
> static void disconnect(struct rconn *, int error);
> @@ -236,8 +249,7 @@ int
> rconn_connect(struct rconn *rc, const char *name)
> {
> rconn_disconnect(rc);
> - free(rc->name);
> - rc->name = xstrdup(name);
> + set_vconn_name(rc, name);
> rc->reliable = true;
> return reconnect(rc);
> }
> @@ -248,8 +260,7 @@ rconn_connect_unreliably(struct rconn *rc,
> {
> assert(vconn != NULL);
> rconn_disconnect(rc);
> - free(rc->name);
> - rc->name = xstrdup(name);
> + set_vconn_name(rc, name);
> rc->reliable = false;
> rc->vconn = vconn;
> rc->last_connected = time_now();
> @@ -273,8 +284,7 @@ rconn_disconnect(struct rconn *rc)
> vconn_close(rc->vconn);
> rc->vconn = NULL;
> }
> - free(rc->name);
> - rc->name = xstrdup("void");
> + set_vconn_name(rc, "void");
> rc->reliable = false;
>
> rc->backoff = 0;
> @@ -323,6 +333,9 @@ reconnect(struct rconn *rc)
> rc->n_attempted_connections++;
> retval = vconn_open(rc->name, OFP_VERSION, &rc->vconn);
> if (!retval) {
> + rc->remote_ip = vconn_get_remote_ip(rc->vconn);
> + rc->local_ip = vconn_get_local_ip(rc->vconn);
> + rc->remote_port = vconn_get_remote_port(rc->vconn);
> rc->backoff_deadline = time_now() + rc->backoff;
> state_transition(rc, S_CONNECTING);
> } else {
> @@ -635,20 +648,20 @@ rconn_failure_duration(const struct rconn
> *rconn)
> return rconn_is_connected(rconn) ? 0 : time_now() - rconn-
> >last_admitted;
> }
>
> -/* 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 known. */
> +/* Returns the IP address of the peer, or 0 if the peer's IP
> address is not
> + * known. */
> uint32_t
> rconn_get_remote_ip(const struct rconn *rconn)
> {
> - return rconn->vconn ? vconn_get_remote_ip(rconn->vconn) : 0;
> + return rconn->remote_ip;
> }
>
> -/* Returns the transport port of the peer, or 0 if the peer does not
> - * contain a port or if the port is not known. */
> +/* Returns the transport port of the peer, or 0 if the peer's port
> is not
> + * known. */
> uint16_t
> rconn_get_remote_port(const struct rconn *rconn)
> {
> - return rconn->vconn ? vconn_get_remote_port(rconn->vconn) : 0;
> + return rconn->remote_port;
> }
>
> /* Returns the IP address used to connect to the peer, or 0 if the
> @@ -657,7 +670,7 @@ rconn_get_remote_port(const struct rconn *rconn)
> uint32_t
> rconn_get_local_ip(const struct rconn *rconn)
> {
> - return rconn->vconn ? vconn_get_local_ip(rconn->vconn) : 0;
> + return rconn->local_ip;
> }
>
> /* Returns the transport port used to connect to the peer, or 0 if the
> @@ -805,6 +818,19 @@ rconn_packet_counter_dec(struct
> rconn_packet_counter *c)
> }
> }
>
> +/* Set the name of the remote vconn to 'name' and clear out the
> cached IP
> + * address and port information, since changing the name also
> likely changes
> + * these values. */
> +static void
> +set_vconn_name(struct rconn *rc, const char *name)
> +{
> + free(rc->name);
> + rc->name = xstrdup(name);
> + rc->local_ip = 0;
> + rc->remote_ip = 0;
> + rc->remote_port = 0;
> +}
> +
> /* Tries to send a packet from 'rc''s send buffer. Returns 0 if
> successful,
> * otherwise a positive errno value. */
> static int
> --
> 1.6.3.3
>
>
> _______________________________________________
> dev mailing list
> dev at openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev_openvswitch.org
More information about the dev
mailing list