aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Willi <martin@revosec.ch>2012-09-11 11:33:42 +0200
committerMartin Willi <martin@revosec.ch>2012-09-11 16:18:28 +0200
commit1e04488f3230b42beab1453f12806b574a69ceb0 (patch)
tree07dc073342df8fcfad460c6bacae5ff710584e72
parent28a3d5bfbde466f71a3f8b692d58b775ff7290ce (diff)
downloadstrongswan-1e04488f3230b42beab1453f12806b574a69ceb0.tar.bz2
strongswan-1e04488f3230b42beab1453f12806b574a69ceb0.tar.xz
Check for an existing lease in all stroke pools before creating a new one
-rw-r--r--src/libcharon/plugins/stroke/stroke_attribute.c38
-rw-r--r--src/libhydra/attributes/mem_pool.c204
-rw-r--r--src/libhydra/attributes/mem_pool.h21
3 files changed, 180 insertions, 83 deletions
diff --git a/src/libcharon/plugins/stroke/stroke_attribute.c b/src/libcharon/plugins/stroke/stroke_attribute.c
index e0c8360a1..85fb94e9e 100644
--- a/src/libcharon/plugins/stroke/stroke_attribute.c
+++ b/src/libcharon/plugins/stroke/stroke_attribute.c
@@ -89,35 +89,59 @@ static mem_pool_t *find_pool(private_stroke_attribute_t *this, char *name)
return found;
}
-METHOD(attribute_provider_t, acquire_address, host_t*,
- private_stroke_attribute_t *this, linked_list_t *pools, identification_t *id,
- host_t *requested)
+/**
+ * Find an existing or not yet existing lease
+ */
+static host_t *find_addr(private_stroke_attribute_t *this, linked_list_t *pools,
+ identification_t *id, host_t *requested,
+ mem_pool_op_t operation)
{
+ host_t *addr = NULL;
enumerator_t *enumerator;
mem_pool_t *pool;
- host_t *addr = NULL;
char *name;
enumerator = pools->create_enumerator(pools);
- this->lock->read_lock(this->lock);
while (enumerator->enumerate(enumerator, &name))
{
pool = find_pool(this, name);
if (pool)
{
- addr = pool->acquire_address(pool, id, requested);
+ addr = pool->acquire_address(pool, id, requested, operation);
if (addr)
{
break;
}
}
}
- this->lock->unlock(this->lock);
enumerator->destroy(enumerator);
return addr;
}
+METHOD(attribute_provider_t, acquire_address, host_t*,
+ private_stroke_attribute_t *this, linked_list_t *pools, identification_t *id,
+ host_t *requested)
+{
+ host_t *addr;
+
+ this->lock->read_lock(this->lock);
+
+ addr = find_addr(this, pools, id, requested, MEM_POOL_EXISTING);
+ if (!addr)
+ {
+ addr = find_addr(this, pools, id, requested, MEM_POOL_NEW);
+ if (!addr)
+ {
+ addr = find_addr(this, pools, id, requested, MEM_POOL_REASSIGN);
+ }
+ }
+
+ this->lock->unlock(this->lock);
+
+ return addr;
+}
+
METHOD(attribute_provider_t, release_address, bool,
private_stroke_attribute_t *this, linked_list_t *pools, host_t *address,
identification_t *id)
diff --git a/src/libhydra/attributes/mem_pool.c b/src/libhydra/attributes/mem_pool.c
index 39159bfb0..1c420318f 100644
--- a/src/libhydra/attributes/mem_pool.c
+++ b/src/libhydra/attributes/mem_pool.c
@@ -212,12 +212,123 @@ METHOD(mem_pool_t, get_offline, u_int,
return count;
}
-METHOD(mem_pool_t, acquire_address, host_t*,
- private_mem_pool_t *this, identification_t *id, host_t *requested)
+/**
+ * Get an existing lease for id
+ */
+static int get_existing(private_mem_pool_t *this, identification_t *id,
+ host_t *requested)
+{
+ enumerator_t *enumerator;
+ uintptr_t current;
+ entry_t *entry;
+ int offset = 0;
+
+ entry = this->leases->get(this->leases, id);
+ if (!entry)
+ {
+ return 0;
+ }
+
+ /* check for a valid offline lease, refresh */
+ enumerator = entry->offline->create_enumerator(entry->offline);
+ if (enumerator->enumerate(enumerator, &current))
+ {
+ entry->offline->remove_at(entry->offline, enumerator);
+ entry->online->insert_last(entry->online, (void*)current);
+ offset = current;
+ }
+ enumerator->destroy(enumerator);
+ if (offset)
+ {
+ DBG1(DBG_CFG, "reassigning offline lease to '%Y'", id);
+ return offset;
+ }
+
+ /* check for a valid online lease to reassign */
+ enumerator = entry->online->create_enumerator(entry->online);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (current == host2offset(this, requested))
+ {
+ offset = current;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (offset)
+ {
+ DBG1(DBG_CFG, "reassigning online lease to '%Y'", id);
+ }
+ return offset;
+}
+
+/**
+ * Get a new lease for id
+ */
+static int get_new(private_mem_pool_t *this, identification_t *id)
+{
+ entry_t *entry;
+ int offset = 0;
+
+ if (this->unused < this->size)
+ {
+ INIT(entry,
+ .id = id->clone(id),
+ .online = linked_list_create(),
+ .offline = linked_list_create(),
+ );
+ this->leases->put(this->leases, entry->id, entry);
+
+ /* assigning offset, starting by 1 */
+ offset = ++this->unused;
+ entry->online->insert_last(entry->online, (void*)offset);
+ DBG1(DBG_CFG, "assigning new lease to '%Y'", id);
+ }
+ return offset;
+}
+
+/**
+ * Get a reassigned lease for id in case the pool is full
+ */
+static int get_reassigned(private_mem_pool_t *this, identification_t *id)
{
- uintptr_t offset = 0, current;
enumerator_t *enumerator;
- entry_t *entry, *old;
+ entry_t *entry;
+ uintptr_t current;
+ int offset = 0;
+
+ enumerator = this->leases->create_enumerator(this->leases);
+ while (enumerator->enumerate(enumerator, NULL, &entry))
+ {
+ if (entry->offline->remove_first(entry->offline,
+ (void**)&current) == SUCCESS)
+ {
+ offset = current;
+ DBG1(DBG_CFG, "reassigning existing offline lease by '%Y'"
+ " to '%Y'", entry->id, id);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (offset)
+ {
+ INIT(entry,
+ .id = id->clone(id),
+ .online = linked_list_create(),
+ .offline = linked_list_create(),
+ );
+ entry->online->insert_last(entry->online, (void*)offset);
+ this->leases->put(this->leases, entry->id, entry);
+ }
+ return offset;
+}
+
+METHOD(mem_pool_t, acquire_address, host_t*,
+ private_mem_pool_t *this, identification_t *id, host_t *requested,
+ mem_pool_op_t operation)
+{
+ int offset = 0;
/* if the pool is empty (e.g. in the %config case) we simply return the
* requested address */
@@ -233,76 +344,24 @@ METHOD(mem_pool_t, acquire_address, host_t*,
}
this->mutex->lock(this->mutex);
- while (TRUE)
+ switch (operation)
{
- entry = this->leases->get(this->leases, id);
- if (entry)
- {
- /* check for a valid offline lease, refresh */
- enumerator = entry->offline->create_enumerator(entry->offline);
- if (enumerator->enumerate(enumerator, &current))
- {
- entry->offline->remove_at(entry->offline, enumerator);
- entry->online->insert_last(entry->online, (void*)current);
- offset = current;
- }
- enumerator->destroy(enumerator);
- if (offset)
- {
- DBG1(DBG_CFG, "reassigning offline lease to '%Y'", id);
- break;
- }
- /* check for a valid online lease to reassign */
- enumerator = entry->online->create_enumerator(entry->online);
- while (enumerator->enumerate(enumerator, &current))
- {
- if (current == host2offset(this, requested))
- {
- offset = current;
- break;
- }
- }
- enumerator->destroy(enumerator);
- if (offset)
- {
- DBG1(DBG_CFG, "reassigning online lease to '%Y'", id);
- break;
- }
- }
- else
- {
- INIT(entry,
- .id = id->clone(id),
- .online = linked_list_create(),
- .offline = linked_list_create(),
- );
- this->leases->put(this->leases, entry->id, entry);
- }
- if (this->unused < this->size)
- {
- /* assigning offset, starting by 1 */
- offset = ++this->unused;
- entry->online->insert_last(entry->online, (void*)offset);
- DBG1(DBG_CFG, "assigning new lease to '%Y'", id);
+ case MEM_POOL_EXISTING:
+ offset = get_existing(this, id, requested);
break;
- }
-
- /* no more addresses, replace the first found offline lease */
- enumerator = this->leases->create_enumerator(this->leases);
- while (enumerator->enumerate(enumerator, NULL, &old))
- {
- if (old->offline->remove_first(old->offline,
- (void**)&current) == SUCCESS)
+ case MEM_POOL_NEW:
+ offset = get_new(this, id);
+ break;
+ case MEM_POOL_REASSIGN:
+ offset = get_reassigned(this, id);
+ if (!offset)
{
- offset = current;
- entry->online->insert_last(entry->online, (void*)offset);
- DBG1(DBG_CFG, "reassigning existing offline lease by '%Y'"
- " to '%Y'", old->id, id);
- break;
+ DBG1(DBG_CFG, "pool '%s' is full, unable to assign address",
+ this->name);
}
- }
- enumerator->destroy(enumerator);
- break;
+ break;
+ default:
+ break;
}
this->mutex->unlock(this->mutex);
@@ -310,11 +369,6 @@ METHOD(mem_pool_t, acquire_address, host_t*,
{
return offset2host(this, offset);
}
- else
- {
- DBG1(DBG_CFG, "pool '%s' is full, unable to assign address",
- this->name);
- }
return NULL;
}
diff --git a/src/libhydra/attributes/mem_pool.h b/src/libhydra/attributes/mem_pool.h
index 7b7e58af7..fa4e6485c 100644
--- a/src/libhydra/attributes/mem_pool.h
+++ b/src/libhydra/attributes/mem_pool.h
@@ -22,11 +22,24 @@
#define MEM_POOL_H
typedef struct mem_pool_t mem_pool_t;
+typedef enum mem_pool_op_t mem_pool_op_t;
#include <utils/host.h>
#include <utils/identification.h>
/**
+ * In-memory IP pool acquire operation.
+ */
+enum mem_pool_op_t {
+ /** Check for an exsiting lease */
+ MEM_POOL_EXISTING,
+ /** Get a new lease */
+ MEM_POOL_NEW,
+ /** Replace an existing offline lease of another ID */
+ MEM_POOL_REASSIGN,
+};
+
+/**
* An in-memory IP address pool.
*/
struct mem_pool_t {
@@ -69,12 +82,18 @@ struct mem_pool_t {
/**
* Acquire an address for the given id from this pool.
*
+ * This call is usually invoked several times: The first time to find an
+ * existing lease (MEM_POOL_EXISTING), if none found a second time to
+ * acquire a new lease (MEM_POOL_NEW), and if the pool is full once again
+ * to assign an existing offline lease (MEM_POOL_REASSIGN).
+ *
* @param id the id to acquire an address for
* @param requested acquire this address, if possible
+ * @param existing TRUE to look for an existing lease, FALSE for a new one
* @return the acquired address
*/
host_t* (*acquire_address)(mem_pool_t *this, identification_t *id,
- host_t *requested);
+ host_t *requested, mem_pool_op_t operation);
/**
* Release a previously acquired address.