diff options
Diffstat (limited to 'src/libcharon/sa/ike_sa_manager.c')
-rw-r--r-- | src/libcharon/sa/ike_sa_manager.c | 121 |
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, |