diff options
Diffstat (limited to 'src/libcharon/sa/ikev2/task_manager_v2.c')
-rw-r--r-- | src/libcharon/sa/ikev2/task_manager_v2.c | 47 |
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), ); |