summaryrefslogtreecommitdiff
path: root/accel-pppd/shaper
diff options
context:
space:
mode:
authorDmitry Kozlov <xeb@mail.ru>2014-09-13 10:49:16 +0400
committerDmitry Kozlov <xeb@mail.ru>2014-09-13 10:49:16 +0400
commit8e4a659d3830f83216308e5203933af2c4c72a19 (patch)
tree45d1413d94df3f47672d2027218a908fcdd649ab /accel-pppd/shaper
parent292439d2e4e7a02a33a621dbb24e0a25490d3ebf (diff)
downloadaccel-ppp-8e4a659d3830f83216308e5203933af2c4c72a19.tar.gz
accel-ppp-8e4a659d3830f83216308e5203933af2c4c72a19.zip
shaper: implemented fq_codel leaf qdisc
Parameters are same as for tc: [shaper] leaf-qdisc=fq_codel [ limit PACKETS ] [flows NUMBER ] [ target TIME ] [ interval TIME ] [ quantum BYTES ] [ [no]ecn ]
Diffstat (limited to 'accel-pppd/shaper')
-rw-r--r--accel-pppd/shaper/leaf_qdisc.c133
-rw-r--r--accel-pppd/shaper/shaper.c3
-rw-r--r--accel-pppd/shaper/shaper.h4
3 files changed, 140 insertions, 0 deletions
diff --git a/accel-pppd/shaper/leaf_qdisc.c b/accel-pppd/shaper/leaf_qdisc.c
index 51b8c8d7..4240a344 100644
--- a/accel-pppd/shaper/leaf_qdisc.c
+++ b/accel-pppd/shaper/leaf_qdisc.c
@@ -56,6 +56,34 @@ static int parse_size(const char *str, int *r)
return 0;
}
+static int parse_time(const char *str, int *r)
+{
+ double t;
+ char *endptr;
+
+ t = strtod(str, &endptr);
+
+ if (endptr == str)
+ return -1;
+
+ if (*endptr == 0) {
+ *r = t;
+ return 0;
+ }
+
+ if (strcmp(endptr, "s") == 0 || strcmp(endptr, "sec") == 0)
+ *r = t * TIME_UNITS_PER_SEC;
+ else if (strcmp(endptr, "ms") == 0 || strcmp(endptr, "msec") == 0)
+ *r = t * TIME_UNITS_PER_SEC/1000;
+ else if (strcmp(endptr, "us") == 0 || strcmp(endptr, "usec") == 0)
+ *r = t * TIME_UNITS_PER_SEC/1000000;
+ else
+ return -1;
+
+ return 0;
+}
+
+
static int parse_int(const char *str, int *r)
{
char *endptr;
@@ -125,6 +153,70 @@ out:
return 0;
}
+static int parse_fq_codel(char *str)
+{
+ char *ptr1, *ptr2;
+
+ conf_lq_arg6 = -1;
+
+ if (!*str)
+ goto out;
+
+ while (1) {
+ for (ptr1 = str + 1; *ptr1 && *ptr1 != ' '; ptr1++);
+
+ if (!*ptr1)
+ return -1;
+
+ *ptr1 = 0;
+
+ for (ptr1++; *ptr1 && *ptr1 == ' '; ptr1++);
+
+ if (!*ptr1)
+ return -1;
+
+ for (ptr2 = ptr1 + 1; *ptr2 && *ptr2 != ' '; ptr2++);
+
+ if (*ptr2) {
+ *ptr2 = 0;
+ for (ptr2++; *ptr2 && *ptr2 == ' '; ptr2++);
+ }
+
+ if (strcmp(str, "limit") == 0) {
+ if (parse_u32(ptr1, &conf_lq_arg1))
+ return -1;
+ } else if (strcmp(str, "flows") == 0) {
+ if (parse_u32(ptr1, &conf_lq_arg2))
+ return -1;
+ } else if (strcmp(str, "quantum") == 0) {
+ if (parse_u32(ptr1, &conf_lq_arg3))
+ return -1;
+ } else if (strcmp(str, "target") == 0) {
+ if (parse_time(ptr1, &conf_lq_arg4))
+ return -1;
+ } else if (strcmp(str, "interval") == 0) {
+ if (parse_time(ptr1, &conf_lq_arg5))
+ return -1;
+ } else if (strcmp(str, "ecn") == 0) {
+ conf_lq_arg6 = 1;
+ } else if (strcmp(str, "noecn") == 0) {
+ conf_lq_arg6 = 0;
+ } else
+ return -1;
+
+ if (*ptr2 == 0)
+ break;
+
+ str = ptr2;
+ }
+
+out:
+ conf_leaf_qdisc = LEAF_QDISC_FQ_CODEL;
+
+ return 0;
+}
+
+
void leaf_qdisc_parse(const char *opt)
{
char *ptr1;
@@ -140,6 +232,9 @@ void leaf_qdisc_parse(const char *opt)
if (strcmp(str, "sfq") == 0) {
if (parse_sfq(ptr1))
goto out_err;
+ } if (strcmp(str, "fq_codel") == 0) {
+ if (parse_fq_codel(ptr1))
+ goto out_err;
} else
log_emerg("shaper: unknown leaf-qdisc '%s'\n", str);
@@ -175,12 +270,50 @@ static int install_sfq(struct rtnl_handle *rth, int ifindex, int parent, int han
return tc_qdisc_modify(rth, ifindex, RTM_NEWQDISC, NLM_F_EXCL|NLM_F_CREATE, &opt);
}
+static int qdisc_fq_codel(struct qdisc_opt *qopt, struct nlmsghdr *n)
+{
+ struct rtattr *tail = NLMSG_TAIL(n);
+
+ addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
+
+ if (conf_lq_arg1)
+ addattr_l(n, 1024, TCA_FQ_CODEL_LIMIT, &conf_lq_arg1, sizeof(conf_lq_arg1));
+ if (conf_lq_arg2)
+ addattr_l(n, 1024, TCA_FQ_CODEL_FLOWS, &conf_lq_arg2, sizeof(conf_lq_arg2));
+ if (conf_lq_arg3)
+ addattr_l(n, 1024, TCA_FQ_CODEL_QUANTUM, &conf_lq_arg3, sizeof(conf_lq_arg3));
+ if (conf_lq_arg4)
+ addattr_l(n, 1024, TCA_FQ_CODEL_INTERVAL, &conf_lq_arg4, sizeof(conf_lq_arg4));
+ if (conf_lq_arg5)
+ addattr_l(n, 1024, TCA_FQ_CODEL_TARGET, &conf_lq_arg5, sizeof(conf_lq_arg5));
+ if (conf_lq_arg6 != -1)
+ addattr_l(n, 1024, TCA_FQ_CODEL_ECN, &conf_lq_arg6, sizeof(conf_lq_arg6));
+
+ tail->rta_len = (void *)NLMSG_TAIL(n) - (void *)tail;
+
+ return 0;
+}
+
+static int install_fq_codel(struct rtnl_handle *rth, int ifindex, int parent, int handle)
+{
+ struct qdisc_opt opt = {
+ .kind = "fq_codel",
+ .handle = handle,
+ .parent = parent,
+ .qdisc = qdisc_fq_codel,
+ };
+
+ return tc_qdisc_modify(rth, ifindex, RTM_NEWQDISC, NLM_F_EXCL|NLM_F_CREATE, &opt);
+}
int install_leaf_qdisc(struct rtnl_handle *rth, int ifindex, int parent, int handle)
{
if (conf_leaf_qdisc == LEAF_QDISC_SFQ)
return install_sfq(rth, ifindex, parent, handle);
+ if (conf_leaf_qdisc == LEAF_QDISC_FQ_CODEL)
+ return install_fq_codel(rth, ifindex, parent, handle);
+
return 0;
}
diff --git a/accel-pppd/shaper/shaper.c b/accel-pppd/shaper/shaper.c
index c27ec72e..40677de8 100644
--- a/accel-pppd/shaper/shaper.c
+++ b/accel-pppd/shaper/shaper.c
@@ -50,6 +50,9 @@ int conf_leaf_qdisc;
int conf_lq_arg1;
int conf_lq_arg2;
int conf_lq_arg3;
+int conf_lq_arg4;
+int conf_lq_arg5;
+int conf_lq_arg6;
static int temp_down_speed;
static int temp_up_speed;
diff --git a/accel-pppd/shaper/shaper.h b/accel-pppd/shaper/shaper.h
index 4e6b9ff1..946c9918 100644
--- a/accel-pppd/shaper/shaper.h
+++ b/accel-pppd/shaper/shaper.h
@@ -6,6 +6,7 @@
#define LIM_HTB 2
#define LEAF_QDISC_SFQ 1
+#define LEAF_QDISC_FQ_CODEL 2
struct rtnl_handle;
struct nlmsghdr;
@@ -39,6 +40,9 @@ extern int conf_leaf_qdisc;
extern int conf_lq_arg1;
extern int conf_lq_arg2;
extern int conf_lq_arg3;
+extern int conf_lq_arg4;
+extern int conf_lq_arg5;
+extern int conf_lq_arg6;
int install_limiter(struct ap_session *ses, int down_speed, int down_burst, int up_speed, int up_burst);
int remove_limiter(struct ap_session *ses);