svn commit: r202758 - in user/luigi/ipfw3-head: sbin/ipfw
sys/netinet sys/netinet/ipfw
Luigi Rizzo
luigi at FreeBSD.org
Thu Jan 21 17:34:02 UTC 2010
Author: luigi
Date: Thu Jan 21 17:34:01 2010
New Revision: 202758
URL: http://svn.freebsd.org/changeset/base/202758
Log:
+ more renaming (pipe->link, dn_sched ->dn_alg)
+ implement more listing options;
Modified:
user/luigi/ipfw3-head/sbin/ipfw/dummynet.c
user/luigi/ipfw3-head/sbin/ipfw/ipfw2.h
user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h
user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h
user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_fifo.c
user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_rr.c
user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c
user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h
user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c
Modified: user/luigi/ipfw3-head/sbin/ipfw/dummynet.c
==============================================================================
--- user/luigi/ipfw3-head/sbin/ipfw/dummynet.c Thu Jan 21 17:26:11 2010 (r202757)
+++ user/luigi/ipfw3-head/sbin/ipfw/dummynet.c Thu Jan 21 17:34:01 2010 (r202758)
@@ -67,7 +67,7 @@ static struct _s_x dummynet_params[] = {
{ "bw", TOK_BW },
{ "bandwidth", TOK_BW },
{ "delay", TOK_DELAY },
- { "link", TOK_PIPE },
+ { "link", TOK_LINK },
{ "pipe", TOK_PIPE },
{ "queue", TOK_QUEUE },
{ "flowset", TOK_FLOWSET },
@@ -79,7 +79,7 @@ static struct _s_x dummynet_params[] = {
{ "dst-ip6", TOK_DSTIP6},
{ "src-ipv6", TOK_SRCIP6},
{ "src-ip6", TOK_SRCIP6},
- { "profile", TOK_PIPE_PROFILE},
+ { "profile", TOK_PROFILE},
{ "burst", TOK_BURST},
{ "dummynet-params", TOK_NULL },
{ NULL, 0 } /* terminator */
@@ -179,7 +179,7 @@ list_flow(struct dn_flow *ni)
pe = getprotobynumber(id->proto);
/* XXX: Should check for IPv4 flows */
- printf("%3d ", ni->oid.id);
+ printf("%3u ", (ni->oid.id) & 0xff);
if (!IS_IP6_FLOW_ID(id)) {
if (pe)
printf("%-4s ", pe->p_name);
@@ -243,9 +243,17 @@ print_flowset_parms(struct new_fs *fs, c
#endif
sprintf(red, "droptail");
- printf("%s %s%s %d queues (%d buckets) %s\n",
- prefix, qs, plr, fs->oid.id, fs->buckets, red);
- prefix[0] = '\0';
+ if (prefix[0]) {
+ printf("%s %s%s %d queues (%d buckets) %s\n",
+ prefix, qs, plr, fs->oid.id, fs->buckets, red);
+ prefix[0] = '\0';
+ } else {
+ printf("q%05d %s%s %d queues (%d buckets) %s sched %d\n",
+ fs->fs_nr, qs, plr, fs->oid.id, fs->buckets, red,
+ fs->sched_nr);
+ if (fs->flags & DN_HAVE_MASK)
+ print_mask(&fs->flow_mask);
+ }
}
static void
@@ -273,7 +281,8 @@ flush_buf(char *buf)
* generic list routine. We expect objects in a specific order, i.e.
* PIPES AND SCHEDULERS:
* link; scheduler; internal flowset if any; instances
- * XXX do we need the queue ?
+ * we can tell a pipe from the number.
+ *
* FLOWSETS:
* flowset; queues;
* link i (int queue); scheduler i; si(i) { flowsets() : queues }
@@ -294,13 +303,31 @@ list_pipes(struct dn_id *oid, struct dn_
flush_buf(buf);
printf("unrecognized object %d size %d\n", oid->type, oid->len);
break;
+ case DN_TEXT: /* list of attached flowsets */
+ {
+ int i, l;
+ struct {
+ struct dn_id id;
+ uint16_t p[0];
+ } *d = (void *)oid;
+ l = (oid->len - sizeof(*oid))/sizeof(uint16_t);
+ if (l == 0)
+ break;
+ printf(" Children flowsets: ");
+ for (i = 0; i < l; i++)
+ printf("%d ", d->p[i]);
+ printf("\n");
+ break;
+ }
case DN_CMD_GET:
- printf("respond to cmd %d buflen %d\n", oid->type, oid->id);
+ if (co.verbose)
+ printf("answer for cmd %d, len %d\n", oid->type, oid->id);
break;
case DN_SCH: {
struct new_sch *s = (struct new_sch *)oid;
flush_buf(buf);
- printf(" type %s flags 0x%x %d buckets\n",
+ printf(" sched %d type %s flags 0x%x %d buckets\n",
+ s->sched_nr,
s->name, s->flags, s->buckets);
if (s->flags & DN_HAVE_MASK)
print_mask(&s->sched_mask);
@@ -333,7 +360,7 @@ list_pipes(struct dn_id *oid, struct dn_
"", HN_AUTOSCALE, 0) < 0 || co.verbose)
sprintf(burst, "%d", (int)p->burst);
sprintf(buf, "%05d: %s %4d ms burst %s",
- p->link_nr, bwbuf, p->delay, burst);
+ p->link_nr % DN_MAX_ID, bwbuf, p->delay, burst);
}
break;
@@ -382,7 +409,7 @@ ipfw_delete_pipe(int pipe_or_queue, int
{
struct {
struct dn_id oid;
- uint32_t a[1]; /* more if we want a list */
+ uint32_t a[1]; /* add more if we want a list */
} cmd;
oid_fill((void *)&cmd, sizeof(cmd), DN_CMD_DELETE, DN_API_VERSION);
cmd.oid.subtype = (co.do_pipe == 1) ? DN_LINK :
@@ -764,8 +791,7 @@ ipfw_config_pipe(int ac, char **av)
*/
lmax = sizeof(struct dn_id); /* command header */
lmax += sizeof(struct new_sch) + sizeof(struct dn_link) +
- sizeof(struct new_fs) +
- sizeof(struct new_profile);
+ sizeof(struct new_fs) + sizeof(struct new_profile);
av++; ac--;
/* Pipe number */
@@ -779,49 +805,51 @@ ipfw_config_pipe(int ac, char **av)
errx(1, "no memory for buffer");
}
/* all commands start with a 'CONFIGURE' and a version */
- o_next(&buf, sizeof(struct dn_id), DN_CMD_CONFIGURE);
+ o_next(&buf, sizeof(struct dn_id), DN_CMD_CONFIG);
base->id = DN_API_VERSION;
switch (co.do_pipe) {
- case 1:
- /* the WFQ scheduler */
+ case 1: /* "pipe N config ..." */
+ /* Allocate space for the WF2Q+ scheduler, its link
+ * and the FIFO flowset. Set the number, but leave
+ * the scheduler subtype and other parameters to 0
+ * so the kernel will use appropriate defaults.
+ * XXX todo: add a flag to record if a parameter
+ * is actually configured.
+ * If we do a 'pipe config' mask -> sched_mask.
+ * The FIFO scheduler and link are derived from the
+ * WF2Q+ one in the kernel.
+ */
sch = o_next(&buf, sizeof(*sch), DN_SCH);
+ p = o_next(&buf, sizeof(*p), DN_LINK);
+ fs = o_next(&buf, sizeof(*fs), DN_FS);
+
sch->sched_nr = i;
- /* type should be wfq, but we set the default in the kernel. */
- sch->oid.subtype = 0;
+ sch->oid.subtype = 0; /* defaults to WF2Q+ */
mask = &sch->sched_mask;
flags = &sch->flags;
- /* the FIFO scheduler is created in the kernel from the WFQ one */
- /* the WFQ link */
- p = o_next(&buf, sizeof(*p), DN_LINK);
p->link_nr = i;
- /* the FIFO link is created in the kernel from WFQ link */
- /*
- * FIFO flowsets N+i are automatically created for
- * FIFO schedulers i, but we provide room to pass
- * queue parameters
- */
- fs = o_next(&buf, sizeof(*fs), DN_FS);
+ /* This flowset is only for the FIFO scheduler */
fs->fs_nr = i + 2*DN_MAX_ID;
fs->sched_nr = i + DN_MAX_ID;
break;
- case 2: /* flowset */
+ case 2: /* "queue N config ... " */
fs = o_next(&buf, sizeof(*fs), DN_FS);
fs->fs_nr = i;
mask = &fs->flow_mask;
flags = &fs->flags;
break;
- case 3: /* scheduler */
+ case 3: /* "sched N config ..." */
sch = o_next(&buf, sizeof(*sch), DN_SCH);
+ fs = o_next(&buf, sizeof(*fs), DN_FS);
sch->sched_nr = i;
mask = &sch->sched_mask;
flags = &sch->flags;
- /* room in case we have a FIFO scheduler */
- fs = o_next(&buf, sizeof(*fs), DN_FS);
+ /* fs is used only with !MULTIQUEUE schedulers */
fs->fs_nr = i + DN_MAX_ID;
fs->sched_nr = i;
break;
@@ -1075,7 +1103,7 @@ end_mask:
ac--; av++;
break;
- case TOK_PIPE_PROFILE:
+ case TOK_PROFILE:
NEED((!pf), "profile already set");
NEED(p, "profile");
{
Modified: user/luigi/ipfw3-head/sbin/ipfw/ipfw2.h
==============================================================================
--- user/luigi/ipfw3-head/sbin/ipfw/ipfw2.h Thu Jan 21 17:26:11 2010 (r202757)
+++ user/luigi/ipfw3-head/sbin/ipfw/ipfw2.h Thu Jan 21 17:34:01 2010 (r202758)
@@ -82,6 +82,7 @@ enum tokens {
TOK_ACCEPT,
TOK_COUNT,
TOK_PIPE,
+ TOK_LINK,
TOK_QUEUE,
TOK_FLOWSET,
TOK_SCHED,
@@ -157,7 +158,7 @@ enum tokens {
TOK_SCHED_MASK,
TOK_BW,
TOK_DELAY,
- TOK_PIPE_PROFILE,
+ TOK_PROFILE,
TOK_BURST,
TOK_RED,
TOK_GRED,
Modified: user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h Thu Jan 21 17:26:11 2010 (r202757)
+++ user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h Thu Jan 21 17:34:01 2010 (r202758)
@@ -71,10 +71,9 @@ enum {
DN_DELAY_LINE,
DN_PROFILE,
DN_FLOW, /* struct dn_flow */
- //DN_FS_EXT,
- //DN_QUEUE_EXT,
DN_TEXT, /* opaque text is the object */
- DN_CMD_CONFIGURE, /* objects follow */
+
+ DN_CMD_CONFIG = 0x80, /* objects follow */
DN_CMD_DELETE, /* subtype + list of entries */
DN_CMD_GET, /* subtype + list of entries */
DN_CMD_FLUSH,
@@ -115,21 +114,21 @@ struct dn_link {
};
/*
- * A flowset, which is a template for queues. Store here parameters
+ * A flowset, which is a template for flows. Contains parameters
* from the command line: id, target scheduler, queue sizes, plr,
- * flow masks, buckets for the queue hash, and possibly scheduler-
+ * flow masks, buckets for the flow hash, and possibly scheduler-
* specific parameters (weight, quantum and so on).
*/
struct new_fs {
struct dn_id oid;
- int fs_nr; /* the flowset number */
+ uint32_t fs_nr; /* the flowset number */
int flags; /* userland flags */
int qsize; /* queue size in slots or bytes */
- int plr; /* PLR, pkt loss rate (2^31-1 means 100%) */
- int buckets; /* buckets used for the queue hash table */
+ int32_t plr; /* PLR, pkt loss rate (2^31-1 means 100%) */
+ uint32_t buckets; /* buckets used for the queue hash table */
- struct ipfw_flow_id flow_mask; /* M */
- int sched_nr; /* the scheduler we attach to */
+ struct ipfw_flow_id flow_mask;
+ uint32_t sched_nr; /* the scheduler we attach to */
/* generic scheduler parameters */
int weight;
int quantum;
@@ -148,7 +147,6 @@ struct dn_flow {
uint32_t length; /* Queue lenght, in packets */
uint32_t len_bytes; /* Queue lenght, in bytes */
uint32_t drops;
- int hash_slot; /* XXX do we need it ? */
uint64_t tot_pkts; /* statistics counters */
uint64_t tot_bytes;
};
Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h Thu Jan 21 17:26:11 2010 (r202757)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h Thu Jan 21 17:34:01 2010 (r202758)
@@ -33,12 +33,12 @@
#define DN_MULTIQUEUE 0x01
/*
- * Descriptor for the scheduler.
+ * Descriptor for a scheduling algorithm.
* Contains all function pointers for a given scheduler
* This is typically created when a module is loaded, and stored
* in a global list of schedulers.
*/
-struct dn_sched {
+struct dn_alg {
uint32_t type; /* the scheduler type */
uint32_t flags; /* DN_MULTIQUEUE if supports multiple queues */
const char *name; /* scheduler name */
@@ -62,7 +62,7 @@ struct dn_sched {
size_t q_datalen; /* per-queue parameters (e.g. S,F) */
- SLIST_ENTRY(dn_sched) next; /* Next scheduler in the list */
+ SLIST_ENTRY(dn_alg) next; /* Next scheduler in the list */
/*
* Methods implemented by the scheduler:
Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_fifo.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_fifo.c Thu Jan 21 17:26:11 2010 (r202757)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_fifo.c Thu Jan 21 17:34:01 2010 (r202758)
@@ -92,7 +92,7 @@ fifo_free_sched(struct new_sch_inst *si)
* contains the type of the scheduler, the name, the size of extra
* data structures, and function pointers.
*/
-static struct dn_sched fifo_desc = {
+static struct dn_alg fifo_desc = {
.type = DN_SCHED_FIFO,
.name = "FIFO",
Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_rr.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_rr.c Thu Jan 21 17:26:11 2010 (r202757)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_rr.c Thu Jan 21 17:34:01 2010 (r202758)
@@ -257,7 +257,7 @@ rr_free_queue(struct new_queue *_q)
* contains the type of the scheduler, the name, the size of the
* structures and function pointers.
*/
-static struct dn_sched rr_desc = {
+static struct dn_alg rr_desc = {
.type = DN_SCHED_RR,
.name = "RR",
.flags = DN_MULTIQUEUE,
Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c Thu Jan 21 17:26:11 2010 (r202757)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c Thu Jan 21 17:34:01 2010 (r202758)
@@ -257,7 +257,7 @@ wf2qp_free_sched(struct new_sch_inst *_s
static int
wf2qp_new_fsk(struct new_fsk *fs)
{
- printf("%s called\n", __FUNCTION__);
+ // printf("%s called\n", __FUNCTION__);
if (fs->fs.weight < 1)
fs->fs.weight = 1;
else if (fs->fs.weight > 100)
@@ -314,7 +314,7 @@ wf2qp_free_queue(struct new_queue *q)
* contains the type of the scheduler, the name, the size of the
* structures and function pointers.
*/
-static struct dn_sched wf2qp_desc = {
+static struct dn_alg wf2qp_desc = {
.type = DN_SCHED_WF2QP,
.name = "WF2Q+",
.flags = DN_MULTIQUEUE,
Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h Thu Jan 21 17:26:11 2010 (r202757)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h Thu Jan 21 17:34:01 2010 (r202758)
@@ -64,7 +64,7 @@ SLIST_HEAD(new_schk_head, new_schk);
SLIST_HEAD(new_sch_inst_head, new_sch_inst);
SLIST_HEAD(new_fsk_head, new_fsk);
SLIST_HEAD(new_queue_head, new_queue);
-SLIST_HEAD(dn_sched_head, dn_sched);
+SLIST_HEAD(dn_alg_head, dn_alg);
struct mq { /* a basic queue of packets*/
struct mbuf *head, *tail;
@@ -116,7 +116,7 @@ struct dn_parms {
struct dn_ht *schedhash;
/* list of flowsets without a scheduler -- use sch_chain */
struct new_fsk_head fsu; /* list of unlinked flowsets */
- struct dn_sched_head schedlist; /* list of algorithms */
+ struct dn_alg_head schedlist; /* list of algorithms */
/* if the upper half is busy doing something long,
* can set the busy flag and we will enqueue packets in
@@ -159,7 +159,7 @@ struct delay_line {
*/
struct new_fsk { /* kernel side of a flowset */
struct new_fs fs;
- SLIST_ENTRY(new_fsk) fsk_next; /* hash chain list */
+ SLIST_ENTRY(new_fsk) fsk_next; /* hash chain for fshash */
struct ipfw_flow_id fsk_mask;
@@ -167,7 +167,6 @@ struct new_fsk { /* kernel side of a flo
struct dn_ht *_qht;
struct new_schk *sched; /* Sched we are linked to */
SLIST_ENTRY(new_fsk) sch_chain; /* list of fsk attached to sched */
- // void *sched_info; /* scheduler-specific info */
};
/*
@@ -182,9 +181,8 @@ struct new_queue {
struct dn_flow ni; /* oid, flow_id, stats */
struct mq mq; /* packets queue */
struct new_sch_inst *_si; /* owner scheduler instance */
- SLIST_ENTRY(new_queue) q_next; /* hash chain list for fs */
+ SLIST_ENTRY(new_queue) q_next; /* hash chain list for qht */
struct new_fsk *fs; /* parent flowset. */
- /* If fs->kflags & DN_DELETE, remove the queue when empty. */
};
/*
@@ -197,17 +195,19 @@ struct new_queue {
*/
struct new_schk {
struct new_sch sch;
- struct dn_sched *fp; /* Pointer to scheduler functions */
- struct dn_link link; /* the link is embedded */
- struct new_profile *profile;
- struct dn_id *cfg; /* extra config arguments */
+ struct dn_alg *fp; /* Pointer to scheduler functions */
+ struct dn_link link; /* The link, embedded */
+ struct new_profile *profile; /* delay profile, if any */
+ struct dn_id *cfg; /* extra config arguments */
- SLIST_ENTRY(new_schk) schk_next; /* hash chain list */
+ SLIST_ENTRY(new_schk) schk_next; /* hash chain for schedhash */
struct new_fsk_head fsk_list; /* all fsk linked to me */
- struct new_fsk *fs; /* flowset for !MULTIQUEUE */
+ struct new_fsk *fs; /* Flowset for !MULTIQUEUE */
- /* Hash table of all instances (through sched_mask) */
+ /* Hash table of all instances (through sch.sched_mask)
+ * or single instance if no mask. Always valid.
+ */
struct dn_ht *siht;
};
@@ -218,8 +218,8 @@ struct new_schk {
* This struct is created a runtime.
*/
struct new_sch_inst {
- struct dn_flow ni; /* oid, id and stats */
- SLIST_ENTRY(new_sch_inst) si_next; /* next item in the bucket */
+ struct dn_flow ni; /* oid, flowid and stats */
+ SLIST_ENTRY(new_sch_inst) si_next; /* hash chain for siht */
struct delay_line dline;
struct new_schk *sched; /* the template */
int kflags; /* DN_ACTIVE */
@@ -247,9 +247,8 @@ int dummynet_io(struct mbuf **, int , st
void dummynet_task(void *context, int pending);
void dn_reschedule(void);
-struct new_queue *ipdn_q_find(struct new_fsk *fs, struct new_sch_inst *si,
- struct ipfw_flow_id *id);
-
-struct new_sch_inst *ipdn_si_find(struct new_schk *s, struct ipfw_flow_id *id);
+struct new_queue *ipdn_q_find(struct new_fsk *, struct new_sch_inst *,
+ struct ipfw_flow_id *);
+struct new_sch_inst *ipdn_si_find(struct new_schk *, struct ipfw_flow_id *);
#endif /* _IP_DN_PRIVATE_H */
Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Thu Jan 21 17:26:11 2010 (r202757)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Thu Jan 21 17:34:01 2010 (r202758)
@@ -28,16 +28,16 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+/*
+ * Configuration and internal object management for dummynet.
+ */
+
#include "opt_inet6.h"
/* debug support */
-// #define D(fmt, args...) do {} while (0)
#define ND(fmt, args...) do {} while (0)
#define D(fmt, args...) printf("%s " fmt "\n", __FUNCTION__ , ## args)
-/*
- * Configuration and internal object management for dummynet.
- */
#include <sys/param.h>
#include <sys/systm.h>
@@ -64,15 +64,15 @@ __FBSDID("$FreeBSD$");
#include <netinet/ipfw/dn_sched.h>
/* which objects to copy */
-#define DN_C_PIPE 0x01
+#define DN_C_LINK 0x01
#define DN_C_SCH 0x02
-#define DN_C_SCH_INST 0x04
+#define DN_C_FLOW 0x04
#define DN_C_FS 0x08
#define DN_C_QUEUE 0x10
/* we use this argument in case of a schk_new */
struct schk_new_arg {
- struct dn_sched *fp;
+ struct dn_alg *fp;
struct new_sch *sch;
};
@@ -96,10 +96,10 @@ dn_reschedule(void)
/*----- end of callout hooks -----*/
/* Return a scheduler descriptor given the type or name. */
-static struct dn_sched *
+static struct dn_alg *
find_sched_type(int type, char *name)
{
- struct dn_sched *d;
+ struct dn_alg *d;
SLIST_FOREACH(d, &dn_cfg.schedlist, next) {
if (d->type == type || (name && !strcmp(d->name, name)))
@@ -113,10 +113,12 @@ bound_var(int *v, int dflt, int lo, int
{
if (*v < lo) {
*v = dflt;
- printf("force %s to %d\n", msg, *v);
+ if (msg)
+ printf("default %s to %d\n", msg, *v);
} else if (*v > hi) {
*v = hi;
- printf("clamp %s to %d\n", msg, *v);
+ if (msg)
+ printf("clamp %s to %d\n", msg, *v);
}
return *v;
}
@@ -772,15 +774,42 @@ struct copy_args {
};
static int
+copy_q_cb(void *obj, void *arg)
+{
+ struct new_queue *q = obj;
+ struct copy_args *a = arg;
+ struct dn_flow *ni = (struct dn_flow *)(*a->start);
+ if (copy_obj(a->start, a->end, &q->ni, "queue", -1))
+ return DNHT_SCAN_END;
+ ni->oid.type = DN_FLOW; /* override the DN_QUEUE */
+ ni->oid.id = si_hash((uintptr_t)&ni->fid, 0, NULL);
+ return 0;
+}
+
+static int
+copy_q(struct copy_args *a, struct new_fsk *fs, int flags)
+{
+ if (!fs->_qht)
+ return 0;
+ if (fs->fs.flags & DN_HAVE_MASK)
+ dn_ht_scan(fs->_qht, copy_q_cb, a);
+ else
+ copy_q_cb(fs->_qht, a);
+ return 0;
+}
+
+static int
copy_flowset(struct copy_args *a, struct new_fsk *fs, int flags)
{
struct new_fs *ufs = (struct new_fs *)(*a->start);
if (!fs)
return 0;
+ ND("flowset %d", fs->fs.fs_nr);
if (copy_obj(a->start, a->end, &fs->fs, "flowset", fs->fs.fs_nr))
return DNHT_SCAN_END;
ufs->oid.id = 0; /* XXX number of queues ? */
if (flags) { /* copy queues */
+ copy_q(a, fs, 0);
}
return 0;
}
@@ -795,6 +824,7 @@ copy_si_cb(void *obj, void *arg)
si->sched->sch.sched_nr))
return DNHT_SCAN_END;
ni->oid.type = DN_FLOW; /* override the DN_SCH_I */
+ ni->oid.id = si_hash((uintptr_t)si, DNHT_KEY_IS_OBJ, NULL);
return 0;
}
@@ -809,6 +839,33 @@ copy_si(struct copy_args *a, struct new_
}
static int
+copy_fsk_list(struct copy_args *a, struct new_schk *s, int flags)
+{
+ struct new_fsk *fs;
+ struct dn_id *o;
+ uint16_t *p;
+
+ int n = 0, space = sizeof(*o);
+ SLIST_FOREACH(fs, &s->fsk_list, sch_chain) {
+ if (fs->fs.fs_nr < DN_MAX_ID)
+ n++;;
+ }
+ space += 2*n;
+ D("sched %d has %d flowsets", s->sch.sched_nr, n);
+ if (a->end - *(a->start) < space)
+ return DNHT_SCAN_END;
+ o = (struct dn_id *)(*(a->start));
+ o->len = space;
+ *a->start += o->len;
+ o->type = DN_TEXT;
+ p = (uint16_t *)(o+1);
+ SLIST_FOREACH(fs, &s->fsk_list, sch_chain)
+ if (fs->fs.fs_nr < DN_MAX_ID)
+ *p++ = fs->fs.fs_nr;
+ return 0;
+}
+
+static int
copy_data_helper(void *_o, void *_arg)
{
struct copy_args *a = _arg;
@@ -820,7 +877,7 @@ copy_data_helper(void *_o, void *_arg)
return 0; /* not valid scheduler */
if (a->type == DN_LINK && s->sch.sched_nr <= DN_MAX_ID)
return 0; /* not valid pipe */
- if (a->flags & DN_C_PIPE) {
+ if (a->flags & DN_C_LINK) {
if (copy_obj(a->start, a->end, &s->link,
"link", s->sch.sched_nr))
return DNHT_SCAN_END;
@@ -831,8 +888,11 @@ copy_data_helper(void *_o, void *_arg)
if (copy_obj(a->start, a->end, &s->sch,
"sched", s->sch.sched_nr))
return DNHT_SCAN_END;
+ /* list all attached flowsets */
+ if (copy_fsk_list(a, s, 0))
+ return DNHT_SCAN_END;
}
- if (a->flags & DN_C_SCH_INST) {
+ if (a->flags & DN_C_FLOW) {
copy_si(a, s, 0);
}
}
@@ -840,11 +900,9 @@ copy_data_helper(void *_o, void *_arg)
struct new_fsk *fs = _o;
if (fs->fs.fs_nr >= DN_MAX_ID)
return 0;
- /* if extra is set, only copy unlinked ones */
- if (a->extra == 0 || fs->sched == NULL) {
- if (copy_flowset(a, fs, 0))
- return DNHT_SCAN_END;
- }
+ if (copy_flowset(a, fs, 0))
+ return DNHT_SCAN_END;
+ copy_q(a, fs, 0);
}
return 0;
}
@@ -869,11 +927,15 @@ fsk_attach(struct new_fsk *fs, struct ne
/* XXX compute fsk_mask */
fs->fsk_mask = fs->fs.flow_mask;
if (fs->sched->sch.flags & DN_HAVE_MASK)
- flow_id_or(&fs->fsk_mask, &fs->sched->sch.sched_mask);
+ flow_id_or(&fs->sched->sch.sched_mask, &fs->fsk_mask);
if (!fs->_qht)
return;
D("XXX TODO requeue from fs %d to sch %d",
fs->fs.fs_nr, s->sch.sched_nr);
+ /*
+ * The requeue is complex -- in general we need to
+ * reclassify every single packet.
+ */
}
/* update all flowsets which may refer to this scheduler */
@@ -999,22 +1061,17 @@ config_fs(struct new_fs *nfs, struct dn_
DN_BH_WLOCK();
do { /* exit with break when done */
struct new_schk *s;
-
- fs = dn_ht_find(dn_cfg.fshash, i, DNHT_INSERT, NULL);
- if (fs == NULL)
- break;
- if (nfs->sched_nr == 0) {
- if (fs->fs.sched_nr != 0) { /* reuse */
- nfs->sched_nr = fs->fs.sched_nr;
- } else {
- D("missing sched for flowset %d", i);
- fs = NULL;
- break;
- }
+ int flags = nfs->sched_nr ? DNHT_INSERT : 0;
+ fs = dn_ht_find(dn_cfg.fshash, i, flags, NULL);
+ if (fs == NULL) {
+ D("missing sched for flowset %d", i);
+ break;
}
+ if (nfs->sched_nr == 0) /* reuse */
+ nfs->sched_nr = fs->fs.sched_nr;
dn_cfg.id++;
if (bcmp(&fs->fs, nfs, sizeof(*nfs)) == 0) {
- D("flowset %d unchanged", i);
+ ND("flowset %d unchanged", i);
break; /* no change, nothing to do */
}
s = locate_scheduler(nfs->sched_nr);
@@ -1022,7 +1079,7 @@ config_fs(struct new_fs *nfs, struct dn_
* queues if we need to reattach. Then update the
* configuration, and possibly attach to the new sched.
*/
- D("fs %d changed args/sched %d %p to %d %p",
+ D("fs %d changed sched %d@%p to %d@%p",
fs->fs.fs_nr,
fs->fs.sched_nr, fs->sched, nfs->sched_nr, s);
if (fs->sched) {
@@ -1115,7 +1172,7 @@ again: /* run twice, for wfq and fifo */
/* already existing. */
D("sched %d type changed from %s to %s",
i, s->fp->name, a.fp->name);
- D(" type/sub %d/%d -> %d/%d",
+ ND(" type/sub %d/%d -> %d/%d",
s->sch.oid.type, s->sch.oid.subtype,
a.sch->oid.type, a.sch->oid.subtype);
if (s->link.link_nr == 0)
@@ -1129,7 +1186,7 @@ again: /* run twice, for wfq and fifo */
schk_delete_cb(s, (void *)DN_DELETE);
goto again;
} else {
- D("sched %d unchanged type %s", i, a.fp->name);
+ ND("sched %d unchanged type %s", i, a.fp->name);
}
/* complete initialization */
s->sch = *a.sch;
@@ -1263,6 +1320,7 @@ do_config(void *p, int l)
struct dn_id *next, *o;
int err = 0, err2 = 0;
struct dn_id *arg = NULL;
+ uint32_t *a;
o = p;
if (o->id != DN_API_VERSION) {
@@ -1285,17 +1343,22 @@ do_config(void *p, int l)
D("cmd %d not implemented", o->type);
break;
- case DN_CMD_CONFIGURE: /* simply a header */
- /* XXX add a version check */
+ case DN_CMD_CONFIG: /* simply a header */
break;
case DN_CMD_DELETE:
+ /* the argument is in the first uint32 after o */
+ a = (uint32_t *)(o+1);
+ if (o->len < sizeof(*o) + sizeof(*a)) {
+ err = EINVAL;
+ break;
+ }
switch (o->subtype) {
case DN_LINK:
/* delete base and derived schedulers */
DN_BH_WLOCK();
- err = delete_schk(o->id);
- err2 = delete_schk(o->id + DN_MAX_ID);
+ err = delete_schk(*a);
+ err2 = delete_schk(*a + DN_MAX_ID);
DN_BH_WUNLOCK();
if (!err)
err = err2;
@@ -1308,8 +1371,8 @@ do_config(void *p, int l)
break;
case DN_FS:
- err = (o->id<1 || o->id >= DN_MAX_ID) ?
- EINVAL : delete_fs(o->id, 0) ;
+ err = (*a <1 || *a >= DN_MAX_ID) ?
+ EINVAL : delete_fs(*a, 0) ;
break;
}
break;
@@ -1353,10 +1416,10 @@ compute_space(struct dn_id *cmd, int *to
default:
return -1;
case DN_LINK: /* pipe show */
- x = DN_C_PIPE | DN_C_FS | DN_SCH | DN_C_SCH_INST;
+ x = DN_C_LINK | DN_C_FS | DN_SCH | DN_C_FLOW;
break;
case DN_SCH: /* sched show */
- x = DN_C_SCH | DN_C_PIPE | DN_C_SCH_INST;
+ x = DN_C_SCH | DN_C_LINK | DN_C_FLOW;
break;
case DN_FS: /* queue show */
x = DN_C_FS | DN_C_QUEUE;
@@ -1367,12 +1430,12 @@ compute_space(struct dn_id *cmd, int *to
need += dn_cfg.schk_count * sizeof(struct new_sch);
if (x & DN_C_FS)
need += dn_cfg.fsk_count * sizeof(struct new_fs);
- if (x & DN_C_PIPE)
+ if (x & DN_C_LINK)
need += dn_cfg.schk_count * sizeof(struct dn_link);
/* XXX queue space might be variable */
if (x & DN_C_QUEUE)
need += dn_cfg.queue_count * sizeof(struct new_queue);
- if (x & DN_C_SCH_INST)
+ if (x & DN_C_FLOW)
need += dn_cfg.si_count * sizeof(struct dn_flow);
return need;
}
@@ -1590,9 +1653,9 @@ dummynet_modevent(module_t mod, int type
/* modevent helpers for the modules */
static int
-load_dn_sched(struct dn_sched *d)
+load_dn_sched(struct dn_alg *d)
{
- struct dn_sched *s;
+ struct dn_alg *s;
if (d == NULL)
return 1; /* error */
@@ -1620,9 +1683,9 @@ load_dn_sched(struct dn_sched *d)
}
static int
-unload_dn_sched(struct dn_sched *s)
+unload_dn_sched(struct dn_alg *s)
{
- struct dn_sched *tmp, *r;
+ struct dn_alg *tmp, *r;
int err = EINVAL;
D("called for %s", s->name);
@@ -1634,7 +1697,7 @@ unload_dn_sched(struct dn_sched *s)
D("ref_count = %d", r->ref_count);
err = (r->ref_count != 0) ? EBUSY : 0;
if (err == 0)
- SLIST_REMOVE(&dn_cfg.schedlist, r, dn_sched, next);
+ SLIST_REMOVE(&dn_cfg.schedlist, r, dn_alg, next);
break;
}
DN_BH_WUNLOCK();
@@ -1645,7 +1708,7 @@ unload_dn_sched(struct dn_sched *s)
int
dn_sched_modevent(module_t mod, int cmd, void *arg)
{
- struct dn_sched *sch = arg;
+ struct dn_alg *sch = arg;
if (cmd == MOD_LOAD)
return load_dn_sched(sch);
More information about the svn-src-user
mailing list