Date: Fri, 8 Jan 2010 22:37:53 +0000 (UTC) From: Luigi Rizzo <luigi@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r201844 - in user/luigi/ipfw3-head/sys/netinet: . ipfw Message-ID: <201001082237.o08MbrEY012907@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: luigi Date: Fri Jan 8 22:37:52 2010 New Revision: 201844 URL: http://svn.freebsd.org/changeset/base/201844 Log: partial processing of 'configure' Modified: 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/sys/netinet/ip_dummynet.h ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h Fri Jan 8 22:34:17 2010 (r201843) +++ user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h Fri Jan 8 22:37:52 2010 (r201844) @@ -66,13 +66,15 @@ enum { DN_FS_EXT, DN_QUEUE_EXT, DN_UNKNOW, - DN_CMD_CONFIGURE, - DN_CMD_DELETE, + DN_CMD_CONFIGURE, /* objects follow */ + DN_CMD_DELETE, /* subtype + list of entries */ + DN_CMD_GET, /* subtype + list of entries */ + DN_CMD_FLUSH, DN_LAST, }; /* These values are in the subtype field of struct gen */ -enum dn_configure { +enum { DN_CONF_PIPE = 1, DN_CONF_QUEUE = 2, DN_CONF_SCHED = 3, @@ -93,13 +95,21 @@ enum sched_flag { 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 */ +}; + #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 */ }; Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c Fri Jan 8 22:34:17 2010 (r201843) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c Fri Jan 8 22:37:52 2010 (r201844) @@ -245,12 +245,12 @@ struct dn_pkt_tag { static struct dn_pkt_tag * dn_tag_get(struct mbuf *m) { - struct m_tag *mtag = m_tag_first(m); - KASSERT(mtag != NULL && + struct m_tag *mtag = m_tag_first(m); + KASSERT(mtag != NULL && mtag->m_tag_cookie == MTAG_ABI_COMPAT && mtag->m_tag_id == PACKET_TAG_DUMMYNET, ("packet on dummynet queue w/o dummynet tag!")); - return (struct dn_pkt_tag *)(mtag+1); + return (struct dn_pkt_tag *)(mtag+1); } /* @@ -262,6 +262,7 @@ transmit_event(struct delay_line *dline, { struct mbuf *m; struct mbuf *head = NULL, *tail = NULL; + struct dn_pkt_tag *pkt = NULL; /* XXX we are under scheduler lock */ while ((m = dline->head) != NULL) { @@ -280,7 +281,6 @@ transmit_event(struct delay_line *dline, tail->m_nextpkt = NULL; if ((m = dline->head) != NULL) { - struct dn_pkt_tag *pkt = dn_tag_get(m); DN_HEAP_LOCK(); heap_insert(&dn_cfg.system_heap, pkt->output_time, dline); DN_HEAP_UNLOCK(); @@ -471,7 +471,7 @@ create_scheduler_instance(struct new_sch if (si == NULL) goto error; - si->dline = malloc(sizeof(*si->dline, M_DUMMYNET, M_NOWAIT | M_ZERO); + si->dline = malloc(sizeof(*si->dline), M_DUMMYNET, M_NOWAIT | M_ZERO); if (si->dline == NULL) goto error; @@ -670,7 +670,7 @@ dummynet_task(void *context, int pending struct mbuf *head = NULL; DN_HEAP_LOCK(); - if (&dn_cfg.system_heap->elements > 0 && + if (dn_cfg.system_heap.elements > 0 && DN_KEY_LEQ(HEAP_TOP(&dn_cfg.system_heap)->key, curr_time)) { p = HEAP_TOP(&dn_cfg.system_heap)->object; heap_extract(&dn_cfg.system_heap, NULL); @@ -735,8 +735,6 @@ dummynet_task(void *context, int pending DN_S_LOCK(dline->si->ptr_sched); head = transmit_event(dline, curr_time); DN_S_UNLOCK(dline->si->ptr_sched); - if (head != NULL) - dummynet_send(head); } } if (head != NULL) @@ -1256,11 +1254,10 @@ dummynet_io(struct mbuf **m0, int dir, s *m0 = NULL; } done: - DUMMYNET_UNLOCK(); - if (head != NULL) - dummynet_send(head); - - return 0; + DUMMYNET_UNLOCK(); + if (head != NULL) + dummynet_send(head); + return 0; dropit: io_pkt_drop++; 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 8 22:34:17 2010 (r201843) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h Fri Jan 8 22:37:52 2010 (r201844) @@ -78,6 +78,7 @@ struct dn_parms { int io_fast; struct timeval prev_t; + struct dn_heap system_heap; }; static inline void Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Fri Jan 8 22:34:17 2010 (r201843) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Fri Jan 8 22:37:52 2010 (r201844) @@ -76,6 +76,10 @@ static struct taskqueue *dn_tq = NULL; static struct dn_sched_head list_of_scheduler; +static int config_pipe(struct new_pipe *p); +static int config_profile(struct new_profile *p); +static int config_fs(struct new_fs *p); +static int config_sched(struct new_sch *p); /* * This is called one tick, after previous run. It is used to * schedule next run. @@ -183,7 +187,7 @@ really_deletescheduler(struct new_sch *s return 0; } - +/* remove a pipe and attached objects */ static void free_pipe(struct new_pipe *p) { @@ -193,63 +197,6 @@ free_pipe(struct new_pipe *p) } /* - * Dispose all packets and flow_queues on a flow_set. - * If all=1, also remove red lookup table and other storage, - * including the descriptor itself. - * For the one in dn_pipe MUST also cleanup ready_heap... - */ -static void -purge_flow_set(struct new_fs *fs, int all) -{ -#if 0 - struct new_queue *q, *qn; - int i; - - DUMMYNET_LOCK_ASSERT(); - - for (i = 0; i <= fs->rq_size; i++) { - for (q = fs->rq[i]; q != NULL; q = qn) { - dn_free_pkts(q->head); - qn = q->next; - free(q, M_DUMMYNET); - } - fs->rq[i] = NULL; - } - - fs->rq_elements = 0; - if (all) { - /* RED - free lookup table. */ - if (fs->w_q_lookup != NULL) - free(fs->w_q_lookup, M_DUMMYNET); - if (fs->rq != NULL) - free(fs->rq, M_DUMMYNET); - /* If this fs is not part of a pipe, free it. */ - if (fs->pipe == NULL || fs != &(fs->pipe->fs)) - free(fs, M_DUMMYNET); - } -#endif -} - -/* - * Dispose all packets queued on a pipe (not a flow_set). - * Also free all resources associated to a pipe, which is about - * to be deleted. - */ -static void -purge_pipe(struct new_pipe *pipe) -{ -#if 0 - purge_flow_set( &(pipe->fs), 1 ); - - dn_free_pkts(pipe->head); - - heap_free( pipe->scheduler_heap ); - heap_free( pipe->not_eligible_heap ); - heap_free( pipe->idle_heap ); -#endif -} - -/* * Deelete all objects. */ static void @@ -257,6 +204,7 @@ dummynet_flush(void) { struct new_pipe *pipe, *pipe1; struct new_fs *fs, *fs1; + struct new_sch *sch_t, *sch_t1; int i; DUMMYNET_LOCK(); @@ -265,7 +213,7 @@ dummynet_flush(void) heap_free(&dn_cfg.system_heap); /* Free all pipes */ - for (i = 0; i < HASHSIZE; i++) { + for (i = 0; i < DN_HASHSIZE; i++) { SLIST_FOREACH_SAFE(pipe, &pipehash[i], next, pipe1) { SLIST_REMOVE(&pipehash[i], pipe, new_pipe, next); free_pipe(pipe); @@ -279,10 +227,10 @@ dummynet_flush(void) } /* Free all flowsets in the system */ - for (i = 0; i < HASHSIZE; i++) { + for (i = 0; i < DN_HASHSIZE; i++) { SLIST_FOREACH_SAFE(fs, &flowsethash[i], next, fs1) { SLIST_REMOVE(&flowsethash[i], fs, new_fs, next); - fs->fp->delete_alg_fs(fs->alg_fs); + fs->fp->free_fs(fs->alg_fs); fs->fp->ref_count--; free(fs->alg_fs, M_DUMMYNET); free(fs, M_DUMMYNET); @@ -290,7 +238,7 @@ dummynet_flush(void) } /* Free all schedulers */ - for (i = 0; i < HASHSIZE; i++) { + for (i = 0; i < DN_HASHSIZE; i++) { SLIST_FOREACH_SAFE(sch_t, &schedulerhash[i], next, sch_t1) { SLIST_REMOVE(&schedulerhash[i], sch_t, new_sch, next); sch_t->flags |= DN_SCH_DELETE_DELAY_LINE; @@ -418,13 +366,44 @@ set_fs_parms(struct dn_flow_set *x, stru static int do_config(void *p, int l) { - struct dn_id *o = p; + struct dn_id *next, *o; + int err = 0, cmd = 0; - while (l && o->len > 0) { + for (o = p; l >= sizeof(*o); o = next) { + err = EINVAL; + if (o->len < sizeof(*o) || l < o->len) { + printf("bad len o->len %d len %d\n", o->len, l); + break; + } l -= o->len; - o = (struct dn_id *)((char *)o + l); + printf("%s cmd %d len %d left %d\n", + __FUNCTION__, o->type, o->len, l); + next = (struct dn_id *)((char *)o + o->len); + switch (o->type) { + case DN_CMD_CONFIGURE: + case DN_CMD_GET: + case DN_CMD_DELETE: + case DN_CMD_FLUSH: + cmd = o->type; + err = 0; + break; + case DN_PIPE: + err = config_pipe((struct new_pipe *)o); + break; + case DN_PROFILE: + err = config_profile((struct new_profile *)o); + break; + case DN_SCH: + err = config_sched((struct new_sch *)o); + break; + case DN_FS: + err = config_fs((struct new_fs *)o); + break; + } + if (err != 0) + break; } - return 0; + return err; } static struct new_sch * @@ -673,16 +652,17 @@ dn_fs_config(struct new_fs *fs) * (re)configures the WFQ scheduler for the pipe. */ static int -config_pipe(struct dn_pipe *p) +config_pipe(struct new_pipe *p) { -#if 0 - struct dn_flow_set *pfs = &(p->fs); - struct dn_flow_queue *q; - int i, error; + struct new_pipe *pipe; + if (p->oid.len < sizeof(*p)) { + printf("%s: short pipe\n", __FUNCTION__); + return EINVAL; + } /* We need either a pipe number or a flow_set number. */ - if (p->pipe_nr == 0 && pfs->fs_nr == 0) - return (EINVAL); + if (p->pipe_nr <= 0 || p->pipe_nr >= DN_PIPEOFFSET) + return EINVAL; /* * The config program passes parameters as follows: * bw = bits/second (0 means no limits), @@ -694,79 +674,103 @@ config_pipe(struct dn_pipe *p) p->burst *= 8 * hz; DUMMYNET_LOCK(); - if (p->pipe_nr != 0) { /* this is a pipe */ - struct dn_pipe *pipe; - - pipe = locate_pipe(p->pipe_nr); /* locate pipe */ + pipe = locate_pipe(p->pipe_nr); /* locate pipe */ - if (pipe == NULL) { /* new pipe */ - /* space for pipe + 3 heaps right after the pipe */ - pipe = malloc(sizeof(struct dn_pipe) + - 3 * sizeof(struct dn_heap), M_DUMMYNET, - M_NOWAIT | M_ZERO); - if (pipe == NULL) { - DUMMYNET_UNLOCK(); - printf("dummynet: no memory for new pipe\n"); - return (ENOMEM); - } + if (pipe == NULL) { /* brand new pipe */ + pipe = malloc(sizeof(*pipe), M_DUMMYNET, M_NOWAIT | M_ZERO); + if (pipe == NULL) { + DUMMYNET_UNLOCK(); + printf("dummynet: no memory for new pipe\n"); + return (ENOMEM); + } + bcopy(p, pipe, sizeof(*pipe)); + /* XXX schedulers should attach to us... */ + } else { + /* pipe already exists, reconfigure it. */ + struct new_sch *sch; + struct new_sch_inst *si; + int i; + + sch = locate_scheduler(pipe->pipe_nr + DN_PIPEOFFSET); + if (sch) { + /* Flush accumulated credit for all queues. */ + for (i = 0; i < sch->sch_i_size; i++) + for (si = sch->sch_i[i]; si; si = si->next) + si->numbytes = p->burst + dn_cfg.io_fast ? + p->bandwidth : 0; + } + pipe->delay = p->delay; + pipe->bandwidth = p->bandwidth; + pipe->burst = p->burst; + bcopy(p->if_name, pipe->if_name, sizeof(p->if_name)); + pipe->ifp = NULL; /* reset interface ptr */ + } + dn_cfg.id++; + DUMMYNET_UNLOCK(); + return 0; +} - pipe->scheduler_heap = (struct dn_heap *)(pipe + 1); - pipe->not_eligible_heap = pipe->scheduler_heap + 1; - pipe->idle_heap = pipe->scheduler_heap + 2; +static int +config_sched(struct new_sch *sch) +{ + return 0; +} - pipe->pipe_nr = p->pipe_nr; - pipe->fs.pipe = pipe; - /* - * idle_heap is the only one from which - * we extract from the middle. - */ - pipe->idle_heap->ofs = - offsetof(struct dn_flow_queue, heap_pos); - } else { - /* Flush accumulated credit for all queues. */ - for (i = 0; i <= pipe->fs.rq_size; i++) { - for (q = pipe->fs.rq[i]; q; q = q->next) { - q->numbytes = p->burst + - (dn_cfg.io_fast ? p->bandwidth : 0); - } - } - } +static int +config_fs(struct new_fs *fs) +{ + return 0; +} +/* + * attach a profile to a pipe + */ +static int +config_profile(struct new_profile *pf) +{ + struct new_pipe *pipe; - pipe->bandwidth = p->bandwidth; - pipe->burst = p->burst; - pipe->numbytes = pipe->burst + (dn_cfg.io_fast ? pipe->bandwidth : 0); - bcopy(p->if_name, pipe->if_name, sizeof(p->if_name)); - pipe->ifp = NULL; /* reset interface ptr */ - pipe->delay = p->delay; - set_fs_parms(&(pipe->fs), pfs); + if (pf->oid.len < sizeof(*pf)) { + printf("%s: short profile\n", __FUNCTION__); + return EINVAL; + } + /* We need a pipe number . */ + if (pf->pipe_nr <= 0 || pf->pipe_nr >= DN_PIPEOFFSET) + return EINVAL; + /* XXX other sanity checks */ + DUMMYNET_LOCK(); + pipe = locate_pipe(pf->pipe_nr); /* locate pipe */ - /* Handle changes in the delay profile. */ - if (p->samples_no > 0) { - if (pipe->samples_no != p->samples_no) { - if (pipe->samples != NULL) - free(pipe->samples, M_DUMMYNET); - pipe->samples = - malloc(p->samples_no*sizeof(dn_key), - M_DUMMYNET, M_NOWAIT | M_ZERO); - if (pipe->samples == NULL) { - DUMMYNET_UNLOCK(); - printf("dummynet: no memory " - "for new samples\n"); - return (ENOMEM); - } - pipe->samples_no = p->samples_no; - } + if (pipe == NULL) { /* brand new pipe */ + DUMMYNET_UNLOCK(); + printf("%s: no pipe %d\n", __FUNCTION__, pf->pipe_nr); + return EINVAL; + } - strncpy(pipe->name,p->name,sizeof(pipe->name)); - pipe->loss_level = p->loss_level; - for (i = 0; i<pipe->samples_no; ++i) - pipe->samples[i] = p->samples[i]; - } else if (pipe->samples != NULL) { - free(pipe->samples, M_DUMMYNET); - pipe->samples = NULL; - pipe->samples_no = 0; + dn_cfg.id++; + /* see if we need to allocate memory */ + if (pipe->profile && (pf->samples_no == 0 || + pipe->profile->oid.len < pf->oid.len)) { + free(pipe->profile, M_DUMMYNET); + pipe->profile = NULL; + } + if (pf->samples_no > 0) { + if (pipe->profile == NULL) + pipe->profile = malloc(pf->oid.len, + M_DUMMYNET, M_NOWAIT | M_ZERO); + if (pipe->profile == NULL) { + DUMMYNET_UNLOCK(); + printf("%s: no memory\n", __FUNCTION__); + return ENOMEM; } - + bcopy(pf, pipe->profile, pf->oid.len); + } + DUMMYNET_UNLOCK(); + return 0; +} + +#if 0 + /* We need either a pipe number or a flow_set number. */ + set_fs_parms(&(pipe->fs), pfs); if (pipe->fs.rq == NULL) { /* a new pipe */ error = alloc_hash(&(pipe->fs), pfs); if (error) { @@ -828,11 +832,9 @@ config_pipe(struct dn_pipe *p) } } DUMMYNET_UNLOCK(); -#endif return (0); } -#if 0 /* * Helper function to remove from a heap queues which are linked to * a flow_set about to be deleted. @@ -860,16 +862,14 @@ scan_remove_pipe(void *_o, uintptr_t p) { return (0 == (void *)p) ? HEAP_SCAN_DEL | HEAP_SCAN_END : 0; } -#endif /* * Fully delete a pipe or a queue, cleaning up associated info. */ static int -delete_pipe(struct dn_pipe *p) +delete_pipe(struct dn_id *p, int l) { int err = 0; -#if 0 struct dn_pipe *pipe; struct new_fs *fs; @@ -931,11 +931,9 @@ done: DUMMYNET_UNLOCK(); if (pipe) free_pipe(pipe); -#endif return err; } -#if 0 /* * helper function used to copy data from kernel in DUMMYNET_GET */ @@ -1088,65 +1086,54 @@ dummynet_get(struct sockopt *sopt) static int ip_dn_ctl(struct sockopt *sopt) { - int error; - struct dn_pipe *p = NULL; - int l; - - error = priv_check(sopt->sopt_td, PRIV_NETINET_DUMMYNET); - if (error) - return (error); - - /* Disallow sets in really-really secure mode. */ - if (sopt->sopt_dir == SOPT_SET) { - error = securelevel_ge(sopt->sopt_td->td_ucred, 3); + void *p = NULL; + int error, l; + + error = priv_check(sopt->sopt_td, PRIV_NETINET_DUMMYNET); if (error) - return (error); - } + return (error); - switch (sopt->sopt_name) { - default : - printf("dummynet: -- unknown option %d", sopt->sopt_name); - error = EINVAL ; - break; - - case IP_DUMMYNET_GET : - error = dummynet_get(sopt); - break ; - - case IP_DUMMYNET_FLUSH : - dummynet_flush() ; - break ; - - case IP_DUMMYNET_CONFIGURE : - l = (sopt->sopt_dir == SOPT_SET) ? sopt->sopt_valsize : - *(int *)(sopt->sopt_valsize); - if (l < 0 || l > 12000) { - printf("argument too large, %d\n", l); - break; + /* 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); } - printf("%s size %d\n", __FUNCTION__, l); - p = malloc(l, M_TEMP, M_WAITOK); - error = sooptcopyin(sopt, p, l, l); - if (error) - break ; - error = do_config(p, l); - break; - error = config_pipe(p); - break ; - - case IP_DUMMYNET_DEL : /* remove a pipe or queue */ - p = malloc(sizeof(struct dn_pipe), M_TEMP, M_WAITOK); - error = sooptcopyin(sopt, p, sizeof(struct dn_pipe), sizeof *p); - if (error) - break ; + switch (sopt->sopt_name) { + default : + printf("dummynet: -- unknown option %d", sopt->sopt_name); + error = EINVAL; + break; - error = delete_pipe(p); - break ; - } + case IP_DUMMYNET_GET : + error = dummynet_get(sopt); + break; + + case IP_DUMMYNET_FLUSH : + dummynet_flush(); + break; + + case IP_DUMMYNET_CONFIGURE : + case IP_DUMMYNET_DEL : /* remove a pipe or queue */ + l = (sopt->sopt_dir == SOPT_SET) ? sopt->sopt_valsize : + *(int *)(sopt->sopt_valsize); + if (l < 0 || l > 12000) { + printf("argument too large, %d\n", l); + break; + } + printf("%s size %d\n", __FUNCTION__, l); + p = malloc(l, M_TEMP, M_WAITOK); + error = sooptcopyin(sopt, p, l, l); + if (error) + break ; + + error = do_config(p, l); + break; + } - if (p != NULL) - free(p, M_TEMP); + if (p != NULL) + free(p, M_TEMP); return error ; }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201001082237.o08MbrEY012907>