On Tue, 2006-11-04 at 00:34 +0200, KOVACS Krisztian wrote: [..] > But I still perfer the flag.
Ok, so consensus is to use a flag. > Another thing still present is the possible xfrm_state leak. I think we > need to call xfrm_state_put() as the last statement of > xfrm_replay_timer_handler() to drop the reference we acquired when > starting the timer. Good eye. Fixed. Ok, if both you can provide feedback on the attached patch (untested but compiles) I will make any necessary changes, test and push this + documentation to Dave. cheers, jamal
Send aevent immediately if we have sent nothing since last timer and this is the first packet. 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 | 8 ++++++++ net/xfrm/xfrm_state.c | 29 ++++++++++++++++++++++------- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 0d5529c..b77d333 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -143,6 +143,11 @@ struct xfrm_state /* Replay detection state at the time we sent the last notification */ struct xfrm_replay_state preplay; + /* internal flag that only holds state for delayed aevent at the + * moment + */ + u32 xflags; + /* Replay detection notification settings */ u32 replay_maxage; u32 replay_maxdiff; @@ -167,6 +172,9 @@ struct xfrm_state * interpreted by xfrm_type methods. */ void *data; }; + +/* xflags - make enum if more show up */ +#define XFRM_TIME_DEFER 1 enum { XFRM_STATE_VOID, diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index a8e14dc..22203eb 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->xflags &= ~XFRM_TIME_DEFER; + } wake_up(&km_waitq); } @@ -805,16 +807,22 @@ void xfrm_replay_notify(struct xfrm_stat case XFRM_REPLAY_UPDATE: if (x->replay_maxdiff && (x->replay.seq - x->preplay.seq < x->replay_maxdiff) && - (x->replay.oseq - x->preplay.oseq < x->replay_maxdiff)) - return; + (x->replay.oseq - x->preplay.oseq < x->replay_maxdiff)) { + if (x->xflags & XFRM_TIME_DEFER) + 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->xflags |= XFRM_TIME_DEFER; 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->xflags &= ~XFRM_TIME_DEFER; + } } EXPORT_SYMBOL(xfrm_replay_notify); @@ -836,10 +846,15 @@ 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->xflags |= XFRM_TIME_DEFER; + } spin_unlock(&x->lock); + xfrm_state_put(x); } int xfrm_replay_check(struct xfrm_state *x, u32 seq)