diff options
author | Kozlov Dmitry <xeb@mail.ru> | 2012-05-15 23:49:48 +0400 |
---|---|---|
committer | Kozlov Dmitry <xeb@mail.ru> | 2012-05-15 23:49:48 +0400 |
commit | d669038e70d2e3690423792e63b8179e44a7a340 (patch) | |
tree | 18dfc9e4ddcc9d11f0ff0b8cb9a82e4bb795af52 | |
parent | 6efad618371915bf0b402f26117a02ad53aaeb20 (diff) | |
download | accel-ppp-d669038e70d2e3690423792e63b8179e44a7a340.tar.gz accel-ppp-d669038e70d2e3690423792e63b8179e44a7a340.zip |
shaper: implemented leaf qdisc attachment
-rw-r--r-- | accel-pppd/accel-ppp.conf | 1 | ||||
-rw-r--r-- | accel-pppd/accel-ppp.conf.5 | 4 | ||||
-rw-r--r-- | accel-pppd/extra/ippool.c | 14 | ||||
-rw-r--r-- | accel-pppd/shaper/CMakeLists.txt | 2 | ||||
-rw-r--r-- | accel-pppd/shaper/leaf_qdisc.c | 186 | ||||
-rw-r--r-- | accel-pppd/shaper/libnetlink.h | 3 | ||||
-rw-r--r-- | accel-pppd/shaper/limiter.c | 28 | ||||
-rw-r--r-- | accel-pppd/shaper/shaper.c | 12 | ||||
-rw-r--r-- | accel-pppd/shaper/shaper.h | 27 |
9 files changed, 251 insertions, 26 deletions
diff --git a/accel-pppd/accel-ppp.conf b/accel-pppd/accel-ppp.conf index da56dae8..d055c590 100644 --- a/accel-pppd/accel-ppp.conf +++ b/accel-pppd/accel-ppp.conf @@ -158,6 +158,7 @@ gw-ip-address=192.168.100.1 #ifb=ifb0 up-limiter=police down-limiter=tbf +#leaf-qdisc=sfq perturb 10 verbose=1 #tbf is obsolete, use shaper module diff --git a/accel-pppd/accel-ppp.conf.5 b/accel-pppd/accel-ppp.conf.5 index 71163db1..3a1efa7c 100644 --- a/accel-pppd/accel-ppp.conf.5 +++ b/accel-pppd/accel-ppp.conf.5 @@ -576,3 +576,7 @@ Specifes upstream rate limiting method. .TP .BI "down-limiter=" tbf|htb Specifies downstream rate limiting method. +.TP +.BI "leaf-qdisc=" "qdisc parameters" +In case if htb is used as up-limiter or down-limiter specified leaf qdisc can be attached automaticaly. +At present on sfq qdisc is implemented. Parameters are same as for tc: [ limit NUMBER ] [ perturn SECS ] [ quantum BYTES ]. diff --git a/accel-pppd/extra/ippool.c b/accel-pppd/extra/ippool.c index 7117c3e2..f18aa050 100644 --- a/accel-pppd/extra/ippool.c +++ b/accel-pppd/extra/ippool.c @@ -325,11 +325,12 @@ static void ippool_init(void) list_for_each_entry(opt, &s->items, entry) { #ifdef RADIUS - if (!strcmp(opt->name, "vendor")) - conf_vendor = parse_vendor_opt(opt->val); - else if (!strcmp(opt->name, "attr")) - conf_attr = parse_attr_opt(opt->val); - else + if (triton_module_loaded("radius")) { + if (!strcmp(opt->name, "vendor")) + conf_vendor = parse_vendor_opt(opt->val); + else if (!strcmp(opt->name, "attr")) + conf_attr = parse_attr_opt(opt->val); + } else #endif if (!strcmp(opt->name, "gw-ip-address")) parse_gw_ip_address(opt->val); @@ -358,7 +359,8 @@ static void ippool_init(void) ipdb_register(&ipdb); #ifdef RADIUS - triton_event_register_handler(EV_RADIUS_ACCESS_ACCEPT, (triton_event_func)ev_radius_access_accept); + if (triton_module_loaded("radius")) + triton_event_register_handler(EV_RADIUS_ACCESS_ACCEPT, (triton_event_func)ev_radius_access_accept); #endif } diff --git a/accel-pppd/shaper/CMakeLists.txt b/accel-pppd/shaper/CMakeLists.txt index abfd8ecb..515fd839 100644 --- a/accel-pppd/shaper/CMakeLists.txt +++ b/accel-pppd/shaper/CMakeLists.txt @@ -1,4 +1,4 @@ -ADD_LIBRARY(shaper SHARED shaper.c limiter.c tc_core.c libnetlink.c) +ADD_LIBRARY(shaper SHARED shaper.c limiter.c leaf_qdisc.c tc_core.c libnetlink.c) INSTALL(TARGETS shaper LIBRARY DESTINATION lib/accel-ppp diff --git a/accel-pppd/shaper/leaf_qdisc.c b/accel-pppd/shaper/leaf_qdisc.c new file mode 100644 index 00000000..51b8c8d7 --- /dev/null +++ b/accel-pppd/shaper/leaf_qdisc.c @@ -0,0 +1,186 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <sys/ioctl.h> +#include <linux/if.h> +#include <linux/if_ether.h> +#include <linux/pkt_cls.h> +#include <linux/pkt_sched.h> +#include <linux/tc_act/tc_mirred.h> +#include <linux/tc_act/tc_skbedit.h> + +#include "log.h" +#include "ppp.h" + +#include "shaper.h" +#include "tc_core.h" +#include "libnetlink.h" + +static int parse_size(const char *str, int *r) +{ + double sz; + char *endptr; + + sz = strtod(str, &endptr); + + if (endptr == str) + return -1; + + if (*endptr == 0) { + *r = sz; + return 0; + } + + if (strcmp(endptr, "kb") == 0 || strcmp(endptr, "k") == 0) + *r = sz * 1024; + else if (strcmp(endptr, "mb") == 0 || strcmp(endptr, "m") == 0) + *r = sz * 1024 * 1024; + else if (strcmp(endptr, "gb") == 0 || strcmp(endptr, "g") == 0) + *r = sz * 1024 * 1024 * 1024; + else if (strcmp(endptr, "kbit") == 0) + *r = sz * 1024 / 8; + else if (strcmp(endptr, "mbit") == 0) + *r = sz * 1024 * 1024 / 8; + else if (strcmp(endptr, "gbit") == 0) + *r = sz * 1024 * 1024 * 1024 / 8; + else if (strcmp(endptr, "b") == 0) + *r = sz; + else + return -1; + + return 0; +} + +static int parse_int(const char *str, int *r) +{ + char *endptr; + + *r = strtol(str, &endptr, 10); + + return *endptr != 0; +} + +static int parse_u32(const char *str, int *r) +{ + char *endptr; + + *r = strtol(str, &endptr, 10); + + return *endptr != 0 || *r < 0; +} + +static int parse_sfq(char *str) +{ + char *ptr1, *ptr2; + + 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, "quantum") == 0) { + if (parse_size(ptr1, &conf_lq_arg1)) + return -1; + } else if (strcmp(str, "perturb") == 0) { + if (parse_int(ptr1, &conf_lq_arg2)) + return -1; + } else if (strcmp(str, "limit") == 0) { + if (parse_u32(ptr1, &conf_lq_arg3)) + return -1; + } else + return -1; + + if (*ptr2 == 0) + break; + + str = ptr2; + } + +out: + conf_leaf_qdisc = LEAF_QDISC_SFQ; + + return 0; +} + +void leaf_qdisc_parse(const char *opt) +{ + char *ptr1; + char *str = strdup(opt); + + for (ptr1 = str; *ptr1 && *ptr1 != ' '; ptr1++); + + if (*ptr1) { + *ptr1 = 0; + for (ptr1++; *ptr1 && *ptr1 == ' '; ptr1++); + } + + if (strcmp(str, "sfq") == 0) { + if (parse_sfq(ptr1)) + goto out_err; + } else + log_emerg("shaper: unknown leaf-qdisc '%s'\n", str); + + free(str); + + return; +out_err: + log_emerg("shaper: failed to parse '%s'\n", opt); +} + +static int qdisc_sfq(struct qdisc_opt *qopt, struct nlmsghdr *n) +{ + struct tc_sfq_qopt opt = { + .quantum = conf_lq_arg1, + .perturb_period = conf_lq_arg2, + .limit = conf_lq_arg3, + }; + + addattr_l(n, 1024, TCA_OPTIONS, &opt, sizeof(opt)); + + return 0; +} + +static int install_sfq(struct rtnl_handle *rth, int ifindex, int parent, int handle) +{ + struct qdisc_opt opt = { + .kind = "sfq", + .handle = handle, + .parent = parent, + .qdisc = qdisc_sfq, + }; + + 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); + + return 0; +} + diff --git a/accel-pppd/shaper/libnetlink.h b/accel-pppd/shaper/libnetlink.h index 63ba5ad1..f68bf8a1 100644 --- a/accel-pppd/shaper/libnetlink.h +++ b/accel-pppd/shaper/libnetlink.h @@ -8,6 +8,9 @@ #include <linux/if_addr.h> #include <linux/neighbour.h> +#define TCA_BUF_MAX 64*1024 +#define MAX_MSG 16384 + struct rtnl_handle { int fd; diff --git a/accel-pppd/shaper/limiter.c b/accel-pppd/shaper/limiter.c index f368b331..92e343b7 100644 --- a/accel-pppd/shaper/limiter.c +++ b/accel-pppd/shaper/limiter.c @@ -21,22 +21,6 @@ #include "tc_core.h" #include "libnetlink.h" -#define TCA_BUF_MAX 64*1024 -#define MAX_MSG 16384 - -struct qdisc_opt -{ - char *kind; - int handle; - int parent; - double latency; - int rate; - int buffer; - int quantum; - int defcls; - int (*qdisc)(struct qdisc_opt *opt, struct nlmsghdr *n); -}; - static int qdisc_tbf(struct qdisc_opt *qopt, struct nlmsghdr *n) { struct tc_tbf_qopt opt; @@ -121,7 +105,7 @@ static int qdisc_htb_class(struct qdisc_opt *qopt, struct nlmsghdr *n) return 0; } -static int tc_qdisc_modify(struct rtnl_handle *rth, int ifindex, int cmd, unsigned flags, struct qdisc_opt *opt) +int tc_qdisc_modify(struct rtnl_handle *rth, int ifindex, int cmd, unsigned flags, struct qdisc_opt *opt) { struct { struct nlmsghdr n; @@ -446,13 +430,19 @@ int install_limiter(struct ppp_t *ppp, int down_speed, int down_burst, int up_sp if (conf_down_limiter == LIM_TBF) r = install_tbf(&rth, ppp->ifindex, down_speed, down_burst); - else + else { r = install_htb(&rth, ppp->ifindex, down_speed, down_burst); + if (r == 0) + r = install_leaf_qdisc(&rth, ppp->ifindex, 0x00010001, 0x00020000); + } if (conf_up_limiter == LIM_POLICE) r = install_police(&rth, ppp->ifindex, up_speed, up_burst); - else + else { r = install_htb_ifb(&rth, ppp->ifindex, ppp->unit_idx + 1, up_speed, up_burst); + if (r == 0) + r = install_leaf_qdisc(&rth, conf_ifb_ifindex, 0x00010001 + ppp->unit_idx + 1, (1 + ppp->unit_idx + 1) << 16); + } rtnl_close(&rth); diff --git a/accel-pppd/shaper/shaper.c b/accel-pppd/shaper/shaper.c index 0ea2e373..8ae2630a 100644 --- a/accel-pppd/shaper/shaper.c +++ b/accel-pppd/shaper/shaper.c @@ -44,6 +44,11 @@ int conf_ifb_ifindex; int conf_up_limiter = LIM_POLICE; int conf_down_limiter = LIM_TBF; +int conf_leaf_qdisc; +int conf_lq_arg1; +int conf_lq_arg2; +int conf_lq_arg3; + static int temp_down_speed; static int temp_up_speed; @@ -895,6 +900,13 @@ static void load_config(void) conf_up_limiter = LIM_POLICE; } + opt = conf_get_opt("shaper", "leaf-qdisc"); + if (opt) + leaf_qdisc_parse(opt); + else + conf_leaf_qdisc = 0; + + opt = conf_get_opt("shaper", "verbose"); if (opt && atoi(opt) > 0) conf_verbose = 1; diff --git a/accel-pppd/shaper/shaper.h b/accel-pppd/shaper/shaper.h index bd2a718c..41e6e437 100644 --- a/accel-pppd/shaper/shaper.h +++ b/accel-pppd/shaper/shaper.h @@ -5,6 +5,24 @@ #define LIM_TBF 1 #define LIM_HTB 2 +#define LEAF_QDISC_SFQ 1 + +struct rtnl_handle; +struct nlmsghdr; + +struct qdisc_opt +{ + char *kind; + int handle; + int parent; + double latency; + int rate; + int buffer; + int quantum; + int defcls; + int (*qdisc)(struct qdisc_opt *opt, struct nlmsghdr *n); +}; + extern int conf_up_limiter; extern int conf_down_limiter; @@ -16,9 +34,18 @@ extern int conf_quantum; extern int conf_r2q; extern int conf_cburst; extern int conf_ifb_ifindex; +extern int conf_leaf_qdisc; +extern int conf_lq_arg1; +extern int conf_lq_arg2; +extern int conf_lq_arg3; int install_limiter(struct ppp_t *ppp, int down_speed, int down_burst, int up_speed, int up_burst); int remove_limiter(struct ppp_t *ppp); +int install_leaf_qdisc(struct rtnl_handle *rth, int ifindex, int parent, int handle); int init_ifb(const char *); +void leaf_qdisc_parse(const char *); + +int tc_qdisc_modify(struct rtnl_handle *rth, int ifindex, int cmd, unsigned flags, struct qdisc_opt *opt); + #endif |