Update the work on ipfw tables, reduce diffs.
[ipfw.git] / dummynet / ip_dummynet.c
index b8cbc2e..5b36ecc 100644 (file)
@@ -56,6 +56,8 @@ __FBSDID("$FreeBSD: src/sys/netinet/ip_dummynet.c,v 1.110.2.4 2008/10/31 12:58:1
  * include files marked with XXX are probably not needed
  */
 
+#include "missing.h"
+
 #include <sys/limits.h>
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -64,15 +66,15 @@ __FBSDID("$FreeBSD: src/sys/netinet/ip_dummynet.c,v 1.110.2.4 2008/10/31 12:58:1
 #include <sys/kernel.h>
 #include <sys/lock.h>
 #include <sys/module.h>
-#include <sys/mutex.h>
 #include <sys/priv.h>
 #include <sys/proc.h>
+#include <sys/rwlock.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
 #include <sys/time.h>
 #include <sys/sysctl.h>
 #include <sys/taskqueue.h>
-#include <net/if.h>    /* IFNAMSIZ, struct ifaddr, ifq head */
+#include <net/if.h>    /* IFNAMSIZ, struct ifaddr, ifq head, lock.h mutex.h */
 #include <net/netisr.h>
 #include <netinet/in.h>
 #include <netinet/ip.h>                /* ip_len, ip_off */
@@ -85,8 +87,6 @@ __FBSDID("$FreeBSD: src/sys/netinet/ip_dummynet.c,v 1.110.2.4 2008/10/31 12:58:1
 #include <netinet/ip6.h>       /* for ip6_input, ip6_output prototypes */
 #include <netinet6/ip6_var.h>
 
-#include "missing.h"
-
 /*
  * We keep a private variable for the simulation time, but we could
  * probably use an existing one ("softticks" in sys/kern/kern_timeout.c)
@@ -248,8 +248,8 @@ static void dummynet(void *);
 static void    dummynet_flush(void);
 static void    dummynet_send(struct mbuf *);
 void           dummynet_drain(void);
-static ip_dn_io_t dummynet_io;
 static void    dn_rule_delete(void *);
+static int     dummynet_io(struct mbuf **, int , struct ip_fw_args *);
 
 /*
  * Heap management functions.
@@ -697,13 +697,17 @@ ready_event_wfq(struct dn_pipe *p, struct mbuf **head, struct mbuf **tail)
        struct dn_heap *neh = &(p->not_eligible_heap);
        int64_t p_numbytes = p->numbytes;
 
+       /*
+        * p->numbytes is only 32bits in FBSD7, but we might need 64 bits.
+        * Use a local variable for the computations, and write back the
+        * results when done, saturating if needed.
+        * The local variable has no impact on performance and helps
+        * reducing diffs between the various branches.
+        */
+
        DUMMYNET_LOCK_ASSERT();
 
        if (p->if_name[0] == 0)         /* tx clock is simulated */
-               /*
-                * Since result may not fit into p->numbytes (32bit) we
-                * are using 64bit var here.
-                */
                p_numbytes += (curr_time - p->sched_time) * p->bandwidth;
        else {  /*
                 * tx clock is for real,
@@ -814,13 +818,8 @@ ready_event_wfq(struct dn_pipe *p, struct mbuf **head, struct mbuf **tail)
                 */
        }
 
-       /* Fit (adjust if necessary) 64bit result into 32bit variable. */
-       if (p_numbytes > INT_MAX)
-               p->numbytes = INT_MAX;
-       else if (p_numbytes < INT_MIN)
-               p->numbytes = INT_MIN;
-       else
-               p->numbytes = p_numbytes;
+       /* Write back p_numbytes (adjust 64->32bit if necessary). */
+       p->numbytes = p_numbytes;
 
        /*
         * If the delay line was empty call transmit_event() now.
@@ -1245,7 +1244,7 @@ red_drops(struct dn_flow_set *fs, struct dn_flow_queue *q, int len)
                        u_int t = div64(curr_time - q->q_time,
                            fs->lookup_step);
 
-                       q->avg = (t >= 0 && t < fs->lookup_depth) ?
+                       q->avg = (t < fs->lookup_depth) ?
                            SCALE_MUL(q->avg, fs->w_q_lookup[t]) : 0;
                }
        }
@@ -1423,6 +1422,8 @@ dummynet_io(struct mbuf **m0, int dir, struct ip_fw_args *fwa)
         * Build and enqueue packet + parameters.
         */
        pkt->rule = fwa->rule;
+       pkt->rule_id = fwa->rule_id;
+       pkt->chain_id = fwa->chain_id;
        pkt->dn_dir = dir;
 
        pkt->ifp = fwa->oif;
@@ -1477,7 +1478,7 @@ dummynet_io(struct mbuf **m0, int dir, struct ip_fw_args *fwa)
                        heap_extract(&(pipe->idle_heap), q);
                        q->S = MAX64(q->F, pipe->V);
                }
-               q->F = div64(q->S + (len << MY_M), fs->weight);
+               q->F = q->S + div64(len << MY_M, fs->weight);
 
                if (pipe->not_eligible_heap.elements == 0 &&
                    pipe->scheduler_heap.elements == 0)
@@ -1540,7 +1541,7 @@ dropit:
                pkt = dn_tag_get(m);
                pkt->dn_dir = DN_TO_DROP;
        }
-       dummynet_send(m);       /* drop the packet */
+       dummynet_send(m);       /* drop the packet */
        *m0 = NULL;
        return ((fs && (fs->flags_fs & DN_NOERROR)) ? 0 : ENOBUFS);
 }
@@ -1549,9 +1550,15 @@ dropit:
  * Below, the rt_unref is only needed when (pkt->dn_dir == DN_TO_IP_OUT)
  * Doing this would probably save us the initial bzero of dn_pkt
  */
-#define        DN_FREE_PKT(_m) do {                            \
+#if defined( __linux__ )
+#define DN_FREE_PKT(_m) do {                           \
+       netisr_dispatch(-1, _m);                        \
+} while (0)
+#else
+#define DN_FREE_PKT(_m) do {                           \
        m_freem(_m);                                    \
 } while (0)
+#endif
 
 /*
  * Dispose all packets and flow_queues on a flow_set.
@@ -1830,6 +1837,8 @@ config_pipe(struct dn_pipe *p)
         * qsize = slots/bytes
         */
        p->delay = (p->delay * hz) / 1000;
+       /* Scale burst size: bytes -> bits * hz */
+       p->burst *= 8 * hz;
        /* We need either a pipe number or a flow_set number. */
        if (p->pipe_nr == 0 && pfs->fs_nr == 0)
                return (EINVAL);
@@ -2206,6 +2215,7 @@ dummynet_get(struct sockopt *sopt)
                 */
                bcopy(pipe, bp, sizeof(*pipe));
                pipe_bp->delay = (pipe_bp->delay * 1000) / hz;
+               pipe_bp->burst = div64(pipe_bp->burst, 8 * hz);
                /*
                 * XXX the following is a hack based on ->next being the
                 * first field in dn_pipe and dn_flow_set. The correct
@@ -2272,7 +2282,7 @@ ip_dn_ctl(struct sockopt *sopt)
     switch (sopt->sopt_name) {
     default :
        printf("dummynet: -- unknown option %d", sopt->sopt_name);
-        error = EINVAL ;
+       error = EINVAL ;
        break ;
 
     case IP_DUMMYNET_GET :
@@ -2295,8 +2305,8 @@ ip_dn_ctl(struct sockopt *sopt)
        break ;
 
     case IP_DUMMYNET_DEL :     /* remove a pipe or queue */
-       p = malloc(sizeof(struct dn_pipe_max), M_TEMP, M_WAITOK);
-       error = sooptcopyin(sopt, p, sizeof *p, sizeof *p);
+       p = malloc(sizeof(struct dn_pipe), M_TEMP, M_WAITOK);
+       error = sooptcopyin(sopt, p, sizeof (struct dn_pipe), sizeof *p);
        if (error)
            break ;