From owner-svn-src-user@FreeBSD.ORG Thu Jan 21 08:53:01 2010 Return-Path: Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id CFF3D106566B; Thu, 21 Jan 2010 08:53:01 +0000 (UTC) (envelope-from luigi@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id BDF1F8FC14; Thu, 21 Jan 2010 08:53:01 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o0L8r1mi075218; Thu, 21 Jan 2010 08:53:01 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0L8r12L075213; Thu, 21 Jan 2010 08:53:01 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <201001210853.o0L8r12L075213@svn.freebsd.org> From: Luigi Rizzo Date: Thu, 21 Jan 2010 08:53:01 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r202735 - in user/luigi/ipfw3-head: sbin/ipfw sys/netinet sys/netinet/ipfw X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 21 Jan 2010 08:53:01 -0000 Author: luigi Date: Thu Jan 21 08:53:01 2010 New Revision: 202735 URL: http://svn.freebsd.org/changeset/base/202735 Log: - in new_sch, rename 'type' to 'name'; - introduce macros D() and ND() to take care of debugging printfs - staticize function dn_delete_queue - adjust comments and formatting Modified: user/luigi/ipfw3-head/sbin/ipfw/dummynet.c 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/ip_dn_io.c 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 03:49:18 2010 (r202734) +++ user/luigi/ipfw3-head/sbin/ipfw/dummynet.c Thu Jan 21 08:53:01 2010 (r202735) @@ -299,7 +299,8 @@ list_pipes(struct dn_id *oid, struct dn_ case DN_SCH: { struct new_sch *s = (struct new_sch *)oid; flush_buf(buf); - printf(" type %s flags 0x%x %d buckets\n", s->type, s->flags, s->buckets); + printf(" type %s flags 0x%x %d buckets\n", + s->name, s->flags, s->buckets); if (s->flags & DN_HAVE_MASK) print_mask(&s->sched_mask); } @@ -1043,7 +1044,7 @@ end_mask: l = strlen(av[0]); if (l == 0 || l > 15) errx(1, "type %s too long\n", av[0]); - strcpy(sch->type, av[0]); + strcpy(sch->name, av[0]); sch->oid.subtype = 0; /* use string */ ac--; av++; break; Modified: user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h Thu Jan 21 03:49:18 2010 (r202734) +++ user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h Thu Jan 21 08:53:01 2010 (r202735) @@ -181,7 +181,7 @@ struct new_sch { int buckets; /* number of buckets for the instances */ int flags; /* have_mask, ... */ - char type[16]; /* null terminated */ + char name[16]; /* null terminated */ /* mask to select the appropriate scheduler instance */ struct ipfw_flow_id sched_mask; /* M */ }; Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h Thu Jan 21 03:49:18 2010 (r202734) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h Thu Jan 21 08:53:01 2010 (r202735) @@ -120,12 +120,7 @@ struct dn_sched { * Additionally, dummynet exports some functions and macros * to be used by schedulers: */ -/* delete a queue, which we assume nobody references. - * if do_free is set, propagate to the flowset and destroy it - * if the refcount becomes 0 - */ void dn_free_pkts(struct mbuf *mnext); -void dn_delete_queue(struct new_queue *, int do_free); int dn_enqueue(struct new_queue *q, struct mbuf* m, int drop); /* Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c Thu Jan 21 03:49:18 2010 (r202734) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c Thu Jan 21 08:53:01 2010 (r202735) @@ -208,6 +208,20 @@ mq_append(struct mq *q, struct mbuf *m) } /* + * Dispose a list of packet. Use a functions so if we need to do + * more work, this is a central point to do it. + */ +void dn_free_pkts(struct mbuf *mnext) +{ + struct mbuf *m; + + while ((m = mnext) != NULL) { + mnext = m->m_nextpkt; + FREE_PKT(m); + } +} + +/* * Enqueue a packet in q, subject to space and queue management policy * (whose parameters are in q->fs). * Update stats for the queue and the scheduler. Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Thu Jan 21 03:49:18 2010 (r202734) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Thu Jan 21 08:53:01 2010 (r202735) @@ -30,8 +30,13 @@ __FBSDID("$FreeBSD$"); #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 support for dummynet. + * Configuration and internal object management for dummynet. */ #include @@ -103,20 +108,6 @@ find_sched_type(int type, char *name) return NULL; /* not found */ } -/* - * Dispose a list of packet. Use a functions so if we need to do - * more work, this is a central point to do it. - */ -void dn_free_pkts(struct mbuf *mnext) -{ - struct mbuf *m; - - while ((m = mnext) != NULL) { - mnext = m->m_nextpkt; - FREE_PKT(m); - } -} - static int bound_var(int *v, int dflt, int lo, int hi, const char *msg) { @@ -251,7 +242,7 @@ q_new(uintptr_t key, int flags, void *ar q = malloc(size, M_DUMMYNET, M_NOWAIT | M_ZERO); if (q == NULL) { - printf("%s: no memory for new queue\n", __FUNCTION__); + D("no memory for new queue"); return NULL; } @@ -272,12 +263,12 @@ q_new(uintptr_t key, int flags, void *ar * If (flags & DN_DELETE), also free the packets. * The version for callbacks is called q_delete_cb(). */ -void +static void dn_delete_queue(struct new_queue *q, int flags) { struct new_fsk *fs = q->fs; - // printf("%s fs %p si %p\n", __FUNCTION__, fs, q->_si); + // D("fs %p si %p\n", fs, q->_si); /* notify the parent scheduler that the queue is going away */ if (fs && fs->sched->fp->free_queue) fs->sched->fp->free_queue(q); @@ -307,10 +298,8 @@ q_delete_cb(void *q, void *arg) static void qht_delete(struct new_fsk *fs, int flags) { -#if 0 - printf("+++ %s fs %d start flags %d qht %p\n", - __FUNCTION__, fs->fs.fs_nr, flags, fs->_qht); -#endif + ND("fs %d start flags %d qht %p", + fs->fs.fs_nr, flags, fs->_qht); if (!fs->_qht) return; if (fs->fs.flags & DN_HAVE_MASK) { @@ -329,7 +318,6 @@ qht_delete(struct new_fsk *fs, int flags /* * Find and possibly create the right queue for a MULTIQUEUE scheduler. * We never call it for !MULTIQUEUE (when the queue is in the sch_inst). - * in a better way. */ struct new_queue * ipdn_q_find(struct new_fsk *fs, struct new_sch_inst *si, @@ -404,7 +392,8 @@ si_new(uintptr_t key, int flags, void *a goto error; /* Set length only for the part passed up to userland. */ set_oid(&si->ni.oid, DN_SCH_I, sizeof(struct new_inst)); - set_oid(&(si->dline.oid), DN_DELAY_LINE, sizeof(struct delay_line)); + set_oid(&(si->dline.oid), DN_DELAY_LINE, + sizeof(struct delay_line)); /* mark si and dline as outside the event queue */ si->ni.oid.id = si->dline.oid.id = -1; @@ -412,7 +401,7 @@ si_new(uintptr_t key, int flags, void *a si->dline.si = si; if (s->fp->new_sched && s->fp->new_sched(si)) { - printf("%s: new_sched error\n", __FUNCTION__); + D("new_sched error"); goto error; } if (s->sch.flags & DN_HAVE_MASK) @@ -458,6 +447,7 @@ si_destroy(void *_si, void *arg) /* * Find the scheduler instance for this packet. If we need to apply * a mask, do on a local copy of the flow_id to preserve the original. + * Assume siht is always initialized. */ struct new_sch_inst * ipdn_si_find(struct new_schk *s, struct ipfw_flow_id *id) @@ -469,8 +459,6 @@ ipdn_si_find(struct new_schk *s, struct return dn_ht_find(s->siht, (uintptr_t)&id_t, DNHT_INSERT, s); } else { - if (s->siht == NULL) - s->siht = si_new((uintptr_t)id, 0, s); return (struct new_sch_inst *)s->siht; } } @@ -491,7 +479,7 @@ schk_reset_credit(struct new_schk *s) { if (s->sch.flags & DN_HAVE_MASK) dn_ht_scan(s->siht, si_reset_credit, NULL); - else if (s->siht) + else si_reset_credit(s->siht, NULL); } /*---- end of sch_inst hashtable ---------------------*/ @@ -545,13 +533,11 @@ fsk_detach(struct new_fsk *fs, int flags { if (flags & DN_DELETE_FS) flags |= DN_DELETE; -#if 0 - printf("%s fs %d from sched %d flags %s %s %s\n", - __FUNCTION__, fs->fs.fs_nr, fs->fs.sched_nr, + ND("fs %d from sched %d flags %s %s %s", + fs->fs.fs_nr, fs->fs.sched_nr, (flags & DN_DELETE_FS) ? "DEL_FS":"", (flags & DN_DELETE) ? "DEL":"", (flags & DN_DETACH) ? "DET":""); -#endif if (flags & DN_DETACH) { /* detach from the list */ struct new_fsk_head *h; h = fs->sched ? &fs->sched->fsk_list : &dn_cfg.fsu; @@ -583,13 +569,13 @@ fsk_detach_list(struct new_fsk_head *h, struct new_fsk *fs; int n = 0; /* only for stats */ - // printf("+++ %s head %p flags %x\n", __FUNCTION__, h, flags); + ND("head %p flags %x", h, flags); while ((fs = SLIST_FIRST(h))) { SLIST_REMOVE_HEAD(h, sch_chain); n++; fsk_detach(fs, flags); } - // printf("+++ %s done flowsets\n", __FUNCTION__, n); + ND("done %d flowsets", n); } /* @@ -606,7 +592,7 @@ delete_fs(int i, int locked) if (!locked) DN_BH_WLOCK(); fs = dn_ht_find(dn_cfg.fshash, i, DNHT_REMOVE, NULL); - // printf("%s fs %d found %p\n", __FUNCTION__, i, fs); + ND("fs %d found %p", i, fs); if (fs) { fsk_detach(fs, DN_DETACH | DN_DELETE_FS); err = 0; @@ -661,13 +647,15 @@ schk_new(uintptr_t key, int flags, void s->sch = *a->sch; // copy initial values s->pipe.pipe_nr = s->sch.sched_nr; SLIST_INIT(&s->fsk_list); - /* initialize the hash table if needed. Otherwise, - * ht points to the single instance we own - */ - if (s->sch.flags & DN_HAVE_MASK) { - s->siht = dn_ht_init(NULL, s->sch.buckets, + /* initialize the hash table or create the single instance */ + s->siht = (s->sch.flags & DN_HAVE_MASK) ? + dn_ht_init(NULL, s->sch.buckets, offsetof(struct new_sch_inst, si_next), - si_hash, si_match, si_new); + si_hash, si_match, si_new) : + si_new(0, 0, s); + if (s->siht == NULL) { + free(s, M_DUMMYNET); + return NULL; } dn_cfg.schk_count++; return s; @@ -686,18 +674,17 @@ schk_delete_cb(void *obj, void *arg) { struct new_schk *s = obj; #if 0 - int i = s->sch.sched_nr; int a = (int)arg; - printf(">>> %s sched %d arg %s%s\n", - __FUNCTION__, i, + ND("sched %d arg %s%s", + s->sch.sched_nr, a&DN_DELETE ? "DEL ":"", a&DN_DELETE_FS ? "DEL_FS":""); #endif fsk_detach_list(&s->fsk_list, arg ? DN_DELETE : 0); /* no more flowset pointing to us now */ - if (s->sch.flags & DN_HAVE_MASK) { + if (s->sch.flags & DN_HAVE_MASK) dn_ht_scan(s->siht, si_destroy, NULL); - } else if (s->siht) + else si_destroy(s->siht, NULL); s->siht = NULL; if (s->fp->destroy) @@ -719,16 +706,14 @@ delete_schk(int i) struct new_schk *s; s = dn_ht_find(dn_cfg.schedhash, i, DNHT_REMOVE, NULL); - // printf("%s sched %d %p\n", __FUNCTION__, i, s); + ND("%d %p", i, s); if (!s) return EINVAL; - /* detach flowsets, delete traffic */ - delete_fs(i + DN_MAX_ID, 1); /* first remove internal pipe */ + delete_fs(i + DN_MAX_ID, 1); /* first delete internal fs */ + /* then detach flowsets, delete traffic */ schk_delete_cb(s, (void*)(uintptr_t)DN_DELETE); return 0; } - - /*--- end of schk hashtable support ---*/ static int @@ -738,11 +723,11 @@ copy_obj(char **start, char *end, void * int have = end - *start; if (have < o->len || o->len == 0 || o->type == 0) { - printf("XXX %s ERROR type %d %s %d have %d need %d\n", - __FUNCTION__, o->type, msg, i, have, o->len); + D("ERROR type %d %s %d have %d need %d", + o->type, msg, i, have, o->len); return 1; } - // printf("%s type %d %s %d len %d\n", __FUNCTION__, o->type, msg, i, o->len); + ND("type %d %s %d len %d", o->type, msg, i, o->len); bcopy(_o, *start, o->len); *start += o->len; return 0; @@ -777,7 +762,8 @@ copy_si_cb(void *obj, void *arg) struct new_sch_inst *si = obj; struct copy_args *a = arg; struct new_inst *ni = (struct new_inst *)(*a->start); - if (copy_obj(a->start, a->end, &si->ni, "inst", si->sched->sch.sched_nr)) + if (copy_obj(a->start, a->end, &si->ni, "inst", + si->sched->sch.sched_nr)) return DNHT_SCAN_END; ni->oid.type = DN_NI; return 0; @@ -786,12 +772,10 @@ copy_si_cb(void *obj, void *arg) static int copy_si(struct copy_args *a, struct new_schk *s, int flags) { - if (s->sch.flags & DN_HAVE_MASK) { + if (s->sch.flags & DN_HAVE_MASK) dn_ht_scan(s->siht, copy_si_cb, a); - } else { - if (s->siht) - copy_si_cb(s->siht, a); - } + else + copy_si_cb(s->siht, a); return 0; } @@ -808,13 +792,15 @@ copy_data_helper(void *_o, void *_arg) if (a->type == DN_PIPE && s->sch.sched_nr <= DN_MAX_ID) return 0; /* not valid pipe */ if (a->flags & DN_C_PIPE) { - if (copy_obj(a->start, a->end, &s->pipe, "pipe", s->sch.sched_nr)) + if (copy_obj(a->start, a->end, &s->pipe, + "pipe", s->sch.sched_nr)) return DNHT_SCAN_END; if (copy_flowset(a, s->fs, 0)) return DNHT_SCAN_END; } if (a->flags & DN_C_SCH) { - if (copy_obj(a->start, a->end, &s->sch, "sched", s->sch.sched_nr)) + if (copy_obj(a->start, a->end, &s->sch, + "sched", s->sch.sched_nr)) return DNHT_SCAN_END; } if (a->flags & DN_C_SCH_INST) { @@ -844,10 +830,8 @@ locate_scheduler(int i) static void fsk_attach(struct new_fsk *fs, struct new_schk *s) { -#if 0 - printf("remove fs %d from fsunlinked, link to sched %d\n", + ND("remove fs %d from fsunlinked, link to sched %d", fs->fs.fs_nr, s->sch.sched_nr); -#endif SLIST_REMOVE(&dn_cfg.fsu, fs, new_fsk, sch_chain); fs->sched = s; SLIST_INSERT_HEAD(&s->fsk_list, fs, sch_chain); @@ -855,8 +839,8 @@ fsk_attach(struct new_fsk *fs, struct ne s->fp->new_fsk(fs); if (!fs->_qht) return; - printf("XXX %s TODO requeue from fs %d to sch %d\n", - __FUNCTION__, fs->fs.fs_nr, s->sch.sched_nr); + D("XXX TODO requeue from fs %d to sch %d", + fs->fs.fs_nr, s->sch.sched_nr); } /* update all flowsets which may refer to this scheduler */ @@ -867,7 +851,7 @@ update_fs(struct new_schk *s) SLIST_FOREACH_SAFE(fs, &dn_cfg.fsu, sch_chain, tmp) { if (s->sch.sched_nr != fs->fs.sched_nr) { - printf("fs %d for sch %d not %d still unlinked\n", + D("fs %d for sch %d not %d still unlinked", fs->fs.fs_nr, fs->fs.sched_nr, s->sch.sched_nr); continue; @@ -899,15 +883,15 @@ update_fs(struct new_schk *s) */ /* - * configure a pipe + * configure a pipe (and its FIFO instance) */ static int config_pipe(struct new_pipe *p, struct dn_id *arg) { int i; - if (p->oid.len < sizeof(*p)) { - printf("%s: short pipe\n", __FUNCTION__); + if (p->oid.len != sizeof(*p)) { + D("invalid pipe len %d", p->oid.len); return EINVAL; } i = p->pipe_nr; @@ -930,7 +914,7 @@ config_pipe(struct new_pipe *p, struct d struct new_schk *s = locate_scheduler(i); if (s == NULL) { DN_BH_WUNLOCK(); - printf("%s sched %d not found\n", __FUNCTION__, i); + D("sched %d not found", i); return EINVAL; } /* copy all parameters */ @@ -955,14 +939,14 @@ config_fs(struct new_fs *nfs, struct dn_ int i; struct new_fsk *fs; - if (nfs->oid.len < sizeof(*nfs)) { - printf("%s: short flowset\n", __FUNCTION__); + if (nfs->oid.len != sizeof(*nfs)) { + D("invalid flowset len %d", nfs->oid.len); return NULL; } i = nfs->fs_nr; if (i <= 0 || i >= 3*DN_MAX_ID) return NULL; - // printf("%s flowset %d\n", __FUNCTION__, i); + ND("flowset %d", i); /* XXX other sanity checks */ if (nfs->flags & DN_QSIZE_BYTES) { if (nfs->qsize > dn_cfg.pipe_byte_limit) @@ -992,14 +976,14 @@ config_fs(struct new_fs *nfs, struct dn_ if (fs->fs.sched_nr != 0) { /* reuse */ nfs->sched_nr = fs->fs.sched_nr; } else { - printf("missing sched for flowset %d\n", i); + D("missing sched for flowset %d", i); fs = NULL; break; } } dn_cfg.id++; if (bcmp(&fs->fs, nfs, sizeof(*nfs)) == 0) { - printf("%s flowset %d unchanged\n", __FUNCTION__, i); + D("flowset %d unchanged", i); break; /* no change, nothing to do */ } s = locate_scheduler(nfs->sched_nr); @@ -1007,8 +991,8 @@ 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. */ - printf("%s fs %d changed args/sched %d %p to %d %p\n", - __FUNCTION__, fs->fs.fs_nr, + D("fs %d changed args/sched %d %p to %d %p", + fs->fs.fs_nr, fs->fs.sched_nr, fs->sched, nfs->sched_nr, s); if (fs->sched) { int flags = s ? DN_DETACH : (DN_DETACH | DN_DELETE); @@ -1025,7 +1009,7 @@ config_fs(struct new_fs *nfs, struct dn_ } /* - * configure a scheduler and its FIFO variant. + * config/reconfig a scheduler and its FIFO variant. * For !MULTIQUEUE schedulers, also set up the flowset. * * On reconfigurations (detected because s->fp is set), @@ -1042,7 +1026,7 @@ config_sched(struct new_sch *_nsch, stru a.sch = _nsch; if (a.sch->oid.len != sizeof(*a.sch)) { - printf("%s: bad sched len\n", __FUNCTION__); + D("bad sched len %d", a.sch->oid.len); return EINVAL; } i = a.sch->sched_nr; @@ -1056,53 +1040,55 @@ config_sched(struct new_sch *_nsch, stru bzero(&p, sizeof(p)); DN_BH_WLOCK(); again: /* run twice, for wfq and fifo */ - a.fp = find_sched_type(a.sch->oid.subtype, a.sch->type); + /* + * lookup the type. If not supplied, use the previous one + * or default to WF2Q+. Otherwise, return an error. + */ + dn_cfg.id++; + a.fp = find_sched_type(a.sch->oid.subtype, a.sch->name); if (a.fp != NULL) { + /* found. Lookup or create entry */ s = dn_ht_find(dn_cfg.schedhash, i, DNHT_INSERT, &a); - } else if (a.sch->oid.subtype != 0 || a.sch->type[0]) { - DN_BH_WUNLOCK(); - printf("invalid scheduler type %d %s\n", - a.sch->oid.subtype, a.sch->type); - return EINVAL; - } else { - /* type not supplied. If it exist already, use - * the existing one. Otherwise default to WF2Q+ - */ + } else if (a.sch->oid.subtype == 0 && !a.sch->name[0]) { + /* No type. search existing s* or retry with WF2Q+ */ s = dn_ht_find(dn_cfg.schedhash, i, 0, &a); - if (s == NULL) { + if (s != NULL) { + a.fp = s->fp; + } else { a.sch->oid.subtype = DN_SCHED_WF2QP; goto again; } - a.fp = s->fp; + } else { + DN_BH_WUNLOCK(); + D("invalid scheduler type %d %s", + a.sch->oid.subtype, a.sch->name); + return EINVAL; } - /* normalize type and subtype */ + /* normalize name and subtype */ a.sch->oid.subtype = a.fp->type; - bzero(a.sch->type, sizeof(a.sch->type)); - strlcpy(a.sch->type, a.fp->name, sizeof(a.sch->type)); + bzero(a.sch->name, sizeof(a.sch->name)); + strlcpy(a.sch->name, a.fp->name, sizeof(a.sch->name)); if (s == NULL) { DN_BH_WUNLOCK(); - printf("cannot allocate scheduler\n"); + D("cannot allocate scheduler %d", i); return ENOMEM; } /* restore existing pipe if any */ if (p.pipe_nr) s->pipe = p; p.pipe_nr = 0; - dn_cfg.id++; if (s->fp == NULL) { - printf("%s sched %d new type %s\n", __FUNCTION__, i, - a.fp->name); + D("sched %d new type %s", i, a.fp->name); } else if (s->fp != a.fp || bcmp(a.sch, &s->sch, sizeof(*a.sch)) ) { /* already existing. */ - printf("sched %d type changed from %s to %s\n", + D("sched %d type changed from %s to %s", i, s->fp->name, a.fp->name); - printf(" type/sub %d/%d -> %d/%d\n", + D(" type/sub %d/%d -> %d/%d", s->sch.oid.type, s->sch.oid.subtype, a.sch->oid.type, a.sch->oid.subtype); if (s->pipe.pipe_nr == 0) - printf("XXX WARNING pipe 0 for sched %d\n", - s->sch.sched_nr); + D("XXX WARNING pipe 0 for sched %d", i); p = s->pipe; /* preserve pipe */ /* remove from the hash */ dn_ht_find(dn_cfg.schedhash, i, DNHT_REMOVE, NULL); @@ -1112,37 +1098,42 @@ again: /* run twice, for wfq and fifo */ schk_delete_cb(s, (void *)DN_DELETE); goto again; } else { - printf("%s sched %d unchanged type %s\n", __FUNCTION__, i, - a.fp->name); + D("sched %d unchanged type %s", i, a.fp->name); } /* complete initialization */ s->sch = *a.sch; s->fp = a.fp; s->cfg = arg; // XXX schk_reset_credit(s); - /* create the internal flowset if needed */ + /* create the internal flowset if needed, + * trying to reuse existing ones if available + */ if (!(s->fp->flags & DN_MULTIQUEUE) && !s->fs) { - struct new_fs fs; - - bzero(&fs, sizeof(fs)); - set_oid(&fs.oid, DN_FS, sizeof(fs)); - fs.fs_nr = i + DN_MAX_ID; - fs.sched_nr = i; - s->fs = config_fs(&fs, NULL, 1 /* locked */); - printf("+++ sched %d fs %p len %d ty %d\n", - s->sch.sched_nr, - s->fs, s->fs->fs.oid.len, s->fs->fs.oid.type); + s->fs = dn_ht_find(dn_cfg.fshash, i, 0, NULL); + if (!s->fs) { + struct new_fs fs; + bzero(&fs, sizeof(fs)); + set_oid(&fs.oid, DN_FS, sizeof(fs)); + fs.fs_nr = i + DN_MAX_ID; + fs.sched_nr = i; + s->fs = config_fs(&fs, NULL, 1 /* locked */); + } + if (!s->fs) { + schk_delete_cb(s, (void *)DN_DELETE); + D("error creating internal fs for %d", i); + DN_BH_WUNLOCK(); + return ENOMEM; + } } /* call init function after the flowset is created */ if (s->fp->config) s->fp->config(s); update_fs(s); - if (i < DN_MAX_ID) { /* update the FIFO instance */ + if (i < DN_MAX_ID) { /* now configure the FIFO instance */ i += DN_MAX_ID; a.sch->sched_nr = i; - /* now configure a FIFO instance */ a.sch->oid.subtype = DN_SCHED_FIFO; - bzero(a.sch->type, sizeof(a.sch->type)); + bzero(a.sch->name, sizeof(a.sch->name)); goto again; } DN_BH_WUNLOCK(); @@ -1159,7 +1150,7 @@ config_profile(struct new_profile *pf, s int i; if (pf->oid.len < sizeof(*pf)) { - printf("%s: short profile\n", __FUNCTION__); + D("short profile len %d", pf->oid.len); return EINVAL; } i = pf->pipe_nr; @@ -1171,7 +1162,7 @@ config_profile(struct new_profile *pf, s if (s == NULL) { DN_BH_WUNLOCK(); - printf("%s: no scheduler %d\n", __FUNCTION__, i); + D("no scheduler %d", i); return EINVAL; } dn_cfg.id++; @@ -1195,7 +1186,7 @@ config_profile(struct new_profile *pf, s M_DUMMYNET, M_NOWAIT | M_ZERO); if (s->profile == NULL) { DN_BH_WUNLOCK(); - printf("%s: no memory\n", __FUNCTION__); + D("no memory for profile %d", i); return ENOMEM; } /* preserve larger length */ @@ -1220,7 +1211,7 @@ dummynet_flush(void) dn_ht_scan(dn_cfg.schedhash, schk_delete_cb, (void *)(uintptr_t)DN_DELETE_FS); /* delete all remaining (unlinked) flowsets */ - printf("%s still %d unlinked fs\n", __FUNCTION__, dn_cfg.fsk_count); + D("still %d unlinked fs", dn_cfg.fsk_count); dn_ht_free(dn_cfg.fshash, DNHT_REMOVE); fsk_detach_list(&dn_cfg.fsu, DN_DELETE_FS); /* Reinitialize system heap... */ @@ -1241,10 +1232,13 @@ do_config(void *p, int l) int err = 0, err2 = 0; struct dn_id *arg = NULL; + /* XXX TODO require the first block to be a 'CONFIGURE' + * or at least carry with a version number + */ for (o = p; l >= sizeof(*o); o = next) { struct dn_id *prev = arg; if (o->len < sizeof(*o) || l < o->len) { - printf("bad len o->len %d len %d\n", o->len, l); + D("bad len o->len %d len %d", o->len, l); err = EINVAL; break; } @@ -1253,10 +1247,11 @@ do_config(void *p, int l) err = 0; switch (o->type) { default: - printf("cmd %d not implemented\n", o->type); + D("cmd %d not implemented", o->type); break; case DN_CMD_CONFIGURE: /* simply a header */ + /* XXX add a version check */ break; case DN_CMD_DELETE: @@ -1272,13 +1267,13 @@ do_config(void *p, int l) break; default: - printf("invalid delete type %d\n", + D("invalid delete type %d", o->subtype); err = EINVAL; break; case DN_FS: - err = (o->id < 1 || o->id >= DN_MAX_ID) ? + err = (o->id<1 || o->id >= DN_MAX_ID) ? EINVAL : delete_fs(o->id, 0) ; break; } @@ -1350,10 +1345,11 @@ compute_space(struct dn_id *cmd, int *to static int dummynet_get(struct sockopt *sopt) { - int have, i, need, error, to_copy = 0; - char *start = NULL, *buf, *end; + int have, i, need, error; + char *start = NULL, *buf; size_t sopt_valsize; struct dn_id cmd; + struct copy_args a; /* save and restore original sopt_valsize around copyin */ sopt_valsize = sopt->sopt_valsize; @@ -1367,7 +1363,7 @@ dummynet_get(struct sockopt *sopt) */ for (have = 0, i = 0; i < 10; i++) { DN_BH_WLOCK(); - need = compute_space(&cmd, &to_copy); + need = compute_space(&cmd, &a.flags); if (need < 0) { DN_BH_WUNLOCK(); return EINVAL; @@ -1389,30 +1385,24 @@ dummynet_get(struct sockopt *sopt) } if (start == NULL) return sooptcopyout(sopt, &cmd, sizeof(cmd)); - printf("have %d:%d sched %d, %d:%d pipes %d, %d:%d flows %d, " - "%d:%d si %d, %d:%d queues %d\n", + ND("have %d:%d sched %d, %d:%d pipes %d, %d:%d flows %d, " + "%d:%d si %d, %d:%d queues %d", dn_cfg.schk_count, sizeof(struct new_sch), DN_SCH, dn_cfg.schk_count, sizeof(struct new_pipe), DN_PIPE, dn_cfg.fsk_count, sizeof(struct new_fs), DN_FS, dn_cfg.si_count, sizeof(struct new_inst), DN_SCH_I, dn_cfg.queue_count, sizeof(struct new_queue), DN_QUEUE); - end = start + have; sopt->sopt_valsize = sopt_valsize; bcopy(&cmd, start, sizeof(cmd)); buf = start + sizeof(cmd); + a.start = &buf; + a.end = start + have; + a.type = cmd.subtype; /* start copying other objects */ - { - struct copy_args a; - - a.start = &buf; - a.end = end; - a.flags = to_copy; - a.type = cmd.subtype; - if (a.type == DN_FS) - dn_ht_scan(dn_cfg.fshash, copy_data_helper, &a); - else - dn_ht_scan(dn_cfg.schedhash, copy_data_helper, &a); - } + if (a.type == DN_FS) + dn_ht_scan(dn_cfg.fshash, copy_data_helper, &a); + else + dn_ht_scan(dn_cfg.schedhash, copy_data_helper, &a); DN_BH_WUNLOCK(); error = sooptcopyout(sopt, start, buf - start); free(start, M_DUMMYNET); @@ -1421,7 +1411,6 @@ dummynet_get(struct sockopt *sopt) /* * Handler for the various dummynet socket options - * (get, flush, config, del) */ static int ip_dn_ctl(struct sockopt *sopt) @@ -1442,7 +1431,7 @@ ip_dn_ctl(struct sockopt *sopt) switch (sopt->sopt_name) { default : - printf("dummynet: unknown option %d", sopt->sopt_name); + D("dummynet: unknown option %d", sopt->sopt_name); error = EINVAL; break; @@ -1450,7 +1439,7 @@ ip_dn_ctl(struct sockopt *sopt) case IP_DUMMYNET_CONFIGURE: case IP_DUMMYNET_DEL: /* remove a pipe or queue */ case IP_DUMMYNET_GET: - printf("dummynet: compat option %d", sopt->sopt_name); + D("dummynet: compat option %d", sopt->sopt_name); error = EINVAL; break; @@ -1461,7 +1450,7 @@ ip_dn_ctl(struct sockopt *sopt) } l = sopt->sopt_valsize; if (l < 0 || l > 12000) { - printf("argument len %d invalid\n", l); + D("argument len %d invalid", l); break; } p = malloc(l, M_TEMP, M_WAITOK); // XXX can it fail ? @@ -1545,28 +1534,23 @@ static int dummynet_modevent(module_t mod, int type, void *data) { - switch (type) { - case MOD_LOAD: + if (type == MOD_LOAD) { if (ip_dn_io_ptr) { printf("DUMMYNET already loaded\n"); return EEXIST ; } ip_dn_init(); - break; - - case MOD_UNLOAD: + return 0; + } else if (type == MOD_UNLOAD) { #if !defined(KLD_MODULE) printf("dummynet statically compiled, cannot unload\n"); return EINVAL ; #else ip_dn_destroy(); + return 0; #endif - break ; - default: + } else return EOPNOTSUPP; - break ; - } - return 0 ; } /* modevent helpers for the modules */ @@ -1581,7 +1565,7 @@ load_dn_sched(struct dn_sched *d) /* Check that mandatory funcs exists */ if (d->enqueue == NULL || d->dequeue == NULL) { - printf("missing enqueue or dequeue for %s\n", d->name); + D("missing enqueue or dequeue for %s", d->name); return 1; } @@ -1589,14 +1573,14 @@ load_dn_sched(struct dn_sched *d) DN_BH_WLOCK(); SLIST_FOREACH(s, &dn_cfg.schedlist, next) { if (strcmp(s->name, d->name) == 0) { - printf("%s %s already loaded\n", __FUNCTION__, d->name); + D("%s already loaded", d->name); break; /* scheduler already exists */ } } if (s == NULL) SLIST_INSERT_HEAD(&dn_cfg.schedlist, d, next); DN_BH_WUNLOCK(); - printf("dn_sched %s %sloaded\n", d->name, s ? "not ":""); + D("dn_sched %s %sloaded", d->name, s ? "not ":""); return s ? 1 : 0; } @@ -1606,20 +1590,20 @@ unload_dn_sched(struct dn_sched *s) struct dn_sched *tmp, *r; int err = EINVAL; - printf("%s %s called\n", __FUNCTION__, s->name); + D("called for %s", s->name); DN_BH_WLOCK(); SLIST_FOREACH_SAFE(r, &dn_cfg.schedlist, next, tmp) { if (strcmp(s->name, r->name) != 0) continue; - printf("ref_count = %d\n", r->ref_count); + 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); break; } DN_BH_WUNLOCK(); - printf("dn_sched %s %sunloaded\n", s->name, err ? "not ":""); + D("dn_sched %s %sunloaded", s->name, err ? "not ":""); return err; }