police: add support for packet-per-second rate limiting

Allow a policer action to enforce a rate-limit based on packets-per-second,
configurable using a packet-per-second rate and burst parameters.

e.g.
 # $TC actions add action police pkts_rate 1000 pkts_burst 200 index 1
 # $TC actions ls action police
 total acts 1

	action order 0:  police 0x1 rate 0bit burst 0b mtu 4096Mb pkts_rate 1000 pkts_burst 200
	ref 1 bind 0

Signed-off-by: Baowen Zheng <baowen.zheng@corigine.com>
Signed-off-by: Simon Horman <simon.horman@netronome.com>
Signed-off-by: Louis Peens <louis.peens@netronome.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
This commit is contained in:
Baowen Zheng 2021-03-26 13:50:18 +01:00 committed by David Ahern
parent 16430e9afd
commit cf9ae1bd31
2 changed files with 75 additions and 10 deletions

View File

@ -5,9 +5,11 @@ police - policing action
.SH SYNOPSIS
.in +8
.ti -8
.BR tc " ... " "action police"
.BR tc " ... " "action police ["
.BI rate " RATE " burst
.IR BYTES [\fB/ BYTES "] ["
.IR BYTES [\fB/ BYTES "] ] ["
.BI pkts_rate " RATE " pkts_burst
.IR PACKETS "] ["
.B mtu
.IR BYTES [\fB/ BYTES "] ] ["
.BI peakrate " RATE"
@ -34,19 +36,29 @@ police - policing action
.SH DESCRIPTION
The
.B police
action allows to limit bandwidth of traffic matched by the filter it is
attached to. Basically there are two different algorithms available to measure
the packet rate: The first one uses an internal dual token bucket and is
configured using the
action allows limiting of the byte or packet rate of traffic matched by the
filter it is attached to.
.P
There are two different algorithms available to measure the byte rate: The
first one uses an internal dual token bucket and is configured using the
.BR rate ", " burst ", " mtu ", " peakrate ", " overhead " and " linklayer
parameters. The second one uses an in-kernel sampling mechanism. It can be
fine-tuned using the
.B estimator
filter parameter.
.P
There is one algorithm available to measure packet rate and it is similar to
the first algorithm described for byte rate. It is configured using the
.BR pkt_rate " and " pkt_burst
parameters.
.P
At least one of the
.BR rate " and " pkt_rate "
parameters must be configured.
.SH OPTIONS
.TP
.BI rate " RATE"
The maximum traffic rate of packets passing this action. Those exceeding it will
The maximum byte rate of packets passing this action. Those exceeding it will
be treated as defined by the
.B conform-exceed
option.
@ -55,6 +67,15 @@ option.
Set the maximum allowed burst in bytes, optionally followed by a slash ('/')
sign and cell size which must be a power of 2.
.TP
.BI pkt_rate " RATE"
The maximum packet rate or packets passing this action. Those exceeding it will
be treated as defined by the
.B conform-exceed
option.
.TP
.BI pkt_burst " PACKETS"
Set the maximum allowed burst in packets.
.TP
.BI mtu " BYTES\fR[\fB/\fIBYTES\fR]"
This is the maximum packet size handled by the policer (larger ones will be
handled like they exceeded the configured rate). Setting this value correctly

View File

@ -38,7 +38,8 @@ struct action_util police_action_util = {
static void usage(void)
{
fprintf(stderr,
"Usage: ... police rate BPS burst BYTES[/BYTES] [ mtu BYTES[/BYTES] ]\n"
"Usage: ... police [ rate BPS burst BYTES[/BYTES] ] \n"
" [ pkts_rate RATE pkts_burst PACKETS ] [ mtu BYTES[/BYTES] ]\n"
" [ peakrate BPS ] [ avrate BPS ] [ overhead BYTES ]\n"
" [ linklayer TYPE ] [ CONTROL ]\n"
"Where: CONTROL := conform-exceed <EXCEEDACT>[/NOTEXCEEDACT]\n"
@ -67,6 +68,7 @@ static int act_parse_police(struct action_util *a, int *argc_p, char ***argv_p,
int Rcell_log = -1, Pcell_log = -1;
struct rtattr *tail;
__u64 rate64 = 0, prate64 = 0;
__u64 pps64 = 0, ppsburst64 = 0;
if (a) /* new way of doing things */
NEXT_ARG();
@ -144,6 +146,18 @@ static int act_parse_police(struct action_util *a, int *argc_p, char ***argv_p,
NEXT_ARG();
if (get_linklayer(&linklayer, *argv))
invarg("linklayer", *argv);
} else if (matches(*argv, "pkts_rate") == 0) {
NEXT_ARG();
if (pps64)
duparg("pkts_rate", *argv);
if (get_u64(&pps64, *argv, 10))
invarg("pkts_rate", *argv);
} else if (matches(*argv, "pkts_burst") == 0) {
NEXT_ARG();
if (ppsburst64)
duparg("pkts_burst", *argv);
if (get_u64(&ppsburst64, *argv, 10))
invarg("pkts_burst", *argv);
} else if (strcmp(*argv, "help") == 0) {
usage();
} else {
@ -161,8 +175,8 @@ action_ctrl_ok:
return -1;
/* Must at least do late binding, use TB or ewma policing */
if (!rate64 && !avrate && !p.index && !mtu) {
fprintf(stderr, "'rate' or 'avrate' or 'mtu' MUST be specified.\n");
if (!rate64 && !avrate && !p.index && !mtu && !pps64) {
fprintf(stderr, "'rate' or 'avrate' or 'mtu' or 'pkts_rate' MUST be specified.\n");
return -1;
}
@ -172,6 +186,18 @@ action_ctrl_ok:
return -1;
}
/* When the packets TB policer is used, pkts_burst is required */
if (pps64 && !ppsburst64) {
fprintf(stderr, "'pkts_burst' requires 'pkts_rate'.\n");
return -1;
}
/* forbid rate and pkts_rate in same action */
if (pps64 && rate64) {
fprintf(stderr, "'rate' and 'pkts_rate' are not allowed in same action.\n");
return -1;
}
if (prate64) {
if (!rate64) {
fprintf(stderr, "'peakrate' requires 'rate'.\n");
@ -223,6 +249,12 @@ action_ctrl_ok:
if (presult)
addattr32(n, MAX_MSG, TCA_POLICE_RESULT, presult);
if (pps64) {
addattr64(n, MAX_MSG, TCA_POLICE_PKTRATE64, pps64);
ppsburst64 = tc_calc_xmittime(pps64, ppsburst64);
addattr64(n, MAX_MSG, TCA_POLICE_PKTBURST64, ppsburst64);
}
addattr_nest_end(n, tail);
res = 0;
@ -244,6 +276,7 @@ static int print_police(struct action_util *a, FILE *f, struct rtattr *arg)
unsigned int buffer;
unsigned int linklayer;
__u64 rate64, prate64;
__u64 pps64, ppsburst64;
if (arg == NULL)
return 0;
@ -287,6 +320,17 @@ static int print_police(struct action_util *a, FILE *f, struct rtattr *arg)
tc_print_rate(PRINT_FP, NULL, "avrate %s ",
rta_getattr_u32(tb[TCA_POLICE_AVRATE]));
if ((tb[TCA_POLICE_PKTRATE64] &&
RTA_PAYLOAD(tb[TCA_POLICE_PKTRATE64]) >= sizeof(pps64)) &&
(tb[TCA_POLICE_PKTBURST64] &&
RTA_PAYLOAD(tb[TCA_POLICE_PKTBURST64]) >= sizeof(ppsburst64))) {
pps64 = rta_getattr_u64(tb[TCA_POLICE_PKTRATE64]);
ppsburst64 = rta_getattr_u64(tb[TCA_POLICE_PKTBURST64]);
ppsburst64 = tc_calc_xmitsize(pps64, ppsburst64);
fprintf(f, "pkts_rate %llu ", pps64);
fprintf(f, "pkts_burst %llu ", ppsburst64);
}
print_action_control(f, "action ", p->action, "");
if (tb[TCA_POLICE_RESULT]) {