aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2017-05-19 16:14:40 +0200
committerTobias Brunner <tobias@strongswan.org>2017-05-23 18:02:15 +0200
commit389e4b8e673fe679c3074f5563c3581b3271ef2a (patch)
treeed16eaf0bf0bc7a42f405478eff9924cc33cc6ea /src
parentd140b3bd3f7ff6f6b7bdc5202bd0dee7f39fa699 (diff)
downloadstrongswan-389e4b8e673fe679c3074f5563c3581b3271ef2a.tar.bz2
strongswan-389e4b8e673fe679c3074f5563c3581b3271ef2a.tar.xz
ike: Use optional jitter to calculate retransmission timeouts
Also adds an optional limit to avoid very high retransmission timeouts with high numbers of retries.
Diffstat (limited to 'src')
-rw-r--r--src/libcharon/sa/ikev1/task_manager_v1.c31
-rw-r--r--src/libcharon/sa/ikev2/task_manager_v2.c26
-rw-r--r--src/libcharon/sa/task_manager.h5
3 files changed, 57 insertions, 5 deletions
diff --git a/src/libcharon/sa/ikev1/task_manager_v1.c b/src/libcharon/sa/ikev1/task_manager_v1.c
index 1da17ee50..89077b013 100644
--- a/src/libcharon/sa/ikev1/task_manager_v1.c
+++ b/src/libcharon/sa/ikev1/task_manager_v1.c
@@ -210,6 +210,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;
+
+ /**
* Sequence number for sending DPD requests
*/
uint32_t dpd_send;
@@ -345,7 +355,7 @@ static status_t retransmit_packet(private_task_manager_t *this, uint32_t seqnr,
u_int mid, u_int retransmitted, array_t *packets)
{
packet_t *packet;
- uint32_t t;
+ uint32_t t, max_jitter;
array_get(packets, 0, &packet);
if (retransmitted > this->retransmit_tries)
@@ -356,6 +366,15 @@ static status_t retransmit_packet(private_task_manager_t *this, uint32_t seqnr,
}
t = (uint32_t)(this->retransmit_timeout * 1000.0 *
pow(this->retransmit_base, retransmitted));
+ if (this->retransmit_jitter)
+ {
+ max_jitter = (t / 100.0) * this->retransmit_jitter;
+ t -= max_jitter * (random() / (RAND_MAX + 1.0));
+ }
+ if (this->retransmit_limit)
+ {
+ t = min(t, this->retransmit_limit);
+ }
if (retransmitted)
{
DBG1(DBG_IKE, "sending retransmit %u of %s message ID %u, seq %u",
@@ -2034,11 +2053,15 @@ task_manager_v1_t *task_manager_v1_create(ike_sa_t *ike_sa)
.active_tasks = linked_list_create(),
.passive_tasks = linked_list_create(),
.retransmit_tries = lib->settings->get_int(lib->settings,
- "%s.retransmit_tries", RETRANSMIT_TRIES, lib->ns),
+ "%s.retransmit_tries", RETRANSMIT_TRIES, lib->ns),
.retransmit_timeout = lib->settings->get_double(lib->settings,
- "%s.retransmit_timeout", RETRANSMIT_TIMEOUT, lib->ns),
+ "%s.retransmit_timeout", RETRANSMIT_TIMEOUT, lib->ns),
.retransmit_base = lib->settings->get_double(lib->settings,
- "%s.retransmit_base", RETRANSMIT_BASE, lib->ns),
+ "%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,
);
if (!this->rng)
diff --git a/src/libcharon/sa/ikev2/task_manager_v2.c b/src/libcharon/sa/ikev2/task_manager_v2.c
index e4a16faf0..5bd308f7a 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_jitter)
+ {
+ max_jitter = (timeout / 100.0) * this->retransmit_jitter;
+ timeout -= max_jitter * (random() / (RAND_MAX + 1.0));
+ }
+ if (this->retransmit_limit)
+ {
+ timeout = min(timeout, this->retransmit_limit);
+ }
}
else
{
@@ -2151,6 +2171,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),
);
diff --git a/src/libcharon/sa/task_manager.h b/src/libcharon/sa/task_manager.h
index 7e9262291..4d3f9bef5 100644
--- a/src/libcharon/sa/task_manager.h
+++ b/src/libcharon/sa/task_manager.h
@@ -48,6 +48,11 @@ typedef enum task_queue_t task_queue_t;
#define RETRANSMIT_TRIES 5
/**
+ * Maximum jitter in percent.
+ */
+#define RETRANSMIT_JITTER_MAX 20
+
+/**
* Interval for mobike routability checks in ms.
*/
#define ROUTEABILITY_CHECK_INTERVAL 2500