On Thu, 2006-06-04 at 22:13 +0200, KOVACS Krisztian wrote: > Hi, > > On Thursday 06 April 2006 17:18, jamal wrote: > > On Fri, 2006-07-04 at 00:30 +1000, Herbert Xu wrote: > > > If so I see what you mean but I think a better solution is to just > > > set a flag when the XFRM_REPLAY_TIMEOUT fires and nothing has > > > changed. Then when you get XFRM_REPLAY_UPDATE you can notify > > > unconditionally if this flag is set. > > > > > > The flag gets cleared in case of a notification. > > > > That does sound reasonable but i need to think about it a little in > > case it misses some scenario. > > Krisztian, see any leaks with that? > > None, it's fine with me.
Ok, I built on Herbert's suggestion and tried to be a little clever/accurate. Instead of a flag i introduce a variable that stores the jiffy point when the timer is killed. If we fall anywhere to the right or at exact point of the next point expected timer when the first packet arrives, then we do an immediate update of type XFRM_REPLAY_TIMEOUT else we keep receiving packets and wait until the right time. I havent tested this so there maybe holes, it compiles though. I would like to test it first (probably at end of day) and then submit; so please review and provide comments which i can incorporate before i punt to Dave. cheers, jamal
Send aevent immediately if time since last update is >= threshold timer. Fixes a corner case when packet threshold is very high, the timer low and a very low packet rate input which is bursty. Signed-off-by: Jamal Hadi Salim <[EMAIL PROTECTED]> --- include/net/xfrm.h | 3 +++ net/xfrm/xfrm_state.c | 26 ++++++++++++++++++++------ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 0d5529c..82fdc2c 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -140,6 +140,9 @@ struct xfrm_state /* State for replay detection */ struct xfrm_replay_state replay; + /* keeps track of last time event */ + unsigned long last_time; + /* Replay detection state at the time we sent the last notification */ struct xfrm_replay_state preplay; diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index a8e14dc..61bcffa 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -448,8 +448,10 @@ static void __xfrm_state_insert(struct x xfrm_state_hold(x); if (x->replay_maxage && - !mod_timer(&x->rtimer, jiffies + x->replay_maxage)) + !mod_timer(&x->rtimer, jiffies + x->replay_maxage)) { xfrm_state_hold(x); + x->last_time = 0; + } wake_up(&km_waitq); } @@ -806,15 +808,21 @@ void xfrm_replay_notify(struct xfrm_stat if (x->replay_maxdiff && (x->replay.seq - x->preplay.seq < x->replay_maxdiff) && (x->replay.oseq - x->preplay.oseq < x->replay_maxdiff)) - return; + if (x->last_time && + time_after_eq(jiffies, x->replay_maxage+x->last_time)) + event = XFRM_REPLAY_TIMEOUT; + else + return; break; case XFRM_REPLAY_TIMEOUT: if ((x->replay.seq == x->preplay.seq) && (x->replay.bitmap == x->preplay.bitmap) && - (x->replay.oseq == x->preplay.oseq)) + (x->replay.oseq == x->preplay.oseq)) { + x->last_time = jiffies; return; + } break; } @@ -825,8 +833,10 @@ void xfrm_replay_notify(struct xfrm_stat km_state_notify(x, &c); if (x->replay_maxage && - !mod_timer(&x->rtimer, jiffies + x->replay_maxage)) + !mod_timer(&x->rtimer, jiffies + x->replay_maxage)) { xfrm_state_hold(x); + x->last_time = 0; + } } EXPORT_SYMBOL(xfrm_replay_notify); @@ -836,8 +846,12 @@ static void xfrm_replay_timer_handler(un spin_lock(&x->lock); - if (xfrm_aevent_is_on() && x->km.state == XFRM_STATE_VALID) - xfrm_replay_notify(x, XFRM_REPLAY_TIMEOUT); + if (x->km.state == XFRM_STATE_VALID) { + if (xfrm_aevent_is_on()) + xfrm_replay_notify(x, XFRM_REPLAY_TIMEOUT); + else + x->last_time = jiffies; + } spin_unlock(&x->lock); }