integrated
[ipfw.git] / dummynet2 / include / netinet / ipfw / dn_sched.h
index 3c75b64..a755e86 100644 (file)
@@ -119,6 +119,10 @@ struct dn_alg {
         * free_queue   actions related to a queue removal, e.g. undo
         *      all the above. If the queue has data in it, also remove
         *      from the scheduler. This can e.g. happen during a reconfigure.
+        *      If safe == 1 remove the queue only if the scheduler no longer
+        *      need it, otherwise delete it even if the scheduler is using
+        *      it. Usually, the flag safe is set when the drain routine is
+        *      running to delete idle queues.
         */
        int (*enqueue)(struct dn_sch_inst *, struct dn_queue *,
                struct mbuf *);
@@ -131,7 +135,7 @@ struct dn_alg {
        int (*new_fsk)(struct dn_fsk *f);
        int (*free_fsk)(struct dn_fsk *f);
        int (*new_queue)(struct dn_queue *q);
-       int (*free_queue)(struct dn_queue *q);
+       int (*free_queue)(struct dn_queue *q, int safe);
 
        /* run-time fields */
        int ref_count;      /* XXX number of instances in the system */
@@ -166,14 +170,27 @@ dn_dequeue(struct dn_queue *q)
        if (m == NULL)
                return NULL;
        q->mq.head = m->m_nextpkt;
+
+       /* Update stats for the queue */
        q->ni.length--;
        q->ni.len_bytes -= m->m_pkthdr.len;
+       /* When the queue becomes idle, update idle_time (used by RED)
+        * and also update the count of idle queues (for garbage collection).
+        */
+       if (q->ni.length == 0) {
+               dn_cfg.idle_queue++;
+               q->q_time = dn_cfg.curr_time;
+       }
        if (q->_si) {
-               q->_si->ni.length--;
-               q->_si->ni.len_bytes -= m->m_pkthdr.len;
+               struct dn_flow *ni = &(q->_si->ni);
+               /* update stats for the scheduler instance, and keep track
+                * of idle scheduler instances if needed
+                */
+               ni->length--;
+               ni->len_bytes -= m->m_pkthdr.len;
+               if (ni->length == 0)
+                       dn_cfg.idle_si++;
        }
-       if (q->ni.length == 0) /* queue is now idle */
-               q->q_time = dn_cfg.curr_time;
        return m;
 }