]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: peers: Add infos in peer structure to know if it is synchronized or not
authorChristopher Faulet <cfaulet@haproxy.com>
Mon, 29 Sep 2025 13:46:25 +0000 (15:46 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Thu, 30 Oct 2025 13:17:49 +0000 (14:17 +0100)
Info about the last update message sent are now saved for each peer. The
shared-table and the update message id are saved. These information are used
when a ack message is received to know if it matches the last update message
sent. When this matches, we are sure the peer as received all updates sent
and is synchronized. This information is saved thanks to the flag
PEER_F_SYNCHED.

So, at any time, we know if a peer is synchronized or not.

include/haproxy/peers-t.h
src/cfgparse.c
src/peers.c

index 19619d0a1ae8a90ccc167e23085519dc52e3de2c..ee48d73da4948d303166f38a172bf86edf965a87 100644 (file)
@@ -106,7 +106,8 @@ static forceinline char *peers_show_flags(char *buf, size_t len, const char *del
 #define PEER_F_ALIVE                0x00000020 /* Used to flag a peer a alive. */
 #define PEER_F_HEARTBEAT            0x00000040 /* Heartbeat message to send. */
 #define PEER_F_DWNGRD               0x00000080 /* When this flag is enabled, we must downgrade the supported version announced during peer sessions. */
-/* unused 0x00000100..0x00080000 */
+#define PEER_F_SYNCHED              0x00000100 /* Remote peer is synchronized with the local peer */
+/* unused 0x00000200..0x00080000 */
 #define PEER_F_DBG_RESYNC_REQUESTED 0x00100000 /* A resnyc was explicitly requested at least once (for debugging purpose) */
 
 #define PEER_TEACH_FLAGS            (PEER_F_TEACH_PROCESS|PEER_F_TEACH_FINISHED)
@@ -124,7 +125,7 @@ static forceinline char *peer_show_flags(char *buf, size_t len, const char *deli
        _(PEER_F_TEACH_PROCESS, _(PEER_F_TEACH_FINISHED, _(PEER_F_LOCAL_TEACH_COMPLETE,
         _(PEER_F_LEARN_NOTUP2DATE, _(PEER_F_WAIT_SYNCTASK_ACK,
         _(PEER_F_ALIVE, _(PEER_F_HEARTBEAT, _(PEER_F_DWNGRD,
-       _(PEER_F_DBG_RESYNC_REQUESTED)))))))));
+       _(PEER_F_SYNCHED ,_(PEER_F_DBG_RESYNC_REQUESTED))))))))));
        /* epilogue */
        _(~0U);
        return buf;
@@ -174,6 +175,10 @@ struct peer {
        struct shared_table *last_local_table; /* Last table that emit update messages during a teach process */
        struct shared_table *stop_local_table; /* last evaluated table, used as restart point for the next teach process */
        struct shared_table *tables;
+       struct {
+               struct shared_table *table;
+               unsigned int id;
+       } last;
        struct server *srv;
        struct dcache *dcache;        /* dictionary cache */
        struct peers *peers;          /* associated peer section */
index 5a7ec7405006b79111659207df9ff612677282eb..f411d6ea1b4713e8d531806530269fc6dd303596 100644 (file)
@@ -636,6 +636,7 @@ static struct peer *cfg_peers_add_peer(struct peers *peers,
        /* the peers are linked backwards first */
        peers->count++;
        p->peers = peers;
+       p->flags |= PEER_F_SYNCHED;
        p->next = peers->remote;
        peers->remote = p;
        p->conf.file = strdup(file);
index 07a9797d1e69278ac6a9995a40b5c29ee414ff98..06500a9b67ec0c31b780893d0629343835d5a6b1 100644 (file)
@@ -1693,6 +1693,9 @@ int peer_send_teachmsgs(struct appctx *appctx, struct peer *p,
                        break;
 
                st->last_pushed = updateid;
+               p->last.table = st;
+               p->last.id = updateid;
+               p->flags &= ~PEER_F_SYNCHED;
 
                /* identifier may not needed in next update message */
                new_pushed = 0;
@@ -2236,6 +2239,10 @@ static inline int peer_treat_ackmsg(struct appctx *appctx, struct peer *p,
                        break;
                }
        }
+       if (table_id == p->last.table->local_id && update == p->last.id) {
+               TRACE_STATE("Peer synched again", PEERS_EV_SESS_IO|PEERS_EV_RX_MSG|PEERS_EV_PROTO_ACK, appctx, p);
+               p->flags |= PEER_F_SYNCHED;
+       }
 
   end:
        TRACE_LEAVE(PEERS_EV_SESS_IO|PEERS_EV_RX_MSG|PEERS_EV_PROTO_ACK, appctx, p, st);
@@ -2618,6 +2625,7 @@ static inline int peer_treat_awaited_msg(struct appctx *appctx, struct peer *pee
                                TRACE_STATE("process stopping, stop any resync", PEERS_EV_SESS_IO|PEERS_EV_RX_MSG|PEERS_EV_PROTO_CTRL, appctx, peer);
                                return 0;
                        }
+                       peer->flags |= PEER_F_SYNCHED;
                        for (st = peer->tables; st; st = st->next) {
                                st->update = st->last_pushed = st->teaching_origin;
                                st->flags = 0;
@@ -2964,8 +2972,10 @@ static inline void init_connected_peer(struct peer *peer, struct peers *peers)
                 * Here a partial fix consist to set st->update at
                 * the max past value.
                 */
-               if ((int)(st->table->localupdate - st->update) < 0)
+               if (!(peer->flags & PEER_F_SYNCHED) || (int)(st->table->localupdate - st->update) < 0) {
                        st->update = st->table->localupdate + (2147483648U);
+                       peer->flags &= ~PEER_F_SYNCHED;
+               }
                st->teaching_origin = st->last_pushed = st->update;
                st->flags = 0;
 
@@ -2986,6 +2996,7 @@ static inline void init_connected_peer(struct peer *peer, struct peers *peers)
                 * on the frontend side), flag it to start to teach lesson.
                 */
                 peer->flags |= PEER_F_TEACH_PROCESS;
+               peer->flags &= ~PEER_F_SYNCHED;
                TRACE_STATE("peer elected to teach lesson to lacal peer", PEERS_EV_SESS_NEW, NULL, peer);
        }