]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
Do not automatically take over segments, as we need to resync first
authorMartin Willi <martin@strongswan.org>
Wed, 30 Sep 2009 08:36:27 +0000 (10:36 +0200)
committerMartin Willi <martin@revosec.ch>
Wed, 7 Apr 2010 11:55:16 +0000 (13:55 +0200)
src/charon/plugins/ha/ha_dispatcher.c
src/charon/plugins/ha/ha_kernel.c
src/charon/plugins/ha/ha_segments.c

index b9d3f6322308dc6274fe3e7189533a6c65bc8f73..f2eabc67217b374c30cd2a1d93f9c238885ea991 100644 (file)
@@ -591,10 +591,12 @@ static void process_segment(private_ha_dispatcher_t *this,
                        case HA_SEGMENT:
                                if (take)
                                {
+                                       DBG1(DBG_CFG, "remote node takes segment %d", value.u16);
                                        this->segments->deactivate(this->segments, value.u16, FALSE);
                                }
                                else
                                {
+                                       DBG1(DBG_CFG, "remote node drops segment %d", value.u16);
                                        this->segments->activate(this->segments, value.u16, FALSE);
                                }
                                break;
index 69e1c9e28c0abcbacdcab71c1ce2a9ef3ea4e10b..0ad9c22c350bfe7fecbf02dcfb8aa1e390bf0a6f 100644 (file)
@@ -175,9 +175,9 @@ static void deactivate(private_ha_kernel_t *this, u_int segment)
 }
 
 /**
- * Enable all not-yet enabled segments on all clusterip addresses
+ * Disable all not-yet disabled segments on all clusterip addresses
  */
-static void activate_all(private_ha_kernel_t *this)
+static void disable_all(private_ha_kernel_t *this)
 {
        enumerator_t *enumerator;
        segment_mask_t active;
@@ -190,9 +190,9 @@ static void activate_all(private_ha_kernel_t *this)
                active = get_active(this, file);
                for (i = 1; i <= this->count; i++)
                {
-                       if (!(active & SEGMENTS_BIT(i)))
+                       if (active & SEGMENTS_BIT(i))
                        {
-                               enable_disable(this, i, file, TRUE);
+                               enable_disable(this, i, file, FALSE);
                        }
                }
        }
@@ -222,7 +222,7 @@ ha_kernel_t *ha_kernel_create(u_int count)
        this->initval = 0;
        this->count = count;
 
-       activate_all(this);
+       disable_all(this);
 
        return &this->public;
 }
index 4a96b24f4835da003a619304c2c61d723453ac59..9b7490c94a9fc29b8440ac75d131482219674a0f 100644 (file)
@@ -323,29 +323,39 @@ static bool alert_hook(private_ha_segments_t *this, ike_sa_t *ike_sa,
 }
 
 /**
- * Get the number of SAs in a segment.
+ * Monitor heartbeat activity of remote node
  */
-static u_int get_sa_count(private_ha_segments_t *this)
+static job_requeue_t watchdog(private_ha_segments_t *this)
 {
-       enumerator_t *enumerator;
-       ike_sa_t *ike_sa;
-       u_int count = 0;
+       int oldstate;
+       bool timeout;
 
-       enumerator = charon->ike_sa_manager->create_enumerator(charon->ike_sa_manager);
-       while (enumerator->enumerate(enumerator, &ike_sa))
+       this->mutex->lock(this->mutex);
+       pthread_cleanup_push((void*)this->mutex->unlock, this->mutex);
+       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
+       timeout = this->condvar->timed_wait(this->condvar, this->mutex,
+                                                                               HEARTBEAT_TIMEOUT);
+       pthread_setcancelstate(oldstate, NULL);
+       pthread_cleanup_pop(TRUE);
+       if (timeout)
        {
-               if (ike_sa->get_state(ike_sa) != IKE_ESTABLISHED)
-               {
-                       continue;
-               }
-               if (this->tunnel && this->tunnel->is_sa(this->tunnel, ike_sa))
-               {
-                       continue;
-               }
-               count++;
+               DBG1(DBG_CFG, "no heartbeat received, taking all segments");
+               activate(this, 0, TRUE);
+               /* disable heartbeat detection util we get one */
+               this->job = NULL;
+               return JOB_REQUEUE_NONE;
        }
-       enumerator->destroy(enumerator);
-       return count;
+       return JOB_REQUEUE_DIRECT;
+}
+
+/**
+ * Start the heartbeat detection thread
+ */
+static void start_watchdog(private_ha_segments_t *this)
+{
+       this->job = callback_job_create((callback_job_cb_t)watchdog,
+                                                                       this, NULL, NULL);
+       charon->processor->queue_job(charon->processor, (job_t*)this->job);
 }
 
 /**
@@ -353,46 +363,38 @@ static u_int get_sa_count(private_ha_segments_t *this)
  */
 static void handle_status(private_ha_segments_t *this, segment_mask_t mask)
 {
-       segment_mask_t missing, overlap;
+       segment_mask_t missing;
        int i;
 
        this->mutex->lock(this->mutex);
 
        missing = ~(this->active | mask);
-       overlap = this->active & mask;
 
-       /* Activate any missing segment. The master will disable overlapping
-        * segments if both nodes activate the missing segments simultaneously. */
        for (i = 1; i <= this->count; i++)
        {
                if (missing & SEGMENTS_BIT(i))
                {
-                       DBG1(DBG_CFG, "HA segment %d was not handled", i);
-                       enable_disable(this, i, TRUE, TRUE);
-               }
-       }
-       if (this->master && overlap)
-       {
-               /* Disable overlapping segment on one node, controlled by master */
-               for (i = 1; i <= this->count; i++)
-               {
-                       if (overlap & SEGMENTS_BIT(i))
+                       if (this->master != i % 2)
                        {
-                               if (get_sa_count(this))
-                               {
-                                       DBG1(DBG_CFG, "HA segment %d overlaps, taking over", i);
-                                       enable_disable(this, i, TRUE, TRUE);
-                               }
-                               else
-                               {
-                                       DBG1(DBG_CFG, "HA segment %d overlaps, dropping", i);
-                                       enable_disable(this, i, FALSE, TRUE);
-                               }
+                               DBG1(DBG_CFG, "HA segment %d was not handled, taking", i);
+                               enable_disable(this, i, TRUE, TRUE);
+                       }
+                       else
+                       {
+                               DBG1(DBG_CFG, "HA segment %d was not handled, dropping", i);
+                               enable_disable(this, i, FALSE, TRUE);
                        }
                }
        }
+
        this->mutex->unlock(this->mutex);
        this->condvar->signal(this->condvar);
+
+       if (!this->job)
+       {
+               DBG1(DBG_CFG, "received heartbeat, reenabling watchdog");
+               start_watchdog(this);
+       }
 }
 
 /**
@@ -424,34 +426,15 @@ static job_requeue_t send_status(private_ha_segments_t *this)
        return JOB_REQUEUE_NONE;
 }
 
-/**
- * Monitor heartbeat activity of remote node
- */
-static job_requeue_t watchdog(private_ha_segments_t *this)
-{
-       int oldstate;
-       bool timeout;
-
-       this->mutex->lock(this->mutex);
-       pthread_cleanup_push((void*)this->mutex->unlock, this->mutex);
-       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
-       timeout = this->condvar->timed_wait(this->condvar, this->mutex,
-                                                                               HEARTBEAT_TIMEOUT);
-       pthread_setcancelstate(oldstate, NULL);
-       pthread_cleanup_pop(TRUE);
-       if (timeout)
-       {       /* didn't get a heartbeat, take all segments */
-               activate(this, 0, TRUE);
-       }
-       return JOB_REQUEUE_DIRECT;
-}
-
 /**
  * Implementation of ha_segments_t.destroy.
  */
 static void destroy(private_ha_segments_t *this)
 {
-       this->job->cancel(this->job);
+       if (this->job)
+       {
+               this->job->cancel(this->job);
+       }
        this->mutex->destroy(this->mutex);
        this->condvar->destroy(this->condvar);
        free(this);
@@ -464,7 +447,6 @@ ha_segments_t *ha_segments_create(ha_socket_t *socket, ha_kernel_t *kernel,
                                        ha_tunnel_t *tunnel, char *local, char *remote, u_int count)
 {
        private_ha_segments_t *this = malloc_thing(private_ha_segments_t);
-       int i;
 
        memset(&this->public.listener, 0, sizeof(listener_t));
        this->public.listener.alert = (bool(*)(listener_t*, ike_sa_t *, alert_t, va_list))alert_hook;
@@ -482,19 +464,12 @@ ha_segments_t *ha_segments_create(ha_socket_t *socket, ha_kernel_t *kernel,
        this->count = count;
        this->master = strcmp(local, remote) > 0;
 
-       /* initially all segments are active */
+       /* initially all segments are deactivated */
        this->active = 0;
-       for (i = 1; i <= count; i++)
-       {
-               this->active |= SEGMENTS_BIT(i);
-       }
 
        send_status(this);
 
-       /* start heartbeat detection thread */
-       this->job = callback_job_create((callback_job_cb_t)watchdog,
-                                                                       this, NULL, NULL);
-       charon->processor->queue_job(charon->processor, (job_t*)this->job);
+       start_watchdog(this);
 
        return &this->public;
 }