From: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
To: Patrick McHardy <kaber@trash.net>
Cc: netdev@vger.kernel.org
Subject: [PATCH v4 2/2] [iproute2/tc] hfsc: add link layer overhead adaption
Date: Thu, 10 Jul 2008 22:34:54 +0300 [thread overview]
Message-ID: <20080710193454.19601.97736.stgit@fate.lan> (raw)
In-Reply-To: <20080710193448.19601.673.stgit@fate.lan>
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;
}
prev parent reply other threads:[~2008-07-10 19:34 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
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 [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20080710193454.19601.97736.stgit@fate.lan \
--to=jussi.kivilinna@mbnet.fi \
--cc=kaber@trash.net \
--cc=netdev@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.