This patch requires maxqueue.patch to already be installed.
To apply:
cd /usr/src/sys/netinet
patch -p0 < ipqrace.patch
Recompile your kernel.
Index: ip_input.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_input.c,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -r1.35 -r1.36
--- ip_input.c 1999/02/17 23:51:12 1.35
+++ ip_input.c 1999/02/19 19:50:43 1.36
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_input.c,v 1.35 1999/02/17 23:51:12 deraadt Exp $ */
+/* $OpenBSD: ip_input.c,v 1.36 1999/02/19 19:50:43 deraadt Exp $ */
/* $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $ */
/*
@@ -121,6 +121,37 @@
struct mbuf **));
#endif
+int ipq_locked;
+static __inline int ipq_lock_try __P((void));
+static __inline void ipq_unlock __P((void));
+
+static __inline int
+ipq_lock_try()
+{
+ int s;
+
+ s = splimp();
+ if (ipq_locked) {
+ splx(s);
+ return (0);
+ }
+ ipq_locked = 1;
+ splx(s);
+ return (1);
+}
+
+#define ipq_lock() ipq_lock_try()
+
+static __inline void
+ipq_unlock()
+{
+ int s;
+
+ s = splimp();
+ ipq_locked = 0;
+ splx(s);
+}
+
char *
inet_ntoa(ina)
struct in_addr ina;
@@ -396,10 +427,12 @@
}
ip = mtod(m, struct ip *);
}
+
/*
* Look for queue of fragments
* of this datagram.
*/
+ ipq_lock();
for (fp = ipq.lh_first; fp != NULL; fp = fp->ipq_q.le_next)
if (ip->ip_id == fp->ipq_id &&
ip->ip_src.s_addr == fp->ipq_src.s_addr &&
@@ -423,6 +456,7 @@
*/
if (ip->ip_len == 0 || (ip->ip_len & 0x7) != 0) {
ipstat.ips_badfrags++;
+ ipq_unlock();
goto bad;
}
}
@@ -438,6 +472,7 @@
if (ip_frags + 1 > ip_maxqueue) {
ip_flush();
ipstat.ips_rcvmemdrop++;
+ ipq_unlock();
goto bad;
}
@@ -445,20 +480,24 @@
M_IPQ, M_NOWAIT);
if (ipqe == NULL) {
ipstat.ips_rcvmemdrop++;
+ ipq_unlock();
goto bad;
}
ip_frags++;
ipqe->ipqe_mff = mff;
ipqe->ipqe_ip = ip;
ip = ip_reass(ipqe, fp);
- if (ip == 0)
+ if (ip == 0) {
+ ipq_unlock();
goto next;
+ }
ipstat.ips_reassembled++;
m = dtom(ip);
hlen = ip->ip_hl << 2;
} else
if (fp)
ip_freef(fp);
+ ipq_unlock();
} else
ip->ip_len -= hlen;
@@ -701,6 +740,7 @@
register struct ipq *fp, *nfp;
int s = splsoftnet();
+ ipq_lock();
for (fp = ipq.lh_first; fp != NULL; fp = nfp) {
nfp = fp->ipq_q.le_next;
if (--fp->ipq_ttl == 0) {
@@ -708,6 +748,7 @@
ip_freef(fp);
}
}
+ ipq_unlock();
splx(s);
}
@@ -718,10 +759,13 @@
ip_drain()
{
+ if (ipq_lock_try() == 0)
+ return;
while (ipq.lh_first != NULL) {
ipstat.ips_fragdropped++;
ip_freef(ipq.lh_first);
}
+ ipq_unlock();
}
/*
@@ -730,8 +774,10 @@
void
ip_flush()
{
+ int max = 50;
- while (ipq.lh_first != NULL && ip_frags > ip_maxqueue * 3 / 4) {
+ /* ipq already locked */
+ while (ipq.lh_first != NULL && ip_frags > ip_maxqueue * 3 / 4 && --max) {
ipstat.ips_fragdropped++;
ip_freef(ipq.lh_first);
}