Source-Changes-HG archive

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

[src/trunk]: src/sys/netinet6 Change the IPv6 reassembly mechanism to use mut...



details:   https://anonhg.NetBSD.org/src/rev/af1a37d0fa6a
branches:  trunk
changeset: 770954:af1a37d0fa6a
user:      zoltan <zoltan%NetBSD.org@localhost>
date:      Fri Nov 04 00:22:33 2011 +0000

description:
Change the IPv6 reassembly mechanism to use mutex(9).
Also add ip6_reass_packet() to be used by NPF.

diffstat:

 sys/netinet6/frag6.c   |  140 +++++++++++++++++-------------------------------
 sys/netinet6/ip6_var.h |    3 +-
 2 files changed, 53 insertions(+), 90 deletions(-)

diffs (truncated from 342 to 300 lines):

diff -r c797a7b9c091 -r af1a37d0fa6a sys/netinet6/frag6.c
--- a/sys/netinet6/frag6.c      Thu Nov 03 21:59:45 2011 +0000
+++ b/sys/netinet6/frag6.c      Fri Nov 04 00:22:33 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: frag6.c,v 1.49 2011/05/03 17:44:30 dyoung Exp $        */
+/*     $NetBSD: frag6.c,v 1.50 2011/11/04 00:22:33 zoltan Exp $        */
 /*     $KAME: frag6.c,v 1.40 2002/05/27 21:40:31 itojun Exp $  */
 
 /*
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: frag6.c,v 1.49 2011/05/03 17:44:30 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: frag6.c,v 1.50 2011/11/04 00:22:33 zoltan Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -64,66 +64,13 @@
 static void frag6_remque(struct ip6q *);
 static void frag6_freef(struct ip6q *);
 
-static int ip6q_locked;
 static int frag6_drainwanted;
 
 u_int frag6_nfragpackets;
 u_int frag6_nfrags;
 struct ip6q ip6q;      /* ip6 reassemble queue */
 
-static inline int ip6q_lock_try(void);
-static inline void ip6q_unlock(void);
-
-static inline int
-ip6q_lock_try(void)
-{
-       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(void)
-{
-       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 (/*CONSTCOND*/ 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 (/*CONSTCOND*/ 0)
-#else
-#define        IP6Q_LOCK()             (void) ip6q_lock_try()
-#define        IP6Q_LOCK_CHECK()       /* nothing */
-#endif
-
-#define        IP6Q_UNLOCK()           ip6q_unlock()
+static kmutex_t        frag6_lock;
 
 #ifndef offsetof               /* XXX */
 #define        offsetof(type, member)  ((size_t)(&((type *)0)->member))
@@ -137,6 +84,7 @@
 {
 
        ip6q.ip6q_next = ip6q.ip6q_prev = &ip6q;
+       mutex_init(&frag6_lock, MUTEX_DEFAULT, IPL_NET);
 }
 
 /*
@@ -171,8 +119,8 @@
 /*
  * Fragment input
  */
-int
-frag6_input(struct mbuf **mp, int *offp, int proto)
+static int
+frag6_in(struct mbuf **mp, int *offp)
 {
        struct rtentry *rt;
        struct mbuf *m = *mp, *t;
@@ -193,7 +141,7 @@
        ip6 = mtod(m, struct ip6_hdr *);
        IP6_EXTHDR_GET(ip6f, struct ip6_frag *, m, offset, sizeof(*ip6f));
        if (ip6f == NULL)
-               return IPPROTO_DONE;
+               return -1;
 
        dstifp = NULL;
        /* find the destination interface of the packet. */
@@ -205,7 +153,7 @@
        if (ip6->ip6_plen == 0) {
                icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER, offset);
                in6_ifstat_inc(dstifp, ifs6_reass_fail);
-               return IPPROTO_DONE;
+               return -1;
        }
 
        /*
@@ -219,7 +167,7 @@
                icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
                    offsetof(struct ip6_hdr, ip6_plen));
                in6_ifstat_inc(dstifp, ifs6_reass_fail);
-               return IPPROTO_DONE;
+               return -1;
        }
 
        IP6_STATINC(IP6_STAT_FRAGMENTS);
@@ -228,7 +176,7 @@
        /* offset now points to data portion */
        offset += sizeof(struct ip6_frag);
 
-       IP6Q_LOCK();
+       mutex_enter(&frag6_lock);
 
        /*
         * Enforce upper bound on number of fragments.
@@ -269,7 +217,6 @@
                if (q6 == NULL)
                        goto dropfrag;
                memset(q6, 0, sizeof(*q6));
-
                frag6_insque(q6, &ip6q);
 
                /* ip6q_nxt will be filled afterwards, from 1st fragment */
@@ -307,18 +254,18 @@
        if (q6->ip6q_unfrglen >= 0) {
                /* The 1st fragment has already arrived. */
                if (q6->ip6q_unfrglen + fragoff + frgpartlen > IPV6_MAXPACKET) {
+                       mutex_exit(&frag6_lock);
                        icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
                            offset - sizeof(struct ip6_frag) +
                            offsetof(struct ip6_frag, ip6f_offlg));
-                       IP6Q_UNLOCK();
-                       return (IPPROTO_DONE);
+                       return -1;
                }
        } else if (fragoff + frgpartlen > IPV6_MAXPACKET) {
+               mutex_exit(&frag6_lock);
                icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
                            offset - sizeof(struct ip6_frag) +
                                offsetof(struct ip6_frag, ip6f_offlg));
-               IP6Q_UNLOCK();
-               return (IPPROTO_DONE);
+               return -1;
        }
        /*
         * If it's the first fragment, do the above check for each
@@ -476,14 +423,14 @@
        for (af6 = q6->ip6q_down; af6 != (struct ip6asfrag *)q6;
             af6 = af6->ip6af_down) {
                if (af6->ip6af_off != next) {
-                       IP6Q_UNLOCK();
-                       return IPPROTO_DONE;
+                       mutex_exit(&frag6_lock);
+                       return 0;
                }
                next += af6->ip6af_frglen;
        }
        if (af6->ip6af_up->ip6af_mff) {
-               IP6Q_UNLOCK();
-               return IPPROTO_DONE;
+               mutex_exit(&frag6_lock);
+               return 0;
        }
 
        /*
@@ -566,17 +513,39 @@
        *mp = m;
        *offp = offset;
 
-       IP6Q_UNLOCK();
+       mutex_exit(&frag6_lock);
        return nxt;
 
  dropfrag:
+       mutex_exit(&frag6_lock);
        in6_ifstat_inc(dstifp, ifs6_reass_fail);
        IP6_STATINC(IP6_STAT_FRAGDROPPED);
        m_freem(m);
-       IP6Q_UNLOCK();
+       return -1;
+}
+
+int
+frag6_input(struct mbuf **mp, int *offp, int proto)
+{
+       int ret = frag6_in(mp, offp);
+
+       if (ret > 0) {
+               return ret;
+       }
        return IPPROTO_DONE;
 }
 
+int
+ip6_reass_packet(struct mbuf **mp, int offset)
+{
+       int ret = frag6_in(mp, &offset);
+
+       if (ret <= 0) {
+               *mp = NULL;
+       }
+       return ret < 0 ? ret : 0;
+}
+
 /*
  * Free a fragment reassembly header and all
  * associated datagrams.
@@ -586,7 +555,7 @@
 {
        struct ip6asfrag *af6, *down6;
 
-       IP6Q_LOCK_CHECK();
+       KASSERT(mutex_owned(&frag6_lock));
 
        for (af6 = q6->ip6q_down; af6 != (struct ip6asfrag *)q6;
             af6 = down6) {
@@ -629,7 +598,7 @@
 frag6_enq(struct ip6asfrag *af6, struct ip6asfrag *up6)
 {
 
-       IP6Q_LOCK_CHECK();
+       KASSERT(mutex_owned(&frag6_lock));
 
        af6->ip6af_up = up6;
        af6->ip6af_down = up6->ip6af_down;
@@ -644,7 +613,7 @@
 frag6_deq(struct ip6asfrag *af6)
 {
 
-       IP6Q_LOCK_CHECK();
+       KASSERT(mutex_owned(&frag6_lock));
 
        af6->ip6af_up->ip6af_down = af6->ip6af_down;
        af6->ip6af_down->ip6af_up = af6->ip6af_up;
@@ -654,7 +623,7 @@
 frag6_insque(struct ip6q *new, struct ip6q *old)
 {
 
-       IP6Q_LOCK_CHECK();
+       KASSERT(mutex_owned(&frag6_lock));
 
        new->ip6q_prev = old;
        new->ip6q_next = old->ip6q_next;
@@ -666,7 +635,7 @@
 frag6_remque(struct ip6q *p6)
 {
 
-       IP6Q_LOCK_CHECK();
+       KASSERT(mutex_owned(&frag6_lock));
 
        p6->ip6q_prev->ip6q_next = p6->ip6q_next;
        p6->ip6q_next->ip6q_prev = p6->ip6q_prev;
@@ -691,10 +660,7 @@
 {
        struct ip6q *q6;
 
-       mutex_enter(softnet_lock);
-       KERNEL_LOCK(1, NULL);
-
-       IP6Q_LOCK();
+       mutex_enter(&frag6_lock);
        q6 = ip6q.ip6q_next;
        if (q6)
                while (q6 != &ip6q) {
@@ -717,7 +683,7 @@
                /* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */
                frag6_freef(ip6q.ip6q_prev);
        }
-       IP6Q_UNLOCK();
+       mutex_exit(&frag6_lock);
 
 #if 0
        /*
@@ -729,8 +695,6 @@



Home | Main Index | Thread Index | Old Index