Added support for kernel segment manipulation
This commit is contained in:
committed by
Martin Willi
parent
6921e8d5a9
commit
dbc91f7c84
@@ -11,6 +11,7 @@ libstrongswan_ha_sync_la_SOURCES = \
|
||||
ha_sync_tunnel.h ha_sync_tunnel.c \
|
||||
ha_sync_dispatcher.h ha_sync_dispatcher.c \
|
||||
ha_sync_segments.h ha_sync_segments.c \
|
||||
ha_sync_kernel.h ha_sync_kernel.c \
|
||||
ha_sync_ctl.h ha_sync_ctl.c \
|
||||
ha_sync_ike.h ha_sync_ike.c \
|
||||
ha_sync_child.h ha_sync_child.c
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (C) 2009 Martin Willi
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include "ha_sync_kernel.h"
|
||||
|
||||
typedef u_int32_t u32;
|
||||
typedef u_int8_t u8;
|
||||
|
||||
#include <linux/jhash.h>
|
||||
|
||||
typedef struct private_ha_sync_kernel_t private_ha_sync_kernel_t;
|
||||
|
||||
/**
|
||||
* Private data of an ha_sync_kernel_t object.
|
||||
*/
|
||||
struct private_ha_sync_kernel_t {
|
||||
|
||||
/**
|
||||
* Public ha_sync_kernel_t interface.
|
||||
*/
|
||||
ha_sync_kernel_t public;
|
||||
|
||||
/**
|
||||
* Init value for jhash
|
||||
*/
|
||||
u_int initval;
|
||||
|
||||
/**
|
||||
* Total number of ClusterIP segments
|
||||
*/
|
||||
u_int segment_count;
|
||||
|
||||
/**
|
||||
* mask of active segments
|
||||
*/
|
||||
segment_mask_t active;
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation of ha_sync_kernel_t.in_segment
|
||||
*/
|
||||
static bool in_segment(private_ha_sync_kernel_t *this, host_t *host, u_int segment)
|
||||
{
|
||||
if (host->get_family(host) == AF_INET)
|
||||
{
|
||||
unsigned long hash;
|
||||
u_int32_t addr;
|
||||
|
||||
addr = *(u_int32_t*)host->get_address(host).ptr;
|
||||
hash = jhash_1word(ntohl(addr), this->initval);
|
||||
|
||||
if ((((u_int64_t)hash * this->segment_count) >> 32) + 1 == segment)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of ha_sync_kernel_t.destroy.
|
||||
*/
|
||||
static void destroy(private_ha_sync_kernel_t *this)
|
||||
{
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* See header
|
||||
*/
|
||||
ha_sync_kernel_t *ha_sync_kernel_create(u_int count, segment_mask_t active,
|
||||
char *external, char *internal)
|
||||
{
|
||||
private_ha_sync_kernel_t *this = malloc_thing(private_ha_sync_kernel_t);
|
||||
|
||||
this->public.in_segment = (bool(*)(ha_sync_kernel_t*, host_t *host, u_int segment))in_segment;
|
||||
this->public.destroy = (void(*)(ha_sync_kernel_t*))destroy;
|
||||
|
||||
this->initval = 0;
|
||||
this->segment_count = count;
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2009 Martin Willi
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup ha_sync_kernel ha_sync_kernel
|
||||
* @{ @ingroup ha_sync
|
||||
*/
|
||||
|
||||
#ifndef HA_SYNC_KERNEL_H_
|
||||
#define HA_SYNC_KERNEL_H_
|
||||
|
||||
typedef struct ha_sync_kernel_t ha_sync_kernel_t;
|
||||
|
||||
#include "ha_sync_segments.h"
|
||||
|
||||
/**
|
||||
* HA sync segment kernel configuration interface.
|
||||
*/
|
||||
struct ha_sync_kernel_t {
|
||||
|
||||
/**
|
||||
* Check if a host is in a segment.
|
||||
*
|
||||
* @param host host to check
|
||||
* @param segment segment
|
||||
* @return TRUE if host belongs to segment
|
||||
*/
|
||||
bool (*in_segment)(ha_sync_kernel_t *this, host_t *host, u_int segment);
|
||||
|
||||
/**
|
||||
* Destroy a ha_sync_kernel_t.
|
||||
*/
|
||||
void (*destroy)(ha_sync_kernel_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a ha_sync_kernel instance.
|
||||
*
|
||||
* @param count total number of segments to use
|
||||
* @param active bitmask of initially active segments
|
||||
* @param external external virtual IP the cluster acts as
|
||||
* @param internal internal virtual IP the cluster uses
|
||||
*/
|
||||
ha_sync_kernel_t *ha_sync_kernel_create(u_int count, segment_mask_t active,
|
||||
char *external, char *internal);
|
||||
|
||||
#endif /* HA_SYNC_KERNEL_ @}*/
|
||||
@@ -67,6 +67,11 @@ struct private_ha_sync_plugin_t {
|
||||
*/
|
||||
ha_sync_segments_t *segments;
|
||||
|
||||
/**
|
||||
* Interface to control segments at kernel level
|
||||
*/
|
||||
ha_sync_kernel_t *kernel;
|
||||
|
||||
/**
|
||||
* Segment control interface via FIFO
|
||||
*/
|
||||
@@ -85,6 +90,7 @@ static void destroy(private_ha_sync_plugin_t *this)
|
||||
this->child->destroy(this->child);
|
||||
this->dispatcher->destroy(this->dispatcher);
|
||||
this->segments->destroy(this->segments);
|
||||
this->kernel->destroy(this->kernel);
|
||||
this->socket->destroy(this->socket);
|
||||
DESTROY_IF(this->tunnel);
|
||||
free(this);
|
||||
@@ -119,7 +125,7 @@ static segment_mask_t parse_active(char *active)
|
||||
plugin_t *plugin_create()
|
||||
{
|
||||
private_ha_sync_plugin_t *this;
|
||||
char *local, *remote, *secret;
|
||||
char *local, *remote, *secret, *external, *internal;
|
||||
segment_mask_t active;
|
||||
u_int count;
|
||||
bool fifo;
|
||||
@@ -128,6 +134,10 @@ plugin_t *plugin_create()
|
||||
"charon.plugins.ha_sync.local", NULL);
|
||||
remote = lib->settings->get_str(lib->settings,
|
||||
"charon.plugins.ha_sync.remote", NULL);
|
||||
external = lib->settings->get_str(lib->settings,
|
||||
"charon.plugins.ha_sync.external", NULL);
|
||||
internal = lib->settings->get_str(lib->settings,
|
||||
"charon.plugins.ha_sync.internal", NULL);
|
||||
secret = lib->settings->get_str(lib->settings,
|
||||
"charon.plugins.ha_sync.secret", NULL);
|
||||
fifo = lib->settings->get_bool(lib->settings,
|
||||
@@ -141,6 +151,11 @@ plugin_t *plugin_create()
|
||||
DBG1(DBG_CFG, "HA sync config misses local/remote address");
|
||||
return NULL;
|
||||
}
|
||||
if (!external || !internal)
|
||||
{
|
||||
DBG1(DBG_CFG, "HA sync config misses external/internal virtual address");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
this = malloc_thing(private_ha_sync_plugin_t);
|
||||
|
||||
@@ -154,7 +169,16 @@ plugin_t *plugin_create()
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
this->segments = ha_sync_segments_create(this->socket, count, active);
|
||||
this->kernel = ha_sync_kernel_create(count, active, external, internal);
|
||||
if (!this->kernel)
|
||||
{
|
||||
this->socket->destroy(this->socket);
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
this->segments = ha_sync_segments_create(this->socket, this->kernel,
|
||||
count, active);
|
||||
if (secret)
|
||||
{
|
||||
this->tunnel = ha_sync_tunnel_create(secret, local, remote);
|
||||
|
||||
@@ -18,11 +18,6 @@
|
||||
#include <utils/mutex.h>
|
||||
#include <utils/linked_list.h>
|
||||
|
||||
typedef u_int32_t u32;
|
||||
typedef u_int8_t u8;
|
||||
|
||||
#include <linux/jhash.h>
|
||||
|
||||
typedef struct private_ha_sync_segments_t private_ha_sync_segments_t;
|
||||
|
||||
/**
|
||||
@@ -40,16 +35,16 @@ struct private_ha_sync_segments_t {
|
||||
*/
|
||||
ha_sync_socket_t *socket;
|
||||
|
||||
/**
|
||||
* Interface to control segments at kernel level
|
||||
*/
|
||||
ha_sync_kernel_t *kernel;
|
||||
|
||||
/**
|
||||
* read/write lock for segment manipulation
|
||||
*/
|
||||
rwlock_t *lock;
|
||||
|
||||
/**
|
||||
* Init value for jhash
|
||||
*/
|
||||
u_int initval;
|
||||
|
||||
/**
|
||||
* Total number of ClusterIP segments
|
||||
*/
|
||||
@@ -61,28 +56,6 @@ struct private_ha_sync_segments_t {
|
||||
segment_mask_t active;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if a host address is in the CLUSTERIP segment
|
||||
*/
|
||||
static bool in_segment(private_ha_sync_segments_t *this,
|
||||
host_t *host, u_int segment)
|
||||
{
|
||||
if (host->get_family(host) == AF_INET)
|
||||
{
|
||||
unsigned long hash;
|
||||
u_int32_t addr;
|
||||
|
||||
addr = *(u_int32_t*)host->get_address(host).ptr;
|
||||
hash = jhash_1word(ntohl(addr), this->initval);
|
||||
|
||||
if ((((u_int64_t)hash * this->segment_count) >> 32) + 1 == segment)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Log currently active segments
|
||||
*/
|
||||
@@ -152,7 +125,8 @@ static void enable_disable(private_ha_sync_segments_t *this, u_int segment,
|
||||
{
|
||||
for (i = segment; i < limit; i++)
|
||||
{
|
||||
if (in_segment(this, ike_sa->get_other_host(ike_sa), i))
|
||||
if (this->kernel->in_segment(this->kernel,
|
||||
ike_sa->get_other_host(ike_sa), i))
|
||||
{
|
||||
ike_sa->set_state(ike_sa, new);
|
||||
}
|
||||
@@ -254,7 +228,8 @@ static void resync(private_ha_sync_segments_t *this, u_int segment)
|
||||
while (enumerator->enumerate(enumerator, &ike_sa))
|
||||
{
|
||||
if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED &&
|
||||
in_segment(this, ike_sa->get_other_host(ike_sa), segment))
|
||||
this->kernel->in_segment(this->kernel,
|
||||
ike_sa->get_other_host(ike_sa), segment))
|
||||
{
|
||||
id = ike_sa->get_id(ike_sa);
|
||||
list->insert_last(list, id->clone(id));
|
||||
@@ -300,6 +275,7 @@ static void destroy(private_ha_sync_segments_t *this)
|
||||
* See header
|
||||
*/
|
||||
ha_sync_segments_t *ha_sync_segments_create(ha_sync_socket_t *socket,
|
||||
ha_sync_kernel_t *kernel,
|
||||
u_int count, segment_mask_t active)
|
||||
{
|
||||
private_ha_sync_segments_t *this = malloc_thing(private_ha_sync_segments_t);
|
||||
@@ -310,8 +286,8 @@ ha_sync_segments_t *ha_sync_segments_create(ha_sync_socket_t *socket,
|
||||
this->public.destroy = (void(*)(ha_sync_segments_t*))destroy;
|
||||
|
||||
this->socket = socket;
|
||||
this->kernel = kernel;
|
||||
this->lock = rwlock_create(RWLOCK_TYPE_DEFAULT);
|
||||
this->initval = 0;
|
||||
this->active = active;
|
||||
this->segment_count = count;
|
||||
|
||||
|
||||
@@ -21,8 +21,6 @@
|
||||
#ifndef HA_SYNC_SEGMENTS_H_
|
||||
#define HA_SYNC_SEGMENTS_H_
|
||||
|
||||
#include "ha_sync_socket.h"
|
||||
|
||||
#include <daemon.h>
|
||||
|
||||
typedef struct ha_sync_segments_t ha_sync_segments_t;
|
||||
@@ -39,6 +37,9 @@ typedef u_int16_t segment_mask_t;
|
||||
*/
|
||||
#define SEGMENTS_BIT(segment) (0x01 << (segment - 1))
|
||||
|
||||
#include "ha_sync_socket.h"
|
||||
#include "ha_sync_kernel.h"
|
||||
|
||||
/**
|
||||
* Segmentation of peers into active and passive.
|
||||
*/
|
||||
@@ -82,11 +83,13 @@ struct ha_sync_segments_t {
|
||||
* Create a ha_sync_segments instance.
|
||||
*
|
||||
* @param socket socket to communicate segment (de-)activation
|
||||
* @param kernel interface to control segments at kernel level
|
||||
* @param count number of segments the cluster uses
|
||||
* @param active bit mask of initially active segments
|
||||
* @return segment object
|
||||
*/
|
||||
ha_sync_segments_t *ha_sync_segments_create(ha_sync_socket_t *socket,
|
||||
ha_sync_kernel_t *kernel,
|
||||
u_int count, segment_mask_t active);
|
||||
|
||||
#endif /* HA_SYNC_SEGMENTS_ @}*/
|
||||
|
||||
Reference in New Issue
Block a user