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