From 77d4a0281afc3e84a58589e2b10e81d2a39ebcff Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 12 Aug 2013 11:23:34 +0200 Subject: kernel-netlink: Ensure address changes are not missed in roam events If multiple roam events are triggered within ROAM_DELAY, only one job is created. The old code set the address flag to the value of the last triggering call. So if a route change followed an address change within ROAM_DELAY the address change was missed by the upper layers, e.g. causing it not to update the list of addresses via MOBIKE. The new code now keeps the state of the address flag until the job is actually executed, which still has some issues. For instance, if an address disappears and reappears within ROAM_RELAY, the flag would not have to be set to TRUE. So address updates might occasionally get triggered where none would actually be required. Fixes #374. --- .../plugins/kernel_netlink/kernel_netlink_net.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c') diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c index e129ab131..89fb076ad 100644 --- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c +++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c @@ -393,6 +393,11 @@ struct private_kernel_netlink_net_t { */ timeval_t next_roam; + /** + * roam event due to address change + */ + bool roam_address; + /** * lock to check and update roam event time */ @@ -696,9 +701,15 @@ static host_t *get_interface_address(private_kernel_netlink_net_t *this, /** * callback function that raises the delayed roam event */ -static job_requeue_t roam_event(uintptr_t address) +static job_requeue_t roam_event(private_kernel_netlink_net_t *this) { - hydra->kernel_interface->roam(hydra->kernel_interface, address != 0); + bool address; + + this->roam_lock->lock(this->roam_lock); + address = this->roam_address; + this->roam_address = FALSE; + this->roam_lock->unlock(this->roam_lock); + hydra->kernel_interface->roam(hydra->kernel_interface, address); return JOB_REQUEUE_NONE; } @@ -725,11 +736,11 @@ static void fire_roam_event(private_kernel_netlink_net_t *this, bool address) } timeval_add_ms(&now, ROAM_DELAY); this->next_roam = now; + this->roam_address |= address; this->roam_lock->unlock(this->roam_lock); job = (job_t*)callback_job_create((callback_job_cb_t)roam_event, - (void*)(uintptr_t)(address ? 1 : 0), - NULL, NULL); + this, NULL, NULL); lib->scheduler->schedule_job_ms(lib->scheduler, job, ROAM_DELAY); } -- cgit v1.2.3