Drop overlapping segments only if we have no active SAs on it
authorMartin Willi <martin@strongswan.org>
Tue, 29 Sep 2009 14:40:58 +0000 (16:40 +0200)
committerMartin Willi <martin@revosec.ch>
Wed, 7 Apr 2010 11:55:16 +0000 (13:55 +0200)
src/charon/plugins/ha/ha_segments.c

index 59091a6..4a96b24 100644 (file)
@@ -323,24 +323,43 @@ static bool alert_hook(private_ha_segments_t *this, ike_sa_t *ike_sa,
 }
 
 /**
+ * Get the number of SAs in a segment.
+ */
+static u_int get_sa_count(private_ha_segments_t *this)
+{
+       enumerator_t *enumerator;
+       ike_sa_t *ike_sa;
+       u_int count = 0;
+
+       enumerator = charon->ike_sa_manager->create_enumerator(charon->ike_sa_manager);
+       while (enumerator->enumerate(enumerator, &ike_sa))
+       {
+               if (ike_sa->get_state(ike_sa) != IKE_ESTABLISHED)
+               {
+                       continue;
+               }
+               if (this->tunnel && this->tunnel->is_sa(this->tunnel, ike_sa))
+               {
+                       continue;
+               }
+               count++;
+       }
+       enumerator->destroy(enumerator);
+       return count;
+}
+
+/**
  * Implementation of ha_segments_t.handle_status
  */
 static void handle_status(private_ha_segments_t *this, segment_mask_t mask)
 {
        segment_mask_t missing, overlap;
-       int i, active = 0;
+       int i;
 
        this->mutex->lock(this->mutex);
 
        missing = ~(this->active | mask);
        overlap = this->active & mask;
-       for (i = 1; i <= this->count; i++)
-       {
-               if (this->active & SEGMENTS_BIT(i))
-               {
-                       active++;
-               }
-       }
 
        /* Activate any missing segment. The master will disable overlapping
         * segments if both nodes activate the missing segments simultaneously. */
@@ -359,16 +378,15 @@ static void handle_status(private_ha_segments_t *this, segment_mask_t mask)
                {
                        if (overlap & SEGMENTS_BIT(i))
                        {
-                               DBG1(DBG_CFG, "HA segment %d handled twice", i);
-                               if (active > this->count)
+                               if (get_sa_count(this))
                                {
-                                       enable_disable(this, i, FALSE, TRUE);
-                                       active--;
+                                       DBG1(DBG_CFG, "HA segment %d overlaps, taking over", i);
+                                       enable_disable(this, i, TRUE, TRUE);
                                }
                                else
                                {
-                                       enable_disable(this, i, TRUE, TRUE);
-                                       active++;
+                                       DBG1(DBG_CFG, "HA segment %d overlaps, dropping", i);
+                                       enable_disable(this, i, FALSE, TRUE);
                                }
                        }
                }