svn commit: r204047 - in user/luigi/ipfw3-head: sbin/ipfw
sys/netinet sys/netinet/ipfw
Luigi Rizzo
luigi at FreeBSD.org
Thu Feb 18 16:25:38 UTC 2010
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;
More information about the svn-src-user
mailing list