Date: Thu, 18 Feb 2010 16:25:38 +0000 (UTC) From: Luigi Rizzo <luigi@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r204047 - in user/luigi/ipfw3-head: sbin/ipfw sys/netinet sys/netinet/ipfw Message-ID: <201002181625.o1IGPcpF016375@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: luigi Date: Thu Feb 18 16:25:38 2010 New Revision: 204047 URL: http://svn.freebsd.org/changeset/base/204047 Log: corrections to the previous version -- don't do floating point in the kernel! 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_glue.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 Feb 18 16:23:13 2010 (r204046) +++ user/luigi/ipfw3-head/sbin/ipfw/dummynet.c Thu Feb 18 16:25:38 2010 (r204047) @@ -366,8 +366,8 @@ list_pipes(struct dn_id *oid, struct dn_ flush_buf(buf); print_extra_delay_parms((struct dn_profile *)oid); } + flush_buf(buf); // XXX does it really go here ? } - flush_buf(buf); } /* @@ -576,7 +576,8 @@ compare_points(const void *vp1, const vo #define ED_EFMT(s) EX_DATAERR,"error in %s at line %d: "#s,filename,lineno static void -load_extra_delays(const char *filename, struct dn_profile *p) +load_extra_delays(const char *filename, struct dn_profile *p, + struct dn_link *link) { char line[ED_MAX_LINE_LEN]; FILE *f; @@ -591,6 +592,10 @@ load_extra_delays(const char *filename, struct point points[ED_MAX_SAMPLES_NO]; int points_no = 0; + if (link == NULL) + return; /*XXX error */ + p->link_nr = link->link_nr; + profile_name[0] = '\0'; f = fopen(filename, "r"); if (f == NULL) @@ -1098,7 +1103,7 @@ end_mask: { pf = o_next(&buf, sizeof(*pf), DN_PROFILE); NEED1("extra delay needs the file name\n"); - load_extra_delays(av[0], pf); + load_extra_delays(av[0], pf, p); --ac; ++av; } break; Modified: user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h Thu Feb 18 16:23:13 2010 (r204046) +++ user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h Thu Feb 18 16:25:38 2010 (r204047) @@ -77,11 +77,15 @@ enum { DN_CMD_DELETE, /* subtype + list of entries */ DN_CMD_GET, /* subtype + list of entries */ DN_CMD_FLUSH, - /* for compatibility with FreeBSD 7.2/8 */ DN_COMPAT_PIPE, DN_COMPAT_QUEUE, DN_GET_COMPAT, + + /* special commands for emulation of sysctl variables */ + DN_SYSCTL_GET, + DN_SYSCTL_SET, + DN_LAST, }; @@ -141,7 +145,10 @@ struct dn_fs { */ int par[4]; - /* RED/GRED parameters */ + /* RED/GRED parameters. + * weight and probabilities are in the range 0..1 represented + * in fixed point arithmetic with SCALE_RED decimal bits. + */ #define SCALE_RED 16 #define SCALE(x) ( (x) << SCALE_RED ) #define SCALE_VAL(x) ( (x) >> SCALE_RED ) @@ -186,7 +193,9 @@ struct dn_sch { }; -/* A delay profile is attached to a link */ +/* A delay profile is attached to a link. + * Note that a profile, as any other object, cannot be longer than 2^16 + */ #define ED_MAX_SAMPLES_NO 1024 struct dn_profile { struct dn_id oid; @@ -195,7 +204,7 @@ struct dn_profile { char name[ED_MAX_NAME_LEN]; int link_nr; int loss_level; - int bandwidth; + int bandwidth; // XXX maybe not needed ? int samples_no; /* actual length of samples[] */ int samples[ED_MAX_SAMPLES_NO]; /* may be shorter */ }; Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_glue.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_glue.c Thu Feb 18 16:23:13 2010 (r204046) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_glue.c Thu Feb 18 16:25:38 2010 (r204047) @@ -455,6 +455,7 @@ dn_compat_config_profile(struct dn_profi pf->loss_level = p8->loss_level; pf->bandwidth = p->bandwidth; pf->samples_no = p8->samples_no; + strncpy(pf->name, p8->name,sizeof(pf->name)); bcopy(p8->samples, pf->samples, sizeof(pf->samples)); return 0; @@ -600,7 +601,7 @@ dn_c_copy_pipe(struct dn_schk *s, struct if (!is7) { if (s->profile) { struct dn_profile *pf = s->profile; - strncpy(pf->name,pipe8->name,sizeof(pf->name)); + strncpy(pipe8->name, pf->name, sizeof(pf->name)); pipe8->loss_level = pf->loss_level; pipe8->samples_no = pf->samples_no; } Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Thu Feb 18 16:23:13 2010 (r204046) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Thu Feb 18 16:25:38 2010 (r204047) @@ -823,6 +823,29 @@ copy_q(struct copy_args *a, struct dn_fs return 0; } +/* + * This routine only copies the initial part of a profile ? XXX + */ +static int +copy_profile(struct copy_args *a, struct dn_profile *p) +{ + int have = a->end - *a->start; + /* XXX here we check for max length */ + int profile_len = sizeof(struct dn_profile) - + ED_MAX_SAMPLES_NO*sizeof(int); + + if (p == NULL) + return 0; + if (have < profile_len) { + D("error have %d need %d", have, profile_len); + return 1; + } + bcopy(p, *a->start, profile_len); + ((struct dn_id *)(*a->start))->len = profile_len; + *a->start += profile_len; + return 0; +} + static int copy_flowset(struct copy_args *a, struct dn_fsk *fs, int flags) { @@ -910,6 +933,8 @@ copy_data_helper(void *_o, void *_arg) if (copy_obj(a->start, a->end, &s->link, "link", s->sch.sched_nr)) return DNHT_SCAN_END; + if (copy_profile(a, s->profile)) + return DNHT_SCAN_END; if (copy_flowset(a, s->fs, 0)) return DNHT_SCAN_END; } @@ -942,31 +967,33 @@ locate_scheduler(int i) return dn_ht_find(dn_cfg.schedhash, i, 0, NULL); } +/* + * red parameters are in fixed point arithmetic. + */ static int config_red(struct dn_fsk *fs) { - double s, idle, weight; + int64_t s, idle, weight, w0; int t, i; fs->w_q = fs->fs.w_q; fs->max_p = fs->fs.max_p; D("called"); /* Doing stuff that was in userland */ - if (fs->sched->link.bandwidth <= 0) - s = 0; - else - s = hz * dn_cfg.red_avg_pkt_size * 8 / fs->sched->link.bandwidth; - - idle = s * 3. / fs->fs.w_q; - fs->lookup_step = (int)idle / dn_cfg.red_lookup_depth; + i = fs->sched->link.bandwidth; + s = (i <= 0) ? 0 : + hz * dn_cfg.red_avg_pkt_size * 8 * SCALE(1) / i; + + idle = (s * 3) / fs->w_q; /* s, fs->w_q scaled; idle not scaled */ + fs->lookup_step = idle / dn_cfg.red_lookup_depth; + /* fs->lookup_step not scaled, */ if (!fs->lookup_step) fs->lookup_step = 1; - weight = 1 - fs->w_q; + w0 = weight = SCALE(1) - fs->w_q; //fs->w_q scaled for (t = fs->lookup_step; t > 1; --t) - weight *= 1 - fs->w_q; - - fs->lookup_weight = (int)(weight * (1 << SCALE_RED)); + weight = SCALE_MUL(weight, w0); + fs->lookup_weight = (int)(weight); // scaled /* Now doing stuff that was in kerneland */ fs->min_th = SCALE(fs->fs.min_th); @@ -1420,7 +1447,7 @@ static int config_profile(struct dn_profile *pf, struct dn_id *arg) { struct dn_schk *s; - int i; + int i, olen, err = 0; if (pf->oid.len < sizeof(*pf)) { D("short profile len %d", pf->oid.len); @@ -1431,12 +1458,12 @@ config_profile(struct dn_profile *pf, st return EINVAL; /* XXX other sanity checks */ DN_BH_WLOCK(); + for (; i < 2*DN_MAX_ID; i += DN_MAX_ID) { s = locate_scheduler(i); if (s == NULL) { - DN_BH_WUNLOCK(); - D("no scheduler %d", i); - return EINVAL; + err = EINVAL; + break; } dn_cfg.id++; /* @@ -1448,21 +1475,21 @@ config_profile(struct dn_profile *pf, st free(s->profile, M_DUMMYNET); s->profile = NULL; } + if (pf->samples_no == 0) + continue; /* - * if we have a new profile, possibly allocate memory + * new profile, possibly allocate memory * and copy data. */ - if (pf->samples_no > 0) { - int olen; if (s->profile == NULL) s->profile = malloc(pf->oid.len, M_DUMMYNET, M_NOWAIT | M_ZERO); if (s->profile == NULL) { - DN_BH_WUNLOCK(); D("no memory for profile %d", i); - return ENOMEM; + err = ENOMEM; + break; } - /* preserve larger length */ + /* preserve larger length XXX double check */ olen = s->profile->oid.len; if (olen < pf->oid.len) olen = pf->oid.len; @@ -1470,7 +1497,7 @@ config_profile(struct dn_profile *pf, st s->profile->oid.len = olen; } DN_BH_WUNLOCK(); - return 0; + return err; } /* @@ -1527,7 +1554,15 @@ do_config(void *p, int l) default: D("cmd %d not implemented", o->type); break; - +#ifdef EMULATE_SYSCTL + /* sysctl emulation. + * if we recognize the command, jump to the correct + * handler and return + */ + case DN_SYSCTL_SET: + err = kesysctl_set_w32(p); + return err; +#endif case DN_CMD_CONFIG: /* simply a header */ break; @@ -1596,6 +1631,8 @@ static int compute_space(struct dn_id *cmd, int *to_copy) { int x = 0, need = 0; + int profile_size = sizeof(struct dn_profile) - + ED_MAX_SAMPLES_NO*sizeof(int); /* NOTE about compute space: * NP = dn_cfg.schk_count @@ -1626,16 +1663,19 @@ compute_space(struct dn_id *cmd, int *to switch (cmd->subtype) { default: return -1; + /* XXX where do LINK and SCH differ ? */ case DN_LINK: /* pipe show */ - x = DN_C_LINK /*| DN_C_FS*/ | DN_C_SCH | DN_C_FLOW; - need += dn_cfg.schk_count * sizeof(struct dn_fs) / 2; + x = DN_C_LINK | DN_C_SCH | DN_C_FLOW; + need += dn_cfg.schk_count * + (sizeof(struct dn_fs) + profile_size) / 2; need += dn_cfg.si_count * max_qlen; need += dn_cfg.fsk_count * sizeof(uint32_t); break; case DN_SCH: /* sched show */ - need += dn_cfg.schk_count * sizeof(struct dn_fs) / 2; + need += dn_cfg.schk_count * + (sizeof(struct dn_fs) + profile_size) / 2; need += dn_cfg.fsk_count * sizeof(uint32_t); - x = DN_C_SCH | DN_C_LINK | DN_C_FLOW /*|| DN_C_QUEUE*/; + x = DN_C_SCH | DN_C_LINK | DN_C_FLOW; break; case DN_FS: /* queue show */ x = DN_C_FS | DN_C_QUEUE; @@ -1679,9 +1719,18 @@ dummynet_get(struct sockopt *sopt, void /* save and restore original sopt_valsize around copyin */ sopt_valsize = sopt->sopt_valsize; if (!compat) { - D("standard mode"); - error = sooptcopyin(sopt, &cmd, sizeof(cmd), sizeof(cmd)); +#ifdef EMULATE_SYSCTL + /* sysctl emulation. + * if we recognize the command, jump to the correct + * handler and return + */ + if (cmd.type == DN_SYSCTL_GET) { + //jump to sysctl handler + error = kesysctl_get_w32(sopt); + return error; + } +#endif sopt->sopt_valsize = sopt_valsize; if (error) return error;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201002181625.o1IGPcpF016375>