netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 1/2] [iproute2/tc] tc_core: add size table
@ 2008-07-10 19:34 Jussi Kivilinna
  2008-07-10 19:34 ` [PATCH v4 2/2] [iproute2/tc] hfsc: add link layer overhead adaption Jussi Kivilinna
  0 siblings, 1 reply; 2+ messages in thread
From: Jussi Kivilinna @ 2008-07-10 19:34 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: netdev

Patch adds size table that is similiar to rate table, with difference that
size table stores link layer packet size. It's needed for HFSC link
layer adaption patch as it converts skb->len to link layer packet size
directly, unlike HTB/CFQ/etc that convert packet length to link layer
transfer time using rate tables.

Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
---

 include/linux/pkt_sched.h |   10 ++++++
 tc/tc_core.c              |   70 +++++++++++++++++++++++++++++++++++----------
 tc/tc_core.h              |    2 +
 3 files changed, 67 insertions(+), 15 deletions(-)

diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h
index dbb7ac3..5bf1444 100644
--- a/include/linux/pkt_sched.h
+++ b/include/linux/pkt_sched.h
@@ -85,6 +85,16 @@ struct tc_ratespec
 
 #define TC_RTAB_SIZE	1024
 
+struct tc_sizespec {
+	unsigned char	cell_log;
+	unsigned char	size_log;
+	short		overhead;
+	short		cell_align;
+	unsigned short	mpu;
+};
+
+#define TC_STAB_SIZE	1024
+
 /* FIFO section */
 
 struct tc_fifo_qopt
diff --git a/tc/tc_core.c b/tc/tc_core.c
index 855c115..7d8cd82 100644
--- a/tc/tc_core.c
+++ b/tc/tc_core.c
@@ -87,6 +87,21 @@ unsigned tc_align_to_atm(unsigned size)
 	return linksize;
 }
 
+unsigned tc_adjust_size(unsigned sz, unsigned mpu, enum link_layer linklayer)
+{
+	if (sz < mpu)
+		sz = mpu;
+
+	switch (linklayer) {
+	case LINKLAYER_ATM:
+		return tc_align_to_atm(sz);
+	case LINKLAYER_ETHERNET:
+	default:
+		// No size adjustments on Ethernet
+		return sz;
+	}
+}
+
 /*
    rtab[pkt_len>>cell_log] = pkt_xmit_time
  */
@@ -96,6 +111,7 @@ int tc_calc_rtable(struct tc_ratespec *r, __u32 *rtab,
 		   enum link_layer linklayer)
 {
 	int i;
+	unsigned sz;
 	unsigned bps = r->rate;
 	unsigned mpu = r->mpu;
 
@@ -109,21 +125,7 @@ int tc_calc_rtable(struct tc_ratespec *r, __u32 *rtab,
 	}
 
 	for (i=0; i<256; i++) {
-		unsigned sz = (i+1)<<cell_log;
-		if (sz < mpu)
-			sz = mpu;
-
-		switch (linklayer) {
-		case LINKLAYER_ATM:
-			sz = tc_align_to_atm(sz);
-			break;
-		case LINKLAYER_ETHERNET:
-			// No size adjustments on Ethernet
-			break;
-		default:
-			break;
-		}
-
+		sz = tc_adjust_size((i + 1) << cell_log, mpu, linklayer);
 		rtab[i] = tc_calc_xmittime(bps, sz);
 	}
 
@@ -132,6 +134,44 @@ int tc_calc_rtable(struct tc_ratespec *r, __u32 *rtab,
 	return cell_log;
 }
 
+/*
+   stab[pkt_len>>cell_log] = pkt_xmit_size>>size_log
+ */
+
+int tc_calc_stable(struct tc_sizespec *s, __u16 *stab,
+		   int cell_log, unsigned mtu,
+		   enum link_layer linklayer)
+{
+	int i;
+	unsigned mpu = s->mpu;
+	unsigned size_log = 0;
+	unsigned sz;
+
+	if (mtu == 0)
+		mtu = 2047;
+
+	if (cell_log < 0) {
+		cell_log = 0;
+		while ((mtu >> cell_log) > 512 - 1)
+			cell_log++;
+	}
+
+again:
+	for (i = 512 - 1; i >= 0; i--) {
+		sz = tc_adjust_size((i + 1) << cell_log, mpu, linklayer);
+		if ((sz >> size_log) > UINT16_MAX) {
+			size_log++;
+			goto again;
+		}
+		stab[i] = sz >> size_log;
+	}
+
+	s->size_log = size_log;
+	s->cell_align = -1; // Due to the sz calc
+	s->cell_log = cell_log;
+	return cell_log;
+}
+
 int tc_core_init()
 {
 	FILE *fp;
diff --git a/tc/tc_core.h b/tc/tc_core.h
index 9f835e8..97a4894 100644
--- a/tc/tc_core.h
+++ b/tc/tc_core.h
@@ -21,6 +21,8 @@ unsigned tc_calc_xmittime(unsigned rate, unsigned size);
 unsigned tc_calc_xmitsize(unsigned rate, unsigned ticks);
 int tc_calc_rtable(struct tc_ratespec *r, __u32 *rtab,
 		   int cell_log, unsigned mtu, enum link_layer link_layer);
+int tc_calc_stable(struct tc_sizespec *r, __u16 *stab,
+		   int cell_log, unsigned mtu, enum link_layer link_layer);
 
 int tc_setup_estimator(unsigned A, unsigned time_const, struct tc_estimator *est);
 


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* [PATCH v4 2/2] [iproute2/tc] hfsc: add link layer overhead adaption
  2008-07-10 19:34 [PATCH v4 1/2] [iproute2/tc] tc_core: add size table Jussi Kivilinna
@ 2008-07-10 19:34 ` Jussi Kivilinna
  0 siblings, 0 replies; 2+ messages in thread
From: Jussi Kivilinna @ 2008-07-10 19:34 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: netdev

Patch adds 'mpu', 'mtu', 'overhead' and 'linklayer' options to hfsc. These
options are used to create size table for sch_hfsc. Size table is only used
and passed to kernel if these options are used.

Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
---

 include/linux/pkt_sched.h |    5 +
 tc/q_hfsc.c               |  155 ++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 155 insertions(+), 5 deletions(-)

diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h
index 5bf1444..46db55d 100644
--- a/include/linux/pkt_sched.h
+++ b/include/linux/pkt_sched.h
@@ -303,6 +303,9 @@ struct tc_htb_xstats
 struct tc_hfsc_qopt
 {
 	__u16	defcls;		/* default class */
+	__u16	__reserved;
+	struct tc_sizespec szopts;
+	__u16	stab[512];
 };
 
 struct tc_service_curve
@@ -326,6 +329,8 @@ enum
 	TCA_HFSC_RSC,
 	TCA_HFSC_FSC,
 	TCA_HFSC_USC,
+	TCA_HFSC_SZOPTS,
+	TCA_HFSC_STAB,
 	__TCA_HFSC_MAX,
 };
 
diff --git a/tc/q_hfsc.c b/tc/q_hfsc.c
index b190c71..e8bff6e 100644
--- a/tc/q_hfsc.c
+++ b/tc/q_hfsc.c
@@ -12,6 +12,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <stddef.h>
 #include <unistd.h>
 #include <syslog.h>
 #include <fcntl.h>
@@ -24,6 +25,9 @@
 #include "utils.h"
 #include "tc_util.h"
 
+#define endof(type, member) \
+	(offsetof(type, member) + sizeof(((type *)0)->member))
+
 static int hfsc_get_sc(int *, char ***, struct tc_service_curve *);
 
 
@@ -31,7 +35,13 @@ static void
 explain_qdisc(void)
 {
 	fprintf(stderr,
-		"Usage: ... hfsc [ default CLASSID ]\n"
+		"Usage: ... hfsc [ default CLASSID ] [ mtu BYTES] [ mpu BYTES ]\n"
+		"                [ overhead BYTES ] [ linklayer TYPE ]\n"
+		"\n"
+		" mtu       : max packet size we create rate map for {2047}\n"
+		" mpu       : minimum packet size used in rate computations\n"
+		" overhead  : per-packet size overhead used in rate computations\n"
+		" linklayer : adapting to a linklayer e.g. atm\n"
 		"\n"
 		" default: default class for unclassified packets\n"
 	);
@@ -42,6 +52,13 @@ explain_class(void)
 {
 	fprintf(stderr,
 		"Usage: ... hfsc [ [ rt SC ] [ ls SC ] | [ sc SC ] ] [ ul SC ]\n"
+		"                [ mtu BYTES] [ mpu BYTES ] [ overhead BYTES ]\n"
+		"                [ linklayer TYPE ]\n"
+		"\n"
+		" mtu       : max packet size we create rate map for {2047}\n"
+		" mpu       : minimum packet size used in rate computations\n"
+		" overhead  : per-packet size overhead used in rate computations\n"
+		" linklayer : adapting to a linklayer e.g. atm\n"
 		"\n"
 		"SC := [ [ m1 BPS ] [ d SEC ] m2 BPS\n"
 		"\n"
@@ -67,14 +84,86 @@ explain1(char *arg)
 }
 
 static int
+hfsc_parse_stab(int *argcp, char ***argvp, unsigned *mtup,
+		unsigned int *linklayerp, short *overheadp,
+		unsigned short *mpup)
+{
+	char **argv = *argvp;
+	int argc = *argcp;
+	int next = 0;
+
+	if (matches(*argv, "mtu") == 0) {
+		NEXT_ARG();
+		if (get_u32(mtup, *argv, 10)) {
+			explain1("mtu");
+			return -1;
+		}
+	} else if (matches(*argv, "mpu") == 0) {
+		NEXT_ARG();
+		if (get_u16(mpup, *argv, 10)) {
+			explain1("mpu");
+			return -1;
+		}
+	} else if (matches(*argv, "overhead") == 0) {
+		NEXT_ARG();
+		if (get_s16(overheadp, *argv, 10)) {
+			explain1("overhead");
+			return -1;
+		}
+	} else if (matches(*argv, "linklayer") == 0) {
+		NEXT_ARG();
+		if (get_linklayer(linklayerp, *argv)) {
+			explain1("linklayer");
+			return -1;
+		}
+	} else {
+		next = 1;
+	}
+
+	*argvp = argv;
+	*argcp = argc;
+	return next;
+}
+
+static int
+hfsc_create_stab(struct tc_sizespec *szoptsp, __u16 *stabp, unsigned mtu,
+			unsigned int linklayer, short overhead,
+			unsigned short mpu)
+{
+	/* Only use stab when needed, mtu only defines stab properties so
+	 * it is not checked here. */
+	if (linklayer != LINKLAYER_ETHERNET || mpu != 0 || overhead != 0) {
+		szoptsp->mpu = mpu;
+		szoptsp->overhead = overhead;
+		if (tc_calc_stable(szoptsp, stabp, -1, mtu, linklayer) < 0) {
+			fprintf(stderr, "HFSC: failed to calculate size table.\n");
+			return -1;
+		}
+		return 1;
+	}
+	return 0;
+}
+
+static int
 hfsc_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n)
 {
 	struct tc_hfsc_qopt qopt;
+	unsigned qopt_len;
+	unsigned mtu = 0;
+	unsigned int linklayer = LINKLAYER_ETHERNET; /* Assume ethernet */
+	short overhead = 0;
+	unsigned short mpu = 0;
+	int use_stab, next;
 
 	memset(&qopt, 0, sizeof(qopt));
 
 	while (argc > 0) {
-		if (matches(*argv, "default") == 0) {
+		next = hfsc_parse_stab(&argc, &argv, &mtu, &linklayer,
+					&overhead, &mpu);
+		if (next != 1) {
+			if (next < 0)
+				return next;
+		} else if (matches(*argv, "default") == 0) {
 			NEXT_ARG();
 			if (qopt.defcls != 0) {
 				fprintf(stderr, "HFSC: Double \"default\"\n");
@@ -95,7 +184,15 @@ hfsc_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n)
 		argc--, argv++;
 	}
 
-	addattr_l(n, 1024, TCA_OPTIONS, &qopt, sizeof(qopt));
+	use_stab = hfsc_create_stab(&qopt.szopts, qopt.stab, mtu, linklayer,
+				overhead, mpu);
+	if (use_stab < 0)
+		return use_stab;
+	qopt_len = (use_stab > 0) ? endof(struct tc_hfsc_qopt, stab) :
+					endof(struct tc_hfsc_qopt, defcls);
+
+	addattr_l(n, 2024, TCA_OPTIONS, &qopt, qopt_len);
+
 	return 0;
 }
 
@@ -103,16 +200,27 @@ static int
 hfsc_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 {
 	struct tc_hfsc_qopt *qopt;
+	SPRINT_BUF(b1);
 
 	if (opt == NULL)
 		return 0;
-	if (RTA_PAYLOAD(opt) < sizeof(*qopt))
+	if (RTA_PAYLOAD(opt) < endof(struct tc_hfsc_qopt, defcls))
 		return -1;
 	qopt = RTA_DATA(opt);
 
 	if (qopt->defcls != 0)
 		fprintf(f, "default %x ", qopt->defcls);
 
+	if (show_details && RTA_PAYLOAD(opt) >=
+					endof(struct tc_hfsc_qopt, szopts)) {
+		if (qopt->szopts.mpu)
+			fprintf(f, "mpu %s ",
+				sprint_size(qopt->szopts.mpu, b1));
+		if (qopt->szopts.overhead)
+			fprintf(f, "overhead %s ",
+				sprint_size(qopt->szopts.overhead, b1));
+	}
+
 	return 0;
 }
 
@@ -145,14 +253,28 @@ hfsc_parse_class_opt(struct qdisc_util *qu, int argc, char **argv,
 	struct tc_service_curve rsc, fsc, usc;
 	int rsc_ok, fsc_ok, usc_ok;
 	struct rtattr *tail;
+	struct tc_sizespec szopts;
+	__u16 stab[512];
+	int use_stab, next;
+	unsigned mtu = 0;
+	unsigned int linklayer = LINKLAYER_ETHERNET; /* Assume ethernet */
+	short overhead = 0;
+	unsigned short mpu = 0;
 
 	memset(&rsc, 0, sizeof(rsc));
 	memset(&fsc, 0, sizeof(fsc));
 	memset(&usc, 0, sizeof(usc));
+	memset(&szopts, 0, sizeof(szopts));
+	memset(stab, 0, TCA_HFSC_STAB);
 	rsc_ok = fsc_ok = usc_ok = 0;
 
 	while (argc > 0) {
-		if (matches(*argv, "rt") == 0) {
+		next = hfsc_parse_stab(&argc, &argv, &mtu, &linklayer,
+					&overhead, &mpu);
+		if (next != 1) {
+			if (next < 0)
+				return next;
+		} else if (matches(*argv, "rt") == 0) {
 			NEXT_ARG();
 			if (hfsc_get_sc(&argc, &argv, &rsc) < 0) {
 				explain1("rt");
@@ -205,6 +327,10 @@ hfsc_parse_class_opt(struct qdisc_util *qu, int argc, char **argv,
 		return -1;
 	}
 
+	use_stab = hfsc_create_stab(&szopts, stab, mtu, linklayer, overhead, mpu);
+	if (use_stab < 0)
+		return use_stab;
+
 	tail = NLMSG_TAIL(n);
 
 	addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
@@ -214,6 +340,10 @@ hfsc_parse_class_opt(struct qdisc_util *qu, int argc, char **argv,
 		addattr_l(n, 1024, TCA_HFSC_FSC, &fsc, sizeof(fsc));
 	if (usc_ok)
 		addattr_l(n, 1024, TCA_HFSC_USC, &usc, sizeof(usc));
+	if (use_stab) {
+		addattr_l(n, 2024, TCA_HFSC_SZOPTS, &szopts, sizeof(szopts));
+		addattr_l(n, 3024, TCA_HFSC_STAB, stab, TC_STAB_SIZE);
+	}
 
 	tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
 	return 0;
@@ -235,6 +365,8 @@ hfsc_print_class_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 {
 	struct rtattr *tb[TCA_HFSC_MAX+1];
 	struct tc_service_curve *rsc = NULL, *fsc = NULL, *usc = NULL;
+	struct tc_sizespec *szopts = NULL;
+	SPRINT_BUF(b1);
 
 	if (opt == NULL)
 		return 0;
@@ -259,6 +391,12 @@ hfsc_print_class_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 		else
 			usc = RTA_DATA(tb[TCA_HFSC_USC]);
 	}
+	if (tb[TCA_HFSC_SZOPTS]) {
+		if (RTA_PAYLOAD(tb[TCA_HFSC_SZOPTS]) < sizeof(*szopts))
+			fprintf(stderr, "HFSC: truncated rate options\n");
+		else
+			szopts = RTA_DATA(tb[TCA_HFSC_SZOPTS]);
+	}
 
 
 	if (rsc != NULL && fsc != NULL &&
@@ -273,6 +411,13 @@ hfsc_print_class_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 	if (usc != NULL)
 		hfsc_print_sc(f, "ul", usc);
 
+	if (szopts != NULL && show_details) {
+		if (szopts->mpu)
+			fprintf(f, "mpu %s ", sprint_size(szopts->mpu, b1));
+		if (szopts->overhead)
+			fprintf(f, "overhead %s ", sprint_size(szopts->overhead, b1));
+	}
+
 	return 0;
 }
 


^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2008-07-10 19:34 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-07-10 19:34 [PATCH v4 1/2] [iproute2/tc] tc_core: add size table Jussi Kivilinna
2008-07-10 19:34 ` [PATCH v4 2/2] [iproute2/tc] hfsc: add link layer overhead adaption Jussi Kivilinna

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).