summaryrefslogtreecommitdiff
path: root/src/libcharon/sa/ikev2/task_manager_v2.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcharon/sa/ikev2/task_manager_v2.c')
-rw-r--r--src/libcharon/sa/ikev2/task_manager_v2.c47
1 files changed, 39 insertions, 8 deletions
diff --git a/src/libcharon/sa/ikev2/task_manager_v2.c b/src/libcharon/sa/ikev2/task_manager_v2.c
index e4a16faf0..c2ddbc588 100644
--- a/src/libcharon/sa/ikev2/task_manager_v2.c
+++ b/src/libcharon/sa/ikev2/task_manager_v2.c
@@ -161,6 +161,16 @@ struct private_task_manager_t {
double retransmit_base;
/**
+ * Jitter to apply to calculated retransmit timeout (in percent)
+ */
+ u_int retransmit_jitter;
+
+ /**
+ * Limit retransmit timeout to this value
+ */
+ uint32_t retransmit_limit;
+
+ /**
* Use make-before-break instead of break-before-make reauth?
*/
bool make_before_break;
@@ -321,7 +331,7 @@ METHOD(task_manager_t, retransmit, status_t,
if (message_id == this->initiating.mid &&
array_count(this->initiating.packets))
{
- uint32_t timeout;
+ uint32_t timeout, max_jitter;
job_t *job;
enumerator_t *enumerator;
packet_t *packet;
@@ -351,6 +361,16 @@ METHOD(task_manager_t, retransmit, status_t,
{
timeout = (uint32_t)(this->retransmit_timeout * 1000.0 *
pow(this->retransmit_base, this->initiating.retransmitted));
+
+ if (this->retransmit_limit)
+ {
+ timeout = min(timeout, this->retransmit_limit);
+ }
+ if (this->retransmit_jitter)
+ {
+ max_jitter = (timeout / 100.0) * this->retransmit_jitter;
+ timeout -= max_jitter * (random() / (RAND_MAX + 1.0));
+ }
}
else
{
@@ -2059,13 +2079,20 @@ METHOD(task_manager_t, reset, void,
this->reset = TRUE;
}
-/**
- * Filter queued tasks
- */
-static bool filter_queued(void *unused, queued_task_t **queued, task_t **task)
+CALLBACK(filter_queued, bool,
+ void *unused, enumerator_t *orig, va_list args)
{
- *task = (*queued)->task;
- return TRUE;
+ queued_task_t *queued;
+ task_t **task;
+
+ VA_ARGS_VGET(args, task);
+
+ if (orig->enumerate(orig, &queued))
+ {
+ *task = queued->task;
+ return TRUE;
+ }
+ return FALSE;
}
METHOD(task_manager_t, create_task_enumerator, enumerator_t*,
@@ -2080,7 +2107,7 @@ METHOD(task_manager_t, create_task_enumerator, enumerator_t*,
case TASK_QUEUE_QUEUED:
return enumerator_create_filter(
array_create_enumerator(this->queued_tasks),
- (void*)filter_queued, NULL, NULL);
+ filter_queued, NULL, NULL);
default:
return enumerator_create_empty();
}
@@ -2151,6 +2178,10 @@ task_manager_v2_t *task_manager_v2_create(ike_sa_t *ike_sa)
"%s.retransmit_timeout", RETRANSMIT_TIMEOUT, lib->ns),
.retransmit_base = lib->settings->get_double(lib->settings,
"%s.retransmit_base", RETRANSMIT_BASE, lib->ns),
+ .retransmit_jitter = min(lib->settings->get_int(lib->settings,
+ "%s.retransmit_jitter", 0, lib->ns), RETRANSMIT_JITTER_MAX),
+ .retransmit_limit = lib->settings->get_int(lib->settings,
+ "%s.retransmit_limit", 0, lib->ns) * 1000,
.make_before_break = lib->settings->get_bool(lib->settings,
"%s.make_before_break", FALSE, lib->ns),
);