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); }