Fixed a race condition when querying stats of a child_sa in different order.
This commit is contained in:
@@ -146,8 +146,7 @@ static void log_ike_sa(FILE *out, ike_sa_t *ike_sa, bool all)
|
|||||||
*/
|
*/
|
||||||
static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all)
|
static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all)
|
||||||
{
|
{
|
||||||
u_int32_t rekey, now = time(NULL);
|
time_t use_in, use_out, rekey, now = time(NULL);
|
||||||
u_int32_t use_in, use_out;
|
|
||||||
u_int64_t bytes_in, bytes_out;
|
u_int64_t bytes_in, bytes_out;
|
||||||
proposal_t *proposal;
|
proposal_t *proposal;
|
||||||
child_cfg_t *config = child_sa->get_config(child_sa);
|
child_cfg_t *config = child_sa->get_config(child_sa);
|
||||||
@@ -207,26 +206,18 @@ static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bytes_in = child_sa->get_usebytes(child_sa, TRUE);
|
child_sa->get_usestats(child_sa, TRUE, &use_in, &bytes_in);
|
||||||
fprintf(out, ", %lu bytes_i", bytes_in);
|
fprintf(out, ", %lu bytes_i", bytes_in);
|
||||||
if (bytes_in)
|
if (use_in)
|
||||||
{
|
{
|
||||||
use_in = child_sa->get_usetime(child_sa, TRUE);
|
fprintf(out, " (%ds ago)", now - use_in);
|
||||||
if (use_in)
|
|
||||||
{
|
|
||||||
fprintf(out, " (%ds ago)", now - use_in);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bytes_out = child_sa->get_usebytes(child_sa, FALSE);
|
child_sa->get_usestats(child_sa, FALSE, &use_out, &bytes_out);
|
||||||
fprintf(out, ", %lu bytes_o", bytes_out);
|
fprintf(out, ", %lu bytes_o", bytes_out);
|
||||||
if (bytes_out)
|
if (use_out)
|
||||||
{
|
{
|
||||||
use_out = child_sa->get_usetime(child_sa, FALSE);
|
fprintf(out, " (%ds ago)", now - use_out);
|
||||||
if (use_out)
|
|
||||||
{
|
|
||||||
fprintf(out, " (%ds ago)", now - use_out);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
fprintf(out, ", rekeying ");
|
fprintf(out, ", rekeying ");
|
||||||
|
|
||||||
|
|||||||
+19
-15
@@ -380,7 +380,7 @@ static enumerator_t* create_policy_enumerator(private_child_sa_t *this)
|
|||||||
* are available, and NOT_SUPPORTED if the kernel interface does not support
|
* are available, and NOT_SUPPORTED if the kernel interface does not support
|
||||||
* quering the usebytes.
|
* quering the usebytes.
|
||||||
*/
|
*/
|
||||||
static bool update_usebytes(private_child_sa_t *this, bool inbound)
|
static status_t update_usebytes(private_child_sa_t *this, bool inbound)
|
||||||
{
|
{
|
||||||
status_t status = FAILED;
|
status_t status = FAILED;
|
||||||
u_int64_t bytes;
|
u_int64_t bytes;
|
||||||
@@ -427,19 +427,14 @@ static bool update_usebytes(private_child_sa_t *this, bool inbound)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of child_sa_t.get_usetime
|
* updates the cached usetime
|
||||||
*/
|
*/
|
||||||
static u_int32_t get_usetime(private_child_sa_t *this, bool inbound)
|
static void update_usetime(private_child_sa_t *this, bool inbound)
|
||||||
{
|
{
|
||||||
enumerator_t *enumerator;
|
enumerator_t *enumerator;
|
||||||
traffic_selector_t *my_ts, *other_ts;
|
traffic_selector_t *my_ts, *other_ts;
|
||||||
u_int32_t last_use = 0;
|
u_int32_t last_use = 0;
|
||||||
|
|
||||||
if (update_usebytes(this, inbound) == FAILED)
|
|
||||||
{ /* no SPI or no traffic since last update */
|
|
||||||
return inbound ? this->my_usetime : this->other_usetime;
|
|
||||||
}
|
|
||||||
|
|
||||||
enumerator = create_policy_enumerator(this);
|
enumerator = create_policy_enumerator(this);
|
||||||
while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
|
while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
|
||||||
{
|
{
|
||||||
@@ -479,16 +474,26 @@ static u_int32_t get_usetime(private_child_sa_t *this, bool inbound)
|
|||||||
{
|
{
|
||||||
this->other_usetime = last_use;
|
this->other_usetime = last_use;
|
||||||
}
|
}
|
||||||
return last_use;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of child_sa_t.get_usebytes
|
* Implementation of child_sa_t.get_usestats
|
||||||
*/
|
*/
|
||||||
static u_int64_t get_usebytes(private_child_sa_t *this, bool inbound)
|
static void get_usestats(private_child_sa_t *this, bool inbound,
|
||||||
|
time_t *time, u_int64_t *bytes)
|
||||||
{
|
{
|
||||||
update_usebytes(this, inbound);
|
if (update_usebytes(this, inbound) != FAILED)
|
||||||
return inbound ? this->my_usebytes : this->other_usebytes;
|
{ /* there was traffic since last update or the KI does not support it */
|
||||||
|
update_usetime(this, inbound);
|
||||||
|
}
|
||||||
|
if (time)
|
||||||
|
{
|
||||||
|
*time = inbound ? this->my_usetime : this->other_usetime;
|
||||||
|
}
|
||||||
|
if (bytes)
|
||||||
|
{
|
||||||
|
*bytes = inbound ? this->my_usebytes : this->other_usebytes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -869,8 +874,7 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
|
|||||||
this->public.get_proposal = (proposal_t*(*)(child_sa_t*))get_proposal;
|
this->public.get_proposal = (proposal_t*(*)(child_sa_t*))get_proposal;
|
||||||
this->public.set_proposal = (void(*)(child_sa_t*, proposal_t *proposal))set_proposal;
|
this->public.set_proposal = (void(*)(child_sa_t*, proposal_t *proposal))set_proposal;
|
||||||
this->public.get_lifetime = (u_int32_t(*)(child_sa_t*, bool))get_lifetime;
|
this->public.get_lifetime = (u_int32_t(*)(child_sa_t*, bool))get_lifetime;
|
||||||
this->public.get_usetime = (u_int32_t(*)(child_sa_t*, bool))get_usetime;
|
this->public.get_usestats = (void(*)(child_sa_t*,bool,time_t*,u_int64_t*))get_usestats;
|
||||||
this->public.get_usebytes = (u_int64_t(*)(child_sa_t*, bool))get_usebytes;
|
|
||||||
this->public.has_encap = (bool(*)(child_sa_t*))has_encap;
|
this->public.has_encap = (bool(*)(child_sa_t*))has_encap;
|
||||||
this->public.get_ipcomp = (ipcomp_transform_t(*)(child_sa_t*))get_ipcomp;
|
this->public.get_ipcomp = (ipcomp_transform_t(*)(child_sa_t*))get_ipcomp;
|
||||||
this->public.set_ipcomp = (void(*)(child_sa_t*,ipcomp_transform_t))set_ipcomp;
|
this->public.set_ipcomp = (void(*)(child_sa_t*,ipcomp_transform_t))set_ipcomp;
|
||||||
|
|||||||
@@ -237,20 +237,14 @@ struct child_sa_t {
|
|||||||
u_int32_t (*get_lifetime)(child_sa_t *this, bool hard);
|
u_int32_t (*get_lifetime)(child_sa_t *this, bool hard);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get last use time of the CHILD_SA.
|
* Get last use time and the number of bytes processed.
|
||||||
*
|
|
||||||
* @param inbound TRUE for inbound traffic, FALSE for outbound
|
|
||||||
* @return time of last use in seconds
|
|
||||||
*/
|
|
||||||
u_int32_t (*get_usetime)(child_sa_t *this, bool inbound);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get number of bytes processed by CHILD_SA.
|
|
||||||
*
|
*
|
||||||
* @param inbound TRUE for inbound traffic, FALSE for outbound
|
* @param inbound TRUE for inbound traffic, FALSE for outbound
|
||||||
* @return number of processed bytes
|
* @param[out] time time of last use in seconds (NULL to ignore)
|
||||||
|
* @param[out] bytes number of processed bytes (NULL to ignore)
|
||||||
*/
|
*/
|
||||||
u_int64_t (*get_usebytes)(child_sa_t *this, bool inbound);
|
void (*get_usestats)(child_sa_t *this, bool inbound, time_t *time,
|
||||||
|
u_int64_t *bytes);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the traffic selectors list added for one side.
|
* Get the traffic selectors list added for one side.
|
||||||
|
|||||||
@@ -260,7 +260,7 @@ static time_t get_use_time(private_ike_sa_t* this, bool inbound)
|
|||||||
{
|
{
|
||||||
enumerator_t *enumerator;
|
enumerator_t *enumerator;
|
||||||
child_sa_t *child_sa;
|
child_sa_t *child_sa;
|
||||||
time_t use_time;
|
time_t use_time, current;
|
||||||
|
|
||||||
if (inbound)
|
if (inbound)
|
||||||
{
|
{
|
||||||
@@ -273,7 +273,8 @@ static time_t get_use_time(private_ike_sa_t* this, bool inbound)
|
|||||||
enumerator = this->child_sas->create_enumerator(this->child_sas);
|
enumerator = this->child_sas->create_enumerator(this->child_sas);
|
||||||
while (enumerator->enumerate(enumerator, &child_sa))
|
while (enumerator->enumerate(enumerator, &child_sa))
|
||||||
{
|
{
|
||||||
use_time = max(use_time, child_sa->get_usetime(child_sa, inbound));
|
child_sa->get_usestats(child_sa, inbound, ¤t, NULL);
|
||||||
|
use_time = max(use_time, current);
|
||||||
}
|
}
|
||||||
enumerator->destroy(enumerator);
|
enumerator->destroy(enumerator);
|
||||||
|
|
||||||
|
|||||||
@@ -240,17 +240,19 @@ static void log_children(private_child_delete_t *this)
|
|||||||
{
|
{
|
||||||
iterator_t *iterator;
|
iterator_t *iterator;
|
||||||
child_sa_t *child_sa;
|
child_sa_t *child_sa;
|
||||||
|
u_int64_t bytes_in, bytes_out;
|
||||||
|
|
||||||
iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
|
iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
|
||||||
while (iterator->iterate(iterator, (void**)&child_sa))
|
while (iterator->iterate(iterator, (void**)&child_sa))
|
||||||
{
|
{
|
||||||
|
child_sa->get_usestats(child_sa, TRUE, NULL, &bytes_in);
|
||||||
|
child_sa->get_usestats(child_sa, FALSE, NULL, &bytes_out);
|
||||||
|
|
||||||
DBG0(DBG_IKE, "closing CHILD_SA %s{%d} "
|
DBG0(DBG_IKE, "closing CHILD_SA %s{%d} "
|
||||||
"with SPIs %.8x_i (%lu bytes) %.8x_o (%lu bytes) and TS %#R=== %#R",
|
"with SPIs %.8x_i (%lu bytes) %.8x_o (%lu bytes) and TS %#R=== %#R",
|
||||||
child_sa->get_name(child_sa), child_sa->get_reqid(child_sa),
|
child_sa->get_name(child_sa), child_sa->get_reqid(child_sa),
|
||||||
ntohl(child_sa->get_spi(child_sa, TRUE)),
|
ntohl(child_sa->get_spi(child_sa, TRUE)), bytes_in,
|
||||||
child_sa->get_usebytes(child_sa, TRUE),
|
ntohl(child_sa->get_spi(child_sa, FALSE)), bytes_out,
|
||||||
ntohl(child_sa->get_spi(child_sa, FALSE)),
|
|
||||||
child_sa->get_usebytes(child_sa, FALSE),
|
|
||||||
child_sa->get_traffic_selectors(child_sa, TRUE),
|
child_sa->get_traffic_selectors(child_sa, TRUE),
|
||||||
child_sa->get_traffic_selectors(child_sa, FALSE));
|
child_sa->get_traffic_selectors(child_sa, FALSE));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user