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