Commit e3c0d047 authored by Fan Du's avatar Fan Du Committed by David S. Miller

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: default avatarFan Du <fdu@windriver.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 1485348d
...@@ -213,6 +213,9 @@ struct xfrm_state { ...@@ -213,6 +213,9 @@ struct xfrm_state {
struct xfrm_lifetime_cur curlft; struct xfrm_lifetime_cur curlft;
struct tasklet_hrtimer mtimer; struct tasklet_hrtimer mtimer;
/* used to fix curlft->add_time when changing date */
long saved_tmo;
/* Last used time */ /* Last used time */
unsigned long lastused; unsigned long lastused;
...@@ -238,6 +241,7 @@ static inline struct net *xs_net(struct xfrm_state *x) ...@@ -238,6 +241,7 @@ static inline struct net *xs_net(struct xfrm_state *x)
/* xflags - make enum if more show up */ /* xflags - make enum if more show up */
#define XFRM_TIME_DEFER 1 #define XFRM_TIME_DEFER 1
#define XFRM_SOFT_EXPIRE 2
enum { enum {
XFRM_STATE_VOID, XFRM_STATE_VOID,
......
...@@ -415,8 +415,17 @@ static enum hrtimer_restart xfrm_timer_handler(struct hrtimer * me) ...@@ -415,8 +415,17 @@ static enum hrtimer_restart xfrm_timer_handler(struct hrtimer * me)
if (x->lft.hard_add_expires_seconds) { if (x->lft.hard_add_expires_seconds) {
long tmo = x->lft.hard_add_expires_seconds + long tmo = x->lft.hard_add_expires_seconds +
x->curlft.add_time - now; x->curlft.add_time - now;
if (tmo <= 0) if (tmo <= 0) {
goto expired; if (x->xflags & XFRM_SOFT_EXPIRE) {
/* enter hard expire without soft expire first?!
* setting a new date could trigger this.
* workarbound: fix x->curflt.add_time by below:
*/
x->curlft.add_time = now - x->saved_tmo - 1;
tmo = x->lft.hard_add_expires_seconds - x->saved_tmo;
} else
goto expired;
}
if (tmo < next) if (tmo < next)
next = tmo; next = tmo;
} }
...@@ -433,10 +442,14 @@ static enum hrtimer_restart xfrm_timer_handler(struct hrtimer * me) ...@@ -433,10 +442,14 @@ static enum hrtimer_restart xfrm_timer_handler(struct hrtimer * me)
if (x->lft.soft_add_expires_seconds) { if (x->lft.soft_add_expires_seconds) {
long tmo = x->lft.soft_add_expires_seconds + long tmo = x->lft.soft_add_expires_seconds +
x->curlft.add_time - now; x->curlft.add_time - now;
if (tmo <= 0) if (tmo <= 0) {
warn = 1; warn = 1;
else if (tmo < next) x->xflags &= ~XFRM_SOFT_EXPIRE;
} else if (tmo < next) {
next = tmo; next = tmo;
x->xflags |= XFRM_SOFT_EXPIRE;
x->saved_tmo = tmo;
}
} }
if (x->lft.soft_use_expires_seconds) { if (x->lft.soft_use_expires_seconds) {
long tmo = x->lft.soft_use_expires_seconds + long tmo = x->lft.soft_use_expires_seconds +
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment