summaryrefslogtreecommitdiff
path: root/src/libcharon/sa/ike_sa_manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcharon/sa/ike_sa_manager.c')
-rw-r--r--src/libcharon/sa/ike_sa_manager.c121
1 files changed, 69 insertions, 52 deletions
diff --git a/src/libcharon/sa/ike_sa_manager.c b/src/libcharon/sa/ike_sa_manager.c
index 6bd49a086..c0bfebb83 100644
--- a/src/libcharon/sa/ike_sa_manager.c
+++ b/src/libcharon/sa/ike_sa_manager.c
@@ -151,8 +151,10 @@ static entry_t *entry_create()
/**
* Function that matches entry_t objects by ike_sa_id_t.
*/
-static bool entry_match_by_id(entry_t *entry, ike_sa_id_t *id)
+static bool entry_match_by_id(entry_t *entry, void *arg)
{
+ ike_sa_id_t *id = arg;
+
if (id->equals(id, entry->ike_sa_id))
{
return TRUE;
@@ -172,7 +174,7 @@ static bool entry_match_by_id(entry_t *entry, ike_sa_id_t *id)
/**
* Function that matches entry_t objects by ike_sa_t pointers.
*/
-static bool entry_match_by_sa(entry_t *entry, ike_sa_t *ike_sa)
+static bool entry_match_by_sa(entry_t *entry, void *ike_sa)
{
return entry->ike_sa == ike_sa;
}
@@ -276,9 +278,6 @@ typedef struct segment_t segment_t;
struct segment_t {
/** mutex to access a segment exclusively */
mutex_t *mutex;
-
- /** the number of entries in this segment */
- u_int count;
};
typedef struct shareable_segment_t shareable_segment_t;
@@ -371,6 +370,11 @@ struct private_ike_sa_manager_t {
refcount_t half_open_count_responder;
/**
+ * Total number of IKE_SAs registered with IKE_SA manager.
+ */
+ refcount_t total_sa_count;
+
+ /**
* Hash table with connected_peers_t objects.
*/
table_item_t **connected_peers_table;
@@ -511,8 +515,13 @@ struct private_enumerator_t {
};
METHOD(enumerator_t, enumerate, bool,
- private_enumerator_t *this, entry_t **entry, u_int *segment)
+ private_enumerator_t *this, va_list args)
{
+ entry_t **entry;
+ u_int *segment;
+
+ VA_ARGS_VGET(args, entry, segment);
+
if (this->entry)
{
this->entry->condvar->signal(this->entry->condvar);
@@ -570,7 +579,8 @@ static enumerator_t* create_table_enumerator(private_ike_sa_manager_t *this)
INIT(enumerator,
.enumerator = {
- .enumerate = (void*)_enumerate,
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _enumerate,
.destroy = _enumerator_destroy,
},
.manager = this,
@@ -601,7 +611,7 @@ static u_int put_entry(private_ike_sa_manager_t *this, entry_t *entry)
item->next = current;
}
this->ike_sa_table[row] = item;
- this->segments[segment].count++;
+ ref_get(&this->total_sa_count);
return segment;
}
@@ -612,10 +622,9 @@ static u_int put_entry(private_ike_sa_manager_t *this, entry_t *entry)
static void remove_entry(private_ike_sa_manager_t *this, entry_t *entry)
{
table_item_t *item, *prev = NULL;
- u_int row, segment;
+ u_int row;
row = ike_sa_id_hash(entry->ike_sa_id) & this->table_mask;
- segment = row & this->segment_mask;
item = this->ike_sa_table[row];
while (item)
{
@@ -629,7 +638,7 @@ static void remove_entry(private_ike_sa_manager_t *this, entry_t *entry)
{
this->ike_sa_table[row] = item->next;
}
- this->segments[segment].count--;
+ ignore_result(ref_put(&this->total_sa_count));
free(item);
break;
}
@@ -648,7 +657,7 @@ static void remove_entry_at(private_enumerator_t *this)
{
table_item_t *current = this->current;
- this->manager->segments[this->segment].count--;
+ ignore_result(ref_put(&this->manager->total_sa_count));
this->current = this->prev;
if (this->prev)
@@ -670,7 +679,7 @@ static void remove_entry_at(private_enumerator_t *this)
*/
static status_t get_entry_by_match_function(private_ike_sa_manager_t *this,
ike_sa_id_t *ike_sa_id, entry_t **entry, u_int *segment,
- linked_list_match_t match, void *param)
+ bool (*match)(entry_t*,void*), void *param)
{
table_item_t *item;
u_int row, seg;
@@ -703,7 +712,7 @@ static status_t get_entry_by_id(private_ike_sa_manager_t *this,
ike_sa_id_t *ike_sa_id, entry_t **entry, u_int *segment)
{
return get_entry_by_match_function(this, ike_sa_id, entry, segment,
- (linked_list_match_t)entry_match_by_id, ike_sa_id);
+ entry_match_by_id, ike_sa_id);
}
/**
@@ -714,7 +723,7 @@ static status_t get_entry_by_sa(private_ike_sa_manager_t *this,
ike_sa_id_t *ike_sa_id, ike_sa_t *ike_sa, entry_t **entry, u_int *segment)
{
return get_entry_by_match_function(this, ike_sa_id, entry, segment,
- (linked_list_match_t)entry_match_by_sa, ike_sa);
+ entry_match_by_sa, ike_sa);
}
/**
@@ -851,6 +860,15 @@ static void remove_half_open(private_ike_sa_manager_t *this, entry_t *entry)
lock->unlock(lock);
}
+CALLBACK(id_matches, bool,
+ ike_sa_id_t *a, va_list args)
+{
+ ike_sa_id_t *b;
+
+ VA_ARGS_VGET(args, b);
+ return a->equals(a, b);
+}
+
/**
* Put an SA between two peers into the hash table.
*/
@@ -879,8 +897,7 @@ static void put_connected_peers(private_ike_sa_manager_t *this, entry_t *entry)
entry->other_id, family))
{
if (connected_peers->sas->find_first(connected_peers->sas,
- (linked_list_match_t)entry->ike_sa_id->equals,
- NULL, entry->ike_sa_id) == SUCCESS)
+ id_matches, NULL, entry->ike_sa_id))
{
lock->unlock(lock);
return;
@@ -1555,42 +1572,52 @@ METHOD(ike_sa_manager_t, checkout_by_name, ike_sa_t*,
return ike_sa;
}
-/**
- * enumerator filter function, waiting variant
- */
-static bool enumerator_filter_wait(private_ike_sa_manager_t *this,
- entry_t **in, ike_sa_t **out, u_int *segment)
+CALLBACK(enumerator_filter_wait, bool,
+ private_ike_sa_manager_t *this, enumerator_t *orig, va_list args)
{
- if (wait_for_entry(this, *in, *segment))
+ entry_t *entry;
+ u_int segment;
+ ike_sa_t **out;
+
+ VA_ARGS_VGET(args, out);
+
+ while (orig->enumerate(orig, &entry, &segment))
{
- *out = (*in)->ike_sa;
- charon->bus->set_sa(charon->bus, *out);
- return TRUE;
+ if (wait_for_entry(this, entry, segment))
+ {
+ *out = entry->ike_sa;
+ charon->bus->set_sa(charon->bus, *out);
+ return TRUE;
+ }
}
return FALSE;
}
-/**
- * enumerator filter function, skipping variant
- */
-static bool enumerator_filter_skip(private_ike_sa_manager_t *this,
- entry_t **in, ike_sa_t **out, u_int *segment)
+CALLBACK(enumerator_filter_skip, bool,
+ private_ike_sa_manager_t *this, enumerator_t *orig, va_list args)
{
- if (!(*in)->driveout_new_threads &&
- !(*in)->driveout_waiting_threads &&
- !(*in)->checked_out)
+ entry_t *entry;
+ u_int segment;
+ ike_sa_t **out;
+
+ VA_ARGS_VGET(args, out);
+
+ while (orig->enumerate(orig, &entry, &segment))
{
- *out = (*in)->ike_sa;
- charon->bus->set_sa(charon->bus, *out);
- return TRUE;
+ if (!entry->driveout_new_threads &&
+ !entry->driveout_waiting_threads &&
+ !entry->checked_out)
+ {
+ *out = entry->ike_sa;
+ charon->bus->set_sa(charon->bus, *out);
+ return TRUE;
+ }
}
return FALSE;
}
-/**
- * Reset threads SA after enumeration
- */
-static void reset_sa(void *data)
+CALLBACK(reset_sa, void,
+ void *data)
{
charon->bus->set_sa(charon->bus, NULL);
}
@@ -2034,17 +2061,7 @@ METHOD(ike_sa_manager_t, has_contact, bool,
METHOD(ike_sa_manager_t, get_count, u_int,
private_ike_sa_manager_t *this)
{
- u_int segment, count = 0;
- mutex_t *mutex;
-
- for (segment = 0; segment < this->segment_count; segment++)
- {
- mutex = this->segments[segment & this->segment_mask].mutex;
- mutex->lock(mutex);
- count += this->segments[segment].count;
- mutex->unlock(mutex);
- }
- return count;
+ return (u_int)ref_cur(&this->total_sa_count);
}
METHOD(ike_sa_manager_t, get_half_open_count, u_int,