Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/netinet Replace the single global IP reassembly list/lis...



details:   https://anonhg.NetBSD.org/src/rev/32a2bc615ae1
branches:  trunk
changeset: 556055:32a2bc615ae1
user:      jonathan <jonathan%NetBSD.org@localhost>
date:      Sat Dec 06 23:56:10 2003 +0000

description:
Replace the single global IP reassembly list/listhead, with a
hashtable of list-heads. Independently re-invented, then reworked to
match similar code in FreeBSD.

diffstat:

 sys/netinet/ip_input.c |  82 ++++++++++++++++++++++++++++++++++++++-----------
 sys/netinet/ip_var.h   |   6 +-
 2 files changed, 66 insertions(+), 22 deletions(-)

diffs (213 lines):

diff -r 942606d0209e -r 32a2bc615ae1 sys/netinet/ip_input.c
--- a/sys/netinet/ip_input.c    Sat Dec 06 22:40:03 2003 +0000
+++ b/sys/netinet/ip_input.c    Sat Dec 06 23:56:10 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ip_input.c,v 1.189 2003/12/04 19:38:24 atatat Exp $    */
+/*     $NetBSD: ip_input.c,v 1.190 2003/12/06 23:56:10 jonathan Exp $  */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -98,7 +98,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.189 2003/12/04 19:38:24 atatat Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.190 2003/12/06 23:56:10 jonathan Exp $");
 
 #include "opt_inet.h"
 #include "opt_gateway.h"
@@ -236,7 +236,16 @@
 struct pfil_head inet_pfil_hook;
 #endif
 
-struct ipqhead ipq;
+/* IP datagram reassembly queues (hashed) */
+#define IPREASS_NHASH_LOG2      6
+#define IPREASS_NHASH           (1 << IPREASS_NHASH_LOG2)
+#define IPREASS_HMASK           (IPREASS_NHASH - 1)
+#define IPREASS_HASH(x,y) \
+       (((((x) & 0xF) | ((((x) >> 8) & 0xF) << 4)) ^ (y)) & IPREASS_HMASK)
+struct ipqhead ipq[IPREASS_NHASH];
+#ifdef notyet
+static int    nipq = 0;         /* total # of reass queues */
+#endif
 int    ipq_locked;
 int    ip_nfragpackets = 0;
 int    ip_maxfragpackets = 200;
@@ -363,7 +372,9 @@
                if (pr->pr_domain->dom_family == PF_INET &&
                    pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW)
                        ip_protox[pr->pr_protocol] = pr - inetsw;
-       LIST_INIT(&ipq);
+       for (i = 0; i < IPREASS_NHASH; i++)
+               LIST_INIT(&ipq[i]);
+
        ip_id = time.tv_sec & 0xfffff;
        ipintrq.ifq_maxlen = ipqmaxlen;
        TAILQ_INIT(&in_ifaddrhead);
@@ -437,6 +448,7 @@
        int downmatch;
        int checkif;
        int srcrt = 0;
+       u_int hash;
 #ifdef FAST_IPSEC
        struct m_tag *mtag;
        struct tdb_ident *tdbi;
@@ -823,12 +835,17 @@
                 * of this datagram.
                 */
                IPQ_LOCK();
-               LIST_FOREACH(fp, &ipq, ipq_q)
+               hash = IPREASS_HASH(ip->ip_src.s_addr, ip->ip_id);
+               /* XXX LIST_FOREACH(fp, &ipq[hash], ipq_q) */
+               for (fp = LIST_FIRST(&ipq[hash]); fp != NULL;
+                    fp = LIST_NEXT(fp, ipq_q)) {
                        if (ip->ip_id == fp->ipq_id &&
                            in_hosteq(ip->ip_src, fp->ipq_src) &&
                            in_hosteq(ip->ip_dst, fp->ipq_dst) &&
                            ip->ip_p == fp->ipq_p)
                                goto found;
+
+               }
                fp = 0;
 found:
 
@@ -869,7 +886,7 @@
                        ipqe->ipqe_mff = mff;
                        ipqe->ipqe_m = m;
                        ipqe->ipqe_ip = ip;
-                       m = ip_reass(ipqe, fp);
+                       m = ip_reass(ipqe, fp, &ipq[hash]);
                        if (m == 0) {
                                IPQ_UNLOCK();
                                return;
@@ -966,9 +983,10 @@
  * is given as fp; otherwise have to make a chain.
  */
 struct mbuf *
-ip_reass(ipqe, fp)
+ip_reass(ipqe, fp, ipqhead)
        struct ipqent *ipqe;
        struct ipq *fp;
+       struct ipqhead *ipqhead;
 {
        struct mbuf *m = ipqe->ipqe_m;
        struct ipqent *nq, *p, *q;
@@ -1005,7 +1023,7 @@
                    M_FTABLE, M_NOWAIT);
                if (fp == NULL)
                        goto dropfrag;
-               LIST_INSERT_HEAD(&ipq, fp, ipq_q);
+               LIST_INSERT_HEAD(ipqhead, fp, ipq_q);
                fp->ipq_ttl = IPFRAGTTL;
                fp->ipq_p = ipqe->ipqe_ip->ip_p;
                fp->ipq_id = ipqe->ipqe_ip->ip_id;
@@ -1171,27 +1189,47 @@
 void
 ip_slowtimo()
 {
+       static unsigned dropscanidx = 0;
+       unsigned i;
        struct ipq *fp, *nfp;
        int s = splsoftnet();
 
        IPQ_LOCK();
-       for (fp = LIST_FIRST(&ipq); fp != NULL; fp = nfp) {
-               nfp = LIST_NEXT(fp, ipq_q);
-               if (--fp->ipq_ttl == 0) {
-                       ipstat.ips_fragtimeout++;
-                       ip_freef(fp);
+       for (i = 0; i < IPREASS_NHASH; i++) {
+               for (fp = LIST_FIRST(&ipq[i]); fp != NULL; fp = nfp) {
+                       nfp = LIST_NEXT(fp, ipq_q);
+                       if (--fp->ipq_ttl == 0) {
+                               ipstat.ips_fragtimeout++;
+                               ip_freef(fp);
+                       }
                }
        }
        /*
         * If we are over the maximum number of fragments
         * (due to the limit being lowered), drain off
-        * enough to get down to the new limit.
+        * enough to get down to the new limit. Start draining
+        * from the reassembly hashqueue most recently drained.
         */
        if (ip_maxfragpackets < 0)
                ;
        else {
-               while (ip_nfragpackets > ip_maxfragpackets && LIST_FIRST(&ipq))
-                       ip_freef(LIST_FIRST(&ipq));
+               int wrapped = 0;
+
+               i = dropscanidx;
+               while (ip_nfragpackets > ip_maxfragpackets && wrapped == 0) {
+                       while (LIST_FIRST(&ipq[i]) != NULL)
+                               ip_freef(LIST_FIRST(&ipq[i]));
+                       if (++i >= IPREASS_NHASH) {
+                               i = 0;
+                       }
+                       /*
+                        * Dont scan forever even if fragment counters are
+                        * wrong: stop after scanning entire reassembly queue.
+                        */
+                       if (i == dropscanidx)
+                           wrapped = 1;
+               }
+               dropscanidx = i;
        }
        IPQ_UNLOCK();
 #ifdef GATEWAY
@@ -1206,6 +1244,7 @@
 void
 ip_drain()
 {
+       int i;
 
        /*
         * We may be called from a device's interrupt context.  If
@@ -1214,9 +1253,14 @@
        if (ipq_lock_try() == 0)
                return;
 
-       while (LIST_FIRST(&ipq) != NULL) {
-               ipstat.ips_fragdropped++;
-               ip_freef(LIST_FIRST(&ipq));
+       for (i = 0; i < IPREASS_NHASH; i++) {
+               struct ipqhead *ipqh = &ipq[i];
+               struct ipq *fp, *nfp;
+               for (fp = LIST_FIRST(ipqh); fp != NULL; fp = nfp) {
+                       nfp = LIST_NEXT(fp, ipq_q);
+                       ip_freef(fp);
+                       ipstat.ips_fragdropped++;
+               }
        }
 
        IPQ_UNLOCK();
diff -r 942606d0209e -r 32a2bc615ae1 sys/netinet/ip_var.h
--- a/sys/netinet/ip_var.h      Sat Dec 06 22:40:03 2003 +0000
+++ b/sys/netinet/ip_var.h      Sat Dec 06 23:56:10 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ip_var.h,v 1.62 2003/11/26 21:15:47 itojun Exp $       */
+/*     $NetBSD: ip_var.h,v 1.63 2003/12/06 23:56:10 jonathan Exp $     */
 
 /*
  * Copyright (c) 1982, 1986, 1993
@@ -192,7 +192,7 @@
 #endif
 
 extern struct ipstat ipstat;           /* ip statistics */
-extern LIST_HEAD(ipqhead, ipq) ipq;    /* ip reass. queue */
+extern LIST_HEAD(ipqhead, ipq) ipq[];  /* ip reass. queue */
 extern int   ip_defttl;                        /* default IP ttl */
 extern int   ipforwarding;             /* ip forwarding */
 extern int   ip_mtudisc;               /* mtu discovery */
@@ -227,7 +227,7 @@
 int     ip_fragment(struct mbuf *, struct ifnet *, u_long);
 int     ip_pcbopts __P((struct mbuf **, struct mbuf *));
 struct mbuf *
-        ip_reass __P((struct ipqent *, struct ipq *));
+        ip_reass __P((struct ipqent *, struct ipq *, struct ipqhead *));
 struct in_ifaddr *
         ip_rtaddr __P((struct in_addr));
 void    ip_savecontrol __P((struct inpcb *, struct mbuf **, struct ip *,



Home | Main Index | Thread Index | Old Index