svn commit: r202083 - in user/luigi/ipfw3-head: sbin/ipfw
sys/netinet/ipfw
Luigi Rizzo
luigi at FreeBSD.org
Mon Jan 11 15:12:14 UTC 2010
Author: luigi
Date: Mon Jan 11 15:12:13 2010
New Revision: 202083
URL: http://svn.freebsd.org/changeset/base/202083
Log:
data start flowing...
Modified:
user/luigi/ipfw3-head/sbin/ipfw/dummynet.c
user/luigi/ipfw3-head/sbin/ipfw/ipfw2.c
user/luigi/ipfw3-head/sbin/ipfw/ipfw2.h
user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_fifo.c
user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.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 Mon Jan 11 12:35:16 2010 (r202082)
+++ user/luigi/ipfw3-head/sbin/ipfw/dummynet.c Mon Jan 11 15:12:13 2010 (r202083)
@@ -288,65 +288,51 @@ print_extra_delay_parms(struct dn_pipe *
p->name, loss, p->samples_no);
}
#endif
-void
-ipfw_list_pipes(void *data, uint nbytes, int ac, char *av[])
-{
-#if 0
- int rulenum;
- void *next = data;
- struct dn_pipe *p = (struct dn_pipe *) data;
- struct dn_flow_set *fs;
- struct dn_flow_queue *q;
- int l;
- if (ac > 0)
- rulenum = strtoul(*av++, NULL, 10);
+/*
+ * filt is an array of sorted ranges whithin where we list
+ */
+static void
+list_pipes(struct dn_id *oid, struct dn_id *end, int *filt)
+{
+ for (; oid != end; oid = O_NEXT(oid, oid->len)) {
+ struct new_pipe *p = (struct new_pipe *)oid;
+ //struct dn_flow_set *fs;
+ //struct dn_flow_queue *q;
+
+ double b = p->bandwidth;
+ char buf[30];
+ char prefix[80];
+ char burst[5 + 7];
+
+ if (oid->type != DN_PIPE)
+ continue;
+ /*
+ * Print rate (or clocking interface)
+ */
+ if (b == 0)
+ sprintf(buf, "unlimited");
+ else if (b >= 1000000)
+ sprintf(buf, "%7.3f Mbit/s", b/1000000);
+ else if (b >= 1000)
+ sprintf(buf, "%7.3f Kbit/s", b/1000);
else
- rulenum = 0;
- for (; nbytes >= sizeof *p; p = (struct dn_pipe *)next) {
- double b = p->bandwidth;
- char buf[30];
- char prefix[80];
- char burst[5 + 7];
-
- if (SLIST_NEXT(p, next) != (struct dn_pipe *)DN_IS_PIPE)
- break; /* done with pipes, now queues */
+ sprintf(buf, "%7.3f bit/s ", b);
- /*
- * compute length, as pipe have variable size
- */
- l = sizeof(*p) + p->fs.rq_elements * sizeof(*q);
- next = (char *)p + l;
- nbytes -= l;
-
- if ((rulenum != 0 && rulenum != p->pipe_nr) || co.do_pipe == 2)
- continue;
-
- /*
- * Print rate (or clocking interface)
- */
- if (b == 0)
- sprintf(buf, "unlimited");
- else if (b >= 1000000)
- sprintf(buf, "%7.3f Mbit/s", b/1000000);
- else if (b >= 1000)
- sprintf(buf, "%7.3f Kbit/s", b/1000);
- else
- sprintf(buf, "%7.3f bit/s ", b);
-
- sprintf(prefix, "%05d: %s %4d ms ",
+ sprintf(prefix, "%05d: %s %4d ms ",
p->pipe_nr, buf, p->delay);
- print_flowset_parms(&(p->fs), prefix);
+ // print_flowset_parms(&(p->fs), prefix);
+ printf("%s", prefix);
- if (humanize_number(burst, sizeof(burst), p->burst,
+ if (humanize_number(burst, sizeof(burst), p->burst,
"Byte", HN_AUTOSCALE, 0) < 0 || co.verbose)
- printf("\t burst: %ju Byte\n", p->burst);
- else
- printf("\t burst: %s\n", burst);
-
- print_extra_delay_parms(p);
+ printf("\t burst: %ju Byte\n", p->burst);
+ else
+ printf("\t burst: %s\n", burst);
+ // print_extra_delay_parms(p);
+#if 0
q = (struct dn_flow_queue *)(p+1);
list_queues(&(p->fs), q);
}
@@ -371,6 +357,7 @@ ipfw_list_pipes(void *data, uint nbytes,
list_queues(fs, q);
}
#endif
+ }
}
/*
@@ -549,7 +536,8 @@ read_bandwidth(char *arg, int *bandwidth
errx(EX_DATAERR, "bandwidth too large");
*bandwidth = bw;
- if_name[0] = '\0';
+ if (if_name)
+ if_name[0] = '\0';
}
}
@@ -807,6 +795,10 @@ ipfw_config_pipe(int ac, char **av)
mask = &sch->sched_mask;
break;
}
+ if (p)
+ p->bandwidth = -1;
+ if (p2)
+ p2->bandwidth = -1;
while (ac > 0) {
double d;
@@ -1198,3 +1190,36 @@ end_mask:
if (i)
err(1, "setsockopt(%s)", "IP_DUMMYNET_CONFIGURE");
}
+
+void
+dummynet_list(int ac, char *av[], int show_counters)
+{
+ struct dn_id oid , *x;
+ int ret, l = sizeof(oid);
+
+ oid.type = DN_CMD_GET;
+ oid.len = l;
+ oid.id = 0;
+ switch (co.do_pipe) {
+ case 1:
+ oid.subtype = DN_SCH; /* list pipe */
+ break;
+ case 2:
+ oid.subtype = DN_FS; /* list queue */
+ break;
+ }
+ ret = do_cmd(IP_DUMMYNET_GET, &oid, (uintptr_t)&l);
+ printf("%s returns %d need %d\n", __FUNCTION__, ret, oid.id);
+ if (ret != 0 || oid.id <= sizeof(oid))
+ return;
+ l = oid.id;
+ x = malloc(l);
+ if (x == NULL) {
+ err(1, "no memory in %s", __FUNCTION__);
+ }
+ *x = oid;
+ ret = do_cmd(IP_DUMMYNET_GET, x, (uintptr_t)&l);
+ printf("%s returns %d need %d\n", __FUNCTION__, ret, oid.id);
+ list_pipes(x, O_NEXT(x, l), NULL);
+ free(x);
+}
Modified: user/luigi/ipfw3-head/sbin/ipfw/ipfw2.c
==============================================================================
--- user/luigi/ipfw3-head/sbin/ipfw/ipfw2.c Mon Jan 11 12:35:16 2010 (r202082)
+++ user/luigi/ipfw3-head/sbin/ipfw/ipfw2.c Mon Jan 11 15:12:13 2010 (r202083)
@@ -1762,6 +1762,10 @@ ipfw_list(int ac, char *av[], int show_c
fprintf(stderr, "Testing only, list disabled\n");
return;
}
+ if (co.do_pipe) {
+ dummynet_list(ac, av, show_counters);
+ return;
+ }
ac--;
av++;
@@ -1778,11 +1782,6 @@ ipfw_list(int ac, char *av[], int show_c
co.do_pipe ? "DUMMYNET" : "FW");
}
- if (co.do_pipe) {
- ipfw_list_pipes(data, nbytes, ac, av);
- goto done;
- }
-
/*
* Count static rules. They have variable size so we
* need to scan the list to count them.
Modified: user/luigi/ipfw3-head/sbin/ipfw/ipfw2.h
==============================================================================
--- user/luigi/ipfw3-head/sbin/ipfw/ipfw2.h Mon Jan 11 12:35:16 2010 (r202082)
+++ user/luigi/ipfw3-head/sbin/ipfw/ipfw2.h Mon Jan 11 15:12:13 2010 (r202083)
@@ -265,7 +265,7 @@ u_int32_t altq_name_to_qid(const char *n
void print_altq_cmd(struct _ipfw_insn_altq *altqptr);
/* dummynet.c */
-void ipfw_list_pipes(void *data, uint nbytes, int ac, char *av[]);
+void dummynet_list(int ac, char *av[], int show_counters);
int ipfw_delete_pipe(int pipe_or_queue, int n);
/* ipv6.c */
Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_fifo.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_fifo.c Mon Jan 11 12:35:16 2010 (r202082)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_fifo.c Mon Jan 11 15:12:13 2010 (r202083)
@@ -91,12 +91,14 @@ fifo_enqueue(struct new_sch_inst *_si, s
if (si->q == NULL) {
si->q = dn_create_queue(_si, f, id);
if (si->q == NULL) {
+ printf("%s dn_create_queue failed\n", __FUNCTION__);
FREE_PKT(m);
return 1;
}
}
/* Now the si->q is valid, so insert the packet in this queue */
if (dn_queue_packet(si->q, m)) {
+ printf("%s dn_queue_packet failed\n", __FUNCTION__);
/* packet was dropped */
return 1;
}
Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c Mon Jan 11 12:35:16 2010 (r202082)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c Mon Jan 11 15:12:13 2010 (r202083)
@@ -249,7 +249,6 @@ dn_queue_packet(struct new_queue *q, str
/* Update statistics, then check reasons to drop pkt. */
q->tot_bytes += m->m_pkthdr.len;
q->tot_pkts++;
-
if (f->plr && random() < f->plr)
goto drop;
if (f->flags & DN_QSIZE_BYTES) {
@@ -442,6 +441,7 @@ create_si(struct new_schk *s, int slot)
int ret;
int l = sizeof(*si) + s->fp->sch_inst_len;
+printf("%s start slot %d\n", __FUNCTION__, slot);
si = malloc(l, M_DUMMYNET, M_NOWAIT | M_ZERO);
if (si == NULL)
@@ -467,6 +467,7 @@ create_si(struct new_schk *s, int slot)
/* Put entry in front of the hash list of the parent. */
SLIST_INSERT_HEAD(&s->ht[slot], si, next);
si->hash_slot = slot;
+ dn_cfg.si_count++;
return si;
error:
@@ -483,6 +484,7 @@ find_sch_inst(struct new_schk *s, struct
int i;
struct ipfw_flow_id id_t;
+printf("%s start id %p\n", __FUNCTION__, id);
if ( 0 == (s->sch.flags & DN_HAVE_MASK) ) {
i = 0;
si = SLIST_FIRST(&s->ht[0]);
@@ -760,8 +762,7 @@ dummynet_io(struct mbuf **m0, int dir, s
dn_key now; /* save a copy of curr_time */
int fs_id = (fwa->rule.info & IPFW_INFO_MASK) +
- (fwa->rule.info & IPFW_IS_PIPE) ? DN_PIPEOFFSET : 0;
-
+ ((fwa->rule.info & IPFW_IS_PIPE) ? DN_PIPEOFFSET : 0);
DUMMYNET_LOCK();
io_pkt++;
/* XXX locate_flowset could be optimised with a direct ref. */
@@ -793,6 +794,7 @@ dummynet_io(struct mbuf **m0, int dir, s
if (fs->kflags & DN_HAVE_MASK)
do_mask(&fs->fs.flow_mask, &(fwa->f_id));
if (sch->fp->enqueue(sch_inst, fs, m, &(fwa->f_id))) {
+ printf("%s dropped by enqueue\n", __FUNCTION__);
/* packet was dropped by enqueue() */
*m0 = NULL;
goto dropit;
Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h Mon Jan 11 12:35:16 2010 (r202082)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h Mon Jan 11 15:12:13 2010 (r202083)
@@ -71,6 +71,12 @@ struct dn_parms {
struct timeval prev_t;
struct dn_heap system_heap;
+ /* how many objects we have -- useful for reporting space */
+ int schk_count;
+ int si_count;
+ int fsk_count;
+ int queue_count;
+
int hmask; /* mask for hashsize, must be 2^n-1 */
/* fhash and schedhash are hmask+1 entries */
struct new_fsk_head fsunlinked;
@@ -156,6 +162,7 @@ struct new_schk {
*/
int ht_slots; /* number of slots */
struct new_sch_inst_head *ht;
+ struct new_sch_inst_head h0; /* used if malloc fails */
int kflags;
Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Mon Jan 11 12:35:16 2010 (r202082)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Mon Jan 11 15:12:13 2010 (r202083)
@@ -61,6 +61,13 @@ __FBSDID("$FreeBSD$");
static int ip_dn_ctl(struct sockopt *sopt);
+ /* which objects to copy */
+#define DN_C_PIPE 0x01
+#define DN_C_SCH 0x02
+#define DN_C_SCH_INST 0x04
+#define DN_C_FS 0x08
+#define DN_C_QUEUE 0x10
+
static int config_pipe(struct new_pipe *p, struct dn_id *arg);
static int config_profile(struct new_profile *p, struct dn_id *arg);
@@ -139,6 +146,7 @@ destroy_si(struct new_sch_inst *si)
dn_delete_queue(q);
}
free(si, M_DUMMYNET);
+ dn_cfg.si_count--;
return 0;
}
@@ -161,9 +169,23 @@ destroy_fs(struct new_fsk *fs)
fs->kflags |= DN_DELETE;
if (fs->refcnt != 0)
return;
+ dn_cfg.fsk_count--;
SLIST_REMOVE(&s->fsk_list, fs, new_fsk, sch_chain);
}
+static struct new_fsk *
+create_fs(void)
+{
+ struct new_fsk *fs;
+
+ fs = malloc(sizeof(*fs), M_DUMMYNET, M_NOWAIT | M_ZERO);
+ if (fs) {
+ SLIST_INSERT_HEAD(&dn_cfg.fsunlinked, fs, next);
+ dn_cfg.fsk_count++;
+ }
+ return fs;
+}
+
/*
* helper for schedulers. Creates a queue
*/
@@ -180,7 +202,7 @@ dn_create_queue(struct new_sch_inst *si,
return NULL;
}
- set_oid(&q->oid, DN_QUEUE, size, 0);
+ set_oid(&q->oid, DN_QUEUE, 0, size);
q->fs = fs;
q->si = si;
fs->refcnt++;
@@ -188,6 +210,7 @@ dn_create_queue(struct new_sch_inst *si,
if (si->sched->fp->new_queue)
si->sched->fp->new_queue(q);
SLIST_INSERT_HEAD(&si->ql_list, q, ql_next);
+ dn_cfg.queue_count++;
return q;
}
@@ -206,13 +229,14 @@ dn_delete_queue(struct new_queue *q)
fs->sched->fp->free_queue(q);
free(q, M_DUMMYNET);
fs->refcnt--;
+ dn_cfg.queue_count--;
if (fs->refcnt == 0 && fs->kflags & DN_DELETE)
destroy_fs(fs);
return 0;
}
static struct new_schk *
-destroy_sched(struct new_schk *s, int del)
+destroy_schk(struct new_schk *s, int del)
{
int i;
struct new_sch_inst *si;
@@ -228,9 +252,87 @@ destroy_sched(struct new_schk *s, int de
if (fp->destroy)
fp->destroy(s, 1);
free(s, M_DUMMYNET);
+ dn_cfg.schk_count--;
return NULL;
}
+static struct new_schk *
+create_schk(struct dn_sched *fp)
+{
+ struct new_schk *s;
+ int l = sizeof(*s) + fp->schk_len;
+
+ s = malloc(l, M_DUMMYNET, M_NOWAIT | M_ZERO);
+ if (s) {
+ set_oid(&s->pipe.oid, DN_PIPE, 0, sizeof(s->pipe));
+ s->fp = fp;
+ SLIST_INIT(&s->fsk_list);
+ /* use a default hash */
+ s->ht_slots = 1;
+ s->ht = &s->h0;
+ dn_cfg.schk_count++;
+ }
+ return s;
+}
+
+static int
+copy_obj(char **start, char *end, void *_o)
+{
+ struct dn_id *o = _o;
+
+ if (end - *start < o->len)
+ return 1;
+ bcopy(_o, *start, o->len);
+ *start += o->len;
+ return 0;
+}
+
+/* copy data, return 1 when full */
+static int
+copy_data(char **start, char *end, int flags)
+{
+ int i;
+
+ if (flags & (DN_C_PIPE | DN_C_SCH | DN_C_SCH_INST)) {
+ for (i = 0; i < dn_cfg.hmask+1; i++) {
+ struct new_schk *s;
+ SLIST_FOREACH(s, &dn_cfg.schedhash[i], next) {
+ if (flags & DN_C_PIPE) {
+ printf("copy pipe %d len %d\n",
+ s->pipe.pipe_nr, s->pipe.oid.len);
+ if (copy_obj(start, end, &s->pipe))
+ return 1;
+ }
+ if (flags & DN_C_SCH) {
+ printf("copy sched %d\n", s->sch.sched_nr);
+ if (copy_obj(start, end, &s->sch))
+ return 1;
+ }
+ if (flags & DN_C_SCH_INST) {
+ printf("copy shc_inst %d\n", s->sch.sched_nr);
+ /* scan the hashtable */
+ }
+ }
+ }
+ }
+ if (flags & (DN_C_FS)) {
+ struct new_fsk *fs;
+ for (i = 0; i < dn_cfg.hmask+1; i++) {
+ SLIST_FOREACH(fs, &dn_cfg.fshash[i], next) {
+ printf("copy flowset %d\n", fs->fs.fs_nr);
+ if (copy_obj(start, end, &fs->fs))
+ return 1;
+ }
+ }
+ SLIST_FOREACH(fs, &dn_cfg.fsunlinked, next) {
+ printf("copy flowset %d\n", fs->fs.fs_nr);
+ if (copy_obj(start, end, &fs->fs))
+ return 1;
+ }
+ }
+ return 0;
+}
+
/*
* Delete all objects:
* - mark as shutting down;
@@ -256,7 +358,7 @@ dummynet_flush(void)
while ( (s = SLIST_FIRST(sh)) != NULL) {
SLIST_REMOVE_HEAD(sh, next);
- destroy_sched(s, 1 /* delete */);
+ destroy_schk(s, 1 /* delete */);
}
}
@@ -444,7 +546,7 @@ config_sched(struct new_sch *nsch, struc
{
struct new_schk *s;
struct dn_sched *fp;
- int i, l, is_new;
+ int i, is_new;
struct new_fsk_head fsk_list;
SLIST_INIT(&fsk_list);
@@ -466,23 +568,25 @@ config_sched(struct new_sch *nsch, struc
DUMMYNET_LOCK();
s = locate_scheduler(i);
printf("%s type %s old %p\n", __FUNCTION__, fp->name, s);
- if (s && s->fp != fp) /* type changed, hard delete */
- s = destroy_sched(s, 1);
+ if (s && s->fp != fp) { /* type changed, hard delete */
+ /* preserve old pipe ? */
+ s = destroy_schk(s, 1);
+ }
if (s) {
is_new = 0;
} else {
- l = sizeof(*s) + fp->schk_len;
- s = malloc(l, M_DUMMYNET, M_NOWAIT | M_ZERO);
+ s = create_schk(fp);
if (s == NULL)
return ENOMEM;
- s->fp = fp;
- SLIST_INIT(&s->fsk_list);
+ s->pipe.pipe_nr = i;
+ SLIST_INSERT_HEAD(&dn_cfg.schedhash[HASH(i)], s, next);
is_new = 1;
}
s->sch = *nsch;
s->cfg = arg;
- if (is_new) {
- SLIST_INSERT_HEAD(&dn_cfg.schedhash[HASH(i)], s, next);
+ /* initialize the hash table */
+ if (s->sch.flags & DN_HAVE_MASK) {
+ } else {
}
/* call init function */
if (s->fp->config)
@@ -514,18 +618,26 @@ config_fs(struct new_fs *nfs, struct dn_
if (i <= 0 || i > DN_MAXID)
return EINVAL;
/* XXX other sanity checks */
+ if (nfs->flags & DN_QSIZE_IS_BYTES) {
+ if (nfs->qsize > dn_cfg.pipe_byte_limit)
+ nfs->qsize = dn_cfg.pipe_byte_limit;
+ } else {
+ if (nfs->qsize == 0)
+ nfs->qsize = 50;
+ if (nfs->qsize > dn_cfg.pipe_slot_limit)
+ nfs->qsize = dn_cfg.pipe_slot_limit;
+ }
+
DUMMYNET_LOCK();
fs = ipdn_locate_flowset(i);
printf("%s %d old %p\n", __FUNCTION__, i, fs);
if (fs == NULL) {
- fs = malloc(sizeof(*fs),
- M_DUMMYNET, M_NOWAIT | M_ZERO);
+ fs = create_fs();
if (fs == NULL) {
DUMMYNET_UNLOCK();
return ENOMEM;
}
- SLIST_INSERT_HEAD(&dn_cfg.fsunlinked, fs, next);
}
fs->fs = *nfs; /* update config */
/* copy values, check if scheduler exists and mark active */
@@ -621,46 +733,69 @@ config_profile(struct new_profile *pf, s
return 0;
}
-static size_t
-dn_calc_size(void)
-{
- return 100;
-}
-
static int
dummynet_get(struct sockopt *sopt)
{
- int error=0;
- char *buf, *bp ; /* bp is the "copy-pointer" */
- size_t size ;
- int i;
-
- /* XXX lock held too long */
- DUMMYNET_LOCK();
- /*
- * XXX: Ugly, but we need to allocate memory with M_WAITOK flag and we
- * cannot use this flag while holding a mutex.
- */
- for (i = 0; i < 10; i++) {
- size = dn_calc_size();
- DUMMYNET_UNLOCK();
- buf = malloc(size, M_TEMP, M_WAITOK);
+ int have = 0, i, need, error;
+ char *start = NULL, *buf, *end;
+ size_t sopt_valsize;
+ struct dn_id cmd;
+ int to_copy = 0;
+
+ /* save original values */
+ sopt_valsize = sopt->sopt_valsize;
+ printf("%s have %d bytes\n", __FUNCTION__, sopt_valsize);
+
+ error = sooptcopyin(sopt, &cmd, sizeof(cmd), sizeof(cmd));
+ sopt->sopt_valsize = sopt_valsize;
+ if (error)
+ return error;
+ printf("%s cmd %d len %d\n", __FUNCTION__, cmd.type, cmd.len);
+ for (have = 0, i = 0; i < 10; i++) {
DUMMYNET_LOCK();
- if (size >= dn_calc_size())
- break;
- free(buf, M_TEMP);
- buf = NULL;
- }
- if (buf == NULL) {
+ switch (cmd.subtype) {
+ default:
+ return EINVAL;
+ case DN_SCH: /* pipe show */
+ to_copy = DN_C_SCH | DN_C_PIPE;
+ need = dn_cfg.schk_count *
+ (sizeof(struct new_sch) + sizeof(struct new_pipe));
+ break;
+ case DN_FS: /* queue show */
+ to_copy = DN_C_FS;
+ need = dn_cfg.fsk_count *
+ (sizeof(struct new_fs));
+ break;
+ }
+ need += sizeof(cmd);
+ cmd.id = need;
+ printf("pass %d have %d need %d len %d\n",
+ i, have, need, sopt_valsize);
+ if (have >= need)
+ break;
DUMMYNET_UNLOCK();
- return ENOBUFS ;
+ if (start)
+ free(start, M_DUMMYNET);
+ buf = NULL;
+ if (need > sopt_valsize)
+ break;
+ have = need;
+ start = malloc(have, M_DUMMYNET, M_WAITOK | M_ZERO);
+ if (start == NULL)
+ return ENOMEM;
}
- bp = buf;
+ if (start == NULL)
+ return sooptcopyout(sopt, &cmd, sizeof(cmd));
+ end = start + have;
+ sopt->sopt_valsize = sopt_valsize;
+ bcopy(&cmd, start, sizeof(cmd));
+ buf = start + sizeof(cmd);
+ /* start copying other objects */
+ copy_data(&buf, end, to_copy);
DUMMYNET_UNLOCK();
-
- error = sooptcopyout(sopt, buf, size);
- free(buf, M_TEMP);
- return error ;
+ error = sooptcopyout(sopt, start, buf - start);
+ free(start, M_DUMMYNET);
+ return error;
}
/*
@@ -699,8 +834,7 @@ ip_dn_ctl(struct sockopt *sopt)
case IP_DUMMYNET_CONFIGURE :
case IP_DUMMYNET_DEL : /* remove a pipe or queue */
- l = (sopt->sopt_dir == SOPT_SET) ? sopt->sopt_valsize :
- *(int *)(sopt->sopt_valsize);
+ l = sopt->sopt_valsize;
if (l < 0 || l > 12000) {
printf("argument too large, %d\n", l);
break;
More information about the svn-src-user
mailing list