From c57a8d1089daa5b48930eba62cd4dc31487cb964 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Mon, 14 Jul 2008 13:32:13 -0700 Subject: [PATCH] rconn: Add questionability. --- include/rconn.h | 1 + lib/rconn.c | 46 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/include/rconn.h b/include/rconn.h index 1872aa9f..0e9f4a7a 100644 --- a/include/rconn.h +++ b/include/rconn.h @@ -78,6 +78,7 @@ const char *rconn_get_name(const struct rconn *); bool rconn_is_alive(const struct rconn *); bool rconn_is_connected(const struct rconn *); int rconn_disconnected_duration(const struct rconn *); +bool rconn_is_connectivity_questionable(struct rconn *); uint32_t rconn_get_ip(const struct rconn *); diff --git a/lib/rconn.c b/lib/rconn.c index bb7d3fe1..7f5a1dcf 100644 --- a/lib/rconn.c +++ b/lib/rconn.c @@ -93,6 +93,16 @@ struct rconn { unsigned int packets_sent; + /* If we can't connect to the peer, it could be for any number of reasons. + * Usually, one would assume it is because the peer is not running or + * because the network is partitioned. But it could also be because the + * network topology has changed, in which case the upper layer will need to + * reassess it (in particular, obtain a new IP address via DHCP and find + * the new location of the controller). We set this flag when we suspect + * that this could be the case. */ + bool questionable_connectivity; + time_t last_questioned; + /* Throughout this file, "probe" is shorthand for "inactivity probe". * When nothing has been received from the peer for a while, we send out * an echo request as an inactivity probe packet. We should receive back @@ -108,6 +118,7 @@ static void state_transition(struct rconn *, enum state); static int try_send(struct rconn *); static void reconnect(struct rconn *); static void disconnect(struct rconn *, int error); +static void question_connectivity(struct rconn *); /* Creates a new rconn, connects it (reliably) to 'name', and returns it. */ struct rconn * @@ -168,6 +179,9 @@ rconn_create(int txq_limit, int probe_interval, int max_backoff) rc->packets_sent = 0; + rc->questionable_connectivity = false; + rc->last_questioned = time(0); + rc->probe_interval = probe_interval ? MAX(5, probe_interval) : 0; return rc; @@ -311,6 +325,7 @@ static void run_IDLE(struct rconn *rc) { if (timeout(rc, rc->probe_interval)) { + question_connectivity(rc); VLOG_ERR("%s: no response to inactivity probe after %u " "seconds, disconnecting", rc->name, elapsed_in_this_state(rc)); @@ -463,7 +478,7 @@ rconn_get_name(const struct rconn *rc) bool rconn_is_alive(const struct rconn *rconn) { - return rconn->reliable || rconn->vconn; + return rconn->state != S_VOID; } /* Returns true if 'rconn' is connected, false otherwise. */ @@ -488,6 +503,22 @@ rconn_get_ip(const struct rconn *rconn) { return rconn->vconn ? vconn_get_ip(rconn->vconn) : 0; } + +/* If 'rconn' can't connect to the peer, it could be for any number of reasons. + * Usually, one would assume it is because the peer is not running or because + * the network is partitioned. But it could also be because the network + * topology has changed, in which case the upper layer will need to reassess it + * (in particular, obtain a new IP address via DHCP and find the new location + * of the controller). When this appears that this might be the case, this + * function returns true. It also clears the questionability flag and prevents + * it from being set again for some time. */ +bool +rconn_is_connectivity_questionable(struct rconn *rconn) +{ + bool questionable = rconn->questionable_connectivity; + rconn->questionable_connectivity = false; + return questionable; +} /* Tries to send a packet from 'rc''s send buffer. Returns 0 if successful, * otherwise a positive errno value. */ @@ -542,6 +573,9 @@ disconnect(struct rconn *rc, int error) } rc->backoff_deadline = now + rc->backoff; state_transition(rc, S_BACKOFF); + if (now - rc->last_connected > 60) { + question_connectivity(rc); + } } else { rconn_disconnect(rc); } @@ -580,3 +614,13 @@ sat_mul(unsigned int x, unsigned int y) assert(y); return x <= UINT_MAX / y ? x * y : UINT_MAX; } + +static void +question_connectivity(struct rconn *rc) +{ + time_t now = time(0); + if (now - rc->last_questioned > 60) { + rc->questionable_connectivity = true; + rc->last_questioned = now; + } +} -- 2.30.2