integrated
[ipfw.git] / dummynet2 / include / netinet / ipfw / ip_dn_private.h
index 47cc5e8..ecb4fe2 100644 (file)
 
 MALLOC_DECLARE(M_DUMMYNET);
 
-#ifndef FREE_PKT
-#define        FREE_PKT(m)     m_freem(m)
-#endif
-
 #ifndef __linux__
 #define div64(a, b)  ((int64_t)(a) / (int64_t)(b))
 #endif
@@ -97,6 +93,17 @@ set_oid(struct dn_id *o, int type, int len)
         o->subtype = 0;
 };
 
+uint64_t readTSC (void);
+/*
+ * see if tsc (ot other timer) is supported.
+ * - FreeBSD has rdtsc macro for i386 and amd64
+ * - Linux has rdtscll and/or rdtsc (also for openWRT patched kernel source)
+ * - Windows has KeQueryPerformanceCounter() function that use tsc or other
+ *   timer
+ */
+#if defined(rdtscll) || defined(rdtsc) || defined(_WIN32)
+#define HAVE_TSC
+#endif
 /*
  * configuration and global data for a dummynet instance
  *
@@ -129,7 +136,21 @@ struct dn_parms {
        int     queue_count;
 
        /* ticks and other stuff */
-       uint64_t        curr_time;
+       uint64_t        curr_time;      /* in ticks */
+
+       /*
+        * Variables to manage the time spent in the drain routines.
+        * max_drain is max the fraction of a tick (0..100) to be used
+        * for draining.
+        * We also need some variables to store the average number of
+        * timecounter ticks between calls to the periodic task, etc.
+        */
+       int drain_ratio;
+       uint64_t cycle_task_new;        /* TSC when dummynet_task() starts */
+       uint64_t cycle_task_old;        /* TSC when prev. dummynet_task() starts */
+       uint64_t cycle_task;
+       uint64_t cycle_task_avg;        /* Moving average of cicle_task */
+
        /* flowsets and schedulers are in hash tables, with 'hash_size'
         * buckets. fshash is looked up at every packet arrival
         * so better be generous if we expect many entries.
@@ -140,16 +161,33 @@ struct dn_parms {
        struct dn_fsk_head      fsu;    /* list of unlinked flowsets */
        struct dn_alg_head      schedlist;      /* list of algorithms */
 
-       /* Store the fs/sch to scan when draining. The value is the
-        * bucket number of the hash table. Expire can be disabled
-        * with net.inet.ip.dummynet.expire=0, or it happens every
-        * expire ticks.
-        **/
-       int drain_fs;
-       int drain_sch;
-       uint32_t expire;
-       uint32_t expire_cycle;  /* tick count */
-       
+       /* Counter of idle objects -- used by drain routine
+        * We scan when idle_queue (or idle_si) > expire_object.
+        * The drain routine is called every 'expire' cycles (the counter
+        * used is expire_cycle).
+        * We can disable the expire routine by setting expire to 0.
+        * An object is kept alive for at least object_idle_tick after it
+        * becomes idle. During the scan, we count the number of objects
+        * that are idle but not ready in 'idle_si_wait' and 'idle_queue_wait'
+        */
+       int     idle_queue;
+       int     idle_queue_wait;                /* idle but not expired yet */
+       int     idle_si;
+       int     idle_si_wait;                   /* idle but not expired yet */
+       uint32_t expire_object;                 /* threshold for expires */
+       uint32_t expire;                        /* how often to expire */
+       uint32_t expire_cycle;
+       uint32_t object_idle_tick;              /* lifetime of objs */
+       uint32_t expire_object_examined;        /* Burst of object examined */
+
+       /* drain_fs and drain_sch point to the next bucket to scan when
+        * draining.
+        */
+       uint32_t drain_fs;
+       uint32_t drain_sch;
+
+       int init_done;
+
        /* if the upper half is busy doing something long,
         * can set the busy flag and we will enqueue packets in
         * a queue for later processing.
@@ -310,37 +348,14 @@ struct dn_sch_inst {
         * The counter is incremented or decremented when
         * a reference from the queue is created or deleted.
         * It is used to make sure that a scheduler instance can be safely
-        * deleted by the drain routine. See notes below.
+        * deleted by the drain routine.
         */
        int q_count;
 
 };
 
-/*
- * NOTE about object drain.
- * The system will automatically (XXX check when) drain queues and
- * scheduler instances when they are idle.
- * A queue is idle when it has no packets; an instance is idle when
- * it is not in the evheap heap, and the corresponding delay line is empty.
- * A queue can be safely deleted when it is idle because of the scheduler
- * function xxx_free_queue() will remove any references to it.
- * An instance can be only deleted when no queues reference it. To be sure
- * of that, a counter (q_count) stores the number of queues that are pointing
- * to the instance.
- *
- * XXX
- * Order of scan:
- * - take all flowset in a bucket for the flowset hash table
- * - take all queues in a bucket for the flowset
- * - increment the queue bucket
- * - scan next flowset bucket
- * Nothing is done if a bucket contains no entries.
- *
- * The same schema is used for sceduler instances
- */
-
 
-/* kernel-side flags. Linux has DN_DELETE in fcntl.h 
+/* kernel-side flags. Linux has DN_DELETE in fcntl.h
  */
 enum {
        /* 1 and 2 are reserved for the SCAN flags */
@@ -349,18 +364,20 @@ enum {
        DN_DETACH       = 0x0010,
        DN_ACTIVE       = 0x0020, /* object is in evheap */
        DN_F_DLINE      = 0x0040, /* object is a delay line */
-       DN_F_SCHI       = 0x00C0, /* object is a sched.instance */
+       DN_DEL_SAFE     = 0x0080, /* delete a queue only if no longer needed
+                                  * by scheduler */
        DN_QHT_IS_Q     = 0x0100, /* in flowset, qht is a single queue */
 };
 
 extern struct dn_parms dn_cfg;
+//VNET_DECLARE(struct dn_parms, _base_dn_cfg);
+//#define dn_cfg       VNET(_base_dn_cfg)
 
 int dummynet_io(struct mbuf **, int , struct ip_fw_args *);
 void dummynet_task(void *context, int pending);
 void dn_reschedule(void);
 
-struct dn_queue *ipdn_q_find(struct dn_fsk *, struct dn_sch_inst *,
-        struct ipfw_flow_id *);
+struct dn_queue *ipdn_q_find(struct dn_fsk *, struct ipfw_flow_id *);
 struct dn_sch_inst *ipdn_si_find(struct dn_schk *, struct ipfw_flow_id *);
 
 /*