diff options
author | Tobias Brunner <tobias@strongswan.org> | 2008-12-04 16:46:08 +0000 |
---|---|---|
committer | Tobias Brunner <tobias@strongswan.org> | 2008-12-04 16:46:08 +0000 |
commit | 3fb404d8da1e964f4edb5e2e555b11df1f54a2a1 (patch) | |
tree | f754dcbd005c59f9dc1d3ccbf24c75194eec364b /src/charon/plugins/kernel_netlink/kernel_netlink_ipsec.c | |
parent | ffa645069557df1beca1d3671619b0290442a805 (diff) | |
download | strongswan-3fb404d8da1e964f4edb5e2e555b11df1f54a2a1.tar.bz2 strongswan-3fb404d8da1e964f4edb5e2e555b11df1f54a2a1.tar.xz |
implemented the policy cache in kernel_netlink_ipsec_t with a hash table instead of a linked list.
Diffstat (limited to 'src/charon/plugins/kernel_netlink/kernel_netlink_ipsec.c')
-rw-r--r-- | src/charon/plugins/kernel_netlink/kernel_netlink_ipsec.c | 95 |
1 files changed, 54 insertions, 41 deletions
diff --git a/src/charon/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/charon/plugins/kernel_netlink/kernel_netlink_ipsec.c index 2abbab477..8c472f2ce 100644 --- a/src/charon/plugins/kernel_netlink/kernel_netlink_ipsec.c +++ b/src/charon/plugins/kernel_netlink/kernel_netlink_ipsec.c @@ -39,7 +39,7 @@ #include <daemon.h> #include <utils/mutex.h> -#include <utils/linked_list.h> +#include <utils/hashtable.h> #include <processing/jobs/callback_job.h> #include <processing/jobs/acquire_job.h> #include <processing/jobs/migrate_job.h> @@ -250,6 +250,24 @@ struct policy_entry_t { u_int refcount; }; +/** + * Hash function for policy_entry_t objects + */ +static u_int policy_hash(policy_entry_t *key) +{ + chunk_t chunk = chunk_create((void*)&key->sel, sizeof(struct xfrm_selector)); + return chunk_hash(chunk); +} + +/** + * Equality function for policy_entry_t objects + */ +static bool policy_equals(policy_entry_t *key, policy_entry_t *other_key) +{ + return memeq(&key->sel, &other_key->sel, sizeof(struct xfrm_selector)) && + key->direction == other_key->direction; +} + typedef struct private_kernel_netlink_ipsec_t private_kernel_netlink_ipsec_t; /** @@ -267,9 +285,9 @@ struct private_kernel_netlink_ipsec_t { mutex_t *mutex; /** - * List of installed policies (policy_entry_t) + * Hash table of installed policies (policy_entry_t) */ - linked_list_t *policies; + hashtable_t *policies; /** * job receiving netlink events @@ -1396,7 +1414,6 @@ static status_t add_policy(private_kernel_netlink_ipsec_t *this, ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi, bool routed) { - iterator_t *iterator; policy_entry_t *current, *policy; bool found = FALSE; netlink_buf_t request; @@ -1411,27 +1428,21 @@ static status_t add_policy(private_kernel_netlink_ipsec_t *this, /* find the policy, which matches EXACTLY */ this->mutex->lock(this->mutex); - iterator = this->policies->create_iterator(this->policies, TRUE); - while (iterator->iterate(iterator, (void**)¤t)) + current = this->policies->get(this->policies, policy); + if (current) { - if (memeq(¤t->sel, &policy->sel, sizeof(struct xfrm_selector)) && - policy->direction == current->direction) - { - /* use existing policy */ - current->refcount++; - DBG2(DBG_KNL, "policy %R === %R %N already exists, increasing " - "refcount", src_ts, dst_ts, - policy_dir_names, direction); - free(policy); - policy = current; - found = TRUE; - break; - } + /* use existing policy */ + current->refcount++; + DBG2(DBG_KNL, "policy %R === %R %N already exists, increasing " + "refcount", src_ts, dst_ts, + policy_dir_names, direction); + free(policy); + policy = current; + found = TRUE; } - iterator->destroy(iterator); - if (!found) + else { /* apply the new one, if we have no such policy */ - this->policies->insert_last(this->policies, policy); + this->policies->put(this->policies, policy, policy); policy->refcount = 1; } @@ -1659,7 +1670,6 @@ static status_t del_policy(private_kernel_netlink_ipsec_t *this, netlink_buf_t request; struct nlmsghdr *hdr; struct xfrm_userpolicy_id *policy_id; - enumerator_t *enumerator; DBG2(DBG_KNL, "deleting policy %R === %R %N", src_ts, dst_ts, policy_dir_names, direction); @@ -1671,28 +1681,21 @@ static status_t del_policy(private_kernel_netlink_ipsec_t *this, /* find the policy */ this->mutex->lock(this->mutex); - enumerator = this->policies->create_enumerator(this->policies); - while (enumerator->enumerate(enumerator, ¤t)) + current = this->policies->get(this->policies, &policy); + if (current) { - if (memeq(¤t->sel, &policy.sel, sizeof(struct xfrm_selector)) && - policy.direction == current->direction) + to_delete = current; + if (--to_delete->refcount > 0) { - to_delete = current; - if (--to_delete->refcount > 0) - { - /* is used by more SAs, keep in kernel */ - DBG2(DBG_KNL, "policy still used by another CHILD_SA, not removed"); - this->mutex->unlock(this->mutex); - enumerator->destroy(enumerator); - return SUCCESS; - } - /* remove if last reference */ - this->policies->remove_at(this->policies, enumerator); - break; + /* is used by more SAs, keep in kernel */ + DBG2(DBG_KNL, "policy still used by another CHILD_SA, not removed"); + this->mutex->unlock(this->mutex); + return SUCCESS; } + /* remove if last reference */ + this->policies->remove(this->policies, to_delete); } this->mutex->unlock(this->mutex); - enumerator->destroy(enumerator); if (!to_delete) { DBG1(DBG_KNL, "deleting policy %R === %R %N failed, not found", src_ts, @@ -1741,9 +1744,18 @@ static status_t del_policy(private_kernel_netlink_ipsec_t *this, */ static void destroy(private_kernel_netlink_ipsec_t *this) { + enumerator_t *enumerator; + policy_entry_t *policy; + this->job->cancel(this->job); close(this->socket_xfrm_events); this->socket_xfrm->destroy(this->socket_xfrm); + enumerator = this->policies->create_enumerator(this->policies); + while (enumerator->enumerate(enumerator, (void**)&policy)) + { + free(policy); + } + enumerator->destroy(enumerator); this->policies->destroy(this->policies); this->mutex->destroy(this->mutex); free(this); @@ -1834,7 +1846,8 @@ kernel_netlink_ipsec_t *kernel_netlink_ipsec_create() this->public.interface.destroy = (void(*)(kernel_ipsec_t*)) destroy; /* private members */ - this->policies = linked_list_create(); + this->policies = hashtable_create((hashtable_hash_t)policy_hash, + (hashtable_equals_t)policy_equals, 1); this->mutex = mutex_create(MUTEX_DEFAULT); this->install_routes = lib->settings->get_bool(lib->settings, "charon.install_routes", TRUE); |