summaryrefslogtreecommitdiff
path: root/lib/rconn.c
diff options
context:
space:
mode:
authorBen Pfaff <blp@ovn.org>2016-12-23 09:23:43 -0800
committerBen Pfaff <blp@ovn.org>2016-12-23 13:23:13 -0800
commita203ce69c96e8a38c71113973caf64a22003616f (patch)
treebdd9f8ba6f7cac8100afa27f0893de4bf82cf884 /lib/rconn.c
parent8415fe322c21248dc5e15d50883e74dd563e2bcf (diff)
downloadopenvswitch-a203ce69c96e8a38c71113973caf64a22003616f.tar.gz
rconn: Avoid abort for ill-behaved remote.
If an rconn peer fails to send a hello message, the version number doesn't get set. Later, if the peer delays long enough, the rconn attempts to send an echo request but assert-fails instead because it doesn't know what version to use. This fixes the problem. To reproduce this problem: make sandbox ovs-vsctl add-br br0 ovs-vsctl set-controller br0 ptcp:12345 nc 127.0.0.1 12345 and wait 10 seconds for ovs-vswitchd to die. (Then exit the sandbox.) Reported-by: 张东亚 <fortitude.zhang@gmail.com> Signed-off-by: Ben Pfaff <blp@ovn.org> Acked-by: Justin Pettit <jpettit@ovn.org>
Diffstat (limited to 'lib/rconn.c')
-rw-r--r--lib/rconn.c16
1 files changed, 10 insertions, 6 deletions
diff --git a/lib/rconn.c b/lib/rconn.c
index 0c1812a27..8a2986403 100644
--- a/lib/rconn.c
+++ b/lib/rconn.c
@@ -558,19 +558,23 @@ run_ACTIVE(struct rconn *rc)
{
if (timed_out(rc)) {
unsigned int base = MAX(rc->last_activity, rc->state_entered);
- int version;
-
VLOG_DBG("%s: idle %u seconds, sending inactivity probe",
rc->name, (unsigned int) (time_now() - base));
- version = rconn_get_version__(rc);
- ovs_assert(version >= 0 && version <= 0xff);
-
/* Ordering is important here: rconn_send() can transition to BACKOFF,
* and we don't want to transition back to IDLE if so, because then we
* can end up queuing a packet with vconn == NULL and then *boom*. */
state_transition(rc, S_IDLE);
- rconn_send__(rc, make_echo_request(version), NULL);
+
+ /* Send an echo request if we can. (If version negotiation is not
+ * complete, that is, if we did not yet receive a "hello" message from
+ * the peer, we do not know the version to use, so we don't send
+ * anything.) */
+ int version = rconn_get_version__(rc);
+ if (version >= 0 && version <= 0xff) {
+ rconn_send__(rc, make_echo_request(version), NULL);
+ }
+
return;
}