diff options
author | Dmitry Kozlov <xeb@mail.ru> | 2014-09-13 10:49:16 +0400 |
---|---|---|
committer | Dmitry Kozlov <xeb@mail.ru> | 2014-09-13 10:49:16 +0400 |
commit | 8e4a659d3830f83216308e5203933af2c4c72a19 (patch) | |
tree | 45d1413d94df3f47672d2027218a908fcdd649ab /accel-pppd/shaper | |
parent | 292439d2e4e7a02a33a621dbb24e0a25490d3ebf (diff) | |
download | accel-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.c | 133 | ||||
-rw-r--r-- | accel-pppd/shaper/shaper.c | 3 | ||||
-rw-r--r-- | accel-pppd/shaper/shaper.h | 4 |
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); |