Drop overlapping segments only if we have no active SAs on it

This commit is contained in:
Martin Willi
2010-04-07 13:55:16 +02:00
committed by Martin Willi
parent a05e388540
commit ea249cc6f0
+32 -14
View File
@@ -322,25 +322,44 @@ static bool alert_hook(private_ha_segments_t *this, ike_sa_t *ike_sa,
return TRUE; return TRUE;
} }
/**
* 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 * Implementation of ha_segments_t.handle_status
*/ */
static void handle_status(private_ha_segments_t *this, segment_mask_t mask) static void handle_status(private_ha_segments_t *this, segment_mask_t mask)
{ {
segment_mask_t missing, overlap; segment_mask_t missing, overlap;
int i, active = 0; int i;
this->mutex->lock(this->mutex); this->mutex->lock(this->mutex);
missing = ~(this->active | mask); missing = ~(this->active | mask);
overlap = 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 /* Activate any missing segment. The master will disable overlapping
* segments if both nodes activate the missing segments simultaneously. */ * 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)) if (overlap & SEGMENTS_BIT(i))
{ {
DBG1(DBG_CFG, "HA segment %d handled twice", i); if (get_sa_count(this))
if (active > this->count)
{ {
enable_disable(this, i, FALSE, TRUE); DBG1(DBG_CFG, "HA segment %d overlaps, taking over", i);
active--; enable_disable(this, i, TRUE, TRUE);
} }
else else
{ {
enable_disable(this, i, TRUE, TRUE); DBG1(DBG_CFG, "HA segment %d overlaps, dropping", i);
active++; enable_disable(this, i, FALSE, TRUE);
} }
} }
} }