]> 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>
Tue, 21 Oct 2025 13:03:24 +0000 (15:03 +0200)
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 a36e88983d2b894929c20e0ed72b1afffb6e9d61..edaaa70e6d61ee151bbf241ab5dfb73f333e9171 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 aadc6af5d1e8c956f32c23115728b3e16555ec29..30783f9f841ae32ebbcea0fadd854bd9be4ef0be 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);
        }