summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey V. Lobanov <sergey@lobanov.in>2024-04-11 01:27:18 +0200
committerSergey V. Lobanov <sergey@lobanov.in>2024-04-11 09:40:10 +0200
commit3ec2d773950ed9730467062ebd4eeec5e9d8b35c (patch)
tree6aedeb28cef8772363fb1e387e9bcf9ed0785773
parent3668336266cb74b6d37e5b56c9c5b74761a868fc (diff)
downloadaccel-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--README4
-rw-r--r--accel-pppd/accel-ppp.conf.54
-rw-r--r--accel-pppd/shaper/limiter.c97
-rw-r--r--accel-pppd/shaper/shaper.c2
-rw-r--r--accel-pppd/shaper/shaper.h1
5 files changed, 101 insertions, 7 deletions
diff --git a/README b/README
index 6498d803..143c5e13 100644
--- a/README
+++ b/README
@@ -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