aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFan Du <fdu@windriver.com>2012-07-30 17:43:54 -0400
committerDavid S. Miller <davem@davemloft.net>2012-08-02 03:19:17 -0400
commite3c0d04750751389d5116267f8cf4687444d9a50 (patch)
treedfa831b0d4fc388da81ccc0f8f3ce4f62c3916f4
parent1485348d2424e1131ea42efc033cbd9366462b01 (diff)
Fix unexpected SA hard expiration after changing date
After SA is setup, one timer is armed to detect soft/hard expiration, however the timer handler uses xtime to do the math. This makes hard expiration occurs first before soft expiration after setting new date with big interval. As a result new child SA is deleted before rekeying the new one. Signed-off-by: Fan Du <fdu@windriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/xfrm.h4
-rw-r--r--net/xfrm/xfrm_state.c21
2 files changed, 21 insertions, 4 deletions
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index d9509eb29b80..62b619e82a90 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -213,6 +213,9 @@ struct xfrm_state {
213 struct xfrm_lifetime_cur curlft; 213 struct xfrm_lifetime_cur curlft;
214 struct tasklet_hrtimer mtimer; 214 struct tasklet_hrtimer mtimer;
215 215
216 /* used to fix curlft->add_time when changing date */
217 long saved_tmo;
218
216 /* Last used time */ 219 /* Last used time */
217 unsigned long lastused; 220 unsigned long lastused;
218 221
@@ -238,6 +241,7 @@ static inline struct net *xs_net(struct xfrm_state *x)
238 241
239/* xflags - make enum if more show up */ 242/* xflags - make enum if more show up */
240#define XFRM_TIME_DEFER 1 243#define XFRM_TIME_DEFER 1
244#define XFRM_SOFT_EXPIRE 2
241 245
242enum { 246enum {
243 XFRM_STATE_VOID, 247 XFRM_STATE_VOID,
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 5b228f97d4b3..87cd0e4d4282 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -415,8 +415,17 @@ static enum hrtimer_restart xfrm_timer_handler(struct hrtimer * me)
415 if (x->lft.hard_add_expires_seconds) { 415 if (x->lft.hard_add_expires_seconds) {
416 long tmo = x->lft.hard_add_expires_seconds + 416 long tmo = x->lft.hard_add_expires_seconds +
417 x->curlft.add_time - now; 417 x->curlft.add_time - now;
418 if (tmo <= 0) 418 if (tmo <= 0) {
419 goto expired; 419 if (x->xflags & XFRM_SOFT_EXPIRE) {
420 /* enter hard expire without soft expire first?!
421 * setting a new date could trigger this.
422 * workarbound: fix x->curflt.add_time by below:
423 */
424 x->curlft.add_time = now - x->saved_tmo - 1;
425 tmo = x->lft.hard_add_expires_seconds - x->saved_tmo;
426 } else
427 goto expired;
428 }
420 if (tmo < next) 429 if (tmo < next)
421 next = tmo; 430 next = tmo;
422 } 431 }
@@ -433,10 +442,14 @@ static enum hrtimer_restart xfrm_timer_handler(struct hrtimer * me)
433 if (x->lft.soft_add_expires_seconds) { 442 if (x->lft.soft_add_expires_seconds) {
434 long tmo = x->lft.soft_add_expires_seconds + 443 long tmo = x->lft.soft_add_expires_seconds +
435 x->curlft.add_time - now; 444 x->curlft.add_time - now;
436 if (tmo <= 0) 445 if (tmo <= 0) {
437 warn = 1; 446 warn = 1;
438 else if (tmo < next) 447 x->xflags &= ~XFRM_SOFT_EXPIRE;
448 } else if (tmo < next) {
439 next = tmo; 449 next = tmo;
450 x->xflags |= XFRM_SOFT_EXPIRE;
451 x->saved_tmo = tmo;
452 }
440 } 453 }
441 if (x->lft.soft_use_expires_seconds) { 454 if (x->lft.soft_use_expires_seconds) {
442 long tmo = x->lft.soft_use_expires_seconds + 455 long tmo = x->lft.soft_use_expires_seconds +