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
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 *
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;
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));
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. */
{
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;
+}
\f
/* Tries to send a packet from 'rc''s send buffer. Returns 0 if successful,
* otherwise a positive errno value. */
}
rc->backoff_deadline = now + rc->backoff;
state_transition(rc, S_BACKOFF);
+ if (now - rc->last_connected > 60) {
+ question_connectivity(rc);
+ }
} else {
rconn_disconnect(rc);
}
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;
+ }
+}