#ifdef _KERNEL
#include <sys/malloc.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/mbuf.h>
#include <sys/module.h>
#include <sys/rwlock.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/ip_var.h>
#include <netinet/ip_fw.h>
#include <netinet/ip_dummynet.h>
#include <netpfil/ipfw/ip_fw_private.h>
#include <netpfil/ipfw/dn_heap.h>
#include <netpfil/ipfw/ip_dn_private.h>
#ifdef NEW_AQM
#include <netpfil/ipfw/dn_aqm.h>
#endif
#include <netpfil/ipfw/dn_sched.h>
#else
#include <dn_test.h>
#endif
#define DN_SCHED_PRIO 5
#if !defined(_KERNEL) || !defined(__linux__)
#define test_bit(ix, pData) ((*pData) & (1<<(ix)))
#define __set_bit(ix, pData) (*pData) |= (1<<(ix))
#define __clear_bit(ix, pData) (*pData) &= ~(1<<(ix))
#endif
#ifdef __MIPSEL__
#define __clear_bit(ix, pData) (*pData) &= ~(1<<(ix))
#endif
#define BITMAP_T unsigned long
#define MAXPRIO (sizeof(BITMAP_T) * 8)
struct prio_si {
BITMAP_T bitmap;
struct dn_queue *q_array[MAXPRIO];
};
static int
prio_enqueue(struct dn_sch_inst *_si, struct dn_queue *q, struct mbuf *m)
{
struct prio_si *si = (struct prio_si *)(_si + 1);
int prio = q->fs->fs.par[0];
if (test_bit(prio, &si->bitmap) == 0) {
__set_bit(prio, &si->bitmap);
si->q_array[prio] = q;
} else {
q = si->q_array[prio];
}
if (dn_enqueue(q, m, 0))
return 1;
return 0;
}
static struct mbuf *
prio_dequeue(struct dn_sch_inst *_si)
{
struct prio_si *si = (struct prio_si *)(_si + 1);
struct mbuf *m;
struct dn_queue *q;
int prio;
if (si->bitmap == 0)
return NULL;
prio = ffs(si->bitmap) - 1;
q = si->q_array[prio];
m = dn_dequeue(q);
if (q->mq.head == NULL) {
si->q_array[prio] = NULL;
__clear_bit(prio, &si->bitmap);
}
return m;
}
static int
prio_new_sched(struct dn_sch_inst *_si)
{
struct prio_si *si = (struct prio_si *)(_si + 1);
bzero(si->q_array, sizeof(si->q_array));
si->bitmap = 0;
return 0;
}
static int
prio_new_fsk(struct dn_fsk *fs)
{
ipdn_bound_var(&fs->fs.par[0], 0, 0, MAXPRIO - 1, "PRIO priority");
return 0;
}
static int
prio_new_queue(struct dn_queue *q)
{
struct prio_si *si = (struct prio_si *)(q->_si + 1);
int prio = q->fs->fs.par[0];
struct dn_queue *oldq;
q->ni.oid.subtype = DN_SCHED_PRIO;
if (q->mq.head == NULL)
return 0;
if (test_bit(prio, &si->bitmap) == 0) {
__set_bit(prio, &si->bitmap);
si->q_array[prio] = q;
} else if ( (oldq = si->q_array[prio]) != q) {
oldq->mq.tail->m_nextpkt = q->mq.head;
oldq->mq.tail = q->mq.tail;
oldq->ni.length += q->ni.length;
q->ni.length = 0;
oldq->ni.len_bytes += q->ni.len_bytes;
q->ni.len_bytes = 0;
q->mq.tail = q->mq.head = NULL;
}
return 0;
}
static int
prio_free_queue(struct dn_queue *q)
{
int prio = q->fs->fs.par[0];
struct prio_si *si = (struct prio_si *)(q->_si + 1);
if (si->q_array[prio] == q) {
si->q_array[prio] = NULL;
__clear_bit(prio, &si->bitmap);
}
return 0;
}
static struct dn_alg prio_desc = {
_SI( .type = ) DN_SCHED_PRIO,
_SI( .name = ) "PRIO",
_SI( .flags = ) DN_MULTIQUEUE,
_SI( .schk_datalen = ) 0,
_SI( .si_datalen = ) sizeof(struct prio_si),
_SI( .q_datalen = ) 0,
_SI( .enqueue = ) prio_enqueue,
_SI( .dequeue = ) prio_dequeue,
_SI( .config = ) NULL,
_SI( .destroy = ) NULL,
_SI( .new_sched = ) prio_new_sched,
_SI( .free_sched = ) NULL,
_SI( .new_fsk = ) prio_new_fsk,
_SI( .free_fsk = ) NULL,
_SI( .new_queue = ) prio_new_queue,
_SI( .free_queue = ) prio_free_queue,
#ifdef NEW_AQM
_SI( .getconfig = ) NULL,
#endif
};
DECLARE_DNSCHED_MODULE(dn_prio, &prio_desc);