tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: KASSERT() in kern_timeout.c



On Mon, Apr 19, 2010 at 02:41:42PM +0200, Manuel Bouyer wrote:
> > That won't work well, because syn_cache_put() is called from
> > syn_cache_timer(). In addition syn_cache_rm() which does a callout_stop
> > is always called before syn_cache_put(), or syn_cache_put() is called
> > before the timer is armed. 
> > would the attacched diff be OK ?
> 
> Forgot to free sc_route and sc_ipopts in the dropit: case. Updated
> patch attached.

This doesn't work because the timer is stopped in syn_cache_rm(), so
syn entries are never freed.
The attached patch fixes this issue, now all syn entries are freed
when the timer fires (I tested with nemesis flooding a test system with
syn entries). the remaning issue would be that the pool_cache_put is
delayed by several seconds, this could maybe cause memory starvation.

> > 
> > BTW, there is a comment in syn_cache_timer() saying "calls pool_put but
> > see spl above", but syn_cache_timer() has no spl calls. Should it raise
> > the IPL to splsoftnet() ?
> 
> This remains ...

I also added splsoftnet calls before pool_put().

-- 
Manuel Bouyer <bouyer%antioche.eu.org@localhost>
     NetBSD: 26 ans d'experience feront toujours la difference
--
Index: tcp_input.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/tcp_input.c,v
retrieving revision 1.291.4.2
diff -u -p -u -r1.291.4.2 tcp_input.c
--- tcp_input.c 26 Sep 2009 18:34:29 -0000      1.291.4.2
+++ tcp_input.c 19 Apr 2010 14:27:13 -0000
@@ -3333,7 +3333,6 @@ syn_cache_rm(struct syn_cache *sc)
        sc->sc_tp = NULL;
        LIST_REMOVE(sc, sc_tpq);
        tcp_syn_cache[sc->sc_bucketidx].sch_length--;
-       callout_stop(&sc->sc_timer);
        syn_cache_count--;
 }
 
@@ -3343,12 +3342,7 @@ syn_cache_put(struct syn_cache *sc)
        if (sc->sc_ipopts)
                (void) m_free(sc->sc_ipopts);
        rtcache_free(&sc->sc_route);
-       if (callout_invoking(&sc->sc_timer))
-               sc->sc_flags |= SCF_DEAD;
-       else {
-               callout_destroy(&sc->sc_timer);
-               pool_put(&syn_cache_pool, sc);
-       }
+       sc->sc_flags |= SCF_DEAD;
 }
 
 void
@@ -3467,6 +3461,7 @@ void
 syn_cache_timer(void *arg)
 {
        struct syn_cache *sc = arg;
+       int s;
 
        mutex_enter(softnet_lock);
        KERNEL_LOCK(1, NULL);
@@ -3475,7 +3470,9 @@ syn_cache_timer(void *arg)
        if (__predict_false(sc->sc_flags & SCF_DEAD)) {
                TCP_STATINC(TCP_STAT_SC_DELAYED_FREE);
                callout_destroy(&sc->sc_timer);
+               s = splsoftnet();
                pool_put(&syn_cache_pool, sc);
+               splx(s);
                KERNEL_UNLOCK_ONE(NULL);
                mutex_exit(softnet_lock);
                return;
@@ -3509,7 +3506,13 @@ syn_cache_timer(void *arg)
  dropit:
        TCP_STATINC(TCP_STAT_SC_TIMED_OUT);
        syn_cache_rm(sc);
-       syn_cache_put(sc);      /* calls pool_put but see spl above */
+       if (sc->sc_ipopts)
+               (void) m_free(sc->sc_ipopts);
+       rtcache_free(&sc->sc_route);
+       callout_destroy(&sc->sc_timer);
+       s = splsoftnet();
+       pool_put(&syn_cache_pool, sc);
+       splx(s);
        KERNEL_UNLOCK_ONE(NULL);
        mutex_exit(softnet_lock);
 }


Home | Main Index | Thread Index | Old Index