diff mbox series

[ovs-dev,v5,06/13] conntrack: Add per zone lock.

Message ID d6c4ccc0d27fb18f1373debaf65bcafea670cf16.1788272618.git.felix.huettner@digits.schwarz
State New
Delegated to: aaron conole
Headers show
Series Multiple conntrack performance improvements. | expand

Checks

Context Check Description
ovsrobot/apply-robot success apply and check: success
ovsrobot/github-robot-_Build_and_Test success github build: passed
ovsrobot/github-robot-_FreeBSD_Build_and_Test success github build: passed

Commit Message

Felix Huettner Sept. 1, 2026, 2:24 p.m. UTC
This lock will in the future be the only thing that is needed to insert
or remove connections. For now it is there additionally to ct_lock which
is still needed for the rculists.

This will increase memory usage by roughly 3MB however it is necessary
to make the zones more independent and thereby allow for performance
improvements.

Signed-off-by: Felix Huettner <felix.huettner@digits.schwarz>
---

Notes:
    v4->v5: reword commit message

 lib/conntrack-private.h |  1 +
 lib/conntrack.c         | 19 ++++++++++++++++---
 2 files changed, 17 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/lib/conntrack-private.h b/lib/conntrack-private.h
index a0aaf5bc3..3409b91e2 100644
--- a/lib/conntrack-private.h
+++ b/lib/conntrack-private.h
@@ -208,6 +208,7 @@  struct conntrack_zone_limit {
 };
 
 struct conntrack_zone {
+    struct ovs_mutex zone_lock; /* Protects the following fields. */
     struct cmap conns;
 };
 
diff --git a/lib/conntrack.c b/lib/conntrack.c
index f313eaa15..f82258775 100644
--- a/lib/conntrack.c
+++ b/lib/conntrack.c
@@ -261,6 +261,7 @@  struct conntrack *
 conntrack_init(void)
 {
     static struct ovsthread_once setup_l4_once = OVSTHREAD_ONCE_INITIALIZER;
+    struct conntrack_zone *cz;
     struct conntrack *ct = xzalloc(sizeof *ct);
 
     /* This value can be used during init (e.g. timeout_policy_init()),
@@ -277,7 +278,9 @@  conntrack_init(void)
     ovs_mutex_init_adaptive(&ct->ct_lock);
     ovs_mutex_lock(&ct->ct_lock);
     for (unsigned i = 0; i < ARRAY_SIZE(ct->zones); i++) {
-        cmap_init(&ct->zones[i].conns);
+        cz = zone_lookup(ct, i);
+        ovs_mutex_init_adaptive(&cz->zone_lock);
+        cmap_init(&cz->conns);
     }
     for (unsigned i = 0; i < ARRAY_SIZE(ct->exp_lists); i++) {
         rculist_init(&ct->exp_lists[i]);
@@ -584,6 +587,7 @@  conn_clean__(struct conntrack *ct, struct conn *conn)
     cz = zone_lookup(ct, fwd_zone);
 
     hash = conn_key_hash(&conn->key_node[CT_DIR_FWD].key, ct->hash_basis);
+    ovs_mutex_lock(&cz->zone_lock);
     cmap_remove(&cz->conns,
                 &conn->key_node[CT_DIR_FWD].cm_node, hash);
 
@@ -596,6 +600,7 @@  conn_clean__(struct conntrack *ct, struct conn *conn)
     }
 
     rculist_remove(&conn->node);
+    ovs_mutex_unlock(&cz->zone_lock);
 }
 
 /* Also removes the associated nat 'conn' from the lookup
@@ -634,6 +639,7 @@  conn_force_expire(struct conn *conn)
 void
 conntrack_destroy(struct conntrack *ct)
 {
+    struct conntrack_zone *cz;
     struct conn *conn;
 
     latch_set(&ct->clean_thread_exit);
@@ -664,7 +670,11 @@  conntrack_destroy(struct conntrack *ct)
 
     ovs_mutex_lock(&ct->ct_lock);
     for (unsigned i = 0; i < ARRAY_SIZE(ct->zones); i++) {
-        cmap_destroy(&ct->zones[i].conns);
+        cz = zone_lookup(ct, i);
+        ovs_mutex_lock(&cz->zone_lock);
+        cmap_destroy(&cz->conns);
+        ovs_mutex_unlock(&cz->zone_lock);
+        ovs_mutex_destroy(&cz->zone_lock);
     }
     cmap_destroy(&ct->zone_limits);
     cmap_destroy(&ct->timeout_policies);
@@ -1054,7 +1064,7 @@  conn_insert(struct conntrack *ct, struct conntrack_zone *cz,
             const struct nat_action_info_t *nat_action_info,
             const char *helper, const struct alg_exp_node *alg_exp,
             enum ct_alg_ctl_type ct_alg_ctl, uint32_t tp_id)
-    OVS_REQUIRES(ct->ct_lock)
+    OVS_REQUIRES(ct->ct_lock, cz->zone_lock)
 {
     struct conn_key_node *fwd_key_node, *rev_key_node;
     struct conn *nc = NULL;
@@ -1203,15 +1213,18 @@  conn_maybe_not_found(struct conntrack *ct, struct dp_packet *pkt,
      * analysis. */
     if (commit) {
         ovs_mutex_lock(&ct->ct_lock);
+        ovs_mutex_lock(&cz->zone_lock);
         bool found = conn_lookup_zone(ct, cz, &ctx->key, now, NULL, NULL);
         if (!found) {
             if (!pkt_validate_and_set_new_ct_state(pkt, ctx, alg_exp)) {
+                ovs_mutex_unlock(&cz->zone_lock);
                 ovs_mutex_unlock(&ct->ct_lock);
                 return nc;
             }
             nc = conn_insert(ct, cz, pkt, ctx, now, nat_action_info,
                              helper, alg_exp, ct_alg_ctl, tp_id);
         }
+        ovs_mutex_unlock(&cz->zone_lock);
         ovs_mutex_unlock(&ct->ct_lock);
     } else {
         bool found = conn_lookup_zone(ct, cz, &ctx->key, now, NULL, NULL);