]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: stick-tables: mark the seen stksess with a flag "seen"
authorWilly Tarreau <w@1wt.eu>
Tue, 2 Apr 2024 16:49:53 +0000 (18:49 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 3 Apr 2024 15:34:47 +0000 (17:34 +0200)
Right now we're taking the stick-tables update lock for reads just for
the sake of checking if the update index is past it or not. That's
costly because even taking the read lock is sufficient to provoke a
cache line write, while when under load or attack it's frequent that
the update has not yet been propagated and wouldn't require anything.

This commit brings a new field to the stksess, "seen", which is zeroed
when the entry is updated, and set to one as soon as at least one peer
starts to consult it. This way it will reflect that the entry must be
updated again so that this peer can see it. Otherwise no update will
be necessary. For now the flag is only set/reset but not exploited.
A great care is taken to avoid writes whenever possible.

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

index e170fcdea0e383800839267b0dcce0b77f97e72f..6c953ef09c5a4f63d555b397655c61ecab7af7b2 100644 (file)
@@ -147,7 +147,8 @@ struct stksess {
        unsigned int expire;      /* session expiration date */
        unsigned int ref_cnt;     /* reference count, can only purge when zero */
        __decl_thread(HA_RWLOCK_T lock); /* lock related to the table entry */
-       int shard;                /* shard */
+       int shard;                /* shard number used by peers */
+       int seen;                 /* 0 only when no peer has seen this entry yet */
        struct eb32_node exp;     /* ebtree node used to hold the session in expiration tree */
        struct eb32_node upd;     /* ebtree node used to hold the update sequence tree */
        struct ebmb_node key;     /* ebtree node used to hold the session in table */
index 628b9358c61bbde2a46ba85dc3d722aac34d4c11..1182c2117a088047f85e2a2854442a810f3aab3a 100644 (file)
@@ -1478,6 +1478,7 @@ static inline int peer_send_error_protomsg(struct appctx *appctx)
 static inline struct stksess *peer_teach_process_stksess_lookup(struct shared_table *st)
 {
        struct eb32_node *eb;
+       struct stksess *ret;
 
        eb = eb32_lookup_ge(&st->table->updates, st->last_pushed+1);
        if (!eb) {
@@ -1497,7 +1498,10 @@ static inline struct stksess *peer_teach_process_stksess_lookup(struct shared_ta
                return NULL;
        }
 
-       return eb32_entry(eb, struct stksess, upd);
+       ret = eb32_entry(eb, struct stksess, upd);
+       if (!_HA_ATOMIC_LOAD(&ret->seen))
+               _HA_ATOMIC_STORE(&ret->seen, 1);
+       return ret;
 }
 
 /*
@@ -1507,6 +1511,7 @@ static inline struct stksess *peer_teach_process_stksess_lookup(struct shared_ta
 static inline struct stksess *peer_teach_stage1_stksess_lookup(struct shared_table *st)
 {
        struct eb32_node *eb;
+       struct stksess *ret;
 
        eb = eb32_lookup_ge(&st->table->updates, st->last_pushed+1);
        if (!eb) {
@@ -1517,7 +1522,10 @@ static inline struct stksess *peer_teach_stage1_stksess_lookup(struct shared_tab
                return NULL;
        }
 
-       return eb32_entry(eb, struct stksess, upd);
+       ret = eb32_entry(eb, struct stksess, upd);
+       if (!_HA_ATOMIC_LOAD(&ret->seen))
+               _HA_ATOMIC_STORE(&ret->seen, 1);
+       return ret;
 }
 
 /*
@@ -1527,6 +1535,7 @@ static inline struct stksess *peer_teach_stage1_stksess_lookup(struct shared_tab
 static inline struct stksess *peer_teach_stage2_stksess_lookup(struct shared_table *st)
 {
        struct eb32_node *eb;
+       struct stksess *ret;
 
        eb = eb32_lookup_ge(&st->table->updates, st->last_pushed+1);
        if (!eb || eb->key > st->teaching_origin) {
@@ -1534,7 +1543,10 @@ static inline struct stksess *peer_teach_stage2_stksess_lookup(struct shared_tab
                return NULL;
        }
 
-       return eb32_entry(eb, struct stksess, upd);
+       ret = eb32_entry(eb, struct stksess, upd);
+       if (!_HA_ATOMIC_LOAD(&ret->seen))
+               _HA_ATOMIC_STORE(&ret->seen, 1);
+       return ret;
 }
 
 /*
index 3dbf0025983c079413a3710b221d27eabeed8965..a1f1efa180a7927b145f984a7fe5d3e9dc898ed7 100644 (file)
@@ -215,6 +215,7 @@ static struct stksess *__stksess_init(struct stktable *t, struct stksess * ts)
        memset((void *)ts - t->data_size, 0, t->data_size);
        ts->ref_cnt = 0;
        ts->shard = 0;
+       ts->seen = 0;
        ts->key.node.leaf_p = NULL;
        ts->exp.node.leaf_p = NULL;
        ts->upd.node.leaf_p = NULL;
@@ -523,6 +524,7 @@ void stktable_touch_with_exp(struct stktable *t, struct stksess *ts, int local,
 
                                /* here we're write-locked */
 
+                               ts->seen = 0;
                                ts->upd.key = ++t->update;
                                t->localupdate = t->update;
                                eb32_delete(&ts->upd);
@@ -552,6 +554,7 @@ void stktable_touch_with_exp(struct stktable *t, struct stksess *ts, int local,
 
                                /* here we're write-locked */
 
+                               ts->seen = 0;
                                ts->upd.key= (++t->update)+(2147483648U);
                                eb = eb32_insert(&t->updates, &ts->upd);
                                if (eb != &ts->upd) {