Log CHILD_SA segment responsibility
authorMartin Willi <martin@revosec.ch>
Mon, 26 Jul 2010 11:49:35 +0000 (13:49 +0200)
committerMartin Willi <martin@revosec.ch>
Mon, 26 Jul 2010 11:53:54 +0000 (13:53 +0200)
src/libcharon/plugins/ha/ha_child.c
src/libcharon/plugins/ha/ha_child.h
src/libcharon/plugins/ha/ha_dispatcher.c
src/libcharon/plugins/ha/ha_dispatcher.h
src/libcharon/plugins/ha/ha_kernel.c
src/libcharon/plugins/ha/ha_kernel.h
src/libcharon/plugins/ha/ha_plugin.c
src/libcharon/plugins/ha/ha_segments.c
src/libcharon/plugins/ha/ha_segments.h

index 640aa16..1a94254 100644 (file)
@@ -38,9 +38,14 @@ struct private_ha_child_t {
        ha_tunnel_t *tunnel;
 
        /**
-        * message cache
+        * Segment handling
         */
-       ha_cache_t *cache;
+       ha_segments_t *segments;
+
+       /**
+        * Kernel helper
+        */
+       ha_kernel_t *kernel;
 };
 
 METHOD(listener_t, child_keys, bool,
@@ -51,9 +56,10 @@ METHOD(listener_t, child_keys, bool,
        chunk_t secret;
        proposal_t *proposal;
        u_int16_t alg, len;
-       linked_list_t *list;
+       linked_list_t *local_ts, *remote_ts;
        enumerator_t *enumerator;
        traffic_selector_t *ts;
+       u_int seg_i, seg_o;
 
        if (this->tunnel && this->tunnel->is_sa(this->tunnel, ike_sa))
        {       /* do not sync SA between nodes */
@@ -93,21 +99,31 @@ METHOD(listener_t, child_keys, bool,
                chunk_clear(&secret);
        }
 
-       list = child_sa->get_traffic_selectors(child_sa, TRUE);
-       enumerator = list->create_enumerator(list);
+       local_ts = child_sa->get_traffic_selectors(child_sa, TRUE);
+       enumerator = local_ts->create_enumerator(local_ts);
        while (enumerator->enumerate(enumerator, &ts))
        {
                m->add_attribute(m, HA_LOCAL_TS, ts);
        }
        enumerator->destroy(enumerator);
-       list = child_sa->get_traffic_selectors(child_sa, FALSE);
-       enumerator = list->create_enumerator(list);
+       remote_ts = child_sa->get_traffic_selectors(child_sa, FALSE);
+       enumerator = remote_ts->create_enumerator(remote_ts);
        while (enumerator->enumerate(enumerator, &ts))
        {
                m->add_attribute(m, HA_REMOTE_TS, ts);
        }
        enumerator->destroy(enumerator);
 
+       seg_i = this->kernel->get_segment_spi(this->kernel,
+                       ike_sa->get_my_host(ike_sa), child_sa->get_spi(child_sa, TRUE));
+       seg_o = this->kernel->get_segment_spi(this->kernel,
+                       ike_sa->get_other_host(ike_sa), child_sa->get_spi(child_sa, FALSE));
+       DBG1(DBG_CFG, "handling HA CHILD_SA %s{%d} %#R=== %#R "
+               "(segment in: %d%s, out: %d%s)", child_sa->get_name(child_sa),
+               child_sa->get_reqid(child_sa), local_ts, remote_ts,
+               seg_i, this->segments->is_active(this->segments, seg_i) ? "*" : "",
+               seg_o, this->segments->is_active(this->segments, seg_o) ? "*" : "");
+
        this->socket->push(this->socket, m);
        m->destroy(m);
 
@@ -155,7 +171,7 @@ METHOD(ha_child_t, destroy, void,
  * See header
  */
 ha_child_t *ha_child_create(ha_socket_t *socket, ha_tunnel_t *tunnel,
-                                                       ha_cache_t *cache)
+                                                       ha_segments_t *segments, ha_kernel_t *kernel)
 {
        private_ha_child_t *this;
 
@@ -169,7 +185,8 @@ ha_child_t *ha_child_create(ha_socket_t *socket, ha_tunnel_t *tunnel,
                },
                .socket = socket,
                .tunnel = tunnel,
-               .cache = cache,
+               .segments = segments,
+               .kernel = kernel,
        );
 
        return &this->public;
index 9a28e51..56cd769 100644 (file)
@@ -26,7 +26,7 @@ typedef struct ha_child_t ha_child_t;
 #include "ha_socket.h"
 #include "ha_tunnel.h"
 #include "ha_segments.h"
-#include "ha_cache.h"
+#include "ha_kernel.h"
 
 #include <daemon.h>
 
@@ -51,10 +51,11 @@ struct ha_child_t {
  *
  * @param socket               socket to use for sending synchronization messages
  * @param tunnel               tunnel securing sync messages, if any
- * @param cache                        message resync cache
+ * @param segments             segment handling
+ * @param kernel               kernel helper
  * @return                             CHILD listener
  */
 ha_child_t *ha_child_create(ha_socket_t *socket, ha_tunnel_t *tunnel,
-                                                       ha_cache_t *cache);
+                                                       ha_segments_t *segments, ha_kernel_t *kernel);
 
 #endif /** HA_CHILD_ @}*/
index af45429..2385be3 100644 (file)
@@ -46,6 +46,11 @@ struct private_ha_dispatcher_t {
        ha_cache_t *cache;
 
        /**
+        * Kernel helper
+        */
+       ha_kernel_t *kernel;
+
+       /**
         * Dispatcher job
         */
        callback_job_t *job;
@@ -428,6 +433,7 @@ static void process_child_add(private_ha_dispatcher_t *this,
        u_int16_t inbound_cpi = 0, outbound_cpi = 0;
        u_int8_t mode = MODE_TUNNEL, ipcomp = 0;
        u_int16_t encr = ENCR_UNDEFINED, integ = AUTH_UNDEFINED, len = 0;
+       u_int seg_i, seg_o;
        chunk_t nonce_i = chunk_empty, nonce_r = chunk_empty, secret = chunk_empty;
        chunk_t encr_i, integ_i, encr_r, integ_r;
        linked_list_t *local_ts, *remote_ts;
@@ -594,8 +600,16 @@ static void process_child_add(private_ha_dispatcher_t *this,
                return;
        }
 
-       DBG1(DBG_CFG, "installed HA CHILD_SA '%s' %#R=== %#R",
-                child_sa->get_name(child_sa), local_ts, remote_ts);
+       seg_i = this->kernel->get_segment_spi(this->kernel,
+                                                               ike_sa->get_my_host(ike_sa), inbound_spi);
+       seg_o = this->kernel->get_segment_spi(this->kernel,
+                                                               ike_sa->get_other_host(ike_sa), outbound_spi);
+
+       DBG1(DBG_CFG, "installed HA CHILD_SA %s{%d} %#R=== %#R "
+               "(segment in: %d%s, out: %d%s)", child_sa->get_name(child_sa),
+               child_sa->get_reqid(child_sa), local_ts, remote_ts,
+               seg_i, this->segments->is_active(this->segments, seg_i) ? "*" : "",
+               seg_o, this->segments->is_active(this->segments, seg_o) ? "*" : "");
        child_sa->add_policies(child_sa, local_ts, remote_ts);
        local_ts->destroy_offset(local_ts, offsetof(traffic_selector_t, destroy));
        remote_ts->destroy_offset(remote_ts, offsetof(traffic_selector_t, destroy));
@@ -808,7 +822,7 @@ METHOD(ha_dispatcher_t, destroy, void,
  * See header
  */
 ha_dispatcher_t *ha_dispatcher_create(ha_socket_t *socket,
-                                                                       ha_segments_t *segments, ha_cache_t *cache)
+                       ha_segments_t *segments, ha_cache_t *cache, ha_kernel_t *kernel)
 {
        private_ha_dispatcher_t *this;
 
@@ -820,6 +834,7 @@ ha_dispatcher_t *ha_dispatcher_create(ha_socket_t *socket,
                .socket = socket,
                .segments = segments,
                .cache = cache,
+               .kernel = kernel,
        );
        this->job = callback_job_create((callback_job_cb_t)dispatch,
                                                                        this, NULL, NULL);
index 3190458..3a5ec79 100644 (file)
@@ -24,6 +24,7 @@
 #include "ha_socket.h"
 #include "ha_segments.h"
 #include "ha_cache.h"
+#include "ha_kernel.h"
 
 typedef struct ha_dispatcher_t ha_dispatcher_t;
 
@@ -44,9 +45,10 @@ struct ha_dispatcher_t {
  * @param socket               socket to pull messages from
  * @param segments             segments to control based on received messages
  * @param cache                        message cache to use for resynchronization
+ * @param kernel               kernel helper
  * @return                             dispatcher object
  */
 ha_dispatcher_t *ha_dispatcher_create(ha_socket_t *socket,
-                                                                       ha_segments_t *segments, ha_cache_t *cache);
+                       ha_segments_t *segments, ha_cache_t *cache, ha_kernel_t *kernel);
 
 #endif /** HA_DISPATCHER_ @}*/
index 7428de4..69ba295 100644 (file)
@@ -67,6 +67,22 @@ METHOD(ha_kernel_t, get_segment, u_int,
        return 0;
 }
 
+METHOD(ha_kernel_t, get_segment_spi, u_int,
+       private_ha_kernel_t *this, host_t *host, u_int32_t spi)
+{
+       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_2words(ntohl(addr), ntohl(spi), this->initval);
+
+               return (((u_int64_t)hash * this->count) >> 32) + 1;
+       }
+       return 0;
+}
+
 /**
  * Activate/Deactivate a segment for a given clusterip file
  */
@@ -206,6 +222,7 @@ ha_kernel_t *ha_kernel_create(u_int count)
        INIT(this,
                .public = {
                        .get_segment = _get_segment,
+                       .get_segment_spi = _get_segment_spi,
                        .activate = _activate,
                        .deactivate = _deactivate,
                        .destroy = _destroy,
index b9341f4..5e8c054 100644 (file)
@@ -39,6 +39,15 @@ struct ha_kernel_t {
        u_int (*get_segment)(ha_kernel_t *this, host_t *host);
 
        /**
+        * Get the segment a host/SPI is in, as used for CHILD_SA segmentation.
+        *
+        * @param host          host to get segment for
+        * @param spi           SPI to include in hash
+        * @return                      segment number
+        */
+       u_int (*get_segment_spi)(ha_kernel_t *this, host_t *host, u_int32_t spi);
+
+       /**
         * Activate a segment at kernel level for all cluster addresses.
         *
         * @param segment       segment to activate
index cfce45e..b20868b 100644 (file)
@@ -156,9 +156,10 @@ plugin_t *ha_plugin_create()
                this->ctl = ha_ctl_create(this->segments, this->cache);
        }
        this->dispatcher = ha_dispatcher_create(this->socket, this->segments,
-                                                                                       this->cache);
+                                                                                       this->cache, this->kernel);
        this->ike = ha_ike_create(this->socket, this->tunnel, this->cache);
-       this->child = ha_child_create(this->socket, this->tunnel, this->cache);
+       this->child = ha_child_create(this->socket, this->tunnel, this->segments,
+                                                                 this->kernel);
        charon->bus->add_listener(charon->bus, &this->segments->listener);
        charon->bus->add_listener(charon->bus, &this->ike->listener);
        charon->bus->add_listener(charon->bus, &this->child->listener);
index bdd850f..c8748ab 100644 (file)
@@ -343,6 +343,12 @@ static job_requeue_t send_status(private_ha_segments_t *this)
        return JOB_REQUEUE_NONE;
 }
 
+METHOD(ha_segments_t, is_active, bool,
+       private_ha_segments_t *this, u_int segment)
+{
+       return (this->active & SEGMENTS_BIT(segment)) != 0;
+}
+
 METHOD(ha_segments_t, destroy, void,
        private_ha_segments_t *this)
 {
@@ -370,6 +376,7 @@ ha_segments_t *ha_segments_create(ha_socket_t *socket, ha_kernel_t *kernel,
                        .activate = _activate,
                        .deactivate = _deactivate,
                        .handle_status = _handle_status,
+                       .is_active = _is_active,
                        .destroy = _destroy,
                },
                .socket = socket,
index 1699f7b..eb9e5c1 100644 (file)
@@ -75,6 +75,14 @@ struct ha_segments_t {
        void (*handle_status)(ha_segments_t *this, segment_mask_t mask);
 
        /**
+        * Check if a given segment is currently active.
+        *
+        * @param segment       segment to check
+        * @return                      TRUE if segment active
+        */
+       bool (*is_active)(ha_segments_t *this, u_int segment);
+
+       /**
         * Destroy a ha_segments_t.
         */
        void (*destroy)(ha_segments_t *this);