Skip site navigation (1)Skip section navigation (2)
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>