diff options
Diffstat (limited to 'accel-pppd')
-rw-r--r-- | accel-pppd/accel-ppp.conf.5 | 4 | ||||
-rw-r--r-- | accel-pppd/shaper/limiter.c | 97 | ||||
-rw-r--r-- | accel-pppd/shaper/shaper.c | 2 | ||||
-rw-r--r-- | accel-pppd/shaper/shaper.h | 1 |
4 files changed, 99 insertions, 5 deletions
diff --git a/accel-pppd/accel-ppp.conf.5 b/accel-pppd/accel-ppp.conf.5 index 93856fae..1086a4ce 100644 --- a/accel-pppd/accel-ppp.conf.5 +++ b/accel-pppd/accel-ppp.conf.5 @@ -1231,8 +1231,8 @@ Specifies the fwmark for traffic that won't be passed through shaper. .BI "up-limiter=" police|htb Specifes upstream rate limiting method. .TP -.BI "down-limiter=" tbf|htb -Specifies downstream rate limiting method. +.BI "down-limiter=" tbf|htb|clsact +Specifies downstream rate limiting method. \fIclsact\fR is a policer .TP .BI "leaf-qdisc=" "qdisc parameters" In case if htb is used as up-limiter or down-limiter specified leaf qdisc can be attached automatically. diff --git a/accel-pppd/shaper/limiter.c b/accel-pppd/shaper/limiter.c index 2189fca4..423b9969 100644 --- a/accel-pppd/shaper/limiter.c +++ b/accel-pppd/shaper/limiter.c @@ -146,6 +146,91 @@ int tc_qdisc_modify(struct rtnl_handle *rth, int ifindex, int cmd, unsigned flag return 0; } +static int install_police_clsact(struct rtnl_handle *rth, int ifindex, int rate, int burst, int direction) +{ + __u32 rtab[256]; + struct rtattr *tail, *tail1, *tail2, *tail3; + int Rcell_log = -1; + int mtu = conf_mtu; + unsigned int linklayer = LINKLAYER_ETHERNET; /* Assume ethernet */ + + struct { + struct nlmsghdr n; + struct tcmsg t; + char buf[TCA_BUF_MAX]; + } req; + + struct tc_police police = { + .action = TC_POLICE_SHOT, + .rate.rate = rate, + .rate.mpu = conf_mpu, + .limit = (double)rate * conf_latency + burst, + .burst = tc_calc_xmittime(rate, burst), + }; + + if (tc_calc_rtable(&police.rate, rtab, Rcell_log, mtu, linklayer) < 0) { + log_ppp_error("shaper: failed to calculate ceil rate table.\n"); + return -1; + } + + memset(&req, 0, sizeof(req)); + + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg)); + req.n.nlmsg_flags = NLM_F_REQUEST|NLM_F_EXCL|NLM_F_CREATE; + req.n.nlmsg_type = RTM_NEWTFILTER; + req.t.tcm_family = AF_UNSPEC; + req.t.tcm_ifindex = ifindex; + req.t.tcm_handle = 0x1; + req.t.tcm_parent = TC_H_MAKE(TC_H_CLSACT, direction); + + + req.t.tcm_info = TC_H_MAKE(100 << 16, ntohs(ETH_P_ALL)); + + addattr_l(&req.n, sizeof(req), TCA_KIND, "matchall", 9); + + tail = NLMSG_TAIL(&req.n); + addattr_l(&req.n, MAX_MSG, TCA_OPTIONS, NULL, 0); + + tail1 = NLMSG_TAIL(&req.n); + addattr_l(&req.n, MAX_MSG, TCA_FW_POLICE, NULL, 0); + + tail2 = NLMSG_TAIL(&req.n); + addattr_l(&req.n, MAX_MSG, 1, NULL, 0); + addattr_l(&req.n, MAX_MSG, TCA_ACT_KIND, "police", 7); + + tail3 = NLMSG_TAIL(&req.n); + addattr_l(&req.n, MAX_MSG, TCA_ACT_OPTIONS, NULL, 0); + addattr_l(&req.n, MAX_MSG, TCA_POLICE_TBF, &police, sizeof(police)); + addattr_l(&req.n, MAX_MSG, TCA_POLICE_RATE, rtab, 1024); + tail3->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)tail3; + + tail2->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)tail2; + + tail1->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)tail1; + + tail->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)tail; + + if (rtnl_talk(rth, &req.n, 0, 0, NULL, NULL, NULL, 0) < 0) + return -1; + + return 0; +} + +static int install_clsact(struct rtnl_handle *rth, int ifindex, int rate, int burst) +{ + struct qdisc_opt opt = { + .kind = "clsact", + .handle = TC_H_MAKE(TC_H_CLSACT, 0), + .parent = TC_H_CLSACT, + }; + + if (tc_qdisc_modify(rth, ifindex, RTM_NEWQDISC, NLM_F_EXCL|NLM_F_CREATE, &opt)) { + return -1; + } + + return install_police_clsact(rth, ifindex, rate, burst, TC_H_MIN_EGRESS); +} + static int install_tbf(struct rtnl_handle *rth, int ifindex, int rate, int burst) { struct qdisc_opt opt = { @@ -469,6 +554,8 @@ int install_limiter(struct ap_session *ses, int down_speed, int down_burst, int if (conf_down_limiter == LIM_TBF) r = install_tbf(rth, ses->ifindex, down_speed, down_burst); + else if (conf_down_limiter == LIM_CLSACT) + r = install_clsact(rth, ses->ifindex, down_speed, down_burst); else { r = install_htb(rth, ses->ifindex, down_speed, down_burst); if (r == 0) @@ -480,9 +567,13 @@ int install_limiter(struct ap_session *ses, int down_speed, int down_burst, int up_speed = up_speed * 1000 / 8; up_burst = up_burst ? up_burst : conf_up_burst_factor * up_speed; - if (conf_up_limiter == LIM_POLICE) - r = install_police(rth, ses->ifindex, up_speed, up_burst); - else { + if (conf_up_limiter == LIM_POLICE) { + /* if clsact is used for down_limiter then normal policer doesn't work, use clsact version */ + if (conf_down_limiter == LIM_CLSACT && down_speed) + r = install_police_clsact(rth, ses->ifindex, up_speed, up_burst, TC_H_MIN_INGRESS); + else + r = install_police(rth, ses->ifindex, up_speed, up_burst); + } else { r = install_htb_ifb(rth, ses->ifindex, idx, up_speed, up_burst); if (r == 0) r = install_leaf_qdisc(rth, conf_ifb_ifindex, 0x00010000 + idx, idx << 16); diff --git a/accel-pppd/shaper/shaper.c b/accel-pppd/shaper/shaper.c index 69555318..3c2a1da6 100644 --- a/accel-pppd/shaper/shaper.c +++ b/accel-pppd/shaper/shaper.c @@ -1150,6 +1150,8 @@ static void load_config(void) conf_down_limiter = LIM_TBF; else if (!strcmp(opt, "htb")) conf_down_limiter = LIM_HTB; + else if (!strcmp(opt, "clsact")) + conf_down_limiter = LIM_CLSACT; else log_error("shaper: unknown downstream limiter '%s'\n", opt); } diff --git a/accel-pppd/shaper/shaper.h b/accel-pppd/shaper/shaper.h index 1b1e885e..d8f3618a 100644 --- a/accel-pppd/shaper/shaper.h +++ b/accel-pppd/shaper/shaper.h @@ -4,6 +4,7 @@ #define LIM_POLICE 0 #define LIM_TBF 1 #define LIM_HTB 2 +#define LIM_CLSACT 3 #define LEAF_QDISC_SFQ 1 #define LEAF_QDISC_FQ_CODEL 2 |