I am not sure how we could receive a pre-vote reply for a term of the
actual vote, but if somehow it does happen, we must not accept it, as
the same server can vote differently in the pre-vote and the real vote
and so we may end up with more than one elected leader.

Ignore the pre-vote reply during the actual elections and warn the user
if this ever happens, so we could investigate further.

Found while investigating a report with a cluster with two elected
leaders.  It may not be the cause of the issue and, as stated above,
I'm not even sure if receiving a pre-vote for the actual election term
is possible.  But it's better to cover this case explicitly, as the
flag in the reply is not used today.

Fixes: 85634fd58004 ("ovsdb: raft: Support pre-vote mechanism to deal with 
disruptive server.")
Signed-off-by: Ilya Maximets <[email protected]>
---
 ovsdb/raft.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/ovsdb/raft.c b/ovsdb/raft.c
index 32349c8af..1fc8a5c34 100644
--- a/ovsdb/raft.c
+++ b/ovsdb/raft.c
@@ -1857,11 +1857,18 @@ raft_set_term(struct raft *raft, uint64_t term, const 
struct uuid *vote)
 
 static bool
 raft_accept_vote(struct raft *raft, struct raft_server *s,
-                 const struct uuid *vote)
+                 const struct uuid *vote, bool is_prevote)
 {
     if (uuid_equals(&s->vote, vote)) {
         return false;
     }
+    if (raft->prevote_passed && is_prevote) {
+        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
+        VLOG_WARN_RL(&rl, "ignoring pre-vote reply from server %s "
+                          "during the actual election on term %"PRIu64".",
+                     s->nickname, raft->term);
+        return false;
+    }
     if (!uuid_is_zero(&s->vote)) {
         static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
         char buf1[SID_LEN + 1];
@@ -1959,7 +1966,7 @@ raft_start_election(struct raft *raft, bool is_prevote,
     }
 
     /* Vote for ourselves. */
-    if (raft_accept_vote(raft, me, &raft->sid)) {
+    if (raft_accept_vote(raft, me, &raft->sid, is_prevote)) {
         /* We just started vote, so it shouldn't be accepted yet unless this is
          * a one-node cluster. In such case we don't do pre-vote, and become
          * leader immediately. */
@@ -3985,7 +3992,7 @@ raft_handle_vote_reply(struct raft *raft,
 
     struct raft_server *s = raft_find_peer(raft, &rpy->common.sid);
     if (s) {
-        if (raft_accept_vote(raft, s, &rpy->vote)) {
+        if (raft_accept_vote(raft, s, &rpy->vote, rpy->is_prevote)) {
             if (raft->prevote_passed) {
                 raft_become_leader(raft);
             } else {
-- 
2.52.0

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to