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
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
*
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.
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.
* 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 */
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 *);
/*