ike-sa-manager: Improve scalability of half-open IKE_SA checking
authorTobias Brunner <tobias@strongswan.org>
Fri, 11 Apr 2014 14:23:39 +0000 (16:23 +0200)
committerTobias Brunner <tobias@strongswan.org>
Thu, 24 Apr 2014 15:54:14 +0000 (17:54 +0200)
This patch is based on one by Christoph Gouault.

Currently, to count the total number of half_open IKE_SAs,
get_half_open_count sums up the count of each segment in the SA hash
table (acquiring a lock for each segment).  This procedure does not scale
well when the number of segments increases, as the method is called for
each new negotiation.

Instead, lets maintain a global atomic counter.

This optimization allows the use of big values for charon.ikesa_table_size
and charon.ikesa_table_segments.

src/libcharon/sa/ike_sa_manager.c

index f2f81cf..525117f 100644 (file)
@@ -354,6 +354,11 @@ struct private_ike_sa_manager_t {
        shareable_segment_t *half_open_segments;
 
        /**
+        * Total number of half-open IKE_SAs.
+        */
+       refcount_t half_open_count;
+
+       /**
         * Hash table with connected_peers_t objects.
         */
        table_item_t **connected_peers_table;
@@ -764,6 +769,7 @@ static void put_half_open(private_ike_sa_manager_t *this, entry_t *entry)
                this->half_open_table[row] = item;
        }
        this->half_open_segments[segment].count++;
+       ref_get(&this->half_open_count);
        lock->unlock(lock);
 }
 
@@ -803,6 +809,7 @@ static void remove_half_open(private_ike_sa_manager_t *this, entry_t *entry)
                                free(item);
                        }
                        this->half_open_segments[segment].count--;
+                       ignore_result(ref_put(&this->half_open_count));
                        break;
                }
                prev = item;
@@ -1962,13 +1969,7 @@ METHOD(ike_sa_manager_t, get_half_open_count, u_int,
        }
        else
        {
-               for (segment = 0; segment < this->segment_count; segment++)
-               {
-                       lock = this->half_open_segments[segment].lock;
-                       lock->read_lock(lock);
-                       count += this->half_open_segments[segment].count;
-                       lock->unlock(lock);
-               }
+               count = (u_int)ref_cur(&this->half_open_count);
        }
        return count;
 }