Changeset View
Changeset View
Standalone View
Standalone View
head/sys/netpfil/ipfw/ip_dn_io.c
Show First 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | |||||
#include <netinet/ip_dummynet.h> | #include <netinet/ip_dummynet.h> | ||||
#include <netinet/if_ether.h> /* various ether_* routines */ | #include <netinet/if_ether.h> /* various ether_* routines */ | ||||
#include <netinet/ip6.h> /* for ip6_input, ip6_output prototypes */ | #include <netinet/ip6.h> /* for ip6_input, ip6_output prototypes */ | ||||
#include <netinet6/ip6_var.h> | #include <netinet6/ip6_var.h> | ||||
#include <netpfil/ipfw/ip_fw_private.h> | #include <netpfil/ipfw/ip_fw_private.h> | ||||
#include <netpfil/ipfw/dn_heap.h> | #include <netpfil/ipfw/dn_heap.h> | ||||
#include <netpfil/ipfw/ip_dn_private.h> | #include <netpfil/ipfw/ip_dn_private.h> | ||||
#ifdef NEW_AQM | |||||
#include <netpfil/ipfw/dn_aqm.h> | |||||
#endif | |||||
#include <netpfil/ipfw/dn_sched.h> | #include <netpfil/ipfw/dn_sched.h> | ||||
/* | /* | ||||
* We keep a private variable for the simulation time, but we could | * We keep a private variable for the simulation time, but we could | ||||
* probably use an existing one ("softticks" in sys/kern/kern_timeout.c) | * probably use an existing one ("softticks" in sys/kern/kern_timeout.c) | ||||
* instead of dn_cfg.curr_time | * instead of dn_cfg.curr_time | ||||
*/ | */ | ||||
struct dn_parms dn_cfg; | struct dn_parms dn_cfg; | ||||
//VNET_DEFINE(struct dn_parms, _base_dn_cfg); | //VNET_DEFINE(struct dn_parms, _base_dn_cfg); | ||||
static long tick_last; /* Last tick duration (usec). */ | static long tick_last; /* Last tick duration (usec). */ | ||||
static long tick_delta; /* Last vs standard tick diff (usec). */ | static long tick_delta; /* Last vs standard tick diff (usec). */ | ||||
static long tick_delta_sum; /* Accumulated tick difference (usec).*/ | static long tick_delta_sum; /* Accumulated tick difference (usec).*/ | ||||
static long tick_adjustment; /* Tick adjustments done. */ | static long tick_adjustment; /* Tick adjustments done. */ | ||||
static long tick_lost; /* Lost(coalesced) ticks number. */ | static long tick_lost; /* Lost(coalesced) ticks number. */ | ||||
/* Adjusted vs non-adjusted curr_time difference (ticks). */ | /* Adjusted vs non-adjusted curr_time difference (ticks). */ | ||||
static long tick_diff; | static long tick_diff; | ||||
static unsigned long io_pkt; | static unsigned long io_pkt; | ||||
static unsigned long io_pkt_fast; | static unsigned long io_pkt_fast; | ||||
static unsigned long io_pkt_drop; | |||||
#ifdef NEW_AQM | |||||
unsigned long io_pkt_drop; | |||||
#else | |||||
static unsigned long io_pkt_drop; | |||||
#endif | |||||
/* | /* | ||||
* We use a heap to store entities for which we have pending timer events. | * We use a heap to store entities for which we have pending timer events. | ||||
* The heap is checked at every tick and all entities with expired events | * The heap is checked at every tick and all entities with expired events | ||||
* are extracted. | * are extracted. | ||||
*/ | */ | ||||
MALLOC_DEFINE(M_DUMMYNET, "dummynet", "dummynet heap"); | MALLOC_DEFINE(M_DUMMYNET, "dummynet", "dummynet heap"); | ||||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | sysctl_limits(SYSCTL_HANDLER_ARGS) | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
SYSBEGIN(f4) | SYSBEGIN(f4) | ||||
SYSCTL_DECL(_net_inet); | SYSCTL_DECL(_net_inet); | ||||
SYSCTL_DECL(_net_inet_ip); | SYSCTL_DECL(_net_inet_ip); | ||||
#ifdef NEW_AQM | |||||
SYSCTL_NODE(_net_inet_ip, OID_AUTO, dummynet, CTLFLAG_RW, 0, "Dummynet"); | |||||
#else | |||||
static SYSCTL_NODE(_net_inet_ip, OID_AUTO, dummynet, CTLFLAG_RW, 0, "Dummynet"); | static SYSCTL_NODE(_net_inet_ip, OID_AUTO, dummynet, CTLFLAG_RW, 0, "Dummynet"); | ||||
#endif | |||||
/* wrapper to pass dn_cfg fields to SYSCTL_* */ | /* wrapper to pass dn_cfg fields to SYSCTL_* */ | ||||
//#define DC(x) (&(VNET_NAME(_base_dn_cfg).x)) | //#define DC(x) (&(VNET_NAME(_base_dn_cfg).x)) | ||||
#define DC(x) (&(dn_cfg.x)) | #define DC(x) (&(dn_cfg.x)) | ||||
/* parameters */ | /* parameters */ | ||||
SYSCTL_PROC(_net_inet_ip_dummynet, OID_AUTO, hash_size, | SYSCTL_PROC(_net_inet_ip_dummynet, OID_AUTO, hash_size, | ||||
▲ Show 20 Lines • Show All 85 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* Return the mbuf tag holding the dummynet state (it should | * Return the mbuf tag holding the dummynet state (it should | ||||
* be the first one on the list). | * be the first one on the list). | ||||
*/ | */ | ||||
static struct dn_pkt_tag * | static struct dn_pkt_tag * | ||||
dn_tag_get(struct mbuf *m) | dn_tag_get(struct mbuf *m) | ||||
{ | { | ||||
struct m_tag *mtag = m_tag_first(m); | struct m_tag *mtag = m_tag_first(m); | ||||
#ifdef NEW_AQM | |||||
/* XXX: to skip ts m_tag. For Debugging only*/ | |||||
if (mtag != NULL && mtag->m_tag_id == DN_AQM_MTAG_TS) { | |||||
m_tag_delete(m,mtag); | |||||
mtag = m_tag_first(m); | |||||
D("skip TS tag"); | |||||
} | |||||
#endif | |||||
KASSERT(mtag != NULL && | KASSERT(mtag != NULL && | ||||
mtag->m_tag_cookie == MTAG_ABI_COMPAT && | mtag->m_tag_cookie == MTAG_ABI_COMPAT && | ||||
mtag->m_tag_id == PACKET_TAG_DUMMYNET, | mtag->m_tag_id == PACKET_TAG_DUMMYNET, | ||||
("packet on dummynet queue w/o dummynet tag!")); | ("packet on dummynet queue w/o dummynet tag!")); | ||||
return (struct dn_pkt_tag *)(mtag+1); | return (struct dn_pkt_tag *)(mtag+1); | ||||
} | } | ||||
#ifndef NEW_AQM | |||||
static inline void | static inline void | ||||
mq_append(struct mq *q, struct mbuf *m) | mq_append(struct mq *q, struct mbuf *m) | ||||
{ | { | ||||
#ifdef USERSPACE | #ifdef USERSPACE | ||||
// buffers from netmap need to be copied | // buffers from netmap need to be copied | ||||
// XXX note that the routine is not expected to fail | // XXX note that the routine is not expected to fail | ||||
ND("append %p to %p", m, q); | ND("append %p to %p", m, q); | ||||
if (m->m_flags & M_STACK) { | if (m->m_flags & M_STACK) { | ||||
Show All 23 Lines | #endif /* USERSPACE */ | ||||
if (q->head == NULL) | if (q->head == NULL) | ||||
q->head = m; | q->head = m; | ||||
else | else | ||||
q->tail->m_nextpkt = m; | q->tail->m_nextpkt = m; | ||||
q->count++; | q->count++; | ||||
q->tail = m; | q->tail = m; | ||||
m->m_nextpkt = NULL; | m->m_nextpkt = NULL; | ||||
} | } | ||||
#endif | |||||
/* | /* | ||||
* Dispose a list of packet. Use a functions so if we need to do | * Dispose a list of packet. Use a functions so if we need to do | ||||
* more work, this is a central point to do it. | * more work, this is a central point to do it. | ||||
*/ | */ | ||||
void dn_free_pkts(struct mbuf *mnext) | void dn_free_pkts(struct mbuf *mnext) | ||||
{ | { | ||||
struct mbuf *m; | struct mbuf *m; | ||||
▲ Show 20 Lines • Show All 108 Lines • ▼ Show 20 Lines | red_drops (struct dn_queue *q, int len) | ||||
return (0); /* accept */ | return (0); /* accept */ | ||||
} | } | ||||
/* | /* | ||||
* ECN/ECT Processing (partially adopted from altq) | * ECN/ECT Processing (partially adopted from altq) | ||||
*/ | */ | ||||
static int | #ifndef NEW_AQM | ||||
static | |||||
#endif | |||||
int | |||||
ecn_mark(struct mbuf* m) | ecn_mark(struct mbuf* m) | ||||
{ | { | ||||
struct ip *ip; | struct ip *ip; | ||||
ip = mtod(m, struct ip *); | ip = mtod(m, struct ip *); | ||||
switch (ip->ip_v) { | switch (ip->ip_v) { | ||||
case IPVERSION: | case IPVERSION: | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 66 Lines • ▼ Show 20 Lines | dn_enqueue(struct dn_queue *q, struct mbuf* m, int drop) | ||||
q->ni.tot_bytes += len; | q->ni.tot_bytes += len; | ||||
q->ni.tot_pkts++; | q->ni.tot_pkts++; | ||||
ni->tot_bytes += len; | ni->tot_bytes += len; | ||||
ni->tot_pkts++; | ni->tot_pkts++; | ||||
if (drop) | if (drop) | ||||
goto drop; | goto drop; | ||||
if (f->plr && random() < f->plr) | if (f->plr && random() < f->plr) | ||||
goto drop; | goto drop; | ||||
#ifdef NEW_AQM | |||||
/* Call AQM enqueue function */ | |||||
if (q->fs->aqmfp) | |||||
return q->fs->aqmfp->enqueue(q ,m); | |||||
#endif | |||||
if (f->flags & DN_IS_RED && red_drops(q, m->m_pkthdr.len)) { | if (f->flags & DN_IS_RED && red_drops(q, m->m_pkthdr.len)) { | ||||
if (!(f->flags & DN_IS_ECN) || !ecn_mark(m)) | if (!(f->flags & DN_IS_ECN) || !ecn_mark(m)) | ||||
goto drop; | goto drop; | ||||
} | } | ||||
if (f->flags & DN_QSIZE_BYTES) { | if (f->flags & DN_QSIZE_BYTES) { | ||||
if (q->ni.len_bytes > f->qsize) | if (q->ni.len_bytes > f->qsize) | ||||
goto drop; | goto drop; | ||||
} else if (q->ni.length >= f->qsize) { | } else if (q->ni.length >= f->qsize) { | ||||
▲ Show 20 Lines • Show All 371 Lines • ▼ Show 20 Lines | dummynet_io(struct mbuf **m0, int dir, struct ip_fw_args *fwa) | ||||
if (fs->sched->fp->flags & DN_MULTIQUEUE) { | if (fs->sched->fp->flags & DN_MULTIQUEUE) { | ||||
q = ipdn_q_find(fs, si, &(fwa->f_id)); | q = ipdn_q_find(fs, si, &(fwa->f_id)); | ||||
if (q == NULL) | if (q == NULL) | ||||
goto dropit; | goto dropit; | ||||
} | } | ||||
if (fs->sched->fp->enqueue(si, q, m)) { | if (fs->sched->fp->enqueue(si, q, m)) { | ||||
/* packet was dropped by enqueue() */ | /* packet was dropped by enqueue() */ | ||||
m = *m0 = NULL; | m = *m0 = NULL; | ||||
/* dn_enqueue already increases io_pkt_drop */ | |||||
io_pkt_drop--; | |||||
goto dropit; | goto dropit; | ||||
} | } | ||||
if (si->kflags & DN_ACTIVE) { | if (si->kflags & DN_ACTIVE) { | ||||
m = *m0 = NULL; /* consumed */ | m = *m0 = NULL; /* consumed */ | ||||
goto done; /* already active, nothing to do */ | goto done; /* already active, nothing to do */ | ||||
} | } | ||||
▲ Show 20 Lines • Show All 51 Lines • Show Last 20 Lines |