naccyde / rpms / iproute

Forked from rpms/iproute 8 months ago
Clone

Blame SOURCES/0005-police-add-support-for-packet-per-second-rate-limiti.patch

d5a8e7
From b061aeba93b1c730b7dafeece6b90aad2e7afce8 Mon Sep 17 00:00:00 2001
d5a8e7
Message-Id: <b061aeba93b1c730b7dafeece6b90aad2e7afce8.1628790091.git.aclaudi@redhat.com>
d5a8e7
In-Reply-To: <650694eb0120722499207078f965442ef7343bb1.1628790091.git.aclaudi@redhat.com>
d5a8e7
References: <650694eb0120722499207078f965442ef7343bb1.1628790091.git.aclaudi@redhat.com>
d5a8e7
From: Andrea Claudi <aclaudi@redhat.com>
d5a8e7
Date: Wed, 11 Aug 2021 12:55:14 +0200
d5a8e7
Subject: [PATCH] police: add support for packet-per-second rate limiting
d5a8e7
d5a8e7
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1981393
d5a8e7
Upstream Status: iproute2.git commit cf9ae1bd
d5a8e7
d5a8e7
commit cf9ae1bd31187d8ae62bc1bb408e443dbc8bd6a0
d5a8e7
Author: Baowen Zheng <baowen.zheng@corigine.com>
d5a8e7
Date:   Fri Mar 26 13:50:18 2021 +0100
d5a8e7
d5a8e7
    police: add support for packet-per-second rate limiting
d5a8e7
d5a8e7
    Allow a policer action to enforce a rate-limit based on packets-per-second,
d5a8e7
    configurable using a packet-per-second rate and burst parameters.
d5a8e7
d5a8e7
    e.g.
d5a8e7
     # $TC actions add action police pkts_rate 1000 pkts_burst 200 index 1
d5a8e7
     # $TC actions ls action police
d5a8e7
     total acts 1
d5a8e7
d5a8e7
            action order 0:  police 0x1 rate 0bit burst 0b mtu 4096Mb pkts_rate 1000 pkts_burst 200
d5a8e7
            ref 1 bind 0
d5a8e7
d5a8e7
    Signed-off-by: Baowen Zheng <baowen.zheng@corigine.com>
d5a8e7
    Signed-off-by: Simon Horman <simon.horman@netronome.com>
d5a8e7
    Signed-off-by: Louis Peens <louis.peens@netronome.com>
d5a8e7
    Signed-off-by: David Ahern <dsahern@kernel.org>
d5a8e7
d5a8e7
Signed-off-by: Andrea Claudi <aclaudi@redhat.com>
d5a8e7
---
d5a8e7
 man/man8/tc-police.8 | 35 ++++++++++++++++++++++++-------
d5a8e7
 tc/m_police.c        | 50 +++++++++++++++++++++++++++++++++++++++++---
d5a8e7
 2 files changed, 75 insertions(+), 10 deletions(-)
d5a8e7
d5a8e7
diff --git a/man/man8/tc-police.8 b/man/man8/tc-police.8
d5a8e7
index 52279755..86e263bb 100644
d5a8e7
--- a/man/man8/tc-police.8
d5a8e7
+++ b/man/man8/tc-police.8
d5a8e7
@@ -5,9 +5,11 @@ police - policing action
d5a8e7
 .SH SYNOPSIS
d5a8e7
 .in +8
d5a8e7
 .ti -8
d5a8e7
-.BR tc " ... " "action police"
d5a8e7
+.BR tc " ... " "action police ["
d5a8e7
 .BI rate " RATE " burst
d5a8e7
-.IR BYTES [\fB/ BYTES "] ["
d5a8e7
+.IR BYTES [\fB/ BYTES "] ] ["
d5a8e7
+.BI pkts_rate " RATE " pkts_burst
d5a8e7
+.IR PACKETS "] ["
d5a8e7
 .B mtu
d5a8e7
 .IR BYTES [\fB/ BYTES "] ] ["
d5a8e7
 .BI peakrate " RATE"
d5a8e7
@@ -34,19 +36,29 @@ police - policing action
d5a8e7
 .SH DESCRIPTION
d5a8e7
 The
d5a8e7
 .B police
d5a8e7
-action allows to limit bandwidth of traffic matched by the filter it is
d5a8e7
-attached to. Basically there are two different algorithms available to measure
d5a8e7
-the packet rate: The first one uses an internal dual token bucket and is
d5a8e7
-configured using the
d5a8e7
+action allows limiting of the byte or packet rate of traffic matched by the
d5a8e7
+filter it is attached to.
d5a8e7
+.P
d5a8e7
+There are two different algorithms available to measure the byte rate: The
d5a8e7
+first one uses an internal dual token bucket and is configured using the
d5a8e7
 .BR rate ", " burst ", " mtu ", " peakrate ", " overhead " and " linklayer
d5a8e7
 parameters. The second one uses an in-kernel sampling mechanism. It can be
d5a8e7
 fine-tuned using the
d5a8e7
 .B estimator
d5a8e7
 filter parameter.
d5a8e7
+.P
d5a8e7
+There is one algorithm available to measure packet rate and it is similar to
d5a8e7
+the first algorithm described for byte rate. It is configured using the
d5a8e7
+.BR pkt_rate " and " pkt_burst
d5a8e7
+parameters.
d5a8e7
+.P
d5a8e7
+At least one of the
d5a8e7
+.BR rate " and " pkt_rate "
d5a8e7
+parameters must be configured.
d5a8e7
 .SH OPTIONS
d5a8e7
 .TP
d5a8e7
 .BI rate " RATE"
d5a8e7
-The maximum traffic rate of packets passing this action. Those exceeding it will
d5a8e7
+The maximum byte rate of packets passing this action. Those exceeding it will
d5a8e7
 be treated as defined by the
d5a8e7
 .B conform-exceed
d5a8e7
 option.
d5a8e7
@@ -55,6 +67,15 @@ option.
d5a8e7
 Set the maximum allowed burst in bytes, optionally followed by a slash ('/')
d5a8e7
 sign and cell size which must be a power of 2.
d5a8e7
 .TP
d5a8e7
+.BI pkt_rate " RATE"
d5a8e7
+The maximum packet rate or packets passing this action. Those exceeding it will
d5a8e7
+be treated as defined by the
d5a8e7
+.B conform-exceed
d5a8e7
+option.
d5a8e7
+.TP
d5a8e7
+.BI pkt_burst " PACKETS"
d5a8e7
+Set the maximum allowed burst in packets.
d5a8e7
+.TP
d5a8e7
 .BI mtu " BYTES\fR[\fB/\fIBYTES\fR]"
d5a8e7
 This is the maximum packet size handled by the policer (larger ones will be
d5a8e7
 handled like they exceeded the configured rate). Setting this value correctly
d5a8e7
diff --git a/tc/m_police.c b/tc/m_police.c
d5a8e7
index bb51df68..9ef0e40b 100644
d5a8e7
--- a/tc/m_police.c
d5a8e7
+++ b/tc/m_police.c
d5a8e7
@@ -38,7 +38,8 @@ struct action_util police_action_util = {
d5a8e7
 static void usage(void)
d5a8e7
 {
d5a8e7
 	fprintf(stderr,
d5a8e7
-		"Usage: ... police rate BPS burst BYTES[/BYTES] [ mtu BYTES[/BYTES] ]\n"
d5a8e7
+		"Usage: ... police [ rate BPS burst BYTES[/BYTES] ] \n"
d5a8e7
+		"		[ pkts_rate RATE pkts_burst PACKETS ] [ mtu BYTES[/BYTES] ]\n"
d5a8e7
 		"		[ peakrate BPS ] [ avrate BPS ] [ overhead BYTES ]\n"
d5a8e7
 		"		[ linklayer TYPE ] [ CONTROL ]\n"
d5a8e7
 		"Where: CONTROL := conform-exceed <EXCEEDACT>[/NOTEXCEEDACT]\n"
d5a8e7
@@ -67,6 +68,7 @@ static int act_parse_police(struct action_util *a, int *argc_p, char ***argv_p,
d5a8e7
 	int Rcell_log =  -1, Pcell_log = -1;
d5a8e7
 	struct rtattr *tail;
d5a8e7
 	__u64 rate64 = 0, prate64 = 0;
d5a8e7
+	__u64 pps64 = 0, ppsburst64 = 0;
d5a8e7
 
d5a8e7
 	if (a) /* new way of doing things */
d5a8e7
 		NEXT_ARG();
d5a8e7
@@ -144,6 +146,18 @@ static int act_parse_police(struct action_util *a, int *argc_p, char ***argv_p,
d5a8e7
 			NEXT_ARG();
d5a8e7
 			if (get_linklayer(&linklayer, *argv))
d5a8e7
 				invarg("linklayer", *argv);
d5a8e7
+		} else if (matches(*argv, "pkts_rate") == 0) {
d5a8e7
+			NEXT_ARG();
d5a8e7
+			if (pps64)
d5a8e7
+				duparg("pkts_rate", *argv);
d5a8e7
+			if (get_u64(&pps64, *argv, 10))
d5a8e7
+				invarg("pkts_rate", *argv);
d5a8e7
+		} else if (matches(*argv, "pkts_burst") == 0) {
d5a8e7
+			NEXT_ARG();
d5a8e7
+			if (ppsburst64)
d5a8e7
+				duparg("pkts_burst", *argv);
d5a8e7
+			if (get_u64(&ppsburst64, *argv, 10))
d5a8e7
+				invarg("pkts_burst", *argv);
d5a8e7
 		} else if (strcmp(*argv, "help") == 0) {
d5a8e7
 			usage();
d5a8e7
 		} else {
d5a8e7
@@ -161,8 +175,8 @@ action_ctrl_ok:
d5a8e7
 		return -1;
d5a8e7
 
d5a8e7
 	/* Must at least do late binding, use TB or ewma policing */
d5a8e7
-	if (!rate64 && !avrate && !p.index && !mtu) {
d5a8e7
-		fprintf(stderr, "'rate' or 'avrate' or 'mtu' MUST be specified.\n");
d5a8e7
+	if (!rate64 && !avrate && !p.index && !mtu && !pps64) {
d5a8e7
+		fprintf(stderr, "'rate' or 'avrate' or 'mtu' or 'pkts_rate' MUST be specified.\n");
d5a8e7
 		return -1;
d5a8e7
 	}
d5a8e7
 
d5a8e7
@@ -172,6 +186,18 @@ action_ctrl_ok:
d5a8e7
 		return -1;
d5a8e7
 	}
d5a8e7
 
d5a8e7
+	/* When the packets TB policer is used, pkts_burst is required */
d5a8e7
+	if (pps64 && !ppsburst64) {
d5a8e7
+		fprintf(stderr, "'pkts_burst' requires 'pkts_rate'.\n");
d5a8e7
+		return -1;
d5a8e7
+	}
d5a8e7
+
d5a8e7
+	/* forbid rate and pkts_rate in same action */
d5a8e7
+	if (pps64 && rate64) {
d5a8e7
+		fprintf(stderr, "'rate' and 'pkts_rate' are not allowed in same action.\n");
d5a8e7
+		return -1;
d5a8e7
+	}
d5a8e7
+
d5a8e7
 	if (prate64) {
d5a8e7
 		if (!rate64) {
d5a8e7
 			fprintf(stderr, "'peakrate' requires 'rate'.\n");
d5a8e7
@@ -223,6 +249,12 @@ action_ctrl_ok:
d5a8e7
 	if (presult)
d5a8e7
 		addattr32(n, MAX_MSG, TCA_POLICE_RESULT, presult);
d5a8e7
 
d5a8e7
+	if (pps64) {
d5a8e7
+		addattr64(n, MAX_MSG, TCA_POLICE_PKTRATE64, pps64);
d5a8e7
+		ppsburst64 = tc_calc_xmittime(pps64, ppsburst64);
d5a8e7
+		addattr64(n, MAX_MSG, TCA_POLICE_PKTBURST64, ppsburst64);
d5a8e7
+	}
d5a8e7
+
d5a8e7
 	addattr_nest_end(n, tail);
d5a8e7
 	res = 0;
d5a8e7
 
d5a8e7
@@ -244,6 +276,7 @@ static int print_police(struct action_util *a, FILE *f, struct rtattr *arg)
d5a8e7
 	unsigned int buffer;
d5a8e7
 	unsigned int linklayer;
d5a8e7
 	__u64 rate64, prate64;
d5a8e7
+	__u64 pps64, ppsburst64;
d5a8e7
 
d5a8e7
 	if (arg == NULL)
d5a8e7
 		return 0;
d5a8e7
@@ -287,6 +320,17 @@ static int print_police(struct action_util *a, FILE *f, struct rtattr *arg)
d5a8e7
 		tc_print_rate(PRINT_FP, NULL, "avrate %s ",
d5a8e7
 			      rta_getattr_u32(tb[TCA_POLICE_AVRATE]));
d5a8e7
 
d5a8e7
+	if ((tb[TCA_POLICE_PKTRATE64] &&
d5a8e7
+	     RTA_PAYLOAD(tb[TCA_POLICE_PKTRATE64]) >= sizeof(pps64)) &&
d5a8e7
+	     (tb[TCA_POLICE_PKTBURST64] &&
d5a8e7
+	      RTA_PAYLOAD(tb[TCA_POLICE_PKTBURST64]) >= sizeof(ppsburst64))) {
d5a8e7
+		pps64 = rta_getattr_u64(tb[TCA_POLICE_PKTRATE64]);
d5a8e7
+		ppsburst64 = rta_getattr_u64(tb[TCA_POLICE_PKTBURST64]);
d5a8e7
+		ppsburst64 = tc_calc_xmitsize(pps64, ppsburst64);
d5a8e7
+		fprintf(f, "pkts_rate %llu ", pps64);
d5a8e7
+		fprintf(f, "pkts_burst %llu ", ppsburst64);
d5a8e7
+	}
d5a8e7
+
d5a8e7
 	print_action_control(f, "action ", p->action, "");
d5a8e7
 
d5a8e7
 	if (tb[TCA_POLICE_RESULT]) {
d5a8e7
-- 
d5a8e7
2.31.1
d5a8e7