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:
parent
16430e9afd
commit
cf9ae1bd31
|
|
@ -5,9 +5,11 @@ police - policing action
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.in +8
|
.in +8
|
||||||
.ti -8
|
.ti -8
|
||||||
.BR tc " ... " "action police"
|
.BR tc " ... " "action police ["
|
||||||
.BI rate " RATE " burst
|
.BI rate " RATE " burst
|
||||||
.IR BYTES [\fB/ BYTES "] ["
|
.IR BYTES [\fB/ BYTES "] ] ["
|
||||||
|
.BI pkts_rate " RATE " pkts_burst
|
||||||
|
.IR PACKETS "] ["
|
||||||
.B mtu
|
.B mtu
|
||||||
.IR BYTES [\fB/ BYTES "] ] ["
|
.IR BYTES [\fB/ BYTES "] ] ["
|
||||||
.BI peakrate " RATE"
|
.BI peakrate " RATE"
|
||||||
|
|
@ -34,19 +36,29 @@ police - policing action
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
The
|
The
|
||||||
.B police
|
.B police
|
||||||
action allows to limit bandwidth of traffic matched by the filter it is
|
action allows limiting of the byte or packet rate of traffic matched by the
|
||||||
attached to. Basically there are two different algorithms available to measure
|
filter it is attached to.
|
||||||
the packet rate: The first one uses an internal dual token bucket and is
|
.P
|
||||||
configured using the
|
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
|
.BR rate ", " burst ", " mtu ", " peakrate ", " overhead " and " linklayer
|
||||||
parameters. The second one uses an in-kernel sampling mechanism. It can be
|
parameters. The second one uses an in-kernel sampling mechanism. It can be
|
||||||
fine-tuned using the
|
fine-tuned using the
|
||||||
.B estimator
|
.B estimator
|
||||||
filter parameter.
|
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
|
.SH OPTIONS
|
||||||
.TP
|
.TP
|
||||||
.BI rate " RATE"
|
.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
|
be treated as defined by the
|
||||||
.B conform-exceed
|
.B conform-exceed
|
||||||
option.
|
option.
|
||||||
|
|
@ -55,6 +67,15 @@ option.
|
||||||
Set the maximum allowed burst in bytes, optionally followed by a slash ('/')
|
Set the maximum allowed burst in bytes, optionally followed by a slash ('/')
|
||||||
sign and cell size which must be a power of 2.
|
sign and cell size which must be a power of 2.
|
||||||
.TP
|
.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]"
|
.BI mtu " BYTES\fR[\fB/\fIBYTES\fR]"
|
||||||
This is the maximum packet size handled by the policer (larger ones will be
|
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
|
handled like they exceeded the configured rate). Setting this value correctly
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,8 @@ struct action_util police_action_util = {
|
||||||
static void usage(void)
|
static void usage(void)
|
||||||
{
|
{
|
||||||
fprintf(stderr,
|
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"
|
" [ peakrate BPS ] [ avrate BPS ] [ overhead BYTES ]\n"
|
||||||
" [ linklayer TYPE ] [ CONTROL ]\n"
|
" [ linklayer TYPE ] [ CONTROL ]\n"
|
||||||
"Where: CONTROL := conform-exceed <EXCEEDACT>[/NOTEXCEEDACT]\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;
|
int Rcell_log = -1, Pcell_log = -1;
|
||||||
struct rtattr *tail;
|
struct rtattr *tail;
|
||||||
__u64 rate64 = 0, prate64 = 0;
|
__u64 rate64 = 0, prate64 = 0;
|
||||||
|
__u64 pps64 = 0, ppsburst64 = 0;
|
||||||
|
|
||||||
if (a) /* new way of doing things */
|
if (a) /* new way of doing things */
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
|
|
@ -144,6 +146,18 @@ static int act_parse_police(struct action_util *a, int *argc_p, char ***argv_p,
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
if (get_linklayer(&linklayer, *argv))
|
if (get_linklayer(&linklayer, *argv))
|
||||||
invarg("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) {
|
} else if (strcmp(*argv, "help") == 0) {
|
||||||
usage();
|
usage();
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -161,8 +175,8 @@ action_ctrl_ok:
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Must at least do late binding, use TB or ewma policing */
|
/* Must at least do late binding, use TB or ewma policing */
|
||||||
if (!rate64 && !avrate && !p.index && !mtu) {
|
if (!rate64 && !avrate && !p.index && !mtu && !pps64) {
|
||||||
fprintf(stderr, "'rate' or 'avrate' or 'mtu' MUST be specified.\n");
|
fprintf(stderr, "'rate' or 'avrate' or 'mtu' or 'pkts_rate' MUST be specified.\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -172,6 +186,18 @@ action_ctrl_ok:
|
||||||
return -1;
|
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 (prate64) {
|
||||||
if (!rate64) {
|
if (!rate64) {
|
||||||
fprintf(stderr, "'peakrate' requires 'rate'.\n");
|
fprintf(stderr, "'peakrate' requires 'rate'.\n");
|
||||||
|
|
@ -223,6 +249,12 @@ action_ctrl_ok:
|
||||||
if (presult)
|
if (presult)
|
||||||
addattr32(n, MAX_MSG, TCA_POLICE_RESULT, 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);
|
addattr_nest_end(n, tail);
|
||||||
res = 0;
|
res = 0;
|
||||||
|
|
||||||
|
|
@ -244,6 +276,7 @@ static int print_police(struct action_util *a, FILE *f, struct rtattr *arg)
|
||||||
unsigned int buffer;
|
unsigned int buffer;
|
||||||
unsigned int linklayer;
|
unsigned int linklayer;
|
||||||
__u64 rate64, prate64;
|
__u64 rate64, prate64;
|
||||||
|
__u64 pps64, ppsburst64;
|
||||||
|
|
||||||
if (arg == NULL)
|
if (arg == NULL)
|
||||||
return 0;
|
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 ",
|
tc_print_rate(PRINT_FP, NULL, "avrate %s ",
|
||||||
rta_getattr_u32(tb[TCA_POLICE_AVRATE]));
|
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, "");
|
print_action_control(f, "action ", p->action, "");
|
||||||
|
|
||||||
if (tb[TCA_POLICE_RESULT]) {
|
if (tb[TCA_POLICE_RESULT]) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue