From owner-svn-src-user@FreeBSD.ORG Sun Jan 17 22:40:47 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 AD4C6106566B; Sun, 17 Jan 2010 22:40:47 +0000 (UTC) (envelope-from kmacy@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 9A9D58FC12; Sun, 17 Jan 2010 22:40:47 +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 o0HMelde066958; Sun, 17 Jan 2010 22:40:47 GMT (envelope-from kmacy@svn.freebsd.org) Received: (from kmacy@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0HMeluH066952; Sun, 17 Jan 2010 22:40:47 GMT (envelope-from kmacy@svn.freebsd.org) Message-Id: <201001172240.o0HMeluH066952@svn.freebsd.org> From: Kip Macy Date: Sun, 17 Jan 2010 22:40:47 +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: r202533 - in user/kmacy/releng_8_rump/lib/libunet: . unet_sys 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: Sun, 17 Jan 2010 22:40:47 -0000 Author: kmacy Date: Sun Jan 17 22:40:47 2010 New Revision: 202533 URL: http://svn.freebsd.org/changeset/base/202533 Log: move local source files in to unet_sys, update Makefile Added: user/kmacy/releng_8_rump/lib/libunet/unet_sys/ user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_compat.c - copied unchanged from r201550, user/kmacy/releng_8_rump/lib/libunet/unet_compat.c user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_glue.c - copied unchanged from r202139, user/kmacy/releng_8_rump/lib/libunet/unet_glue.c user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_in_cksum.c - copied unchanged from r201475, user/kmacy/releng_8_rump/lib/libunet/unet_in_cksum.c user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_init_main.c - copied unchanged from r201470, user/kmacy/releng_8_rump/lib/libunet/unet_init_main.c user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_kern_condvar.c - copied unchanged from r201549, user/kmacy/releng_8_rump/lib/libunet/unet_kern_condvar.c user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_kern_descrip.c - copied unchanged from r202058, user/kmacy/releng_8_rump/lib/libunet/unet_kern_descrip.c user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_kern_intr.c - copied unchanged from r202276, user/kmacy/releng_8_rump/lib/libunet/unet_kern_intr.c user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_kern_subr.c - copied unchanged from r201557, user/kmacy/releng_8_rump/lib/libunet/unet_kern_subr.c user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_kern_synch.c - copied unchanged from r202055, user/kmacy/releng_8_rump/lib/libunet/unet_kern_synch.c user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_kern_timeout.c - copied unchanged from r202139, user/kmacy/releng_8_rump/lib/libunet/unet_kern_timeout.c user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_lock.c - copied unchanged from r201623, user/kmacy/releng_8_rump/lib/libunet/unet_lock.c user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_subr_taskqueue.c - copied unchanged from r201550, user/kmacy/releng_8_rump/lib/libunet/unet_subr_taskqueue.c user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_uma_core.c - copied unchanged from r202067, user/kmacy/releng_8_rump/lib/libunet/unet_uma_core.c Deleted: user/kmacy/releng_8_rump/lib/libunet/unet_compat.c user/kmacy/releng_8_rump/lib/libunet/unet_glue.c user/kmacy/releng_8_rump/lib/libunet/unet_in_cksum.c user/kmacy/releng_8_rump/lib/libunet/unet_init_main.c user/kmacy/releng_8_rump/lib/libunet/unet_kern_condvar.c user/kmacy/releng_8_rump/lib/libunet/unet_kern_descrip.c user/kmacy/releng_8_rump/lib/libunet/unet_kern_intr.c user/kmacy/releng_8_rump/lib/libunet/unet_kern_subr.c user/kmacy/releng_8_rump/lib/libunet/unet_kern_synch.c user/kmacy/releng_8_rump/lib/libunet/unet_kern_timeout.c user/kmacy/releng_8_rump/lib/libunet/unet_lock.c user/kmacy/releng_8_rump/lib/libunet/unet_subr_taskqueue.c user/kmacy/releng_8_rump/lib/libunet/unet_uma_core.c Modified: user/kmacy/releng_8_rump/lib/libunet/Makefile Modified: user/kmacy/releng_8_rump/lib/libunet/Makefile ============================================================================== --- user/kmacy/releng_8_rump/lib/libunet/Makefile Sun Jan 17 21:56:27 2010 (r202532) +++ user/kmacy/releng_8_rump/lib/libunet/Makefile Sun Jan 17 22:40:47 2010 (r202533) @@ -6,6 +6,7 @@ PREFIX= ${.CURDIR}/../../sys .PATH: ${PREFIX}/netinet .PATH: ${PREFIX}/libkern .PATH: ${PREFIX}/dev/random +.PATH: unet_sys LIB= unet Copied: user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_compat.c (from r201550, user/kmacy/releng_8_rump/lib/libunet/unet_compat.c) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_compat.c Sun Jan 17 22:40:47 2010 (r202533, copy of r201550, user/kmacy/releng_8_rump/lib/libunet/unet_compat.c) @@ -0,0 +1,99 @@ +#undef _KERNEL +#define _WANT_UCRED +#include +#include +#include +#include +#include +#include + +struct malloc_type; + +vm_offset_t kmem_malloc(void * map, int bytes, int wait); +void kmem_free(void *map, vm_offset_t addr, vm_size_t size); + +vm_offset_t +kmem_malloc(void * map, int bytes, int wait) +{ + + return ((vm_offset_t)mmap(NULL, bytes, PROT_READ|PROT_WRITE, MAP_ANON, -1, 0)); +} + + +void +kmem_free(void *map, vm_offset_t addr, vm_size_t size) +{ + + munmap((void *)addr, size); +} + +void * +unet_malloc(unsigned long size, struct malloc_type *type, int flags) +{ + + return (malloc(size)); +} + +void +unet_free(void *addr, struct malloc_type *type) +{ + + free(addr); +} + +/* + * Claim another reference to a ucred structure. + */ +struct ucred * +crhold(struct ucred *cr) +{ + + refcount_acquire(&cr->cr_ref); + return (cr); +} + +/* + * Free a cred structure. Throws away space when ref count gets to 0. + */ +void +crfree(struct ucred *cr) +{ + if (refcount_release(&cr->cr_ref)) { + free(cr); + } +} + +void +panic(const char *fmt, ...) +{ + + abort(); +} + +void +bintime(struct bintime *bt) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + timeval2bintime(&tv, bt); +} + +void +getmicrouptime(struct timeval *tvp) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); +} + +void +getmicrotime(struct timeval *tvp) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); +} + + + Copied: user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_glue.c (from r202139, user/kmacy/releng_8_rump/lib/libunet/unet_glue.c) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_glue.c Sun Jan 17 22:40:47 2010 (r202533, copy of r202139, user/kmacy/releng_8_rump/lib/libunet/unet_glue.c) @@ -0,0 +1,757 @@ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +SYSCTL_NODE(, 0, sysctl, CTLFLAG_RW, 0, + "Sysctl internal magic"); + +SYSCTL_NODE(, CTL_KERN, kern, CTLFLAG_RW, 0, + "High kernel, proc, limits &c"); + +SYSCTL_NODE(, CTL_NET, net, CTLFLAG_RW, 0, + "Network, (see socket.h)"); + +SYSCTL_NODE(, CTL_VM, vm, CTLFLAG_RW, 0, + "Virtual memory"); + +SYSCTL_NODE(, CTL_DEBUG, debug, CTLFLAG_RW, 0, + "Debugging"); + +MALLOC_DEFINE(M_DEVBUF, "devbuf", "device driver memory"); +MALLOC_DEFINE(M_TEMP, "temp", "misc temporary data buffers"); + + +extern void abort(void); + +int ticks; + +time_t time_second = 1; +time_t time_uptime = 1; + +/* This is used in modules that need to work in both SMP and UP. */ +cpumask_t all_cpus; + +int mp_ncpus; +/* export this for libkvm consumers. */ +int mp_maxcpus = MAXCPU; + +volatile int smp_started; +u_int mp_maxid; + +long first_page = 0; + +struct vmmeter cnt; +vm_map_t kernel_map=0; +vm_map_t kmem_map=0; + +struct vm_object kernel_object_store; +struct vm_object kmem_object_store; + +struct filterops fs_filtops; +struct filterops sig_filtops; + +int cold; + +static void timevalfix(struct timeval *); + +int +prison_if(struct ucred *cred, struct sockaddr *sa) +{ + + return (0); +} + +int +prison_check_af(struct ucred *cred, int af) +{ + + return (0); +} + +int +prison_check_ip4(struct ucred *cred, struct in_addr *ia) +{ + + return (0); +} + + +int +prison_equal_ip4(struct prison *pr1, struct prison *pr2) +{ + + return (1); +} + +/* + * See if a prison has the specific flag set. + */ +int +prison_flag(struct ucred *cred, unsigned flag) +{ + + /* This is an atomic read, so no locking is necessary. */ + return (flag & PR_HOST); +} + +int +prison_get_ip4(struct ucred *cred, struct in_addr *ia) +{ + + return (0); +} + +int +prison_local_ip4(struct ucred *cred, struct in_addr *ia) +{ + + return (0); +} + +int +prison_remote_ip4(struct ucred *cred, struct in_addr *ia) +{ + + return (0); +} + + +/* + * Return 1 if the passed credential is in a jail and that jail does not + * have its own virtual network stack, otherwise 0. + */ +int +jailed_without_vnet(struct ucred *cred) +{ + + return (0); +} + +int +priv_check(struct thread *td, int priv) +{ + + return (0); +} + +int +priv_check_cred(struct ucred *cred, int priv, int flags) +{ + + return (0); +} + + +int +vslock(void *addr, size_t len) +{ + + return (0); +} + +void +vsunlock(void *addr, size_t len) +{ + +} + + +/* + * Check that a proposed value to load into the .it_value or + * .it_interval part of an interval timer is acceptable, and + * fix it to have at least minimal value (i.e. if it is less + * than the resolution of the clock, round it up.) + */ +int +itimerfix(struct timeval *tv) +{ + + if (tv->tv_sec < 0 || tv->tv_usec < 0 || tv->tv_usec >= 1000000) + return (EINVAL); + if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick) + tv->tv_usec = tick; + return (0); +} + +/* + * Decrement an interval timer by a specified number + * of microseconds, which must be less than a second, + * i.e. < 1000000. If the timer expires, then reload + * it. In this case, carry over (usec - old value) to + * reduce the value reloaded into the timer so that + * the timer does not drift. This routine assumes + * that it is called in a context where the timers + * on which it is operating cannot change in value. + */ +int +itimerdecr(struct itimerval *itp, int usec) +{ + + if (itp->it_value.tv_usec < usec) { + if (itp->it_value.tv_sec == 0) { + /* expired, and already in next interval */ + usec -= itp->it_value.tv_usec; + goto expire; + } + itp->it_value.tv_usec += 1000000; + itp->it_value.tv_sec--; + } + itp->it_value.tv_usec -= usec; + usec = 0; + if (timevalisset(&itp->it_value)) + return (1); + /* expired, exactly at end of interval */ +expire: + if (timevalisset(&itp->it_interval)) { + itp->it_value = itp->it_interval; + itp->it_value.tv_usec -= usec; + if (itp->it_value.tv_usec < 0) { + itp->it_value.tv_usec += 1000000; + itp->it_value.tv_sec--; + } + } else + itp->it_value.tv_usec = 0; /* sec is already 0 */ + return (0); +} + +/* + * Add and subtract routines for timevals. + * N.B.: subtract routine doesn't deal with + * results which are before the beginning, + * it just gets very confused in this case. + * Caveat emptor. + */ +void +timevaladd(struct timeval *t1, const struct timeval *t2) +{ + + t1->tv_sec += t2->tv_sec; + t1->tv_usec += t2->tv_usec; + timevalfix(t1); +} + +void +timevalsub(struct timeval *t1, const struct timeval *t2) +{ + + t1->tv_sec -= t2->tv_sec; + t1->tv_usec -= t2->tv_usec; + timevalfix(t1); +} + +static void +timevalfix(struct timeval *t1) +{ + + if (t1->tv_usec < 0) { + t1->tv_sec--; + t1->tv_usec += 1000000; + } + if (t1->tv_usec >= 1000000) { + t1->tv_sec++; + t1->tv_usec -= 1000000; + } +} + +/* + * ratecheck(): simple time-based rate-limit checking. + */ +int +ratecheck(struct timeval *lasttime, const struct timeval *mininterval) +{ + struct timeval tv, delta; + int rv = 0; + + getmicrouptime(&tv); /* NB: 10ms precision */ + delta = tv; + timevalsub(&delta, lasttime); + + /* + * check for 0,0 is so that the message will be seen at least once, + * even if interval is huge. + */ + if (timevalcmp(&delta, mininterval, >=) || + (lasttime->tv_sec == 0 && lasttime->tv_usec == 0)) { + *lasttime = tv; + rv = 1; + } + + return (rv); +} + +/* + * ppsratecheck(): packets (or events) per second limitation. + * + * Return 0 if the limit is to be enforced (e.g. the caller + * should drop a packet because of the rate limitation). + * + * maxpps of 0 always causes zero to be returned. maxpps of -1 + * always causes 1 to be returned; this effectively defeats rate + * limiting. + * + * Note that we maintain the struct timeval for compatibility + * with other bsd systems. We reuse the storage and just monitor + * clock ticks for minimal overhead. + */ +int +ppsratecheck(struct timeval *lasttime, int *curpps, int maxpps) +{ + int now; + + /* + * Reset the last time and counter if this is the first call + * or more than a second has passed since the last update of + * lasttime. + */ + now = ticks; + if (lasttime->tv_sec == 0 || (u_int)(now - lasttime->tv_sec) >= hz) { + lasttime->tv_sec = now; + *curpps = 1; + return (maxpps != 0); + } else { + (*curpps)++; /* NB: ignore potential overflow */ + return (maxpps < 0 || *curpps < maxpps); + } +} + +/* + * Compute number of ticks in the specified amount of time. + */ +int +tvtohz(tv) + struct timeval *tv; +{ + register unsigned long ticks; + register long sec, usec; + + /* + * If the number of usecs in the whole seconds part of the time + * difference fits in a long, then the total number of usecs will + * fit in an unsigned long. Compute the total and convert it to + * ticks, rounding up and adding 1 to allow for the current tick + * to expire. Rounding also depends on unsigned long arithmetic + * to avoid overflow. + * + * Otherwise, if the number of ticks in the whole seconds part of + * the time difference fits in a long, then convert the parts to + * ticks separately and add, using similar rounding methods and + * overflow avoidance. This method would work in the previous + * case but it is slightly slower and assumes that hz is integral. + * + * Otherwise, round the time difference down to the maximum + * representable value. + * + * If ints have 32 bits, then the maximum value for any timeout in + * 10ms ticks is 248 days. + */ + sec = tv->tv_sec; + usec = tv->tv_usec; + if (usec < 0) { + sec--; + usec += 1000000; + } + if (sec < 0) { +#ifdef DIAGNOSTIC + if (usec > 0) { + sec++; + usec -= 1000000; + } + printf("tvotohz: negative time difference %ld sec %ld usec\n", + sec, usec); +#endif + ticks = 1; + } else if (sec <= LONG_MAX / 1000000) + ticks = (sec * 1000000 + (unsigned long)usec + (tick - 1)) + / tick + 1; + else if (sec <= LONG_MAX / hz) + ticks = sec * hz + + ((unsigned long)usec + (tick - 1)) / tick + 1; + else + ticks = LONG_MAX; + if (ticks > INT_MAX) + ticks = INT_MAX; + return ((int)ticks); +} + +int +copyin(const void *uaddr, void *kaddr, size_t len) +{ + + memcpy(kaddr, uaddr, len); + + return (0); +} + +int +copyout(const void *kaddr, void *uaddr, size_t len) +{ + + memcpy(uaddr, kaddr, len); + + return (0); +} + + +int +copystr(const void *kfaddr, void *kdaddr, size_t len, size_t *done) +{ + size_t bytes; + + bytes = strlcpy(kdaddr, kfaddr, len); + if (done != NULL) + *done = bytes; + + return (0); +} + + + +int +copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done) +{ + size_t bytes; + + bytes = strlcpy(kaddr, uaddr, len); + if (done != NULL) + *done = bytes; + + return (0); +} + + +int +subyte(void *base, int byte) +{ + + *(char *)base = (uint8_t)byte; + return (0); +} + + + +/* + * Change the total socket buffer size a user has used. + */ +int +chgsbsize(uip, hiwat, to, max) + struct uidinfo *uip; + u_int *hiwat; + u_int to; + rlim_t max; +{ + int diff; + + diff = to - *hiwat; + if (diff > 0) { + if (atomic_fetchadd_long(&uip->ui_sbsize, (long)diff) + diff > max) { + atomic_subtract_long(&uip->ui_sbsize, (long)diff); + return (0); + } + } else { + atomic_add_long(&uip->ui_sbsize, (long)diff); + if (uip->ui_sbsize < 0) + printf("negative sbsize for uid = %d\n", uip->ui_uid); + } + *hiwat = to; + return (1); +} + + +/* + * Return the current (soft) limit for a particular system resource. + * The which parameter which specifies the index into the rlimit array + */ +rlim_t +lim_cur(struct proc *p, int which) +{ + struct rlimit rl; + + lim_rlimit(p, which, &rl); + return (rl.rlim_cur); +} + +/* + * Return a copy of the entire rlimit structure for the system limit + * specified by 'which' in the rlimit structure pointed to by 'rlp'. + */ +void +lim_rlimit(struct proc *p, int which, struct rlimit *rlp) +{ + +#if 0 + PROC_LOCK_ASSERT(p, MA_OWNED); + KASSERT(which >= 0 && which < RLIM_NLIMITS, + ("request for invalid resource limit")); + *rlp = p->p_limit->pl_rlimit[which]; + if (p->p_sysent->sv_fixlimit != NULL) + p->p_sysent->sv_fixlimit(rlp, which); +#endif +} + +int +useracc(void *addr, int len, int rw) +{ + return (1); +} + + + +struct proc * +zpfind(pid_t pid) +{ + + return (NULL); +} + +int +p_cansee(struct thread *td, struct proc *p) +{ + + return (0); +} + +struct proc * +pfind(pid_t pid) +{ + + return (NULL); +} + +/* + * Fill in a struct xucred based on a struct ucred. + */ +void +cru2x(struct ucred *cr, struct xucred *xcr) +{ +#if 0 + int ngroups; + + bzero(xcr, sizeof(*xcr)); + xcr->cr_version = XUCRED_VERSION; + xcr->cr_uid = cr->cr_uid; + + ngroups = MIN(cr->cr_ngroups, XU_NGROUPS); + xcr->cr_ngroups = ngroups; + bcopy(cr->cr_groups, xcr->cr_groups, + ngroups * sizeof(*cr->cr_groups)); +#endif +} + +int +cr_cansee(struct ucred *u1, struct ucred *u2) +{ + + return (0); +} + +int +cr_canseeinpcb(struct ucred *cred, struct inpcb *inp) +{ + + return (0); +} + +int +securelevel_gt(struct ucred *cr, int level) +{ + + return (0); +} + + +/** + * @brief Send a 'notification' to userland, using standard ways + */ +void +devctl_notify(const char *system, const char *subsystem, const char *type, + const char *data) +{ + ; +} + +void +cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size) +{ + ; +} + + +/* + * Send a SIGIO or SIGURG signal to a process or process group using stored + * credentials rather than those of the current process. + */ +void +pgsigio(sigiop, sig, checkctty) + struct sigio **sigiop; + int sig, checkctty; +{ + printf("SIGIO not supported yet\n"); + abort(); +#ifdef notyet + ksiginfo_t ksi; + struct sigio *sigio; + + ksiginfo_init(&ksi); + ksi.ksi_signo = sig; + ksi.ksi_code = SI_KERNEL; + + SIGIO_LOCK(); + sigio = *sigiop; + if (sigio == NULL) { + SIGIO_UNLOCK(); + return; + } + if (sigio->sio_pgid > 0) { + PROC_LOCK(sigio->sio_proc); + if (CANSIGIO(sigio->sio_ucred, sigio->sio_proc->p_ucred)) + psignal(sigio->sio_proc, sig); + PROC_UNLOCK(sigio->sio_proc); + } else if (sigio->sio_pgid < 0) { + struct proc *p; + + PGRP_LOCK(sigio->sio_pgrp); + LIST_FOREACH(p, &sigio->sio_pgrp->pg_members, p_pglist) { + PROC_LOCK(p); + if (CANSIGIO(sigio->sio_ucred, p->p_ucred) && + (checkctty == 0 || (p->p_flag & P_CONTROLT))) + psignal(p, sig); + PROC_UNLOCK(p); + } + PGRP_UNLOCK(sigio->sio_pgrp); + } + SIGIO_UNLOCK(); +#endif +} + +void +kproc_exit(int ecode) +{ + panic("kproc_exit unsupported"); +} + +vm_offset_t +kmem_alloc_contig(vm_map_t map, vm_size_t size, int flags, vm_paddr_t low, + vm_paddr_t high, unsigned long alignment, unsigned long boundary, + vm_memattr_t memattr) +{ + return (kmem_malloc(map, size, flags)); +} + +void +malloc_init(void *data) +{ +#ifdef notyet + struct malloc_type_internal *mtip; + struct malloc_type *mtp; + + KASSERT(cnt.v_page_count != 0, ("malloc_register before vm_init")); + + mtp = data; + if (mtp->ks_magic != M_MAGIC) + panic("malloc_init: bad malloc type magic"); + + mtip = uma_zalloc(mt_zone, M_WAITOK | M_ZERO); + mtp->ks_handle = mtip; + + mtx_lock(&malloc_mtx); + mtp->ks_next = kmemstatistics; + kmemstatistics = mtp; + kmemcount++; + mtx_unlock(&malloc_mtx); +#endif +} + +void +malloc_uninit(void *data) +{ +#ifdef notyet + struct malloc_type_internal *mtip; + struct malloc_type_stats *mtsp; + struct malloc_type *mtp, *temp; + uma_slab_t slab; + long temp_allocs, temp_bytes; + int i; + + mtp = data; + KASSERT(mtp->ks_magic == M_MAGIC, + ("malloc_uninit: bad malloc type magic")); + KASSERT(mtp->ks_handle != NULL, ("malloc_deregister: cookie NULL")); + + mtx_lock(&malloc_mtx); + mtip = mtp->ks_handle; + mtp->ks_handle = NULL; + if (mtp != kmemstatistics) { + for (temp = kmemstatistics; temp != NULL; + temp = temp->ks_next) { + if (temp->ks_next == mtp) { + temp->ks_next = mtp->ks_next; + break; + } + } + KASSERT(temp, + ("malloc_uninit: type '%s' not found", mtp->ks_shortdesc)); + } else + kmemstatistics = mtp->ks_next; + kmemcount--; + mtx_unlock(&malloc_mtx); + + /* + * Look for memory leaks. + */ + temp_allocs = temp_bytes = 0; + for (i = 0; i < MAXCPU; i++) { + mtsp = &mtip->mti_stats[i]; + temp_allocs += mtsp->mts_numallocs; + temp_allocs -= mtsp->mts_numfrees; + temp_bytes += mtsp->mts_memalloced; + temp_bytes -= mtsp->mts_memfreed; + } + if (temp_allocs > 0 || temp_bytes > 0) { + printf("Warning: memory type %s leaked memory on destroy " + "(%ld allocations, %ld bytes leaked).\n", mtp->ks_shortdesc, + temp_allocs, temp_bytes); + } + + slab = vtoslab((vm_offset_t) mtip & (~UMA_SLAB_MASK)); + uma_zfree_arg(mt_zone, mtip, slab); +#endif +} + +void +knote(struct knlist *list, long hint, int lockflags) +{ + +} + +void +knlist_destroy(struct knlist *knl) +{ + +} + +void +knlist_init_mtx(struct knlist *knl, struct mtx *lock) +{ + +} Copied: user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_in_cksum.c (from r201475, user/kmacy/releng_8_rump/lib/libunet/unet_in_cksum.c) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_in_cksum.c Sun Jan 17 22:40:47 2010 (r202533, copy of r201475, user/kmacy/releng_8_rump/lib/libunet/unet_in_cksum.c) @@ -0,0 +1,491 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from tahoe: in_cksum.c 1.2 86/01/05 + * from: @(#)in_cksum.c 1.3 (Berkeley) 1/19/91 + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include + +#include +#include +#include + +#include + +/* + * Checksum routine for Internet Protocol family headers. + * + * This routine is very heavily used in the network + * code and should be modified for each CPU to be as fast as possible. + * + * This implementation is 386 version. + */ + +#undef ADDCARRY +#define ADDCARRY(x) if ((x) > 0xffff) (x) -= 0xffff +/* + * icc needs to be special cased here, as the asm code below results + * in broken code if compiled with icc. + */ +#if !defined(__GNUCLIKE_ASM) || defined(__INTEL_COMPILER) || defined(UNET) +/* non gcc parts stolen from sys/alpha/alpha/in_cksum.c */ +#define REDUCE32 \ + { \ + q_util.q = sum; \ + sum = q_util.s[0] + q_util.s[1] + q_util.s[2] + q_util.s[3]; \ + } +#define REDUCE16 \ + { \ + q_util.q = sum; \ + l_util.l = q_util.s[0] + q_util.s[1] + q_util.s[2] + q_util.s[3]; \ + sum = l_util.s[0] + l_util.s[1]; \ + ADDCARRY(sum); \ + } +#endif +#define REDUCE {sum = (sum & 0xffff) + (sum >> 16); ADDCARRY(sum);} + +#if !defined(__GNUCLIKE_ASM) || defined(__INTEL_COMPILER) || defined(UNET) +static const u_int32_t in_masks[] = { + /*0 bytes*/ /*1 byte*/ /*2 bytes*/ /*3 bytes*/ + 0x00000000, 0x000000FF, 0x0000FFFF, 0x00FFFFFF, /* offset 0 */ + 0x00000000, 0x0000FF00, 0x00FFFF00, 0xFFFFFF00, /* offset 1 */ + 0x00000000, 0x00FF0000, 0xFFFF0000, 0xFFFF0000, /* offset 2 */ + 0x00000000, 0xFF000000, 0xFF000000, 0xFF000000, /* offset 3 */ +}; + +union l_util { + u_int16_t s[2]; + u_int32_t l; +}; +union q_util { + u_int16_t s[4]; + u_int32_t l[2]; + u_int64_t q; +}; + +static u_int64_t +in_cksumdata(const u_int32_t *lw, int len) +{ + u_int64_t sum = 0; + u_int64_t prefilled; + int offset; + union q_util q_util; + + if ((3 & (long) lw) == 0 && len == 20) { + sum = (u_int64_t) lw[0] + lw[1] + lw[2] + lw[3] + lw[4]; + REDUCE32; + return sum; + } + + if ((offset = 3 & (long) lw) != 0) { + const u_int32_t *masks = in_masks + (offset << 2); + lw = (u_int32_t *) (((long) lw) - offset); + sum = *lw++ & masks[len >= 3 ? 3 : len]; + len -= 4 - offset; + if (len <= 0) { + REDUCE32; + return sum; + } + } +#if 0 + /* + * Force to cache line boundary. + */ + offset = 32 - (0x1f & (long) lw); *** DIFF OUTPUT TRUNCATED AT 1000 LINES *** From owner-svn-src-user@FreeBSD.ORG Mon Jan 18 00:43:34 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 6F3F01065672; Mon, 18 Jan 2010 00:43:34 +0000 (UTC) (envelope-from kmacy@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 451278FC17; Mon, 18 Jan 2010 00:43:34 +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 o0I0hYCa095364; Mon, 18 Jan 2010 00:43:34 GMT (envelope-from kmacy@svn.freebsd.org) Received: (from kmacy@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0I0hYB1095361; Mon, 18 Jan 2010 00:43:34 GMT (envelope-from kmacy@svn.freebsd.org) Message-Id: <201001180043.o0I0hYB1095361@svn.freebsd.org> From: Kip Macy Date: Mon, 18 Jan 2010 00:43:34 +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: r202535 - in user/kmacy/releng_8_rump/lib/libunet: . unet_sys 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: Mon, 18 Jan 2010 00:43:34 -0000 Author: kmacy Date: Mon Jan 18 00:43:33 2010 New Revision: 202535 URL: http://svn.freebsd.org/changeset/base/202535 Log: don't use inline sx locks Modified: user/kmacy/releng_8_rump/lib/libunet/Makefile user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_lock.c Modified: user/kmacy/releng_8_rump/lib/libunet/Makefile ============================================================================== --- user/kmacy/releng_8_rump/lib/libunet/Makefile Sun Jan 17 23:23:35 2010 (r202534) +++ user/kmacy/releng_8_rump/lib/libunet/Makefile Mon Jan 18 00:43:33 2010 (r202535) @@ -123,9 +123,11 @@ CFLAGS+= -I${PREFIX} CFLAGS+= -D_KERNEL CFLAGS+= -DMUTEX_NOINLINE CFLAGS+= -DRWLOCK_NOINLINE +CFLAGS+= -DSX_NOINLINE CFLAGS+= -DUNET CFLAGS+= -DMAXUSERS=32 CFLAGS+= -fno-builtin +CFLAGS+= -O0 CFLAGS+= -g .include Modified: user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_lock.c ============================================================================== --- user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_lock.c Sun Jan 17 23:23:35 2010 (r202534) +++ user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_lock.c Mon Jan 18 00:43:33 2010 (r202535) @@ -303,7 +303,7 @@ sx_destroy(struct sx *sx) } int -_sx_xlock_hard(struct sx *sx, uintptr_t tid, int opts, +_sx_xlock(struct sx *sx, int opts, const char *file, int line) { @@ -312,7 +312,7 @@ _sx_xlock_hard(struct sx *sx, uintptr_t } int -_sx_slock_hard(struct sx *sx, int opts, const char *file, int line) +_sx_slock(struct sx *sx, int opts, const char *file, int line) { _rw_rlock((struct rwlock *)sx, file, line); @@ -320,15 +320,14 @@ _sx_slock_hard(struct sx *sx, int opts, } void -_sx_xunlock_hard(struct sx *sx, uintptr_t tid, const char *file, int - line) +_sx_xunlock(struct sx *sx, const char *file, int line) { _rw_wunlock((struct rwlock *)sx, file, line); } void -_sx_sunlock_hard(struct sx *sx, const char *file, int line) +_sx_sunlock(struct sx *sx, const char *file, int line) { _rw_runlock((struct rwlock *)sx, file, line); From owner-svn-src-user@FreeBSD.ORG Mon Jan 18 01:49:47 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 422E0106566C; Mon, 18 Jan 2010 01:49:47 +0000 (UTC) (envelope-from kmacy@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 319AB8FC14; Mon, 18 Jan 2010 01:49:47 +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 o0I1nlDB010764; Mon, 18 Jan 2010 01:49:47 GMT (envelope-from kmacy@svn.freebsd.org) Received: (from kmacy@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0I1nlqj010762; Mon, 18 Jan 2010 01:49:47 GMT (envelope-from kmacy@svn.freebsd.org) Message-Id: <201001180149.o0I1nlqj010762@svn.freebsd.org> From: Kip Macy Date: Mon, 18 Jan 2010 01:49:47 +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: r202537 - user/kmacy/releng_8_rump/lib/libunet/unet_sys 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: Mon, 18 Jan 2010 01:49:47 -0000 Author: kmacy Date: Mon Jan 18 01:49:46 2010 New Revision: 202537 URL: http://svn.freebsd.org/changeset/base/202537 Log: implement rw_sysinit Modified: user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_lock.c Modified: user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_lock.c ============================================================================== --- user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_lock.c Mon Jan 18 00:53:21 2010 (r202536) +++ user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_lock.c Mon Jan 18 01:49:46 2010 (r202537) @@ -113,8 +113,9 @@ struct lock_class lock_class_rw = { void rw_sysinit(void *arg) { + struct rw_args *args = arg; - panic(""); + rw_init(args->ra_rw, args->ra_desc); } void From owner-svn-src-user@FreeBSD.ORG Mon Jan 18 01:50:53 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 8317F106568D; Mon, 18 Jan 2010 01:50:53 +0000 (UTC) (envelope-from kmacy@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 725678FC1F; Mon, 18 Jan 2010 01:50:53 +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 o0I1orHf011045; Mon, 18 Jan 2010 01:50:53 GMT (envelope-from kmacy@svn.freebsd.org) Received: (from kmacy@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0I1orMw011043; Mon, 18 Jan 2010 01:50:53 GMT (envelope-from kmacy@svn.freebsd.org) Message-Id: <201001180150.o0I1orMw011043@svn.freebsd.org> From: Kip Macy Date: Mon, 18 Jan 2010 01:50:53 +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: r202538 - user/kmacy/releng_8_rump/lib/libunet/unet_sys 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: Mon, 18 Jan 2010 01:50:53 -0000 Author: kmacy Date: Mon Jan 18 01:50:53 2010 New Revision: 202538 URL: http://svn.freebsd.org/changeset/base/202538 Log: enable debugging don't allocate bootmem Modified: user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_uma_core.c Modified: user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_uma_core.c ============================================================================== --- user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_uma_core.c Mon Jan 18 01:49:46 2010 (r202537) +++ user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_uma_core.c Mon Jan 18 01:50:53 2010 (r202538) @@ -52,11 +52,11 @@ __FBSDID("$FreeBSD$"); /* I should really use ktr.. */ -/* + #define UMA_DEBUG 1 #define UMA_DEBUG_ALLOC 1 #define UMA_DEBUG_ALLOC_1 1 -*/ + #include "opt_ddb.h" #include "opt_param.h" @@ -1762,6 +1762,7 @@ uma_startup(void *bootmem, int boot_page /* The initial zone has no Per cpu queues so it's smaller */ zone_ctor(kegs, sizeof(struct uma_zone), &args, M_WAITOK); +#if 0 #ifdef UMA_DEBUG printf("Filling boot free list.\n"); #endif @@ -1772,7 +1773,8 @@ uma_startup(void *bootmem, int boot_page LIST_INSERT_HEAD(&uma_boot_pages, slab, us_link); } pthread_mutex_init(&uma_boot_pages_mtx, NULL); - +#endif + #ifdef UMA_DEBUG printf("Creating uma zone headers zone and keg.\n"); #endif From owner-svn-src-user@FreeBSD.ORG Mon Jan 18 01:52:38 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 C35A7106566B; Mon, 18 Jan 2010 01:52:38 +0000 (UTC) (envelope-from kmacy@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id B2B158FC1F; Mon, 18 Jan 2010 01:52:38 +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 o0I1qc7p011499; Mon, 18 Jan 2010 01:52:38 GMT (envelope-from kmacy@svn.freebsd.org) Received: (from kmacy@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0I1qc6d011497; Mon, 18 Jan 2010 01:52:38 GMT (envelope-from kmacy@svn.freebsd.org) Message-Id: <201001180152.o0I1qc6d011497@svn.freebsd.org> From: Kip Macy Date: Mon, 18 Jan 2010 01:52:38 +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: r202539 - user/kmacy/releng_8_rump/lib/libunet/unet_sys 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: Mon, 18 Jan 2010 01:52:38 -0000 Author: kmacy Date: Mon Jan 18 01:52:38 2010 New Revision: 202539 URL: http://svn.freebsd.org/changeset/base/202539 Log: - enable verbosity - sysinit set is allocated in the text and thus not writeable copy to newly allocated memory before sorting Modified: user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_init_main.c Modified: user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_init_main.c ============================================================================== --- user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_init_main.c Mon Jan 18 01:50:53 2010 (r202538) +++ user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_init_main.c Mon Jan 18 01:52:38 2010 (r202539) @@ -102,6 +102,10 @@ SYSCTL_INT(_debug, OID_AUTO, boothowto, int bootverbose; SYSCTL_INT(_debug, OID_AUTO, bootverbose, CTLFLAG_RW, &bootverbose, 0, ""); #endif + +#define VERBOSE_SYSINIT + + /* * This ensures that there is at least one entry so that the sysinit_set * symbol is not undefined. A sybsystem ID of SI_SUB_DUMMY is never @@ -152,6 +156,7 @@ sysinit_add(struct sysinit **set, struct newsysinit_end = newset + count; } + /* * System startup; initialize the world, create process 0, mount root * filesystem, and fork to create init and pagedaemon. Most of the @@ -170,15 +175,22 @@ mi_startup(void) register struct sysinit **sipp; /* system initialization*/ register struct sysinit **xipp; /* interior loop of sort*/ register struct sysinit *save; /* bubble*/ + struct sysinit **temp; + int size; #if defined(VERBOSE_SYSINIT) int last; int verbose; #endif - if (sysinit == NULL) { + if (sysinit == NULL) { sysinit = SET_BEGIN(sysinit_set); sysinit_end = SET_LIMIT(sysinit_set); + size = (uintptr_t)sysinit_end - (uintptr_t)sysinit; + temp = malloc(size, M_DEVBUF, M_WAITOK); + memcpy(temp, sysinit, size); + sysinit = temp; + sysinit_end = (struct sysinit **)(((uint8_t *)sysinit) + size); } restart: From owner-svn-src-user@FreeBSD.ORG Mon Jan 18 01:53:04 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 19AD110656C1; Mon, 18 Jan 2010 01:53:04 +0000 (UTC) (envelope-from kmacy@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 091028FC14; Mon, 18 Jan 2010 01:53:04 +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 o0I1r3Ne011641; Mon, 18 Jan 2010 01:53:03 GMT (envelope-from kmacy@svn.freebsd.org) Received: (from kmacy@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0I1r3g5011639; Mon, 18 Jan 2010 01:53:03 GMT (envelope-from kmacy@svn.freebsd.org) Message-Id: <201001180153.o0I1r3g5011639@svn.freebsd.org> From: Kip Macy Date: Mon, 18 Jan 2010 01:53:03 +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: r202540 - user/kmacy/releng_8_rump/lib/libunet/unet_sys 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: Mon, 18 Jan 2010 01:53:04 -0000 Author: kmacy Date: Mon Jan 18 01:53:03 2010 New Revision: 202540 URL: http://svn.freebsd.org/changeset/base/202540 Log: set timeout_cpu to always be 0 Modified: user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_kern_timeout.c Modified: user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_kern_timeout.c ============================================================================== --- user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_kern_timeout.c Mon Jan 18 01:52:38 2010 (r202539) +++ user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_kern_timeout.c Mon Jan 18 01:53:03 2010 (r202540) @@ -143,7 +143,11 @@ kern_timeout_callwheel_alloc(caddr_t v) { struct callout_cpu *cc; +#ifdef notyet timeout_cpu = PCPU_GET(cpuid); +#else + timeout_cpu = 0; +#endif cc = CC_CPU(timeout_cpu); /* * Calculate callout wheel size From owner-svn-src-user@FreeBSD.ORG Mon Jan 18 01:56:41 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 11C2C1065672; Mon, 18 Jan 2010 01:56:41 +0000 (UTC) (envelope-from kmacy@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 014428FC12; Mon, 18 Jan 2010 01:56:41 +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 o0I1uehg012525; Mon, 18 Jan 2010 01:56:40 GMT (envelope-from kmacy@svn.freebsd.org) Received: (from kmacy@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0I1ue9X012523; Mon, 18 Jan 2010 01:56:40 GMT (envelope-from kmacy@svn.freebsd.org) Message-Id: <201001180156.o0I1ue9X012523@svn.freebsd.org> From: Kip Macy Date: Mon, 18 Jan 2010 01:56:40 +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: r202541 - user/kmacy/releng_8_rump/lib/libunet/test 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: Mon, 18 Jan 2010 01:56:41 -0000 Author: kmacy Date: Mon Jan 18 01:56:40 2010 New Revision: 202541 URL: http://svn.freebsd.org/changeset/base/202541 Log: add test program for testing SYSINIT (bootstrap) Added: user/kmacy/releng_8_rump/lib/libunet/test/ user/kmacy/releng_8_rump/lib/libunet/test/init.c (contents, props changed) Added: user/kmacy/releng_8_rump/lib/libunet/test/init.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/kmacy/releng_8_rump/lib/libunet/test/init.c Mon Jan 18 01:56:40 2010 (r202541) @@ -0,0 +1,24 @@ +#include +#include +#include + +extern void mi_startup(void); +extern void uma_startup(void *, int); +caddr_t kern_timeout_callwheel_alloc(caddr_t v); +void kern_timeout_callwheel_init(void); +extern int ncallout; + + +int +main(void) +{ + /* vm_init bits */ + ncallout = 64; + kern_timeout_callwheel_alloc(malloc(512*1024)); + kern_timeout_callwheel_init(); + uma_startup(NULL, 0); + + + mi_startup(); + +} From owner-svn-src-user@FreeBSD.ORG Mon Jan 18 03:47:23 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 5BD161065670; Mon, 18 Jan 2010 03:47:23 +0000 (UTC) (envelope-from kmacy@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 4B3A98FC13; Mon, 18 Jan 2010 03:47:23 +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 o0I3lNla038180; Mon, 18 Jan 2010 03:47:23 GMT (envelope-from kmacy@svn.freebsd.org) Received: (from kmacy@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0I3lMLm038179; Mon, 18 Jan 2010 03:47:22 GMT (envelope-from kmacy@svn.freebsd.org) Message-Id: <201001180347.o0I3lMLm038179@svn.freebsd.org> From: Kip Macy Date: Mon, 18 Jan 2010 03:47:22 +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: r202542 - user/kmacy/releng_8_rump/sys/kern 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: Mon, 18 Jan 2010 03:47:23 -0000 Author: kmacy Date: Mon Jan 18 03:47:22 2010 New Revision: 202542 URL: http://svn.freebsd.org/changeset/base/202542 Log: conditionally exclude locks not used by libunet Modified: user/kmacy/releng_8_rump/sys/kern/subr_lock.c Modified: user/kmacy/releng_8_rump/sys/kern/subr_lock.c ============================================================================== --- user/kmacy/releng_8_rump/sys/kern/subr_lock.c Mon Jan 18 01:56:40 2010 (r202541) +++ user/kmacy/releng_8_rump/sys/kern/subr_lock.c Mon Jan 18 03:47:22 2010 (r202542) @@ -63,12 +63,16 @@ __FBSDID("$FreeBSD$"); CTASSERT(LOCK_CLASS_MAX == 15); struct lock_class *lock_classes[LOCK_CLASS_MAX + 1] = { +#ifndef UNET &lock_class_mtx_spin, +#endif &lock_class_mtx_sleep, &lock_class_sx, &lock_class_rm, &lock_class_rw, +#ifndef UNET &lock_class_lockmgr, +#endif }; void From owner-svn-src-user@FreeBSD.ORG Mon Jan 18 03:49:14 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 02379106566C; Mon, 18 Jan 2010 03:49:14 +0000 (UTC) (envelope-from kmacy@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id E447B8FC14; Mon, 18 Jan 2010 03:49:13 +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 o0I3nD70038662; Mon, 18 Jan 2010 03:49:13 GMT (envelope-from kmacy@svn.freebsd.org) Received: (from kmacy@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0I3nDio038660; Mon, 18 Jan 2010 03:49:13 GMT (envelope-from kmacy@svn.freebsd.org) Message-Id: <201001180349.o0I3nDio038660@svn.freebsd.org> From: Kip Macy Date: Mon, 18 Jan 2010 03:49:13 +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: r202543 - user/kmacy/releng_8_rump/lib/libunet/include/sys 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: Mon, 18 Jan 2010 03:49:14 -0000 Author: kmacy Date: Mon Jan 18 03:49:13 2010 New Revision: 202543 URL: http://svn.freebsd.org/changeset/base/202543 Log: import modified param to re-name sysctl Added: user/kmacy/releng_8_rump/lib/libunet/include/sys/param.h (contents, props changed) Added: user/kmacy/releng_8_rump/lib/libunet/include/sys/param.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/kmacy/releng_8_rump/lib/libunet/include/sys/param.h Mon Jan 18 03:49:13 2010 (r202543) @@ -0,0 +1,323 @@ +/*- + * Copyright (c) 1982, 1986, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)param.h 8.3 (Berkeley) 4/4/95 + * $FreeBSD$ + */ + +#ifndef _SYS_PARAM_H_ +#define _SYS_PARAM_H_ + +#include + +#define BSD 199506 /* System version (year & month). */ +#define BSD4_3 1 +#define BSD4_4 1 + +/* + * __FreeBSD_version numbers are documented in the Porter's Handbook. + * If you bump the version for any reason, you should update the documentation + * there. + * Currently this lives here: + * + * doc/en_US.ISO8859-1/books/porters-handbook/book.sgml + * + * scheme is: Rxx + * 'R' is in the range 0 to 4 if this is a release branch or + * x.0-CURRENT before RELENG_*_0 is created, otherwise 'R' is + * in the range 5 to 9. + */ +#undef __FreeBSD_version +#define __FreeBSD_version 800108 /* Master, propagated to newvers */ + +#ifndef LOCORE +#include +#endif + +/* + * Machine-independent constants (some used in following include files). + * Redefined constants are from POSIX 1003.1 limits file. + * + * MAXCOMLEN should be >= sizeof(ac_comm) (see ) + * MAXLOGNAME should be == UT_NAMESIZE+1 (see ) + */ +#include + +#define MAXCOMLEN 19 /* max command name remembered */ +#define MAXINTERP 32 /* max interpreter file name length */ +#define MAXLOGNAME 17 /* max login name length (incl. NUL) */ +#define MAXUPRC CHILD_MAX /* max simultaneous processes */ +#define NCARGS ARG_MAX /* max bytes for an exec function */ +#define NGROUPS (NGROUPS_MAX+1) /* max number groups */ +#define NOFILE OPEN_MAX /* max open files per process */ +#define NOGROUP 65535 /* marker for empty group set member */ +#define MAXHOSTNAMELEN 256 /* max hostname size */ +#define SPECNAMELEN 63 /* max length of devicename */ + +/* More types and definitions used throughout the kernel. */ +#ifdef _KERNEL +#include +#include +#ifndef LOCORE +#include +#include +#endif + +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif +#endif + +#ifndef _KERNEL +/* Signals. */ +#include +#endif + +/* Machine type dependent parameters. */ +#include +#ifndef _KERNEL +#include +#endif + +#ifndef _NO_NAMESPACE_POLLUTION + +#ifndef DEV_BSHIFT +#define DEV_BSHIFT 9 /* log2(DEV_BSIZE) */ +#endif +#define DEV_BSIZE (1<>PAGE_SHIFT) +#endif + +/* + * btodb() is messy and perhaps slow because `bytes' may be an off_t. We + * want to shift an unsigned type to avoid sign extension and we don't + * want to widen `bytes' unnecessarily. Assume that the result fits in + * a daddr_t. + */ +#ifndef btodb +#define btodb(bytes) /* calculates (bytes / DEV_BSIZE) */ \ + (sizeof (bytes) > sizeof(long) \ + ? (daddr_t)((unsigned long long)(bytes) >> DEV_BSHIFT) \ + : (daddr_t)((unsigned long)(bytes) >> DEV_BSHIFT)) +#endif + +#ifndef dbtob +#define dbtob(db) /* calculates (db * DEV_BSIZE) */ \ + ((off_t)(db) << DEV_BSHIFT) +#endif + +#endif /* _NO_NAMESPACE_POLLUTION */ + +#define PRIMASK 0x0ff +#define PCATCH 0x100 /* OR'd with pri for tsleep to check signals */ +#define PDROP 0x200 /* OR'd with pri to stop re-entry of interlock mutex */ +#define PBDRY 0x400 /* for PCATCH stop is done on the user boundary */ + +#define NZERO 0 /* default "nice" */ + +#define NBBY 8 /* number of bits in a byte */ +#define NBPW sizeof(int) /* number of bytes per word (integer) */ + +#define CMASK 022 /* default file mask: S_IWGRP|S_IWOTH */ + +#define NODEV (dev_t)(-1) /* non-existent device */ + +/* + * File system parameters and macros. + * + * MAXBSIZE - Filesystems are made out of blocks of at most MAXBSIZE bytes + * per block. MAXBSIZE may be made larger without effecting + * any existing filesystems as long as it does not exceed MAXPHYS, + * and may be made smaller at the risk of not being able to use + * filesystems which require a block size exceeding MAXBSIZE. + * + * BKVASIZE - Nominal buffer space per buffer, in bytes. BKVASIZE is the + * minimum KVM memory reservation the kernel is willing to make. + * Filesystems can of course request smaller chunks. Actual + * backing memory uses a chunk size of a page (PAGE_SIZE). + * + * If you make BKVASIZE too small you risk seriously fragmenting + * the buffer KVM map which may slow things down a bit. If you + * make it too big the kernel will not be able to optimally use + * the KVM memory reserved for the buffer cache and will wind + * up with too-few buffers. + * + * The default is 16384, roughly 2x the block size used by a + * normal UFS filesystem. + */ +#define MAXBSIZE 65536 /* must be power of 2 */ +#define BKVASIZE 16384 /* must be power of 2 */ +#define BKVAMASK (BKVASIZE-1) + +/* + * MAXPATHLEN defines the longest permissible path length after expanding + * symbolic links. It is used to allocate a temporary buffer from the buffer + * pool in which to do the name expansion, hence should be a power of two, + * and must be less than or equal to MAXBSIZE. MAXSYMLINKS defines the + * maximum number of symbolic links that may be expanded in a path name. + * It should be set high enough to allow all legitimate uses, but halt + * infinite loops reasonably quickly. + */ +#define MAXPATHLEN PATH_MAX +#define MAXSYMLINKS 32 + +/* Bit map related macros. */ +#define setbit(a,i) (((unsigned char *)(a))[(i)/NBBY] |= 1<<((i)%NBBY)) +#define clrbit(a,i) (((unsigned char *)(a))[(i)/NBBY] &= ~(1<<((i)%NBBY))) +#define isset(a,i) \ + (((const unsigned char *)(a))[(i)/NBBY] & (1<<((i)%NBBY))) +#define isclr(a,i) \ + ((((const unsigned char *)(a))[(i)/NBBY] & (1<<((i)%NBBY))) == 0) + +/* Macros for counting and rounding. */ +#ifndef howmany +#define howmany(x, y) (((x)+((y)-1))/(y)) +#endif +#define rounddown(x, y) (((x)/(y))*(y)) +#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) /* to any y */ +#define roundup2(x, y) (((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */ +#define powerof2(x) ((((x)-1)&(x))==0) + +/* Macros for min/max. */ +#define MIN(a,b) (((a)<(b))?(a):(b)) +#define MAX(a,b) (((a)>(b))?(a):(b)) + +#ifdef _KERNEL +/* + * Basic byte order function prototypes for non-inline functions. + */ +#ifndef LOCORE +#ifndef _BYTEORDER_PROTOTYPED +#define _BYTEORDER_PROTOTYPED +__BEGIN_DECLS +__uint32_t htonl(__uint32_t); +__uint16_t htons(__uint16_t); +__uint32_t ntohl(__uint32_t); +__uint16_t ntohs(__uint16_t); +__END_DECLS +#endif +#endif + +#ifndef lint +#ifndef _BYTEORDER_FUNC_DEFINED +#define _BYTEORDER_FUNC_DEFINED +#define htonl(x) __htonl(x) +#define htons(x) __htons(x) +#define ntohl(x) __ntohl(x) +#define ntohs(x) __ntohs(x) +#endif /* !_BYTEORDER_FUNC_DEFINED */ +#endif /* lint */ +#endif /* _KERNEL */ + +/* + * Scale factor for scaled integers used to count %cpu time and load avgs. + * + * The number of CPU `tick's that map to a unique `%age' can be expressed + * by the formula (1 / (2 ^ (FSHIFT - 11))). The maximum load average that + * can be calculated (assuming 32 bits) can be closely approximated using + * the formula (2 ^ (2 * (16 - FSHIFT))) for (FSHIFT < 15). + * + * For the scheduler to maintain a 1:1 mapping of CPU `tick' to `%age', + * FSHIFT must be at least 11; this gives us a maximum load avg of ~1024. + */ +#define FSHIFT 11 /* bits to right of fixed binary point */ +#define FSCALE (1<> (PAGE_SHIFT - DEV_BSHIFT)) + +#define ctodb(db) /* calculates pages to devblks */ \ + ((db) << (PAGE_SHIFT - DEV_BSHIFT)) + +/* + * Given the pointer x to the member m of the struct s, return + * a pointer to the containing structure. + */ +#define member2struct(s, m, x) \ + ((struct s *)(void *)((char *)(x) - offsetof(struct s, m))) + + + +#ifdef UNET +#define __sysctl __unet_sysctl +#endif + + + +#endif /* _SYS_PARAM_H_ */ From owner-svn-src-user@FreeBSD.ORG Mon Jan 18 03:50:36 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 BD0D11065672; Mon, 18 Jan 2010 03:50:36 +0000 (UTC) (envelope-from kmacy@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id AC3A48FC15; Mon, 18 Jan 2010 03:50:36 +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 o0I3oaKY039017; Mon, 18 Jan 2010 03:50:36 GMT (envelope-from kmacy@svn.freebsd.org) Received: (from kmacy@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0I3oarP039014; Mon, 18 Jan 2010 03:50:36 GMT (envelope-from kmacy@svn.freebsd.org) Message-Id: <201001180350.o0I3oarP039014@svn.freebsd.org> From: Kip Macy Date: Mon, 18 Jan 2010 03:50:36 +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: r202544 - in user/kmacy/releng_8_rump/sys: sys vm 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: Mon, 18 Jan 2010 03:50:36 -0000 Author: kmacy Date: Mon Jan 18 03:50:36 2010 New Revision: 202544 URL: http://svn.freebsd.org/changeset/base/202544 Log: exclude malloc.h from uma in unet & add to mbuf.h Modified: user/kmacy/releng_8_rump/sys/sys/mbuf.h user/kmacy/releng_8_rump/sys/vm/uma.h Modified: user/kmacy/releng_8_rump/sys/sys/mbuf.h ============================================================================== --- user/kmacy/releng_8_rump/sys/sys/mbuf.h Mon Jan 18 03:49:13 2010 (r202543) +++ user/kmacy/releng_8_rump/sys/sys/mbuf.h Mon Jan 18 03:50:36 2010 (r202544) @@ -39,6 +39,7 @@ #ifdef _KERNEL #include #include +#include #ifdef WITNESS #include #endif Modified: user/kmacy/releng_8_rump/sys/vm/uma.h ============================================================================== --- user/kmacy/releng_8_rump/sys/vm/uma.h Mon Jan 18 03:49:13 2010 (r202543) +++ user/kmacy/releng_8_rump/sys/vm/uma.h Mon Jan 18 03:50:36 2010 (r202544) @@ -37,8 +37,9 @@ #define VM_UMA_H #include /* For NULL */ +#ifndef UNET #include /* For M_* */ - +#endif /* User visible parameters */ #define UMA_SMALLEST_UNIT (PAGE_SIZE / 256) /* Smallest item allocated */ From owner-svn-src-user@FreeBSD.ORG Mon Jan 18 03:54:20 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 4D1A11065672; Mon, 18 Jan 2010 03:54:20 +0000 (UTC) (envelope-from kmacy@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 237138FC12; Mon, 18 Jan 2010 03:54:20 +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 o0I3sKGx039900; Mon, 18 Jan 2010 03:54:20 GMT (envelope-from kmacy@svn.freebsd.org) Received: (from kmacy@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0I3sKTO039898; Mon, 18 Jan 2010 03:54:20 GMT (envelope-from kmacy@svn.freebsd.org) Message-Id: <201001180354.o0I3sKTO039898@svn.freebsd.org> From: Kip Macy Date: Mon, 18 Jan 2010 03:54:20 +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: r202545 - user/kmacy/releng_8_rump/sys/sys 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: Mon, 18 Jan 2010 03:54:20 -0000 Author: kmacy Date: Mon Jan 18 03:54:19 2010 New Revision: 202545 URL: http://svn.freebsd.org/changeset/base/202545 Log: include malloc.h Modified: user/kmacy/releng_8_rump/sys/sys/acl.h Modified: user/kmacy/releng_8_rump/sys/sys/acl.h ============================================================================== --- user/kmacy/releng_8_rump/sys/sys/acl.h Mon Jan 18 03:50:36 2010 (r202544) +++ user/kmacy/releng_8_rump/sys/sys/acl.h Mon Jan 18 03:54:19 2010 (r202545) @@ -39,6 +39,7 @@ #include #include #include +#include /* * POSIX.1e and NFSv4 ACL types and related constants. From owner-svn-src-user@FreeBSD.ORG Mon Jan 18 03:58:24 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 339741065670; Mon, 18 Jan 2010 03:58:24 +0000 (UTC) (envelope-from kmacy@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 22D8E8FC0C; Mon, 18 Jan 2010 03:58:24 +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 o0I3wOlK040872; Mon, 18 Jan 2010 03:58:24 GMT (envelope-from kmacy@svn.freebsd.org) Received: (from kmacy@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0I3wOq2040870; Mon, 18 Jan 2010 03:58:24 GMT (envelope-from kmacy@svn.freebsd.org) Message-Id: <201001180358.o0I3wOq2040870@svn.freebsd.org> From: Kip Macy Date: Mon, 18 Jan 2010 03:58:24 +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: r202546 - user/kmacy/releng_8_rump/lib/libunet/unet_sys 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: Mon, 18 Jan 2010 03:58:24 -0000 Author: kmacy Date: Mon Jan 18 03:58:23 2010 New Revision: 202546 URL: http://svn.freebsd.org/changeset/base/202546 Log: ifdef out kproc_kthread_add Modified: user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_kern_intr.c Modified: user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_kern_intr.c ============================================================================== --- user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_kern_intr.c Mon Jan 18 03:54:19 2010 (r202545) +++ user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_kern_intr.c Mon Jan 18 03:58:23 2010 (r202546) @@ -361,6 +361,7 @@ ithread_create(const char *name) ithd = malloc(sizeof(struct intr_thread), M_ITHREAD, M_WAITOK | M_ZERO); +#ifdef notyet error = kproc_kthread_add(ithread_loop, ithd, &intrproc, &td, RFSTOPPED | RFHIGHPID, 0, "intr", "%s", name); @@ -368,6 +369,7 @@ ithread_create(const char *name) panic("kproc_create() failed with %d", error); td->td_pflags |= TDP_ITHREAD; ithd->it_thread = td; +#endif CTR2(KTR_INTR, "%s: created %s", __func__, name); return (ithd); } From owner-svn-src-user@FreeBSD.ORG Mon Jan 18 09:13:47 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 6EB30106566C; Mon, 18 Jan 2010 09:13:47 +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 5D8F08FC1D; Mon, 18 Jan 2010 09:13:47 +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 o0I9DlQX013759; Mon, 18 Jan 2010 09:13:47 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0I9Dlx0013757; Mon, 18 Jan 2010 09:13:47 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <201001180913.o0I9Dlx0013757@svn.freebsd.org> From: Luigi Rizzo Date: Mon, 18 Jan 2010 09:13:47 +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: r202554 - 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: Mon, 18 Jan 2010 09:13:47 -0000 Author: luigi Date: Mon Jan 18 09:13:47 2010 New Revision: 202554 URL: http://svn.freebsd.org/changeset/base/202554 Log: code cleanup (not compiling) Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c Mon Jan 18 09:04:53 2010 (r202553) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c Mon Jan 18 09:13:47 2010 (r202554) @@ -58,32 +58,51 @@ * ne_heap (key is Start time) stores not-eligible queues * idle_heap (key=start/finish time) stores idle flows. It must * support extract-from-middle. - * A flow is normally only in 1 of the three heaps. + * A flow is only in 1 of the three heaps. * XXX todo: use a more efficient data structure, e.g. a tree sorted * by F with min_subtree(S) in each node */ struct wf2qp_si { - struct dn_heap *sch_heap; /* top extract - key Finish time */ - struct dn_heap *ne_heap; /* top extract - key Start time */ - struct dn_heap *idle_heap; /* random extract - key Start=Finish time */ + struct dn_heap *sch_heap; /* top extract - key Finish time */ + struct dn_heap *ne_heap; /* top extract - key Start time */ + struct dn_heap *idle_heap; /* random extract - key Start=Finish time */ dn_key V ; /* virtual time */ - int sum; + uint32_t sum; /* sum of weights */ }; struct wf2qp_queue { - struct new_queue g; - dn_key S,F; /* start time, finish time */ - int heap_pos; /* position (index) of struct in heap */ -// struct wf2qp_queue *next; /* next queue in the bucket */ }; /* * This file implements a WF2Q+ scheduler as it has been in dummynet * since 2000. * The scheduler supports per-flow queues and has O(log N) complexity. + * + * WF2Q+ needs to drain entries from the idle heap so that we + * can keep the sum of weights up to date. We can do it whenever + * we get a chance, or periodically, or following some other + * strategy. The function idle_check() drains at most N elements + * from the idle heap. */ +static void +idle_check(struct wf2qp_si *siwfq, int n) +{ + struct dn_heap *h = si->idle_heap; + while (n-- > 0 && h->elements > 0 && + DN_KEY_LT(HEAP_TOP(h)->key, si->V)) { + struct dn_queue *q = HEAP_TOP(h)->object; + struct wf2qp_queue *alg_fq = (struct wf2qp_queue *)(q+1); + + heap_extract(h, NULL); + /* XXX to let the flowset delete the queue we should + * mark it as 'unused' by the scheduler. + */ + alg_fq->S = alg_fq->F + 1; /* Mark timestamp as invalid. */ + si->sum -= q->fs->fs.weight; /* adjust sum of weights */ + } +} static int wf2qp_enqueue(struct new_sch_inst *_si, struct new_queue *q, struct mbuf *m) @@ -92,32 +111,30 @@ wf2qp_enqueue(struct new_sch_inst *_si, struct wf2qp_si *si = (struct wf2qp_si *)(_si + 1); struct wf2qp_queue *alg_fq; uint64_t len = m->m_pkthdr.len; + int q_was_idle; - int q_was_idle = 0; - - if (q->mq.head == NULL) - q_was_idle = 1; + q_was_idle = (q->mq.head == NULL) if (dn_enqueue(q, m, 0)) /* packet was dropped */ return 1; - if(!q_was_idle) + if (!q_was_idle) return 0; /* If reach this point, queue q was idle */ - alg_fq = (struct wf2qp_queue *)q; + alg_fq = (struct wf2qp_queue *)(q+1); if (DN_KEY_LT(alg_fq->F, alg_fq->S)) { /* Fbrand new queue. */ - alg_fq->S = si->V; - si->sum += fs->fs.weight; /* Add weight of new queue. */ + alg_fq->S = si->V; /* init start time */ + si->sum += fs->fs.weight; /* add weight of new queue. */ } else { /* if it was idle then it was in the idle heap */ heap_extract(si->idle_heap, q); - alg_fq->S = MAX64(alg_fq->F, si->V); + alg_fq->S = MAX64(alg_fq->F, si->V); /* compute new S */ } - // XXX use div64 - alg_fq->F = alg_fq->S + (len << MY_M) / (uint64_t)fs->fs.weight; + alg_fq->F = alg_fq->S + div64((len << MY_M), fs->fs.weight); + /* if nothing is backlogged, make sure this flow is eligible */ if (si->ne_heap->elements == 0 && si->sch_heap->elements == 0) si->V = MAX64(alg_fq->S, si->V); @@ -137,233 +154,135 @@ wf2qp_enqueue(struct new_sch_inst *_si, if (si->sch_heap->elements == 0) printf("dummynet: ++ ouch! not eligible but empty scheduler!\n"); heap_insert(si->ne_heap, alg_fq->S, q); - } - else { + } else { heap_insert(si->sch_heap, alg_fq->F, q); - /* Pipe *must* be idle. */ -#if 0 - if ((si->sch_heap.elements != 1) && (s->numbytes >= 0)) - printf("dummynet: OUCH! pipe should have been idle!\n"); - DPRINTF(("dummynet: waking up pipe %d at %d\n", - s->sched_nr, (int)(alg_fq->F >> MY_M))); -#endif } return 0; } +/* XXX invariant: sch > 0 || neh == 0 */ static struct mbuf * wf2qp_dequeue(struct new_sch_inst *_si) { /* Access scheduler instance private data */ struct wf2qp_si *si = (struct wf2qp_si *)(_si + 1); - struct mbuf *pkt = NULL; struct new_queue *qq, *q1, *q = NULL; - struct dn_heap *sch = si->sch_heap; struct dn_heap *neh = si->ne_heap; - struct wf2qp_queue *alg_fq = NULL; - uint64_t len; - /* XXX: - * This block in the previous version were done in the dummynet_task() - * function. Check if this is the appropriate function to do it. - */ - if (si->idle_heap->elements > 0 && - DN_KEY_LT(HEAP_TOP(si->idle_heap)->key, si->V)) { - qq = HEAP_TOP(si->idle_heap)->object; - alg_fq = (struct wf2qp_queue *) qq; - - heap_extract(si->idle_heap, NULL); - /* Mark timestamp as invalid. */ - /* XXX why don't delete the queue now? */ - alg_fq->S = alg_fq->F + 1; - si->sum -= qq->fs->fs.weight; - } - - -#if 0 - if (p->if_name[0] == 0) { /* tx clock is simulated */ - s->numbytes += (curr_time - s->sched_time) * p->bandwidth; - } - else { - /* tx clock is for real, the ifq must be empty or this is a NOP. */ - if (p->ifp && p->ifp->if_snd.ifq_head != NULL) - return NULL; - else { - DPRINTF(("dummynet: pipe %d ready from %s --\n", - p->pipe_nr, p->if_name)); - } + if (sch->elements == 0 && neh->elements == 0) { + /* we have nothing to do. We could kill the idle heap + * altogether and reset V + */ + idle_check(si, 0x7fffffff); + si->V = 0; + si->sum = 0; /* should be set already */ + return NULL; /* quick return if nothing to } -#endif - /* - * While we have backlogged traffic AND credit, we need to do - * something on the queue. - * XXX cannot be a 'while -- - */ - while ( sch->elements > 0 || neh->elements > 0) { - if (sch->elements > 0) { + idle_check(si, 1); /* drain something from the idle heap */ + if (sch->elements > 0) { /* Have some eligible pkts to send out. */ q = HEAP_TOP(sch)->object; - alg_fq = (struct wf2qp_queue *)q; - + alg_fq = (struct wf2qp_queue *)(q + 1); pkt = q->mq.head; - heap_extract(sch, NULL); /* Remove queue from heap. */ - - si->V += (pkt->m_pkthdr.len << MY_M) / si->sum; /* Update V. */ + si->V += div64(pkt->m_pkthdr.len << MY_M, si->sum); alg_fq->S = alg_fq->F; /* Update start time. */ - - if (q->ni.length == 1) /* Flow not backlogged any more. */ - heap_insert(si->idle_heap, alg_fq->F, q); - else { - /* Still backlogged. */ - /* - * Update F and position in backlogged queue, - * then put flow in ne_heap - * (we will fix this later). - */ - /* len = (q->head)->m_pkthdr.len; */ - len = ((q->mq.head)->m_nextpkt)->m_pkthdr.len; - alg_fq->F += (len << MY_M) / (uint64_t)q->fs->fs.weight; + if (q->ni.length == 1) { /* not backlogged any more. */ + heap_insert(si->idle_heap, alg_fq->F, q); + } else { /* Still backlogged. */ + /* Update F, store in neh or sch */ + len = pkt->m_nextpkt->m_pkthdr.len; + alg_fq->F += div64(len << MY_M, q->fs->fs.weight); if (DN_KEY_LEQ(alg_fq->S, si->V)) { - heap_insert(neh, alg_fq->S, q); - } - else { heap_insert(sch, alg_fq->F, q); + } else { + heap_insert(neh, alg_fq->S, q); } } - } - /* - * Now compute V = max(V, min(S_i)). Remember that all elements - * in sch have by definition S_i <= V so if sch is not empty, - * V is surely the max and we must not update it. Conversely, - * if sch is empty we only need to look at neh. - */ - if (sch->elements == 0 && neh->elements > 0) - si->V = MAX64(si->V, HEAP_TOP(neh)->key); - /* Move from neh to sch any packets that have become eligible */ - while (neh->elements > 0 && DN_KEY_LEQ(HEAP_TOP(neh)->key, si->V)) { - qq = HEAP_TOP(neh)->object; - alg_fq = (struct wf2qp_queue *)qq; - heap_extract(neh, NULL); - heap_insert(sch, alg_fq->F, qq); - } -#if 0 - if (p->if_name[0] != '\0') { /* Tx clock is from a real thing */ - s->numbytes = -1; /* Mark not ready for I/O. */ /* WARNING*/ - debMes(" %s f\n", __FUNCTION__); - break; - } -#endif - if (pkt != NULL) - return dn_dequeue(q); - - } /* end of while */ - - if (sch->elements == 0 && neh->elements == 0 && - si->idle_heap->elements > 0) { - /* - * No traffic and no events scheduled. - * We can get rid of idle-heap. - */ - int i; - int elem = si->idle_heap->elements; - - for (i = 0; i < elem; i++) { - /* XXX NOTE: before the heap changed, this block extracted - * all elements - */ - q1 = HEAP_TOP(si->idle_heap)->object; - heap_extract(si->idle_heap, NULL); - alg_fq = (struct wf2qp_queue *)q1; - - alg_fq->F = 0; - alg_fq->S = alg_fq->F + 1; - /* XXX: why don't call delete queue? */ - } - si->sum = 0; - si->V = 0; -// si->idle_heap.elements = 0; } /* - * If we are getting clocks from dummynet (not a real interface) and - * If we are under credit, schedule the next ready event. - * Also fix the delivery time of the last packet. + * Now compute V = max(V, min(S_i)). Remember that all elements + * in sch have by definition S_i <= V so if sch is not empty, + * V is surely the max and we must not update it. Conversely, + * if sch is empty we only need to look at neh. */ - -#if 0 - if (p->if_name[0]==0 && s->numbytes < 0) - ... -#endif + if (sch->elements == 0 && neh->elements > 0) + si->V = MAX64(si->V, HEAP_TOP(neh)->key); + /* Move from neh to sch any packets that have become eligible */ + while (neh->elements > 0 && DN_KEY_LEQ(HEAP_TOP(neh)->key, si->V)) { + qq = HEAP_TOP(neh)->object; + alg_fq = (struct wf2qp_queue *)qq; + heap_extract(neh, NULL); + heap_insert(sch, alg_fq->F, qq); + } + if (pkt != NULL) + return dn_dequeue(q); return NULL; } static int wf2qp_new_sched(struct new_sch_inst *_si) { - struct wf2qp_si *si = (struct wf2qp_si *)(_si + 1); - int ofs = offsetof(struct wf2qp_queue, heap_pos); + struct wf2qp_si *si = (struct wf2qp_si *)(_si + 1); + int ofs = offsetof(struct wf2qp_queue, heap_pos); - /* only idle-heap supports extract from middle */ - if (heap_init(si->idle_heap, 16, ofs) || - heap_init(si->sch_heap, 16, -1) || - heap_init(si->ne_heap, 16, -1)) { - heap_free(si->ne_heap); - heap_free(si->sch_heap); - heap_free(si->idle_heap); - return ENOMEM; - } - return 0; + /* only idle-heap supports extract from middle */ + if (heap_init(si->idle_heap, 16, ofs) || + heap_init(si->sch_heap, 16, -1) || + heap_init(si->ne_heap, 16, -1)) { + heap_free(si->ne_heap); + heap_free(si->sch_heap); + heap_free(si->idle_heap); + return ENOMEM; + } + return 0; } static int wf2qp_free_sched(struct new_sch_inst *_si) { - struct wf2qp_si *si = (struct wf2qp_si *)(_si + 1); + struct wf2qp_si *si = (struct wf2qp_si *)(_si + 1); - heap_free(si->sch_heap); - heap_free(si->ne_heap); - heap_free(si->idle_heap); + heap_free(si->sch_heap); + heap_free(si->ne_heap); + heap_free(si->idle_heap); - return 0; + return 0; } static int -wf2qp_new_queue (struct new_queue *q) +wf2qp_new_queue(struct new_queue *_q) { - struct wf2qp_queue *tmp = (struct wf2qp_queue *) q; - - q->ni.oid.subtype = DN_SCHED_WF2QP; - - tmp->S = tmp->F + 1; /* hack - mark timestamp as invalid. */ + struct wf2qp_queue *q = (struct wf2qp_queue *)(_q + 1); + _q->ni.oid.subtype = DN_SCHED_WF2QP; + q->F = 0; /* not strictly necessary */ + q->S = q->F + 1; /* mark timestamp as invalid. */ return 0; } static int wf2qp_free_queue(struct new_queue *q) { - struct wf2qp_si *si = (struct wf2qp_si *)q->si + 1; - struct wf2qp_queue *alg_fq = (struct wf2qp_queue *)q; + struct wf2qp_queue *alg_fq = (struct wf2qp_queue *)(q + 1); - /* If the queue was valid, decrement the sum value - * else this was done by dequeue() - */ - if(alg_fq->S != alg_fq->F + 1) - si->sum -= q->fs->fs.weight; - - return 0; + /* If the queue was valid, decrement the sum value */ + if (alg_fq->S != alg_fq->F + 1) { + struct wf2qp_si *si = (struct wf2qp_si *)(q->si + 1); + si->sum -= q->fs->fs.weight; + } + return 0; } /* * WF2Q+ scheduler descriptor - * contains the type of the scheduler, the name, the size of the various - * structures and function pointers. If a function is not implemented, - * the pointer is initialized to NULL + * contains the type of the scheduler, the name, the size of the + * structures and function pointers. */ static struct dn_sched wf2qp_desc = { .type = DN_SCHED_WF2QP, @@ -381,7 +300,6 @@ static struct dn_sched wf2qp_desc = { .new_queue = wf2qp_new_queue, .free_queue = wf2qp_free_queue, - }; From owner-svn-src-user@FreeBSD.ORG Mon Jan 18 09:41:54 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 A179C106566B; Mon, 18 Jan 2010 09:41:54 +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 907E58FC1D; Mon, 18 Jan 2010 09:41:54 +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 o0I9fsfF020227; Mon, 18 Jan 2010 09:41:54 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0I9fsj9020223; Mon, 18 Jan 2010 09:41:54 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <201001180941.o0I9fsj9020223@svn.freebsd.org> From: Luigi Rizzo Date: Mon, 18 Jan 2010 09:41:54 +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: r202555 - 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: Mon, 18 Jan 2010 09:41:54 -0000 Author: luigi Date: Mon Jan 18 09:41:54 2010 New Revision: 202555 URL: http://svn.freebsd.org/changeset/base/202555 Log: make wf2q compile; move div64 to ip_dn_private.h Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c Mon Jan 18 09:13:47 2010 (r202554) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c Mon Jan 18 09:41:54 2010 (r202555) @@ -87,12 +87,12 @@ struct wf2qp_queue { * from the idle heap. */ static void -idle_check(struct wf2qp_si *siwfq, int n) +idle_check(struct wf2qp_si *si, int n) { struct dn_heap *h = si->idle_heap; while (n-- > 0 && h->elements > 0 && DN_KEY_LT(HEAP_TOP(h)->key, si->V)) { - struct dn_queue *q = HEAP_TOP(h)->object; + struct new_queue *q = HEAP_TOP(h)->object; struct wf2qp_queue *alg_fq = (struct wf2qp_queue *)(q+1); heap_extract(h, NULL); @@ -113,7 +113,7 @@ wf2qp_enqueue(struct new_sch_inst *_si, uint64_t len = m->m_pkthdr.len; int q_was_idle; - q_was_idle = (q->mq.head == NULL) + q_was_idle = (q->mq.head == NULL); if (dn_enqueue(q, m, 0)) /* packet was dropped */ return 1; @@ -160,69 +160,74 @@ wf2qp_enqueue(struct new_sch_inst *_si, return 0; } -/* XXX invariant: sch > 0 || neh == 0 */ +/* XXX invariant: sch > 0 || V >= min(S in neh) */ static struct mbuf * wf2qp_dequeue(struct new_sch_inst *_si) { - /* Access scheduler instance private data */ - struct wf2qp_si *si = (struct wf2qp_si *)(_si + 1); - struct mbuf *pkt = NULL; - struct new_queue *qq, *q1, *q = NULL; - struct dn_heap *sch = si->sch_heap; - struct dn_heap *neh = si->ne_heap; - struct wf2qp_queue *alg_fq = NULL; - uint64_t len; - - if (sch->elements == 0 && neh->elements == 0) { - /* we have nothing to do. We could kill the idle heap - * altogether and reset V + /* Access scheduler instance private data */ + struct wf2qp_si *si = (struct wf2qp_si *)(_si + 1); + struct mbuf *pkt; + struct new_queue *q; + struct dn_heap *sch = si->sch_heap; + struct dn_heap *neh = si->ne_heap; + struct wf2qp_queue *alg_fq; + + if (sch->elements == 0 && neh->elements == 0) { + /* we have nothing to do. We could kill the idle heap + * altogether and reset V + */ + idle_check(si, 0x7fffffff); + si->V = 0; + si->sum = 0; /* should be set already */ + return NULL; /* quick return if nothing to do */ + } + idle_check(si, 1); /* drain something from the idle heap */ + + /* make sure at least one element is eligible, bumping V + * and moving entries that have become eligible */ - idle_check(si, 0x7fffffff); - si->V = 0; - si->sum = 0; /* should be set already */ - return NULL; /* quick return if nothing to - } - idle_check(si, 1); /* drain something from the idle heap */ - if (sch->elements > 0) { - /* Have some eligible pkts to send out. */ - q = HEAP_TOP(sch)->object; - alg_fq = (struct wf2qp_queue *)(q + 1); - pkt = q->mq.head; - heap_extract(sch, NULL); /* Remove queue from heap. */ - si->V += div64(pkt->m_pkthdr.len << MY_M, si->sum); - alg_fq->S = alg_fq->F; /* Update start time. */ - - if (q->ni.length == 1) { /* not backlogged any more. */ - heap_insert(si->idle_heap, alg_fq->F, q); - } else { /* Still backlogged. */ - /* Update F, store in neh or sch */ - len = pkt->m_nextpkt->m_pkthdr.len; - alg_fq->F += div64(len << MY_M, q->fs->fs.weight); - if (DN_KEY_LEQ(alg_fq->S, si->V)) { - heap_insert(sch, alg_fq->F, q); - } else { - heap_insert(neh, alg_fq->S, q); - } - } - } - /* - * Now compute V = max(V, min(S_i)). Remember that all elements - * in sch have by definition S_i <= V so if sch is not empty, - * V is surely the max and we must not update it. Conversely, - * if sch is empty we only need to look at neh. - */ - if (sch->elements == 0 && neh->elements > 0) - si->V = MAX64(si->V, HEAP_TOP(neh)->key); - /* Move from neh to sch any packets that have become eligible */ - while (neh->elements > 0 && DN_KEY_LEQ(HEAP_TOP(neh)->key, si->V)) { - qq = HEAP_TOP(neh)->object; - alg_fq = (struct wf2qp_queue *)qq; - heap_extract(neh, NULL); - heap_insert(sch, alg_fq->F, qq); - } - if (pkt != NULL) - return dn_dequeue(q); - return NULL; + if (sch->elements == 0 && neh->elements > 0) + si->V = MAX64(si->V, HEAP_TOP(neh)->key); + while (neh->elements > 0 && + DN_KEY_LEQ(HEAP_TOP(neh)->key, si->V)) { + q = HEAP_TOP(neh)->object; + alg_fq = (struct wf2qp_queue *)q; + heap_extract(neh, NULL); + heap_insert(sch, alg_fq->F, q); + } + + /* ok we have at least one eligible pkt */ + q = HEAP_TOP(sch)->object; + alg_fq = (struct wf2qp_queue *)(q + 1); + pkt = dn_dequeue(q); + heap_extract(sch, NULL); /* Remove queue from heap. */ + si->V += div64(pkt->m_pkthdr.len << MY_M, si->sum); + alg_fq->S = alg_fq->F; /* Update start time. */ + + if (q->mq.head == 0) { /* not backlogged any more. */ + heap_insert(si->idle_heap, alg_fq->F, q); + } else { /* Still backlogged. */ + /* Update F, store in neh or sch */ + uint64_t len = q->mq.head->m_pkthdr.len; + alg_fq->F += div64(len << MY_M, q->fs->fs.weight); + if (DN_KEY_LEQ(alg_fq->S, si->V)) { + heap_insert(sch, alg_fq->F, q); + } else { + heap_insert(neh, alg_fq->S, q); + } + } + + /* + * Now compute V = max(V, min(S_i)). Remember that all elements + * in sch have by definition S_i <= V so if sch is not empty, + * V is surely the max and we must not update it. Conversely, + * if sch is empty we only need to look at neh. + * We don't need to move the queues, as it will be done at the + * next enqueue + */ + if (sch->elements == 0 && neh->elements > 0) + si->V = MAX64(si->V, HEAP_TOP(neh)->key); + return pkt; } static int @@ -258,12 +263,12 @@ wf2qp_free_sched(struct new_sch_inst *_s static int wf2qp_new_queue(struct new_queue *_q) { - struct wf2qp_queue *q = (struct wf2qp_queue *)(_q + 1); + struct wf2qp_queue *q = (struct wf2qp_queue *)(_q + 1); - _q->ni.oid.subtype = DN_SCHED_WF2QP; - q->F = 0; /* not strictly necessary */ - q->S = q->F + 1; /* mark timestamp as invalid. */ - return 0; + _q->ni.oid.subtype = DN_SCHED_WF2QP; + q->F = 0; /* not strictly necessary */ + q->S = q->F + 1; /* mark timestamp as invalid. */ + return 0; } static int @@ -285,21 +290,21 @@ wf2qp_free_queue(struct new_queue *q) * structures and function pointers. */ static struct dn_sched wf2qp_desc = { - .type = DN_SCHED_WF2QP, - .name = "WF2Q+", - .flags = DN_MULTIQUEUE, + .type = DN_SCHED_WF2QP, + .name = "WF2Q+", + .flags = DN_MULTIQUEUE, - .sch_inst_len = sizeof(struct wf2qp_si), - .queue_len = sizeof(struct wf2qp_queue), + .sch_inst_len = sizeof(struct wf2qp_si), + .queue_len = sizeof(struct wf2qp_queue), - .enqueue = wf2qp_enqueue, - .dequeue = wf2qp_dequeue, + .enqueue = wf2qp_enqueue, + .dequeue = wf2qp_dequeue, - .new_sched = wf2qp_new_sched, - .free_sched = wf2qp_free_sched, + .new_sched = wf2qp_new_sched, + .free_sched = wf2qp_free_sched, - .new_queue = wf2qp_new_queue, - .free_queue = wf2qp_free_queue, + .new_queue = wf2qp_new_queue, + .free_queue = wf2qp_free_queue, }; 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 18 09:13:47 2010 (r202554) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c Mon Jan 18 09:41:54 2010 (r202555) @@ -278,8 +278,6 @@ transmit_event(struct mq *q, struct dela } } -#define div64(a, b) ((int64_t)(a) / (int64_t)(b)) - /* * Convert the additional MAC overheads/delays into an equivalent * number of bits for the given data rate. The samples are 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 18 09:13:47 2010 (r202554) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h Mon Jan 18 09:41:54 2010 (r202555) @@ -36,6 +36,7 @@ MALLOC_DECLARE(M_DUMMYNET); #ifndef FREE_PKT #define FREE_PKT(m) m_freem(m) #endif +#define div64(a, b) ((int64_t)(a) / (int64_t)(b)) extern struct mtx dummynet_mtx; #define DUMMYNET_LOCK_INIT() \ From owner-svn-src-user@FreeBSD.ORG Mon Jan 18 12:43: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 DE6B61065676; Mon, 18 Jan 2010 12:43:57 +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 CD9A18FC12; Mon, 18 Jan 2010 12:43:57 +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 o0IChvhi065032; Mon, 18 Jan 2010 12:43:57 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0IChvAt065026; Mon, 18 Jan 2010 12:43:57 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <201001181243.o0IChvAt065026@svn.freebsd.org> From: Luigi Rizzo Date: Mon, 18 Jan 2010 12:43:57 +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: r202568 - 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: Mon, 18 Jan 2010 12:43:58 -0000 Author: luigi Date: Mon Jan 18 12:43:57 2010 New Revision: 202568 URL: http://svn.freebsd.org/changeset/base/202568 Log: - the heaps must be allocated before heap_init(); - make sure that the number of buckets is valid before allocating a hash table; - insert new_fsk/free_fsk callbacks in the schedulers, useful to validate flowset's parameters such as weights and so on; Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.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/sys/netinet/ipfw/dn_sched.h ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h Mon Jan 18 11:33:58 2010 (r202567) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h Mon Jan 18 12:43:57 2010 (r202568) @@ -88,6 +88,10 @@ struct dn_sched { * free_sched called when deleting an instance, cleans * extra data in the per-instance area. * + * new_fsk called when a flowset is linked to a scheduler, + * e.g. to validate parameters such as weights etc. + * free_fsk when a flowset is unlinked from a scheduler. + * * new_queue called to set the per-queue parameters, * e.g. S and F, adjust sum of weights in the parent, etc. * @@ -100,10 +104,10 @@ struct dn_sched { int (*config)(struct new_schk *, int reconfigure); int (*destroy)(struct new_schk*, int delete); - int (*new_sched)(struct new_sch_inst *); int (*free_sched)(struct new_sch_inst *); - + int (*new_fsk)(struct new_fsk *f); + int (*free_fsk)(struct new_fsk *f); int (*new_queue)(struct new_queue *q); int (*free_queue)(struct new_queue *q); }; Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c Mon Jan 18 11:33:58 2010 (r202567) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c Mon Jan 18 12:43:57 2010 (r202568) @@ -63,9 +63,9 @@ * by F with min_subtree(S) in each node */ struct wf2qp_si { - struct dn_heap *sch_heap; /* top extract - key Finish time */ - struct dn_heap *ne_heap; /* top extract - key Start time */ - struct dn_heap *idle_heap; /* random extract - key Start=Finish time */ + struct dn_heap sch_heap; /* top extract - key Finish time */ + struct dn_heap ne_heap; /* top extract - key Start time */ + struct dn_heap idle_heap; /* random extract - key Start=Finish time */ dn_key V ; /* virtual time */ uint32_t sum; /* sum of weights */ }; @@ -87,11 +87,11 @@ struct wf2qp_queue { * from the idle heap. */ static void -idle_check(struct wf2qp_si *si, int n) +idle_check(struct wf2qp_si *si, int n, int force) { - struct dn_heap *h = si->idle_heap; + struct dn_heap *h = &si->idle_heap; while (n-- > 0 && h->elements > 0 && - DN_KEY_LT(HEAP_TOP(h)->key, si->V)) { + (force || DN_KEY_LT(HEAP_TOP(h)->key, si->V))) { struct new_queue *q = HEAP_TOP(h)->object; struct wf2qp_queue *alg_fq = (struct wf2qp_queue *)(q+1); @@ -129,13 +129,13 @@ wf2qp_enqueue(struct new_sch_inst *_si, alg_fq->S = si->V; /* init start time */ si->sum += fs->fs.weight; /* add weight of new queue. */ } else { /* if it was idle then it was in the idle heap */ - heap_extract(si->idle_heap, q); + heap_extract(&si->idle_heap, q); alg_fq->S = MAX64(alg_fq->F, si->V); /* compute new S */ } alg_fq->F = alg_fq->S + div64((len << MY_M), fs->fs.weight); /* if nothing is backlogged, make sure this flow is eligible */ - if (si->ne_heap->elements == 0 && si->sch_heap->elements == 0) + if (si->ne_heap.elements == 0 && si->sch_heap.elements == 0) si->V = MAX64(alg_fq->S, si->V); /* @@ -151,11 +151,11 @@ wf2qp_enqueue(struct new_sch_inst *_si, */ if (DN_KEY_LT(si->V, alg_fq->S)) { /* S>V means flow Not eligible. */ - if (si->sch_heap->elements == 0) + if (si->sch_heap.elements == 0) printf("dummynet: ++ ouch! not eligible but empty scheduler!\n"); - heap_insert(si->ne_heap, alg_fq->S, q); + heap_insert(&si->ne_heap, alg_fq->S, q); } else { - heap_insert(si->sch_heap, alg_fq->F, q); + heap_insert(&si->sch_heap, alg_fq->F, q); } return 0; } @@ -168,26 +168,27 @@ wf2qp_dequeue(struct new_sch_inst *_si) struct wf2qp_si *si = (struct wf2qp_si *)(_si + 1); struct mbuf *pkt; struct new_queue *q; - struct dn_heap *sch = si->sch_heap; - struct dn_heap *neh = si->ne_heap; + struct dn_heap *sch = &si->sch_heap; + struct dn_heap *neh = &si->ne_heap; struct wf2qp_queue *alg_fq; if (sch->elements == 0 && neh->elements == 0) { /* we have nothing to do. We could kill the idle heap * altogether and reset V */ - idle_check(si, 0x7fffffff); + idle_check(si, 0x7fffffff, 1); si->V = 0; si->sum = 0; /* should be set already */ return NULL; /* quick return if nothing to do */ } - idle_check(si, 1); /* drain something from the idle heap */ + idle_check(si, 1, 0); /* drain something from the idle heap */ /* make sure at least one element is eligible, bumping V * and moving entries that have become eligible */ - if (sch->elements == 0 && neh->elements > 0) + if (sch->elements == 0 && neh->elements > 0) { si->V = MAX64(si->V, HEAP_TOP(neh)->key); + } while (neh->elements > 0 && DN_KEY_LEQ(HEAP_TOP(neh)->key, si->V)) { q = HEAP_TOP(neh)->object; @@ -195,7 +196,6 @@ wf2qp_dequeue(struct new_sch_inst *_si) heap_extract(neh, NULL); heap_insert(sch, alg_fq->F, q); } - /* ok we have at least one eligible pkt */ q = HEAP_TOP(sch)->object; alg_fq = (struct wf2qp_queue *)(q + 1); @@ -203,9 +203,8 @@ wf2qp_dequeue(struct new_sch_inst *_si) heap_extract(sch, NULL); /* Remove queue from heap. */ si->V += div64(pkt->m_pkthdr.len << MY_M, si->sum); alg_fq->S = alg_fq->F; /* Update start time. */ - if (q->mq.head == 0) { /* not backlogged any more. */ - heap_insert(si->idle_heap, alg_fq->F, q); + heap_insert(&si->idle_heap, alg_fq->F, q); } else { /* Still backlogged. */ /* Update F, store in neh or sch */ uint64_t len = q->mq.head->m_pkthdr.len; @@ -225,8 +224,9 @@ wf2qp_dequeue(struct new_sch_inst *_si) * We don't need to move the queues, as it will be done at the * next enqueue */ - if (sch->elements == 0 && neh->elements > 0) + if (sch->elements == 0 && neh->elements > 0) { si->V = MAX64(si->V, HEAP_TOP(neh)->key); + } return pkt; } @@ -237,12 +237,12 @@ wf2qp_new_sched(struct new_sch_inst *_si int ofs = offsetof(struct wf2qp_queue, heap_pos); /* only idle-heap supports extract from middle */ - if (heap_init(si->idle_heap, 16, ofs) || - heap_init(si->sch_heap, 16, -1) || - heap_init(si->ne_heap, 16, -1)) { - heap_free(si->ne_heap); - heap_free(si->sch_heap); - heap_free(si->idle_heap); + if (heap_init(&si->idle_heap, 16, ofs) || + heap_init(&si->sch_heap, 16, -1) || + heap_init(&si->ne_heap, 16, -1)) { + heap_free(&si->ne_heap); + heap_free(&si->sch_heap); + heap_free(&si->idle_heap); return ENOMEM; } return 0; @@ -253,10 +253,21 @@ wf2qp_free_sched(struct new_sch_inst *_s { struct wf2qp_si *si = (struct wf2qp_si *)(_si + 1); - heap_free(si->sch_heap); - heap_free(si->ne_heap); - heap_free(si->idle_heap); + heap_free(&si->sch_heap); + heap_free(&si->ne_heap); + heap_free(&si->idle_heap); + + return 0; +} +static int +wf2qp_new_fsk(struct new_fsk *fs) +{ + printf("%s called\n", __FUNCTION__); + if (fs->fs.weight < 1) + fs->fs.weight = 1; + else if (fs->fs.weight > 100) + fs->fs.weight = 100; return 0; } @@ -303,6 +314,8 @@ static struct dn_sched wf2qp_desc = { .new_sched = wf2qp_new_sched, .free_sched = wf2qp_free_sched, + .new_fsk = wf2qp_new_fsk, + .new_queue = wf2qp_new_queue, .free_queue = wf2qp_free_queue, }; 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 18 11:33:58 2010 (r202567) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c Mon Jan 18 12:43:57 2010 (r202568) @@ -72,11 +72,11 @@ struct dn_parms dn_cfg = { .pipe_slot_limit = 100, /* Foot shooting limit for pipe queues. */ .pipe_byte_limit = 1024 * 1024, - .hash_size = 64, /* default hash size */ .red_lookup_depth = 256, /* RED - default lookup table depth */ .red_avg_pkt_size = 512, /* RED - default medium packet size */ .red_max_pkt_size = 1500, /* RED - default max packet size */ - .buckets = 16, + .max_hash_size = 1024, /* max in the hash tables */ + .hash_size = 64, /* default hash size */ }; static long tick_last; /* Last tick duration (usec). */ @@ -591,6 +591,7 @@ dummynet_io(struct mbuf **m0, int dir, s struct new_queue template; template.si = si; template.fs = fs; + /* XXX could be simplified if no flow_mask */ q = dn_ht_find(fs->qht, (uintptr_t)&(fwa->f_id), DNHT_INSERT, &template); if (q == NULL) 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 18 11:33:58 2010 (r202567) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h Mon Jan 18 12:43:57 2010 (r202568) @@ -66,6 +66,7 @@ struct dn_parms { int red_avg_pkt_size; int red_max_pkt_size; int hash_size; + int max_hash_size; long pipe_byte_limit; long pipe_slot_limit; @@ -85,7 +86,6 @@ struct dn_parms { * is programmable. fshash is looked up at every packet arrival * so better be generous if we expect many entries. */ - int buckets; /* for the hash tables below */ struct dn_ht *fshash; struct dn_ht *schedhash; /* list of flowsets without a scheduler -- use sch_chain */ Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Mon Jan 18 11:33:58 2010 (r202567) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Mon Jan 18 12:43:57 2010 (r202568) @@ -426,6 +426,8 @@ fsk_destroy(struct new_fsk *fs, int do_f h = fs->sched ? &fs->sched->fsk_list : &dn_cfg.fsu; SLIST_REMOVE(h, fs, new_fsk, sch_chain); dn_cfg.fsk_count--; + if (fs->sched && fs->sched->fp->free_fsk) + fs->sched->fp->free_fsk(fs); fs->sched = NULL; if (do_free) { if (fs->qht) @@ -739,6 +741,15 @@ config_fs(struct new_fs *nfs, struct dn_ if (nfs->qsize > dn_cfg.pipe_slot_limit) nfs->qsize = dn_cfg.pipe_slot_limit; } + if (nfs->flags & DN_HAVE_MASK) { + /* make sure we have some buckets */ + if (nfs->buckets < 1) + nfs->buckets = dn_cfg.hash_size; + else if (nfs->buckets > dn_cfg.max_hash_size) + nfs->buckets = dn_cfg.max_hash_size; + } else { + nfs->buckets = 1; /* we only need 1 */ + } if (!locked) DUMMYNET_LOCK(); again: @@ -760,6 +771,8 @@ again: fs->qht = dn_ht_init(NULL, nfs->buckets, offsetof(struct new_queue, q_next), q_hash, q_match, q_new); + if (s->fp->new_fsk) + s->fp->new_fsk(fs); } } else if (fs->sched != s) { /* scheduler changed. Let it die and recreate */ @@ -1256,10 +1269,10 @@ ip_dn_init(void) * In both we search by key and by pointer. * Insertion in schedhash uses externally allocated objects. */ - dn_cfg.schedhash = dn_ht_init(NULL, dn_cfg.buckets, + dn_cfg.schedhash = dn_ht_init(NULL, dn_cfg.hash_size, offsetof(struct new_schk, schk_next), schk_hash, schk_match, schk_new); - dn_cfg.fshash = dn_ht_init(NULL, dn_cfg.buckets, + dn_cfg.fshash = dn_ht_init(NULL, dn_cfg.hash_size, offsetof(struct new_fsk, fsk_next), fsk_hash, fsk_match, fsk_new); From owner-svn-src-user@FreeBSD.ORG Mon Jan 18 12:52:42 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 856B51065670; Mon, 18 Jan 2010 12:52:42 +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 752A18FC08; Mon, 18 Jan 2010 12:52:42 +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 o0ICqgmw067066; Mon, 18 Jan 2010 12:52:42 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0ICqg04067064; Mon, 18 Jan 2010 12:52:42 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <201001181252.o0ICqg04067064@svn.freebsd.org> From: Luigi Rizzo Date: Mon, 18 Jan 2010 12:52:42 +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: r202569 - 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: Mon, 18 Jan 2010 12:52:42 -0000 Author: luigi Date: Mon Jan 18 12:52:42 2010 New Revision: 202569 URL: http://svn.freebsd.org/changeset/base/202569 Log: small indentation fixes. Also indicate where scheduler-specific info could go in the flowset. Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h 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 18 12:43:57 2010 (r202568) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h Mon Jan 18 12:52:42 2010 (r202569) @@ -74,7 +74,7 @@ struct dn_parms { /* timekeeping */ struct timeval prev_t; /* last time dummynet_tick ran */ - struct dn_heap evheap; /* scheduled events */ + struct dn_heap evheap; /* scheduled events */ /* counters of objects -- used for reporting space */ int schk_count; @@ -124,6 +124,9 @@ struct delay_line { * When we remove a flowset, mark as DN_DELETE so it can go away * when the hash table will be empty. * XXX refcnt is redundant, the info is already in qht->entries + * If we want to add scheduler-specific parameters, we need to + * put them in external storage because the scheduler may not be + * available when the fsk is created. */ struct new_fsk { /* kernel side of a flowset */ struct new_fs fs; @@ -131,10 +134,13 @@ struct new_fsk { /* kernel side of a flo int kflags; /* kernel-side flags */ int refcnt; /* entries in qht */ - /* hash table of queues, or just our queue if we have no mask */ + /* hash table of queues. XXX if we have no flow_mask we could + * avoid the hash table and just allocate one queue. + */ 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 */ }; /* @@ -178,7 +184,6 @@ struct new_schk { /* Hash table of all instances (through sched_mask) */ struct dn_ht *siht; - }; @@ -191,25 +196,25 @@ struct new_sch_inst { struct new_inst ni; /* oid, id and stats */ SLIST_ENTRY(new_sch_inst) si_next; /* next item in the bucket */ struct delay_line dline; - struct new_schk *sched; /* the template */ + struct new_schk *sched; /* the template */ int kflags; /* DN_ACTIVE */ - int64_t credit; /* bits I can transmit (more or less). */ - dn_key sched_time ; /* time pipe was scheduled in ready_heap */ - dn_key idle_time; /* start of scheduler instance idle time */ + int64_t credit; /* bits I can transmit (more or less). */ + dn_key sched_time; /* time pipe was scheduled in ready_heap */ + dn_key idle_time; /* start of scheduler instance idle time */ }; /* kernel-side flags */ enum { - DN_DELETE = 0x0004, /* destroy when refcnt=0 */ - DN_ACTIVE = 0x0010, /* object is in evheap */ - DN_F_DLINE = 0x0020, /* object is a delay line */ - DN_F_SCHI = 0x0030, /* object is a sched.instance */ + DN_DELETE = 0x0004, /* destroy when refcnt=0 */ + DN_ACTIVE = 0x0010, /* object is in evheap */ + DN_F_DLINE = 0x0020, /* object is a delay line */ + DN_F_SCHI = 0x0030, /* object is a sched.instance */ }; extern struct dn_parms dn_cfg; -int dummynet_io(struct mbuf **, int , struct ip_fw_args *); +int dummynet_io(struct mbuf **, int , struct ip_fw_args *); void dummynet_task(void *context, int pending); void dn_reschedule(void); From owner-svn-src-user@FreeBSD.ORG Mon Jan 18 13:38:45 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 A4D281065679; Mon, 18 Jan 2010 13:38:45 +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 93F0F8FC1B; Mon, 18 Jan 2010 13:38:45 +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 o0IDcj7S077645; Mon, 18 Jan 2010 13:38:45 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0IDcjM9077643; Mon, 18 Jan 2010 13:38:45 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <201001181338.o0IDcjM9077643@svn.freebsd.org> From: Luigi Rizzo Date: Mon, 18 Jan 2010 13:38:45 +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: r202571 - 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: Mon, 18 Jan 2010 13:38:45 -0000 Author: luigi Date: Mon Jan 18 13:38:45 2010 New Revision: 202571 URL: http://svn.freebsd.org/changeset/base/202571 Log: implement scheduler destruction when queues drain; fix management of changes in flowsets' parameters. 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 Mon Jan 18 13:11:37 2010 (r202570) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Mon Jan 18 13:38:45 2010 (r202571) @@ -409,6 +409,7 @@ fsk_new(uintptr_t key, int flags, void * return fs; } +static int schk_del_cb(void *obj, void *arg); /* * delete a flowset. Mark as delete, and free all when no refcount. * Return 1 if freed, o otherwise. @@ -428,6 +429,15 @@ fsk_destroy(struct new_fsk *fs, int do_f dn_cfg.fsk_count--; if (fs->sched && fs->sched->fp->free_fsk) fs->sched->fp->free_fsk(fs); + /* XXX possibly notify the event to the scheduler */ + if (fs->sched != NULL && (fs->sched->kflags & DN_DELETE) && + SLIST_FIRST(&fs->sched->fsk_list) == NULL) { + printf("scheduler %p should be deleted\n", fs->sched); + dn_ht_find(dn_cfg.schedhash, (uintptr_t)(fs->sched), + DNHT_KEY_IS_OBJ | DNHT_MATCH_PTR | DNHT_REMOVE, NULL); + schk_del_cb(fs->sched, NULL); + } + fs->sched = NULL; if (do_free) { if (fs->qht) @@ -757,28 +767,36 @@ again: if (fs == NULL) goto done; dn_cfg.id++; + if (bcmp(&fs->fs, nfs, sizeof(*nfs)) == 0) + goto done; /* no change, nothing to do */ fs->fs = *nfs; /* update config */ + /* + * XXX note that if we modify some scheduler-specific parameter, + * such as weights, we must notify the scheduler otherwise things + * might go really badly, such as sum-of-weights mismatches. + */ s = locate_scheduler(nfs->sched_nr); - if (fs->sched == NULL) { /* no scheduler before */ - if (s) { - /* have a new scheduler, remove from unlinked - * and add to the list of children of s - */ - SLIST_REMOVE(&dn_cfg.fsu, fs, new_fsk, sch_chain); - fs->sched = s; - SLIST_INSERT_HEAD(&s->fsk_list, fs, sch_chain); - if (s->fp->flags & DN_MULTIQUEUE) - fs->qht = dn_ht_init(NULL, nfs->buckets, - offsetof(struct new_queue, q_next), - q_hash, q_match, q_new); - if (s->fp->new_fsk) - s->fp->new_fsk(fs); - } - } else if (fs->sched != s) { - /* scheduler changed. Let it die and recreate */ + if (fs->sched != NULL) { + /* we had a scheduler before, let the flowset die + * and create a new one with the new parameters. + */ fs->kflags |= DN_DELETE; goto again; } + if (s) { + /* have a new scheduler, remove from unlinked + * and add to the list of children of s + */ + SLIST_REMOVE(&dn_cfg.fsu, fs, new_fsk, sch_chain); + fs->sched = s; + SLIST_INSERT_HEAD(&s->fsk_list, fs, sch_chain); + if (s->fp->flags & DN_MULTIQUEUE) + fs->qht = dn_ht_init(NULL, nfs->buckets, + offsetof(struct new_queue, q_next), + q_hash, q_match, q_new); + if (s->fp->new_fsk) + s->fp->new_fsk(fs); + } done: if (!locked) DUMMYNET_UNLOCK(); @@ -794,6 +812,7 @@ config_sched(struct new_sch *nsch, struc { struct new_schk *s; struct dn_sched *fp; + struct new_fsk_head *pending = NULL; int i, notify_fs = 0; if (nsch->oid.len != sizeof(*nsch)) { @@ -831,9 +850,16 @@ again: /* run twice, for wfq and fifo */ /* mark delete so it won't be matched. * XXX todo: make it die when its queues are done. * XXX otherwise do a real delete. + * XXX MISSING: + * The flowsets are still linked to the old scheduler. + * we should clone the flowsets, put them in the + * fsunlinked list, and mark the old flowsets as DELETE, + * so they die as the queues drain out. We must postpone + * the cloning to after the new scheduler has been created. */ - s->kflags = DN_DELETE; + s->kflags |= DN_DELETE; notify_fs = 1; + pending = &s->fsk_list; goto again; } /* complete initialization */ @@ -856,6 +882,17 @@ again: /* run twice, for wfq and fifo */ /* call init function after the flowset is created */ if (s->fp->config) s->fp->config(s, 1); + if (pending) { + struct new_fsk *fs; + /* mark and clone flowsets for the old scheduler */ + SLIST_FOREACH(fs, pending, sch_chain) { + int dying = fs->kflags & DN_DELETE; + fs->kflags |= DN_DELETE; + if (!dying) /* clone if necessary */ + config_fs(&fs->fs, NULL, 1 /* locked */); + } + pending = NULL; + } if (notify_fs) update_fs(s); if (i < DN_MAX_ID) { /* update the FIFO instance */ From owner-svn-src-user@FreeBSD.ORG Mon Jan 18 14:31:10 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 BEA37106566B; Mon, 18 Jan 2010 14:31:10 +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 ADCAA8FC19; Mon, 18 Jan 2010 14:31:10 +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 o0IEVADs089627; Mon, 18 Jan 2010 14:31:10 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0IEVAes089625; Mon, 18 Jan 2010 14:31:10 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <201001181431.o0IEVAes089625@svn.freebsd.org> From: Luigi Rizzo Date: Mon, 18 Jan 2010 14:31:10 +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: r202574 - 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: Mon, 18 Jan 2010 14:31:10 -0000 Author: luigi Date: Mon Jan 18 14:31:10 2010 New Revision: 202574 URL: http://svn.freebsd.org/changeset/base/202574 Log: remove testing code Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.c Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.c Mon Jan 18 14:07:41 2010 (r202573) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.c Mon Jan 18 14:31:10 2010 (r202574) @@ -449,128 +449,3 @@ dn_ht_scan(struct dn_ht *ht, int (*fn)(v } return found; } - -#ifndef _KERNEL -/* - * testing code for the heap and hash table - */ -#include - -struct x { - struct x *ht_link; - char buf[0]; -}; - -int hf(uintptr_t key, int flags, void *arg) -{ - return (flags & DNHT_KEY_IS_OBJ) ? - ((struct x *)key)->buf[0] : *(char *)key; -} - -int matchf(void *obj, uintptr_t key, int flags, void *arg) -{ - char *s = (flags & DNHT_KEY_IS_OBJ) ? - ((struct x *)key)->buf : (char *)key; - return (strcmp(((struct x *)obj)->buf, s) == 0); -} - -void *newfn(uintptr_t key, int flags, void *arg) -{ - char *s = (char *)key; - struct x *p = malloc(sizeof(*p) + 1 + strlen(s), M_DN_HEAP, 0); - if (p) - strcpy(p->buf, s); - return p; -} - -char *strings[] = { - "undici", "unico", "doppio", "devoto", - "uno", "due", "tre", "quattro", "cinque", "sei", - "uno", "due", "tre", "quattro", "cinque", "sei", - NULL, -}; - -int doprint(void *_x, void *arg) -{ - struct x *x = _x; - printf("found element <%s>\n", x->buf); - return (int)arg; -} - -static void -test_hash() -{ - char **p; - struct dn_ht *h; - uintptr_t x = 0; - uintptr_t x1 = 0; - - /* first, find and allocate */ - h = dn_ht_init(NULL, 10, 0, hf, matchf, newfn, 0); - - for (p = strings; *p; p++) { - dn_ht_find(h, (uintptr_t)*p, DNHT_INSERT); - } - dn_ht_scan(h, doprint, 0); - printf("/* second -- find without allocate */\n"); - h = dn_ht_init(NULL, 10, 0, hf, matchf, NULL, 0); - for (p = strings; *p; p++) { - void **y = newfn((uintptr_t)*p, 0, NULL); - if (x == 0) - x = (uintptr_t)y; - else { - if (x1 == 0) - x1 = (uintptr_t)*p; - } - dn_ht_find(h, (uintptr_t)y, DNHT_INSERT | DNHT_KEY_IS_OBJ); - } - dn_ht_scan(h, doprint, 0); - printf("remove %p gives %p\n", (void *)x, - dn_ht_find(h, x, DNHT_KEY_IS_OBJ | DNHT_REMOVE)); - printf("remove %p gives %p\n", (void *)x, - dn_ht_find(h, x, DNHT_KEY_IS_OBJ | DNHT_REMOVE)); - printf("remove %p gives %p\n", (void *)x, - dn_ht_find(h, x1, DNHT_REMOVE)); - printf("remove %p gives %p\n", (void *)x, - dn_ht_find(h, x1, DNHT_REMOVE)); - dn_ht_scan(h, doprint, 0); -} - -int -main(int argc, char *argv[]) -{ - struct dn_heap h; - int i, n, n2, n3; - - test_hash(); - return 0; - - /* n = elements, n2 = cycles */ - n = (argc > 1) ? atoi(argv[1]) : 0; - if (n <= 0 || n > 1000000) - n = 100; - n2 = (argc > 2) ? atoi(argv[2]) : 0; - if (n2 <= 0) - n = 1000000; - n3 = (argc > 3) ? atoi(argv[3]) : 0; - bzero(&h, sizeof(h)); - heap_init(&h, n, -1); - while (n2-- > 0) { - uint64_t prevk = 0; - for (i=0; i < n; i++) - heap_insert(&h, n3 ? n-i: random(), (void *)(100+i)); - - for (i=0; h.elements > 0; i++) { - uint64_t k = h.p[0].key; - if (k < prevk) - panic("wrong sequence\n"); - prevk = k; - if (0) - printf("%d key %llu, val %p\n", - i, h.p[0].key, h.p[0].object); - heap_extract(&h, NULL); - } - } - return 0; -} -#endif From owner-svn-src-user@FreeBSD.ORG Mon Jan 18 14:32:38 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 B3C641065693; Mon, 18 Jan 2010 14:32:38 +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 A225B8FC22; Mon, 18 Jan 2010 14:32:38 +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 o0IEWcdQ089991; Mon, 18 Jan 2010 14:32:38 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0IEWca2089987; Mon, 18 Jan 2010 14:32:38 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <201001181432.o0IEWca2089987@svn.freebsd.org> From: Luigi Rizzo Date: Mon, 18 Jan 2010 14:32:38 +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: r202575 - 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: Mon, 18 Jan 2010 14:32:38 -0000 Author: luigi Date: Mon Jan 18 14:32:38 2010 New Revision: 202575 URL: http://svn.freebsd.org/changeset/base/202575 Log: add files for userland testing Added: user/luigi/ipfw3-head/sys/netinet/ipfw/Makefile user/luigi/ipfw3-head/sys/netinet/ipfw/dn_test.h user/luigi/ipfw3-head/sys/netinet/ipfw/test_dn_heap.c user/luigi/ipfw3-head/sys/netinet/ipfw/test_dn_sched.c Added: user/luigi/ipfw3-head/sys/netinet/ipfw/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/Makefile Mon Jan 18 14:32:38 2010 (r202575) @@ -0,0 +1,23 @@ +# Makefile for building userland tests + +SCHED_SRCS = test_dn_sched.c +SCHED_SRCS += dn_sched_fifo.c + +SCHED_OBJS=$(SCHED_SRCS:.c=.o) + +HEAP_SRCS = dn_heap.c test_dn_heap.c +HEAP_OBJS=$(HEAP_SRCS:.c=.o) + +CFLAGS = -I../../ -Wall -Werror -O2 +TARGETS= test_heap test_sched + +all: $(TARGETS) + +test_heap : $(HEAP_OBJS) + $(CC) -o $@ $> + +test_sched : $(SCHED_OBJS) + $(CC) -o $@ $> + +clean: + - rm *.o $(TARGETS) *.core Added: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_test.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_test.h Mon Jan 18 14:32:38 2010 (r202575) @@ -0,0 +1,38 @@ +/* + * Header for testing kernel stuff in userland + */ + +#ifndef _DN_TEST_H +#define _DN_TEST_H +#include +#include +#include +#include +#include + +#define MALLOC_DECLARE(x) +#define KASSERT(x, y) do { if (!(x)) printf y ; exit(0); } while (0) +struct ipfw_flow_id { +}; + +struct ip_fw_args { +}; + +struct mbuf { + struct { + int len; + } m_pkthdr; + struct mbuf *m_nextpkt; +}; +typedef void * module_t; +struct _md_t { + const char *name; + int (*f)(module_t, int, void *); + void *p; +}; +typedef struct _md_t moduledata_t; +#define DECLARE_MODULE(name, b, c, d) \ + moduledata_t *_g_##name = & name##_mod +#define MODULE_DEPEND(a, b, c, d, e) + +#endif /* _DN_TEST_H */ Added: user/luigi/ipfw3-head/sys/netinet/ipfw/test_dn_heap.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/test_dn_heap.c Mon Jan 18 14:32:38 2010 (r202575) @@ -0,0 +1,160 @@ +/*- + * Copyright (c) 1998-2002,2010 Luigi Rizzo, Universita` di Pisa + * All rights reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Userland code for testing heap and hash tables + */ + +#include +#include + +#include +#include +#include + +#include "dn_heap.h" +#define log(x, arg...) fprintf(stderr, ## arg) +#define panic(x...) fprintf(stderr, ## x), exit(1) + +#include + +struct x { + struct x *ht_link; + char buf[0]; +}; + +int hf(uintptr_t key, int flags, void *arg) +{ + return (flags & DNHT_KEY_IS_OBJ) ? + ((struct x *)key)->buf[0] : *(char *)key; +} + +int matchf(void *obj, uintptr_t key, int flags, void *arg) +{ + char *s = (flags & DNHT_KEY_IS_OBJ) ? + ((struct x *)key)->buf : (char *)key; + return (strcmp(((struct x *)obj)->buf, s) == 0); +} + +void *newfn(uintptr_t key, int flags, void *arg) +{ + char *s = (char *)key; + struct x *p = malloc(sizeof(*p) + 1 + strlen(s)); + if (p) + strcpy(p->buf, s); + return p; +} + +char *strings[] = { + "undici", "unico", "doppio", "devoto", + "uno", "due", "tre", "quattro", "cinque", "sei", + "uno", "due", "tre", "quattro", "cinque", "sei", + NULL, +}; + +int doprint(void *_x, void *arg) +{ + struct x *x = _x; + printf("found element <%s>\n", x->buf); + return (int)arg; +} + +static void +test_hash() +{ + char **p; + struct dn_ht *h; + uintptr_t x = 0; + uintptr_t x1 = 0; + + /* first, find and allocate */ + h = dn_ht_init(NULL, 10, 0, hf, matchf, newfn); + + for (p = strings; *p; p++) { + dn_ht_find(h, (uintptr_t)*p, DNHT_INSERT, NULL); + } + dn_ht_scan(h, doprint, 0); + printf("/* second -- find without allocate */\n"); + h = dn_ht_init(NULL, 10, 0, hf, matchf, NULL); + for (p = strings; *p; p++) { + void **y = newfn((uintptr_t)*p, 0, NULL); + if (x == 0) + x = (uintptr_t)y; + else { + if (x1 == 0) + x1 = (uintptr_t)*p; + } + dn_ht_find(h, (uintptr_t)y, DNHT_INSERT | DNHT_KEY_IS_OBJ, NULL); + } + dn_ht_scan(h, doprint, 0); + printf("remove %p gives %p\n", (void *)x, + dn_ht_find(h, x, DNHT_KEY_IS_OBJ | DNHT_REMOVE, NULL)); + printf("remove %p gives %p\n", (void *)x, + dn_ht_find(h, x, DNHT_KEY_IS_OBJ | DNHT_REMOVE, NULL)); + printf("remove %p gives %p\n", (void *)x, + dn_ht_find(h, x1, DNHT_REMOVE, NULL)); + printf("remove %p gives %p\n", (void *)x, + dn_ht_find(h, x1, DNHT_REMOVE, NULL)); + dn_ht_scan(h, doprint, 0); +} + +int +main(int argc, char *argv[]) +{ + struct dn_heap h; + int i, n, n2, n3; + + test_hash(); + return 0; + + /* n = elements, n2 = cycles */ + n = (argc > 1) ? atoi(argv[1]) : 0; + if (n <= 0 || n > 1000000) + n = 100; + n2 = (argc > 2) ? atoi(argv[2]) : 0; + if (n2 <= 0) + n = 1000000; + n3 = (argc > 3) ? atoi(argv[3]) : 0; + bzero(&h, sizeof(h)); + heap_init(&h, n, -1); + while (n2-- > 0) { + uint64_t prevk = 0; + for (i=0; i < n; i++) + heap_insert(&h, n3 ? n-i: random(), (void *)(100+i)); + + for (i=0; h.elements > 0; i++) { + uint64_t k = h.p[0].key; + if (k < prevk) + panic("wrong sequence\n"); + prevk = k; + if (0) + printf("%d key %llu, val %p\n", + i, h.p[0].key, h.p[0].object); + heap_extract(&h, NULL); + } + } + return 0; +} Added: user/luigi/ipfw3-head/sys/netinet/ipfw/test_dn_sched.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/test_dn_sched.c Mon Jan 18 14:32:38 2010 (r202575) @@ -0,0 +1,107 @@ +/* + * $FreeBSD + */ + +#include "dn_test.h" +#include +#include +#include +#include + +int io_pkt_drop; + +void +m_freem(struct mbuf *m) +{ + free(m); +} + +int +dn_sched_modevent(module_t mod, int cmd, void *arg) +{ + return 0; +} + +void +dn_free_pkts(struct mbuf *m) +{ + struct mbuf *x; + while ( (x = m) ) { + m = m->m_nextpkt; + m_freem(x); + } +} + +static inline void +mq_append(struct mq *q, struct mbuf *m) +{ + if (q->head == NULL) + q->head = m; + else + q->tail->m_nextpkt = m; + q->tail = m; + m->m_nextpkt = NULL; +} + +int +dn_delete_queue(void *_q, void *do_free) +{ + struct new_queue *q = _q; + if (q->mq.head) + dn_free_pkts(q->mq.head); + free(q); + return 0; +} + +/* + * 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. + * Return 0 on success, 1 on drop. The packet is consumed anyways. + */ +int +dn_enqueue(struct new_queue *q, struct mbuf* m, int drop) +{ + struct new_fs *f; + struct new_inst *ni; /* stats for scheduler instance */ + uint64_t len; + + f = &q->fs->fs; + ni = &q->ni; + len = m->m_pkthdr.len; + /* Update statistics, then check reasons to drop pkt. */ + q->ni.tot_bytes += len; + q->ni.tot_pkts++; + ni->tot_bytes += len; + ni->tot_pkts++; + if (drop) + goto drop; + if (f->plr && random() < f->plr) + goto drop; + if (f->flags & DN_QSIZE_BYTES) { + if (q->ni.len_bytes > f->qsize) + goto drop; + } else if (q->ni.length >= f->qsize) { + goto drop; + } + mq_append(&q->mq, m); + q->ni.length++; + q->ni.len_bytes += len; + ni->length++; + ni->len_bytes += len; + return 0; + +drop: + io_pkt_drop++; + q->ni.drops++; + ni->drops++; + FREE_PKT(m); + return 1; +} + +int +main(int argc, char *argv[]) +{ + printf("test code for the schedulers\n"); + return 0; +} From owner-svn-src-user@FreeBSD.ORG Mon Jan 18 14:51: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 405D910656A8; Mon, 18 Jan 2010 14:51:01 +0000 (UTC) (envelope-from ed@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 182988FC18; Mon, 18 Jan 2010 14:51: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 o0IEp0Kc094161; Mon, 18 Jan 2010 14:51:01 GMT (envelope-from ed@svn.freebsd.org) Received: (from ed@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0IEp0cG094159; Mon, 18 Jan 2010 14:51:00 GMT (envelope-from ed@svn.freebsd.org) Message-Id: <201001181451.o0IEp0cG094159@svn.freebsd.org> From: Ed Schouten Date: Mon, 18 Jan 2010 14:51:00 +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: r202577 - user/ed/newcons/sys/kern 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: Mon, 18 Jan 2010 14:51:01 -0000 Author: ed Date: Mon Jan 18 14:51:00 2010 New Revision: 202577 URL: http://svn.freebsd.org/changeset/base/202577 Log: Perform a forced commit to see whether I can perform forced commits. Modified: user/ed/newcons/sys/kern/subr_terminal.c Modified: user/ed/newcons/sys/kern/subr_terminal.c ============================================================================== From owner-svn-src-user@FreeBSD.ORG Mon Jan 18 21:00:29 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 CFF991065670; Mon, 18 Jan 2010 21:00:29 +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 C07FC8FC43; Mon, 18 Jan 2010 21:00:29 +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 o0IL0TmQ076492; Mon, 18 Jan 2010 21:00:29 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0IL0TBi076490; Mon, 18 Jan 2010 21:00:29 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <201001182100.o0IL0TBi076490@svn.freebsd.org> From: Luigi Rizzo Date: Mon, 18 Jan 2010 21:00:29 +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: r202590 - 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: Mon, 18 Jan 2010 21:00:29 -0000 Author: luigi Date: Mon Jan 18 21:00:29 2010 New Revision: 202590 URL: http://svn.freebsd.org/changeset/base/202590 Log: it is correct to call dn_dequeue on an empty queue Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h Mon Jan 18 20:57:50 2010 (r202589) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h Mon Jan 18 21:00:29 2010 (r202590) @@ -131,7 +131,8 @@ static __inline struct mbuf* dn_dequeue(struct new_queue *q) { struct mbuf *m = q->mq.head; - KASSERT(m != NULL, ("empty queue to dn_return_packet")); + if (m == NULL) + return NULL; q->mq.head = m->m_nextpkt; q->ni.length--; q->ni.len_bytes -= m->m_pkthdr.len; From owner-svn-src-user@FreeBSD.ORG Mon Jan 18 22:39:33 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 CFEFE106568F; Mon, 18 Jan 2010 22:39:33 +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 BF0528FC13; Mon, 18 Jan 2010 22:39:33 +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 o0IMdXof098784; Mon, 18 Jan 2010 22:39:33 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0IMdXna098776; Mon, 18 Jan 2010 22:39:33 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <201001182239.o0IMdXna098776@svn.freebsd.org> From: Luigi Rizzo Date: Mon, 18 Jan 2010 22:39:33 +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: r202597 - 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: Mon, 18 Jan 2010 22:39:33 -0000 Author: luigi Date: Mon Jan 18 22:39:33 2010 New Revision: 202597 URL: http://svn.freebsd.org/changeset/base/202597 Log: various formatting fixes Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.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_wf2q.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/sys/netinet/ipfw/dn_heap.h ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.h Mon Jan 18 21:56:08 2010 (r202596) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.h Mon Jan 18 22:39:33 2010 (r202597) @@ -141,7 +141,8 @@ int heap_scan(struct dn_heap *, int (*)( * * DNHT_MATCH_PTR during a lookup, match pointers instead * of calling match(). Normally used when removing specific - * entries. XXX should it imply DNHT_KEY_IS_OBJ ? + * entries. Does not imply KEY_IS_OBJ as the latter _is_ used + * by the match function. * * DNHT_INSERT insert the element if not found. * Calls new() to allocates a new object unless Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h Mon Jan 18 21:56:08 2010 (r202596) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h Mon Jan 18 22:39:33 2010 (r202597) @@ -53,14 +53,14 @@ struct dn_sched { /* + parameters attached to the template, e.g. * default queue sizes, weights, quantum size, and so on; */ - size_t schk_len; + size_t schk_datalen; /* + per-instance parameters, such as timestamps, * containers for queues, etc; */ - size_t sch_inst_len; + size_t si_datalen; - size_t queue_len; /* per-queue parameters (e.g. S,F) */ + size_t q_datalen; /* per-queue parameters (e.g. S,F) */ SLIST_ENTRY(dn_sched) next; /* Next scheduler in the list */ 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 18 21:56:08 2010 (r202596) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_fifo.c Mon Jan 18 22:39:33 2010 (r202597) @@ -84,7 +84,7 @@ static struct dn_sched fifo_desc = { .type = DN_SCHED_FIFO, .name = "FIFO", - .sch_inst_len = sizeof(struct new_queue), + .si_datalen = sizeof(struct new_queue), .enqueue = fifo_enqueue, .dequeue = fifo_dequeue, Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c Mon Jan 18 21:56:08 2010 (r202596) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c Mon Jan 18 22:39:33 2010 (r202597) @@ -305,8 +305,8 @@ static struct dn_sched wf2qp_desc = { .name = "WF2Q+", .flags = DN_MULTIQUEUE, - .sch_inst_len = sizeof(struct wf2qp_si), - .queue_len = sizeof(struct wf2qp_queue), + .si_datalen = sizeof(struct wf2qp_si), + .q_datalen = sizeof(struct wf2qp_queue), .enqueue = wf2qp_enqueue, .dequeue = wf2qp_dequeue, 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 18 21:56:08 2010 (r202596) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c Mon Jan 18 22:39:33 2010 (r202597) @@ -576,7 +576,7 @@ dummynet_io(struct mbuf **m0, int dir, s goto dropit; /* This queue/pipe does not exist! */ if (fs->sched == NULL) /* should not happen */ goto dropit; - /* dn_si_find can be fast */ + /* find scheduler instance, possibly applying mask */ si = ipdn_si_find(fs->sched, &(fwa->f_id)); if (si == NULL) goto dropit; @@ -591,13 +591,16 @@ dummynet_io(struct mbuf **m0, int dir, s struct new_queue template; template.si = si; template.fs = fs; - /* XXX could be simplified if no flow_mask */ - q = dn_ht_find(fs->qht, (uintptr_t)&(fwa->f_id), - DNHT_INSERT, &template); + if (fs->fs.flags & DN_HAVE_MASK) { + q = dn_ht_find(fs->qht, (uintptr_t)&(fwa->f_id), + DNHT_INSERT, &template); + } else { /* qht is simply a queue */ + if (fs->qht == NULL) + fs->qht = q_new(0, 0, &template); + q = (struct new_queue *)fs->qht; + } if (q == NULL) goto dropit; - } else { - q = NULL; } if (fs->sched->fp->enqueue(si, q, m)) { printf("%s dropped by enqueue\n", __FUNCTION__); 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 18 21:56:08 2010 (r202596) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h Mon Jan 18 22:39:33 2010 (r202597) @@ -219,5 +219,7 @@ void dummynet_task(void *context, int pe void dn_reschedule(void); struct new_sch_inst *ipdn_si_find(struct new_schk *s, struct ipfw_flow_id *id); +void * q_new(uintptr_t key, int flags, void *arg); + #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 Mon Jan 18 21:56:08 2010 (r202596) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Mon Jan 18 22:39:33 2010 (r202597) @@ -65,6 +65,12 @@ __FBSDID("$FreeBSD$"); #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 new_sch *sch; +}; + /*---- callout hooks. ----*/ static struct callout dn_timeout; static struct task dn_task; @@ -98,9 +104,8 @@ find_sched_type(int type, char *name) } /* - * Dispose a list of packet. Use an inline functions so if we - * need to free extra state associated to a packet, this is a - * central point to do it. + * Dispose a list of packet. Use a functions so if we need to do + * more work, this is a central point to do it. */ static void dn_free_pkts(struct mbuf *mnext) { @@ -130,7 +135,6 @@ flow_id_mask(struct ipfw_flow_id *mask, id->dst_ip &= mask->dst_ip; id->src_ip &= mask->src_ip; } - return id; } @@ -226,13 +230,12 @@ q_match(void *obj, uintptr_t key, int fl /* * create a new queue instance for the given 'key'. */ -static void * +void * q_new(uintptr_t key, int flags, void *arg) { - struct ipfw_flow_id *id = (struct ipfw_flow_id *)key; struct new_queue *q, *template = arg; struct new_fsk *fs = template->fs; - int size = sizeof(*q) + fs->sched->fp->queue_len; + int size = sizeof(*q) + fs->sched->fp->q_datalen; q = malloc(size, M_DUMMYNET, M_NOWAIT | M_ZERO); if (q == NULL) { @@ -241,7 +244,8 @@ q_new(uintptr_t key, int flags, void *ar } set_oid(&q->ni.oid, DN_QUEUE, size); - q->ni.id = *id; + if (fs->fs.flags & DN_HAVE_MASK) + q->ni.id = *(struct ipfw_flow_id *)key; q->fs = fs; q->si = template->si; fs->refcnt++; @@ -288,24 +292,22 @@ si_new(uintptr_t key, int flags, void *a { struct new_schk *s = arg; struct new_sch_inst *si; - int l = sizeof(*si) + s->fp->sch_inst_len; + int l = sizeof(*si) + s->fp->si_datalen; si = malloc(l, M_DUMMYNET, M_NOWAIT | M_ZERO); if (si == NULL) goto error; - /* XXX note we set the length only for the initial part which - * is passed up to userland. - */ + /* 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)); - si->ni.oid.id = si->dline.oid.id = -1; /* mark outside scheduler */ + /* mark si and dline as outside the event queue */ + si->ni.oid.id = si->dline.oid.id = -1; si->sched = s; si->dline.si = si; if (s->fp->new_sched) { - int ret; - ret = s->fp->new_sched(si); + int ret = s->fp->new_sched(si); if (ret) { printf("%s: new_sched error %d\n", __FUNCTION__, ret); goto error; @@ -389,7 +391,7 @@ static int fsk_match(void *obj, uintptr_t key, int flags, void *arg) { struct new_fsk *fs = obj; - int i = ((flags & DNHT_KEY_IS_OBJ) == 0) ? key : + int i = !(flags & DNHT_KEY_IS_OBJ) ? key : ((struct new_fsk *)key)->fs.fs_nr; return !(fs->kflags & DN_DELETE) && (fs->fs.fs_nr == i); @@ -440,7 +442,7 @@ fsk_destroy(struct new_fsk *fs, int do_f fs->sched = NULL; if (do_free) { - if (fs->qht) + if (fs->qht) /* only if DN_HAVE_MASK */ dn_ht_free(fs->qht, 0); free(fs, M_DUMMYNET); } @@ -448,6 +450,20 @@ fsk_destroy(struct new_fsk *fs, int do_f /*----- end of flowset hashtable support -------------*/ /* + * delete the queues in qht, consider the presence of a flow_mask + */ +static void +delete_qht(struct new_fsk *fs) +{ + if (fs->fs.flags & DN_HAVE_MASK) + dn_ht_scan(fs->qht, dn_delete_queue, NULL); + else { + dn_delete_queue(fs->qht, NULL); + fs->qht = NULL; + } +} + +/* * Destroy all flowsets in a list. Used when deleting a scheduler, * or for all those in fsunlinked. * For 'ipfw queue flush' we need a callback. @@ -473,8 +489,7 @@ fsk_destroy_list(struct new_fsk_head *h, * If the flowset was marked delete, destroy it. * otherwise move it to fsunlinked. */ - if (fs->qht) - dn_ht_scan(fs->qht, dn_delete_queue, NULL); + delete_qht(fs); fs->sched = NULL; if (fs->kflags & DN_DELETE) { if (fs->qht) @@ -521,9 +536,9 @@ reset_credit(void *_si, void *arg) static void schk_reset_credit(struct new_schk *s) { - if (s->sch.flags & DN_HAVE_MASK) { + if (s->sch.flags & DN_HAVE_MASK) dn_ht_scan(s->siht, reset_credit, NULL); - } else if (s->siht) + else if (s->siht) reset_credit(s->siht, NULL); } @@ -585,9 +600,8 @@ copy_data_helper(void *_o, void *_arg) } /* - * callback for sched delete. - * Tell all attached flowsets to remove their queues, - * unlink the flowsets. + * Callback for sched delete. Tell all attached flowsets to + * remove their queues, unlink the flowsets. */ static int schk_del_cb(void *obj, void *arg) @@ -681,7 +695,6 @@ update_fs(struct new_schk *s) static int config_pipe(struct new_pipe *p, struct dn_id *arg) { - struct new_schk *s; int i; if (p->oid.len < sizeof(*p)) { @@ -703,21 +716,19 @@ config_pipe(struct new_pipe *p, struct d p->burst *= 8 * hz; DUMMYNET_LOCK(); - again: - s = locate_scheduler(i); - if (s == NULL) { + /* do it twice, base pipe and FIFO pipe */ + for (; i < 2*DN_MAX_ID; i += DN_MAX_ID) { + struct new_schk *s = locate_scheduler(i); + if (s == NULL) { DUMMYNET_UNLOCK(); printf("%s sched %d not found\n", __FUNCTION__, i); return EINVAL; - } - /* copy all parameters */ - s->pipe.delay = p->delay; - s->pipe.bandwidth = p->bandwidth; - s->pipe.burst = p->burst; - schk_reset_credit(s); - if (i < DN_MAX_ID) { /* repeat for the FIFO pipe */ - i += DN_MAX_ID; - goto again; + } + /* copy all parameters */ + s->pipe.delay = p->delay; + s->pipe.bandwidth = p->bandwidth; + s->pipe.burst = p->burst; + schk_reset_credit(s); } dn_cfg.id++; DUMMYNET_UNLOCK(); @@ -762,42 +773,49 @@ config_fs(struct new_fs *nfs, struct dn_ } if (!locked) DUMMYNET_LOCK(); -again: - fs = dn_ht_find(dn_cfg.fshash, i, DNHT_INSERT, NULL); - if (fs == NULL) - goto done; - dn_cfg.id++; - if (bcmp(&fs->fs, nfs, sizeof(*nfs)) == 0) - goto done; /* no change, nothing to do */ - fs->fs = *nfs; /* update config */ - /* - * XXX note that if we modify some scheduler-specific parameter, - * such as weights, we must notify the scheduler otherwise things - * might go really badly, such as sum-of-weights mismatches. - */ - s = locate_scheduler(nfs->sched_nr); - if (fs->sched != NULL) { - /* we had a scheduler before, let the flowset die - * and create a new one with the new parameters. + do { /* exit with break when done */ + fs = dn_ht_find(dn_cfg.fshash, i, DNHT_INSERT, NULL); + if (fs == NULL) + break; + dn_cfg.id++; + if (bcmp(&fs->fs, nfs, sizeof(*nfs)) == 0) + break; /* no change, nothing to do */ + fs->fs = *nfs; /* update config */ + /* + * XXX note that if we modify some scheduler-specific + * parameter, e.g. weights, we must notify the + * scheduler otherwise things might go really badly, + * such as sum-of-weights mismatches. */ - fs->kflags |= DN_DELETE; - goto again; - } - if (s) { + s = locate_scheduler(nfs->sched_nr); + if (fs->sched != NULL) { + /* we had a scheduler before, let the flowset + * die and create a new one with the new + * parameters. + */ + fs->kflags |= DN_DELETE; + continue; + } + if (s == NULL) + break; + /* have a new scheduler, remove from unlinked * and add to the list of children of s */ SLIST_REMOVE(&dn_cfg.fsu, fs, new_fsk, sch_chain); fs->sched = s; SLIST_INSERT_HEAD(&s->fsk_list, fs, sch_chain); - if (s->fp->flags & DN_MULTIQUEUE) + /* only create the hash table if the scheduler supports + * multiple queues and we have a flow mask. + */ + if (s->fp->flags & DN_MULTIQUEUE && + fs->fs.flags & DN_HAVE_MASK) fs->qht = dn_ht_init(NULL, nfs->buckets, - offsetof(struct new_queue, q_next), - q_hash, q_match, q_new); + offsetof(struct new_queue, q_next), + q_hash, q_match, q_new); if (s->fp->new_fsk) s->fp->new_fsk(fs); - } -done: + } while (0); if (!locked) DUMMYNET_UNLOCK(); return fs; @@ -808,32 +826,33 @@ done: * For !MULTIQUEUE schedulers, also set up the flowset. */ static int -config_sched(struct new_sch *nsch, struct dn_id *arg) +config_sched(struct new_sch *_nsch, struct dn_id *arg) { struct new_schk *s; - struct dn_sched *fp; + struct schk_new_arg a; /* argument for schk_new */ struct new_fsk_head *pending = NULL; int i, notify_fs = 0; - if (nsch->oid.len != sizeof(*nsch)) { + a.sch = _nsch; + if (a.sch->oid.len != sizeof(*a.sch)) { printf("%s: bad sched len\n", __FUNCTION__); return EINVAL; } - i = nsch->sched_nr; + i = a.sch->sched_nr; if (i <= 0 || i >= DN_MAX_ID) return EINVAL; /* XXX other sanity checks */ DUMMYNET_LOCK(); again: /* run twice, for wfq and fifo */ - fp = find_sched_type(nsch->oid.subtype, nsch->type); - if (fp == NULL) { + a.fp = find_sched_type(a.sch->oid.subtype, a.sch->type); + if (a.fp == NULL) { DUMMYNET_UNLOCK(); - printf("invalid scheduler type %d\n", nsch->oid.subtype); + printf("invalid scheduler type %s %d\n", + a.sch->type, a.sch->oid.subtype); return EINVAL; } - nsch->oid.subtype = fp->type; - s = dn_ht_find(dn_cfg.schedhash, (uintptr_t)nsch, - DNHT_KEY_IS_OBJ | DNHT_INSERT, fp); + a.sch->oid.subtype = a.fp->type; + s = dn_ht_find(dn_cfg.schedhash, i, DNHT_INSERT, &a); if (s == NULL) { DUMMYNET_UNLOCK(); printf("cannot allocate scheduler\n"); @@ -843,19 +862,17 @@ again: /* run twice, for wfq and fifo */ notify_fs = 0; if (s->fp == NULL) { /* new scheduler, nothing to clean up */ notify_fs = 1; - } else if (s->fp != fp) { + } else if (s->fp != a.fp) { printf("sched %d type changed from %s to %s" " let it drain and reallocate\n", - i, s->fp->name, fp->name); + i, s->fp->name, a.fp->name); /* mark delete so it won't be matched. * XXX todo: make it die when its queues are done. * XXX otherwise do a real delete. - * XXX MISSING: - * The flowsets are still linked to the old scheduler. - * we should clone the flowsets, put them in the - * fsunlinked list, and mark the old flowsets as DELETE, - * so they die as the queues drain out. We must postpone - * the cloning to after the new scheduler has been created. + * XXX Reconfiguration should be done differently, + * removing packets from the old scheduler and + * requeueing to the new one. Otherwise we can have + * reordering and unwanted effects. */ s->kflags |= DN_DELETE; notify_fs = 1; @@ -863,7 +880,7 @@ again: /* run twice, for wfq and fifo */ goto again; } /* complete initialization */ - s->fp = fp; + s->fp = a.fp; s->cfg = arg; // XXX schk_reset_credit(s); /* create the internal flowset if needed */ @@ -884,6 +901,7 @@ again: /* run twice, for wfq and fifo */ s->fp->config(s, 1); if (pending) { struct new_fsk *fs; + /* XXX should do the requeue here */ /* mark and clone flowsets for the old scheduler */ SLIST_FOREACH(fs, pending, sch_chain) { int dying = fs->kflags & DN_DELETE; @@ -897,8 +915,8 @@ again: /* run twice, for wfq and fifo */ update_fs(s); if (i < DN_MAX_ID) { /* update the FIFO instance */ i += DN_MAX_ID; - nsch->sched_nr = i; - nsch->oid.subtype = DN_SCHED_FIFO; + a.sch->sched_nr = i; + a.sch->oid.subtype = DN_SCHED_FIFO; goto again; } DUMMYNET_UNLOCK(); @@ -968,8 +986,9 @@ config_profile(struct new_profile *pf, s static int del_fs(int i) { - struct new_fsk *fs = dn_ht_find(dn_cfg.fshash, i, DNHT_REMOVE, NULL); + struct new_fsk *fs; + fs = dn_ht_find(dn_cfg.fshash, i, DNHT_REMOVE, NULL); printf("%s fs %d found %p\n", __FUNCTION__, i, fs); if (fs == NULL) return EINVAL; @@ -983,7 +1002,9 @@ del_fs(int i) static int del_schk(int i) { - struct new_schk *s = dn_ht_find(dn_cfg.schedhash, i, DNHT_REMOVE, NULL); + struct new_schk *s; + + s = dn_ht_find(dn_cfg.schedhash, i, DNHT_REMOVE, NULL); printf("%s sched %d %p\n", __FUNCTION__, i, s); if (s) { schk_del_cb(s, NULL); @@ -1031,9 +1052,9 @@ do_config(void *p, int l) /* delete base and derived schedulers */ if ( (err = del_schk(o->id)) ) break; - if ( (err = del_schk(o->id + DN_MAX_ID)) ) - break; + err = del_schk(o->id + DN_MAX_ID); break; + default: printf("invalid delete type %d\n", o->subtype); @@ -1043,7 +1064,6 @@ do_config(void *p, int l) case DN_FS: err = (o->id < 1 || o->id >= DN_MAX_ID) ? EINVAL : del_fs(o->id) ; - break; break; } break; @@ -1075,6 +1095,7 @@ do_config(void *p, int l) } return err; } + static int compute_space(struct dn_id *cmd, int *to_copy) { @@ -1155,6 +1176,7 @@ dummynet_get(struct sockopt *sopt) /* start copying other objects */ { struct copy_args a; + a.start = &buf; a.end = end; a.flags = to_copy; @@ -1170,7 +1192,8 @@ dummynet_get(struct sockopt *sopt) } /* - * Handler for the various dummynet socket options (get, flush, config, del) + * Handler for the various dummynet socket options + * (get, flush, config, del) */ static int ip_dn_ctl(struct sockopt *sopt) @@ -1226,20 +1249,14 @@ ip_dn_ctl(struct sockopt *sopt) if (p != NULL) free(p, M_TEMP); - return error ; + 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 we need to pass an additional argument - * (struct dn_sched *)and the hash table API does not support that. - * To work around the problem, we pass a struct new_sch *, store the - * struct dn_sched * in sch->oid.id, and set DNHT_KEY_IS_OBJ but - * not - * XXX the way to remove this restriction is adding an argument to - * the 'find' call, which is passed to the various functions. + * because in the create phase (but it should be fixed). */ static int schk_hash(uintptr_t key, int flags, void *_arg) @@ -1264,25 +1281,23 @@ schk_match(void *obj, uintptr_t key, int * a new object or a previously existing one. */ static void * -schk_new(uintptr_t key, int flags, void *_fp) +schk_new(uintptr_t key, int flags, void *arg) { + struct schk_new_arg *a = arg; struct new_schk *s; - struct new_sch *sch = (struct new_sch *)key; - int l; + int l = sizeof(*s) +a->fp->schk_datalen; - l = sizeof(*s) + ((struct dn_sched *)_fp)->schk_len; - 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 = *sch; // copy initial values - s->pipe.pipe_nr = sch->sched_nr; + 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 (sch->flags & DN_HAVE_MASK) { + 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); @@ -1304,7 +1319,6 @@ ip_dn_init(void) /* create hash tables for schedulers and flowsets. * In both we search by key and by pointer. - * Insertion in schedhash uses externally allocated objects. */ dn_cfg.schedhash = dn_ht_init(NULL, dn_cfg.hash_size, offsetof(struct new_schk, schk_next), From owner-svn-src-user@FreeBSD.ORG Tue Jan 19 13:33:54 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 A607A10656B0; Tue, 19 Jan 2010 13:33:54 +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 9374C8FC0A; Tue, 19 Jan 2010 13:33:54 +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 o0JDXs2J003746; Tue, 19 Jan 2010 13:33:54 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0JDXsY8003738; Tue, 19 Jan 2010 13:33:54 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <201001191333.o0JDXsY8003738@svn.freebsd.org> From: Luigi Rizzo Date: Tue, 19 Jan 2010 13:33:54 +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: r202625 - in 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 13:33:54 -0000 Author: luigi Date: Tue Jan 19 13:33:54 2010 New Revision: 202625 URL: http://svn.freebsd.org/changeset/base/202625 Log: revise the detach/reconfigure paths Modified: user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.c user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.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/sys/netinet/ip_dummynet.h ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h Tue Jan 19 13:33:31 2010 (r202624) +++ user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h Tue Jan 19 13:33:54 2010 (r202625) @@ -259,7 +259,5 @@ flow using a number of heaps defined int #define DN_QSIZE_IS_BYTES 0x0008 /* queue size is measured in bytes */ #define DN_NOERROR 0x0010 /* do not report ENOBUFS on drops */ #define DN_HAS_PROFILE 0x0020 /* the pipe has a delay profile. */ -#define DN_IS_PIPE 0x4000 -#define DN_IS_QUEUE 0x8000 #endif /* _IP_DUMMYNET_H */ Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.c Tue Jan 19 13:33:31 2010 (r202624) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.c Tue Jan 19 13:33:54 2010 (r202625) @@ -386,6 +386,8 @@ dn_ht_find(struct dn_ht *ht, uintptr_t k int i; void **pp, *p; + if (ht == NULL) /* easy on an empty hash */ + return NULL; i = (ht->buckets == 1) ? 0 : (ht->hash(key, flags, arg) % ht->buckets); // printf("%s key %p in bucket %d\n", __FUNCTION__, (void *)key, i); Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h Tue Jan 19 13:33:31 2010 (r202624) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h Tue Jan 19 13:33:54 2010 (r202625) @@ -94,9 +94,12 @@ struct dn_sched { * * new_queue called to set the per-queue parameters, * e.g. S and F, adjust sum of weights in the parent, etc. + * If the queue has packets in it, add them to the scheduler + * as well. * * free_queue actions related to a queue removal, e.g. undo - * all the above. + * all the above. If the queue has data in it, also remove + * from the scheduler. This can e.g. happen during a reconfigure. */ int (*enqueue)(struct new_sch_inst *, struct new_queue *, struct mbuf *); @@ -120,7 +123,7 @@ struct dn_sched { * if do_free is set, propagate to the flowset and destroy it * if the refcount becomes 0 */ -int dn_delete_queue(void *, void *do_free); +struct new_queue *dn_delete_queue(struct new_queue *, int do_free); int dn_enqueue(struct new_queue *q, struct mbuf* m, int drop); /* @@ -141,7 +144,7 @@ dn_dequeue(struct new_queue *q) q->si->ni.len_bytes -= m->m_pkthdr.len; } if (q->mq.head == NULL && q->fs && q->fs->kflags & DN_DELETE) - dn_delete_queue(q, (void *)1 /* free if possible */); + (void)dn_delete_queue(q, 1 /* free if possible */); return m; } Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c Tue Jan 19 13:33:31 2010 (r202624) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c Tue Jan 19 13:33:54 2010 (r202625) @@ -111,15 +111,13 @@ wf2qp_enqueue(struct new_sch_inst *_si, struct wf2qp_si *si = (struct wf2qp_si *)(_si + 1); struct wf2qp_queue *alg_fq; uint64_t len = m->m_pkthdr.len; - int q_was_idle; - q_was_idle = (q->mq.head == NULL); - - if (dn_enqueue(q, m, 0)) /* packet was dropped */ - return 1; - - if (!q_was_idle) - return 0; + if (m != q->mq.head) { + if (dn_enqueue(q, m, 0)) /* packet was dropped */ + return 1; + if (m != q->mq.head) /* queue was already busy */ + return 0; + } /* If reach this point, queue q was idle */ alg_fq = (struct wf2qp_queue *)(q+1); @@ -238,8 +236,8 @@ wf2qp_new_sched(struct new_sch_inst *_si /* only idle-heap supports extract from middle */ if (heap_init(&si->idle_heap, 16, ofs) || - heap_init(&si->sch_heap, 16, -1) || - heap_init(&si->ne_heap, 16, -1)) { + heap_init(&si->sch_heap, 16, ofs) || + heap_init(&si->ne_heap, 16, ofs)) { heap_free(&si->ne_heap); heap_free(&si->sch_heap); heap_free(&si->idle_heap); @@ -279,6 +277,9 @@ wf2qp_new_queue(struct new_queue *_q) _q->ni.oid.subtype = DN_SCHED_WF2QP; q->F = 0; /* not strictly necessary */ q->S = q->F + 1; /* mark timestamp as invalid. */ + if (_q->mq.head != NULL) { + wf2qp_enqueue(_q->si, _q, _q->mq.head); + } return 0; } @@ -286,11 +287,24 @@ static int wf2qp_free_queue(struct new_queue *q) { struct wf2qp_queue *alg_fq = (struct wf2qp_queue *)(q + 1); + struct wf2qp_si *si = (struct wf2qp_si *)(q->si + 1); + printf("%s called\n", __FUNCTION__); /* If the queue was valid, decrement the sum value */ - if (alg_fq->S != alg_fq->F + 1) { - struct wf2qp_si *si = (struct wf2qp_si *)(q->si + 1); - si->sum -= q->fs->fs.weight; + if (alg_fq->S == alg_fq->F + 1) + return 0; /* nothing to do, not in any heap */ + /* decrement the sum of weights */ + si->sum -= q->fs->fs.weight; + + /* extract from the heap. Note that we may need to adjust V + * to make sure the invariants hold. + */ + if (q->mq.head == NULL) { + heap_extract(&si->idle_heap, q); + } else if (DN_KEY_LT(si->V, alg_fq->S)) { + heap_extract(&si->ne_heap, q); + } else { + heap_extract(&si->sch_heap, q); } return 0; } Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c Tue Jan 19 13:33:31 2010 (r202624) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c Tue Jan 19 13:33:54 2010 (r202625) @@ -545,6 +545,7 @@ tag_mbuf(struct mbuf *m, int dir, struct return 0; } + /* * dummynet hook for packets. * We use the argument to locate the flowset fs and the sched_set sch @@ -588,17 +589,7 @@ dummynet_io(struct mbuf **m0, int dir, s * We cannot pass si as an argument :( */ if (fs->sched->fp->flags & DN_MULTIQUEUE) { - struct new_queue template; - template.si = si; - template.fs = fs; - if (fs->fs.flags & DN_HAVE_MASK) { - q = dn_ht_find(fs->qht, (uintptr_t)&(fwa->f_id), - DNHT_INSERT, &template); - } else { /* qht is simply a queue */ - if (fs->qht == NULL) - fs->qht = q_new(0, 0, &template); - q = (struct new_queue *)fs->qht; - } + q = ipdn_q_find(fs, si, &(fwa->f_id)); if (q == 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 Tue Jan 19 13:33:31 2010 (r202624) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h Tue Jan 19 13:33:54 2010 (r202625) @@ -137,7 +137,7 @@ struct new_fsk { /* kernel side of a flo /* hash table of queues. XXX if we have no flow_mask we could * avoid the hash table and just allocate one queue. */ - struct dn_ht *qht; + 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 */ @@ -207,9 +207,11 @@ struct new_sch_inst { /* kernel-side flags */ enum { DN_DELETE = 0x0004, /* destroy when refcnt=0 */ + DN_DELETE_FS = 0x0008, /* destroy when refcnt=0 */ DN_ACTIVE = 0x0010, /* object is in evheap */ DN_F_DLINE = 0x0020, /* object is a delay line */ DN_F_SCHI = 0x0030, /* object is a sched.instance */ + DN_QHT_IS_Q = 0x0100, /* in flowset, qht is a single queue */ }; extern struct dn_parms dn_cfg; @@ -218,8 +220,9 @@ int dummynet_io(struct mbuf **, int , st void dummynet_task(void *context, int pending); void dn_reschedule(void); -struct new_sch_inst *ipdn_si_find(struct new_schk *s, struct ipfw_flow_id *id); -void * q_new(uintptr_t key, int flags, void *arg); +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); #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 Tue Jan 19 13:33:31 2010 (r202624) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Tue Jan 19 13:33:54 2010 (r202625) @@ -230,7 +230,7 @@ q_match(void *obj, uintptr_t key, int fl /* * create a new queue instance for the given 'key'. */ -void * +static void * q_new(uintptr_t key, int flags, void *arg) { struct new_queue *q, *template = arg; @@ -410,90 +410,92 @@ fsk_new(uintptr_t key, int flags, void * } return fs; } +/*----- end of flowset hashtable support -------------*/ -static int schk_del_cb(void *obj, void *arg); /* - * delete a flowset. Mark as delete, and free all when no refcount. - * Return 1 if freed, o otherwise. - * Removal from the hashtable must be done outside this function. + * 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. */ -static void -fsk_destroy(struct new_fsk *fs, int do_free) +struct new_queue * +dn_delete_queue(struct new_queue *q, int do_free) { - struct new_fsk_head *h; + struct new_fsk *fs = q->fs; - fs->kflags |= DN_DELETE; - if (fs->refcnt != 0) - return; - /* find the container list */ - h = fs->sched ? &fs->sched->fsk_list : &dn_cfg.fsu; - SLIST_REMOVE(h, fs, new_fsk, sch_chain); - dn_cfg.fsk_count--; - if (fs->sched && fs->sched->fp->free_fsk) - fs->sched->fp->free_fsk(fs); - /* XXX possibly notify the event to the scheduler */ - if (fs->sched != NULL && (fs->sched->kflags & DN_DELETE) && - SLIST_FIRST(&fs->sched->fsk_list) == NULL) { - printf("scheduler %p should be deleted\n", fs->sched); - dn_ht_find(dn_cfg.schedhash, (uintptr_t)(fs->sched), - DNHT_KEY_IS_OBJ | DNHT_MATCH_PTR | DNHT_REMOVE, NULL); - schk_del_cb(fs->sched, NULL); - } - - fs->sched = NULL; - if (do_free) { - if (fs->qht) /* only if DN_HAVE_MASK */ - dn_ht_free(fs->qht, 0); - free(fs, M_DUMMYNET); - } + 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; } -/*----- end of flowset hashtable support -------------*/ /* - * delete the queues in qht, consider the presence of a flow_mask + * 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 -delete_qht(struct new_fsk *fs) +qht_delete(struct new_fsk *fs, int flags) { - if (fs->fs.flags & DN_HAVE_MASK) - dn_ht_scan(fs->qht, dn_delete_queue, NULL); - else { - dn_delete_queue(fs->qht, NULL); - fs->qht = NULL; + 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; + } } } /* - * Destroy all flowsets in a list. Used when deleting a scheduler, + * Detach or destroy all flowsets in a list. Used when deleting a scheduler, * or for all those in fsunlinked. - * For 'ipfw queue flush' we need a callback. - * (for those + * int_fs points to an internal flowset which must be handled differently. + * 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_destroy_list(struct new_fsk_head *h, struct new_fsk *int_fs) +fsk_detach_list(struct new_fsk_head *h, struct new_fsk *int_fs, int flags) { struct new_fsk *fs; + if (flags & DN_DELETE_FS) + flags |= DN_DELETE; + printf("+++ %s head %p flags %x\n", __FUNCTION__, h, flags); 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; } - /* drain queues, but pass NULL so the fs is not deleted. - * We cannot destroy it from the callback or it - * would kill the hashtable as well. After the pass, - * refcnt is surely 0. - * If the flowset was marked delete, destroy it. - * otherwise move it to fsunlinked. - */ - delete_qht(fs); + /* detach queues from the scheduler and possibly drain them */ + qht_delete(fs, flags); fs->sched = NULL; - if (fs->kflags & DN_DELETE) { - if (fs->qht) - dn_ht_free(fs->qht, 0); + if (flags & DN_DELETE_FS) { + bzero(fs, sizeof(fs)); /* safety */ free(fs, M_DUMMYNET); } else { SLIST_INSERT_HEAD(&dn_cfg.fsu, fs, sch_chain); @@ -501,26 +503,6 @@ fsk_destroy_list(struct new_fsk_head *h, } } -/* - * Delete a queue (helper for the schedulers and callback) - */ -int -dn_delete_queue(void *_q, void *do_free) -{ - struct new_queue *q = _q; - struct new_fsk *fs = q->fs; - - if (q->mq.head) - dn_free_pkts(q->mq.head); - if (fs && fs->sched->fp->free_queue) - fs->sched->fp->free_queue(q); - free(q, M_DUMMYNET); - dn_cfg.queue_count--; - fs->refcnt--; - if (fs->refcnt == 0 && fs->kflags & DN_DELETE) - fsk_destroy(fs, (int)do_free); - return 0; -} /* callback to flush credit for the pipe */ static int @@ -600,49 +582,69 @@ copy_data_helper(void *_o, void *_arg) } /* - * Callback for sched delete. Tell all attached flowsets to - * remove their queues, unlink the flowsets. + * 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_del_cb(void *obj, void *arg) +schk_delete_cb(void *obj, void *arg) { struct new_schk *s = obj; - if (s->fs) { + 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); - s->fs->kflags |= DN_DELETE; } - fsk_destroy_list(&s->fsk_list, s->fs); + 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); - free(obj, M_DUMMYNET); - dn_cfg.schk_count--; - return HEAP_SCAN_DEL; + if (arg) { + free(obj, M_DUMMYNET); + dn_cfg.schk_count--; + return HEAP_SCAN_DEL; + } else + return 0; } + /* - * Delete all objects: + * only called in the DN_MULTIQUEUE CASE so we can handle errors + * in a better way. */ -static void -dummynet_flush(void) -{ - - DUMMYNET_LOCK(); - /* all schedulers and related pipes/queues/flowsets */ - dn_ht_scan(dn_cfg.schedhash, schk_del_cb, NULL); - /* all remaining (unlinked) flowsets */ - fsk_destroy_list(&dn_cfg.fsu, NULL); - /* Reinitialize system heap... */ - heap_init(&dn_cfg.evheap, 16, offsetof(struct dn_id, id)); - - DUMMYNET_UNLOCK(); +struct new_queue * +ipdn_q_find(struct new_fsk *fs, struct new_sch_inst *si, + struct ipfw_flow_id *id) +{ + struct new_queue template; + template.si = si; + template.fs = fs; + + if (fs->fs.flags & DN_HAVE_MASK) { + if (fs->_qht == NULL) { + fs->_qht = dn_ht_init(NULL, fs->fs.buckets, + offsetof(struct new_queue, q_next), + q_hash, q_match, q_new); + if (fs->_qht == NULL) + return NULL; + fs->kflags &= ~DN_QHT_IS_Q; + } + return dn_ht_find(fs->_qht, (uintptr_t)id, + DNHT_INSERT, &template); + } else { + if (fs->_qht == NULL) + fs->_qht = q_new(0, 0, &template); + fs->kflags |= DN_QHT_IS_Q; + return (struct new_queue *)fs->_qht; + } } - static inline struct new_schk * locate_scheduler(int i) { @@ -664,6 +666,10 @@ update_fs(struct new_schk *s) SLIST_REMOVE(&dn_cfg.fsu, fs, new_fsk, sch_chain); fs->sched = s; SLIST_INSERT_HEAD(&s->fsk_list, fs, sch_chain); + if (!fs->_qht) + continue; + printf("+++ %s requeue from fs %d to sch %d\n", + __FUNCTION__, fs->fs.fs_nr, s->sch.sched_nr); } } @@ -780,6 +786,24 @@ config_fs(struct new_fs *nfs, struct dn_ dn_cfg.id++; if (bcmp(&fs->fs, nfs, sizeof(*nfs)) == 0) break; /* no change, nothing to do */ + s = locate_scheduler(nfs->sched_nr); +/* XXX TODO +Configuration and reconfiguration handling. +A new flowset, or one with fs->sched == NULL, has no queues. +- if it is still unattached we have nothing to do; +- if s != NULL, remove from unlinked and add to the children + of s, possibly creating the hash table (or we can postpone + it to when the first packet arrives); + +A flowset with fs->sched != NULL and with queues we have two options: +- if it becomes unlinked, then simply destroy the queues notifying + the old scheduler. +- if it becomes linked, we also need to re-enqueue the packets on + the new scheduler. + There are some easy cases (e.g. flow_mask unchanged) but + in general we should really work on every single packet. + */ + fs->fs = *nfs; /* update config */ /* * XXX note that if we modify some scheduler-specific @@ -787,8 +811,12 @@ config_fs(struct new_fs *nfs, struct dn_ * scheduler otherwise things might go really badly, * such as sum-of-weights mismatches. */ - s = locate_scheduler(nfs->sched_nr); if (fs->sched != NULL) { + /* XXX TODO: if the scheduler does not exist + * anymore, then all queues should be drained. + * If there is a new scheduler, then move + * queues from the old to the new one. + */ /* we had a scheduler before, let the flowset * die and create a new one with the new * parameters. @@ -805,14 +833,7 @@ config_fs(struct new_fs *nfs, struct dn_ SLIST_REMOVE(&dn_cfg.fsu, fs, new_fsk, sch_chain); fs->sched = s; SLIST_INSERT_HEAD(&s->fsk_list, fs, sch_chain); - /* only create the hash table if the scheduler supports - * multiple queues and we have a flow mask. - */ - if (s->fp->flags & DN_MULTIQUEUE && - fs->fs.flags & DN_HAVE_MASK) - fs->qht = dn_ht_init(NULL, nfs->buckets, - offsetof(struct new_queue, q_next), - q_hash, q_match, q_new); + /* _qht is initialized on first use */ if (s->fp->new_fsk) s->fp->new_fsk(fs); } while (0); @@ -830,7 +851,6 @@ config_sched(struct new_sch *_nsch, stru { struct new_schk *s; struct schk_new_arg a; /* argument for schk_new */ - struct new_fsk_head *pending = NULL; int i, notify_fs = 0; a.sch = _nsch; @@ -859,27 +879,21 @@ again: /* run twice, for wfq and fifo */ return ENOMEM; } dn_cfg.id++; - notify_fs = 0; - if (s->fp == NULL) { /* new scheduler, nothing to clean up */ - notify_fs = 1; - } else if (s->fp != a.fp) { - printf("sched %d type changed from %s to %s" - " let it drain and reallocate\n", - i, s->fp->name, a.fp->name); - /* mark delete so it won't be matched. - * XXX todo: make it die when its queues are done. - * XXX otherwise do a real delete. - * XXX Reconfiguration should be done differently, - * removing packets from the old scheduler and - * requeueing to the new one. Otherwise we can have - * reordering and unwanted effects. + if (s->fp != NULL) { + /* in all other cases, remove from the heaps, + * and detach flowsets from + * the old one almost as in sched_delete, but + * preserve traffic. + * XXX what about the internal queue ? */ - s->kflags |= DN_DELETE; + printf("sched %d type changed from %s to %s\n", + i, s->fp->name, a.fp->name); + schk_delete_cb(s, NULL); notify_fs = 1; - pending = &s->fsk_list; - goto again; + /* now we have nothing pointing to us */ } /* complete initialization */ + s->sch = *a.sch; s->fp = a.fp; s->cfg = arg; // XXX schk_reset_credit(s); @@ -899,20 +913,7 @@ again: /* run twice, for wfq and fifo */ /* call init function after the flowset is created */ if (s->fp->config) s->fp->config(s, 1); - if (pending) { - struct new_fsk *fs; - /* XXX should do the requeue here */ - /* mark and clone flowsets for the old scheduler */ - SLIST_FOREACH(fs, pending, sch_chain) { - int dying = fs->kflags & DN_DELETE; - fs->kflags |= DN_DELETE; - if (!dying) /* clone if necessary */ - config_fs(&fs->fs, NULL, 1 /* locked */); - } - pending = NULL; - } - if (notify_fs) - update_fs(s); + update_fs(s); if (i < DN_MAX_ID) { /* update the FIFO instance */ i += DN_MAX_ID; a.sch->sched_nr = i; @@ -983,35 +984,70 @@ config_profile(struct new_profile *pf, s return 0; } +/* + * called on 'queue X delete' -- removes the flowset from fshash, + * deletes all queues for the flowset, and removes the flowset. + */ static int -del_fs(int i) +delete_fs(int i) { + struct new_fsk_head *h; struct new_fsk *fs; fs = dn_ht_find(dn_cfg.fshash, i, DNHT_REMOVE, NULL); printf("%s fs %d found %p\n", __FUNCTION__, i, fs); if (fs == NULL) return EINVAL; - // XXX not sure if we want to kill the queues now - if (0 && fs->qht) - dn_ht_scan(fs->qht, dn_delete_queue, NULL); - fsk_destroy(fs, 1 /* do free the object */); + + /* find the container list */ + h = fs->sched ? &fs->sched->fsk_list : &dn_cfg.fsu; + SLIST_REMOVE(h, fs, new_fsk, sch_chain); + dn_cfg.fsk_count--; + qht_delete(fs, 1); /* get rid of the queues */ + /* XXX possibly notify the event to the scheduler */ + if (fs->sched && fs->sched->fp->free_fsk) + fs->sched->fp->free_fsk(fs); + fs->sched = NULL; + free(fs, M_DUMMYNET); return 0; } +/* + * called on a 'sched X delete' command. Deletes a single scheduler. + * This is done by removing from the schedhash, unlinking all + * flowsets and deleting their traffic. + */ static int -del_schk(int i) +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); - if (s) { - schk_del_cb(s, NULL); - return 0; - } else { + if (!s) return EINVAL; - } + /* detach flowsets, delete traffic */ + schk_delete_cb(s, (void*)(uintptr_t)DN_DELETE); + return 0; +} + +/* + * Delete all objects: + */ +static void +dummynet_flush(void) +{ + + DUMMYNET_LOCK(); + /* all schedulers and related pipes/queues/flowsets */ + 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); + /* Reinitialize system heap... */ + heap_init(&dn_cfg.evheap, 16, offsetof(struct dn_id, id)); + + DUMMYNET_UNLOCK(); } /* @@ -1025,7 +1061,7 @@ static int do_config(void *p, int l) { struct dn_id *next, *o; - int err = 0; + int err = 0, err2 = 0; struct dn_id *arg = NULL; for (o = p; l >= sizeof(*o); o = next) { @@ -1050,9 +1086,12 @@ do_config(void *p, int l) switch (o->subtype) { case DN_PIPE: /* delete base and derived schedulers */ - if ( (err = del_schk(o->id)) ) - break; - err = del_schk(o->id + DN_MAX_ID); + DUMMYNET_LOCK(); + err = delete_schk(o->id); + err2 = delete_schk(o->id + DN_MAX_ID); + DUMMYNET_UNLOCK(); + if (!err) + err = err2; break; default: @@ -1063,7 +1102,7 @@ do_config(void *p, int l) case DN_FS: err = (o->id < 1 || o->id >= DN_MAX_ID) ? - EINVAL : del_fs(o->id) ; + EINVAL : delete_fs(o->id) ; break; } break; 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) From owner-svn-src-user@FreeBSD.ORG Tue Jan 19 18:42:09 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 D56AE106568D; Tue, 19 Jan 2010 18:42:09 +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 C3D568FC17; Tue, 19 Jan 2010 18:42:09 +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 o0JIg9Yr074787; Tue, 19 Jan 2010 18:42:09 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0JIg9Un074778; Tue, 19 Jan 2010 18:42:09 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <201001191842.o0JIg9Un074778@svn.freebsd.org> From: Luigi Rizzo Date: Tue, 19 Jan 2010 18:42:09 +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: r202639 - 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 18:42:09 -0000 Author: luigi Date: Tue Jan 19 18:42:09 2010 New Revision: 202639 URL: http://svn.freebsd.org/changeset/base/202639 Log: snapshot Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.c user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.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_wf2q.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/sys/netinet/ipfw/dn_heap.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.c Tue Jan 19 18:25:49 2010 (r202638) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.c Tue Jan 19 18:42:09 2010 (r202639) @@ -363,14 +363,25 @@ dn_ht_init(struct dn_ht *ht, int buckets return ht; } +/* dummy callback for dn_ht_free to unlink all */ +static int +do_del(void *obj, void *arg) +{ + return DNHT_SCAN_DEL; +} + void dn_ht_free(struct dn_ht *ht, int flags) { if (ht == NULL) return; - if (ht->ht && ht->ht != (void *)(ht + 1)) - free(ht->ht, M_DN_HEAP); - free(ht, M_DN_HEAP); + if (flags & DNHT_REMOVE) { + (void)dn_ht_scan(ht, do_del, NULL); + } else { + if (ht->ht && ht->ht != (void *)(ht + 1)) + free(ht->ht, M_DN_HEAP); + free(ht, M_DN_HEAP); + } } int @@ -437,7 +448,7 @@ dn_ht_scan(struct dn_ht *ht, int (*fn)(v while ( (cur = *curp) != NULL) { next = *(void **)((char *)cur + ht->ofs); ret = fn(cur, arg); - if (ret & HEAP_SCAN_DEL) { + if (ret & DNHT_SCAN_DEL) { printf("element %p removed\n", cur); found++; ht->entries--; @@ -445,7 +456,7 @@ dn_ht_scan(struct dn_ht *ht, int (*fn)(v } else { curp = (void **)((char *)cur + ht->ofs); } - if (ret & HEAP_SCAN_END) + if (ret & DNHT_SCAN_END) return found; } } Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.h ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.h Tue Jan 19 18:25:49 2010 (r202638) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.h Tue Jan 19 18:42:09 2010 (r202639) @@ -118,9 +118,9 @@ int heap_scan(struct dn_heap *, int (*)( * new(key, flags, arg) optional, used to allocate a new * object during insertions. * - * dn_ht_free() frees the heap, optionally unlinking elements - * (XXX unlink is optional and serves only to avoid stale - * pointers in the objects. Probably useless.) + * dn_ht_free() frees the heap or unlink elements. + * DNHT_REMOVE unlink elements, 0 frees the heap. + * You need two calls to do both. * * dn_ht_find() is the main lookup function, which can also be * used to insert or delete elements in the hash table. @@ -175,7 +175,7 @@ enum { /* flags values. DNHT_MATCH_PTR = 0x0008, /* match by pointer, not match() */ DNHT_INSERT = 0x0010, /* insert if not found */ DNHT_UNIQUE = 0x0020, /* report error if already there */ - DNHT_REMOVE = 0x0040, /* remove on find */ + DNHT_REMOVE = 0x0040, /* remove on find or dn_ht_free */ }; #endif /* _IP_DN_HEAP_H */ Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h Tue Jan 19 18:25:49 2010 (r202638) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h Tue Jan 19 18:42:09 2010 (r202639) @@ -91,6 +91,7 @@ struct dn_sched { * new_fsk called when a flowset is linked to a scheduler, * e.g. to validate parameters such as weights etc. * free_fsk when a flowset is unlinked from a scheduler. + * (probably unnecessary) * * new_queue called to set the per-queue parameters, * e.g. S and F, adjust sum of weights in the parent, etc. @@ -105,8 +106,8 @@ struct dn_sched { struct mbuf *); struct mbuf * (*dequeue)(struct new_sch_inst *); - int (*config)(struct new_schk *, int reconfigure); - int (*destroy)(struct new_schk*, int delete); + int (*config)(struct new_schk *); + int (*destroy)(struct new_schk*); int (*new_sched)(struct new_sch_inst *); int (*free_sched)(struct new_sch_inst *); int (*new_fsk)(struct new_fsk *f); @@ -123,6 +124,7 @@ struct dn_sched { * if do_free is set, propagate to the flowset and destroy it * if the refcount becomes 0 */ +void dn_free_pkts(struct mbuf *mnext); struct new_queue *dn_delete_queue(struct new_queue *, int do_free); int dn_enqueue(struct new_queue *q, struct mbuf* m, int drop); @@ -139,9 +141,9 @@ dn_dequeue(struct new_queue *q) q->mq.head = m->m_nextpkt; q->ni.length--; q->ni.len_bytes -= m->m_pkthdr.len; - if (q->si) { - q->si->ni.length--; - q->si->ni.len_bytes -= m->m_pkthdr.len; + if (q->_si) { + q->_si->ni.length--; + q->_si->ni.len_bytes -= m->m_pkthdr.len; } if (q->mq.head == NULL && q->fs && q->fs->kflags & DN_DELETE) (void)dn_delete_queue(q, 1 /* free if possible */); Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_fifo.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_fifo.c Tue Jan 19 18:25:49 2010 (r202638) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_fifo.c Tue Jan 19 18:42:09 2010 (r202639) @@ -70,11 +70,20 @@ fifo_new_sched(struct new_sch_inst *si) struct new_queue *q = (struct new_queue *)(si + 1); set_oid(&q->ni.oid, DN_QUEUE, sizeof(*q)); - q->si = si; + q->_si = si; q->fs = si->sched->fs; return 0; } +static int +fifo_free_sched(struct new_sch_inst *si) +{ + struct new_queue *q = (struct new_queue *)(si + 1); + dn_free_pkts(q->mq.head); + bzero(q, sizeof(*q)); + return 0; +} + /* * FIFO scheduler descriptor * contains the type of the scheduler, the name, the size of extra @@ -89,6 +98,7 @@ static struct dn_sched fifo_desc = { .enqueue = fifo_enqueue, .dequeue = fifo_dequeue, .new_sched = fifo_new_sched, + .free_sched = fifo_free_sched, }; DECLARE_DNSCHED_MODULE(dn_fifo, &fifo_desc); Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c Tue Jan 19 18:25:49 2010 (r202638) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c Tue Jan 19 18:42:09 2010 (r202639) @@ -278,7 +278,7 @@ wf2qp_new_queue(struct new_queue *_q) q->F = 0; /* not strictly necessary */ q->S = q->F + 1; /* mark timestamp as invalid. */ if (_q->mq.head != NULL) { - wf2qp_enqueue(_q->si, _q, _q->mq.head); + wf2qp_enqueue(_q->_si, _q, _q->mq.head); } return 0; } @@ -287,7 +287,7 @@ static int wf2qp_free_queue(struct new_queue *q) { struct wf2qp_queue *alg_fq = (struct wf2qp_queue *)(q + 1); - struct wf2qp_si *si = (struct wf2qp_si *)(q->si + 1); + struct wf2qp_si *si = (struct wf2qp_si *)(q->_si + 1); printf("%s called\n", __FUNCTION__); /* If the queue was valid, decrement the sum value */ Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c Tue Jan 19 18:25:49 2010 (r202638) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c Tue Jan 19 18:42:09 2010 (r202639) @@ -221,7 +221,7 @@ dn_enqueue(struct new_queue *q, struct m uint64_t len; f = &(q->fs->fs); - ni = &q->si->ni; + ni = &q->_si->ni; len = m->m_pkthdr.len; /* Update statistics, then check reasons to drop pkt. */ q->ni.tot_bytes += len; @@ -577,7 +577,7 @@ dummynet_io(struct mbuf **m0, int dir, s goto dropit; /* This queue/pipe does not exist! */ if (fs->sched == NULL) /* should not happen */ goto dropit; - /* find scheduler instance, possibly applying mask */ + /* find scheduler instance, possibly applying sched_mask */ si = ipdn_si_find(fs->sched, &(fwa->f_id)); if (si == 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 Tue Jan 19 18:25:49 2010 (r202638) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h Tue Jan 19 18:42:09 2010 (r202639) @@ -144,18 +144,17 @@ struct new_fsk { /* kernel side of a flo }; /* - * q queue is created as a child of a flowset unless it belongs to + * A queue is created as a child of a flowset unless it belongs to * a !MULTIQUEUE scheduler. It is normally in a hash table in the - * flowset. - * When a scheduler is destroyed we notify all flowsets attached - * to it so queues can be removed. - * When a flowset is deleted we let the queue drain quietly, and - * destroy the flowset when all queues are empty. + * flowset. fs always points to the parent flowset. + * si normally points to the sch_inst, unless the flowset has been + * detached from the scheduler -- in this case si == NULL and we + * should not enqueue. */ struct new_queue { struct new_inst ni; /* oid, flow_id, stats */ struct mq mq; /* packets queue */ - struct new_sch_inst *si; /* owner scheduler instance */ + struct new_sch_inst *_si; /* owner scheduler instance */ SLIST_ENTRY(new_queue) q_next; /* hash chain list for fs */ struct new_fsk *fs; /* parent flowset. */ /* If fs->kflags & DN_DELETE, remove the queue when empty. */ @@ -171,7 +170,6 @@ struct new_queue { */ struct new_schk { struct new_sch sch; - int kflags; struct dn_sched *fp; /* Pointer to scheduler functions */ struct new_pipe pipe; /* the pipe is embedded */ struct new_profile *profile; Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Tue Jan 19 18:25:49 2010 (r202638) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Tue Jan 19 18:42:09 2010 (r202639) @@ -107,7 +107,7 @@ find_sched_type(int type, char *name) * Dispose a list of packet. Use a functions so if we need to do * more work, this is a central point to do it. */ -static void dn_free_pkts(struct mbuf *mnext) +void dn_free_pkts(struct mbuf *mnext) { struct mbuf *m; @@ -247,7 +247,7 @@ q_new(uintptr_t key, int flags, void *ar if (fs->fs.flags & DN_HAVE_MASK) q->ni.id = *(struct ipfw_flow_id *)key; q->fs = fs; - q->si = template->si; + q->_si = template->_si; fs->refcnt++; if (fs->sched->fp->new_queue) @@ -266,10 +266,11 @@ dn_delete_queue(struct new_queue *q, int { struct new_fsk *fs = q->fs; - printf(" +++ %s fs %p si %p\n", __FUNCTION__, fs, q->si); + 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); + q->_si = NULL; if (!do_free) return q; if (q->mq.head) @@ -308,6 +309,40 @@ qht_delete(struct new_fsk *fs, int flags } } } + +/* + * only called in the DN_MULTIQUEUE CASE so we can handle errors + * in a better way. + */ +struct new_queue * +ipdn_q_find(struct new_fsk *fs, struct new_sch_inst *si, + struct ipfw_flow_id *id) +{ + struct new_queue template; + template._si = si; + template.fs = fs; + + if (fs->fs.flags & DN_HAVE_MASK) { + struct ipfw_flow_id masked_id; + if (fs->_qht == NULL) { + fs->_qht = dn_ht_init(NULL, fs->fs.buckets, + offsetof(struct new_queue, q_next), + q_hash, q_match, q_new); + if (fs->_qht == NULL) + return NULL; + fs->kflags &= ~DN_QHT_IS_Q; + } + masked_id = *id; + flow_id_mask(&fs->fs.flow_mask, &masked_id); + return dn_ht_find(fs->_qht, (uintptr_t)&masked_id, + DNHT_INSERT, &template); + } else { + if (fs->_qht == NULL) + fs->_qht = q_new(0, 0, &template); + fs->kflags |= DN_QHT_IS_Q; + return (struct new_queue *)fs->_qht; + } +} /*--- end of queue hash table ---*/ /*--- support functions for the sch_inst hashtable ---- @@ -380,7 +415,7 @@ error: } /* - * Callback for the hashtable scan. + * callback from siht to delete all scheduler instances. * We assume that all flowset have been notified and do not * point to us anymore. * Remove si and delay line from the system heap, destroy all queues. @@ -468,14 +503,15 @@ fsk_new(uintptr_t key, int flags, void * /* * 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: 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, int flags) { struct new_fsk *fs; + int n = 0; if (flags & DN_DELETE_FS) flags |= DN_DELETE; @@ -485,15 +521,52 @@ fsk_detach_list(struct new_fsk_head *h, printf(" +++ %s child fs %d\n", __FUNCTION__, fs->fs.fs_nr); /* detach queues from the scheduler and possibly drain them */ qht_delete(fs, flags); + if (fs->sched && fs->sched->fp->free_fsk) + fs->sched->fp->free_fsk(fs); fs->sched = NULL; if (flags & DN_DELETE_FS) { bzero(fs, sizeof(fs)); /* safety */ free(fs, M_DUMMYNET); + dn_cfg.fsk_count--; } else { SLIST_INSERT_HEAD(&dn_cfg.fsu, fs, sch_chain); } } + printf("+++ %s done %d flowsets\n", __FUNCTION__, n); } + +/* + * called on 'queue X delete' -- removes the flowset from fshash, + * deletes all queues for the flowset, and removes the flowset. + * XXX note that fsk_detach_list also destroys a flowset. + */ +static int +delete_fs(int i) +{ + struct new_fsk_head *h; + struct new_fsk *fs; + + fs = dn_ht_find(dn_cfg.fshash, i, DNHT_REMOVE, NULL); + printf("%s fs %d found %p\n", __FUNCTION__, i, fs); + if (fs == NULL) + return EINVAL; + + /* find the container list */ + h = fs->sched ? &fs->sched->fsk_list : &dn_cfg.fsu; + SLIST_REMOVE(h, fs, new_fsk, sch_chain); + + /* replica of the code in fsk_detach_list */ + qht_delete(fs, DN_DELETE); + if (fs->sched && fs->sched->fp->free_fsk) + fs->sched->fp->free_fsk(fs); + fs->sched = NULL; + bzero(fs, sizeof(fs)); /* safety */ + free(fs, M_DUMMYNET); + dn_cfg.fsk_count--; + + return 0; +} + /*----- end of flowset hashtable support -------------*/ /*------------------------------------------------------------ @@ -516,7 +589,7 @@ schk_match(void *obj, uintptr_t key, int 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); + return (s->sch.sched_nr == i); } /* @@ -550,6 +623,61 @@ schk_new(uintptr_t key, int flags, void return s; } +/* + * Callback for sched delete. Notify all attached flowsets to + * detach from the scheduler, destroy the internal flowset, and + * all instances. The scheduler goes away too. + * 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; + int i = s->sch.sched_nr; + int a = (int)arg; + + printf(">>> %s sched %d arg %s%s\n", + __FUNCTION__, s->sch.sched_nr, + a&DN_DELETE ? "DEL ":"", + a&DN_DELETE_FS ? "DEL_FS":""); + fsk_detach_list(&s->fsk_list, arg ? DN_DELETE : 0); + /* no more 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 (s->fp->destroy) + s->fp->destroy(s); + bzero(s, sizeof(*s)); + free(obj, M_DUMMYNET); + printf("<<< %s done sched %d destroyed\n", __FUNCTION__, i); + dn_cfg.schk_count--; + return DNHT_SCAN_DEL; +} + +/* + * called on a 'sched X delete' command. Deletes a single scheduler. + * This is done by removing from the schedhash, unlinking all + * flowsets and deleting their traffic. + */ +static int +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); + if (!s) + 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; +} + /* callback to flush credit for the pipe */ static int reset_credit(void *_si, void *arg) @@ -570,39 +698,6 @@ 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 @@ -628,6 +723,7 @@ struct copy_args { char *end; int flags; int type; + int extra; /* extra filtering */ }; static int @@ -639,13 +735,13 @@ copy_data_helper(void *_o, void *_arg) struct new_schk *s = _o; if (a->flags & DN_C_PIPE) { if (copy_obj(a->start, a->end, &s->pipe)) - return HEAP_SCAN_END; + return DNHT_SCAN_END; if (s->fs && copy_obj(a->start, a->end, &s->fs->fs)) - return HEAP_SCAN_END; + return DNHT_SCAN_END; } if (a->flags & DN_C_SCH) { if (copy_obj(a->start, a->end, &s->sch)) - return HEAP_SCAN_END; + return DNHT_SCAN_END; } if (a->flags & DN_C_SCH_INST) { printf("XXX todo: scan sched instances\n"); @@ -655,44 +751,14 @@ copy_data_helper(void *_o, void *_arg) struct new_fsk *fs = _o; struct new_fs *ufs = (struct new_fs *)(*a->start); - if (copy_obj(a->start, a->end, &fs->fs)) - return HEAP_SCAN_END; - ufs->oid.id = fs->refcnt; - } - return 0; -} - - - -/* - * only called in the DN_MULTIQUEUE CASE so we can handle errors - * in a better way. - */ -struct new_queue * -ipdn_q_find(struct new_fsk *fs, struct new_sch_inst *si, - struct ipfw_flow_id *id) -{ - struct new_queue template; - template.si = si; - template.fs = fs; - - if (fs->fs.flags & DN_HAVE_MASK) { - if (fs->_qht == NULL) { - fs->_qht = dn_ht_init(NULL, fs->fs.buckets, - offsetof(struct new_queue, q_next), - q_hash, q_match, q_new); - if (fs->_qht == NULL) - return NULL; - fs->kflags &= ~DN_QHT_IS_Q; + /* if extra is set, only copy unlinked ones */ + if (a->extra == 0 || fs->sched == NULL) { + if (copy_obj(a->start, a->end, &fs->fs)) + return DNHT_SCAN_END; + ufs->oid.id = fs->refcnt; } - return dn_ht_find(fs->_qht, (uintptr_t)id, - DNHT_INSERT, &template); - } else { - if (fs->_qht == NULL) - fs->_qht = q_new(0, 0, &template); - fs->kflags |= DN_QHT_IS_Q; - return (struct new_queue *)fs->_qht; } + return 0; } static inline struct new_schk * @@ -785,6 +851,8 @@ config_pipe(struct new_pipe *p, struct d return EINVAL; } /* copy all parameters */ + s->pipe.oid = p->oid; + s->pipe.pipe_nr = i; s->pipe.delay = p->delay; s->pipe.bandwidth = p->bandwidth; s->pipe.burst = p->burst; @@ -839,8 +907,10 @@ config_fs(struct new_fs *nfs, struct dn_ if (fs == NULL) break; dn_cfg.id++; - if (bcmp(&fs->fs, nfs, sizeof(*nfs)) == 0) + if (bcmp(&fs->fs, nfs, sizeof(*nfs)) == 0) { + printf("%s no change\n", __FUNCTION__); break; /* no change, nothing to do */ + } s = locate_scheduler(nfs->sched_nr); /* XXX TODO Configuration and reconfiguration handling. @@ -900,15 +970,19 @@ A flowset with fs->sched != NULL and wit /* * configure a scheduler and its FIFO variant. * For !MULTIQUEUE schedulers, also set up the flowset. + * + * On reconfigurations (detected because s->fp is set), + * detach existing flowsets preserving traffic, preserve pipe, + * and delete the old scheduler creating a new one. */ static int config_sched(struct new_sch *_nsch, struct dn_id *arg) { struct new_schk *s; struct schk_new_arg a; /* argument for schk_new */ - int i, notify_fs = 0; + int i; + struct new_pipe p; /* copy of oldpipe */ - printf("%s start\n", __FUNCTION__); a.sch = _nsch; if (a.sch->oid.len != sizeof(*a.sch)) { printf("%s: bad sched len\n", __FUNCTION__); @@ -918,6 +992,7 @@ config_sched(struct new_sch *_nsch, stru if (i <= 0 || i >= DN_MAX_ID) return EINVAL; /* XXX other sanity checks */ + bzero(&p, sizeof(0)); DUMMYNET_LOCK(); again: /* run twice, for wfq and fifo */ a.fp = find_sched_type(a.sch->oid.subtype, a.sch->type); @@ -929,25 +1004,29 @@ again: /* run twice, for wfq and fifo */ } a.sch->oid.subtype = a.fp->type; s = dn_ht_find(dn_cfg.schedhash, i, DNHT_INSERT, &a); + printf("%s start i %d ty %s -> %s\n", + __FUNCTION__, i, a.sch->type, + s ? (s->fp?"old":"new"):"none"); if (s == NULL) { DUMMYNET_UNLOCK(); printf("cannot allocate scheduler\n"); return ENOMEM; } + /* preserve existing pipe if any */ + if (p.pipe_nr) + s->pipe = p; + p.pipe_nr = 0; dn_cfg.id++; - if (s->fp != NULL) { - /* Already existing -- remove from the heaps, - * and detach flowsets from - * the old one almost as in sched_delete, but - * preserve traffic. - * XXX what about the internal queue ? - */ + if (s->fp != NULL) { /* already existing. */ + /* Detach flowsets, preserve pipe&queues. */ printf("sched %d type changed from %s to %s\n", i, s->fp->name, a.fp->name); + p = s->pipe; + /* remove from the hash */ + dn_ht_find(dn_cfg.schedhash, i, DNHT_REMOVE, NULL); schk_delete_cb(s, NULL); printf("schk_delete_cb done\n"); - notify_fs = 1; - /* now we have nothing pointing to us */ + goto again; } /* complete initialization */ s->sch = *a.sch; @@ -969,7 +1048,7 @@ again: /* run twice, for wfq and fifo */ } /* call init function after the flowset is created */ if (s->fp->config) - s->fp->config(s, 1); + s->fp->config(s); update_fs(s); if (i < DN_MAX_ID) { /* update the FIFO instance */ i += DN_MAX_ID; @@ -1042,53 +1121,6 @@ config_profile(struct new_profile *pf, s return 0; } -/* - * called on 'queue X delete' -- removes the flowset from fshash, - * deletes all queues for the flowset, and removes the flowset. - */ -static int -delete_fs(int i) -{ - struct new_fsk_head *h; - struct new_fsk *fs; - - fs = dn_ht_find(dn_cfg.fshash, i, DNHT_REMOVE, NULL); - printf("%s fs %d found %p\n", __FUNCTION__, i, fs); - if (fs == NULL) - return EINVAL; - - /* find the container list */ - h = fs->sched ? &fs->sched->fsk_list : &dn_cfg.fsu; - SLIST_REMOVE(h, fs, new_fsk, sch_chain); - dn_cfg.fsk_count--; - qht_delete(fs, 1); /* get rid of the queues */ - /* XXX possibly notify the event to the scheduler */ - if (fs->sched && fs->sched->fp->free_fsk) - fs->sched->fp->free_fsk(fs); - fs->sched = NULL; - free(fs, M_DUMMYNET); - return 0; -} - -/* - * called on a 'sched X delete' command. Deletes a single scheduler. - * This is done by removing from the schedhash, unlinking all - * flowsets and deleting their traffic. - */ -static int -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); - if (!s) - 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; -} /* * Delete all objects: @@ -1098,10 +1130,12 @@ dummynet_flush(void) { DUMMYNET_LOCK(); - /* all schedulers and related pipes/queues/flowsets */ + /* delete all schedulers and related pipes/queues/flowsets */ dn_ht_scan(dn_cfg.schedhash, schk_delete_cb, (void *)(uintptr_t)DN_DELETE_FS); - /* all remaining (unlinked) flowsets */ + /* delete all remaining (unlinked) flowsets */ + printf("%s still %d unlinked fs\n", __FUNCTION__, dn_cfg.fsk_count); + dn_ht_free(dn_cfg.fshash, DNHT_REMOVE); fsk_detach_list(&dn_cfg.fsu, DN_DELETE_FS); /* Reinitialize system heap... */ heap_init(&dn_cfg.evheap, 16, offsetof(struct dn_id, id)); @@ -1211,6 +1245,13 @@ compute_space(struct dn_id *cmd, int *to break; } *to_copy = x; + printf("have %d.%d sched %d, %d.%d pipes %d, %d.%d flows %d, " + "%d.%d si %d, %d.%d queues %d\n", + 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); if (x & DN_C_SCH) need += dn_cfg.schk_count * sizeof(struct new_sch); if (x & DN_C_FS) @@ -1278,9 +1319,15 @@ dummynet_get(struct sockopt *sopt) a.start = &buf; a.end = end; a.flags = to_copy; + a.extra = 0; + printf("copy schedulers %d)\n", + dn_ht_entries(dn_cfg.schedhash)); a.type = DN_SCH; dn_ht_scan(dn_cfg.schedhash, copy_data_helper, &a); + printf("copy unlinked flowsets %d\n", + dn_ht_entries(dn_cfg.fshash)); a.type = DN_FS; + a.extra = 1; dn_ht_scan(dn_cfg.fshash, copy_data_helper, &a); } DUMMYNET_UNLOCK(); From owner-svn-src-user@FreeBSD.ORG Tue Jan 19 19:38:03 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 9418710656A3; Tue, 19 Jan 2010 19:38:03 +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 81DAA8FC19; Tue, 19 Jan 2010 19:38:03 +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 o0JJc32B087176; Tue, 19 Jan 2010 19:38:03 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0JJc3vl087172; Tue, 19 Jan 2010 19:38:03 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <201001191938.o0JJc3vl087172@svn.freebsd.org> From: Luigi Rizzo Date: Tue, 19 Jan 2010 19:38:03 +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: r202641 - 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 19:38:03 -0000 Author: luigi Date: Tue Jan 19 19:38:03 2010 New Revision: 202641 URL: http://svn.freebsd.org/changeset/base/202641 Log: cleanup config_fs and fsk_attach/detach Modified: 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/sys/netinet/ipfw/ip_dn_io.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c Tue Jan 19 18:45:29 2010 (r202640) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c Tue Jan 19 19:38:03 2010 (r202641) @@ -220,6 +220,12 @@ dn_enqueue(struct new_queue *q, struct m struct new_inst *ni; /* stats for scheduler instance */ uint64_t len; + if (q->fs == NULL || q->_si == NULL) { + printf("%s fs %p si %p, dropping\n", + __FUNCTION__, q->fs, q->_si); + FREE_PKT(m); + return 1; + } f = &(q->fs->fs); ni = &q->_si->ni; len = m->m_pkthdr.len; Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h Tue Jan 19 18:45:29 2010 (r202640) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h Tue Jan 19 19:38:03 2010 (r202641) @@ -204,11 +204,13 @@ struct new_sch_inst { /* kernel-side flags */ enum { + /* 1 and 2 are reserved for the SCAN flags */ DN_DELETE = 0x0004, /* destroy when refcnt=0 */ DN_DELETE_FS = 0x0008, /* destroy when refcnt=0 */ - DN_ACTIVE = 0x0010, /* object is in evheap */ - DN_F_DLINE = 0x0020, /* object is a delay line */ - DN_F_SCHI = 0x0030, /* object is a sched.instance */ + DN_DETACH = 0x0010, + DN_ACTIVE = 0x0020, /* object is in evheap */ + DN_F_DLINE = 0x0040, /* object is a delay line */ + DN_F_SCHI = 0x00C0, /* object is a sched.instance */ DN_QHT_IS_Q = 0x0100, /* in flowset, qht is a single queue */ }; Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Tue Jan 19 18:45:29 2010 (r202640) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Tue Jan 19 19:38:03 2010 (r202641) @@ -500,6 +500,31 @@ fsk_new(uintptr_t key, int flags, void * return fs; } +/* detach flowset from its current scheduler */ +static void +fsk_detach(struct new_fsk *fs, int flags) +{ + if (flags & DN_DELETE_FS) + flags |= DN_DELETE; + if (flags & DN_DETACH) { /* detach from the list */ + struct new_fsk_head *h; + h = fs->sched ? &fs->sched->fsk_list : &dn_cfg.fsu; + SLIST_REMOVE(h, fs, new_fsk, sch_chain); + } + /* replica of the code in fsk_detach_list */ + qht_delete(fs, flags); + if (fs->sched && fs->sched->fp->free_fsk) + fs->sched->fp->free_fsk(fs); + fs->sched = NULL; + if (flags & DN_DELETE_FS) { + bzero(fs, sizeof(fs)); /* safety */ + free(fs, M_DUMMYNET); + dn_cfg.fsk_count--; + } else { + SLIST_INSERT_HEAD(&dn_cfg.fsu, fs, sch_chain); + } +} + /* * Detach or destroy all flowsets in a list. * flags specifies what to do: @@ -513,24 +538,10 @@ fsk_detach_list(struct new_fsk_head *h, struct new_fsk *fs; int n = 0; - if (flags & DN_DELETE_FS) - flags |= DN_DELETE; printf("+++ %s head %p flags %x\n", __FUNCTION__, h, flags); while ((fs = SLIST_FIRST(h))) { SLIST_REMOVE_HEAD(h, sch_chain); - printf(" +++ %s child fs %d\n", __FUNCTION__, fs->fs.fs_nr); - /* detach queues from the scheduler and possibly drain them */ - qht_delete(fs, flags); - if (fs->sched && fs->sched->fp->free_fsk) - fs->sched->fp->free_fsk(fs); - fs->sched = NULL; - if (flags & DN_DELETE_FS) { - bzero(fs, sizeof(fs)); /* safety */ - free(fs, M_DUMMYNET); - dn_cfg.fsk_count--; - } else { - SLIST_INSERT_HEAD(&dn_cfg.fsu, fs, sch_chain); - } + fsk_detach(fs, flags); } printf("+++ %s done %d flowsets\n", __FUNCTION__, n); } @@ -543,27 +554,13 @@ fsk_detach_list(struct new_fsk_head *h, static int delete_fs(int i) { - struct new_fsk_head *h; struct new_fsk *fs; fs = dn_ht_find(dn_cfg.fshash, i, DNHT_REMOVE, NULL); printf("%s fs %d found %p\n", __FUNCTION__, i, fs); if (fs == NULL) return EINVAL; - - /* find the container list */ - h = fs->sched ? &fs->sched->fsk_list : &dn_cfg.fsu; - SLIST_REMOVE(h, fs, new_fsk, sch_chain); - - /* replica of the code in fsk_detach_list */ - qht_delete(fs, DN_DELETE); - if (fs->sched && fs->sched->fp->free_fsk) - fs->sched->fp->free_fsk(fs); - fs->sched = NULL; - bzero(fs, sizeof(fs)); /* safety */ - free(fs, M_DUMMYNET); - dn_cfg.fsk_count--; - + fsk_detach(fs, DN_DETACH | DN_DELETE_FS); return 0; } @@ -767,12 +764,29 @@ locate_scheduler(int i) return dn_ht_find(dn_cfg.schedhash, i, 0, NULL); } +/* attach flowset to scheduler s, possibly requeue */ +static void +fsk_attach(struct new_fsk *fs, struct new_schk *s) +{ + printf("remove fs %d from fsunlinked, link to sched %d\n", + fs->fs.fs_nr, s->sch.sched_nr); + SLIST_REMOVE(&dn_cfg.fsu, fs, new_fsk, sch_chain); + fs->sched = s; + SLIST_INSERT_HEAD(&s->fsk_list, fs, sch_chain); + if (s->fp->new_fsk) + s->fp->new_fsk(fs); + if (!fs->_qht) + return; + printf("+++ %s TODO requeue from fs %d to sch %d\n", + __FUNCTION__, fs->fs.fs_nr, s->sch.sched_nr); +} + /* update all flowsets which may refer to this scheduler */ 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.sched_nr) { printf("fs %d for sch %d not %d still unlinked\n", @@ -780,17 +794,8 @@ update_fs(struct new_schk *s) s->sch.sched_nr); continue; } - printf("remove fs %d from fsunlinked, link to sched %d\n", - fs->fs.fs_nr, s->sch.sched_nr); - SLIST_REMOVE(&dn_cfg.fsu, fs, new_fsk, sch_chain); - fs->sched = s; - SLIST_INSERT_HEAD(&s->fsk_list, fs, sch_chain); - if (!fs->_qht) - continue; - printf("+++ %s requeue from fs %d to sch %d\n", - __FUNCTION__, fs->fs.fs_nr, s->sch.sched_nr); + fsk_attach(fs, s); } - printf("%s end\n", __FUNCTION__); } /* @@ -869,9 +874,8 @@ config_pipe(struct new_pipe *p, struct d static struct new_fsk * config_fs(struct new_fs *nfs, struct dn_id *arg, int locked) { - struct new_fsk *fs; - struct new_schk *s; int i; + struct new_fsk *fs; if (nfs->oid.len < sizeof(*nfs)) { printf("%s: short flowset\n", __FUNCTION__); @@ -903,64 +907,28 @@ config_fs(struct new_fs *nfs, struct dn_ if (!locked) DUMMYNET_LOCK(); do { /* exit with break when done */ - fs = dn_ht_find(dn_cfg.fshash, i, DNHT_INSERT, NULL); - if (fs == NULL) - break; - dn_cfg.id++; - if (bcmp(&fs->fs, nfs, sizeof(*nfs)) == 0) { - printf("%s no change\n", __FUNCTION__); - break; /* no change, nothing to do */ - } - s = locate_scheduler(nfs->sched_nr); -/* XXX TODO -Configuration and reconfiguration handling. -A new flowset, or one with fs->sched == NULL, has no queues. -- if it is still unattached we have nothing to do; -- if s != NULL, remove from unlinked and add to the children - of s, possibly creating the hash table (or we can postpone - it to when the first packet arrives); - -A flowset with fs->sched != NULL and with queues we have two options: -- if it becomes unlinked, then simply destroy the queues notifying - the old scheduler. -- if it becomes linked, we also need to re-enqueue the packets on - the new scheduler. - There are some easy cases (e.g. flow_mask unchanged) but - in general we should really work on every single packet. - */ - - fs->fs = *nfs; /* update config */ - /* - * XXX note that if we modify some scheduler-specific - * parameter, e.g. weights, we must notify the - * scheduler otherwise things might go really badly, - * such as sum-of-weights mismatches. - */ - if (fs->sched != NULL) { - /* XXX TODO: if the scheduler does not exist - * anymore, then all queues should be drained. - * If there is a new scheduler, then move - * queues from the old to the new one. - */ - /* we had a scheduler before, let the flowset - * die and create a new one with the new - * parameters. - */ - fs->kflags |= DN_DELETE; - continue; - } - if (s == NULL) - break; + struct new_schk *s; - /* have a new scheduler, remove from unlinked - * and add to the list of children of s - */ - SLIST_REMOVE(&dn_cfg.fsu, fs, new_fsk, sch_chain); - fs->sched = s; - SLIST_INSERT_HEAD(&s->fsk_list, fs, sch_chain); - /* _qht is initialized on first use */ - if (s->fp->new_fsk) - s->fp->new_fsk(fs); + fs = dn_ht_find(dn_cfg.fshash, i, DNHT_INSERT, NULL); + if (fs == NULL) + break; + dn_cfg.id++; + if (bcmp(&fs->fs, nfs, sizeof(*nfs)) == 0) { + printf("%s no change\n", __FUNCTION__); + break; /* no change, nothing to do */ + } + s = locate_scheduler(nfs->sched_nr); + /* detach from old scheduler if needed, preserving + * queues if we need to reattach. Then update the + * configuration, and possibly attach to the new sched. + */ + if (fs->sched) { + int flags = s ? DN_DETACH : (DN_DETACH | DN_DELETE); + fsk_detach(fs, flags); + } + fs->fs = *nfs; /* copy configuration */ + if (s != NULL) + fsk_attach(fs, s); } while (0); if (!locked) DUMMYNET_UNLOCK(); @@ -1017,7 +985,12 @@ again: /* run twice, for wfq and fifo */ s->pipe = p; p.pipe_nr = 0; dn_cfg.id++; - if (s->fp != NULL) { /* already existing. */ + if (s->fp == NULL) { + printf("%s sched %d new type %s\n", __FUNCTION__, i, + a.fp->name); + } else if (s->fp != a.fp || + bcmp(a.sch, &s->sch, sizeof(*a.sch)) ) { + /* already existing. */ /* Detach flowsets, preserve pipe&queues. */ printf("sched %d type changed from %s to %s\n", i, s->fp->name, a.fp->name); @@ -1027,6 +1000,9 @@ again: /* run twice, for wfq and fifo */ schk_delete_cb(s, NULL); printf("schk_delete_cb done\n"); goto again; + } else { + printf("%s sched %d unchanged type %s\n", __FUNCTION__, i, + a.fp->name); } /* complete initialization */ s->sch = *a.sch; @@ -1121,7 +1097,6 @@ config_profile(struct new_profile *pf, s return 0; } - /* * Delete all objects: */ @@ -1129,7 +1104,6 @@ static void dummynet_flush(void) { - DUMMYNET_LOCK(); /* delete all schedulers and related pipes/queues/flowsets */ dn_ht_scan(dn_cfg.schedhash, schk_delete_cb, (void *)(uintptr_t)DN_DELETE_FS); @@ -1139,8 +1113,6 @@ dummynet_flush(void) fsk_detach_list(&dn_cfg.fsu, DN_DELETE_FS); /* Reinitialize system heap... */ heap_init(&dn_cfg.evheap, 16, offsetof(struct dn_id, id)); - - DUMMYNET_UNLOCK(); } /* @@ -1167,6 +1139,7 @@ do_config(void *p, int l) l -= o->len; next = (struct dn_id *)((char *)o + o->len); err = 0; + DUMMYNET_LOCK(); switch (o->type) { default: printf("cmd %d not implemented\n", o->type); @@ -1179,10 +1152,8 @@ do_config(void *p, int l) switch (o->subtype) { case DN_PIPE: /* delete base and derived schedulers */ - DUMMYNET_LOCK(); err = delete_schk(o->id); err2 = delete_schk(o->id + DN_MAX_ID); - DUMMYNET_UNLOCK(); if (!err) err = err2; break; @@ -1220,6 +1191,7 @@ do_config(void *p, int l) err = (NULL==config_fs((struct new_fs *)o, arg, 0)); break; } + DUMMYNET_UNLOCK(); if (prev) arg = NULL; if (err != 0) From owner-svn-src-user@FreeBSD.ORG Tue Jan 19 23:03:08 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 EA8CD10656C3; Tue, 19 Jan 2010 23:03:08 +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 D89F18FC1C; Tue, 19 Jan 2010 23:03:08 +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 o0JN38on033405; Tue, 19 Jan 2010 23:03:08 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0JN38Q3033399; Tue, 19 Jan 2010 23:03:08 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <201001192303.o0JN38Q3033399@svn.freebsd.org> From: Luigi Rizzo Date: Tue, 19 Jan 2010 23:03:08 +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: r202660 - in user/luigi/ipfw3-head: sbin/ipfw 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 23:03:09 -0000 Author: luigi Date: Tue Jan 19 23:03:08 2010 New Revision: 202660 URL: http://svn.freebsd.org/changeset/base/202660 Log: fix reconfiguration (still dropping packets in the process) Modified: user/luigi/ipfw3-head/sbin/ipfw/dummynet.c 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_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 Tue Jan 19 22:44:29 2010 (r202659) +++ user/luigi/ipfw3-head/sbin/ipfw/dummynet.c Tue Jan 19 23:03:08 2010 (r202660) @@ -1104,8 +1104,10 @@ end_mask: p->bandwidth = 0; } if (fs) { +#if 0 /* XXX accept a 0 scheduler to keep the default */ if (fs->sched_nr == 0) errx(EX_DATAERR, "sched must be > 0"); +#endif if (fs->flags & DN_QSIZE_IS_BYTES) { size_t len; Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h Tue Jan 19 22:44:29 2010 (r202659) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h Tue Jan 19 23:03:08 2010 (r202660) @@ -125,7 +125,7 @@ struct dn_sched { * if the refcount becomes 0 */ void dn_free_pkts(struct mbuf *mnext); -struct new_queue *dn_delete_queue(struct new_queue *, int do_free); +void dn_delete_queue(struct new_queue *, int do_free); int dn_enqueue(struct new_queue *q, struct mbuf* m, int drop); /* @@ -145,8 +145,6 @@ dn_dequeue(struct new_queue *q) q->_si->ni.length--; q->_si->ni.len_bytes -= m->m_pkthdr.len; } - if (q->mq.head == NULL && q->fs && q->fs->kflags & DN_DELETE) - (void)dn_delete_queue(q, 1 /* free if possible */); return m; } Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c Tue Jan 19 22:44:29 2010 (r202659) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c Tue Jan 19 23:03:08 2010 (r202660) @@ -602,7 +602,7 @@ dummynet_io(struct mbuf **m0, int dir, s if (fs->sched->fp->enqueue(si, q, m)) { printf("%s dropped by enqueue\n", __FUNCTION__); /* packet was dropped by enqueue() */ - *m0 = NULL; + m = *m0 = NULL; goto dropit; } @@ -646,7 +646,8 @@ done: dropit: io_pkt_drop++; DUMMYNET_UNLOCK(); - FREE_PKT(m); + if (m) + FREE_PKT(m); *m0 = NULL; return (fs && (fs->fs.flags & DN_NOERROR)) ? 0 : ENOBUFS; } Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h Tue Jan 19 22:44:29 2010 (r202659) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h Tue Jan 19 23:03:08 2010 (r202660) @@ -52,6 +52,18 @@ SLIST_HEAD(new_fsk_head, new_fsk); SLIST_HEAD(new_queue_head, new_queue); SLIST_HEAD(dn_sched_head, dn_sched); +struct mq { /* a basic queue of packets*/ + struct mbuf *head, *tail; +}; + +static inline void +set_oid(struct dn_id *o, int type, int len) +{ + o->type = type; + o->len = len; + o->subtype = 0; +}; + /* * configuration and global data for a dummynet instance * @@ -82,27 +94,23 @@ struct dn_parms { int fsk_count; int queue_count; - /* flowsets and schedulers are in hash tables, whose size - * is programmable. fshash is looked up at every packet arrival + /* flowsets and schedulers are in hash tables, with 'hash_size' + * buckets. fshash is looked up at every packet arrival * so better be generous if we expect many entries. */ struct dn_ht *fshash; struct dn_ht *schedhash; /* list of flowsets without a scheduler -- use sch_chain */ - struct new_fsk_head fsu; + struct new_fsk_head fsu; /* list of unlinked flowsets */ struct dn_sched_head schedlist; /* list of algorithms */ -}; -static inline void -set_oid(struct dn_id *o, int type, int len) -{ - o->type = type; - o->len = len; - o->subtype = 0; -}; - -struct mq { /* a basic queue of packets*/ - struct mbuf *head, *tail; + /* if the upper half is busy doing something long, + * can set the busy flag and we will enqueue packets in + * a queue for later processing. + */ + int busy; + struct mq pending; + }; /* @@ -116,31 +124,23 @@ struct delay_line { }; /* - * The kernel side of a flowset. In addition to the user parameters - * and kernel flags, it is linked in a hash table of flowsets, - * and in a list of children of their parent scheduler. - * It also contains a hash table of children queues (or one, if - * there is no flow_mask). - * When we remove a flowset, mark as DN_DELETE so it can go away - * when the hash table will be empty. - * XXX refcnt is redundant, the info is already in qht->entries - * If we want to add scheduler-specific parameters, we need to + * The kernel side of a flowset. It is linked in a hash table + * of flowsets, and in a list of children of their parent scheduler. + * qht is either the queue or (if HAVE_MASK) a hash table queues. + * XXX If we want to add scheduler-specific parameters, we need to * put them in external storage because the scheduler may not be * available when the fsk is created. */ struct new_fsk { /* kernel side of a flowset */ struct new_fs fs; SLIST_ENTRY(new_fsk) fsk_next; /* hash chain list */ - int kflags; /* kernel-side flags */ int refcnt; /* entries in qht */ - /* hash table of queues. XXX if we have no flow_mask we could - * avoid the hash table and just allocate one queue. - */ + /* hash table of queues, or just single queue */ 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 */ + // void *sched_info; /* scheduler-specific info */ }; /* Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Tue Jan 19 22:44:29 2010 (r202659) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Tue Jan 19 23:03:08 2010 (r202660) @@ -257,12 +257,12 @@ q_new(uintptr_t key, int flags, void *ar } /* - * 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. + * Notify schedulers that a queue is going away. + * If (flags & DN_DELETE), also free the packets. + * The version for callbacks is called q_delete_cb(). */ -struct new_queue * -dn_delete_queue(struct new_queue *q, int do_free) +void +dn_delete_queue(struct new_queue *q, int flags) { struct new_fsk *fs = q->fs; @@ -271,21 +271,21 @@ dn_delete_queue(struct new_queue *q, int if (fs && fs->sched->fp->free_queue) fs->sched->fp->free_queue(q); q->_si = NULL; - 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; + if (flags & DN_DELETE) { + if (q->mq.head) + dn_free_pkts(q->mq.head); + free(q, M_DUMMYNET); + dn_cfg.queue_count--; + fs->refcnt--; + } } static int q_delete_cb(void *q, void *arg) { - (void)dn_delete_queue(q, (int)(uintptr_t)arg); - return 0; + int flags = (int)(uintptr_t)arg; + dn_delete_queue(q, flags); + return (flags & DN_DELETE) ? DNHT_SCAN_DEL : 0; } /* @@ -296,22 +296,26 @@ q_delete_cb(void *q, void *arg) static void qht_delete(struct new_fsk *fs, int flags) { - printf("+++ %s fs %d start\n", __FUNCTION__, fs->fs.fs_nr); + printf("+++ %s fs %d start flags %d qht %p\n", + __FUNCTION__, fs->fs.fs_nr, flags, fs->_qht); 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 { + if (fs->fs.flags & DN_HAVE_MASK) { dn_ht_scan(fs->_qht, q_delete_cb, (void *)flags); if (flags & DN_DELETE) { dn_ht_free(fs->_qht, 0); fs->_qht = NULL; } + } else { + dn_delete_queue((struct new_queue *)(fs->_qht), flags); + if (flags & DN_DELETE) + fs->_qht = NULL; } } /* - * only called in the DN_MULTIQUEUE CASE so we can handle errors + * 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 * @@ -319,6 +323,7 @@ ipdn_q_find(struct new_fsk *fs, struct n struct ipfw_flow_id *id) { struct new_queue template; + template._si = si; template.fs = fs; @@ -330,7 +335,6 @@ ipdn_q_find(struct new_fsk *fs, struct n q_hash, q_match, q_new); if (fs->_qht == NULL) return NULL; - fs->kflags &= ~DN_QHT_IS_Q; } masked_id = *id; flow_id_mask(&fs->fs.flow_mask, &masked_id); @@ -339,7 +343,6 @@ ipdn_q_find(struct new_fsk *fs, struct n } else { if (fs->_qht == NULL) fs->_qht = q_new(0, 0, &template); - fs->kflags |= DN_QHT_IS_Q; return (struct new_queue *)fs->_qht; } } @@ -395,12 +398,9 @@ si_new(uintptr_t key, int flags, void *a si->sched = s; si->dline.si = si; - if (s->fp->new_sched) { - int ret = s->fp->new_sched(si); - if (ret) { - printf("%s: new_sched error %d\n", __FUNCTION__, ret); - goto error; - } + if (s->fp->new_sched && s->fp->new_sched(si)) { + printf("%s: new_sched error\n", __FUNCTION__); + goto error; } if (s->sch.flags & DN_HAVE_MASK) si->ni.id = *(struct ipfw_flow_id *)key; @@ -415,10 +415,10 @@ error: } /* - * callback from siht to delete all scheduler instances. + * Callback from siht to delete all scheduler instances. Remove + * si and delay line from the system heap, destroy all queues. * We assume that all flowset have been notified and do not * point to us anymore. - * Remove si and delay line from the system heap, destroy all queues. */ static int si_destroy(void *_si, void *arg) @@ -434,6 +434,7 @@ si_destroy(void *_si, void *arg) heap_extract(&dn_cfg.evheap, si); if (s->fp->free_sched) s->fp->free_sched(si); + bzero(si, sizeof(*si)); /* safety */ free(si, M_DUMMYNET); dn_cfg.si_count--; return 0; @@ -446,18 +447,37 @@ si_destroy(void *_si, void *arg) struct new_sch_inst * ipdn_si_find(struct new_schk *s, struct ipfw_flow_id *id) { - struct new_sch_inst *si; - if (!(s->sch.flags & DN_HAVE_MASK)) { - if (s->siht == NULL) - s->siht = si_new((uintptr_t)id, 0, s); - si = (struct new_sch_inst *)s->siht; - } else { + if (s->sch.flags & DN_HAVE_MASK) { struct ipfw_flow_id id_t = *id; flow_id_mask(&s->sch.sched_mask, &id_t); - si = dn_ht_find(s->siht, (uintptr_t)&id_t, DNHT_INSERT, s); + 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; } - return si; +} + +/* callback to flush credit for the scheduler instance */ +static int +si_reset_credit(void *_si, void *arg) +{ + struct new_sch_inst *si = _si; + struct new_pipe *p = &si->sched->pipe; + + si->credit = p->burst + (dn_cfg.io_fast ? p->bandwidth : 0); + return 0; +} + +static void +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) + si_reset_credit(s->siht, NULL); } /*---- end of sch_inst hashtable ---------------------*/ @@ -469,13 +489,12 @@ ipdn_si_find(struct new_schk *s, struct static int fsk_hash(uintptr_t key, int flags, void *arg) { - int i = ((flags & DNHT_KEY_IS_OBJ) == 0) ? key : + int i = !(flags & DNHT_KEY_IS_OBJ) ? key : ((struct new_fsk *)key)->fs.fs_nr; return ( (i>>8)^(i>>4)^i ); } -/* match skips entries those marked as deleted */ static int fsk_match(void *obj, uintptr_t key, int flags, void *arg) { @@ -483,7 +502,7 @@ fsk_match(void *obj, uintptr_t key, int int i = !(flags & DNHT_KEY_IS_OBJ) ? key : ((struct new_fsk *)key)->fs.fs_nr; - return !(fs->kflags & DN_DELETE) && (fs->fs.fs_nr == i); + return (fs->fs.fs_nr == i); } static void * @@ -500,18 +519,27 @@ fsk_new(uintptr_t key, int flags, void * return fs; } -/* detach flowset from its current scheduler */ +/* + * detach flowset from its current scheduler. Flags as follows: + * DN_DETACH removes from the fsk_list + * DN_DELETE deletes individual queues + * DN_DELETE_FS destroys the flowset (otherwise goes in unlinked). + */ static void fsk_detach(struct new_fsk *fs, int flags) { if (flags & DN_DELETE_FS) flags |= DN_DELETE; + printf("%s fs %d from sched %d flags %s %s %s\n", + __FUNCTION__, fs->fs.fs_nr, fs->fs.sched_nr, + (flags & DN_DELETE_FS) ? "DEL_FS":"", + (flags & DN_DELETE) ? "DEL":"", + (flags & DN_DETACH) ? "DET":""); if (flags & DN_DETACH) { /* detach from the list */ struct new_fsk_head *h; h = fs->sched ? &fs->sched->fsk_list : &dn_cfg.fsu; SLIST_REMOVE(h, fs, new_fsk, sch_chain); } - /* replica of the code in fsk_detach_list */ qht_delete(fs, flags); if (fs->sched && fs->sched->fp->free_fsk) fs->sched->fp->free_fsk(fs); @@ -536,7 +564,7 @@ static void fsk_detach_list(struct new_fsk_head *h, int flags) { struct new_fsk *fs; - int n = 0; + int n = 0; /* only for stats */ printf("+++ %s head %p flags %x\n", __FUNCTION__, h, flags); while ((fs = SLIST_FIRST(h))) { @@ -552,16 +580,23 @@ fsk_detach_list(struct new_fsk_head *h, * XXX note that fsk_detach_list also destroys a flowset. */ static int -delete_fs(int i) +delete_fs(int i, int locked) { struct new_fsk *fs; + int err = 0; + if (!locked) + DUMMYNET_LOCK(); fs = dn_ht_find(dn_cfg.fshash, i, DNHT_REMOVE, NULL); printf("%s fs %d found %p\n", __FUNCTION__, i, fs); - if (fs == NULL) - return EINVAL; - fsk_detach(fs, DN_DETACH | DN_DELETE_FS); - return 0; + if (fs) { + fsk_detach(fs, DN_DETACH | DN_DELETE_FS); + err = 0; + } else + err = EINVAL; + if (!locked) + DUMMYNET_UNLOCK(); + return err; } /*----- end of flowset hashtable support -------------*/ @@ -671,29 +706,10 @@ 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; -} - -/* callback to flush credit for the pipe */ -static int -reset_credit(void *_si, void *arg) -{ - struct new_sch_inst *si = _si; - struct new_pipe *p = &si->sched->pipe; - - si->credit = p->burst + (dn_cfg.io_fast ? p->bandwidth : 0); + delete_fs(i + DN_MAX_ID, 1); /* remove internal pipe */ return 0; } -static void -schk_reset_credit(struct new_schk *s) -{ - if (s->sch.flags & DN_HAVE_MASK) - dn_ht_scan(s->siht, reset_credit, NULL); - else if (s->siht) - reset_credit(s->siht, NULL); -} /*--- end of schk hashtable support ---*/ @@ -912,6 +928,14 @@ config_fs(struct new_fs *nfs, struct dn_ fs = dn_ht_find(dn_cfg.fshash, i, DNHT_INSERT, NULL); if (fs == NULL) break; + if (nfs->sched_nr == 0) { + printf("reuse existing number %d\n", fs->fs.sched_nr); + if (fs->fs.sched_nr == 0) { + fs = NULL; + break; + } + nfs->sched_nr = fs->fs.sched_nr; + } dn_cfg.id++; if (bcmp(&fs->fs, nfs, sizeof(*nfs)) == 0) { printf("%s no change\n", __FUNCTION__); @@ -924,6 +948,7 @@ config_fs(struct new_fs *nfs, struct dn_ */ if (fs->sched) { int flags = s ? DN_DETACH : (DN_DETACH | DN_DELETE); + flags |= DN_DELETE; /* XXX temporary */ fsk_detach(fs, flags); } fs->fs = *nfs; /* copy configuration */ @@ -1139,7 +1164,6 @@ do_config(void *p, int l) l -= o->len; next = (struct dn_id *)((char *)o + o->len); err = 0; - DUMMYNET_LOCK(); switch (o->type) { default: printf("cmd %d not implemented\n", o->type); @@ -1152,8 +1176,10 @@ do_config(void *p, int l) switch (o->subtype) { case DN_PIPE: /* delete base and derived schedulers */ + DUMMYNET_LOCK(); err = delete_schk(o->id); err2 = delete_schk(o->id + DN_MAX_ID); + DUMMYNET_UNLOCK(); if (!err) err = err2; break; @@ -1166,13 +1192,15 @@ do_config(void *p, int l) case DN_FS: err = (o->id < 1 || o->id >= DN_MAX_ID) ? - EINVAL : delete_fs(o->id) ; + EINVAL : delete_fs(o->id, 0) ; break; } break; case DN_CMD_FLUSH: + DUMMYNET_LOCK(); dummynet_flush(); + DUMMYNET_UNLOCK(); break; case DN_TEXT: /* store argument the next block */ prev = NULL; @@ -1191,7 +1219,6 @@ do_config(void *p, int l) err = (NULL==config_fs((struct new_fs *)o, arg, 0)); break; } - DUMMYNET_UNLOCK(); if (prev) arg = NULL; if (err != 0) From owner-svn-src-user@FreeBSD.ORG Wed Jan 20 08:41:59 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 03A07106566B; Wed, 20 Jan 2010 08:41:59 +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 E5BD78FC1A; Wed, 20 Jan 2010 08:41: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 o0K8fwIs061523; Wed, 20 Jan 2010 08:41:58 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0K8fwDL061518; Wed, 20 Jan 2010 08:41:58 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <201001200841.o0K8fwDL061518@svn.freebsd.org> From: Luigi Rizzo Date: Wed, 20 Jan 2010 08:41: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: r202680 - 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: Wed, 20 Jan 2010 08:41:59 -0000 Author: luigi Date: Wed Jan 20 08:41:58 2010 New Revision: 202680 URL: http://svn.freebsd.org/changeset/base/202680 Log: rename locks Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dummynet.txt 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/sys/netinet/ipfw/dummynet.txt ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dummynet.txt Wed Jan 20 07:36:29 2010 (r202679) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dummynet.txt Wed Jan 20 08:41:58 2010 (r202680) @@ -1,5 +1,6 @@ Notes on the internal structure of dummynet (2010 version) by Riccardo Panicucci and Luigi Rizzo +Work supported by the EC project ONELAB2 ********* * INDEX * @@ -67,8 +68,10 @@ Internal structure Dummynet-related data is split into several data structures, part of them constituting the userland-kernel API, and others specific to the kernel. +NOTE: for up-to-date details please look at the relevant source + headers (ip_dummynet.h, ip_dn_private.h, dn_sched.h) -USERLAND-KERNEL API +USERLAND-KERNEL API (ip_dummynet.h) struct new_pipe: contains data about the physical link such as @@ -88,40 +91,38 @@ USERLAND-KERNEL API buckets, queue size, plr, weight, and other scheduler-specific parameters. -KERNEL REPRESENTATION +KERNEL REPRESENTATION (ip_dn_private.h) struct new_queue - individual queue of packets, which are created by a - flowset and attached to a scheduler instance. + individual queue of packets, created by a flowset using + flow_mask and attached to a scheduler instance selected + through sched_mask. A new_queue has a pointer to the new_fsk (which in turn counts how many queues point to it), a pointer to the - new_sch_inst it attaches to, and is linked in a list - of queues attached to the new_sch_inst + new_sch_inst it attaches to, and is in a hash table in the + flowset. scheduler instances also should store queues in + their own containers used for scheduling (lists, trees, etc.) CREATE: done on packet arrivals when a flow matches a flowset. DELETE: done only when deleting the parent new_sch_inst + or draining memory. struct new_fsk includes a new_fs; a pointer to the new_schk; a link field - for the list of new_fsk attached to the same scheduler; + for the list of new_fsk attached to the same scheduler, + or for the unlinked list; a refcount for the number of queues pointing to it; - The new_fsk is in a hash table when it is attached to a - scheduler, or in the fsunlinked list when shutting down - or no scheduler is active. + The new_fsk is in a hash table, fshash. CREATE: done on configuration commands. - DELETE: configuration commands mark the flowset as DN_DELETE, - and move it to fsunlinked. Then as queue are drained, - they are deleted and when the last one goes away, - also the flowset goes away. + DELETE: on configuration commands. struct new_sch_inst a scheduler instance, created from a new_schk applying sched_mask. - Contains a delay line, a list of queues, and a reference to the - parent. Both new_sch_inst and its delay line can be in the - system_heap if they have events to be processed. + Contains a delay line, a reference to the parent, and scheduler- + specific info. Both new_sch_inst and its delay line can be in the + evheap if they have events to be processed. CREATE: created from a new_schk applying sched_mask DELETE: configuration command delete a scheduler which in turn - sweeps the hash table of instances, deletes all queues - and then the instance. + sweeps the hash table of instances deleting them struct new_schk includes new_sch, new_pipe, a pointer to new_profile, @@ -153,34 +154,30 @@ KERNEL REPRESENTATION The following global data structures contain all schedulers and flowsets. -- schedulerhash[x]: contains all scheduler templates in the system - this needs to be a hash table because we may have to do - a lookup upon arrival of a packet. +- schedhash[x]: contains all scheduler templates in the system. + Looked up only on manual configurations, where flowsets + are attached to matching schedulers. We have one entry per 'sched X config' command (plus one for each 'pipe X config'). -- flowsethash[x]: contains all flowset linked with a scheduler (or pipe). - we do a lookup on this for each packet. +- fshash[x]: contains all flowsets. + We do a lookup on this for each packet. We have one entry for each 'queue X config' (plus one for each 'pipe X config'). Additionally, a list that contains all unlinked flowset: -- unlinkedflowset: contains flowset that are not linked with any scheduler - flowset are put in this list when they refer to a non - existing scheduler or pipe. - We keep them out of the main hash table because we do not - want to send packets to those flowsets. +- fsu: contains flowset that are not linked with any scheduler. + Flowset are put in this list when they refer to a non + existing scheduler. We don't need an efficient data structure as we never search - here on a packet arrival -- at most we put here a flowset - for which a scheduler does not exist anymore. + here on a packet arrivals. Scheduler instances and the delay lines associated with each scheduler instance need to be woken up at certain times. Because we have many such objects, we keep them in a priority heap (system_heap). -Almost all objects in this implementation are preceded -by a structure (struct dn_id) which makes it easier to -identify it. +Almost all objects in this implementation are preceded by a structure +(struct dn_id) which makes it easier to identify them. Files @@ -188,50 +185,60 @@ Files New dummynet is split in several files. Two headers, a file to implement the userland part and some files for the kernel side are provided. -- ip_dummynet_s.h is the minimal header that is used to implement +- dn_sched.h is the minimal header that is used to implement a scheduler -- ip_dummynet.h is the main header, that includes the ip_dummynet_s.h and is - use by both kernel and user space. +- ip_dummynet.h is the main header defining the kenrel-userland API +- ip_dn_io.c is the main files for the kernel side of dummynet. It contains + main functions for processing packets, some functions exported to help + writing new scheduler; +- ip_dummynet.c cointains module glue and sockopt handlers. - dummynet.c is the file used to implement the user side of dummynet. It contains the function to parsing command line, and functions to show the output of dummynet objects. -- ip_dummynet.c is the main files for the kernel side of dummynet. It contains - main functions for processing packets, some functions exported to help - writing new scheduler, and the handler for the various dummynet socket - options. -- ip_dummynet_config.c cointains functions to create and delete objects. -- ip_dummynet_get.c contains functions to prepare the buffer to pass to - userland to show object info. Moreover, there are two new file (ip_dummynet_glue.c and ip_fw_glue.c) that are used to allow compatibility with the "ipfw" binary from FreeBSd 7.2 and FreeBSD 8. +LOCKING +======= +At the moment the entire processing occurs under a single lock +which is expected to be acquired in exclusive mode +DN_BH_WLOCK() / DN_BH_WUNLOCK(). + +In perspective we aim at the following: +- the 'busy' flag, 'pending' list and all structures modified by packet + arrivals and departures are protected by the BH_WLOCK. + This is normally acquired in exclusive mode by the packet processing + functions for short sections of code (exception -- the timer). + If 'busy' is not set, we can do regular packet processing. + If 'busy' is set, no pieces can be accessed. + We must enqueue the packet on 'pending' and return immediately. + +- the 'busy' flag is set/cleared by long sections of code as follows: + UH_WLOCK(); KASSERT(busy == 0); + BH_WLOCK(); busy=1; BH_WUNLOCK(); + ... do processing ... + BH_WLOCK(); busy=0; drain_queue(pending); BH_WUNLOCK(); + UH_WUNLOCK(); + this normally happens when the upper half has something heavy + to do. The prologue and epilogue are not in the critical path. + +- the main containers (fshash, schedhash, ...) are protected by + UH_WLOCK. + + TO BE COMPLETED -Packet arrival +Packet processing ============== -A packet enter in dummynet process throught the function dummynet_io(). -When a packet arrives, first it is checked the flow set number and the flowset -is searched in the flowset list and if it isn't found the packet is dropped. -Dummynet uses a generation number to check if pointers are valid. The -flowset has a pointer to the scheduler that could be deleted, so in the -flowset struct there is a value that contain a number. If this number doesn't -match the generation number, a reconfigure routine is started to check if -pointers are valid. The generation number is incremented when a change in -the internal struct occurs (for example when a new object is inserted or -deleted). - -At this point, the pointer to the scheduler is valid, and the scheduler -instance is searched from all scheduler instance of the scheduler, depending -of the sched_mask field. If a scheduler instance isn't found, a new one is -created now. - -Now the enqueue() function of the scheduler is called and if the scheduler -instance was idle the dequeue() function is called now, else it will -be called by system later. After the dequeue(), the packet returned is moved -in the delay line and send after a delay depending on link parameters. -See ip_dummynet.c dummynet_io() function for more details +A packet enters dummynet through dummynet_io(). We first lookup +the flowset number in fshash(), then possibly use masks to determine +queue and scheduler instance, and call the enqueue routine for the +scheduler. +If enqueue is successful, we may call dequeue for further processing, +and possibly return the packet upstream. If the packet does not +return, it will be sent later according to the scheduler. -The reconfiguretion routine +The reconfiguration routine --------------------------- The reconfigure routine is called by the system when the flowset ptr_sched_val number differs from the generation number. This means that a new object is Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c Wed Jan 20 07:36:29 2010 (r202679) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c Wed Jan 20 08:41:58 2010 (r202680) @@ -377,7 +377,7 @@ dummynet_task(void *context, int pending struct timeval t; struct mq q = { NULL, NULL }; /* queue to accumulate results */ - DUMMYNET_LOCK(); + DN_BH_WLOCK(); /* Update number of lost(coalesced) ticks. */ tick_lost += pending - 1; @@ -431,7 +431,7 @@ dummynet_task(void *context, int pending transmit_event(&q, (struct delay_line *)p, curr_time); } } - DUMMYNET_UNLOCK(); + DN_BH_WUNLOCK(); dn_reschedule(); if (q.head != NULL) dummynet_send(q.head); @@ -570,13 +570,22 @@ dummynet_io(struct mbuf **m0, int dir, s struct new_fsk *fs = NULL; struct new_sch_inst *si; struct new_queue *q = NULL; /* default */ - dn_key now; /* save a copy of curr_time */ int fs_id = (fwa->rule.info & IPFW_INFO_MASK) + ((fwa->rule.info & IPFW_IS_PIPE) ? 2*DN_MAX_ID : 0); - DUMMYNET_LOCK(); + DN_BH_WLOCK(); io_pkt++; - now = curr_time; + /* we could actually tag outside the lock, but who cares... */ + if (tag_mbuf(m, dir, fwa)) + goto dropit; + if (dn_cfg.busy) { + /* if the upper half is busy doing something expensive, + * lets queue the packet and move forward + */ + mq_append(&dn_cfg.pending, m); + m = *m0 = NULL; /* consumed */ + goto done; /* already active, nothing to do */ + } /* XXX locate_flowset could be optimised with a direct ref. */ fs = dn_ht_find(dn_cfg.fshash, fs_id, 0, NULL); if (fs == NULL) @@ -587,8 +596,6 @@ dummynet_io(struct mbuf **m0, int dir, s si = ipdn_si_find(fs->sched, &(fwa->f_id)); if (si == NULL) goto dropit; - if (tag_mbuf(m, dir, fwa)) - goto dropit; /* * If the support multiple queues, find the right one * (otherwise it will be ignored by enqueue). @@ -616,14 +623,14 @@ dummynet_io(struct mbuf **m0, int dir, s struct new_pipe *p = &fs->sched->pipe; si->credit = dn_cfg.io_fast ? p->bandwidth : 0; if (p->burst) { - uint64_t burst = (now - si->idle_time) * p->bandwidth; + uint64_t burst = (curr_time - si->idle_time) * p->bandwidth; if (burst > p->burst) burst = p->burst; si->credit += burst; } } /* pass through scheduler and delay line */ - m = serve_sched(NULL, si, now); + m = serve_sched(NULL, si, curr_time); /* optimization -- pass it back to ipfw for immediate send */ if (dn_cfg.io_fast && m == *m0 && (dir & PROTO_LAYER2) == 0 ) { @@ -638,14 +645,14 @@ dummynet_io(struct mbuf **m0, int dir, s *m0 = NULL; } done: - DUMMYNET_UNLOCK(); + DN_BH_WUNLOCK(); if (m) dummynet_send(m); return 0; dropit: io_pkt_drop++; - DUMMYNET_UNLOCK(); + DN_BH_WUNLOCK(); if (m) FREE_PKT(m); *m0 = NULL; Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h Wed Jan 20 07:36:29 2010 (r202679) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h Wed Jan 20 08:41:58 2010 (r202680) @@ -38,13 +38,27 @@ MALLOC_DECLARE(M_DUMMYNET); #endif #define div64(a, b) ((int64_t)(a) / (int64_t)(b)) -extern struct mtx dummynet_mtx; -#define DUMMYNET_LOCK_INIT() \ - mtx_init(&dummynet_mtx, "dummynet", NULL, MTX_DEF) -#define DUMMYNET_LOCK_DESTROY() mtx_destroy(&dummynet_mtx) -#define DUMMYNET_LOCK() mtx_lock(&dummynet_mtx) -#define DUMMYNET_UNLOCK() mtx_unlock(&dummynet_mtx) -#define DUMMYNET_LOCK_ASSERT() mtx_assert(&dummynet_mtx, MA_OWNED) +#define DN_LOCK_INIT() do { \ + mtx_init(&dn_cfg.uh_mtx, "dn_uh", NULL, MTX_DEF); \ + mtx_init(&dn_cfg.bh_mtx, "dn_bh", NULL, MTX_DEF); \ + } while (0) +#define DUMMYNET_LOCK_DESTROY() do { \ + mtx_destroy(&dn_cfg.uh_mtx); \ + mtx_destroy(&dn_cfg.bh_mtx); \ + } while (0) +#if 0 /* not used yet */ +#define DN_UH_RLOCK() mtx_lock(&dn_cfg.uh_mtx) +#define DN_UH_RUNLOCK() mtx_unlock(&dn_cfg.uh_mtx) +#define DN_UH_WLOCK() mtx_lock(&dn_cfg.uh_mtx) +#define DN_UH_WUNLOCK() mtx_unlock(&dn_cfg.uh_mtx) +#define DN_UH_LOCK_ASSERT() mtx_assert(&dn_cfg.uh_mtx, MA_OWNED) +#endif + +#define DN_BH_RLOCK() mtx_lock(&dn_cfg.uh_mtx) +#define DN_BH_RUNLOCK() mtx_unlock(&dn_cfg.uh_mtx) +#define DN_BH_WLOCK() mtx_lock(&dn_cfg.uh_mtx) +#define DN_BH_WUNLOCK() mtx_unlock(&dn_cfg.uh_mtx) +#define DN_BH_LOCK_ASSERT() mtx_assert(&dn_cfg.uh_mtx, MA_OWNED) SLIST_HEAD(new_schk_head, new_schk); SLIST_HEAD(new_sch_inst_head, new_sch_inst); @@ -110,7 +124,16 @@ struct dn_parms { */ int busy; struct mq pending; - + + /* uh_mtx arbitrates between system calls and also + * protects fshash, schedhash and fsunlinked. + * These structures are readonly for the lower half. + */ + struct mtx uh_mtx; + /* bh_mtx protects all other structures which may be + * modified upon packet arrivals + */ + struct mtx bh_mtx; }; /* Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Wed Jan 20 07:36:29 2010 (r202679) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Wed Jan 20 08:41:58 2010 (r202680) @@ -586,7 +586,7 @@ delete_fs(int i, int locked) int err = 0; if (!locked) - DUMMYNET_LOCK(); + DN_BH_WLOCK(); fs = dn_ht_find(dn_cfg.fshash, i, DNHT_REMOVE, NULL); printf("%s fs %d found %p\n", __FUNCTION__, i, fs); if (fs) { @@ -595,7 +595,7 @@ delete_fs(int i, int locked) } else err = EINVAL; if (!locked) - DUMMYNET_UNLOCK(); + DN_BH_WUNLOCK(); return err; } @@ -862,12 +862,12 @@ config_pipe(struct new_pipe *p, struct d /* Scale burst size: bytes -> bits * hz */ p->burst *= 8 * hz; - DUMMYNET_LOCK(); + DN_BH_WLOCK(); /* do it twice, base pipe and FIFO pipe */ for (; i < 2*DN_MAX_ID; i += DN_MAX_ID) { struct new_schk *s = locate_scheduler(i); if (s == NULL) { - DUMMYNET_UNLOCK(); + DN_BH_WUNLOCK(); printf("%s sched %d not found\n", __FUNCTION__, i); return EINVAL; } @@ -880,7 +880,7 @@ config_pipe(struct new_pipe *p, struct d schk_reset_credit(s); } dn_cfg.id++; - DUMMYNET_UNLOCK(); + DN_BH_WUNLOCK(); return 0; } @@ -921,7 +921,7 @@ config_fs(struct new_fs *nfs, struct dn_ nfs->buckets = 1; /* we only need 1 */ } if (!locked) - DUMMYNET_LOCK(); + DN_BH_WLOCK(); do { /* exit with break when done */ struct new_schk *s; @@ -956,7 +956,7 @@ config_fs(struct new_fs *nfs, struct dn_ fsk_attach(fs, s); } while (0); if (!locked) - DUMMYNET_UNLOCK(); + DN_BH_WUNLOCK(); return fs; } @@ -986,26 +986,33 @@ config_sched(struct new_sch *_nsch, stru return EINVAL; /* XXX other sanity checks */ bzero(&p, sizeof(0)); - DUMMYNET_LOCK(); + DN_BH_WLOCK(); again: /* run twice, for wfq and fifo */ a.fp = find_sched_type(a.sch->oid.subtype, a.sch->type); - if (a.fp == NULL) { - DUMMYNET_UNLOCK(); - printf("invalid scheduler type %s %d\n", - a.sch->type, a.sch->oid.subtype); - return EINVAL; + if (a.fp != NULL) { + a.sch->oid.subtype = a.fp->type; + s = dn_ht_find(dn_cfg.schedhash, i, DNHT_INSERT, &a); + } else { + /* accept missing type if sched already exists */ + s = dn_ht_find(dn_cfg.schedhash, i, 0, &a); + if (s == NULL) { + DN_BH_WUNLOCK(); + printf("invalid scheduler type %s %d\n", + a.sch->type, a.sch->oid.subtype); + return EINVAL; + } + a.fp = s->fp; + a.sch->oid.subtype = a.fp->type; } - a.sch->oid.subtype = a.fp->type; - s = dn_ht_find(dn_cfg.schedhash, i, DNHT_INSERT, &a); printf("%s start i %d ty %s -> %s\n", __FUNCTION__, i, a.sch->type, s ? (s->fp?"old":"new"):"none"); if (s == NULL) { - DUMMYNET_UNLOCK(); + DN_BH_WUNLOCK(); printf("cannot allocate scheduler\n"); return ENOMEM; } - /* preserve existing pipe if any */ + /* restore existing pipe if any */ if (p.pipe_nr) s->pipe = p; p.pipe_nr = 0; @@ -1016,12 +1023,12 @@ again: /* run twice, for wfq and fifo */ } else if (s->fp != a.fp || bcmp(a.sch, &s->sch, sizeof(*a.sch)) ) { /* already existing. */ - /* Detach flowsets, preserve pipe&queues. */ printf("sched %d type changed from %s to %s\n", i, s->fp->name, a.fp->name); - p = s->pipe; + p = s->pipe; /* preserve pipe */ /* remove from the hash */ dn_ht_find(dn_cfg.schedhash, i, DNHT_REMOVE, NULL); + /* Detach flowsets, preserve queues. */ schk_delete_cb(s, NULL); printf("schk_delete_cb done\n"); goto again; @@ -1057,7 +1064,7 @@ again: /* run twice, for wfq and fifo */ a.sch->oid.subtype = DN_SCHED_FIFO; goto again; } - DUMMYNET_UNLOCK(); + DN_BH_WUNLOCK(); printf("%s end\n", __FUNCTION__); return 0; } @@ -1079,11 +1086,11 @@ config_profile(struct new_profile *pf, s if (i <= 0 || i >= DN_MAX_ID) return EINVAL; /* XXX other sanity checks */ - DUMMYNET_LOCK(); + DN_BH_WLOCK(); s = locate_scheduler(i); if (s == NULL) { - DUMMYNET_UNLOCK(); + DN_BH_WUNLOCK(); printf("%s: no scheduler %d\n", __FUNCTION__, i); return EINVAL; } @@ -1107,7 +1114,7 @@ config_profile(struct new_profile *pf, s s->profile = malloc(pf->oid.len, M_DUMMYNET, M_NOWAIT | M_ZERO); if (s->profile == NULL) { - DUMMYNET_UNLOCK(); + DN_BH_WUNLOCK(); printf("%s: no memory\n", __FUNCTION__); return ENOMEM; } @@ -1118,7 +1125,7 @@ config_profile(struct new_profile *pf, s bcopy(pf, s->profile, pf->oid.len); s->profile->oid.len = olen; } - DUMMYNET_UNLOCK(); + DN_BH_WUNLOCK(); return 0; } @@ -1176,10 +1183,10 @@ do_config(void *p, int l) switch (o->subtype) { case DN_PIPE: /* delete base and derived schedulers */ - DUMMYNET_LOCK(); + DN_BH_WLOCK(); err = delete_schk(o->id); err2 = delete_schk(o->id + DN_MAX_ID); - DUMMYNET_UNLOCK(); + DN_BH_WUNLOCK(); if (!err) err = err2; break; @@ -1198,9 +1205,9 @@ do_config(void *p, int l) break; case DN_CMD_FLUSH: - DUMMYNET_LOCK(); + DN_BH_WLOCK(); dummynet_flush(); - DUMMYNET_UNLOCK(); + DN_BH_WUNLOCK(); break; case DN_TEXT: /* store argument the next block */ prev = NULL; @@ -1284,17 +1291,17 @@ dummynet_get(struct sockopt *sopt) * Try a few times then give up. */ for (have = 0, i = 0; i < 10; i++) { - DUMMYNET_LOCK(); + DN_BH_WLOCK(); need = compute_space(&cmd, &to_copy); if (need < 0) { - DUMMYNET_UNLOCK(); + DN_BH_WUNLOCK(); return EINVAL; } need += sizeof(cmd); cmd.id = need; if (have >= need) break; - DUMMYNET_UNLOCK(); + DN_BH_WUNLOCK(); if (start) free(start, M_DUMMYNET); buf = NULL; @@ -1319,17 +1326,19 @@ dummynet_get(struct sockopt *sopt) a.end = end; a.flags = to_copy; a.extra = 0; - printf("copy schedulers %d)\n", + printf("copy schedulers (%d : %d)\n", + dn_cfg.schk_count, dn_ht_entries(dn_cfg.schedhash)); a.type = DN_SCH; dn_ht_scan(dn_cfg.schedhash, copy_data_helper, &a); - printf("copy unlinked flowsets %d\n", + printf("copy unlinked flowsets (%d : %d)\n", + dn_cfg.fsk_count, dn_ht_entries(dn_cfg.fshash)); a.type = DN_FS; a.extra = 1; dn_ht_scan(dn_cfg.fshash, copy_data_helper, &a); } - DUMMYNET_UNLOCK(); + DN_BH_WUNLOCK(); error = sooptcopyout(sopt, start, buf - start); free(start, M_DUMMYNET); return error; @@ -1420,7 +1429,7 @@ ip_dn_init(void) SLIST_INIT(&dn_cfg.fsu); SLIST_INIT(&dn_cfg.schedlist); - DUMMYNET_LOCK_INIT(); + DN_LOCK_INIT(); ip_dn_ctl_ptr = ip_dn_ctl; ip_dn_io_ptr = dummynet_io; @@ -1440,13 +1449,13 @@ ip_dn_init(void) static void ip_dn_destroy(void) { - DUMMYNET_LOCK(); + DN_BH_WLOCK(); ip_dn_ctl_ptr = NULL; ip_dn_io_ptr = NULL; callout_stop(&dn_timeout); dummynet_flush(); - DUMMYNET_UNLOCK(); + DN_BH_WUNLOCK(); taskqueue_drain(dn_tq, &dn_task); taskqueue_free(dn_tq); @@ -1454,7 +1463,7 @@ ip_dn_destroy(void) dn_ht_free(dn_cfg.fshash, 0); heap_free(&dn_cfg.evheap); - DUMMYNET_LOCK_DESTROY(); + DN_LOCK_DESTROY(); } #endif /* KLD_MODULE */ @@ -1503,7 +1512,7 @@ load_dn_sched(struct dn_sched *d) } /* Search if scheduler already exists */ - DUMMYNET_LOCK(); + 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); @@ -1512,7 +1521,7 @@ load_dn_sched(struct dn_sched *d) } if (s == NULL) SLIST_INSERT_HEAD(&dn_cfg.schedlist, d, next); - DUMMYNET_UNLOCK(); + DN_BH_WUNLOCK(); printf("dn_sched %s %sloaded\n", d->name, s ? "not ":""); return s ? 1 : 0; } @@ -1525,7 +1534,7 @@ unload_dn_sched(struct dn_sched *s) printf("%s %s called\n", __FUNCTION__, s->name); - DUMMYNET_LOCK(); + DN_BH_WLOCK(); SLIST_FOREACH_SAFE(r, &dn_cfg.schedlist, next, tmp) { if (strcmp(s->name, r->name) != 0) continue; @@ -1535,7 +1544,7 @@ unload_dn_sched(struct dn_sched *s) SLIST_REMOVE(&dn_cfg.schedlist, r, dn_sched, next); break; } - DUMMYNET_UNLOCK(); + DN_BH_WUNLOCK(); printf("dn_sched %s %sunloaded\n", s->name, err ? "not ":""); return err; } From owner-svn-src-user@FreeBSD.ORG Wed Jan 20 09:11:42 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 ED81C1065672; Wed, 20 Jan 2010 09:11:42 +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 DC8708FC13; Wed, 20 Jan 2010 09:11:42 +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 o0K9Bg2j068108; Wed, 20 Jan 2010 09:11:42 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0K9Bgeh068104; Wed, 20 Jan 2010 09:11:42 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <201001200911.o0K9Bgeh068104@svn.freebsd.org> From: Luigi Rizzo Date: Wed, 20 Jan 2010 09:11:42 +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: r202681 - 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: Wed, 20 Jan 2010 09:11:43 -0000 Author: luigi Date: Wed Jan 20 09:11:42 2010 New Revision: 202681 URL: http://svn.freebsd.org/changeset/base/202681 Log: add DN_LOCK_DESTROY, plus other small cleanups Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.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/sys/netinet/ipfw/dn_heap.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.c Wed Jan 20 08:41:58 2010 (r202680) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.c Wed Jan 20 09:11:42 2010 (r202681) @@ -76,11 +76,8 @@ heap_resize(struct dn_heap *h, int new_s { struct dn_heap_entry *p; - if (h->size >= new_size ) { - printf("--- %s: Bogus call, have %d want %d\n", - __func__, h->size, new_size); + if (h->size >= new_size ) /* have enough room */ return 0; - } new_size = (new_size + HEAP_INCREMENT ) & ~HEAP_INCREMENT; p = malloc(new_size * sizeof(*p), M_DN_HEAP, M_NOWAIT); if (p == NULL) { Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h Wed Jan 20 08:41:58 2010 (r202680) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h Wed Jan 20 09:11:42 2010 (r202681) @@ -42,7 +42,7 @@ MALLOC_DECLARE(M_DUMMYNET); mtx_init(&dn_cfg.uh_mtx, "dn_uh", NULL, MTX_DEF); \ mtx_init(&dn_cfg.bh_mtx, "dn_bh", NULL, MTX_DEF); \ } while (0) -#define DUMMYNET_LOCK_DESTROY() do { \ +#define DN_LOCK_DESTROY() do { \ mtx_destroy(&dn_cfg.uh_mtx); \ mtx_destroy(&dn_cfg.bh_mtx); \ } while (0) @@ -157,7 +157,6 @@ struct delay_line { struct new_fsk { /* kernel side of a flowset */ struct new_fs fs; SLIST_ENTRY(new_fsk) fsk_next; /* hash chain list */ - int refcnt; /* entries in qht */ /* hash table of queues, or just single queue */ struct dn_ht *_qht; @@ -228,8 +227,8 @@ struct new_sch_inst { /* kernel-side flags */ enum { /* 1 and 2 are reserved for the SCAN flags */ - DN_DELETE = 0x0004, /* destroy when refcnt=0 */ - DN_DELETE_FS = 0x0008, /* destroy when refcnt=0 */ + DN_DELETE = 0x0004, /* destroy */ + DN_DELETE_FS = 0x0008, /* destroy flowset */ DN_DETACH = 0x0010, DN_ACTIVE = 0x0020, /* object is in evheap */ DN_F_DLINE = 0x0040, /* object is a delay line */ Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Wed Jan 20 08:41:58 2010 (r202680) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Wed Jan 20 09:11:42 2010 (r202681) @@ -248,8 +248,12 @@ q_new(uintptr_t key, int flags, void *ar q->ni.id = *(struct ipfw_flow_id *)key; q->fs = fs; q->_si = template->_si; - fs->refcnt++; - + printf("-- %s fs %p si %p mask p %d f %d 0x%08x:%d -> 0x%08x:%d\n", + __FUNCTION__, q->fs, q->_si, + q->ni.id.proto, q->ni.id.flags, + q->ni.id.src_ip, q->ni.id.src_port, + q->ni.id.dst_ip, q->ni.id.dst_port); + if (fs->sched->fp->new_queue) fs->sched->fp->new_queue(q); dn_cfg.queue_count++; @@ -276,7 +280,6 @@ dn_delete_queue(struct new_queue *q, int dn_free_pkts(q->mq.head); free(q, M_DUMMYNET); dn_cfg.queue_count--; - fs->refcnt--; } } @@ -740,6 +743,20 @@ struct copy_args { }; 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; + if (copy_obj(a->start, a->end, &fs->fs)) + return DNHT_SCAN_END; + ufs->oid.id = 0; /* XXX number of queues ? */ + if (flags) { /* copy queues */ + } + return 0; +} + +static int copy_data_helper(void *_o, void *_arg) { struct copy_args *a = _arg; @@ -749,7 +766,7 @@ copy_data_helper(void *_o, void *_arg) if (a->flags & DN_C_PIPE) { if (copy_obj(a->start, a->end, &s->pipe)) return DNHT_SCAN_END; - if (s->fs && copy_obj(a->start, a->end, &s->fs->fs)) + if (copy_flowset(a, s->fs, 0)) return DNHT_SCAN_END; } if (a->flags & DN_C_SCH) { @@ -762,13 +779,10 @@ copy_data_helper(void *_o, void *_arg) } if (a->type == DN_FS) { /* scanning flowsets */ struct new_fsk *fs = _o; - struct new_fs *ufs = - (struct new_fs *)(*a->start); /* if extra is set, only copy unlinked ones */ if (a->extra == 0 || fs->sched == NULL) { - if (copy_obj(a->start, a->end, &fs->fs)) + if (copy_flowset(a, fs, 0)) return DNHT_SCAN_END; - ufs->oid.id = fs->refcnt; } } return 0; @@ -929,12 +943,13 @@ config_fs(struct new_fs *nfs, struct dn_ if (fs == NULL) break; if (nfs->sched_nr == 0) { - printf("reuse existing number %d\n", fs->fs.sched_nr); - if (fs->fs.sched_nr == 0) { - fs = NULL; - break; + if (fs->fs.sched_nr != 0) { /* reuse */ + nfs->sched_nr = fs->fs.sched_nr; + } else { + printf("missing sched for flowset %d\n", i); + fs = NULL; + break; } - nfs->sched_nr = fs->fs.sched_nr; } dn_cfg.id++; if (bcmp(&fs->fs, nfs, sizeof(*nfs)) == 0) { @@ -1251,13 +1266,6 @@ compute_space(struct dn_id *cmd, int *to break; } *to_copy = x; - printf("have %d.%d sched %d, %d.%d pipes %d, %d.%d flows %d, " - "%d.%d si %d, %d.%d queues %d\n", - 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); if (x & DN_C_SCH) need += dn_cfg.schk_count * sizeof(struct new_sch); if (x & DN_C_FS) @@ -1314,6 +1322,13 @@ 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", + 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)); From owner-svn-src-user@FreeBSD.ORG Wed Jan 20 09:48:46 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 AF9AC106566B; Wed, 20 Jan 2010 09:48:46 +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 94E398FC17; Wed, 20 Jan 2010 09:48:46 +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 o0K9mk9o076518; Wed, 20 Jan 2010 09:48:46 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0K9mkHo076515; Wed, 20 Jan 2010 09:48:46 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <201001200948.o0K9mkHo076515@svn.freebsd.org> From: Luigi Rizzo Date: Wed, 20 Jan 2010 09:48:46 +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: r202687 - in user/luigi/ipfw3-head: sbin/ipfw 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: Wed, 20 Jan 2010 09:48:46 -0000 Author: luigi Date: Wed Jan 20 09:48:46 2010 New Revision: 202687 URL: http://svn.freebsd.org/changeset/base/202687 Log: default to wf2q+ in the kernel and not in userland. Modified: user/luigi/ipfw3-head/sbin/ipfw/dummynet.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 Wed Jan 20 09:29:07 2010 (r202686) +++ user/luigi/ipfw3-head/sbin/ipfw/dummynet.c Wed Jan 20 09:48:46 2010 (r202687) @@ -308,6 +308,11 @@ flush_buf(char *buf) /* * generic list routine. We expect objects in a specific order, i.e. + * PIPES AND SCHEDULERS: + * pipe; scheduler; internal flowset if any; instances + * XXX do we need the queue ? + * FLOWSETS: + * flowset; queues; * pipe i (int queue); scheduler i; si(i) { flowsets() : queues } * filt is an array of sorted ranges whithin where we list */ @@ -322,12 +327,17 @@ list_pipes(struct dn_id *oid, struct dn_ errx(1, "invalid oid len %d\n", oid->len); switch (oid->type) { + default: + flush_buf(buf); + printf("unrecognized object %d size %d\n", oid->type, oid->len); + break; case DN_PIPE: { struct new_pipe *p = (struct new_pipe *)oid; double b = p->bandwidth; char bwbuf[30]; char burst[5 + 7]; + /* This starts a new object so flush buffer */ flush_buf(buf); /* data rate */ if (b == 0) @@ -787,7 +797,8 @@ ipfw_config_pipe(int ac, char **av) /* the WFQ scheduler */ sch = o_next(&buf, sizeof(*sch), DN_SCH); sch->sched_nr = i; - sch->oid.subtype = DN_SCHED_WF2QP; + /* type should be wfq, but we set the default in the kernel. */ + sch->oid.subtype = 0; mask = &sch->sched_mask; /* XXX the FIFO scheduler is created from the WFQ one */ Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Wed Jan 20 09:29:07 2010 (r202686) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Wed Jan 20 09:48:46 2010 (r202687) @@ -1005,20 +1005,24 @@ config_sched(struct new_sch *_nsch, stru again: /* run twice, for wfq and fifo */ a.fp = find_sched_type(a.sch->oid.subtype, a.sch->type); if (a.fp != NULL) { - a.sch->oid.subtype = a.fp->type; 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 { - /* accept missing type if sched already exists */ + /* type not supplied. If it exist already, use + * the existing one. Otherwise default to WF2Q+ + */ s = dn_ht_find(dn_cfg.schedhash, i, 0, &a); if (s == NULL) { - DN_BH_WUNLOCK(); - printf("invalid scheduler type %s %d\n", - a.sch->type, a.sch->oid.subtype); - return EINVAL; + a.sch->oid.subtype = DN_SCHED_WF2QP; + goto again; } a.fp = s->fp; - a.sch->oid.subtype = a.fp->type; } + a.sch->oid.subtype = a.fp->type; printf("%s start i %d ty %s -> %s\n", __FUNCTION__, i, a.sch->type, s ? (s->fp?"old":"new"):"none"); From owner-svn-src-user@FreeBSD.ORG Wed Jan 20 13:34:06 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 1E1E4106568B; Wed, 20 Jan 2010 13:34:06 +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 0CF8F8FC18; Wed, 20 Jan 2010 13:34:06 +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 o0KDY6Tj014768; Wed, 20 Jan 2010 13:34:06 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0KDY5ts014761; Wed, 20 Jan 2010 13:34:05 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <201001201334.o0KDY5ts014761@svn.freebsd.org> From: Luigi Rizzo Date: Wed, 20 Jan 2010 13:34:05 +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: r202695 - 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: Wed, 20 Jan 2010 13:34:06 -0000 Author: luigi Date: Wed Jan 20 13:34:05 2010 New Revision: 202695 URL: http://svn.freebsd.org/changeset/base/202695 Log: remove a nasty bug with the hashtable -- the hash function must return an unsigned, otherwise a % operator might return negative values. On passing, also fix various glitches with configuration commands. 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_heap.c user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.h user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.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 Wed Jan 20 13:31:12 2010 (r202694) +++ user/luigi/ipfw3-head/sbin/ipfw/dummynet.c Wed Jan 20 13:34:05 2010 (r202695) @@ -331,6 +331,15 @@ 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_CMD_GET: + printf("respond to cmd %d buflen %d\n", oid->type, oid->id); + break; + case DN_SCH: { + struct new_sch *s = (struct new_sch *)s; + sprintf(buf + strlen(buf), " type %s", s->type); + } + break; + case DN_PIPE: { struct new_pipe *p = (struct new_pipe *)oid; double b = p->bandwidth; @@ -921,22 +930,27 @@ ipfw_config_pipe(int ac, char **av) goto end_mask; case TOK_DSTIP: + mask->addr_type = 4; p32 = &mask->dst_ip; break; case TOK_SRCIP: + mask->addr_type = 4; p32 = &mask->src_ip; break; case TOK_DSTIP6: + mask->addr_type = 6; pa6 = &mask->dst_ip6; break; case TOK_SRCIP6: + mask->addr_type = 6; pa6 = &mask->src_ip6; break; case TOK_FLOWID: + mask->addr_type = 6; p20 = &mask->flow_id6; break; Modified: user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h Wed Jan 20 13:31:12 2010 (r202694) +++ user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h Wed Jan 20 13:34:05 2010 (r202695) @@ -155,7 +155,7 @@ struct new_fs { */ struct new_inst { struct dn_id oid; - struct ipfw_flow_id id; + struct ipfw_flow_id fid; uint32_t length; /* Queue lenght, in packets */ uint32_t len_bytes; /* Queue lenght, in bytes */ uint32_t drops; Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.c Wed Jan 20 13:31:12 2010 (r202694) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.c Wed Jan 20 13:34:05 2010 (r202695) @@ -123,7 +123,7 @@ heap_init(struct dn_heap *h, int size, i */ #define RESET_OFFSET(h, i) do { \ if (h->ofs > 0) \ - *((int32_t *)((char *)(h->p[i].object) + h->ofs)) = -1; \ + *((int32_t *)((char *)(h->p[i].object) + h->ofs)) = -16; \ } while (0) int @@ -308,7 +308,7 @@ struct dn_ht { int buckets; /* how many buckets */ int entries; /* how many entries */ int ofs; /* offset of link field */ - int (*hash)(uintptr_t, int, void *arg); + uint32_t (*hash)(uintptr_t, int, void *arg); int (*match)(void *_el, uintptr_t key, int, void *); void *(*new)(uintptr_t, int, void *); void **ht; /* bucket heads */ @@ -321,7 +321,7 @@ struct dn_ht { */ struct dn_ht * dn_ht_init(struct dn_ht *ht, int buckets, int ofs, - int (*h)(uintptr_t, int, void *), + uint32_t (*h)(uintptr_t, int, void *), int (*match)(void *, uintptr_t, int, void *), void *(*new)(uintptr_t, int, void *)) { @@ -398,7 +398,8 @@ dn_ht_find(struct dn_ht *ht, uintptr_t k return NULL; i = (ht->buckets == 1) ? 0 : (ht->hash(key, flags, arg) % ht->buckets); - // printf("%s key %p in bucket %d\n", __FUNCTION__, (void *)key, i); + // printf("%s key %p in bucket %d entries %d\n", + // __FUNCTION__, (void *)key, i, ht->entries); for (pp = &ht->ht[i]; (p = *pp); pp = (void **)((char *)p + ht->ofs)) { if (flags & DNHT_MATCH_PTR) { if (key == (uintptr_t)p) Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.h ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.h Wed Jan 20 13:31:12 2010 (r202694) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.h Wed Jan 20 13:34:05 2010 (r202695) @@ -156,7 +156,7 @@ int heap_scan(struct dn_heap *, int (*)( struct dn_ht; /* should be opaque */ struct dn_ht *dn_ht_init(struct dn_ht *, int buckets, int ofs, - int (*hash)(uintptr_t, int, void *), + uint32_t (*hash)(uintptr_t, int, void *), int (*match)(void *, uintptr_t, int, void *), void *(*new)(uintptr_t, int, void *)); void dn_ht_free(struct dn_ht *, int flags); Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c Wed Jan 20 13:31:12 2010 (r202694) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c Wed Jan 20 13:34:05 2010 (r202695) @@ -232,7 +232,7 @@ static int wf2qp_new_sched(struct new_sch_inst *_si) { struct wf2qp_si *si = (struct wf2qp_si *)(_si + 1); - int ofs = offsetof(struct wf2qp_queue, heap_pos); + int ofs = sizeof(*_si) + offsetof(struct wf2qp_queue, heap_pos); /* only idle-heap supports extract from middle */ if (heap_init(&si->idle_heap, 16, ofs) || Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Wed Jan 20 13:31:12 2010 (r202694) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Wed Jan 20 13:34:05 2010 (r202695) @@ -139,7 +139,7 @@ flow_id_mask(struct ipfw_flow_id *mask, } /* XXX we may want a better hash function */ -static int +static uint32_t flow_id_hash(struct ipfw_flow_id *id) { uint32_t i; @@ -200,12 +200,12 @@ flow_id_cmp(struct ipfw_flow_id *id1, st /*--- support functions for the qht hashtable ---- * Entries are hashed by flow-id */ -static int +static uint32_t q_hash(uintptr_t key, int flags, void *arg) { /* compute the hash slot from the flow id */ struct ipfw_flow_id *id = (flags & DNHT_KEY_IS_OBJ) ? - &((struct new_queue *)key)->ni.id : + &((struct new_queue *)key)->ni.fid : (struct ipfw_flow_id *)key; return flow_id_hash(id); @@ -214,17 +214,16 @@ q_hash(uintptr_t key, int flags, void *a static int q_match(void *obj, uintptr_t key, int flags, void *arg) { - struct new_queue *o; + struct new_queue *o = (struct new_queue *)obj; struct ipfw_flow_id *id2; if (flags & DNHT_KEY_IS_OBJ) { /* compare pointers */ - id2 = &((struct new_queue *)key)->ni.id; + id2 = &((struct new_queue *)key)->ni.fid; } else { id2 = (struct ipfw_flow_id *)key; } - o = (struct new_queue *)obj; - return flow_id_cmp(&o->ni.id, id2) == 0; + return (0 == flow_id_cmp(&o->ni.fid, id2)); } /* @@ -245,15 +244,10 @@ q_new(uintptr_t key, int flags, void *ar set_oid(&q->ni.oid, DN_QUEUE, size); if (fs->fs.flags & DN_HAVE_MASK) - q->ni.id = *(struct ipfw_flow_id *)key; + q->ni.fid = *(struct ipfw_flow_id *)key; q->fs = fs; q->_si = template->_si; - printf("-- %s fs %p si %p mask p %d f %d 0x%08x:%d -> 0x%08x:%d\n", - __FUNCTION__, q->fs, q->_si, - q->ni.id.proto, q->ni.id.flags, - q->ni.id.src_ip, q->ni.id.src_port, - q->ni.id.dst_ip, q->ni.id.dst_port); - + if (fs->sched->fp->new_queue) fs->sched->fp->new_queue(q); dn_cfg.queue_count++; @@ -299,8 +293,10 @@ 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 if (!fs->_qht) return; if (fs->fs.flags & DN_HAVE_MASK) { @@ -355,12 +351,12 @@ ipdn_q_find(struct new_fsk *fs, struct n * * These are hashed by flow-id */ -static int +static uint32_t si_hash(uintptr_t key, int flags, void *arg) { /* compute the hash slot from the flow id */ struct ipfw_flow_id *id = (flags & DNHT_KEY_IS_OBJ) ? - &((struct new_sch_inst *)key)->ni.id : + &((struct new_sch_inst *)key)->ni.fid : (struct ipfw_flow_id *)key; return flow_id_hash(id); @@ -373,9 +369,9 @@ si_match(void *obj, uintptr_t key, int f struct ipfw_flow_id *id2; id2 = (flags & DNHT_KEY_IS_OBJ) ? - &((struct new_sch_inst *)key)->ni.id : + &((struct new_sch_inst *)key)->ni.fid : (struct ipfw_flow_id *)key; - return flow_id_cmp(&o->ni.id, id2) == 0; + return flow_id_cmp(&o->ni.fid, id2) == 0; } /* @@ -406,7 +402,7 @@ si_new(uintptr_t key, int flags, void *a goto error; } if (s->sch.flags & DN_HAVE_MASK) - si->ni.id = *(struct ipfw_flow_id *)key; + si->ni.fid = *(struct ipfw_flow_id *)key; dn_cfg.si_count++; return si; @@ -489,10 +485,10 @@ schk_reset_credit(struct new_schk *s) * New allocations are put in the fsunlinked list, from which * they are removed when they point to a specific scheduler. */ -static int +static uint32_t fsk_hash(uintptr_t key, int flags, void *arg) { - int i = !(flags & DNHT_KEY_IS_OBJ) ? key : + uint32_t i = !(flags & DNHT_KEY_IS_OBJ) ? key : ((struct new_fsk *)key)->fs.fs_nr; return ( (i>>8)^(i>>4)^i ); @@ -533,11 +529,13 @@ 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, (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; @@ -569,12 +567,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); + // printf("+++ %s head %p flags %x\n", __FUNCTION__, h, flags); while ((fs = SLIST_FIRST(h))) { SLIST_REMOVE_HEAD(h, sch_chain); + n++; fsk_detach(fs, flags); } - printf("+++ %s done %d flowsets\n", __FUNCTION__, n); + // printf("+++ %s done flowsets\n", __FUNCTION__, n); } /* @@ -610,10 +609,10 @@ delete_fs(int i, int locked) * 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 +static uint32_t schk_hash(uintptr_t key, int flags, void *_arg) { - int i = !(flags & DNHT_KEY_IS_OBJ) ? key : + uint32_t i = !(flags & DNHT_KEY_IS_OBJ) ? key : ((struct new_schk *)key)->sch.sched_nr; return ( (i>>8)^(i>>4)^i ); } @@ -670,13 +669,14 @@ static int 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__, s->sch.sched_nr, + __FUNCTION__, i, 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) { @@ -688,7 +688,7 @@ schk_delete_cb(void *obj, void *arg) s->fp->destroy(s); bzero(s, sizeof(*s)); free(obj, M_DUMMYNET); - printf("<<< %s done sched %d destroyed\n", __FUNCTION__, i); + // printf("<<< %s done sched %d destroyed\n", __FUNCTION__, i); dn_cfg.schk_count--; return DNHT_SCAN_DEL; } @@ -722,8 +722,8 @@ copy_obj(char **start, char *end, void * struct dn_id *o = _o; int have = end - *start; - if (have < o->len) { - printf("%s overflow type %d have %d need %d\n", + if (have < o->len || o->len == 0 || o->type == 0) { + printf("XXX %s ERROR type %d have %d need %d\n", __FUNCTION__, o->type, have, o->len); return 1; } @@ -764,14 +764,20 @@ copy_data_helper(void *_o, void *_arg) if (a->type == DN_SCH) { /* scanning schedulers */ struct new_schk *s = _o; if (a->flags & DN_C_PIPE) { + printf("copy pipe %d\n", s->sch.sched_nr); if (copy_obj(a->start, a->end, &s->pipe)) return DNHT_SCAN_END; + printf("copy int-fs for pipe %d %p\n", + s->sch.sched_nr, s->fs); if (copy_flowset(a, s->fs, 0)) return DNHT_SCAN_END; + printf("copy pipe %d done\n", s->sch.sched_nr); } if (a->flags & DN_C_SCH) { + printf("copy sched %d\n", s->sch.sched_nr); if (copy_obj(a->start, a->end, &s->sch)) return DNHT_SCAN_END; + printf("copy sched %d done\n", s->sch.sched_nr); } if (a->flags & DN_C_SCH_INST) { printf("XXX todo: scan sched instances\n"); @@ -781,8 +787,11 @@ copy_data_helper(void *_o, void *_arg) struct new_fsk *fs = _o; /* if extra is set, only copy unlinked ones */ if (a->extra == 0 || fs->sched == NULL) { + printf("copy fs %d to sched %d\n", fs->fs.fs_nr, + fs->sched ? fs->sched->sch.sched_nr : -1); if (copy_flowset(a, fs, 0)) return DNHT_SCAN_END; + printf("copy fs %d done\n",fs->fs.fs_nr); } } return 0; @@ -798,8 +807,10 @@ 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", 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); @@ -807,7 +818,7 @@ fsk_attach(struct new_fsk *fs, struct ne s->fp->new_fsk(fs); if (!fs->_qht) return; - printf("+++ %s TODO requeue from fs %d to sch %d\n", + printf("XXX %s TODO requeue from fs %d to sch %d\n", __FUNCTION__, fs->fs.fs_nr, s->sch.sched_nr); } @@ -914,7 +925,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); + // 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) @@ -927,10 +938,15 @@ config_fs(struct new_fs *nfs, struct dn_ } if (nfs->flags & DN_HAVE_MASK) { /* make sure we have some buckets */ - if (nfs->buckets < 1) + if (nfs->buckets < 1) { nfs->buckets = dn_cfg.hash_size; - else if (nfs->buckets > dn_cfg.max_hash_size) + printf("%s force buckets to %d\n", + __FUNCTION__, nfs->buckets); + } else if (nfs->buckets > dn_cfg.max_hash_size) { nfs->buckets = dn_cfg.max_hash_size; + printf("%s clamp buckets to %d\n", + __FUNCTION__, nfs->buckets); + } } else { nfs->buckets = 1; /* we only need 1 */ } @@ -953,7 +969,7 @@ config_fs(struct new_fs *nfs, struct dn_ } dn_cfg.id++; if (bcmp(&fs->fs, nfs, sizeof(*nfs)) == 0) { - printf("%s no change\n", __FUNCTION__); + printf("%s flowset %d unchanged\n", __FUNCTION__, i); break; /* no change, nothing to do */ } s = locate_scheduler(nfs->sched_nr); @@ -961,6 +977,9 @@ 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, + fs->fs.sched_nr, fs->sched, nfs->sched_nr, s); if (fs->sched) { int flags = s ? DN_DETACH : (DN_DETACH | DN_DELETE); flags |= DN_DELETE; /* XXX temporary */ @@ -1000,7 +1019,7 @@ config_sched(struct new_sch *_nsch, stru if (i <= 0 || i >= DN_MAX_ID) return EINVAL; /* XXX other sanity checks */ - bzero(&p, sizeof(0)); + 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); @@ -1022,10 +1041,10 @@ again: /* run twice, for wfq and fifo */ } a.fp = s->fp; } + /* normalize type and subtype */ a.sch->oid.subtype = a.fp->type; - printf("%s start i %d ty %s -> %s\n", - __FUNCTION__, i, a.sch->type, - s ? (s->fp?"old":"new"):"none"); + bzero(a.sch->type, sizeof(a.sch->type)); + strlcpy(a.sch->type, a.fp->name, sizeof(a.sch->type)); if (s == NULL) { DN_BH_WUNLOCK(); printf("cannot allocate scheduler\n"); @@ -1044,12 +1063,19 @@ again: /* run twice, for wfq and fifo */ /* already existing. */ printf("sched %d type changed from %s to %s\n", i, s->fp->name, a.fp->name); + printf(" type/sub %d/%d -> %d/%d\n", + 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); p = s->pipe; /* preserve pipe */ /* remove from the hash */ dn_ht_find(dn_cfg.schedhash, i, DNHT_REMOVE, NULL); /* Detach flowsets, preserve queues. */ - schk_delete_cb(s, NULL); - printf("schk_delete_cb done\n"); + // schk_delete_cb(s, NULL); + // XXX temporarily, kill queues + schk_delete_cb(s, (void *)DN_DELETE); goto again; } else { printf("%s sched %d unchanged type %s\n", __FUNCTION__, i, @@ -1080,11 +1106,12 @@ again: /* run twice, for wfq and fifo */ if (i < DN_MAX_ID) { /* update 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)); goto again; } DN_BH_WUNLOCK(); - printf("%s end\n", __FUNCTION__); return 0; } @@ -1327,7 +1354,7 @@ 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", + "%d:%d si %d, %d:%d queues %d\n", 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, From owner-svn-src-user@FreeBSD.ORG Wed Jan 20 13:50:30 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 65F701065679; Wed, 20 Jan 2010 13:50:30 +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 5572C8FC12; Wed, 20 Jan 2010 13:50:30 +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 o0KDoU5B018368; Wed, 20 Jan 2010 13:50:30 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0KDoUd7018365; Wed, 20 Jan 2010 13:50:30 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <201001201350.o0KDoUd7018365@svn.freebsd.org> From: Luigi Rizzo Date: Wed, 20 Jan 2010 13:50:30 +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: r202696 - in user/luigi/ipfw3-head/sys: conf 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: Wed, 20 Jan 2010 13:50:30 -0000 Author: luigi Date: Wed Jan 20 13:50:30 2010 New Revision: 202696 URL: http://svn.freebsd.org/changeset/base/202696 Log: add a round-robin scheduler Added: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_rr.c (contents, props changed) Modified: user/luigi/ipfw3-head/sys/conf/files Modified: user/luigi/ipfw3-head/sys/conf/files ============================================================================== --- user/luigi/ipfw3-head/sys/conf/files Wed Jan 20 13:34:05 2010 (r202695) +++ user/luigi/ipfw3-head/sys/conf/files Wed Jan 20 13:50:30 2010 (r202696) @@ -2451,7 +2451,8 @@ netinet/in_rmx.c optional inet netinet/ip_divert.c optional inet ipdivert ipfirewall netinet/ipfw/dn_heap.c optional inet dummynet netinet/ipfw/dn_sched_fifo.c optional inet dummynet -netinet/ipfw/dn_sched_wf2q.c optional inet dummynet +netinet/ipfw/dn_sched_rr.c optional inet dummynet +netinet/ipfw/dn_sched_wf2q.c optional inet dummynet netinet/ipfw/ip_dummynet.c optional inet dummynet netinet/ipfw/ip_dn_io.c optional inet dummynet netinet/ip_ecn.c optional inet | inet6 Added: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_rr.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_rr.c Wed Jan 20 13:50:30 2010 (r202696) @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2010 Riccardo Panicucci, Universita` di Pisa + * All rights reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include /* IFNAMSIZ */ +#include +#include /* ipfw_rule_ref */ +#include /* flow_id */ +#include +#include +#include +#include + +#define DN_SCHED_RR 3 // XXX Where? + +/* rr_queue is appended to a struct new_queue */ +struct rr_queue { + struct new_queue *parent; /* Pointer to standard queue */ + int status; /* 1: queue is in the list */ + TAILQ_ENTRY(rr_queue) entries; /* List of active queue */ + int credit; /* Number of bytes to transmit */ + int quantum; /* quantum * C */ +}; +TAILQ_HEAD(rr_queue_head, rr_queue); + +/* struct rr_schk contains global config parameters + * and is right after new_schk + */ +struct rr_schk { + int min_q; /* Min quantum */ + int max_q; /* Max quantum */ + int q_bytes; /* Bytes per quantum */ +}; + +/* per-instance info, right after new_sch_inst */ +struct rr_si { + struct rr_queue *pointer; /* Pointer to current queue */ + struct rr_queue_head q_list; /* List of queues */ + int queue_n; /* number of queues in the list */ +}; + +static inline void +insert_queue(struct rr_queue *q, struct rr_si *si) +{ + + if (TAILQ_EMPTY(&si->q_list)) { /* or si->queue_n == 0 */ + TAILQ_INSERT_HEAD(&si->q_list, q, entries); + si->pointer = q; + } + else { + TAILQ_INSERT_BEFORE(si->pointer, q, entries); + } + q->status = 1; + si->queue_n++; +} + +static inline void +remove_queue(struct rr_queue *q, struct rr_si *si) +{ + TAILQ_REMOVE(&si->q_list, q, entries); + q->status = 0; + si->queue_n--; +} + +static inline struct rr_queue * +next_pointer(struct rr_si *si) +{ + if (si->queue_n == 0) { /* XXX needed? */ + si->pointer = NULL; + return NULL; + } + si->pointer = TAILQ_NEXT(si->pointer, entries); + if (si->pointer == NULL) + si->pointer = TAILQ_FIRST(&si->q_list); + + return si->pointer; +} + +static int +rr_enqueue(struct new_sch_inst *_si, struct new_queue *q, struct mbuf *m) +{ + struct rr_si *si; + struct rr_queue *alg_fq; + + if (m != q->mq.head) { + if (dn_enqueue(q, m, 0)) /* packet was dropped */ + return 1; + if (m == q->mq.head) + return 0; + } + + /* If reach this point, queue q was idle */ + si = (struct rr_si *)(_si + 1); + alg_fq = (struct rr_queue *)(q+1); + + if (alg_fq->status == 1) /* Queue is already in the queue list */ + return 0; + + /* Insert the queue in the queue list */ + insert_queue(alg_fq, si); + + return 0; +} + +static struct mbuf * +rr_dequeue(struct new_sch_inst *_si) +{ + /* Access scheduler instance private data */ + struct rr_si *si = (struct rr_si *)(_si + 1); + struct mbuf *pkt; + struct rr_queue *q; + struct new_queue *_q; + uint64_t len; + + if (si->queue_n == 0) /* scheduler empty */ + return NULL; + + while (si->queue_n > 0) { + q = si->pointer; + _q = q->parent; + /* or use: _q = ((struct new_queue *)q) - 1; */ + si->pointer = next_pointer(si); + if (_q->mq.head == NULL) { + /* empty queue, remove from list */ + remove_queue(q, si); + continue; + } + pkt = _q->mq.head; + len = pkt->m_pkthdr.len; + + if (len > q->credit) { + /* Packet too big */ + q->credit += q->quantum; + /* Try next queue */ + } else { + q->credit = q->credit - len + q->quantum; + return dn_dequeue(_q); + } + } + + /* no packet to dequeue*/ + return NULL; +} + +static int +rr_config(struct new_schk *_schk) +{ + struct rr_schk *schk = (struct rr_schk *)(_schk + 1); + printf("%s called\n", __FUNCTION__); + + schk->min_q = 1; + schk->max_q = 1000; + schk->q_bytes = 50; + + return 0; +} + +static int +rr_new_sched(struct new_sch_inst *_si) +{ + struct rr_si *si = (struct rr_si *)(_si + 1); + + printf("%s called\n", __FUNCTION__); + si->pointer = NULL; + si->queue_n = 0; + TAILQ_INIT(&si->q_list); + + return 0; +} + +static int +rr_free_sched(struct new_sch_inst *_si) +{ + printf("%s called\n", __FUNCTION__); + /* Nothing to do? */ + return 0; +} + +static int +rr_new_fsk(struct new_fsk *fs) +{ + struct rr_schk *schk = (struct rr_schk *)(fs->sched + 1); + printf("%s called\n", __FUNCTION__); + if (fs->fs.quantum < schk->min_q) + fs->fs.quantum = schk->min_q; + else if (fs->fs.quantum > schk->max_q) + fs->fs.quantum = schk->max_q; + return 0; +} + +static int +rr_new_queue(struct new_queue *_q) +{ + struct rr_queue *q = (struct rr_queue *)(_q + 1); + struct rr_schk *schk = (struct rr_schk *)(_q->_si->sched + 1); + + printf("%s called, schk->quantum=%d\n", __FUNCTION__, schk->q_bytes); + _q->ni.oid.subtype = DN_SCHED_RR; + + q->quantum = _q->fs->fs.quantum * schk->q_bytes; + q->credit = q->quantum; + q->status = 0; + q->parent = _q; + + if (_q->mq.head != NULL) { + /* Queue NOT empty, insert in the queue list */ + insert_queue(q, (struct rr_si *)(_q->_si + 1)); + } + return 0; +} + +static int +rr_free_queue(struct new_queue *_q) +{ + struct rr_queue *q = (struct rr_queue *)(_q + 1); + + printf("%s called\n", __FUNCTION__); + if (q->status == 1) { + struct rr_si *si = (struct rr_si *)(_q->_si + 1); + remove_queue(q, si); + if (si->pointer == q) + si->pointer = next_pointer(si); + } + return 0; +} + +/* + * RR scheduler descriptor + * contains the type of the scheduler, the name, the size of the + * structures and function pointers. + */ +static struct dn_sched rr_desc = { + .type = DN_SCHED_RR, + .name = "RR", + .flags = DN_MULTIQUEUE, + + .si_datalen = sizeof(struct rr_si), + .q_datalen = sizeof(struct rr_queue), + + .enqueue = rr_enqueue, + .dequeue = rr_dequeue, + + .config = rr_config, + .new_sched = rr_new_sched, + .free_sched = rr_free_sched, + + .new_fsk = rr_new_fsk, + + .new_queue = rr_new_queue, + .free_queue = rr_free_queue, +}; + + +DECLARE_DNSCHED_MODULE(dn_rr, &rr_desc); From owner-svn-src-user@FreeBSD.ORG Wed Jan 20 18:28:24 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 5AA17106568D; Wed, 20 Jan 2010 18:28:24 +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 47D538FC1C; Wed, 20 Jan 2010 18:28:24 +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 o0KISO0E081987; Wed, 20 Jan 2010 18:28:24 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0KISOrR081982; Wed, 20 Jan 2010 18:28:24 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <201001201828.o0KISOrR081982@svn.freebsd.org> From: Luigi Rizzo Date: Wed, 20 Jan 2010 18:28:24 +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: r202710 - 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: Wed, 20 Jan 2010 18:28:24 -0000 Author: luigi Date: Wed Jan 20 18:28:24 2010 New Revision: 202710 URL: http://svn.freebsd.org/changeset/base/202710 Log: continue debugging in presence of sched and flow mask: In the kernel: - fix deletion of multiple scheduler instances by making the callback return DNHT_SCAN_DEL - remove some debugging messages; - copy more objects in dummynet_get() In userland: - fix parser so that flags are passed correctly when a mask is specified; - improve printing of 'ipfw pipe show' and 'ipfw sched show' - remove some debugging messages 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_heap.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 Wed Jan 20 18:22:56 2010 (r202709) +++ user/luigi/ipfw3-head/sbin/ipfw/dummynet.c Wed Jan 20 18:28:24 2010 (r202710) @@ -137,115 +137,77 @@ sort_q(void *arg, const void *pa, const res = 1; return (int)(rev ? res : -res); } +#endif static void -list_queues(struct dn_flow_set *fs, struct dn_flow_queue *q) +print_mask(struct ipfw_flow_id *id) +{ + if (!IS_IP6_FLOW_ID(id)) { + printf(" " + "mask: 0x%02x 0x%08x/0x%04x -> 0x%08x/0x%04x\n", + id->proto, + id->src_ip, id->src_port, + id->dst_ip, id->dst_port); + + printf("BKT Prot ___Source IP/port____ " + "____Dest. IP/port____ " + "Tot_pkt/bytes Pkt/Byte Drp\n"); + } else { + char buf[255]; + printf("\n mask: proto: 0x%02x, flow_id: 0x%08x, ", + id->proto, id->flow_id6); + inet_ntop(AF_INET6, &(id->src_ip6), buf, sizeof(buf)); + printf("%s/0x%04x -> ", buf, id->src_port); + inet_ntop(AF_INET6, &(id->dst_ip6), buf, sizeof(buf)); + printf("%s/0x%04x\n", buf, id->dst_port); + + printf("BKT ___Prot___ _flow-id_ " + "______________Source IPv6/port_______________ " + "_______________Dest. IPv6/port_______________ " + "Tot_pkt/bytes Pkt/Byte Drp\n"); + } +} + +static void +list_queue(struct new_inst *ni) { - int l; - int index_printed, indexes = 0; char buff[255]; struct protoent *pe; + struct in_addr ina; + struct ipfw_flow_id *id = &ni->fid; - if (fs->rq_elements == 0) - return; - - if (co.do_sort != 0) - qsort_r(q, fs->rq_elements, sizeof *q, NULL, sort_q); - - /* Print IPv4 flows */ - index_printed = 0; - for (l = 0; l < fs->rq_elements; l++) { - struct in_addr ina; - + pe = getprotobynumber(id->proto); /* XXX: Should check for IPv4 flows */ - if (IS_IP6_FLOW_ID(&(q[l].id))) - continue; - - if (!index_printed) { - index_printed = 1; - if (indexes > 0) /* currently a no-op */ - printf("\n"); - indexes++; - printf(" " - "mask: 0x%02x 0x%08x/0x%04x -> 0x%08x/0x%04x\n", - fs->flow_mask.proto, - fs->flow_mask.src_ip, fs->flow_mask.src_port, - fs->flow_mask.dst_ip, fs->flow_mask.dst_port); - - printf("BKT Prot ___Source IP/port____ " - "____Dest. IP/port____ " - "Tot_pkt/bytes Pkt/Byte Drp\n"); - } - - printf("%3d ", q[l].hash_slot); - pe = getprotobynumber(q[l].id.proto); + printf("%3d ", ni->oid.id); + if (!IS_IP6_FLOW_ID(id)) { if (pe) printf("%-4s ", pe->p_name); else - printf("%4u ", q[l].id.proto); - ina.s_addr = htonl(q[l].id.src_ip); + printf("%4u ", id->proto); + ina.s_addr = htonl(id->src_ip); printf("%15s/%-5d ", - inet_ntoa(ina), q[l].id.src_port); - ina.s_addr = htonl(q[l].id.dst_ip); + inet_ntoa(ina), id->src_port); + ina.s_addr = htonl(id->dst_ip); printf("%15s/%-5d ", - inet_ntoa(ina), q[l].id.dst_port); - printf("%4llu %8llu %2u %4u %3u\n", - align_uint64(&q[l].tot_pkts), - align_uint64(&q[l].tot_bytes), - q[l].len, q[l].len_bytes, q[l].drops); - if (co.verbose) - printf(" S %20llu F %20llu\n", - align_uint64(&q[l].S), align_uint64(&q[l].F)); - } - - /* Print IPv6 flows */ - index_printed = 0; - for (l = 0; l < fs->rq_elements; l++) { - if (!IS_IP6_FLOW_ID(&(q[l].id))) - continue; - - if (!index_printed) { - index_printed = 1; - if (indexes > 0) - printf("\n"); - indexes++; - printf("\n mask: proto: 0x%02x, flow_id: 0x%08x, ", - fs->flow_mask.proto, fs->flow_mask.flow_id6); - inet_ntop(AF_INET6, &(fs->flow_mask.src_ip6), - buff, sizeof(buff)); - printf("%s/0x%04x -> ", buff, fs->flow_mask.src_port); - inet_ntop( AF_INET6, &(fs->flow_mask.dst_ip6), - buff, sizeof(buff) ); - printf("%s/0x%04x\n", buff, fs->flow_mask.dst_port); - - printf("BKT ___Prot___ _flow-id_ " - "______________Source IPv6/port_______________ " - "_______________Dest. IPv6/port_______________ " - "Tot_pkt/bytes Pkt/Byte Drp\n"); - } - printf("%3d ", q[l].hash_slot); - pe = getprotobynumber(q[l].id.proto); + inet_ntoa(ina), id->dst_port); + } else { + /* Print IPv6 flows */ if (pe != NULL) printf("%9s ", pe->p_name); else - printf("%9u ", q[l].id.proto); - printf("%7d %39s/%-5d ", q[l].id.flow_id6, - inet_ntop(AF_INET6, &(q[l].id.src_ip6), buff, sizeof(buff)), - q[l].id.src_port); + printf("%9u ", id->proto); + printf("%7d %39s/%-5d ", id->flow_id6, + inet_ntop(AF_INET6, &(id->src_ip6), buff, sizeof(buff)), + id->src_port); printf(" %39s/%-5d ", - inet_ntop(AF_INET6, &(q[l].id.dst_ip6), buff, sizeof(buff)), - q[l].id.dst_port); - printf(" %4llu %8llu %2u %4u %3u\n", - align_uint64(&q[l].tot_pkts), - align_uint64(&q[l].tot_bytes), - q[l].len, q[l].len_bytes, q[l].drops); - if (co.verbose) - printf(" S %20llu F %20llu\n", - align_uint64(&q[l].S), - align_uint64(&q[l].F)); + inet_ntop(AF_INET6, &(id->dst_ip6), buff, sizeof(buff)), + id->dst_port); } + printf("%4llu %8llu %2u %4u %3u\n", + align_uint64(&ni->tot_pkts), + align_uint64(&ni->tot_bytes), + ni->length, ni->len_bytes, ni->drops); } -#endif static void print_flowset_parms(struct new_fs *fs, char *prefix) @@ -256,7 +218,7 @@ print_flowset_parms(struct new_fs *fs, c char red[90]; /* Display RED parameters */ l = fs->qsize; - if (fs->flags & DN_QSIZE_IS_BYTES) { + if (fs->flags & DN_QSIZE_BYTES) { if (l >= 8192) sprintf(qs, "%d KB", l / 1024); else @@ -335,11 +297,18 @@ list_pipes(struct dn_id *oid, struct dn_ printf("respond to cmd %d buflen %d\n", oid->type, oid->id); break; case DN_SCH: { - struct new_sch *s = (struct new_sch *)s; - sprintf(buf + strlen(buf), " type %s", s->type); + 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); + if (s->flags & DN_HAVE_MASK) + print_mask(&s->sched_mask); } break; + case DN_NI: + list_queue((struct new_inst *)oid); + break; + case DN_PIPE: { struct new_pipe *p = (struct new_pipe *)oid; double b = p->bandwidth; @@ -350,7 +319,7 @@ list_pipes(struct dn_id *oid, struct dn_ flush_buf(buf); /* data rate */ if (b == 0) - sprintf(bwbuf, "unlimited"); + sprintf(bwbuf, "unlimited "); else if (b >= 1000000) sprintf(bwbuf, "%7.3f Mbit/s", b/1000000); else if (b >= 1000) @@ -359,8 +328,8 @@ list_pipes(struct dn_id *oid, struct dn_ sprintf(bwbuf, "%7.3f bit/s ", b); if (humanize_number(burst, sizeof(burst), p->burst, - "Byte", HN_AUTOSCALE, 0) < 0 || co.verbose) - sprintf(burst, "%ju Byte\n", p->burst); + "", HN_AUTOSCALE, 0) < 0 || co.verbose) + sprintf(burst, "%d", (int)p->burst); sprintf(buf, "%05d: %s %4d ms burst %s", p->pipe_nr, bwbuf, p->delay, burst); } @@ -783,6 +752,7 @@ ipfw_config_pipe(int ac, char **av) struct new_cmd *cmd = NULL; struct ipfw_flow_id *mask = NULL; int lmax = sizeof(*cmd); /* always present */ + int _foo = 0, *flags = &_foo; /* worst case: 2 schedulers, 1 profile, 1 pipe, 1 flowset */ lmax += 2*sizeof(*sch) + 2*sizeof(*p) + sizeof(*fs) + sizeof(*pf); @@ -809,12 +779,13 @@ ipfw_config_pipe(int ac, char **av) /* type should be wfq, but we set the default in the kernel. */ sch->oid.subtype = 0; mask = &sch->sched_mask; - /* XXX the FIFO scheduler is created from the WFQ one */ + flags = &sch->flags; + /* the FIFO scheduler is created in the kernel from the WFQ one */ /* the WFQ pipe */ p = o_next(&buf, sizeof(*p), DN_PIPE); p->pipe_nr = i; - /* XXX the FIFO pipe is created from WFQ pipe */ + /* the FIFO pipe is created in the kerne from WFQ pipe */ /* * FIFO flowsets N+i are automatically created for @@ -830,12 +801,14 @@ ipfw_config_pipe(int ac, char **av) fs = o_next(&buf, sizeof(*fs), DN_FS); fs->fs_nr = i; mask = &fs->flow_mask; + flags = &fs->flags; break; case 3: /* scheduler */ sch = o_next(&buf, sizeof(*sch), DN_SCH); 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->fs_nr = i + DN_MAX_ID; @@ -874,11 +847,11 @@ ipfw_config_pipe(int ac, char **av) end = NULL; fs->qsize = strtoul(av[0], &end, 0); if (*end == 'K' || *end == 'k') { - fs->flags |= DN_QSIZE_IS_BYTES; + fs->flags |= DN_QSIZE_BYTES; fs->qsize *= 1024; } else if (*end == 'B' || _substrcmp2(end, "by", "bytes") == 0) { - fs->flags |= DN_QSIZE_IS_BYTES; + fs->flags |= DN_QSIZE_BYTES; } ac--; av++; break; @@ -926,7 +899,7 @@ ipfw_config_pipe(int ac, char **av) n2mask(&mask->dst_ip6, 128); n2mask(&mask->src_ip6, 128); mask->flow_id6 = ~0; - fs->flags |= DN_HAVE_FLOW_MASK; + *flags |= DN_HAVE_MASK; goto end_mask; case TOK_DSTIP: @@ -1002,7 +975,7 @@ ipfw_config_pipe(int ac, char **av) fs->flow_mask.proto = (uint8_t)a; } if (a != 0) - fs->flags |= DN_HAVE_FLOW_MASK; + *flags |= DN_HAVE_MASK; ac--; av++; } /* end while, config masks */ end_mask: @@ -1134,8 +1107,8 @@ end_mask: errx(EX_DATAERR, "sched must be > 0"); #endif - if (fs->flags & DN_QSIZE_IS_BYTES) { - size_t len; + if (fs->flags & DN_QSIZE_BYTES) { + size_t len; long limit; len = sizeof(limit); @@ -1254,7 +1227,7 @@ dummynet_list(int ac, char *av[], int sh oid.id = 0; switch (co.do_pipe) { case 1: - oid.subtype = DN_SCH; /* list pipe */ + oid.subtype = DN_PIPE; /* list pipe */ break; case 2: oid.subtype = DN_FS; /* list queue */ @@ -1265,7 +1238,7 @@ dummynet_list(int ac, char *av[], int sh } /* XXX we could use oid.id for the filter */ ret = do_cmd(-IP_DUMMYNET3, &oid, (uintptr_t)&l); - printf("%s returns %d need %d\n", __FUNCTION__, ret, oid.id); + // printf("%s returns %d need %d\n", __FUNCTION__, ret, oid.id); if (ret != 0 || oid.id <= sizeof(oid)) return; l = oid.id; @@ -1274,7 +1247,7 @@ dummynet_list(int ac, char *av[], int sh err(1, "no memory in %s", __FUNCTION__); *x = oid; ret = do_cmd(-IP_DUMMYNET3, x, (uintptr_t)&l); - printf("%s returns %d need %d\n", __FUNCTION__, ret, oid.id); + // 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/sys/netinet/ip_dummynet.h ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h Wed Jan 20 18:22:56 2010 (r202709) +++ user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h Wed Jan 20 18:28:24 2010 (r202710) @@ -63,8 +63,9 @@ enum { DN_QUEUE, DN_DELAY_LINE, DN_PROFILE, - DN_FS_EXT, - DN_QUEUE_EXT, + DN_NI, /* new_inst */ + //DN_FS_EXT, + //DN_QUEUE_EXT, DN_TEXT, /* subtype is the object */ DN_CMD_CONFIGURE, /* objects follow */ DN_CMD_DELETE, /* subtype + list of entries */ @@ -82,8 +83,13 @@ enum { /* subtype for schedulers, flowse enum { /* user flags */ DN_HAVE_MASK = 0x0001, + DN_NOERROR = 0x0002, DN_QSIZE_BYTES = 0x0008, - DN_NOERROR = 0x0010, + DN_IS_RED = 0x0020, + DN_IS_GENTLE_RED= 0x0040, +#if 0 +#define DN_HAS_PROFILE 0x0020 /* the pipe has a delay profile. */ +#endif }; typedef uint64_t dn_key; @@ -253,11 +259,5 @@ flow using a number of heaps defined int * */ -#define DN_HAVE_FLOW_MASK 0x0001 -#define DN_IS_RED 0x0002 -#define DN_IS_GENTLE_RED 0x0004 -#define DN_QSIZE_IS_BYTES 0x0008 /* queue size is measured in bytes */ -#define DN_NOERROR 0x0010 /* do not report ENOBUFS on drops */ -#define DN_HAS_PROFILE 0x0020 /* the pipe has a delay profile. */ #endif /* _IP_DUMMYNET_H */ Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.c Wed Jan 20 18:22:56 2010 (r202709) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.c Wed Jan 20 18:28:24 2010 (r202710) @@ -447,7 +447,7 @@ dn_ht_scan(struct dn_ht *ht, int (*fn)(v next = *(void **)((char *)cur + ht->ofs); ret = fn(cur, arg); if (ret & DNHT_SCAN_DEL) { - printf("element %p removed\n", cur); + // printf("element %p removed\n", cur); found++; ht->entries--; *curp = next; Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Wed Jan 20 18:22:56 2010 (r202709) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Wed Jan 20 18:28:24 2010 (r202710) @@ -117,6 +117,19 @@ void dn_free_pkts(struct mbuf *mnext) } } +static int +bound_var(int *v, int dflt, int lo, int hi, const char *msg) +{ + if (*v < lo) { + *v = dflt; + printf("force %s to %d\n", msg, *v); + } else if (*v > hi) { + *v = hi; + printf("clamp %s to %d\n", msg, *v); + } + return *v; +} + /*---- flow_id mask, hash and compare functions ---*/ static struct ipfw_flow_id * flow_id_mask(struct ipfw_flow_id *mask, struct ipfw_flow_id *id) @@ -264,7 +277,7 @@ dn_delete_queue(struct new_queue *q, int { struct new_fsk *fs = q->fs; - printf(" +++ %s fs %p si %p\n", __FUNCTION__, fs, q->_si); + // 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); @@ -272,6 +285,7 @@ dn_delete_queue(struct new_queue *q, int if (flags & DN_DELETE) { if (q->mq.head) dn_free_pkts(q->mq.head); + bzero(q, sizeof(*q)); // safety free(q, M_DUMMYNET); dn_cfg.queue_count--; } @@ -408,8 +422,10 @@ si_new(uintptr_t key, int flags, void *a return si; error: - if (si) + if (si) { + bzero(si, sizeof(*si)); // safety free(si, M_DUMMYNET); + } return NULL; } @@ -436,7 +452,7 @@ si_destroy(void *_si, void *arg) bzero(si, sizeof(*si)); /* safety */ free(si, M_DUMMYNET); dn_cfg.si_count--; - return 0; + return DNHT_SCAN_DEL; } /* @@ -590,7 +606,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); + // printf("%s fs %d found %p\n", __FUNCTION__, i, fs); if (fs) { fsk_detach(fs, DN_DETACH | DN_DELETE_FS); err = 0; @@ -686,9 +702,8 @@ schk_delete_cb(void *obj, void *arg) s->siht = NULL; if (s->fp->destroy) s->fp->destroy(s); - bzero(s, sizeof(*s)); + bzero(s, sizeof(*s)); // safety free(obj, M_DUMMYNET); - // printf("<<< %s done sched %d destroyed\n", __FUNCTION__, i); dn_cfg.schk_count--; return DNHT_SCAN_DEL; } @@ -704,12 +719,12 @@ 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); + // printf("%s sched %d %p\n", __FUNCTION__, i, s); if (!s) return EINVAL; /* detach flowsets, delete traffic */ + delete_fs(i + DN_MAX_ID, 1); /* first remove internal pipe */ schk_delete_cb(s, (void*)(uintptr_t)DN_DELETE); - delete_fs(i + DN_MAX_ID, 1); /* remove internal pipe */ return 0; } @@ -717,17 +732,17 @@ delete_schk(int i) /*--- end of schk hashtable support ---*/ static int -copy_obj(char **start, char *end, void *_o) +copy_obj(char **start, char *end, void *_o, const char *msg, int i) { struct dn_id *o = _o; int have = end - *start; if (have < o->len || o->len == 0 || o->type == 0) { - printf("XXX %s ERROR type %d have %d need %d\n", - __FUNCTION__, o->type, have, o->len); + printf("XXX %s ERROR type %d %s %d have %d need %d\n", + __FUNCTION__, o->type, msg, i, have, o->len); return 1; } - printf("%s type %d len %d\n", __FUNCTION__, o->type, o->len); + // printf("%s type %d %s %d len %d\n", __FUNCTION__, o->type, msg, i, o->len); bcopy(_o, *start, o->len); *start += o->len; return 0; @@ -748,7 +763,7 @@ copy_flowset(struct copy_args *a, struct struct new_fs *ufs = (struct new_fs *)(*a->start); if (!fs) return 0; - if (copy_obj(a->start, a->end, &fs->fs)) + 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 */ @@ -757,41 +772,63 @@ copy_flowset(struct copy_args *a, struct } static int +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)) + return DNHT_SCAN_END; + ni->oid.type = DN_NI; + return 0; +} + +static int +copy_si(struct copy_args *a, struct new_schk *s, int flags) +{ + 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); + } + return 0; +} + +static int copy_data_helper(void *_o, void *_arg) { struct copy_args *a = _arg; - if (a->type == DN_SCH) { /* scanning schedulers */ - struct new_schk *s = _o; + if (a->type == DN_PIPE || /* pipe show */ + a->type == DN_SCH) { /* sched show */ + struct new_schk *s = _o; /* we get only schedulers */ + if (a->type == DN_SCH && s->sch.sched_nr >= DN_MAX_ID) + return 0; /* not valid scheduler */ + if (a->type == DN_PIPE && s->sch.sched_nr <= DN_MAX_ID) + return 0; /* not valid pipe */ if (a->flags & DN_C_PIPE) { - printf("copy pipe %d\n", s->sch.sched_nr); - if (copy_obj(a->start, a->end, &s->pipe)) + if (copy_obj(a->start, a->end, &s->pipe, "pipe", s->sch.sched_nr)) return DNHT_SCAN_END; - printf("copy int-fs for pipe %d %p\n", - s->sch.sched_nr, s->fs); if (copy_flowset(a, s->fs, 0)) return DNHT_SCAN_END; - printf("copy pipe %d done\n", s->sch.sched_nr); } if (a->flags & DN_C_SCH) { - printf("copy sched %d\n", s->sch.sched_nr); - if (copy_obj(a->start, a->end, &s->sch)) + if (copy_obj(a->start, a->end, &s->sch, "sched", s->sch.sched_nr)) return DNHT_SCAN_END; - printf("copy sched %d done\n", s->sch.sched_nr); } if (a->flags & DN_C_SCH_INST) { - printf("XXX todo: scan sched instances\n"); + copy_si(a, s, 0); } } - if (a->type == DN_FS) { /* scanning flowsets */ + if (a->type == DN_FS) { /* queue show, skip internal flowsets */ 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) { - printf("copy fs %d to sched %d\n", fs->fs.fs_nr, - fs->sched ? fs->sched->sch.sched_nr : -1); if (copy_flowset(a, fs, 0)) return DNHT_SCAN_END; - printf("copy fs %d done\n",fs->fs.fs_nr); } } return 0; @@ -927,7 +964,7 @@ config_fs(struct new_fs *nfs, struct dn_ return NULL; // printf("%s flowset %d\n", __FUNCTION__, i); /* XXX other sanity checks */ - if (nfs->flags & DN_QSIZE_IS_BYTES) { + if (nfs->flags & DN_QSIZE_BYTES) { if (nfs->qsize > dn_cfg.pipe_byte_limit) nfs->qsize = dn_cfg.pipe_byte_limit; } else { @@ -938,15 +975,8 @@ config_fs(struct new_fs *nfs, struct dn_ } if (nfs->flags & DN_HAVE_MASK) { /* make sure we have some buckets */ - if (nfs->buckets < 1) { - nfs->buckets = dn_cfg.hash_size; - printf("%s force buckets to %d\n", - __FUNCTION__, nfs->buckets); - } else if (nfs->buckets > dn_cfg.max_hash_size) { - nfs->buckets = dn_cfg.max_hash_size; - printf("%s clamp buckets to %d\n", - __FUNCTION__, nfs->buckets); - } + bound_var(&nfs->buckets, dn_cfg.hash_size, + 1, dn_cfg.max_hash_size, "flowset buckets"); } else { nfs->buckets = 1; /* we only need 1 */ } @@ -1018,6 +1048,10 @@ config_sched(struct new_sch *_nsch, stru i = a.sch->sched_nr; if (i <= 0 || i >= DN_MAX_ID) return EINVAL; + /* make sure we have some buckets */ + if (a.sch->flags & DN_HAVE_MASK) + bound_var(&a.sch->buckets, dn_cfg.hash_size, + 1, dn_cfg.max_hash_size, "sched buckets"); /* XXX other sanity checks */ bzero(&p, sizeof(p)); DN_BH_WLOCK(); @@ -1288,9 +1322,11 @@ compute_space(struct dn_id *cmd, int *to switch (cmd->subtype) { default: return -1; - case DN_SCH: /* pipe show */ - x = DN_C_SCH | DN_C_PIPE | DN_C_FS | - DN_C_SCH_INST | DN_C_QUEUE; + case DN_PIPE: /* pipe show */ + x = DN_C_PIPE | DN_C_FS | DN_SCH | DN_C_SCH_INST; + break; + case DN_SCH: /* sched show */ + x = DN_C_SCH | DN_C_PIPE | DN_C_SCH_INST; break; case DN_FS: /* queue show */ x = DN_C_FS | DN_C_QUEUE; @@ -1371,18 +1407,11 @@ dummynet_get(struct sockopt *sopt) a.start = &buf; a.end = end; a.flags = to_copy; - a.extra = 0; - printf("copy schedulers (%d : %d)\n", - dn_cfg.schk_count, - dn_ht_entries(dn_cfg.schedhash)); - a.type = DN_SCH; - dn_ht_scan(dn_cfg.schedhash, copy_data_helper, &a); - printf("copy unlinked flowsets (%d : %d)\n", - dn_cfg.fsk_count, - dn_ht_entries(dn_cfg.fshash)); - a.type = DN_FS; - a.extra = 1; - dn_ht_scan(dn_cfg.fshash, copy_data_helper, &a); + 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); } DN_BH_WUNLOCK(); error = sooptcopyout(sopt, start, buf - start); @@ -1435,8 +1464,7 @@ ip_dn_ctl(struct sockopt *sopt) printf("argument len %d invalid\n", l); break; } - printf("%s size %d\n", __FUNCTION__, l); - p = malloc(l, M_TEMP, M_WAITOK); + p = malloc(l, M_TEMP, M_WAITOK); // XXX can it fail ? error = sooptcopyin(sopt, p, l, l); if (error) break ; 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; } From owner-svn-src-user@FreeBSD.ORG Thu Jan 21 10:08:59 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 148F0106566B; Thu, 21 Jan 2010 10:08:59 +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 048B78FC1D; Thu, 21 Jan 2010 10:08:59 +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 o0LA8w1R092031; Thu, 21 Jan 2010 10:08:58 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0LA8wxR092029; Thu, 21 Jan 2010 10:08:58 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <201001211008.o0LA8wxR092029@svn.freebsd.org> From: Luigi Rizzo Date: Thu, 21 Jan 2010 10:08: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: r202737 - 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: Thu, 21 Jan 2010 10:08:59 -0000 Author: luigi Date: Thu Jan 21 10:08:58 2010 New Revision: 202737 URL: http://svn.freebsd.org/changeset/base/202737 Log: initialize a field for si_new 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 Thu Jan 21 09:11:50 2010 (r202736) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Thu Jan 21 10:08:58 2010 (r202737) @@ -648,6 +648,7 @@ schk_new(uintptr_t key, int flags, void s->pipe.pipe_nr = s->sch.sched_nr; SLIST_INIT(&s->fsk_list); /* initialize the hash table or create the single instance */ + s->fp = a->fp; /* si_new needs this */ s->siht = (s->sch.flags & DN_HAVE_MASK) ? dn_ht_init(NULL, s->sch.buckets, offsetof(struct new_sch_inst, si_next), @@ -657,6 +658,7 @@ schk_new(uintptr_t key, int flags, void free(s, M_DUMMYNET); return NULL; } + s->fp = NULL; /* mark as a new scheduler */ dn_cfg.schk_count++; return s; } From owner-svn-src-user@FreeBSD.ORG Thu Jan 21 10:09:19 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 A9C73106566C; Thu, 21 Jan 2010 10:09:19 +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 997CD8FC14; Thu, 21 Jan 2010 10:09:19 +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 o0LA9JCZ092137; Thu, 21 Jan 2010 10:09:19 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0LA9JTs092134; Thu, 21 Jan 2010 10:09:19 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <201001211009.o0LA9JTs092134@svn.freebsd.org> From: Luigi Rizzo Date: Thu, 21 Jan 2010 10:09:19 +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: r202738 - 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: Thu, 21 Jan 2010 10:09:19 -0000 Author: luigi Date: Thu Jan 21 10:09:19 2010 New Revision: 202738 URL: http://svn.freebsd.org/changeset/base/202738 Log: some documentation fixes Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_fifo.c user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c 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 10:08:58 2010 (r202737) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_fifo.c Thu Jan 21 10:09:19 2010 (r202738) @@ -47,13 +47,16 @@ * This file implements a FIFO scheduler for a single queue. * The queue is allocated as part of the scheduler instance, * and there is a single flowset is in the template which stores - * queue-related information. - * No parameters are used except queue sizes and management policy. + * queue size and policy. * Enqueue and dequeue use the default library functions. */ static int fifo_enqueue(struct new_sch_inst *si, struct new_queue *q, struct mbuf *m) { + /* XXX if called with q != NULL and m=NULL, this is a + * re-enqueue from an existing scheduler, which we should + * handle. + */ return dn_enqueue((struct new_queue *)(si+1), m, 0); } 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 10:08:58 2010 (r202737) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c Thu Jan 21 10:09:19 2010 (r202738) @@ -48,10 +48,6 @@ #define MY_M 16 /* shift for fixed point arithmetic */ #endif -#ifndef isdigit -#define isdigit(x) ((x) >= '0' && (x) <= '9' ) -#endif - /* * Private information for the scheduler instance: * sch_heap (key is Finish time) returns the next queue to serve @@ -234,7 +230,7 @@ wf2qp_new_sched(struct new_sch_inst *_si struct wf2qp_si *si = (struct wf2qp_si *)(_si + 1); int ofs = sizeof(*_si) + offsetof(struct wf2qp_queue, heap_pos); - /* only idle-heap supports extract from middle */ + /* all heaps support extract from middle */ if (heap_init(&si->idle_heap, 16, ofs) || heap_init(&si->sch_heap, 16, ofs) || heap_init(&si->ne_heap, 16, ofs)) { @@ -283,6 +279,12 @@ wf2qp_new_queue(struct new_queue *_q) return 0; } +/* + * Called when the infrastructure removes a queue (e.g. flowset + * is reconfigured). Nothing to do if we did not 'own' the queue, + * otherwise remove it from the right heap and adjust the sum + * of weights. + */ static int wf2qp_free_queue(struct new_queue *q) { @@ -290,13 +292,11 @@ wf2qp_free_queue(struct new_queue *q) struct wf2qp_si *si = (struct wf2qp_si *)(q->_si + 1); printf("%s called\n", __FUNCTION__); - /* If the queue was valid, decrement the sum value */ - if (alg_fq->S == alg_fq->F + 1) + if (alg_fq->S >= alg_fq->F + 1) return 0; /* nothing to do, not in any heap */ - /* decrement the sum of weights */ si->sum -= q->fs->fs.weight; - /* extract from the heap. Note that we may need to adjust V + /* extract from the heap. XXX TODO we may need to adjust V * to make sure the invariants hold. */ if (q->mq.head == NULL) { @@ -319,6 +319,7 @@ static struct dn_sched wf2qp_desc = { .name = "WF2Q+", .flags = DN_MULTIQUEUE, + /* we need extra space in the si and the queue */ .si_datalen = sizeof(struct wf2qp_si), .q_datalen = sizeof(struct wf2qp_queue), From owner-svn-src-user@FreeBSD.ORG Thu Jan 21 11:41:30 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 0B530106566B; Thu, 21 Jan 2010 11:41:30 +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 EF9818FC0C; Thu, 21 Jan 2010 11:41:29 +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 o0LBfTv0015435; Thu, 21 Jan 2010 11:41:29 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0LBfTKw015433; Thu, 21 Jan 2010 11:41:29 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <201001211141.o0LBfTKw015433@svn.freebsd.org> From: Luigi Rizzo Date: Thu, 21 Jan 2010 11:41:29 +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: r202744 - 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: Thu, 21 Jan 2010 11:41:30 -0000 Author: luigi Date: Thu Jan 21 11:41:29 2010 New Revision: 202744 URL: http://svn.freebsd.org/changeset/base/202744 Log: fix an error in a comparison Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_rr.c 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 11:36:40 2010 (r202743) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_rr.c Thu Jan 21 11:41:29 2010 (r202744) @@ -113,7 +113,7 @@ rr_enqueue(struct new_sch_inst *_si, str if (m != q->mq.head) { if (dn_enqueue(q, m, 0)) /* packet was dropped */ return 1; - if (m == q->mq.head) + if (m != q->mq.head) return 0; } From owner-svn-src-user@FreeBSD.ORG Thu Jan 21 13:00:28 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 D57C3106568D; Thu, 21 Jan 2010 13:00:28 +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 C440D8FC15; Thu, 21 Jan 2010 13:00:28 +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 o0LD0SVQ033366; Thu, 21 Jan 2010 13:00:28 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0LD0SGo033358; Thu, 21 Jan 2010 13:00:28 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <201001211300.o0LD0SGo033358@svn.freebsd.org> From: Luigi Rizzo Date: Thu, 21 Jan 2010 13:00:28 +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: r202746 - 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 13:00:28 -0000 Author: luigi Date: Thu Jan 21 13:00:28 2010 New Revision: 202746 URL: http://svn.freebsd.org/changeset/base/202746 Log: - remove stale data structures - remove old, incorrect documentation and add correct one; - adjust the handling of masks. When both flow_mask and sched_mask are present, we must do the initial grouping by (flow_mask|sched_mask) otherwise a queue might end up to two different schedulers. TODO: find better names for 'things' -- especially the naming of queue-related structures is very confusing. 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_wf2q.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 Thu Jan 21 12:18:29 2010 (r202745) +++ user/luigi/ipfw3-head/sbin/ipfw/dummynet.c Thu Jan 21 13:00:28 2010 (r202746) @@ -87,12 +87,12 @@ static struct _s_x dummynet_params[] = { #define O_NEXT(p, len) ((void *)(char *)(p) + len) static void -oid_fill(struct dn_id *oid, int len, int type) +oid_fill(struct dn_id *oid, int len, int type, uintptr_t id) { oid->len = len; oid->type = type; oid->subtype = 0; - oid->id = 0; + oid->id = id; } /* make room in the buffer and move the pointer forward */ @@ -100,7 +100,7 @@ static void * o_next(struct dn_id **o, int len, int type) { struct dn_id *ret = *o; - oid_fill(ret, len, type); + oid_fill(ret, len, type, 0); *o = O_NEXT(*o, len); return ret; } @@ -379,12 +379,15 @@ list_pipes(struct dn_id *oid, struct dn_ int ipfw_delete_pipe(int pipe_or_queue, int i) { - struct dn_id oid; - oid_fill(&oid, sizeof(oid), DN_CMD_DELETE); - oid.subtype = (co.do_pipe == 1) ? DN_PIPE : + struct { + struct dn_id oid; + uint32_t a[1]; /* 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_PIPE : ( (co.do_pipe == 2) ? DN_FS : DN_SCH); - oid.id = i; - i = do_cmd(IP_DUMMYNET3, &oid, oid.len); + cmd.a[0] = i; + i = do_cmd(IP_DUMMYNET3, &cmd, cmd.oid.len); if (i) { i = 1; warn("rule %u: setsockopt(IP_DUMMYNET_DEL)", i); @@ -750,13 +753,18 @@ ipfw_config_pipe(int ac, char **av) struct new_pipe *p = NULL; struct new_fs *fs = NULL; struct new_profile *pf = NULL; - struct new_cmd *cmd = NULL; struct ipfw_flow_id *mask = NULL; - int lmax = sizeof(*cmd); /* always present */ + int lmax; int _foo = 0, *flags = &_foo; - /* worst case: 2 schedulers, 1 profile, 1 pipe, 1 flowset */ - lmax += 2*sizeof(*sch) + 2*sizeof(*p) + sizeof(*fs) + sizeof(*pf); + /* + * allocate space for 1 header, + * 1 scheduler, 1 pipe, 1 flowset, 1 profile + */ + lmax = sizeof(struct dn_id); /* command header */ + lmax += sizeof(struct new_sch) + sizeof(struct new_pipe) + + sizeof(struct new_fs) + + sizeof(struct new_profile); av++; ac--; /* Pipe number */ @@ -769,8 +777,9 @@ ipfw_config_pipe(int ac, char **av) if (buf == NULL) { errx(1, "no memory for pipe buffer"); } - cmd = o_next(&buf, sizeof(*cmd), DN_CMD_CONFIGURE); - cmd->entries = 0; /* no explicit arguments */ + /* all commands start with a 'CONFIGURE' and a version */ + o_next(&buf, sizeof(struct dn_id), DN_CMD_CONFIGURE); + base->id = DN_API_VERSION; switch (co.do_pipe) { case 1: @@ -1213,7 +1222,7 @@ void dummynet_flush(void) { struct dn_id oid; - oid_fill(&oid, sizeof(oid), DN_CMD_FLUSH); + oid_fill(&oid, sizeof(oid), DN_CMD_FLUSH, DN_API_VERSION); do_cmd(IP_DUMMYNET3, &oid, oid.len); } @@ -1225,7 +1234,7 @@ dummynet_list(int ac, char *av[], int sh oid.type = DN_CMD_GET; oid.len = l; - oid.id = 0; + oid.id = DN_API_VERSION; switch (co.do_pipe) { case 1: oid.subtype = DN_PIPE; /* list pipe */ @@ -1237,7 +1246,6 @@ dummynet_list(int ac, char *av[], int sh oid.subtype = DN_SCH; /* list sched */ break; } - /* XXX we could use oid.id for the filter */ ret = do_cmd(-IP_DUMMYNET3, &oid, (uintptr_t)&l); // printf("%s returns %d need %d\n", __FUNCTION__, ret, oid.id); if (ret != 0 || oid.id <= sizeof(oid)) Modified: user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h Thu Jan 21 12:18:29 2010 (r202745) +++ user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h Thu Jan 21 13:00:28 2010 (r202746) @@ -36,14 +36,21 @@ * Setsockopt() and getsockopt() pass a batch of objects, each * of them starting with a "struct dn_id" which should fully identify * the object and its relation with others in the sequence. - * objects in a batch of requests. - * This struct store in the type field an identifier of the type of object - * passed (for example a pipe, a scheduler...). The subtype - * field contains more detail info, if needed. + * The first object in each request should have + * type= DN_CMD_*, id = DN_API_VERSION. + * For other objects, type and subtype specify the object, len indicates + * the total length including the header, and 'id' identifies the specific + * object. + * + * Most objects are numbered with an identifier in the range 1..65535. + * DN_MAX_ID indicates the first value outside the range. */ +#define DN_API_VERSION 12500000 +#define DN_MAX_ID 0x10000 + struct dn_id { - uint16_t len; /* total len including this header */ + uint16_t len; /* total obj len including this header */ uint8_t type; uint8_t subtype; uintptr_t id; /* generic id or pointer */ @@ -63,10 +70,10 @@ enum { DN_QUEUE, DN_DELAY_LINE, DN_PROFILE, - DN_NI, /* new_inst */ + DN_NI, /* struct new_inst */ //DN_FS_EXT, //DN_QUEUE_EXT, - DN_TEXT, /* subtype is the object */ + DN_TEXT, /* opaque text is the object */ DN_CMD_CONFIGURE, /* objects follow */ DN_CMD_DELETE, /* subtype + list of entries */ DN_CMD_GET, /* subtype + list of entries */ @@ -82,36 +89,12 @@ enum { /* subtype for schedulers, flowse }; enum { /* user flags */ - DN_HAVE_MASK = 0x0001, - DN_NOERROR = 0x0002, - DN_QSIZE_BYTES = 0x0008, + DN_HAVE_MASK = 0x0001, /* fs or sched has a mask */ + DN_NOERROR = 0x0002, /* do not report errors */ + DN_QSIZE_BYTES = 0x0008, /* queue size is in bytes */ + DN_HAS_PROFILE = 0x0010, /* a pipe has a profile */ DN_IS_RED = 0x0020, DN_IS_GENTLE_RED= 0x0040, -#if 0 -#define DN_HAS_PROFILE 0x0020 /* the pipe has a delay profile. */ -#endif -}; - -typedef uint64_t dn_key; - -struct new_cmd { /* header for all sockopt */ - struct dn_id oid; - int entries; - uint32_t data[0]; /* actually, entries elements */ -}; - -/* A delay profile is attached to a pipe */ -#define ED_MAX_SAMPLES_NO 1024 -struct new_profile { - struct dn_id oid; - /* fields to simulate a delay profile */ -#define ED_MAX_NAME_LEN 32 - char name[ED_MAX_NAME_LEN]; - int pipe_nr; - int loss_level; - int bandwidth; - int samples_no; - int samples[ED_MAX_SAMPLES_NO]; /* this has actually samples_no slots */ }; /* @@ -187,77 +170,66 @@ struct new_sch { }; -/* - * "queue N" and "pipe N" accept 1<=N<=65535. - * So valid names are from 1 to DN_MAXID-1 - */ -#define DN_MAX_ID 0x10000 +/* A delay profile is attached to a pipe */ +#define ED_MAX_SAMPLES_NO 1024 +struct new_profile { + struct dn_id oid; + /* fields to simulate a delay profile */ +#define ED_MAX_NAME_LEN 32 + char name[ED_MAX_NAME_LEN]; + int pipe_nr; + int loss_level; + int bandwidth; + int samples_no; /* actual length of samples[] */ + int samples[ED_MAX_SAMPLES_NO]; /* may be shorter */ +}; -/* - * The maximum hash table size for queues (unused ?) - */ -#define DN_MAX_HASH_SIZE 65536 /* - * Overall structure of dummynet (with WF2Q+): + * Overall structure of dummynet In dummynet, packets are selected with the firewall rules, and passed -to two different objects: PIPE or QUEUE. +to two different objects: PIPE or QUEUE (bad name). -A QUEUE is just a queue with configurable size and queue management -policy. It is also associated with a mask (to discriminate among -different flows), a weight (used to give different shares of the -bandwidth to different flows) and a "pipe", which essentially -supplies the transmit clock for all queues associated with that -pipe. - -A PIPE emulates a fixed-bandwidth link, whose bandwidth is -configurable. The "clock" for a pipe can come from either an -internal timer, or from the transmit interrupt of an interface. -A pipe is also associated with one (or more, if masks are used) -queue, where all packets for that pipe are stored. - -The bandwidth available on the pipe is shared by the queues -associated with that pipe (only one in case the packet is sent -to a PIPE) according to the WF2Q+ scheduling algorithm and the -configured weights. - -In general, incoming packets are stored in the appropriate queue, -which is then placed into one of a few heaps managed by a scheduler -to decide when the packet should be extracted. -The scheduler (a function called dummynet()) is run at every timer -tick, and grabs queues from the head of the heaps when they are -ready for processing. +A QUEUE defines a classifier, which groups packets into flows +according to a 'mask', puts them into independent queues (one +per flow) with configurable size and queue management policy, +and passes flows to a scheduler: + + (flow_mask|sched_mask) sched_mask + +---------+ weight Wx +-------------+ + | |->-[flow]-->--| |-+ + -->--| QUEUE x | ... | | | + | |->-[flow]-->--| SCHEDuler N | | + +---------+ | | | + ... | +--[LINK N]-->-- + +---------+ weight Wy | | +--[LINK N]-->-- + | |->-[flow]-->--| | | + -->--| QUEUE y | ... | | | + | |->-[flow]-->--| | | + +---------+ +-------------+ | + +-------------+ + +Many QUEUE objects can connect to the same scheduler, each +QUEUE object can have its own set of parameters. + +In turn, the SCHEDuler 'forks' multiple instances according +to a 'sched_mask', each instance manages its own set of queues +and transmits on a private instance of a configurable LINK. + +A PIPE is a simplified version of the above, where there +is no flow_mask, and each scheduler instance handles a single queue. There are three data structures definining a pipe and associated queues: + dn_pipe, which contains the main configuration parameters related to delay and bandwidth; - + dn_flow_set, which contains WF2Q+ configuration, flow - masks, plr and RED configuration; - + dn_flow_queue, which is the per-flow queue (containing the packets) - -Multiple dn_flow_set can be linked to the same pipe, and multiple -dn_flow_queue can be linked to the same dn_flow_set. -All data structures are linked in a linear list which is used for -housekeeping purposes. - -During configuration, we create and initialize the dn_flow_set -and dn_pipe structures (a dn_pipe also contains a dn_flow_set). - -At runtime: packets are sent to the appropriate dn_flow_set (either -WFQ ones, or the one embedded in the dn_pipe for fixed-rate flows), -which in turn dispatches them to the appropriate dn_flow_queue -(created dynamically according to the masks). - -The transmit clock for fixed rate flows (ready_event()) selects the -dn_flow_queue to be used to transmit the next packet. For WF2Q, -wfq_ready_event() extract a pipe which in turn selects the right -flow using a number of heaps defined into the pipe itself. + + dn_flowset, which contains flow masks, weights and queue + parameters; + + dn_flow, which contains the queue status (flow id, statistics) * */ - #endif /* _IP_DUMMYNET_H */ 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 12:18:29 2010 (r202745) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c Thu Jan 21 13:00:28 2010 (r202746) @@ -62,13 +62,13 @@ struct wf2qp_si { struct dn_heap sch_heap; /* top extract - key Finish time */ struct dn_heap ne_heap; /* top extract - key Start time */ struct dn_heap idle_heap; /* random extract - key Start=Finish time */ - dn_key V ; /* virtual time */ + uint64_t V; /* virtual time */ uint32_t sum; /* sum of weights */ }; struct wf2qp_queue { - dn_key S,F; /* start time, finish time */ - int heap_pos; /* position (index) of struct in heap */ + uint64_t S, F; /* start time, finish time */ + int32_t heap_pos; /* position (index) of struct in heap */ }; /* 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 12:18:29 2010 (r202745) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c Thu Jan 21 13:00:28 2010 (r202746) @@ -66,7 +66,7 @@ __FBSDID("$FreeBSD$"); * We keep a private variable for the simulation time, but we could * probably use an existing one ("softticks" in sys/kern/kern_timeout.c) */ -static dn_key curr_time = 0 ; /* current simulation time */ +static uint64_t curr_time = 0; /* current simulation time */ struct dn_parms dn_cfg = { .pipe_slot_limit = 100, /* Foot shooting limit for pipe queues. */ @@ -176,7 +176,7 @@ struct dn_pkt_tag { /* second part, dummynet specific */ int dn_dir; /* action when packet comes out.*/ /* see ip_fw_private.h */ - dn_key output_time; /* when the pkt is due for delivery*/ + uint64_t output_time; /* when the pkt is due for delivery*/ struct ifnet *ifp; /* interface, for ip_output */ struct _ip6dn_args ip6opt; /* XXX ipv6 options */ }; @@ -279,7 +279,7 @@ drop: * Runs under scheduler lock. */ static void -transmit_event(struct mq *q, struct delay_line *dline, dn_key now) +transmit_event(struct mq *q, struct delay_line *dline, uint64_t now) { struct mbuf *m; struct dn_pkt_tag *pkt = NULL; @@ -327,7 +327,7 @@ extra_bits(struct mbuf *m, struct new_sc * Return a pointer to the head of the queue. */ static struct mbuf * -serve_sched(struct mq *q, struct new_sch_inst *si, dn_key now) +serve_sched(struct mq *q, struct new_sch_inst *si, uint64_t now) { struct mq def_q; struct new_schk *s = si->sched; @@ -367,7 +367,7 @@ serve_sched(struct mq *q, struct new_sch if (si->credit >= 0) { si->idle_time = now; } else { - dn_key t; + uint64_t t; KASSERT (bw > 0, ("bw=0 and credit<0 ?")); t = div64(bw - 1 - si->credit, bw); if (m) @@ -611,9 +611,8 @@ dummynet_io(struct mbuf **m0, int dir, s if (si == NULL) goto dropit; /* - * If the support multiple queues, find the right one + * If the scheduler supports multiple queues, find the right one * (otherwise it will be ignored by enqueue). - * We cannot pass si as an argument :( */ if (fs->sched->fp->flags & DN_MULTIQUEUE) { q = ipdn_q_find(fs, si, &(fwa->f_id)); 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 12:18:29 2010 (r202745) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h Thu Jan 21 13:00:28 2010 (r202746) @@ -150,6 +150,9 @@ struct delay_line { * The kernel side of a flowset. It is linked in a hash table * of flowsets, and in a list of children of their parent scheduler. * qht is either the queue or (if HAVE_MASK) a hash table queues. + * Note that the mask to use is the (flow_mask|sched_mask), which + * changes as we attach/detach schedulers. So we store it here. + * * XXX If we want to add scheduler-specific parameters, we need to * put them in external storage because the scheduler may not be * available when the fsk is created. @@ -158,6 +161,8 @@ struct new_fsk { /* kernel side of a flo struct new_fs fs; SLIST_ENTRY(new_fsk) fsk_next; /* hash chain list */ + struct ipfw_flow_id fsk_mask; + /* hash table of queues, or just single queue */ struct dn_ht *_qht; struct new_schk *sched; /* Sched we are linked to */ @@ -220,8 +225,8 @@ struct new_sch_inst { int kflags; /* DN_ACTIVE */ int64_t credit; /* bits I can transmit (more or less). */ - dn_key sched_time; /* time pipe was scheduled in ready_heap */ - dn_key idle_time; /* start of scheduler instance idle time */ + uint64_t sched_time; /* time pipe was scheduled in ready_heap */ + uint64_t idle_time; /* start of scheduler instance idle time */ }; /* kernel-side flags */ Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Thu Jan 21 12:18:29 2010 (r202745) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Thu Jan 21 13:00:28 2010 (r202746) @@ -142,6 +142,33 @@ flow_id_mask(struct ipfw_flow_id *mask, return id; } +/* computes an OR of two masks, result in dst and also returned */ +static struct ipfw_flow_id * +flow_id_or(struct ipfw_flow_id *src, struct ipfw_flow_id *dst) +{ + int is_v6 = IS_IP6_FLOW_ID(dst); + + dst->dst_port |= src->dst_port; + dst->src_port |= src->src_port; + dst->proto |= src->proto; + dst->flags = 0; /* we don't care about this one */ + if (is_v6) { +#define OR_MASK(_d, _s) \ + (_d)->__u6_addr.__u6_addr32[0] |= (_s)->__u6_addr.__u6_addr32[0]; \ + (_d)->__u6_addr.__u6_addr32[1] |= (_s)->__u6_addr.__u6_addr32[1]; \ + (_d)->__u6_addr.__u6_addr32[2] |= (_s)->__u6_addr.__u6_addr32[2]; \ + (_d)->__u6_addr.__u6_addr32[3] |= (_s)->__u6_addr.__u6_addr32[3]; + OR_MASK(&dst->dst_ip6, &src->dst_ip6); + OR_MASK(&dst->src_ip6, &src->src_ip6); +#undef OR_MASK + dst->flow_id6 |= src->flow_id6; + } else { + dst->dst_ip |= src->dst_ip; + dst->src_ip |= src->src_ip; + } + return dst; +} + /* XXX we may want a better hash function */ static uint32_t flow_id_hash(struct ipfw_flow_id *id) @@ -338,7 +365,7 @@ ipdn_q_find(struct new_fsk *fs, struct n return NULL; } masked_id = *id; - flow_id_mask(&fs->fs.flow_mask, &masked_id); + flow_id_mask(&fs->fsk_mask, &masked_id); return dn_ht_find(fs->_qht, (uintptr_t)&masked_id, DNHT_INSERT, &template); } else { @@ -839,6 +866,10 @@ fsk_attach(struct new_fsk *fs, struct ne SLIST_INSERT_HEAD(&s->fsk_list, fs, sch_chain); if (s->fp->new_fsk) s->fp->new_fsk(fs); + /* 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); if (!fs->_qht) return; D("XXX TODO requeue from fs %d to sch %d", @@ -1221,7 +1252,8 @@ dummynet_flush(void) } /* - * Main handler for configuration. Rules of the game: + * Main handler for configuration. We are guaranteed to be called + * with an oid which is at least a dn_id. * - the first object is the command (config, delete, flush, ...) * - config_pipe must be issued after the corresponding config_sched * - parameters (DN_TXT) for an object must preceed the object @@ -1234,10 +1266,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) { + o = p; + if (o->id != DN_API_VERSION) { + D("invalid api version got %d need %d", + o->id, DN_API_VERSION); + return EINVAL; + } + for (; l >= sizeof(*o); o = next) { struct dn_id *prev = arg; if (o->len < sizeof(*o) || l < o->len) { D("bad len o->len %d len %d", o->len, l); @@ -1451,7 +1486,7 @@ ip_dn_ctl(struct sockopt *sopt) break; } l = sopt->sopt_valsize; - if (l < 0 || l > 12000) { + if (l < sizeof(struct dn_id) || l > 12000) { D("argument len %d invalid", l); break; } From owner-svn-src-user@FreeBSD.ORG Thu Jan 21 13:21:06 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 F0C5C1065692; Thu, 21 Jan 2010 13:21:06 +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 DF96A8FC0A; Thu, 21 Jan 2010 13:21:06 +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 o0LDL6Qu038050; Thu, 21 Jan 2010 13:21:06 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0LDL6bc038043; Thu, 21 Jan 2010 13:21:06 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <201001211321.o0LDL6bc038043@svn.freebsd.org> From: Luigi Rizzo Date: Thu, 21 Jan 2010 13:21:06 +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: r202748 - 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 13:21:07 -0000 Author: luigi Date: Thu Jan 21 13:21:06 2010 New Revision: 202748 URL: http://svn.freebsd.org/changeset/base/202748 Log: Replace the 'pipe' prefix/name with 'link' for objects that only relate to a communication link. 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/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 Thu Jan 21 13:15:14 2010 (r202747) +++ user/luigi/ipfw3-head/sbin/ipfw/dummynet.c Thu Jan 21 13:21:06 2010 (r202748) @@ -67,6 +67,7 @@ static struct _s_x dummynet_params[] = { { "bw", TOK_BW }, { "bandwidth", TOK_BW }, { "delay", TOK_DELAY }, + { "link", TOK_PIPE }, { "pipe", TOK_PIPE }, { "queue", TOK_QUEUE }, { "flowset", TOK_FLOWSET }, @@ -271,11 +272,11 @@ flush_buf(char *buf) /* * generic list routine. We expect objects in a specific order, i.e. * PIPES AND SCHEDULERS: - * pipe; scheduler; internal flowset if any; instances + * link; scheduler; internal flowset if any; instances * XXX do we need the queue ? * FLOWSETS: * flowset; queues; - * pipe i (int queue); scheduler i; si(i) { flowsets() : queues } + * link i (int queue); scheduler i; si(i) { flowsets() : queues } * filt is an array of sorted ranges whithin where we list */ static void @@ -310,8 +311,8 @@ list_pipes(struct dn_id *oid, struct dn_ list_queue((struct new_inst *)oid); break; - case DN_PIPE: { - struct new_pipe *p = (struct new_pipe *)oid; + case DN_LINK: { + struct dn_link *p = (struct dn_link *)oid; double b = p->bandwidth; char bwbuf[30]; char burst[5 + 7]; @@ -332,7 +333,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->pipe_nr, bwbuf, p->delay, burst); + p->link_nr, bwbuf, p->delay, burst); } break; @@ -366,7 +367,7 @@ list_pipes(struct dn_id *oid, struct dn_ } q = (struct dn_flow_queue *)(fs+1); - sprintf(prefix, "q%05d: weight %d pipe %d ", + sprintf(prefix, "q%05d: weight %d sched %d ", fs->fs_nr, fs->weight, fs->parent_nr); print_flowset_parms(fs, prefix); list_queues(fs, q); @@ -384,7 +385,7 @@ ipfw_delete_pipe(int pipe_or_queue, int uint32_t a[1]; /* 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_PIPE : + cmd.oid.subtype = (co.do_pipe == 1) ? DN_LINK : ( (co.do_pipe == 2) ? DN_FS : DN_SCH); cmd.a[0] = i; i = do_cmd(IP_DUMMYNET3, &cmd, cmd.oid.len); @@ -424,7 +425,7 @@ ipfw_delete_pipe(int pipe_or_queue, int * The empirical curve may have both vertical and horizontal lines. * Vertical lines represent constant delay for a range of * probabilities; horizontal lines correspond to a discontinuty - * in the delay distribution: the pipe will use the largest delay + * in the delay distribution: the link will use the largest delay * for a given probability. * * To pass the curve to dummynet, we must store the parameters @@ -750,7 +751,7 @@ ipfw_config_pipe(int ac, char **av) void *par = NULL; struct dn_id *buf, *base; struct new_sch *sch = NULL; - struct new_pipe *p = NULL; + struct dn_link *p = NULL; struct new_fs *fs = NULL; struct new_profile *pf = NULL; struct ipfw_flow_id *mask = NULL; @@ -759,10 +760,10 @@ ipfw_config_pipe(int ac, char **av) /* * allocate space for 1 header, - * 1 scheduler, 1 pipe, 1 flowset, 1 profile + * 1 scheduler, 1 link, 1 flowset, 1 profile */ lmax = sizeof(struct dn_id); /* command header */ - lmax += sizeof(struct new_sch) + sizeof(struct new_pipe) + + lmax += sizeof(struct new_sch) + sizeof(struct dn_link) + sizeof(struct new_fs) + sizeof(struct new_profile); @@ -775,7 +776,7 @@ ipfw_config_pipe(int ac, char **av) errx(EX_USAGE, "need a pipe/flowset/sched number"); base = buf = calloc(1, lmax); if (buf == NULL) { - errx(1, "no memory for pipe buffer"); + 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); @@ -792,10 +793,10 @@ ipfw_config_pipe(int ac, char **av) flags = &sch->flags; /* the FIFO scheduler is created in the kernel from the WFQ one */ - /* the WFQ pipe */ - p = o_next(&buf, sizeof(*p), DN_PIPE); - p->pipe_nr = i; - /* the FIFO pipe is created in the kerne from WFQ pipe */ + /* 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 @@ -1033,14 +1034,14 @@ end_mask: break; case TOK_BW: - NEED(p, "bw is only for pipe"); + NEED(p, "bw is only for links"); NEED1("bw needs bandwidth or interface\n"); read_bandwidth(av[0], &p->bandwidth, NULL, 0); ac--; av++; break; case TOK_DELAY: - NEED(p, "delay is only for pipes"); + NEED(p, "delay is only for links"); NEED1("delay needs argument 0..10000ms\n"); p->delay = strtoul(av[0], NULL, 0); ac--; av++; @@ -1069,7 +1070,7 @@ end_mask: case TOK_SCHED: case TOK_PIPE: NEED(fs, "pipe/sched"); - NEED1("pipe needs pipe_number\n"); + NEED1("pipe/link/sched needs number\n"); fs->sched_nr = strtoul(av[0], &end, 0); ac--; av++; break; @@ -1237,7 +1238,7 @@ dummynet_list(int ac, char *av[], int sh oid.id = DN_API_VERSION; switch (co.do_pipe) { case 1: - oid.subtype = DN_PIPE; /* list pipe */ + oid.subtype = DN_LINK; /* list pipe */ break; case 2: oid.subtype = DN_FS; /* list queue */ Modified: user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h Thu Jan 21 13:15:14 2010 (r202747) +++ user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h Thu Jan 21 13:21:06 2010 (r202748) @@ -63,7 +63,7 @@ struct dn_id { */ enum { DN_NONE = 0, - DN_PIPE = 1, + DN_LINK = 1, DN_FS, DN_SCH, DN_SCH_I, @@ -92,15 +92,15 @@ enum { /* user flags */ DN_HAVE_MASK = 0x0001, /* fs or sched has a mask */ DN_NOERROR = 0x0002, /* do not report errors */ DN_QSIZE_BYTES = 0x0008, /* queue size is in bytes */ - DN_HAS_PROFILE = 0x0010, /* a pipe has a profile */ + DN_HAS_PROFILE = 0x0010, /* a link has a profile */ DN_IS_RED = 0x0020, DN_IS_GENTLE_RED= 0x0040, }; /* - * pipe template. + * link template. */ -struct new_pipe { +struct dn_link { struct dn_id oid; /* @@ -108,7 +108,7 @@ struct new_pipe { * The kernel converts this back and forth to bits/tick and ticks. * XXX what about burst ? */ - int32_t pipe_nr; + int32_t link_nr; int bandwidth; /* bit/s or bits/tick. */ int delay; /* ms and ticks */ uint64_t burst; /* scaled. bits*Hz XXX */ @@ -170,14 +170,14 @@ struct new_sch { }; -/* A delay profile is attached to a pipe */ +/* A delay profile is attached to a link */ #define ED_MAX_SAMPLES_NO 1024 struct new_profile { struct dn_id oid; /* fields to simulate a delay profile */ #define ED_MAX_NAME_LEN 32 char name[ED_MAX_NAME_LEN]; - int pipe_nr; + int link_nr; int loss_level; int bandwidth; int samples_no; /* actual length of samples[] */ @@ -223,7 +223,7 @@ is no flow_mask, and each scheduler inst There are three data structures definining a pipe and associated queues: - + dn_pipe, which contains the main configuration parameters related + + dn_link, which contains the main configuration parameters related to delay and bandwidth; + dn_flowset, which contains flow masks, weights and queue parameters; 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 13:15:14 2010 (r202747) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c Thu Jan 21 13:21:06 2010 (r202748) @@ -69,8 +69,8 @@ __FBSDID("$FreeBSD$"); static uint64_t curr_time = 0; /* current simulation time */ struct dn_parms dn_cfg = { - .pipe_slot_limit = 100, /* Foot shooting limit for pipe queues. */ - .pipe_byte_limit = 1024 * 1024, + .slot_limit = 100, /* Foot shooting limit for queues. */ + .byte_limit = 1024 * 1024, .red_lookup_depth = 256, /* RED - default lookup table depth */ .red_avg_pkt_size = 512, /* RED - default medium packet size */ @@ -110,10 +110,10 @@ SYSCTL_NODE(_net_inet_ip, OID_AUTO, dumm SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, hash_size, CTLFLAG_RW, &dn_cfg.hash_size, 0, "Default hash table size"); SYSCTL_LONG(_net_inet_ip_dummynet, OID_AUTO, pipe_slot_limit, - CTLFLAG_RW, &dn_cfg.pipe_slot_limit, 0, + CTLFLAG_RW, &dn_cfg.slot_limit, 0, "Upper limit in slots for pipe queue."); SYSCTL_LONG(_net_inet_ip_dummynet, OID_AUTO, pipe_byte_limit, - CTLFLAG_RW, &dn_cfg.pipe_byte_limit, 0, + CTLFLAG_RW, &dn_cfg.byte_limit, 0, "Upper limit in bytes for pipe queue."); SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, io_fast, CTLFLAG_RW, &dn_cfg.io_fast, 0, "Enable fast dummynet io."); @@ -313,7 +313,7 @@ extra_bits(struct mbuf *m, struct new_sc if (!pf || pf->samples_no == 0) return 0; index = random() % pf->samples_no; - bits = div64((uint64_t)pf->samples[index] * s->pipe.bandwidth, 1000); + bits = div64((uint64_t)pf->samples[index] * s->link.bandwidth, 1000); if (index >= pf->loss_level) { struct dn_pkt_tag *dt = dn_tag_get(m); if (dt) @@ -340,7 +340,7 @@ serve_sched(struct mq *q, struct new_sch q->head = NULL; } - bw = s->pipe.bandwidth; + bw = s->link.bandwidth; si->kflags &= ~DN_ACTIVE; if (bw > 0) @@ -356,7 +356,7 @@ serve_sched(struct mq *q, struct new_sch (m->m_pkthdr.len * 8 + extra_bits(m, s)); si->credit -= len_scaled; /* Move packet in the delay line */ - dn_tag_get(m)->output_time += s->pipe.delay ; + dn_tag_get(m)->output_time += s->link.delay ; mq_append(&si->dline.mq, m); } /* @@ -633,7 +633,7 @@ dummynet_io(struct mbuf **m0, int dir, s /* compute the initial allowance */ { - struct new_pipe *p = &fs->sched->pipe; + struct dn_link *p = &fs->sched->link; si->credit = dn_cfg.io_fast ? p->bandwidth : 0; if (p->burst) { uint64_t burst = (curr_time - si->idle_time) * p->bandwidth; 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 13:15:14 2010 (r202747) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h Thu Jan 21 13:21:06 2010 (r202748) @@ -93,8 +93,8 @@ struct dn_parms { int red_max_pkt_size; int hash_size; int max_hash_size; - long pipe_byte_limit; - long pipe_slot_limit; + long byte_limit; /* max queue sizes */ + long slot_limit; int io_fast; @@ -137,7 +137,7 @@ struct dn_parms { }; /* - * Delay line, contains all packets on output from a pipe. + * Delay line, contains all packets on output from a link. * Every scheduler instance has one. */ struct delay_line { @@ -189,7 +189,7 @@ struct new_queue { /* * The kernel side of a scheduler. Contains the userland config, - * a pipe, pointer to extra config arguments from command line, + * a link, pointer to extra config arguments from command line, * kernel flags, and a pointer to the scheduler methods. * It is stored in a hash table, and holds a list of all * flowsets and scheduler instances. @@ -198,7 +198,7 @@ struct new_queue { struct new_schk { struct new_sch sch; struct dn_sched *fp; /* Pointer to scheduler functions */ - struct new_pipe pipe; /* the pipe is embedded */ + struct dn_link link; /* the link is embedded */ struct new_profile *profile; struct dn_id *cfg; /* extra config arguments */ @@ -225,7 +225,7 @@ struct new_sch_inst { int kflags; /* DN_ACTIVE */ int64_t credit; /* bits I can transmit (more or less). */ - uint64_t sched_time; /* time pipe was scheduled in ready_heap */ + uint64_t sched_time; /* time link was scheduled in ready_heap */ uint64_t idle_time; /* start of scheduler instance idle time */ }; Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Thu Jan 21 13:15:14 2010 (r202747) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Thu Jan 21 13:21:06 2010 (r202748) @@ -495,7 +495,7 @@ static int si_reset_credit(void *_si, void *arg) { struct new_sch_inst *si = _si; - struct new_pipe *p = &si->sched->pipe; + struct dn_link *p = &si->sched->link; si->credit = p->burst + (dn_cfg.io_fast ? p->bandwidth : 0); return 0; @@ -670,9 +670,9 @@ schk_new(uintptr_t key, int flags, void s = malloc(l, M_DUMMYNET, M_NOWAIT | M_ZERO); if (s == NULL) return NULL; - set_oid(&s->pipe.oid, DN_PIPE, sizeof(s->pipe)); + set_oid(&s->link.oid, DN_LINK, sizeof(s->link)); s->sch = *a->sch; // copy initial values - s->pipe.pipe_nr = s->sch.sched_nr; + s->link.link_nr = s->sch.sched_nr; SLIST_INIT(&s->fsk_list); /* initialize the hash table or create the single instance */ s->fp = a->fp; /* si_new needs this */ @@ -813,16 +813,16 @@ copy_data_helper(void *_o, void *_arg) { struct copy_args *a = _arg; - if (a->type == DN_PIPE || /* pipe show */ + if (a->type == DN_LINK || /* pipe show */ a->type == DN_SCH) { /* sched show */ struct new_schk *s = _o; /* we get only schedulers */ if (a->type == DN_SCH && s->sch.sched_nr >= DN_MAX_ID) return 0; /* not valid scheduler */ - if (a->type == DN_PIPE && s->sch.sched_nr <= DN_MAX_ID) + if (a->type == DN_LINK && 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->link, + "link", s->sch.sched_nr)) return DNHT_SCAN_END; if (copy_flowset(a, s->fs, 0)) return DNHT_SCAN_END; @@ -896,7 +896,7 @@ update_fs(struct new_schk *s) /* * Configuration -- to preserve backward compatibility we use * the following scheme (N is 65536) - * NUMBER SCHED PIPE FLOWSET + * NUMBER SCHED LINK FLOWSET * 1 .. N-1 (1)WFQ (2)WFQ (3)queue * N+1 .. 2N-1 (4)FIFO (5)FIFO (6)FIFO for sched 1..N-1 * 2N+1 .. 3N-1 -- -- (7)FIFO for sched N+1..2N-1 @@ -916,10 +916,10 @@ update_fs(struct new_schk *s) */ /* - * configure a pipe (and its FIFO instance) + * configure a link (and its FIFO instance) */ static int -config_pipe(struct new_pipe *p, struct dn_id *arg) +config_link(struct dn_link *p, struct dn_id *arg) { int i; @@ -927,7 +927,7 @@ config_pipe(struct new_pipe *p, struct d D("invalid pipe len %d", p->oid.len); return EINVAL; } - i = p->pipe_nr; + i = p->link_nr; if (i <= 0 || i >= DN_MAX_ID) return EINVAL; /* @@ -942,7 +942,7 @@ config_pipe(struct new_pipe *p, struct d p->burst *= 8 * hz; DN_BH_WLOCK(); - /* do it twice, base pipe and FIFO pipe */ + /* do it twice, base link and FIFO link */ for (; i < 2*DN_MAX_ID; i += DN_MAX_ID) { struct new_schk *s = locate_scheduler(i); if (s == NULL) { @@ -951,11 +951,11 @@ config_pipe(struct new_pipe *p, struct d return EINVAL; } /* copy all parameters */ - s->pipe.oid = p->oid; - s->pipe.pipe_nr = i; - s->pipe.delay = p->delay; - s->pipe.bandwidth = p->bandwidth; - s->pipe.burst = p->burst; + s->link.oid = p->oid; + s->link.link_nr = i; + s->link.delay = p->delay; + s->link.bandwidth = p->bandwidth; + s->link.burst = p->burst; schk_reset_credit(s); } dn_cfg.id++; @@ -982,13 +982,11 @@ config_fs(struct new_fs *nfs, struct dn_ ND("flowset %d", i); /* XXX other sanity checks */ if (nfs->flags & DN_QSIZE_BYTES) { - if (nfs->qsize > dn_cfg.pipe_byte_limit) - nfs->qsize = dn_cfg.pipe_byte_limit; + bound_var(&nfs->qsize, 16384, + 1500, dn_cfg.byte_limit, "queue byte size"); } else { - if (nfs->qsize == 0) - nfs->qsize = 50; - if (nfs->qsize > dn_cfg.pipe_slot_limit) - nfs->qsize = dn_cfg.pipe_slot_limit; + bound_var(&nfs->qsize, 50, + 1, dn_cfg.slot_limit, "queue slot size"); } if (nfs->flags & DN_HAVE_MASK) { /* make sure we have some buckets */ @@ -1046,7 +1044,7 @@ config_fs(struct new_fs *nfs, struct dn_ * For !MULTIQUEUE schedulers, also set up the flowset. * * On reconfigurations (detected because s->fp is set), - * detach existing flowsets preserving traffic, preserve pipe, + * detach existing flowsets preserving traffic, preserve link, * and delete the old scheduler creating a new one. */ static int @@ -1055,7 +1053,7 @@ config_sched(struct new_sch *_nsch, stru struct new_schk *s; struct schk_new_arg a; /* argument for schk_new */ int i; - struct new_pipe p; /* copy of oldpipe */ + struct dn_link p; /* copy of oldlink */ a.sch = _nsch; if (a.sch->oid.len != sizeof(*a.sch)) { @@ -1106,10 +1104,10 @@ again: /* run twice, for wfq and fifo */ D("cannot allocate scheduler %d", i); return ENOMEM; } - /* restore existing pipe if any */ - if (p.pipe_nr) - s->pipe = p; - p.pipe_nr = 0; + /* restore existing link if any */ + if (p.link_nr) + s->link = p; + p.link_nr = 0; if (s->fp == NULL) { D("sched %d new type %s", i, a.fp->name); } else if (s->fp != a.fp || @@ -1120,9 +1118,9 @@ again: /* run twice, for wfq and fifo */ 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) - D("XXX WARNING pipe 0 for sched %d", i); - p = s->pipe; /* preserve pipe */ + if (s->link.link_nr == 0) + D("XXX WARNING link 0 for sched %d", i); + p = s->link; /* preserve link */ /* remove from the hash */ dn_ht_find(dn_cfg.schedhash, i, DNHT_REMOVE, NULL); /* Detach flowsets, preserve queues. */ @@ -1174,7 +1172,7 @@ again: /* run twice, for wfq and fifo */ } /* - * attach a profile to a pipe + * attach a profile to a link */ static int config_profile(struct new_profile *pf, struct dn_id *arg) @@ -1186,7 +1184,7 @@ config_profile(struct new_profile *pf, s D("short profile len %d", pf->oid.len); return EINVAL; } - i = pf->pipe_nr; + i = pf->link_nr; if (i <= 0 || i >= DN_MAX_ID) return EINVAL; /* XXX other sanity checks */ @@ -1240,7 +1238,7 @@ static void dummynet_flush(void) { - /* delete all schedulers and related pipes/queues/flowsets */ + /* delete all schedulers and related links/queues/flowsets */ dn_ht_scan(dn_cfg.schedhash, schk_delete_cb, (void *)(uintptr_t)DN_DELETE_FS); /* delete all remaining (unlinked) flowsets */ @@ -1255,7 +1253,7 @@ dummynet_flush(void) * Main handler for configuration. We are guaranteed to be called * with an oid which is at least a dn_id. * - the first object is the command (config, delete, flush, ...) - * - config_pipe must be issued after the corresponding config_sched + * - config_link must be issued after the corresponding config_sched * - parameters (DN_TXT) for an object must preceed the object * processed on a config_sched. */ @@ -1293,7 +1291,7 @@ do_config(void *p, int l) case DN_CMD_DELETE: switch (o->subtype) { - case DN_PIPE: + case DN_LINK: /* delete base and derived schedulers */ DN_BH_WLOCK(); err = delete_schk(o->id); @@ -1325,8 +1323,8 @@ do_config(void *p, int l) prev = NULL; arg = o; break; - case DN_PIPE: - err = config_pipe((struct new_pipe *)o, arg); + case DN_LINK: + err = config_link((struct dn_link *)o, arg); break; case DN_PROFILE: err = config_profile((struct new_profile *)o, arg); @@ -1354,7 +1352,7 @@ compute_space(struct dn_id *cmd, int *to switch (cmd->subtype) { default: return -1; - case DN_PIPE: /* pipe show */ + case DN_LINK: /* pipe show */ x = DN_C_PIPE | DN_C_FS | DN_SCH | DN_C_SCH_INST; break; case DN_SCH: /* sched show */ @@ -1370,7 +1368,7 @@ compute_space(struct dn_id *cmd, int *to if (x & DN_C_FS) need += dn_cfg.fsk_count * sizeof(struct new_fs); if (x & DN_C_PIPE) - need += dn_cfg.schk_count * sizeof(struct new_pipe); + 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); @@ -1422,10 +1420,10 @@ dummynet_get(struct sockopt *sopt) } if (start == NULL) return sooptcopyout(sopt, &cmd, sizeof(cmd)); - ND("have %d:%d sched %d, %d:%d pipes %d, %d:%d flows %d, " + ND("have %d:%d sched %d, %d:%d links %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.schk_count, sizeof(struct dn_link), DN_LINK, 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); From owner-svn-src-user@FreeBSD.ORG Thu Jan 21 13:31:41 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 6D08B1065672; Thu, 21 Jan 2010 13:31:41 +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 5BD058FC12; Thu, 21 Jan 2010 13:31:41 +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 o0LDVf1Q040526; Thu, 21 Jan 2010 13:31:41 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0LDVf1l040518; Thu, 21 Jan 2010 13:31:41 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <201001211331.o0LDVf1l040518@svn.freebsd.org> From: Luigi Rizzo Date: Thu, 21 Jan 2010 13:31:41 +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: r202749 - 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 13:31:41 -0000 Author: luigi Date: Thu Jan 21 13:31:41 2010 New Revision: 202749 URL: http://svn.freebsd.org/changeset/base/202749 Log: more renaming of objects -- new_inst becomes dn_flow. 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/dummynet.txt 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 user/luigi/ipfw3-head/sys/netinet/ipfw/test_dn_sched.c Modified: user/luigi/ipfw3-head/sbin/ipfw/dummynet.c ============================================================================== --- user/luigi/ipfw3-head/sbin/ipfw/dummynet.c Thu Jan 21 13:21:06 2010 (r202748) +++ user/luigi/ipfw3-head/sbin/ipfw/dummynet.c Thu Jan 21 13:31:41 2010 (r202749) @@ -170,7 +170,7 @@ print_mask(struct ipfw_flow_id *id) } static void -list_queue(struct new_inst *ni) +list_flow(struct dn_flow *ni) { char buff[255]; struct protoent *pe; @@ -307,8 +307,8 @@ list_pipes(struct dn_id *oid, struct dn_ } break; - case DN_NI: - list_queue((struct new_inst *)oid); + case DN_FLOW: + list_flow((struct dn_flow *)oid); break; case DN_LINK: { Modified: user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h Thu Jan 21 13:21:06 2010 (r202748) +++ user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h Thu Jan 21 13:31:41 2010 (r202749) @@ -70,7 +70,7 @@ enum { DN_QUEUE, DN_DELAY_LINE, DN_PROFILE, - DN_NI, /* struct new_inst */ + DN_FLOW, /* struct dn_flow */ //DN_FS_EXT, //DN_QUEUE_EXT, DN_TEXT, /* opaque text is the object */ @@ -137,12 +137,12 @@ struct new_fs { }; /* - * new_inst collects flow_id and stats for queues and scheduler + * dn_flow collects flow_id and stats for queues and scheduler * instances, and is used to pass these info to userland. * oid.type/oid.subtype describe the object, oid.id is number * of the parent object. */ -struct new_inst { +struct dn_flow { struct dn_id oid; struct ipfw_flow_id fid; uint32_t length; /* Queue lenght, in packets */ @@ -221,13 +221,16 @@ and transmits on a private instance of a A PIPE is a simplified version of the above, where there is no flow_mask, and each scheduler instance handles a single queue. -There are three data structures definining a pipe and associated queues: +The following data structures (visible from userland) describe +the objects used by dummynet: - + dn_link, which contains the main configuration parameters related + + dn_link, contains the main configuration parameters related to delay and bandwidth; - + dn_flowset, which contains flow masks, weights and queue - parameters; - + dn_flow, which contains the queue status (flow id, statistics) + + dn_profile describes a delay profile; + + dn_flow describes the flow status (flow id, statistics) + + + new_sch describes a scheduler + + new_fs describes a flowset (msk, weight, queue parameters) * */ Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dummynet.txt ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dummynet.txt Thu Jan 21 13:21:06 2010 (r202748) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dummynet.txt Thu Jan 21 13:31:41 2010 (r202749) @@ -73,7 +73,7 @@ NOTE: for up-to-date details please look USERLAND-KERNEL API (ip_dummynet.h) - struct new_pipe: + struct dn_link: contains data about the physical link such as bandwith, delay, burst size; @@ -125,7 +125,7 @@ KERNEL REPRESENTATION (ip_dn_private.h) sweeps the hash table of instances deleting them struct new_schk - includes new_sch, new_pipe, a pointer to new_profile, + includes new_sch, dn_link, a pointer to new_profile, a hash table of new_sch_inst, a list of new_fsk attached to it. CREATE: configuration command. If there are flowsets that @@ -138,7 +138,7 @@ KERNEL REPRESENTATION (ip_dn_private.h) +---------------+ sched +--------------+ | sched-------------------->| NEW_SCHK| -<----*sch_chain |<-----------------*fsk_list | - |NEW_FSK |<----. | [new_pipe] | + |NEW_FSK |<----. | [dn_link] | +---------------+ | +--------------+ |qht (hash) | | | siht(hash) | | [new_queue] | | | [new_si] | @@ -297,7 +297,7 @@ To create a pipe, queue or scheduler, th The userland side of dummynet will prepare a buffer contains data to pass to kernel side. The buffer contains all struct needed to configure an object. In more detail, -to configure a pipe all three structs (new_pipe, new_sch, new_fs) are needed, +to configure a pipe all three structs (dn_link, new_sch, new_fs) are needed, plus the delay profile struct if the pipe has a delay profile. If configuring a scheduler only the struct new_sch is wrote in the buffer, @@ -361,7 +361,7 @@ The kernel side of dummynet send a buffe pipe, all scheduler, all flowset, plus all scheduler instances and all queues. The dummynet user land will format the output and show only the relevant information. -The buffer sent start with all pipe from the system. The entire struct new_pipe +The buffer sent start with all pipe from the system. The entire struct dn_link is passed, except the delay_profile struct that is useless in user space. After pipes, all flowset are wrote in the buffer. The struct contains scheduler flowset specific data is linked with the flowset writing the @@ -492,7 +492,7 @@ There are four request for old dummynet: - IP_DUMMYNET_CONFIGURE: the configure command receive a buffer depending of the ipfw version. After the properly extraction of all data, that depends by the ipfw version used, new structures are filled and then the dummynet - config_pipe() function is properly called. Note that the 7.2 version does + config_link() function is properly called. Note that the 7.2 version does not support some parameter as burst or delay profile. - IP_DUMMYNET_GET: The get command should send to the ipfw the correct buffer depending of its version. There are two function that build the 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 13:21:06 2010 (r202748) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c Thu Jan 21 13:31:41 2010 (r202749) @@ -231,7 +231,7 @@ int dn_enqueue(struct new_queue *q, struct mbuf* m, int drop) { struct new_fs *f; - struct new_inst *ni; /* stats for scheduler instance */ + struct dn_flow *ni; /* stats for scheduler instance */ uint64_t len; if (q->fs == NULL || q->_si == NULL) { 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 13:21:06 2010 (r202748) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h Thu Jan 21 13:31:41 2010 (r202749) @@ -179,7 +179,7 @@ struct new_fsk { /* kernel side of a flo * should not enqueue. */ struct new_queue { - struct new_inst ni; /* oid, flow_id, stats */ + 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 */ @@ -218,7 +218,7 @@ struct new_schk { * This struct is created a runtime. */ struct new_sch_inst { - struct new_inst ni; /* oid, id and stats */ + struct dn_flow ni; /* oid, id and stats */ SLIST_ENTRY(new_sch_inst) si_next; /* next item in the bucket */ struct delay_line dline; struct new_schk *sched; /* the template */ Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Thu Jan 21 13:21:06 2010 (r202748) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Thu Jan 21 13:31:41 2010 (r202749) @@ -418,7 +418,7 @@ si_new(uintptr_t key, int flags, void *a if (si == NULL) 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->ni.oid, DN_SCH_I, sizeof(struct dn_flow)); set_oid(&(si->dline.oid), DN_DELAY_LINE, sizeof(struct delay_line)); /* mark si and dline as outside the event queue */ @@ -790,11 +790,11 @@ 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); + struct dn_flow *ni = (struct dn_flow *)(*a->start); if (copy_obj(a->start, a->end, &si->ni, "inst", si->sched->sch.sched_nr)) return DNHT_SCAN_END; - ni->oid.type = DN_NI; + ni->oid.type = DN_FLOW; /* override the DN_SCH_I */ return 0; } @@ -1373,7 +1373,7 @@ compute_space(struct dn_id *cmd, int *to if (x & DN_C_QUEUE) need += dn_cfg.queue_count * sizeof(struct new_queue); if (x & DN_C_SCH_INST) - need += dn_cfg.si_count * sizeof(struct new_inst); + need += dn_cfg.si_count * sizeof(struct dn_flow); return need; } @@ -1420,12 +1420,12 @@ dummynet_get(struct sockopt *sopt) } if (start == NULL) return sooptcopyout(sopt, &cmd, sizeof(cmd)); - ND("have %d:%d sched %d, %d:%d links %d, %d:%d flows %d, " + ND("have %d:%d sched %d, %d:%d links %d, %d:%d flowsets %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 dn_link), DN_LINK, dn_cfg.fsk_count, sizeof(struct new_fs), DN_FS, - dn_cfg.si_count, sizeof(struct new_inst), DN_SCH_I, + dn_cfg.si_count, sizeof(struct dn_flow), DN_SCH_I, dn_cfg.queue_count, sizeof(struct new_queue), DN_QUEUE); sopt->sopt_valsize = sopt_valsize; bcopy(&cmd, start, sizeof(cmd)); Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/test_dn_sched.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/test_dn_sched.c Thu Jan 21 13:21:06 2010 (r202748) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/test_dn_sched.c Thu Jan 21 13:31:41 2010 (r202749) @@ -63,7 +63,7 @@ int dn_enqueue(struct new_queue *q, struct mbuf* m, int drop) { struct new_fs *f; - struct new_inst *ni; /* stats for scheduler instance */ + struct dn_flow *ni; /* stats for scheduler instance */ uint64_t len; f = &q->fs->fs; From owner-svn-src-user@FreeBSD.ORG Thu Jan 21 17:34:02 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 24FFE106566B; Thu, 21 Jan 2010 17:34:02 +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 128958FC08; Thu, 21 Jan 2010 17:34:02 +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 o0LHY1St095937; Thu, 21 Jan 2010 17:34:01 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0LHY1kg095927; Thu, 21 Jan 2010 17:34:01 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <201001211734.o0LHY1kg095927@svn.freebsd.org> From: Luigi Rizzo Date: Thu, 21 Jan 2010 17:34: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: r202758 - 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 17:34:02 -0000 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 __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 #include @@ -64,15 +64,15 @@ __FBSDID("$FreeBSD$"); #include /* 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); From owner-svn-src-user@FreeBSD.ORG Fri Jan 22 07:22:46 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 988321065670; Fri, 22 Jan 2010 07:22:46 +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 6DED58FC13; Fri, 22 Jan 2010 07:22:46 +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 o0M7MkHf085946; Fri, 22 Jan 2010 07:22:46 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0M7MkQP085944; Fri, 22 Jan 2010 07:22:46 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <201001220722.o0M7MkQP085944@svn.freebsd.org> From: Luigi Rizzo Date: Fri, 22 Jan 2010 07:22:46 +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: r202781 - 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: Fri, 22 Jan 2010 07:22:46 -0000 Author: luigi Date: Fri Jan 22 07:22:46 2010 New Revision: 202781 URL: http://svn.freebsd.org/changeset/base/202781 Log: indentation and documentation fixes 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 Fri Jan 22 05:19:51 2010 (r202780) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Fri Jan 22 07:22:46 2010 (r202781) @@ -114,11 +114,11 @@ bound_var(int *v, int dflt, int lo, int if (*v < lo) { *v = dflt; if (msg) - printf("default %s to %d\n", msg, *v); + printf("default %s to %d\n", msg, *v); } else if (*v > hi) { *v = hi; if (msg) - printf("clamp %s to %d\n", msg, *v); + printf("clamp %s to %d\n", msg, *v); } return *v; } @@ -345,8 +345,8 @@ 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). + * Find and possibly create the queue for a MULTIQUEUE scheduler. + * We never call it for !MULTIQUEUE (the queue is in the sch_inst). */ struct new_queue * ipdn_q_find(struct new_fsk *fs, struct new_sch_inst *si, @@ -610,7 +610,6 @@ fsk_detach_list(struct new_fsk_head *h, /* * called on 'queue X delete' -- removes the flowset from fshash, * deletes all queues for the flowset, and removes the flowset. - * XXX note that fsk_detach_list also destroys a flowset. */ static int delete_fs(int i, int locked) @@ -807,7 +806,8 @@ copy_flowset(struct copy_args *a, struct 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 ? */ + ufs->oid.id = (fs->fs.flags & DN_HAVE_MASK) ? + dn_ht_entries(fs->_qht) : (fs->_qht ? 1 : 0); if (flags) { /* copy queues */ copy_q(a, fs, 0); } @@ -850,6 +850,7 @@ copy_fsk_list(struct copy_args *a, struc if (fs->fs.fs_nr < DN_MAX_ID) n++;; } + /* XXX beware the alignment */ space += 2*n; D("sched %d has %d flowsets", s->sch.sched_nr, n); if (a->end - *(a->start) < space) @@ -1078,6 +1079,7 @@ config_fs(struct new_fs *nfs, struct dn_ /* detach from old scheduler if needed, preserving * queues if we need to reattach. Then update the * configuration, and possibly attach to the new sched. + * XXX should print more on why the config has changed. */ D("fs %d changed sched %d@%p to %d@%p", fs->fs.fs_nr, @@ -1426,8 +1428,12 @@ compute_space(struct dn_id *cmd, int *to break; } *to_copy = x; - if (x & DN_C_SCH) + if (x & DN_C_SCH) { need += dn_cfg.schk_count * sizeof(struct new_sch); + /* also, each fs might be attached to a sched */ + need += dn_cfg.fsk_count * + (sizeof(struct dn_id) + 4); + } if (x & DN_C_FS) need += dn_cfg.fsk_count * sizeof(struct new_fs); if (x & DN_C_LINK) From owner-svn-src-user@FreeBSD.ORG Fri Jan 22 09:49:08 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 3C1D11065693; Fri, 22 Jan 2010 09:49:08 +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 2A08E8FC0A; Fri, 22 Jan 2010 09:49:08 +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 o0M9n8e5027829; Fri, 22 Jan 2010 09:49:08 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0M9n8mQ027826; Fri, 22 Jan 2010 09:49:08 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <201001220949.o0M9n8mQ027826@svn.freebsd.org> From: Luigi Rizzo Date: Fri, 22 Jan 2010 09:49:08 +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: r202794 - user/luigi/ipfw3-head/sbin/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: Fri, 22 Jan 2010 09:49:08 -0000 Author: luigi Date: Fri Jan 22 09:49:07 2010 New Revision: 202794 URL: http://svn.freebsd.org/changeset/base/202794 Log: build with higher WARNS fix some comments Modified: user/luigi/ipfw3-head/sbin/ipfw/dummynet.c user/luigi/ipfw3-head/sbin/ipfw/ipfw2.c Modified: user/luigi/ipfw3-head/sbin/ipfw/dummynet.c ============================================================================== --- user/luigi/ipfw3-head/sbin/ipfw/dummynet.c Fri Jan 22 09:42:41 2010 (r202793) +++ user/luigi/ipfw3-head/sbin/ipfw/dummynet.c Fri Jan 22 09:49:07 2010 (r202794) @@ -1,10 +1,5 @@ /* - * Copyright (c) 2002-2003 Luigi Rizzo - * Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp - * Copyright (c) 1994 Ugen J.S.Antsilevich - * - * Idea and grammar partially left from: - * Copyright (c) 1993 Daniel Boulet + * Copyright (c) 2002-2003,2010 Luigi Rizzo * * Redistribution and use in source forms, with and without modification, * are permitted provided that this entire comment appears intact. @@ -15,8 +10,6 @@ * * This software is provided ``AS IS'' without any warranties of any kind. * - * NEW command line interface for IP firewall facility - * * $FreeBSD$ * * dummynet support @@ -85,7 +78,7 @@ static struct _s_x dummynet_params[] = { { NULL, 0 } /* terminator */ }; -#define O_NEXT(p, len) ((void *)(char *)(p) + len) +#define O_NEXT(p, len) ((void *)((char *)p + len)) static void oid_fill(struct dn_id *oid, int len, int type, uintptr_t id) @@ -140,6 +133,7 @@ sort_q(void *arg, const void *pa, const } #endif +/* print a mask and header for the subsequent list of flows */ static void print_mask(struct ipfw_flow_id *id) { @@ -286,10 +280,9 @@ flush_buf(char *buf) * FLOWSETS: * flowset; queues; * link i (int queue); scheduler i; si(i) { flowsets() : queues } - * 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) +list_pipes(struct dn_id *oid, struct dn_id *end) { char buf[160]; /* pending buffer */ buf[0] = '\0'; @@ -405,15 +398,15 @@ list_pipes(struct dn_id *oid, struct dn_ * Delete pipe, queue or scheduler i */ int -ipfw_delete_pipe(int pipe_or_queue, int i) +ipfw_delete_pipe(int do_pipe, int i) { struct { struct dn_id oid; - uint32_t a[1]; /* add more if we want a list */ + uintptr_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 : - ( (co.do_pipe == 2) ? DN_FS : DN_SCH); + cmd.oid.subtype = (do_pipe == 1) ? DN_LINK : + ( (do_pipe == 2) ? DN_FS : DN_SCH); cmd.a[0] = i; i = do_cmd(IP_DUMMYNET3, &cmd, cmd.oid.len); if (i) { @@ -733,17 +726,17 @@ load_extra_delays(const char *filename, double y2 = points[i+1].prob * samples; double x2 = points[i+1].delay; - int index = y1; + int ix = y1; int stop = y2; if (x1 == x2) { - for (; indexsamples[index] = x1; + for (; ixsamples[ix] = x1; } else { double m = (y2-y1)/(x2-x1); double c = y1 - m*x1; - for (; indexsamples[index] = (index - c)/m; + for (; ixsamples[ix] = (ix - c)/m; } } p->samples_no = samples; @@ -1255,15 +1248,17 @@ dummynet_flush(void) do_cmd(IP_DUMMYNET3, &oid, oid.len); } +/* main entry point for dummynet list functions. co.do_pipe indicates + * which function we want to support. + * XXX todo- accept filtering arguments. + */ void -dummynet_list(int ac, char *av[], int show_counters) +dummynet_list(int __unused ac, __unused char *av[], int __unused show_counters) { struct dn_id oid, *x; int ret, l = sizeof(oid); - oid.type = DN_CMD_GET; - oid.len = l; - oid.id = DN_API_VERSION; + oid_fill(&oid, l, DN_CMD_GET, DN_API_VERSION); switch (co.do_pipe) { case 1: oid.subtype = DN_LINK; /* list pipe */ @@ -1280,12 +1275,11 @@ dummynet_list(int ac, char *av[], int sh 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 = safe_calloc(1, l); *x = oid; ret = do_cmd(-IP_DUMMYNET3, x, (uintptr_t)&l); // printf("%s returns %d need %d\n", __FUNCTION__, ret, oid.id); - list_pipes(x, O_NEXT(x, l), NULL); + // XXX filter on ac, av + list_pipes(x, O_NEXT(x, l)); free(x); } Modified: user/luigi/ipfw3-head/sbin/ipfw/ipfw2.c ============================================================================== --- user/luigi/ipfw3-head/sbin/ipfw/ipfw2.c Fri Jan 22 09:42:41 2010 (r202793) +++ user/luigi/ipfw3-head/sbin/ipfw/ipfw2.c Fri Jan 22 09:49:07 2010 (r202794) @@ -65,23 +65,23 @@ int resvd_set_number = RESVD_SET; } \ \ { \ - long val; \ + long _xval; \ char *end; \ \ - val = strtol(*av, &end, 10); \ + _xval = strtol(*av, &end, 10); \ \ - if (!isdigit(**av) || *end != '\0' || (val == 0 && errno == EINVAL)) \ + if (!isdigit(**av) || *end != '\0' || (_xval == 0 && errno == EINVAL)) \ errx(EX_DATAERR, "%s: invalid argument: %s", \ match_value(s_x, tok), *av); \ \ - if (errno == ERANGE || val < min || val > max) \ + if (errno == ERANGE || _xval < min || _xval > max) \ errx(EX_DATAERR, "%s: argument is out of range (%u..%u): %s", \ match_value(s_x, tok), min, max, *av); \ \ - if (val == IP_FW_TABLEARG) \ + if (_xval == IP_FW_TABLEARG) \ errx(EX_DATAERR, "%s: illegal argument value: %s", \ match_value(s_x, tok), *av); \ - arg = val; \ + arg = _xval; \ } \ } while (0) @@ -754,7 +754,7 @@ static void print_ip(ipfw_insn_ip *cmd, char const *s) { struct hostent *he = NULL; - int len = F_LEN((ipfw_insn *)cmd); + uint32_t len = F_LEN((ipfw_insn *)cmd); uint32_t *a = ((ipfw_insn_u32 *)cmd)->d; if (cmd->o.opcode == O_IP_DST_LOOKUP && len > F_INSN_SIZE(ipfw_insn_u32)) { @@ -2134,7 +2134,7 @@ fill_ip(ipfw_insn_ip *cmd, char *av) return; } /* A single IP can be stored in an optimized format */ - if (d[1] == ~0 && av == NULL && len == 0) { + if (d[1] == (uint32_t)~0 && av == NULL && len == 0) { cmd->o.len |= F_INSN_SIZE(ipfw_insn_u32); return; } @@ -2279,7 +2279,8 @@ fill_iface(ipfw_insn_if *cmd, char *arg) static void get_mac_addr_mask(const char *p, uint8_t *addr, uint8_t *mask) { - int i, l; + int i; + size_t l; char *ap, *ptr, *optr; struct ether_addr *mac; const char *macset = "0123456789abcdefABCDEF:"; @@ -2301,11 +2302,11 @@ get_mac_addr_mask(const char *p, uint8_t if (ptr != NULL) { /* we have mask? */ if (p[ptr - optr - 1] == '/') { /* mask len */ - l = strtol(ptr, &ap, 10); - if (*ap != 0 || l > ETHER_ADDR_LEN * 8 || l < 0) + long ml = strtol(ptr, &ap, 10); + if (*ap != 0 || ml > ETHER_ADDR_LEN * 8 || ml < 0) errx(EX_DATAERR, "Incorrect mask length"); - for (i = 0; l > 0 && i < ETHER_ADDR_LEN; l -= 8, i++) - mask[i] = (l >= 8) ? 0xff: (~0) << (8 - l); + for (i = 0; ml > 0 && i < ETHER_ADDR_LEN; ml -= 8, i++) + mask[i] = (ml >= 8) ? 0xff: (~0) << (8 - ml); } else { /* mask */ l = strlen(ptr); if (strspn(ptr, macset) != l || @@ -3819,14 +3820,14 @@ ipfw_table_handler(int ac, char *av[]) } } } else if (_substrcmp(*av, "flush") == 0) { - a = is_all ? tables_max : (ent.tbl + 1); + a = is_all ? tables_max : (uint32_t)(ent.tbl + 1); do { if (do_cmd(IP_FW_TABLE_FLUSH, &ent.tbl, sizeof(ent.tbl)) < 0) err(EX_OSERR, "setsockopt(IP_FW_TABLE_FLUSH)"); } while (++ent.tbl < a); } else if (_substrcmp(*av, "list") == 0) { - a = is_all ? tables_max : (ent.tbl + 1); + a = is_all ? tables_max : (uint32_t)(ent.tbl + 1); do { table_list(ent, is_all); } while (++ent.tbl < a); From owner-svn-src-user@FreeBSD.ORG Fri Jan 22 09:50:18 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 15DFB106566B; Fri, 22 Jan 2010 09:50:18 +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 04C7C8FC19; Fri, 22 Jan 2010 09:50:18 +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 o0M9oHZm028129; Fri, 22 Jan 2010 09:50:17 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0M9oHrG028127; Fri, 22 Jan 2010 09:50:17 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <201001220950.o0M9oHrG028127@svn.freebsd.org> From: Luigi Rizzo Date: Fri, 22 Jan 2010 09:50:17 +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: r202795 - 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: Fri, 22 Jan 2010 09:50:18 -0000 Author: luigi Date: Fri Jan 22 09:50:17 2010 New Revision: 202795 URL: http://svn.freebsd.org/changeset/base/202795 Log: use uintptr_t for list of objects (helps with alignment, though a bit of a waste of space) 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 Fri Jan 22 09:49:07 2010 (r202794) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Fri Jan 22 09:50:17 2010 (r202795) @@ -848,10 +848,9 @@ copy_fsk_list(struct copy_args *a, struc int n = 0, space = sizeof(*o); SLIST_FOREACH(fs, &s->fsk_list, sch_chain) { if (fs->fs.fs_nr < DN_MAX_ID) - n++;; + n++; } - /* XXX beware the alignment */ - space += 2*n; + space += n * sizeof(uintptr_t); D("sched %d has %d flowsets", s->sch.sched_nr, n); if (a->end - *(a->start) < space) return DNHT_SCAN_END; @@ -1322,7 +1321,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; + uintptr_t *a; o = p; if (o->id != DN_API_VERSION) { @@ -1349,8 +1348,8 @@ do_config(void *p, int l) break; case DN_CMD_DELETE: - /* the argument is in the first uint32 after o */ - a = (uint32_t *)(o+1); + /* the argument is in the first uintptr_t after o */ + a = (uintptr_t *)(o+1); if (o->len < sizeof(*o) + sizeof(*a)) { err = EINVAL; break; From owner-svn-src-user@FreeBSD.ORG Fri Jan 22 16:23: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 0D7B410656C2; Fri, 22 Jan 2010 16:23: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 EFD898FC13; Fri, 22 Jan 2010 16:23:00 +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 o0MGN0tI021621; Fri, 22 Jan 2010 16:23:00 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0MGN0vv021613; Fri, 22 Jan 2010 16:23:00 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <201001221623.o0MGN0vv021613@svn.freebsd.org> From: Luigi Rizzo Date: Fri, 22 Jan 2010 16:23:00 +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: r202813 - 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: Fri, 22 Jan 2010 16:23:01 -0000 Author: luigi Date: Fri Jan 22 16:23:00 2010 New Revision: 202813 URL: http://svn.freebsd.org/changeset/base/202813 Log: GENERAL: - rename flowset parameters to 'par[]'; the kernel does not need to know what they represent, only the schedulers and the user interface (perhaps); - use -1 as default value for these parameters so we can preserve the existing values on new commands; - export ipdn_bound_var() as there are many places where we use them; DN_SCHED_RR: - use a circular queue to store flows (to be tested); 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/dn_sched_rr.c user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.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 Fri Jan 22 16:05:10 2010 (r202812) +++ user/luigi/ipfw3-head/sbin/ipfw/dummynet.c Fri Jan 22 16:23:00 2010 (r202813) @@ -242,9 +242,9 @@ print_flowset_parms(struct new_fs *fs, c 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", + printf("q%05d %s%s %d flows (%d buckets) %s sched %d weight %d\n", fs->fs_nr, qs, plr, fs->oid.id, fs->buckets, red, - fs->sched_nr); + fs->sched_nr, fs->par[0]); if (fs->flags & DN_HAVE_MASK) print_mask(&fs->flow_mask); } @@ -388,7 +388,7 @@ list_pipes(struct dn_id *oid, struct dn_ q = (struct dn_flow_queue *)(fs+1); sprintf(prefix, "q%05d: weight %d sched %d ", - fs->fs_nr, fs->weight, fs->parent_nr); + fs->fs_nr, fs->par[0], fs->parent_nr); print_flowset_parms(fs, prefix); list_queues(fs, q); } @@ -766,7 +766,7 @@ load_extra_delays(const char *filename, void ipfw_config_pipe(int ac, char **av) { - int i = -1; + int i, j; char *end; void *par = NULL; struct dn_id *buf, *base; @@ -790,13 +790,11 @@ ipfw_config_pipe(int ac, char **av) /* Pipe number */ if (ac && isdigit(**av)) { i = atoi(*av); av++; ac--; - } + } else + i = -1; if (i <= 0) errx(EX_USAGE, "need a pipe/flowset/sched number"); - base = buf = calloc(1, lmax); - if (buf == NULL) { - errx(1, "no memory for buffer"); - } + base = buf = safe_calloc(1, lmax); /* all commands start with a 'CONFIGURE' and a version */ o_next(&buf, sizeof(struct dn_id), DN_CMD_CONFIG); base->id = DN_API_VERSION; @@ -847,9 +845,15 @@ ipfw_config_pipe(int ac, char **av) fs->sched_nr = i; break; } + /* set to -1 those fields for which we want to reuse existing + * values from the kernel. + * Also, *_nr and subtype = 0 mean reuse the value from the kernel. + * XXX todo: support reuse of the mask. + */ if (p) p->bandwidth = -1; - + for (j = 0; j < sizeof(fs->par)/sizeof(fs->par[0]); j++) + fs->par[j] = -1; while (ac > 0) { double d; int tok = match_token(dummynet_params, *av); @@ -1084,7 +1088,7 @@ end_mask: case TOK_WEIGHT: NEED(fs, "weight is only for flowsets"); NEED1("weight needs argument 0..100\n"); - fs->weight = strtoul(av[0], &end, 0); + fs->par[0] = strtol(av[0], &end, 0); ac--; av++; break; Modified: user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h Fri Jan 22 16:05:10 2010 (r202812) +++ user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h Fri Jan 22 16:23:00 2010 (r202813) @@ -129,10 +129,8 @@ struct new_fs { struct ipfw_flow_id flow_mask; uint32_t sched_nr; /* the scheduler we attach to */ - /* generic scheduler parameters */ - int weight; - int quantum; - int par[4]; /* other parameters */ + /* generic scheduler parameters. Leave them at -1 if unset */ + int par[4]; }; /* Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h Fri Jan 22 16:05:10 2010 (r202812) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h Fri Jan 22 16:23:00 2010 (r202813) @@ -122,6 +122,8 @@ struct dn_alg { */ void dn_free_pkts(struct mbuf *mnext); int dn_enqueue(struct new_queue *q, struct mbuf* m, int drop); +/* bound a variable between min and max */ +int ipdn_bound_var(int *v, int dflt, int lo, int hi, const char *msg); /* * Extract the head of a queue, update stats. Must be the very last Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_rr.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_rr.c Fri Jan 22 16:05:10 2010 (r202812) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_rr.c Fri Jan 22 16:23:00 2010 (r202813) @@ -41,15 +41,13 @@ #define DN_SCHED_RR 3 // XXX Where? -/* rr_queue is appended to a struct new_queue */ struct rr_queue { - struct new_queue *parent; /* Pointer to standard queue */ + struct new_queue q; /* Standard queue */ int status; /* 1: queue is in the list */ - TAILQ_ENTRY(rr_queue) entries; /* List of active queue */ int credit; /* Number of bytes to transmit */ int quantum; /* quantum * C */ + struct rr_queue *qnext; /* */ }; -TAILQ_HEAD(rr_queue_head, rr_queue); /* struct rr_schk contains global config parameters * and is right after new_schk @@ -60,55 +58,85 @@ struct rr_schk { int q_bytes; /* Bytes per quantum */ }; -/* per-instance info, right after new_sch_inst */ +/* per-instance round robin list, right after new_sch_inst */ struct rr_si { - struct rr_queue *pointer; /* Pointer to current queue */ - struct rr_queue_head q_list; /* List of queues */ - int queue_n; /* number of queues in the list */ + struct rr_queue *head, *tail; /* Pointer to current queue */ }; +/* Append a queue to the rr list */ static inline void -insert_queue(struct rr_queue *q, struct rr_si *si) +rr_append(struct rr_queue *q, struct rr_si *si) { + q->status = 1; /* mark as in-rr_list */ + q->credit = q->quantum; /* initialize credit */ - if (TAILQ_EMPTY(&si->q_list)) { /* or si->queue_n == 0 */ - TAILQ_INSERT_HEAD(&si->q_list, q, entries); - si->pointer = q; - } - else { - TAILQ_INSERT_BEFORE(si->pointer, q, entries); + /* append to the tail */ + if (si->head == NULL) + si->head = q; + else + si->tail->qnext = q; + si->tail = q; /* advance the tail pointer */ + q->qnext = si->head; /* make it circular */ +} + +/* Remove the head queue from circular list. */ +static inline void +rr_remove_head(struct rr_si *si) +{ + if (si->head == NULL) + return; /* empty queue */ + si->head->status = 0; + + if (si->head == si->tail) { + si->head = si->tail = NULL; + return; } - q->status = 1; - si->queue_n++; + + si->head = si->head->qnext; + si->tail->qnext = si->head; } +/* Remove a queue from circular list. + * XXX see if ti can be merge with remove_queue() + */ static inline void -remove_queue(struct rr_queue *q, struct rr_si *si) +remove_queue_q(struct rr_queue *q, struct rr_si *si) { - TAILQ_REMOVE(&si->q_list, q, entries); + struct rr_queue *prev; + + if (q->status != 1) + return; + if (q == si->head) + return rr_remove_head(si); + + prev = si->head; + while (prev) { + if (prev->qnext == q) { + prev->qnext = q->qnext; + if (q == si->tail) + si->tail = prev; q->status = 0; - si->queue_n--; } + prev = prev->qnext; + } +} + -static inline struct rr_queue * +static inline void next_pointer(struct rr_si *si) { - if (si->queue_n == 0) { /* XXX needed? */ - si->pointer = NULL; - return NULL; - } - si->pointer = TAILQ_NEXT(si->pointer, entries); - if (si->pointer == NULL) - si->pointer = TAILQ_FIRST(&si->q_list); + if (si->head == NULL) + return; /* empty queue */ - return si->pointer; + si->head = si->head->qnext; + si->tail = si->tail->qnext; } static int rr_enqueue(struct new_sch_inst *_si, struct new_queue *q, struct mbuf *m) { struct rr_si *si; - struct rr_queue *alg_fq; + struct rr_queue *rrq; if (m != q->mq.head) { if (dn_enqueue(q, m, 0)) /* packet was dropped */ @@ -119,13 +147,13 @@ rr_enqueue(struct new_sch_inst *_si, str /* If reach this point, queue q was idle */ si = (struct rr_si *)(_si + 1); - alg_fq = (struct rr_queue *)(q+1); + rrq = (struct rr_queue *)q; - if (alg_fq->status == 1) /* Queue is already in the queue list */ + if (rrq->status == 1) /* Queue is already in the queue list */ return 0; /* Insert the queue in the queue list */ - insert_queue(alg_fq, si); + rr_append(rrq, si); return 0; } @@ -135,34 +163,26 @@ rr_dequeue(struct new_sch_inst *_si) { /* Access scheduler instance private data */ struct rr_si *si = (struct rr_si *)(_si + 1); - struct mbuf *pkt; - struct rr_queue *q; - struct new_queue *_q; + struct rr_queue *rrq; uint64_t len; - if (si->queue_n == 0) /* scheduler empty */ - return NULL; - - while (si->queue_n > 0) { - q = si->pointer; - _q = q->parent; - /* or use: _q = ((struct new_queue *)q) - 1; */ - si->pointer = next_pointer(si); - if (_q->mq.head == NULL) { + while ( (rrq = si->head) ) { + struct mbuf *m = rrq->q.mq.head; + if ( m == NULL) { /* empty queue, remove from list */ - remove_queue(q, si); + rr_remove_head(si); continue; } - pkt = _q->mq.head; - len = pkt->m_pkthdr.len; + len = m->m_pkthdr.len; - if (len > q->credit) { + if (len > rrq->credit) { /* Packet too big */ - q->credit += q->quantum; + rrq->credit += rrq->quantum; /* Try next queue */ + next_pointer(si); } else { - q->credit = q->credit - len + q->quantum; - return dn_dequeue(_q); + rrq->credit -= len; + return dn_dequeue(&rrq->q); } } @@ -189,9 +209,7 @@ rr_new_sched(struct new_sch_inst *_si) struct rr_si *si = (struct rr_si *)(_si + 1); printf("%s called\n", __FUNCTION__); - si->pointer = NULL; - si->queue_n = 0; - TAILQ_INIT(&si->q_list); + si->head = si->tail = NULL; return 0; } @@ -208,31 +226,27 @@ static int rr_new_fsk(struct new_fsk *fs) { struct rr_schk *schk = (struct rr_schk *)(fs->sched + 1); - printf("%s called\n", __FUNCTION__); - if (fs->fs.quantum < schk->min_q) - fs->fs.quantum = schk->min_q; - else if (fs->fs.quantum > schk->max_q) - fs->fs.quantum = schk->max_q; + ipdn_bound_var(&fs->fs.par[0], schk->min_q, + schk->min_q, schk->max_q, "RR quantum"); return 0; } static int rr_new_queue(struct new_queue *_q) { - struct rr_queue *q = (struct rr_queue *)(_q + 1); + struct rr_queue *q = (struct rr_queue *)_q; struct rr_schk *schk = (struct rr_schk *)(_q->_si->sched + 1); printf("%s called, schk->quantum=%d\n", __FUNCTION__, schk->q_bytes); _q->ni.oid.subtype = DN_SCHED_RR; - q->quantum = _q->fs->fs.quantum * schk->q_bytes; + q->quantum = _q->fs->fs.par[0] * schk->q_bytes; q->credit = q->quantum; q->status = 0; - q->parent = _q; if (_q->mq.head != NULL) { /* Queue NOT empty, insert in the queue list */ - insert_queue(q, (struct rr_si *)(_q->_si + 1)); + rr_append(q, (struct rr_si *)(_q->_si + 1)); } return 0; } @@ -240,14 +254,12 @@ rr_new_queue(struct new_queue *_q) static int rr_free_queue(struct new_queue *_q) { - struct rr_queue *q = (struct rr_queue *)(_q + 1); + struct rr_queue *q = (struct rr_queue *)_q; printf("%s called\n", __FUNCTION__); if (q->status == 1) { struct rr_si *si = (struct rr_si *)(_q->_si + 1); - remove_queue(q, si); - if (si->pointer == q) - si->pointer = next_pointer(si); + remove_queue_q(q, si); } return 0; } @@ -263,7 +275,7 @@ static struct dn_alg rr_desc = { .flags = DN_MULTIQUEUE, .si_datalen = sizeof(struct rr_si), - .q_datalen = sizeof(struct rr_queue), + .q_datalen = sizeof(struct rr_queue) - sizeof(struct new_queue), .enqueue = rr_enqueue, .dequeue = rr_dequeue, Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c Fri Jan 22 16:05:10 2010 (r202812) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c Fri Jan 22 16:23:00 2010 (r202813) @@ -96,7 +96,7 @@ idle_check(struct wf2qp_si *si, int n, i * mark it as 'unused' by the scheduler. */ alg_fq->S = alg_fq->F + 1; /* Mark timestamp as invalid. */ - si->sum -= q->fs->fs.weight; /* adjust sum of weights */ + si->sum -= q->fs->fs.par[0]; /* adjust sum of weights */ } } @@ -121,12 +121,12 @@ wf2qp_enqueue(struct new_sch_inst *_si, if (DN_KEY_LT(alg_fq->F, alg_fq->S)) { /* Fbrand new queue. */ alg_fq->S = si->V; /* init start time */ - si->sum += fs->fs.weight; /* add weight of new queue. */ + si->sum += fs->fs.par[0]; /* add weight of new queue. */ } else { /* if it was idle then it was in the idle heap */ heap_extract(&si->idle_heap, q); alg_fq->S = MAX64(alg_fq->F, si->V); /* compute new S */ } - alg_fq->F = alg_fq->S + div64((len << MY_M), fs->fs.weight); + alg_fq->F = alg_fq->S + div64((len << MY_M), fs->fs.par[0]); /* if nothing is backlogged, make sure this flow is eligible */ if (si->ne_heap.elements == 0 && si->sch_heap.elements == 0) @@ -202,7 +202,7 @@ wf2qp_dequeue(struct new_sch_inst *_si) } else { /* Still backlogged. */ /* Update F, store in neh or sch */ uint64_t len = q->mq.head->m_pkthdr.len; - alg_fq->F += div64(len << MY_M, q->fs->fs.weight); + alg_fq->F += div64(len << MY_M, q->fs->fs.par[0]); if (DN_KEY_LEQ(alg_fq->S, si->V)) { heap_insert(sch, alg_fq->F, q); } else { @@ -258,10 +258,8 @@ static int wf2qp_new_fsk(struct new_fsk *fs) { // printf("%s called\n", __FUNCTION__); - if (fs->fs.weight < 1) - fs->fs.weight = 1; - else if (fs->fs.weight > 100) - fs->fs.weight = 100; + ipdn_bound_var(&fs->fs.par[0], 1, + 1, 100, "WF2Q+ weight"); return 0; } @@ -294,7 +292,7 @@ wf2qp_free_queue(struct new_queue *q) printf("%s called\n", __FUNCTION__); if (alg_fq->S >= alg_fq->F + 1) return 0; /* nothing to do, not in any heap */ - si->sum -= q->fs->fs.weight; + si->sum -= q->fs->fs.par[0]; /* extract from the heap. XXX TODO we may need to adjust V * to make sure the invariants hold. Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Fri Jan 22 16:05:10 2010 (r202812) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Fri Jan 22 16:23:00 2010 (r202813) @@ -36,8 +36,8 @@ __FBSDID("$FreeBSD$"); /* debug support */ #define ND(fmt, args...) do {} while (0) -#define D(fmt, args...) printf("%s " fmt "\n", __FUNCTION__ , ## args) - +#define D(fmt, args...) printf("%s %d: " fmt "\n", \ + __FUNCTION__ , __LINE__ , ## args) #include #include @@ -108,8 +108,8 @@ find_sched_type(int type, char *name) return NULL; /* not found */ } -static int -bound_var(int *v, int dflt, int lo, int hi, const char *msg) +int +ipdn_bound_var(int *v, int dflt, int lo, int hi, const char *msg) { if (*v < lo) { *v = dflt; @@ -1044,15 +1044,15 @@ config_fs(struct new_fs *nfs, struct dn_ ND("flowset %d", i); /* XXX other sanity checks */ if (nfs->flags & DN_QSIZE_BYTES) { - bound_var(&nfs->qsize, 16384, - 1500, dn_cfg.byte_limit, "queue byte size"); + ipdn_bound_var(&nfs->qsize, 16384, + 1500, dn_cfg.byte_limit, NULL); // "queue byte size"); } else { - bound_var(&nfs->qsize, 50, - 1, dn_cfg.slot_limit, "queue slot size"); + ipdn_bound_var(&nfs->qsize, 50, + 1, dn_cfg.slot_limit, NULL); // "queue slot size"); } if (nfs->flags & DN_HAVE_MASK) { /* make sure we have some buckets */ - bound_var(&nfs->buckets, dn_cfg.hash_size, + ipdn_bound_var(&nfs->buckets, dn_cfg.hash_size, 1, dn_cfg.max_hash_size, "flowset buckets"); } else { nfs->buckets = 1; /* we only need 1 */ @@ -1062,23 +1062,30 @@ config_fs(struct new_fs *nfs, struct dn_ do { /* exit with break when done */ struct new_schk *s; int flags = nfs->sched_nr ? DNHT_INSERT : 0; + int j; + int oldc = dn_cfg.fsk_count; fs = dn_ht_find(dn_cfg.fshash, i, flags, NULL); if (fs == NULL) { D("missing sched for flowset %d", i); break; } + /* grab some defaults from the existing one */ if (nfs->sched_nr == 0) /* reuse */ nfs->sched_nr = fs->fs.sched_nr; - dn_cfg.id++; + for (j = 0; j < sizeof(nfs->par)/sizeof(nfs->par[0]); j++) { + if (nfs->par[j] == -1) /* reuse */ + nfs->par[j] = fs->fs.par[j]; + } if (bcmp(&fs->fs, nfs, sizeof(*nfs)) == 0) { ND("flowset %d unchanged", i); break; /* no change, nothing to do */ } + if (oldc != dn_cfg.fsk_count) /* new item */ + dn_cfg.id++; s = locate_scheduler(nfs->sched_nr); /* detach from old scheduler if needed, preserving * queues if we need to reattach. Then update the * configuration, and possibly attach to the new sched. - * XXX should print more on why the config has changed. */ D("fs %d changed sched %d@%p to %d@%p", fs->fs.fs_nr, @@ -1123,7 +1130,7 @@ config_sched(struct new_sch *_nsch, stru return EINVAL; /* make sure we have some buckets */ if (a.sch->flags & DN_HAVE_MASK) - bound_var(&a.sch->buckets, dn_cfg.hash_size, + ipdn_bound_var(&a.sch->buckets, dn_cfg.hash_size, 1, dn_cfg.max_hash_size, "sched buckets"); /* XXX other sanity checks */ bzero(&p, sizeof(p)); From owner-svn-src-user@FreeBSD.ORG Fri Jan 22 23:40:48 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 29B58106566B; Fri, 22 Jan 2010 23:40:48 +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 002BD8FC15; Fri, 22 Jan 2010 23:40:47 +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 o0MNelP5026414; Fri, 22 Jan 2010 23:40:47 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0MNelHV026409; Fri, 22 Jan 2010 23:40:47 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <201001222340.o0MNelHV026409@svn.freebsd.org> From: Luigi Rizzo Date: Fri, 22 Jan 2010 23:40:47 +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: r202846 - 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: Fri, 22 Jan 2010 23:40:48 -0000 Author: luigi Date: Fri Jan 22 23:40:47 2010 New Revision: 202846 URL: http://svn.freebsd.org/changeset/base/202846 Log: some tweaks to ease testing in user space Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_test.h user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h user/luigi/ipfw3-head/sys/netinet/ipfw/test_dn_heap.c user/luigi/ipfw3-head/sys/netinet/ipfw/test_dn_sched.c Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_test.h ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_test.h Fri Jan 22 23:35:06 2010 (r202845) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_test.h Fri Jan 22 23:40:47 2010 (r202846) @@ -6,6 +6,7 @@ #define _DN_TEST_H #include #include +#include /* bzero */ #include #include #include Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h Fri Jan 22 23:35:06 2010 (r202845) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h Fri Jan 22 23:40:47 2010 (r202846) @@ -125,6 +125,7 @@ struct dn_parms { int busy; struct mq pending; +#ifdef _KERNEL /* uh_mtx arbitrates between system calls and also * protects fshash, schedhash and fsunlinked. * These structures are readonly for the lower half. @@ -134,6 +135,7 @@ struct dn_parms { * modified upon packet arrivals */ struct mtx bh_mtx; +#endif /* _KERNEL */ }; /* Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/test_dn_heap.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/test_dn_heap.c Fri Jan 22 23:35:06 2010 (r202845) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/test_dn_heap.c Fri Jan 22 23:40:47 2010 (r202846) @@ -46,7 +46,7 @@ struct x { char buf[0]; }; -int hf(uintptr_t key, int flags, void *arg) +uint32_t hf(uintptr_t key, int flags, void *arg) { return (flags & DNHT_KEY_IS_OBJ) ? ((struct x *)key)->buf[0] : *(char *)key; Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/test_dn_sched.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/test_dn_sched.c Fri Jan 22 23:35:06 2010 (r202845) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/test_dn_sched.c Fri Jan 22 23:40:47 2010 (r202846) @@ -98,10 +98,11 @@ drop: FREE_PKT(m); return 1; } - +#ifndef NO_MAIN int main(int argc, char *argv[]) { printf("test code for the schedulers\n"); return 0; } +#endif From owner-svn-src-user@FreeBSD.ORG Fri Jan 22 23:56:46 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 C2FB8106568D; Fri, 22 Jan 2010 23:56:46 +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 B2FA68FC15; Fri, 22 Jan 2010 23:56:46 +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 o0MNukZC030716; Fri, 22 Jan 2010 23:56:46 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0MNukdL030712; Fri, 22 Jan 2010 23:56:46 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <201001222356.o0MNukdL030712@svn.freebsd.org> From: Luigi Rizzo Date: Fri, 22 Jan 2010 23:56:46 +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: r202848 - 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: Fri, 22 Jan 2010 23:56:46 -0000 Author: luigi Date: Fri Jan 22 23:56:46 2010 New Revision: 202848 URL: http://svn.freebsd.org/changeset/base/202848 Log: more support for userland testing Modified: 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/dn_test.h Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_rr.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_rr.c Fri Jan 22 23:50:46 2010 (r202847) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_rr.c Fri Jan 22 23:56:46 2010 (r202848) @@ -24,6 +24,7 @@ * SUCH DAMAGE. */ +#ifdef _KERNEL #include #include #include @@ -34,6 +35,9 @@ #include #include /* ipfw_rule_ref */ #include /* flow_id */ +#else +#include +#endif #include #include #include Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c Fri Jan 22 23:50:46 2010 (r202847) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c Fri Jan 22 23:56:46 2010 (r202848) @@ -25,6 +25,7 @@ * SUCH DAMAGE. */ +#ifdef _KERNEL #include #include #include @@ -35,6 +36,9 @@ #include #include /* ipfw_rule_ref */ #include /* flow_id */ +#else +#include +#endif #include #include #include Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_test.h ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_test.h Fri Jan 22 23:50:46 2010 (r202847) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_test.h Fri Jan 22 23:56:46 2010 (r202848) @@ -7,6 +7,7 @@ #include #include #include /* bzero */ +#include #include #include #include From owner-svn-src-user@FreeBSD.ORG Sat Jan 23 00:30:18 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 56AC610656A5; Sat, 23 Jan 2010 00:30:18 +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 2D6D98FC16; Sat, 23 Jan 2010 00:30:18 +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 o0N0UIYx040227; Sat, 23 Jan 2010 00:30:18 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0N0UIqi040225; Sat, 23 Jan 2010 00:30:18 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <201001230030.o0N0UIqi040225@svn.freebsd.org> From: Luigi Rizzo Date: Sat, 23 Jan 2010 00:30:18 +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: r202851 - 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: Sat, 23 Jan 2010 00:30:18 -0000 Author: luigi Date: Sat Jan 23 00:30:17 2010 New Revision: 202851 URL: http://svn.freebsd.org/changeset/base/202851 Log: simplify the testing code Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/test_dn_sched.c Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/test_dn_sched.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/test_dn_sched.c Sat Jan 23 00:24:31 2010 (r202850) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/test_dn_sched.c Sat Jan 23 00:30:17 2010 (r202851) @@ -54,6 +54,8 @@ dn_delete_queue(void *_q, void *do_free) } /* + * This is a simplified function for testing purposes, which does + * not implement statistics or random loss. * 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. @@ -62,39 +64,16 @@ dn_delete_queue(void *_q, void *do_free) int dn_enqueue(struct new_queue *q, struct mbuf* m, int drop) { - struct new_fs *f; - struct dn_flow *ni; /* stats for scheduler instance */ - uint64_t len; - - f = &q->fs->fs; - ni = &q->ni; - len = m->m_pkthdr.len; - /* Update statistics, then check reasons to drop pkt. */ - q->ni.tot_bytes += len; - q->ni.tot_pkts++; - ni->tot_bytes += len; - ni->tot_pkts++; if (drop) goto drop; - if (f->plr && random() < f->plr) - goto drop; - if (f->flags & DN_QSIZE_BYTES) { - if (q->ni.len_bytes > f->qsize) - goto drop; - } else if (q->ni.length >= f->qsize) { + if (q->ni.length >= 50) goto drop; - } mq_append(&q->mq, m); q->ni.length++; - q->ni.len_bytes += len; - ni->length++; - ni->len_bytes += len; return 0; drop: - io_pkt_drop++; q->ni.drops++; - ni->drops++; FREE_PKT(m); return 1; } From owner-svn-src-user@FreeBSD.ORG Sat Jan 23 00:42: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 9E51110656B2; Sat, 23 Jan 2010 00:42: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 8E1688FC15; Sat, 23 Jan 2010 00:42: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 o0N0g1jQ043090; Sat, 23 Jan 2010 00:42:01 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0N0g15Z043089; Sat, 23 Jan 2010 00:42:01 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <201001230042.o0N0g15Z043089@svn.freebsd.org> From: Luigi Rizzo Date: Sat, 23 Jan 2010 00:42: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: r202854 - 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: Sat, 23 Jan 2010 00:42:01 -0000 Author: luigi Date: Sat Jan 23 00:42:01 2010 New Revision: 202854 URL: http://svn.freebsd.org/changeset/base/202854 Log: one more simplification Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/test_dn_sched.c Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/test_dn_sched.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/test_dn_sched.c Sat Jan 23 00:41:04 2010 (r202853) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/test_dn_sched.c Sat Jan 23 00:42:01 2010 (r202854) @@ -13,7 +13,7 @@ int io_pkt_drop; void m_freem(struct mbuf *m) { - free(m); + printf("free %p\n", m); } int @@ -74,7 +74,6 @@ dn_enqueue(struct new_queue *q, struct m drop: q->ni.drops++; - FREE_PKT(m); return 1; } #ifndef NO_MAIN From owner-svn-src-user@FreeBSD.ORG Sat Jan 23 08:45:23 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 EA865106566B; Sat, 23 Jan 2010 08:45:22 +0000 (UTC) (envelope-from kmacy@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id C1F488FC12; Sat, 23 Jan 2010 08:45:22 +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 o0N8jMjE052676; Sat, 23 Jan 2010 08:45:22 GMT (envelope-from kmacy@svn.freebsd.org) Received: (from kmacy@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0N8jM2f052673; Sat, 23 Jan 2010 08:45:22 GMT (envelope-from kmacy@svn.freebsd.org) Message-Id: <201001230845.o0N8jM2f052673@svn.freebsd.org> From: Kip Macy Date: Sat, 23 Jan 2010 08:45:22 +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: r202877 - user/kmacy/releng_8_rump/lib/libunet/unet_sys 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: Sat, 23 Jan 2010 08:45:23 -0000 Author: kmacy Date: Sat Jan 23 08:45:22 2010 New Revision: 202877 URL: http://svn.freebsd.org/changeset/base/202877 Log: emulate kproc_kthread_add Modified: user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_compat.c user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_kern_intr.c Modified: user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_compat.c ============================================================================== --- user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_compat.c Sat Jan 23 08:43:21 2010 (r202876) +++ user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_compat.c Sat Jan 23 08:45:22 2010 (r202877) @@ -6,7 +6,10 @@ #include #include #include +#include + +#include struct malloc_type; vm_offset_t kmem_malloc(void * map, int bytes, int wait); @@ -95,5 +98,20 @@ getmicrotime(struct timeval *tvp) gettimeofday(&tv, NULL); } +int +kproc_kthread_add(void (*start_routine)(void *), void *arg, + struct proc **p, struct thread **td, + int flags, int pages, + char * procname, const char *str, ...) +{ + int error; + pthread_t thread; + pthread_attr_t attr; + *td = malloc(sizeof(struct thread)); + pthread_attr_init(&attr); + + error = pthread_create(&thread, &attr, start_routine, arg); + return (error); +} Modified: user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_kern_intr.c ============================================================================== --- user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_kern_intr.c Sat Jan 23 08:43:21 2010 (r202876) +++ user/kmacy/releng_8_rump/lib/libunet/unet_sys/unet_kern_intr.c Sat Jan 23 08:45:22 2010 (r202877) @@ -361,15 +361,16 @@ ithread_create(const char *name) ithd = malloc(sizeof(struct intr_thread), M_ITHREAD, M_WAITOK | M_ZERO); -#ifdef notyet error = kproc_kthread_add(ithread_loop, ithd, &intrproc, &td, RFSTOPPED | RFHIGHPID, 0, "intr", "%s", name); + + if (error) panic("kproc_create() failed with %d", error); td->td_pflags |= TDP_ITHREAD; ithd->it_thread = td; -#endif + CTR2(KTR_INTR, "%s: created %s", __func__, name); return (ithd); } From owner-svn-src-user@FreeBSD.ORG Sat Jan 23 22:21:56 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 A34BD1065672; Sat, 23 Jan 2010 22:21:56 +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 864D28FC1A; Sat, 23 Jan 2010 22:21:56 +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 o0NMLu2u036089; Sat, 23 Jan 2010 22:21:56 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0NMLuif036084; Sat, 23 Jan 2010 22:21:56 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <201001232221.o0NMLuif036084@svn.freebsd.org> From: Luigi Rizzo Date: Sat, 23 Jan 2010 22:21:56 +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: r202901 - 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: Sat, 23 Jan 2010 22:21:56 -0000 Author: luigi Date: Sat Jan 23 22:21:56 2010 New Revision: 202901 URL: http://svn.freebsd.org/changeset/base/202901 Log: refine includes for testing Modified: 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/dn_test.h Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_fifo.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_fifo.c Sat Jan 23 22:11:18 2010 (r202900) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_fifo.c Sat Jan 23 22:21:56 2010 (r202901) @@ -35,13 +35,13 @@ #include #include /* ipfw_rule_ref */ #include /* flow_id */ -#else -#include "dn_test.h" -#endif #include #include #include #include +#else +#include "dn_test.h" +#endif /* * This file implements a FIFO scheduler for a single queue. Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_rr.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_rr.c Sat Jan 23 22:11:18 2010 (r202900) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_rr.c Sat Jan 23 22:21:56 2010 (r202901) @@ -35,13 +35,13 @@ #include #include /* ipfw_rule_ref */ #include /* flow_id */ -#else -#include -#endif #include #include #include #include +#else +#include "dn_test.h" +#endif #define DN_SCHED_RR 3 // XXX Where? Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c Sat Jan 23 22:11:18 2010 (r202900) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c Sat Jan 23 22:21:56 2010 (r202901) @@ -36,13 +36,13 @@ #include #include /* ipfw_rule_ref */ #include /* flow_id */ -#else -#include -#endif #include #include #include #include +#else +#include "dn_test.h" +#endif #ifndef MAX64 #define MAX64(x,y) (( (int64_t) ( (y)-(x) )) > 0 ) ? (y) : (x) Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_test.h ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_test.h Sat Jan 23 22:11:18 2010 (r202900) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_test.h Sat Jan 23 22:21:56 2010 (r202901) @@ -25,6 +25,7 @@ struct mbuf { int len; } m_pkthdr; struct mbuf *m_nextpkt; + int flow_id; }; typedef void * module_t; struct _md_t { @@ -37,4 +38,9 @@ typedef struct _md_t moduledata_t; moduledata_t *_g_##name = & name##_mod #define MODULE_DEPEND(a, b, c, d, e) +#include +#include +#include +#include + #endif /* _DN_TEST_H */