On Tue, Dec 16, 2025 at 12:34 PM Ilya Maximets <[email protected]> wrote:
>
> 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.

Thanks Ilya. I can't think of how this could happen either, because a
pre-vote reply for term T should already be rejected by
raft_receive_term__() in raft_handle_vote_reply() since we're now at term
T+1 for the real vote, but I agree with this patch as a defensive check.

Probably it would be good to add a comment in the code to explain this is a
defensive check for an unknown edge case.

Acked-by: Han Zhou <[email protected]>

>
> 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