From owner-svn-src-user@FreeBSD.ORG Tue Jan 19 14:45:58 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 79A071065693; Tue, 19 Jan 2010 14:45:58 +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 685648FC08; Tue, 19 Jan 2010 14:45:58 +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 o0JEjw9N019792; Tue, 19 Jan 2010 14:45:58 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0JEjwtq019790; Tue, 19 Jan 2010 14:45:58 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <201001191445.o0JEjwtq019790@svn.freebsd.org> From: Luigi Rizzo Date: Tue, 19 Jan 2010 14:45:58 +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: r202627 - user/luigi/ipfw3-head/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: Tue, 19 Jan 2010 14:45:58 -0000 Author: luigi Date: Tue Jan 19 14:45:58 2010 New Revision: 202627 URL: http://svn.freebsd.org/changeset/base/202627 Log: shuffle functions to pack them by class Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Tue Jan 19 13:36:12 2010 (r202626) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Tue Jan 19 14:45:58 2010 (r202627) @@ -256,6 +256,60 @@ q_new(uintptr_t key, int flags, void *ar return q; } +/* + * Delete a queue. The version for callbacks is called q_delete_cb(). + * Call the 'free_queue' routine on the scheduler. + * If do_free is set, also free the packets. + */ +struct new_queue * +dn_delete_queue(struct new_queue *q, int do_free) +{ + struct new_fsk *fs = q->fs; + + printf(" +++ %s fs %p si %p\n", __FUNCTION__, 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); + if (!do_free) + return q; + if (q->mq.head) + dn_free_pkts(q->mq.head); + free(q, M_DUMMYNET); + dn_cfg.queue_count--; + fs->refcnt--; + return NULL; +} + +static int +q_delete_cb(void *q, void *arg) +{ + (void)dn_delete_queue(q, (int)(uintptr_t)arg); + return 0; +} + +/* + * calls dn_delete_queue/q_delete_cb on all queues, + * which notifies the parent scheduler and possibly drains packets. + * flags & DN_DELETE: drains queues and destroy qht; + */ +static void +qht_delete(struct new_fsk *fs, int flags) +{ + printf("+++ %s fs %d start\n", __FUNCTION__, fs->fs.fs_nr); + if (!fs->_qht) + return; + if (fs->kflags & DN_QHT_IS_Q) { + fs->_qht = (struct dn_ht *)dn_delete_queue((struct new_queue *)(fs->_qht), flags); + } else { + dn_ht_scan(fs->_qht, q_delete_cb, (void *)flags); + if (flags & DN_DELETE) { + dn_ht_free(fs->_qht, 0); + fs->_qht = NULL; + } + } +} +/*--- end of queue hash table ---*/ + /*--- support functions for the sch_inst hashtable ---- * * These are hashed by flow-id @@ -349,7 +403,6 @@ si_destroy(void *_si, void *arg) dn_cfg.si_count--; return 0; } -/*---- end of sch_inst hashtable ---------------------*/ /* * Find the scheduler instance for this packet. If we need to apply @@ -371,6 +424,7 @@ ipdn_si_find(struct new_schk *s, struct } return si; } +/*---- end of sch_inst hashtable ---------------------*/ /*------------------------------------------------------- * flowset hash (fshash) support. Entries are hashed by fs_nr. @@ -410,72 +464,16 @@ fsk_new(uintptr_t key, int flags, void * } return fs; } -/*----- end of flowset hashtable support -------------*/ /* - * Delete a queue. The version for callbacks is called q_delete_cb(). - * Call the 'free_queue' routine on the scheduler. - * If do_free is set, also free the packets. - */ -struct new_queue * -dn_delete_queue(struct new_queue *q, int do_free) -{ - struct new_fsk *fs = q->fs; - - printf(" +++ %s fs %p si %p\n", __FUNCTION__, 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); - if (!do_free) - return q; - if (q->mq.head) - dn_free_pkts(q->mq.head); - free(q, M_DUMMYNET); - dn_cfg.queue_count--; - fs->refcnt--; - return NULL; -} - -static int -q_delete_cb(void *q, void *arg) -{ - (void)dn_delete_queue(q, (int)(uintptr_t)arg); - return 0; -} - -/* - * calls dn_delete_queue/q_delete_cb on all queues, - * which notifies the parent scheduler and possibly drains packets. - * flags & DN_DELETE: drains queues and destroy qht; - */ -static void -qht_delete(struct new_fsk *fs, int flags) -{ - printf("+++ %s fs %d start\n", __FUNCTION__, fs->fs.fs_nr); - if (!fs->_qht) - return; - if (fs->kflags & DN_QHT_IS_Q) { - fs->_qht = (struct dn_ht *)dn_delete_queue((struct new_queue *)(fs->_qht), flags); - } else { - dn_ht_scan(fs->_qht, q_delete_cb, (void *)flags); - if (flags & DN_DELETE) { - dn_ht_free(fs->_qht, 0); - fs->_qht = NULL; - } - } -} - -/* - * Detach or destroy all flowsets in a list. Used when deleting a scheduler, - * or for all those in fsunlinked. - * int_fs points to an internal flowset which must be handled differently. + * Detach or destroy all flowsets in a list. * flags specifies what to do: * DN_DELETE flush all queues * DN_DELETE_FS DN_DELETE + destroy flowset * DN_DELETE_FS implies DN_DELETE */ static void -fsk_detach_list(struct new_fsk_head *h, struct new_fsk *int_fs, int flags) +fsk_detach_list(struct new_fsk_head *h, int flags) { struct new_fsk *fs; @@ -485,12 +483,6 @@ fsk_detach_list(struct new_fsk_head *h, while ((fs = SLIST_FIRST(h))) { SLIST_REMOVE_HEAD(h, sch_chain); printf(" +++ %s child fs %d\n", __FUNCTION__, fs->fs.fs_nr); - if (fs == int_fs) { - /* free the internal flowset. */ - free(fs, M_DUMMYNET); - dn_cfg.fsk_count--; - continue; - } /* detach queues from the scheduler and possibly drain them */ qht_delete(fs, flags); fs->sched = NULL; @@ -502,7 +494,61 @@ fsk_detach_list(struct new_fsk_head *h, } } } +/*----- end of flowset hashtable support -------------*/ +/*------------------------------------------------------------ + * Scheduler hash. When searching by index we pass sched_nr, + * otherwise we pass struct new_sch * which is the first field in + * struct new_schk so we can cast between the two. We use this trick + * because in the create phase (but it should be fixed). + */ +static int +schk_hash(uintptr_t key, int flags, void *_arg) +{ + int i = !(flags & DNHT_KEY_IS_OBJ) ? key : + ((struct new_schk *)key)->sch.sched_nr; + return ( (i>>8)^(i>>4)^i ); +} + +static int +schk_match(void *obj, uintptr_t key, int flags, void *_arg) +{ + struct new_schk *s = ((struct new_schk *)obj); + int i = !(flags & DNHT_KEY_IS_OBJ) ? key : + ((struct new_schk *)key)->sch.sched_nr; + return !(s->kflags & DN_DELETE) && (s->sch.sched_nr == i); +} + +/* + * Create the entry and intialize with the sched hash if needed. + * Leave s->fp unset so we can tell whether a dn_ht_find() returns + * a new object or a previously existing one. + */ +static void * +schk_new(uintptr_t key, int flags, void *arg) +{ + struct schk_new_arg *a = arg; + struct new_schk *s; + int l = sizeof(*s) +a->fp->schk_datalen; + + s = malloc(l, M_DUMMYNET, M_NOWAIT | M_ZERO); + if (s == NULL) + return NULL; + set_oid(&s->pipe.oid, DN_PIPE, sizeof(s->pipe)); + 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, + offsetof(struct new_sch_inst, si_next), + si_hash, si_match, si_new); + } + dn_cfg.schk_count++; + return s; +} /* callback to flush credit for the pipe */ static int @@ -524,6 +570,41 @@ schk_reset_credit(struct new_schk *s) reset_credit(s->siht, NULL); } +/* + * Callback for sched delete. Notify all attached flowsets to + * detach from the scheduler, destroy the internal flowset, and + * all instances. + * arg is 0 (only detach flowsets and destroy instances) + * DN_DELETE (detach & delete queues, delete schk) + * or DN_DELETE_FS (delete queues and flowsets, delete schk) + */ +static int +schk_delete_cb(void *obj, void *arg) +{ + struct new_schk *s = obj; + + printf("+++ %s sched %d arg %d\n", __FUNCTION__, s->sch.sched_nr, (int)arg); + if (0 && arg && s->fs) { + /* remove the internal flowset from the hashtab */ + dn_ht_find(dn_cfg.fshash, s->fs->fs.fs_nr, DNHT_REMOVE, NULL); + } + fsk_detach_list(&s->fsk_list, arg ? DN_DELETE : 0); + /* we should not have any flowset pointing to us now */ + if (s->sch.flags & DN_HAVE_MASK) { + dn_ht_scan(s->siht, si_destroy, NULL); + } else if (s->siht) + si_destroy(s->siht, NULL); + s->siht = NULL; + if (arg) { + bzero(s, sizeof(*s)); + free(obj, M_DUMMYNET); + dn_cfg.schk_count--; + return HEAP_SCAN_DEL; + } else + return 0; +} +/*--- end of schk hashtable support ---*/ + static int copy_obj(char **start, char *end, void *_o) { @@ -581,37 +662,6 @@ copy_data_helper(void *_o, void *_arg) return 0; } -/* - * Callback for sched delete. Notify all attached flowsets to - * detach from the scheduler, destroy the internal flowset, and - * all instances. - * arg is 0 (only detach flowsets and destroy instances) - * DN_DELETE (detach & delete queues, delete schk) - * or DN_DELETE_FS (delete queues and flowsets, delete schk) - */ -static int -schk_delete_cb(void *obj, void *arg) -{ - struct new_schk *s = obj; - - printf("+++ %s sched %d arg %d\n", __FUNCTION__, s->sch.sched_nr, (int)arg); - if (arg && s->fs) { - /* remove the internal flowset from the hashtab */ - dn_ht_find(dn_cfg.fshash, s->fs->fs.fs_nr, DNHT_REMOVE, NULL); - } - fsk_detach_list(&s->fsk_list, s->fs, arg ? DN_DELETE : 0); - /* we should not have any flowset pointing to us now */ - if (s->sch.flags & DN_HAVE_MASK) { - dn_ht_scan(s->siht, si_destroy, NULL); - } else if (s->siht) - si_destroy(s->siht, NULL); - if (arg) { - free(obj, M_DUMMYNET); - dn_cfg.schk_count--; - return HEAP_SCAN_DEL; - } else - return 0; -} /* @@ -656,9 +706,12 @@ static void update_fs(struct new_schk *s) { struct new_fsk *fs, *tmp; + printf("%s start\n", __FUNCTION__); SLIST_FOREACH_SAFE(fs, &dn_cfg.fsu, sch_chain, tmp) { - if (s->sch.sched_nr != fs->fs.fs_nr) { - printf("fs %d still unlinked\n", fs->fs.fs_nr); + if (s->sch.sched_nr != fs->fs.sched_nr) { + printf("fs %d for sch %d not %d still unlinked\n", + fs->fs.fs_nr, fs->fs.sched_nr, + s->sch.sched_nr); continue; } printf("remove fs %d from fsunlinked, link to sched %d\n", @@ -671,6 +724,7 @@ update_fs(struct new_schk *s) printf("+++ %s requeue from fs %d to sch %d\n", __FUNCTION__, fs->fs.fs_nr, s->sch.sched_nr); } + printf("%s end\n", __FUNCTION__); } /* @@ -758,6 +812,7 @@ config_fs(struct new_fs *nfs, struct dn_ i = nfs->fs_nr; if (i <= 0 || i >= 3*DN_MAX_ID) return NULL; + printf("%s flowset %d\n", __FUNCTION__, i); /* XXX other sanity checks */ if (nfs->flags & DN_QSIZE_IS_BYTES) { if (nfs->qsize > dn_cfg.pipe_byte_limit) @@ -853,6 +908,7 @@ config_sched(struct new_sch *_nsch, stru struct schk_new_arg a; /* argument for schk_new */ int i, notify_fs = 0; + printf("%s start\n", __FUNCTION__); a.sch = _nsch; if (a.sch->oid.len != sizeof(*a.sch)) { printf("%s: bad sched len\n", __FUNCTION__); @@ -880,7 +936,7 @@ again: /* run twice, for wfq and fifo */ } dn_cfg.id++; if (s->fp != NULL) { - /* in all other cases, remove from the heaps, + /* Already existing -- remove from the heaps, * and detach flowsets from * the old one almost as in sched_delete, but * preserve traffic. @@ -889,6 +945,7 @@ again: /* run twice, for wfq and fifo */ printf("sched %d type changed from %s to %s\n", i, s->fp->name, a.fp->name); schk_delete_cb(s, NULL); + printf("schk_delete_cb done\n"); notify_fs = 1; /* now we have nothing pointing to us */ } @@ -921,6 +978,7 @@ again: /* run twice, for wfq and fifo */ goto again; } DUMMYNET_UNLOCK(); + printf("%s end\n", __FUNCTION__); return 0; } @@ -1028,6 +1086,7 @@ delete_schk(int i) return EINVAL; /* detach flowsets, delete traffic */ schk_delete_cb(s, (void*)(uintptr_t)DN_DELETE); + delete_fs(i + DN_MAX_ID); /* remove internal pipe */ return 0; } @@ -1043,7 +1102,7 @@ dummynet_flush(void) dn_ht_scan(dn_cfg.schedhash, schk_delete_cb, (void *)(uintptr_t)DN_DELETE_FS); /* all remaining (unlinked) flowsets */ - fsk_detach_list(&dn_cfg.fsu, NULL, DN_DELETE_FS); + fsk_detach_list(&dn_cfg.fsu, DN_DELETE_FS); /* Reinitialize system heap... */ heap_init(&dn_cfg.evheap, 16, offsetof(struct dn_id, id)); @@ -1247,21 +1306,21 @@ ip_dn_ctl(struct sockopt *sopt) /* Disallow sets in really-really secure mode. */ if (sopt->sopt_dir == SOPT_SET) { error = securelevel_ge(sopt->sopt_td->td_ucred, 3); - if (error) - return (error); + if (error) + return (error); } switch (sopt->sopt_name) { default : - printf("dummynet: -- unknown option %d", sopt->sopt_name); + printf("dummynet: unknown option %d", sopt->sopt_name); error = EINVAL; break; - case IP_DUMMYNET_FLUSH : - 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); + case IP_DUMMYNET_FLUSH: + 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); error = EINVAL; break; @@ -1280,7 +1339,6 @@ ip_dn_ctl(struct sockopt *sopt) error = sooptcopyin(sopt, p, l, l); if (error) break ; - error = do_config(p, l); break; } @@ -1291,59 +1349,6 @@ ip_dn_ctl(struct sockopt *sopt) return error ; } -/*------------------------------------------------------------ - * Scheduler hash. When searching by index we pass sched_nr, - * otherwise we pass struct new_sch * which is the first field in - * struct new_schk so we can cast between the two. We use this trick - * because in the create phase (but it should be fixed). - */ -static int -schk_hash(uintptr_t key, int flags, void *_arg) -{ - int i = !(flags & DNHT_KEY_IS_OBJ) ? key : - ((struct new_schk *)key)->sch.sched_nr; - return ( (i>>8)^(i>>4)^i ); -} - -static int -schk_match(void *obj, uintptr_t key, int flags, void *_arg) -{ - struct new_schk *s = ((struct new_schk *)obj); - int i = !(flags & DNHT_KEY_IS_OBJ) ? key : - ((struct new_schk *)key)->sch.sched_nr; - return !(s->kflags & DN_DELETE) && (s->sch.sched_nr == i); -} - -/* - * Create the entry and intialize with the sched hash if needed. - * Leave s->fp unset so we can tell whether a dn_ht_find() returns - * a new object or a previously existing one. - */ -static void * -schk_new(uintptr_t key, int flags, void *arg) -{ - struct schk_new_arg *a = arg; - struct new_schk *s; - int l = sizeof(*s) +a->fp->schk_datalen; - - s = malloc(l, M_DUMMYNET, M_NOWAIT | M_ZERO); - if (s == NULL) - return NULL; - set_oid(&s->pipe.oid, DN_PIPE, sizeof(s->pipe)); - 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, - offsetof(struct new_sch_inst, si_next), - si_hash, si_match, si_new); - } - dn_cfg.schk_count++; - return s; -} static void ip_dn_init(void)