diff options
author | Sergey V. Lobanov <sergey@lobanov.in> | 2024-04-11 01:27:18 +0200 |
---|---|---|
committer | Sergey V. Lobanov <sergey@lobanov.in> | 2024-04-11 09:40:10 +0200 |
commit | 3ec2d773950ed9730467062ebd4eeec5e9d8b35c (patch) | |
tree | 6aedeb28cef8772363fb1e387e9bcf9ed0785773 | |
parent | 3668336266cb74b6d37e5b56c9c5b74761a868fc (diff) | |
download | accel-ppp-3ec2d773950ed9730467062ebd4eeec5e9d8b35c.tar.gz accel-ppp-3ec2d773950ed9730467062ebd4eeec5e9d8b35c.zip |
shaper: add clsact policer support
Use the following configuration to enable clsact up and down limiters:
[shaper]
up-limiter=police
down-limiter=clsact
It is also recommended to set down-burst-factor=1.0
How to check current configuration in Linux:
tc qdisc show dev ppp0
tc filter show dev ppp0 egress
tc filter show dev ppp0 ingress
Signed-off-by: Sergey V. Lobanov <sergey@lobanov.in>
-rw-r--r-- | README | 4 | ||||
-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 |
5 files changed, 101 insertions, 7 deletions
@@ -21,7 +21,7 @@ Features 11. Extensible user/password database, implemented Radius, pppd compatible chap-secrets sources 12. Extensible IP pool, implemented Radius, chap-secrets and static pools 13. Supported pppd compatible ip-up/ip-down scripts -14. Builtin tbf/htb shaper manager +14. Builtin tbf/htb shaper and clsact policer manager 15. Command line interface via telnet 16. SNMP support (master or subagent via AgentX) 17. Supported SSTP @@ -68,7 +68,7 @@ read man accel-ppp.conf Built-in shaper -------------- -accel-ppp supports tbf and htb based shaper manager. +accel-ppp supports tbf and htb based shaper manager. It also supports clsact policer manager. To enable it uncomment shaper in [modules] section. It accepts radius attributes in various formats: rate, down-rate/up-rate and cisco-like. Values have to be in kilobits except cisco-like. For example: 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 |