Previously we slept for a minimum of 200ms after each cleaning run, even
if we did clean the majority of entries. This originally came from the
requirement that we need to take the whole conntrack lock to cleanup
connections and are therefor limited in the progress we can still make
when inserting.

However with the now implemented locks per zone and the batching this is
no longer needed. In addition before we could do partion zone cleanings
we always cleaned a full zone. This meant that a single high load zone
would still be cleaned quite fast.

When using the same testcases as in the previous commits
Below lists the total time for the testrun with these various configs.
|          | Without this patch | With this patch |
| Config 1 | 30.8 s             | 3.7 s           |
| Config 2 | 31.5 s             | 16.1 s          |
| Config 3 | 7.7 s              | 7.4 s           |
| Config 4 | 17.7 s             | 16.7 s          |
| Config 5 | 44.1 s             | 43.9 s          |
| Config 6 | 43.9 s             | 43.0 s          |

Signed-off-by: Felix Huettner <[email protected]>
---
 lib/conntrack.c | 28 ++++++++++++++++++++--------
 1 file changed, 20 insertions(+), 8 deletions(-)

diff --git a/lib/conntrack.c b/lib/conntrack.c
index cd275db54..5145baf7c 100644
--- a/lib/conntrack.c
+++ b/lib/conntrack.c
@@ -1518,8 +1518,8 @@ ct_sweep_buf(struct conntrack *ct, uint16_t zone, struct 
conn *conn_buf[100],
 
 static size_t
 ct_sweep_zone(struct conntrack *ct, uint16_t zone, long long now,
-              size_t *cleaned_count, size_t limit,
-              struct cmap_position **current_position)
+              size_t *cleaned_count, long long *min_expiration,
+              size_t limit, struct cmap_position **current_position)
     OVS_NO_THREAD_SAFETY_ANALYSIS
 {
     struct conn_key_node *keyn;
@@ -1559,7 +1559,9 @@ ct_sweep_zone(struct conntrack *ct, uint16_t zone, long 
long now,
         if (now >= expiration) {
             conn_buf[n_conn_buf++] = conn;
             (*cleaned_count)++;
-         }
+        } else {
+            *min_expiration = MIN(*min_expiration, expiration);
+        }
         if (n_conn_buf == CONN_BUF_SIZE) {
             ct_sweep_buf(ct, zone, conn_buf, n_conn_buf);
             n_conn_buf = 0;
@@ -1581,6 +1583,7 @@ static long long
 conntrack_clean(struct conntrack *ct, long long now)
 {
     long long next_wakeup = now + conntrack_get_sweep_interval(ct);
+    long long min_expiration = LLONG_MAX;
     unsigned int n_conn_limit, i;
     size_t clean_end, count = 0;
     size_t total_cleaned = 0;
@@ -1591,12 +1594,12 @@ conntrack_clean(struct conntrack *ct, long long now)
     for (i = 0; i < ARRAY_SIZE(ct->zones); i++) {
         size_t cleaned = 0;
 
-        if (count > clean_end) {
-            next_wakeup = 0;
+        if (count >= clean_end) {
             break;
         }
 
-        count += ct_sweep_zone(ct, ct->current_clean_zone, now, &cleaned,
+        count += ct_sweep_zone(ct, ct->current_clean_zone, now,
+                               &cleaned, &min_expiration,
                                clean_end - count, &ct->current_clean_position);
         total_cleaned += cleaned;
 
@@ -1609,6 +1612,16 @@ conntrack_clean(struct conntrack *ct, long long now)
              " entries in %lld msec", total_cleaned, count,
              time_msec() - now);
 
+    /* If we did clean more than 10% of our connection limit we assume that
+     * if we would continue we would also find a lot of connections to clean.
+     * In this case we want to rather continue immediately to ensure we get
+     * the connections removed in a high load situation. */
+    if (total_cleaned >= (clean_end / 10)) {
+        next_wakeup = 0;
+    } else {
+        next_wakeup = MIN(next_wakeup, min_expiration);
+    }
+
     return next_wakeup;
 }
 
@@ -1616,7 +1629,6 @@ conntrack_clean(struct conntrack *ct, long long now)
  *
  * We must call conntrack_clean() periodically.  conntrack_clean() return
  * value gives an hint on when the next cleanup must be done. */
-#define CT_CLEAN_MIN_INTERVAL_MS 200
 
 static void *
 clean_thread_main(void *f_)
@@ -1630,7 +1642,7 @@ clean_thread_main(void *f_)
         next_wake = conntrack_clean(ct, now);
 
         if (next_wake < now) {
-            poll_timer_wait_until(now + CT_CLEAN_MIN_INTERVAL_MS);
+            poll_immediate_wake();
         } else {
             poll_timer_wait_until(next_wake);
         }
-- 
2.43.0


_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to