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