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