Source-Changes-HG archive

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

[src/trunk]: src/sys/netinet6 have a real lock around IPv6 reassembly.



details:   https://anonhg.NetBSD.org/src/rev/a0fca46647e8
branches:  trunk
changeset: 523748:a0fca46647e8
user:      itojun <itojun%NetBSD.org@localhost>
date:      Fri Mar 15 10:44:07 2002 +0000

description:
have a real lock around IPv6 reassembly.

diffstat:

 sys/netinet6/frag6.c |  97 ++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 83 insertions(+), 14 deletions(-)

diffs (227 lines):

diff -r f27618c9d1ce -r a0fca46647e8 sys/netinet6/frag6.c
--- a/sys/netinet6/frag6.c      Fri Mar 15 09:36:27 2002 +0000
+++ b/sys/netinet6/frag6.c      Fri Mar 15 10:44:07 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: frag6.c,v 1.16 2001/11/13 00:56:57 lukem Exp $ */
+/*     $NetBSD: frag6.c,v 1.17 2002/03/15 10:44:07 itojun Exp $        */
 /*     $KAME: frag6.c,v 1.31 2001/05/17 13:45:34 jinmei Exp $  */
 
 /*
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: frag6.c,v 1.16 2001/11/13 00:56:57 lukem Exp $");
+__KERNEL_RCSID(0, "$NetBSD: frag6.c,v 1.17 2002/03/15 10:44:07 itojun Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -70,11 +70,64 @@
 static void frag6_remque __P((struct ip6q *));
 static void frag6_freef __P((struct ip6q *));
 
-/* XXX we eventually need splreass6, or some real semaphore */
-int frag6_doing_reass;
+static int ip6q_locked;
 u_int frag6_nfragpackets;
 struct ip6q ip6q;      /* ip6 reassemble queue */
 
+static __inline int ip6q_lock_try __P((void));
+static __inline void ip6q_unlock __P((void));
+
+static __inline int
+ip6q_lock_try()
+{
+       int s;
+
+       /*
+        * Use splvm() -- we're bloking things that would cause
+        * mbuf allocation.
+        */
+       s = splvm();
+       if (ip6q_locked) {
+               splx(s);
+               return (0);
+       }
+       ip6q_locked = 1;
+       splx(s);
+       return (1);
+}
+
+static __inline void
+ip6q_unlock()
+{
+       int s;
+
+       s = splvm();
+       ip6q_locked = 0;
+       splx(s);
+}
+
+#ifdef DIAGNOSTIC
+#define        IP6Q_LOCK()                                                     \
+do {                                                                   \
+       if (ip6q_lock_try() == 0) {                                     \
+               printf("%s:%d: ip6q already locked\n", __FILE__, __LINE__); \
+               panic("ip6q_lock");                                     \
+       }                                                               \
+} while (0)
+#define        IP6Q_LOCK_CHECK()                                               \
+do {                                                                   \
+       if (ip6q_locked == 0) {                                         \
+               printf("%s:%d: ip6q lock not held\n", __FILE__, __LINE__); \
+               panic("ip6q lock check");                               \
+       }                                                               \
+} while (0)
+#else
+#define        IP6Q_LOCK()             (void) ip6q_lock_try()
+#define        IP6Q_LOCK_CHECK()       /* nothing */
+#endif
+
+#define        IP6Q_UNLOCK()           ip6q_unlock()
+
 #ifndef offsetof               /* XXX */
 #define        offsetof(type, member)  ((size_t)(&((type *)0)->member))
 #endif
@@ -210,7 +263,7 @@
        /* offset now points to data portion */
        offset += sizeof(struct ip6_frag);
 
-       frag6_doing_reass = 1;
+       IP6Q_LOCK();
 
        for (q6 = ip6q.ip6q_next; q6 != &ip6q; q6 = q6->ip6q_next)
                if (ip6f->ip6f_ident == q6->ip6q_ident &&
@@ -279,7 +332,7 @@
                        icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
                                    offset - sizeof(struct ip6_frag) +
                                        offsetof(struct ip6_frag, ip6f_offlg));
-                       frag6_doing_reass = 0;
+                       IP6Q_UNLOCK();
                        return(IPPROTO_DONE);
                }
        }
@@ -287,7 +340,7 @@
                icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
                            offset - sizeof(struct ip6_frag) +
                                offsetof(struct ip6_frag, ip6f_offlg));
-               frag6_doing_reass = 0;
+               IP6Q_UNLOCK();
                return(IPPROTO_DONE);
        }
        /*
@@ -442,13 +495,13 @@
        for (af6 = q6->ip6q_down; af6 != (struct ip6asfrag *)q6;
             af6 = af6->ip6af_down) {
                if (af6->ip6af_off != next) {
-                       frag6_doing_reass = 0;
+                       IP6Q_UNLOCK();
                        return IPPROTO_DONE;
                }
                next += af6->ip6af_frglen;
        }
        if (af6->ip6af_up->ip6af_mff) {
-               frag6_doing_reass = 0;
+               IP6Q_UNLOCK();
                return IPPROTO_DONE;
        }
 
@@ -531,14 +584,14 @@
        *mp = m;
        *offp = offset;
 
-       frag6_doing_reass = 0;
+       IP6Q_UNLOCK();
        return nxt;
 
  dropfrag:
        in6_ifstat_inc(dstifp, ifs6_reass_fail);
        ip6stat.ip6s_fragdropped++;
        m_freem(m);
-       frag6_doing_reass = 0;
+       IP6Q_UNLOCK();
        return IPPROTO_DONE;
 }
 
@@ -552,6 +605,8 @@
 {
        struct ip6asfrag *af6, *down6;
 
+       IP6Q_LOCK_CHECK();
+
        for (af6 = q6->ip6q_down; af6 != (struct ip6asfrag *)q6;
             af6 = down6) {
                struct mbuf *m = IP6_REASS_MBUF(af6);
@@ -592,6 +647,9 @@
 frag6_enq(af6, up6)
        struct ip6asfrag *af6, *up6;
 {
+
+       IP6Q_LOCK_CHECK();
+
        af6->ip6af_up = up6;
        af6->ip6af_down = up6->ip6af_down;
        up6->ip6af_down->ip6af_up = af6;
@@ -605,6 +663,9 @@
 frag6_deq(af6)
        struct ip6asfrag *af6;
 {
+
+       IP6Q_LOCK_CHECK();
+
        af6->ip6af_up->ip6af_down = af6->ip6af_down;
        af6->ip6af_down->ip6af_up = af6->ip6af_up;
 }
@@ -613,6 +674,9 @@
 frag6_insque(new, old)
        struct ip6q *new, *old;
 {
+
+       IP6Q_LOCK_CHECK();
+
        new->ip6q_prev = old;
        new->ip6q_next = old->ip6q_next;
        old->ip6q_next->ip6q_prev= new;
@@ -623,6 +687,9 @@
 frag6_remque(p6)
        struct ip6q *p6;
 {
+
+       IP6Q_LOCK_CHECK();
+
        p6->ip6q_prev->ip6q_next = p6->ip6q_next;
        p6->ip6q_next->ip6q_prev = p6->ip6q_prev;
 }
@@ -638,7 +705,7 @@
        struct ip6q *q6;
        int s = splsoftnet();
 
-       frag6_doing_reass = 1;
+       IP6Q_LOCK();
        q6 = ip6q.ip6q_next;
        if (q6)
                while (q6 != &ip6q) {
@@ -661,7 +728,7 @@
                /* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */
                frag6_freef(ip6q.ip6q_prev);
        }
-       frag6_doing_reass = 0;
+       IP6Q_UNLOCK();
 
 #if 0
        /*
@@ -688,11 +755,13 @@
 void
 frag6_drain()
 {
-       if (frag6_doing_reass)
+
+       if (ip6q_lock_try() == 0)
                return;
        while (ip6q.ip6q_next != &ip6q) {
                ip6stat.ip6s_fragdropped++;
                /* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */
                frag6_freef(ip6q.ip6q_next);
        }
+       IP6Q_UNLOCK();
 }



Home | Main Index | Thread Index | Old Index