All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH iproute2-next 00/10] dcb: Support PFC, buffer, maxrate objects
@ 2020-12-10 23:02 Petr Machata
  2020-12-10 23:02 ` [PATCH iproute2-next 01/10] dcb: Remove unsupported command line arguments from getopt_long() Petr Machata
                   ` (10 more replies)
  0 siblings, 11 replies; 12+ messages in thread
From: Petr Machata @ 2020-12-10 23:02 UTC (permalink / raw)
  To: netdev, dsahern, stephen; +Cc: Petr Machata

Add support to the dcb tool for the following three DCB objects:

- PFC, for "Priority-based Flow Control", allows configuration of priority
  lossiness, and related toggles.

- DCBNL buffer interfaces are an extension to the 802.1q DCB interfaces and
  allow configuration of port headroom buffers.

- DCBNL maxrate interfaces are an extension to the 802.1q DCB interfaces
  and allow configuration of rate with which traffic in a given traffic
  class is sent.

Patches #1-#4 fix small issues in the current DCB code and man pages.

Patch #5 adds new helpers to the DCB dispatcher.

Patches #6 and #7 add support for command line arguments -s and -i. These
enable, respectively, display of statistical counters, and ISO/IEC mode of
rate units.

Patches #8-#10 add the subtools themselves and their man pages.

Petr Machata (10):
  dcb: Remove unsupported command line arguments from getopt_long()
  dcb: ets: Fix help display for "show" subcommand
  dcb: ets: Change the way show parameters are given in synopsis
  man: dcb-ets: Remove an unnecessary empty line
  dcb: Add dcb_set_u32(), dcb_set_u64()
  dcb: Add -s to enable statistics
  dcb: Add -i to enable IEC mode
  dcb: Add a subtool for the DCB PFC object
  dcb: Add a subtool for the DCB buffer object
  dcb: Add a subtool for the DCB maxrate object

 dcb/Makefile           |   2 +-
 dcb/dcb.c              |  66 +++++++++-
 dcb/dcb.h              |  24 +++-
 dcb/dcb_buffer.c       | 235 +++++++++++++++++++++++++++++++++
 dcb/dcb_ets.c          |  10 +-
 dcb/dcb_maxrate.c      | 182 ++++++++++++++++++++++++++
 dcb/dcb_pfc.c          | 286 +++++++++++++++++++++++++++++++++++++++++
 man/man8/dcb-buffer.8  | 126 ++++++++++++++++++
 man/man8/dcb-ets.8     |  14 +-
 man/man8/dcb-maxrate.8 |  94 ++++++++++++++
 man/man8/dcb-pfc.8     | 127 ++++++++++++++++++
 man/man8/dcb.8         |  29 ++++-
 12 files changed, 1173 insertions(+), 22 deletions(-)
 create mode 100644 dcb/dcb_buffer.c
 create mode 100644 dcb/dcb_maxrate.c
 create mode 100644 dcb/dcb_pfc.c
 create mode 100644 man/man8/dcb-buffer.8
 create mode 100644 man/man8/dcb-maxrate.8
 create mode 100644 man/man8/dcb-pfc.8

-- 
2.25.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH iproute2-next 01/10] dcb: Remove unsupported command line arguments from getopt_long()
  2020-12-10 23:02 [PATCH iproute2-next 00/10] dcb: Support PFC, buffer, maxrate objects Petr Machata
@ 2020-12-10 23:02 ` Petr Machata
  2020-12-10 23:02 ` [PATCH iproute2-next 02/10] dcb: ets: Fix help display for "show" subcommand Petr Machata
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Petr Machata @ 2020-12-10 23:02 UTC (permalink / raw)
  To: netdev, dsahern, stephen; +Cc: Petr Machata

getopt_long() currently includes "c" and "n" in the short option string.
These probably slipped in as a cut'n'paste, and are not actually accepted.
Remove them.

Signed-off-by: Petr Machata <me@pmachata.org>
---
 dcb/dcb.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/dcb/dcb.c b/dcb/dcb.c
index dc1e9fe04e22..217dd640d7e5 100644
--- a/dcb/dcb.c
+++ b/dcb/dcb.c
@@ -349,7 +349,7 @@ int main(int argc, char **argv)
 		return EXIT_FAILURE;
 	}
 
-	while ((opt = getopt_long(argc, argv, "b:c::fhjnpvN:V",
+	while ((opt = getopt_long(argc, argv, "b:fhjpvN:V",
 				  long_options, NULL)) >= 0) {
 
 		switch (opt) {
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH iproute2-next 02/10] dcb: ets: Fix help display for "show" subcommand
  2020-12-10 23:02 [PATCH iproute2-next 00/10] dcb: Support PFC, buffer, maxrate objects Petr Machata
  2020-12-10 23:02 ` [PATCH iproute2-next 01/10] dcb: Remove unsupported command line arguments from getopt_long() Petr Machata
@ 2020-12-10 23:02 ` Petr Machata
  2020-12-10 23:02 ` [PATCH iproute2-next 03/10] dcb: ets: Change the way show parameters are given in synopsis Petr Machata
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Petr Machata @ 2020-12-10 23:02 UTC (permalink / raw)
  To: netdev, dsahern, stephen; +Cc: Petr Machata

"dcb ets show dev X help" currently shows full "ets" help instead of just
help for the show command. Fix it.

Signed-off-by: Petr Machata <me@pmachata.org>
---
 dcb/dcb_ets.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/dcb/dcb_ets.c b/dcb/dcb_ets.c
index 1735885aa8ed..94c6019e8095 100644
--- a/dcb/dcb_ets.c
+++ b/dcb/dcb_ets.c
@@ -370,7 +370,7 @@ static int dcb_cmd_ets_show(struct dcb *dcb, const char *dev, int argc, char **a
 
 	do {
 		if (matches(*argv, "help") == 0) {
-			dcb_ets_help();
+			dcb_ets_help_show();
 			return 0;
 		} else if (matches(*argv, "willing") == 0) {
 			dcb_ets_print_willing(&ets);
@@ -404,7 +404,7 @@ static int dcb_cmd_ets_show(struct dcb *dcb, const char *dev, int argc, char **a
 			print_nl();
 		} else {
 			fprintf(stderr, "What is \"%s\"?\n", *argv);
-			dcb_ets_help();
+			dcb_ets_help_show();
 			return -EINVAL;
 		}
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH iproute2-next 03/10] dcb: ets: Change the way show parameters are given in synopsis
  2020-12-10 23:02 [PATCH iproute2-next 00/10] dcb: Support PFC, buffer, maxrate objects Petr Machata
  2020-12-10 23:02 ` [PATCH iproute2-next 01/10] dcb: Remove unsupported command line arguments from getopt_long() Petr Machata
  2020-12-10 23:02 ` [PATCH iproute2-next 02/10] dcb: ets: Fix help display for "show" subcommand Petr Machata
@ 2020-12-10 23:02 ` Petr Machata
  2020-12-10 23:02 ` [PATCH iproute2-next 04/10] man: dcb-ets: Remove an unnecessary empty line Petr Machata
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Petr Machata @ 2020-12-10 23:02 UTC (permalink / raw)
  To: netdev, dsahern, stephen; +Cc: Petr Machata

None, one, or many parameters can be given on the command line, but
the current synopsis allows only none or one. Fix it.

Signed-off-by: Petr Machata <me@pmachata.org>
---
 dcb/dcb_ets.c      |  6 +++---
 man/man8/dcb-ets.8 | 13 ++++++++++---
 2 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/dcb/dcb_ets.c b/dcb/dcb_ets.c
index 94c6019e8095..c20881051ffe 100644
--- a/dcb/dcb_ets.c
+++ b/dcb/dcb_ets.c
@@ -32,9 +32,9 @@ static void dcb_ets_help_show(void)
 {
 	fprintf(stderr,
 		"Usage: dcb ets show dev STRING\n"
-		"           [ willing | ets-cap | cbs | tc-tsa | reco-tc-tsa |\n"
-		"             pg-bw | tc-bw | reco-tc-bw | prio-tc |\n"
-		"             reco-prio-tc ]\n"
+		"           [ willing ] [ ets-cap ] [ cbs ] [ tc-tsa ]\n"
+		"           [ reco-tc-tsa ] [ pg-bw ] [ tc-bw ] [ reco-tc-bw ]\n"
+		"           [ prio-tc ] [ reco-prio-tc ]\n"
 		"\n"
 	);
 }
diff --git a/man/man8/dcb-ets.8 b/man/man8/dcb-ets.8
index 0ae3587cb66a..1ef0948fb062 100644
--- a/man/man8/dcb-ets.8
+++ b/man/man8/dcb-ets.8
@@ -17,9 +17,16 @@ the DCB (Data Center Bridging) subsystem
 .ti -8
 .B dcb ets show dev
 .RI DEV
-.RB "[ { " willing " | " ets-cap " | " cbs " | " tc-tsa " | " reco-tc-tsa
-.RB " | " pg-bw " | " tc-bw " | " reco-tc-bw " | " prio-tc
-.RB " | " reco-prio-tc " } ]"
+.RB "[ " willing " ]"
+.RB "[ " ets-cap " ]"
+.RB "[ " cbs " ]"
+.RB "[ " tc-tsa " ]"
+.RB "[ " reco-tc-tsa " ]"
+.RB "[ " pg-bw " ]"
+.RB "[ " tc-bw " ]"
+.RB "[ " reco-tc-bw " ]"
+.RB "[ " prio-tc " ]"
+.RB "[ " reco-prio-tc " ]"
 
 .ti -8
 .B dcb ets set dev
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH iproute2-next 04/10] man: dcb-ets: Remove an unnecessary empty line
  2020-12-10 23:02 [PATCH iproute2-next 00/10] dcb: Support PFC, buffer, maxrate objects Petr Machata
                   ` (2 preceding siblings ...)
  2020-12-10 23:02 ` [PATCH iproute2-next 03/10] dcb: ets: Change the way show parameters are given in synopsis Petr Machata
@ 2020-12-10 23:02 ` Petr Machata
  2020-12-10 23:02 ` [PATCH iproute2-next 05/10] dcb: Add dcb_set_u32(), dcb_set_u64() Petr Machata
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Petr Machata @ 2020-12-10 23:02 UTC (permalink / raw)
  To: netdev, dsahern, stephen; +Cc: Petr Machata

Signed-off-by: Petr Machata <me@pmachata.org>
---
 man/man8/dcb-ets.8 | 1 -
 1 file changed, 1 deletion(-)

diff --git a/man/man8/dcb-ets.8 b/man/man8/dcb-ets.8
index 1ef0948fb062..9c64b33e30ff 100644
--- a/man/man8/dcb-ets.8
+++ b/man/man8/dcb-ets.8
@@ -61,7 +61,6 @@ the DCB (Data Center Bridging) subsystem
 .ti -8
 .IR PRIO " := { " \fB0\fR " .. " \fB7\fR " }"
 
-
 .SH DESCRIPTION
 
 .B dcb ets
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH iproute2-next 05/10] dcb: Add dcb_set_u32(), dcb_set_u64()
  2020-12-10 23:02 [PATCH iproute2-next 00/10] dcb: Support PFC, buffer, maxrate objects Petr Machata
                   ` (3 preceding siblings ...)
  2020-12-10 23:02 ` [PATCH iproute2-next 04/10] man: dcb-ets: Remove an unnecessary empty line Petr Machata
@ 2020-12-10 23:02 ` Petr Machata
  2020-12-10 23:02 ` [PATCH iproute2-next 06/10] dcb: Add -s to enable statistics Petr Machata
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Petr Machata @ 2020-12-10 23:02 UTC (permalink / raw)
  To: netdev, dsahern, stephen; +Cc: Petr Machata

The DCB buffer object has a settable array of 32-bit quantities, and the
maxrate object of 64-bit ones. Adjust dcb_parse_mapping() and related
helpers to support 64-bit values in mappings, and add appropriate helpers.

Signed-off-by: Petr Machata <me@pmachata.org>
---
 dcb/dcb.c | 22 ++++++++++++++++++----
 dcb/dcb.h |  8 +++++---
 2 files changed, 23 insertions(+), 7 deletions(-)

diff --git a/dcb/dcb.c b/dcb/dcb.c
index 217dd640d7e5..7c0beee43686 100644
--- a/dcb/dcb.c
+++ b/dcb/dcb.c
@@ -229,8 +229,8 @@ void dcb_print_named_array(const char *json_name, const char *fp_name,
 }
 
 int dcb_parse_mapping(const char *what_key, __u32 key, __u32 max_key,
-		      const char *what_value, __u32 value, __u32 max_value,
-		      void (*set_array)(__u32 index, __u32 value, void *data),
+		      const char *what_value, __u64 value, __u64 max_value,
+		      void (*set_array)(__u32 index, __u64 value, void *data),
 		      void *set_array_data)
 {
 	bool is_all = key == (__u32) -1;
@@ -242,7 +242,7 @@ int dcb_parse_mapping(const char *what_key, __u32 key, __u32 max_key,
 	}
 
 	if (value > max_value) {
-		fprintf(stderr, "In %s:%s mapping, %s is expected to be 0..%d\n",
+		fprintf(stderr, "In %s:%s mapping, %s is expected to be 0..%llu\n",
 			what_key, what_value, what_value, max_value);
 		return -EINVAL;
 	}
@@ -257,13 +257,27 @@ int dcb_parse_mapping(const char *what_key, __u32 key, __u32 max_key,
 	return 0;
 }
 
-void dcb_set_u8(__u32 key, __u32 value, void *data)
+void dcb_set_u8(__u32 key, __u64 value, void *data)
 {
 	__u8 *array = data;
 
 	array[key] = value;
 }
 
+void dcb_set_u32(__u32 key, __u64 value, void *data)
+{
+	__u32 *array = data;
+
+	array[key] = value;
+}
+
+void dcb_set_u64(__u32 key, __u64 value, void *data)
+{
+	__u64 *array = data;
+
+	array[key] = value;
+}
+
 int dcb_cmd_parse_dev(struct dcb *dcb, int argc, char **argv,
 		      int (*and_then)(struct dcb *dcb, const char *dev,
 				      int argc, char **argv),
diff --git a/dcb/dcb.h b/dcb/dcb.h
index 6f135ed06b08..d22176888811 100644
--- a/dcb/dcb.h
+++ b/dcb/dcb.h
@@ -14,15 +14,17 @@ struct dcb {
 };
 
 int dcb_parse_mapping(const char *what_key, __u32 key, __u32 max_key,
-		      const char *what_value, __u32 value, __u32 max_value,
-		      void (*set_array)(__u32 index, __u32 value, void *data),
+		      const char *what_value, __u64 value, __u64 max_value,
+		      void (*set_array)(__u32 index, __u64 value, void *data),
 		      void *set_array_data);
 int dcb_cmd_parse_dev(struct dcb *dcb, int argc, char **argv,
 		      int (*and_then)(struct dcb *dcb, const char *dev,
 				      int argc, char **argv),
 		      void (*help)(void));
 
-void dcb_set_u8(__u32 key, __u32 value, void *data);
+void dcb_set_u8(__u32 key, __u64 value, void *data);
+void dcb_set_u32(__u32 key, __u64 value, void *data);
+void dcb_set_u64(__u32 key, __u64 value, void *data);
 
 int dcb_get_attribute(struct dcb *dcb, const char *dev, int attr,
 		      void *data, size_t data_len);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH iproute2-next 06/10] dcb: Add -s to enable statistics
  2020-12-10 23:02 [PATCH iproute2-next 00/10] dcb: Support PFC, buffer, maxrate objects Petr Machata
                   ` (4 preceding siblings ...)
  2020-12-10 23:02 ` [PATCH iproute2-next 05/10] dcb: Add dcb_set_u32(), dcb_set_u64() Petr Machata
@ 2020-12-10 23:02 ` Petr Machata
  2020-12-10 23:02 ` [PATCH iproute2-next 07/10] dcb: Add -i to enable IEC mode Petr Machata
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Petr Machata @ 2020-12-10 23:02 UTC (permalink / raw)
  To: netdev, dsahern, stephen; +Cc: Petr Machata

Allow selective display of statistical counters by passing -s.

Signed-off-by: Petr Machata <me@pmachata.org>
---
 dcb/dcb.c      | 9 +++++++--
 dcb/dcb.h      | 1 +
 man/man8/dcb.8 | 5 +++++
 3 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/dcb/dcb.c b/dcb/dcb.c
index 7c0beee43686..9332a8b2e3d4 100644
--- a/dcb/dcb.c
+++ b/dcb/dcb.c
@@ -310,7 +310,8 @@ static void dcb_help(void)
 		"Usage: dcb [ OPTIONS ] OBJECT { COMMAND | help }\n"
 		"       dcb [ -f | --force ] { -b | --batch } filename [ -N | --Netns ] netnsname\n"
 		"where  OBJECT := ets\n"
-		"       OPTIONS := [ -V | --Version | -j | --json | -p | --pretty | -v | --verbose ]\n");
+		"       OPTIONS := [ -V | --Version | -j | --json | -p | --pretty\n"
+		"                  | -s | --statistics | -v | --verbose ]\n");
 }
 
 static int dcb_cmd(struct dcb *dcb, int argc, char **argv)
@@ -346,6 +347,7 @@ int main(int argc, char **argv)
 		{ "batch",		required_argument,	NULL, 'b' },
 		{ "json",		no_argument,		NULL, 'j' },
 		{ "pretty",		no_argument,		NULL, 'p' },
+		{ "statistics",		no_argument,		NULL, 's' },
 		{ "Netns",		required_argument,	NULL, 'N' },
 		{ "help",		no_argument,		NULL, 'h' },
 		{ NULL, 0, NULL, 0 }
@@ -363,7 +365,7 @@ int main(int argc, char **argv)
 		return EXIT_FAILURE;
 	}
 
-	while ((opt = getopt_long(argc, argv, "b:fhjpvN:V",
+	while ((opt = getopt_long(argc, argv, "b:fhjpsvN:V",
 				  long_options, NULL)) >= 0) {
 
 		switch (opt) {
@@ -383,6 +385,9 @@ int main(int argc, char **argv)
 		case 'p':
 			pretty = true;
 			break;
+		case 's':
+			dcb->stats = true;
+			break;
 		case 'N':
 			if (netns_switch(optarg)) {
 				ret = EXIT_FAILURE;
diff --git a/dcb/dcb.h b/dcb/dcb.h
index d22176888811..b2a13b3065f2 100644
--- a/dcb/dcb.h
+++ b/dcb/dcb.h
@@ -11,6 +11,7 @@ struct dcb {
 	char *buf;
 	struct mnl_socket *nl;
 	bool json_output;
+	bool stats;
 };
 
 int dcb_parse_mapping(const char *what_key, __u32 key, __u32 max_key,
diff --git a/man/man8/dcb.8 b/man/man8/dcb.8
index f318435caa98..f853b7baaf33 100644
--- a/man/man8/dcb.8
+++ b/man/man8/dcb.8
@@ -51,6 +51,11 @@ Generate JSON output.
 .BR "\-p" , " --pretty"
 When combined with -j generate a pretty JSON output.
 
+.TP
+.BR "\-s" , " --statistics"
+If the object in question contains any statistical counters, shown them as
+part of the "show" output.
+
 .SH OBJECTS
 
 .TP
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH iproute2-next 07/10] dcb: Add -i to enable IEC mode
  2020-12-10 23:02 [PATCH iproute2-next 00/10] dcb: Support PFC, buffer, maxrate objects Petr Machata
                   ` (5 preceding siblings ...)
  2020-12-10 23:02 ` [PATCH iproute2-next 06/10] dcb: Add -s to enable statistics Petr Machata
@ 2020-12-10 23:02 ` Petr Machata
  2020-12-10 23:02 ` [PATCH iproute2-next 08/10] dcb: Add a subtool for the DCB PFC object Petr Machata
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Petr Machata @ 2020-12-10 23:02 UTC (permalink / raw)
  To: netdev, dsahern, stephen; +Cc: Petr Machata

Allow switching "dcb" into the ISO/IEC mode of units by passing -i.

Signed-off-by: Petr Machata <me@pmachata.org>
---
 dcb/dcb.c      | 10 +++++++---
 dcb/dcb.h      |  1 +
 man/man8/dcb.8 |  5 +++++
 3 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/dcb/dcb.c b/dcb/dcb.c
index 9332a8b2e3d4..4b4a5b9354c6 100644
--- a/dcb/dcb.c
+++ b/dcb/dcb.c
@@ -310,8 +310,8 @@ static void dcb_help(void)
 		"Usage: dcb [ OPTIONS ] OBJECT { COMMAND | help }\n"
 		"       dcb [ -f | --force ] { -b | --batch } filename [ -N | --Netns ] netnsname\n"
 		"where  OBJECT := ets\n"
-		"       OPTIONS := [ -V | --Version | -j | --json | -p | --pretty\n"
-		"                  | -s | --statistics | -v | --verbose ]\n");
+		"       OPTIONS := [ -V | --Version | -i | --iec | -j | --json\n"
+		"                  | -p | --pretty | -s | --statistics | -v | --verbose]\n");
 }
 
 static int dcb_cmd(struct dcb *dcb, int argc, char **argv)
@@ -345,6 +345,7 @@ int main(int argc, char **argv)
 		{ "Version",		no_argument,		NULL, 'V' },
 		{ "force",		no_argument,		NULL, 'f' },
 		{ "batch",		required_argument,	NULL, 'b' },
+		{ "iec",		no_argument,		NULL, 'i' },
 		{ "json",		no_argument,		NULL, 'j' },
 		{ "pretty",		no_argument,		NULL, 'p' },
 		{ "statistics",		no_argument,		NULL, 's' },
@@ -365,7 +366,7 @@ int main(int argc, char **argv)
 		return EXIT_FAILURE;
 	}
 
-	while ((opt = getopt_long(argc, argv, "b:fhjpsvN:V",
+	while ((opt = getopt_long(argc, argv, "b:fhijpsvN:V",
 				  long_options, NULL)) >= 0) {
 
 		switch (opt) {
@@ -394,6 +395,9 @@ int main(int argc, char **argv)
 				goto dcb_free;
 			}
 			break;
+		case 'i':
+			dcb->use_iec = true;
+			break;
 		case 'h':
 			dcb_help();
 			return 0;
diff --git a/dcb/dcb.h b/dcb/dcb.h
index b2a13b3065f2..8637efc159b9 100644
--- a/dcb/dcb.h
+++ b/dcb/dcb.h
@@ -12,6 +12,7 @@ struct dcb {
 	struct mnl_socket *nl;
 	bool json_output;
 	bool stats;
+	bool use_iec;
 };
 
 int dcb_parse_mapping(const char *what_key, __u32 key, __u32 max_key,
diff --git a/man/man8/dcb.8 b/man/man8/dcb.8
index f853b7baaf33..15b43942585a 100644
--- a/man/man8/dcb.8
+++ b/man/man8/dcb.8
@@ -43,6 +43,11 @@ failure will cause termination of dcb.
 Don't terminate dcb on errors in batch mode. If there were any errors during
 execution of the commands, the application return code will be non zero.
 
+.TP
+.BR "\-i" , " --iec"
+When showing rates, use ISO/IEC 1024-based prefixes (Ki, Mi, Bi) instead of
+the 1000-based ones (K, M, B).
+
 .TP
 .BR "\-j" , " --json"
 Generate JSON output.
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH iproute2-next 08/10] dcb: Add a subtool for the DCB PFC object
  2020-12-10 23:02 [PATCH iproute2-next 00/10] dcb: Support PFC, buffer, maxrate objects Petr Machata
                   ` (6 preceding siblings ...)
  2020-12-10 23:02 ` [PATCH iproute2-next 07/10] dcb: Add -i to enable IEC mode Petr Machata
@ 2020-12-10 23:02 ` Petr Machata
  2020-12-10 23:02 ` [PATCH iproute2-next 09/10] dcb: Add a subtool for the DCB buffer object Petr Machata
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Petr Machata @ 2020-12-10 23:02 UTC (permalink / raw)
  To: netdev, dsahern, stephen; +Cc: Petr Machata

PFC, for "Priority-based Flow Control", allows configuration of priority
lossiness, and related toggles.

Add a dcb subtool to allow showing and tweaking of individual PFC
configuration options, and querying statistics. For example:

    # dcb pfc show dev eni1np1
    pfc-cap 8 macsec-bypass on delay 0
    pg-pfc 0:off 1:on 2:off 3:off 4:off 5:off 6:off 7:on
    requests 0:0 1:217 2:0 3:0 4:0 5:0 6:0 7:28
    indications 0:0 1:179 2:0 3:0 4:0 5:0 6:0 7:18

Signed-off-by: Petr Machata <me@pmachata.org>
---
 dcb/Makefile       |   2 +-
 dcb/dcb.c          |  27 ++++-
 dcb/dcb.h          |   6 +
 dcb/dcb_pfc.c      | 286 +++++++++++++++++++++++++++++++++++++++++++++
 man/man8/dcb-pfc.8 | 127 ++++++++++++++++++++
 man/man8/dcb.8     |   9 +-
 6 files changed, 453 insertions(+), 4 deletions(-)
 create mode 100644 dcb/dcb_pfc.c
 create mode 100644 man/man8/dcb-pfc.8

diff --git a/dcb/Makefile b/dcb/Makefile
index 895817163562..ea557a309e81 100644
--- a/dcb/Makefile
+++ b/dcb/Makefile
@@ -5,7 +5,7 @@ TARGETS :=
 
 ifeq ($(HAVE_MNL),y)
 
-DCBOBJ = dcb.o dcb_ets.o
+DCBOBJ = dcb.o dcb_ets.o dcb_pfc.o
 TARGETS += dcb
 
 endif
diff --git a/dcb/dcb.c b/dcb/dcb.c
index 4b4a5b9354c6..cc07d3ddcee0 100644
--- a/dcb/dcb.c
+++ b/dcb/dcb.c
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0+
 
+#include <inttypes.h>
 #include <stdio.h>
 #include <linux/dcbnl.h>
 #include <libmnl/libmnl.h>
@@ -201,6 +202,28 @@ void dcb_print_array_u8(const __u8 *array, size_t size)
 	}
 }
 
+void dcb_print_array_u64(const __u64 *array, size_t size)
+{
+	SPRINT_BUF(b);
+	size_t i;
+
+	for (i = 0; i < size; i++) {
+		snprintf(b, sizeof(b), "%zd:%%" PRIu64 " ", i);
+		print_u64(PRINT_ANY, NULL, b, array[i]);
+	}
+}
+
+void dcb_print_array_on_off(const __u8 *array, size_t size)
+{
+	SPRINT_BUF(b);
+	size_t i;
+
+	for (i = 0; i < size; i++) {
+		snprintf(b, sizeof(b), "%zd:%%s ", i);
+		print_on_off(PRINT_ANY, NULL, b, array[i]);
+	}
+}
+
 void dcb_print_array_kw(const __u8 *array, size_t array_size,
 			const char *const kw[], size_t kw_size)
 {
@@ -309,7 +332,7 @@ static void dcb_help(void)
 	fprintf(stderr,
 		"Usage: dcb [ OPTIONS ] OBJECT { COMMAND | help }\n"
 		"       dcb [ -f | --force ] { -b | --batch } filename [ -N | --Netns ] netnsname\n"
-		"where  OBJECT := ets\n"
+		"where  OBJECT := { ets | pfc }\n"
 		"       OPTIONS := [ -V | --Version | -i | --iec | -j | --json\n"
 		"                  | -p | --pretty | -s | --statistics | -v | --verbose]\n");
 }
@@ -321,6 +344,8 @@ static int dcb_cmd(struct dcb *dcb, int argc, char **argv)
 		return 0;
 	} else if (matches(*argv, "ets") == 0) {
 		return dcb_cmd_ets(dcb, argc - 1, argv + 1);
+	} else if (matches(*argv, "pfc") == 0) {
+		return dcb_cmd_pfc(dcb, argc - 1, argv + 1);
 	}
 
 	fprintf(stderr, "Object \"%s\" is unknown\n", *argv);
diff --git a/dcb/dcb.h b/dcb/dcb.h
index 8637efc159b9..4ecc6afd59a9 100644
--- a/dcb/dcb.h
+++ b/dcb/dcb.h
@@ -37,6 +37,8 @@ void dcb_print_named_array(const char *json_name, const char *fp_name,
 			   const __u8 *array, size_t size,
 			   void (*print_array)(const __u8 *, size_t));
 void dcb_print_array_u8(const __u8 *array, size_t size);
+void dcb_print_array_u64(const __u64 *array, size_t size);
+void dcb_print_array_on_off(const __u8 *array, size_t size);
 void dcb_print_array_kw(const __u8 *array, size_t array_size,
 			const char *const kw[], size_t kw_size);
 
@@ -44,4 +46,8 @@ void dcb_print_array_kw(const __u8 *array, size_t array_size,
 
 int dcb_cmd_ets(struct dcb *dcb, int argc, char **argv);
 
+/* dcb_pfc.c */
+
+int dcb_cmd_pfc(struct dcb *dcb, int argc, char **argv);
+
 #endif /* __DCB_H__ */
diff --git a/dcb/dcb_pfc.c b/dcb/dcb_pfc.c
new file mode 100644
index 000000000000..aaa09022e247
--- /dev/null
+++ b/dcb/dcb_pfc.c
@@ -0,0 +1,286 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <errno.h>
+#include <stdio.h>
+#include <linux/dcbnl.h>
+
+#include "dcb.h"
+#include "utils.h"
+
+static void dcb_pfc_help_set(void)
+{
+	fprintf(stderr,
+		"Usage: dcb pfc set dev STRING\n"
+		"           [ prio-pfc PFC-MAP ]\n"
+		"           [ macsec-bypass { on | off } ]\n"
+		"           [ delay INTEGER ]\n"
+		"\n"
+		" where PFC-MAP := [ PFC-MAP ] PFC-MAPPING\n"
+		"       PFC-MAPPING := { all | TC }:PFC\n"
+		"       TC := { 0 .. 7 }\n"
+		"       PFC := { on | off }\n"
+		"\n"
+	);
+}
+
+static void dcb_pfc_help_show(void)
+{
+	fprintf(stderr,
+		"Usage: dcb [ -s ] pfc show dev STRING\n"
+		"           [ pfc-cap ] [ prio-pfc ] [ macsec-bypass ]\n"
+		"           [ delay ] [ requests ] [ indications ]\n"
+		"\n"
+	);
+}
+
+static void dcb_pfc_help(void)
+{
+	fprintf(stderr,
+		"Usage: dcb pfc help\n"
+		"\n"
+	);
+	dcb_pfc_help_show();
+	dcb_pfc_help_set();
+}
+
+static void dcb_pfc_to_array(__u8 array[IEEE_8021QAZ_MAX_TCS], __u8 pfc_en)
+{
+	int i;
+
+	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)
+		array[i] = !!(pfc_en & (1 << i));
+}
+
+static void dcb_pfc_from_array(__u8 array[IEEE_8021QAZ_MAX_TCS], __u8 *pfc_en_p)
+{
+	__u8 pfc_en = 0;
+	int i;
+
+	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
+		if (array[i])
+			pfc_en |= 1 << i;
+	}
+
+	*pfc_en_p = pfc_en;
+}
+
+static int dcb_pfc_parse_mapping_prio_pfc(__u32 key, char *value, void *data)
+{
+	struct ieee_pfc *pfc = data;
+	__u8 pfc_en[IEEE_8021QAZ_MAX_TCS];
+	bool enabled;
+	int ret;
+
+	dcb_pfc_to_array(pfc_en, pfc->pfc_en);
+
+	enabled = parse_on_off("PFC", value, &ret);
+	if (ret)
+		return ret;
+
+	ret = dcb_parse_mapping("PRIO", key, IEEE_8021QAZ_MAX_TCS - 1,
+				"PFC", enabled, -1,
+				dcb_set_u8, pfc_en);
+	if (ret)
+		return ret;
+
+	dcb_pfc_from_array(pfc_en, &pfc->pfc_en);
+	return 0;
+}
+
+static void dcb_pfc_print_pfc_cap(const struct ieee_pfc *pfc)
+{
+	print_uint(PRINT_ANY, "pfc_cap", "pfc-cap %d ", pfc->pfc_cap);
+}
+
+static void dcb_pfc_print_macsec_bypass(const struct ieee_pfc *pfc)
+{
+	print_on_off(PRINT_ANY, "macsec_bypass", "macsec-bypass %s ", pfc->mbc);
+}
+
+static void dcb_pfc_print_delay(const struct ieee_pfc *pfc)
+{
+	print_uint(PRINT_ANY, "delay", "delay %d ", pfc->delay);
+}
+
+static void dcb_pfc_print_prio_pfc(const struct ieee_pfc *pfc)
+{
+	__u8 pfc_en[IEEE_8021QAZ_MAX_TCS];
+
+	dcb_pfc_to_array(pfc_en, pfc->pfc_en);
+	dcb_print_named_array("prio_pfc", "prio-pfc",
+			      pfc_en, ARRAY_SIZE(pfc_en), &dcb_print_array_on_off);
+}
+
+static void dcb_pfc_print_requests(const struct ieee_pfc *pfc)
+{
+	open_json_array(PRINT_JSON, "requests");
+	print_string(PRINT_FP, NULL, "requests ", NULL);
+	dcb_print_array_u64(pfc->requests, ARRAY_SIZE(pfc->requests));
+	close_json_array(PRINT_JSON, "requests");
+}
+
+static void dcb_pfc_print_indications(const struct ieee_pfc *pfc)
+{
+	open_json_array(PRINT_JSON, "indications");
+	print_string(PRINT_FP, NULL, "indications ", NULL);
+	dcb_print_array_u64(pfc->indications, ARRAY_SIZE(pfc->indications));
+	close_json_array(PRINT_JSON, "indications");
+}
+
+static void dcb_pfc_print(const struct dcb *dcb, const struct ieee_pfc *pfc)
+{
+	dcb_pfc_print_pfc_cap(pfc);
+	dcb_pfc_print_macsec_bypass(pfc);
+	dcb_pfc_print_delay(pfc);
+	print_nl();
+
+	dcb_pfc_print_prio_pfc(pfc);
+	print_nl();
+
+	if (dcb->stats) {
+		dcb_pfc_print_requests(pfc);
+		print_nl();
+
+		dcb_pfc_print_indications(pfc);
+		print_nl();
+	}
+}
+
+static int dcb_pfc_get(struct dcb *dcb, const char *dev, struct ieee_pfc *pfc)
+{
+	return dcb_get_attribute(dcb, dev, DCB_ATTR_IEEE_PFC, pfc, sizeof(*pfc));
+}
+
+static int dcb_pfc_set(struct dcb *dcb, const char *dev, const struct ieee_pfc *pfc)
+{
+	return dcb_set_attribute(dcb, dev, DCB_ATTR_IEEE_PFC, pfc, sizeof(*pfc));
+}
+
+static int dcb_cmd_pfc_set(struct dcb *dcb, const char *dev, int argc, char **argv)
+{
+	struct ieee_pfc pfc;
+	int ret;
+
+	if (!argc) {
+		dcb_pfc_help_set();
+		return 0;
+	}
+
+	ret = dcb_pfc_get(dcb, dev, &pfc);
+	if (ret)
+		return ret;
+
+	do {
+		if (matches(*argv, "help") == 0) {
+			dcb_pfc_help_set();
+			return 0;
+		} else if (matches(*argv, "prio-pfc") == 0) {
+			NEXT_ARG();
+			ret = parse_mapping(&argc, &argv, true,
+					    &dcb_pfc_parse_mapping_prio_pfc, &pfc);
+			if (ret) {
+				fprintf(stderr, "Invalid pfc mapping %s\n", *argv);
+				return ret;
+			}
+			continue;
+		} else if (matches(*argv, "macsec-bypass") == 0) {
+			NEXT_ARG();
+			pfc.mbc = parse_on_off("macsec-bypass", *argv, &ret);
+			if (ret)
+				return ret;
+		} else if (matches(*argv, "delay") == 0) {
+			NEXT_ARG();
+			/* Do not support the size notations for delay.
+			 * Delay is specified in "bit times", not bits, so
+			 * it is not applicable. At the same time it would
+			 * be confusing that 10Kbit does not mean 10240,
+			 * but 1280.
+			 */
+			if (get_u16(&pfc.delay, *argv, 0)) {
+				fprintf(stderr, "Invalid delay `%s', expected an integer 0..65535\n",
+					*argv);
+				return -EINVAL;
+			}
+		} else {
+			fprintf(stderr, "What is \"%s\"?\n", *argv);
+			dcb_pfc_help_set();
+			return -EINVAL;
+		}
+
+		NEXT_ARG_FWD();
+	} while (argc > 0);
+
+	return dcb_pfc_set(dcb, dev, &pfc);
+}
+
+static int dcb_cmd_pfc_show(struct dcb *dcb, const char *dev, int argc, char **argv)
+{
+	struct ieee_pfc pfc;
+	int ret;
+
+	ret = dcb_pfc_get(dcb, dev, &pfc);
+	if (ret)
+		return ret;
+
+	open_json_object(NULL);
+
+	if (!argc) {
+		dcb_pfc_print(dcb, &pfc);
+		goto out;
+	}
+
+	do {
+		if (matches(*argv, "help") == 0) {
+			dcb_pfc_help_show();
+			return 0;
+		} else if (matches(*argv, "prio-pfc") == 0) {
+			dcb_pfc_print_prio_pfc(&pfc);
+			print_nl();
+		} else if (matches(*argv, "pfc-cap") == 0) {
+			dcb_pfc_print_pfc_cap(&pfc);
+			print_nl();
+		} else if (matches(*argv, "macsec-bypass") == 0) {
+			dcb_pfc_print_macsec_bypass(&pfc);
+			print_nl();
+		} else if (matches(*argv, "delay") == 0) {
+			dcb_pfc_print_delay(&pfc);
+			print_nl();
+		} else if (matches(*argv, "requests") == 0) {
+			dcb_pfc_print_requests(&pfc);
+			print_nl();
+		} else if (matches(*argv, "indications") == 0) {
+			dcb_pfc_print_indications(&pfc);
+			print_nl();
+		} else {
+			fprintf(stderr, "What is \"%s\"?\n", *argv);
+			dcb_pfc_help_show();
+			return -EINVAL;
+		}
+
+		NEXT_ARG_FWD();
+	} while (argc > 0);
+
+out:
+	close_json_object();
+	return 0;
+}
+
+int dcb_cmd_pfc(struct dcb *dcb, int argc, char **argv)
+{
+	if (!argc || matches(*argv, "help") == 0) {
+		dcb_pfc_help();
+		return 0;
+	} else if (matches(*argv, "show") == 0) {
+		NEXT_ARG_FWD();
+		return dcb_cmd_parse_dev(dcb, argc, argv,
+					 dcb_cmd_pfc_show, dcb_pfc_help_show);
+	} else if (matches(*argv, "set") == 0) {
+		NEXT_ARG_FWD();
+		return dcb_cmd_parse_dev(dcb, argc, argv,
+					 dcb_cmd_pfc_set, dcb_pfc_help_set);
+	} else {
+		fprintf(stderr, "What is \"%s\"?\n", *argv);
+		dcb_pfc_help();
+		return -EINVAL;
+	}
+}
diff --git a/man/man8/dcb-pfc.8 b/man/man8/dcb-pfc.8
new file mode 100644
index 000000000000..735c16e066cb
--- /dev/null
+++ b/man/man8/dcb-pfc.8
@@ -0,0 +1,127 @@
+.TH DCB-PFC 8 "31 October 2020" "iproute2" "Linux"
+.SH NAME
+dcb-pfc \- show / manipulate PFC (Priority-based Flow Control) settings of
+the DCB (Data Center Bridging) subsystem
+.SH SYNOPSIS
+.sp
+.ad l
+.in +8
+
+.ti -8
+.B dcb
+.RI "[ " OPTIONS " ] "
+.B pfc
+.RI "{ " COMMAND " | " help " }"
+.sp
+
+.ti -8
+.B dcb pfc show dev
+.RI DEV
+.RB "[ " pfc-cap " ]"
+.RB "[ " prio-pfc " ]"
+.RB "[ " macsec-bypass " ]"
+.RB "[ " delay " ]"
+.RB "[ " requests " ]"
+.RB "[ " indications " ]"
+
+.ti -8
+.B dcb pfc set dev
+.RI DEV
+.RB "[ " prio-pfc " " \fIPFC-MAP " ]"
+.RB "[ " macsec-bypass " { " on " | " off " } ]"
+.RB "[ " delay " " \fIINTEGER\fR " ]"
+
+.ti -8
+.IR PFC-MAP " := [ " PFC-MAP " ] " PFC-MAPPING
+
+.ti -8
+.IR PFC-MAPPING " := { " PRIO " | " \fBall " }" \fB:\fR "{ "
+.IR \fBon\fR " | " \fBoff\fR " }"
+
+.ti -8
+.IR PRIO " := { " \fB0\fR " .. " \fB7\fR " }"
+
+.SH DESCRIPTION
+
+.B dcb pfc
+is used to configure Priority-based Flow Control attributes through Linux
+DCB (Data Center Bridging) interface. PFC permits marking flows with a
+certain priority as lossless, and holds related configuration, as well as
+PFC counters.
+
+.SH PARAMETERS
+
+For read-write parameters, the following describes only the write direction,
+i.e. as used with the \fBset\fR command. For the \fBshow\fR command, the
+parameter name is to be used as a simple keyword without further arguments. This
+instructs the tool to show the value of a given parameter. When no parameters
+are given, the tool shows the complete PFC configuration.
+
+.TP
+.B pfc-cap
+A read-only property that shows the number of traffic classes that may
+simultaneously support PFC.
+
+.TP
+.B requests
+A read-only count of the sent PFC frames per traffic class. Only shown when
+-s is given, or when requested explicitly.
+
+.TP
+.B indications
+A read-only count of the received PFC frames per traffic class. Only shown
+when -s is given, or when requested explicitly.
+
+.TP
+.B macsec-bypass \fR{ \fBon\fR | \fBoff\fR }
+Whether the sending station is capable of bypassing MACsec processing when
+MACsec is disabled.
+
+.TP
+.B prio-pfc \fIPFC-MAP
+\fIPFC-MAP\fR uses the array parameter syntax, see
+.BR dcb (8)
+for details. Keys are priorities, values are on / off indicators of whether
+PFC is enabled for a given priority.
+
+.TP
+.B delay \fIINTEGER
+The allowance made for round-trip propagation delay of the link in bits.
+The value shall be 0..65535.
+
+.SH EXAMPLE & USAGE
+
+Enable PFC on priorities 6 and 7, leaving the rest intact:
+
+.P
+# dcb pfc set dev eth0 prio-pfc 6:on 7:on
+
+Disable PFC of all priorities except 6 and 7, and configure delay to 4096
+bits:
+
+.P
+# dcb pfc set dev eth0 prio-pfc all:off 6:on 7:on delay 0x1000
+
+Show what was set:
+
+.P
+# dcb pfc show dev eth0
+.br
+pfc-cap 8 macsec-bypass off delay 4096
+.br
+prio-pfc 0:off 1:off 2:off 3:off 4:off 5:off 6:on 7:on
+
+.SH EXIT STATUS
+Exit status is 0 if command was successful or a positive integer upon failure.
+
+.SH SEE ALSO
+.BR dcb (8)
+
+.SH REPORTING BUGS
+Report any bugs to the Network Developers mailing list
+.B <netdev@vger.kernel.org>
+where the development and maintenance is primarily done.
+You do not have to be subscribed to the list to send a message there.
+
+.SH AUTHOR
+Petr Machata <me@pmachata.org>
diff --git a/man/man8/dcb.8 b/man/man8/dcb.8
index 15b43942585a..01febe166bdf 100644
--- a/man/man8/dcb.8
+++ b/man/man8/dcb.8
@@ -9,7 +9,7 @@ dcb \- show / manipulate DCB (Data Center Bridging) settings
 .ti -8
 .B dcb
 .RI "[ " OPTIONS " ] "
-.B ets
+.RB "{ " ets " | " pfc " }"
 .RI "{ " COMMAND " | " help " }"
 .sp
 
@@ -67,6 +67,10 @@ part of the "show" output.
 .B ets
 - Configuration of ETS (Enhanced Transmission Selection)
 
+.TP
+.B pfc
+- Configuration of PFC (Priority-based Flow Control)
+
 .SH COMMANDS
 
 A \fICOMMAND\fR specifies the action to perform on the object. The set of
@@ -111,7 +115,8 @@ other values:
 Exit status is 0 if command was successful or a positive integer upon failure.
 
 .SH SEE ALSO
-.BR dcb-ets (8)
+.BR dcb-ets (8),
+.BR dcb-pfc (8)
 .br
 
 .SH REPORTING BUGS
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH iproute2-next 09/10] dcb: Add a subtool for the DCB buffer object
  2020-12-10 23:02 [PATCH iproute2-next 00/10] dcb: Support PFC, buffer, maxrate objects Petr Machata
                   ` (7 preceding siblings ...)
  2020-12-10 23:02 ` [PATCH iproute2-next 08/10] dcb: Add a subtool for the DCB PFC object Petr Machata
@ 2020-12-10 23:02 ` Petr Machata
  2020-12-10 23:02 ` [PATCH iproute2-next 10/10] dcb: Add a subtool for the DCB maxrate object Petr Machata
  2020-12-14 16:51 ` [PATCH iproute2-next 00/10] dcb: Support PFC, buffer, maxrate objects David Ahern
  10 siblings, 0 replies; 12+ messages in thread
From: Petr Machata @ 2020-12-10 23:02 UTC (permalink / raw)
  To: netdev, dsahern, stephen; +Cc: Petr Machata

DCBNL buffer interfaces are an extension to the 802.1q DCB interfaces and
allow configuration of port headroom buffers.

Add a dcb subtool to allow showing and tweaking of buffer priority mapping
and buffer sizes. For example:

    # dcb buf show dev eni1np1
    prio-buffer 0:0 1:0 2:0 3:3 4:0 5:0 6:6 7:0
    buffer-size 0:10000 1:0 2:0 3:70000 4:0 5:0 6:10000 7:0
    total-size 221072

Signed-off-by: Petr Machata <me@pmachata.org>
---
 dcb/Makefile          |   2 +-
 dcb/dcb.c             |   4 +-
 dcb/dcb.h             |   4 +
 dcb/dcb_buffer.c      | 235 ++++++++++++++++++++++++++++++++++++++++++
 man/man8/dcb-buffer.8 | 126 ++++++++++++++++++++++
 man/man8/dcb.8        |   7 +-
 6 files changed, 375 insertions(+), 3 deletions(-)
 create mode 100644 dcb/dcb_buffer.c
 create mode 100644 man/man8/dcb-buffer.8

diff --git a/dcb/Makefile b/dcb/Makefile
index ea557a309e81..dc84422f6096 100644
--- a/dcb/Makefile
+++ b/dcb/Makefile
@@ -5,7 +5,7 @@ TARGETS :=
 
 ifeq ($(HAVE_MNL),y)
 
-DCBOBJ = dcb.o dcb_ets.o dcb_pfc.o
+DCBOBJ = dcb.o dcb_buffer.o dcb_ets.o dcb_pfc.o
 TARGETS += dcb
 
 endif
diff --git a/dcb/dcb.c b/dcb/dcb.c
index cc07d3ddcee0..570405a7e628 100644
--- a/dcb/dcb.c
+++ b/dcb/dcb.c
@@ -332,7 +332,7 @@ static void dcb_help(void)
 	fprintf(stderr,
 		"Usage: dcb [ OPTIONS ] OBJECT { COMMAND | help }\n"
 		"       dcb [ -f | --force ] { -b | --batch } filename [ -N | --Netns ] netnsname\n"
-		"where  OBJECT := { ets | pfc }\n"
+		"where  OBJECT := { buffer | ets | pfc }\n"
 		"       OPTIONS := [ -V | --Version | -i | --iec | -j | --json\n"
 		"                  | -p | --pretty | -s | --statistics | -v | --verbose]\n");
 }
@@ -342,6 +342,8 @@ static int dcb_cmd(struct dcb *dcb, int argc, char **argv)
 	if (!argc || matches(*argv, "help") == 0) {
 		dcb_help();
 		return 0;
+	} else if (matches(*argv, "buffer") == 0) {
+		return dcb_cmd_buffer(dcb, argc - 1, argv + 1);
 	} else if (matches(*argv, "ets") == 0) {
 		return dcb_cmd_ets(dcb, argc - 1, argv + 1);
 	} else if (matches(*argv, "pfc") == 0) {
diff --git a/dcb/dcb.h b/dcb/dcb.h
index 4ecc6afd59a9..0638d63938fc 100644
--- a/dcb/dcb.h
+++ b/dcb/dcb.h
@@ -42,6 +42,10 @@ void dcb_print_array_on_off(const __u8 *array, size_t size);
 void dcb_print_array_kw(const __u8 *array, size_t array_size,
 			const char *const kw[], size_t kw_size);
 
+/* dcb_buffer.c */
+
+int dcb_cmd_buffer(struct dcb *dcb, int argc, char **argv);
+
 /* dcb_ets.c */
 
 int dcb_cmd_ets(struct dcb *dcb, int argc, char **argv);
diff --git a/dcb/dcb_buffer.c b/dcb/dcb_buffer.c
new file mode 100644
index 000000000000..e6a88a00f4a6
--- /dev/null
+++ b/dcb/dcb_buffer.c
@@ -0,0 +1,235 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <linux/dcbnl.h>
+
+#include "dcb.h"
+#include "utils.h"
+
+static void dcb_buffer_help_set(void)
+{
+	fprintf(stderr,
+		"Usage: dcb buffer set dev STRING\n"
+		"           [ prio-buffer PRIO-MAP ]\n"
+		"           [ buffer-size SIZE-MAP ]\n"
+		"\n"
+		" where PRIO-MAP := [ PRIO-MAP ] PRIO-MAPPING\n"
+		"       PRIO-MAPPING := { all | PRIO }:BUFFER\n"
+		"       SIZE-MAP := [ SIZE-MAP ] SIZE-MAPPING\n"
+		"       SIZE-MAPPING := { all | BUFFER }:INTEGER\n"
+		"       PRIO := { 0 .. 7 }\n"
+		"       BUFFER := { 0 .. 7 }\n"
+		"\n"
+	);
+}
+
+static void dcb_buffer_help_show(void)
+{
+	fprintf(stderr,
+		"Usage: dcb buffer show dev STRING\n"
+		"           [ prio-buffer ] [ buffer-size ] [ total-size ]\n"
+		"\n"
+	);
+}
+
+static void dcb_buffer_help(void)
+{
+	fprintf(stderr,
+		"Usage: dcb buffer help\n"
+		"\n"
+	);
+	dcb_buffer_help_show();
+	dcb_buffer_help_set();
+}
+
+static int dcb_buffer_parse_mapping_prio_buffer(__u32 key, char *value, void *data)
+{
+	struct dcbnl_buffer *buffer = data;
+	__u8 buf;
+
+	if (get_u8(&buf, value, 0))
+		return -EINVAL;
+
+	return dcb_parse_mapping("PRIO", key, IEEE_8021Q_MAX_PRIORITIES - 1,
+				 "BUFFER", buf, DCBX_MAX_BUFFERS - 1,
+				 dcb_set_u8, buffer->prio2buffer);
+}
+
+static int dcb_buffer_parse_mapping_buffer_size(__u32 key, char *value, void *data)
+{
+	struct dcbnl_buffer *buffer = data;
+	unsigned int size;
+
+	if (get_size(&size, value)) {
+		fprintf(stderr, "%d:%s: Illegal value for buffer size\n", key, value);
+		return -EINVAL;
+	}
+
+	return dcb_parse_mapping("BUFFER", key, DCBX_MAX_BUFFERS - 1,
+				 "INTEGER", size, -1,
+				 dcb_set_u32, buffer->buffer_size);
+}
+
+static void dcb_buffer_print_total_size(const struct dcbnl_buffer *buffer)
+{
+	print_size(PRINT_ANY, "total_size", "total-size %s ", buffer->total_size);
+}
+
+static void dcb_buffer_print_prio_buffer(const struct dcbnl_buffer *buffer)
+{
+	dcb_print_named_array("prio_buffer", "prio-buffer",
+			      buffer->prio2buffer, ARRAY_SIZE(buffer->prio2buffer),
+			      dcb_print_array_u8);
+}
+
+static void dcb_buffer_print_buffer_size(const struct dcbnl_buffer *buffer)
+{
+	size_t size = ARRAY_SIZE(buffer->buffer_size);
+	SPRINT_BUF(b);
+	size_t i;
+
+	open_json_array(PRINT_JSON, "buffer_size");
+	print_string(PRINT_FP, NULL, "buffer-size ", NULL);
+
+	for (i = 0; i < size; i++) {
+		snprintf(b, sizeof(b), "%zd:%%s ", i);
+		print_size(PRINT_ANY, NULL, b, buffer->buffer_size[i]);
+	}
+
+	close_json_array(PRINT_JSON, "buffer_size");
+}
+
+static void dcb_buffer_print(const struct dcbnl_buffer *buffer)
+{
+	dcb_buffer_print_prio_buffer(buffer);
+	print_nl();
+
+	dcb_buffer_print_buffer_size(buffer);
+	print_nl();
+
+	dcb_buffer_print_total_size(buffer);
+	print_nl();
+}
+
+static int dcb_buffer_get(struct dcb *dcb, const char *dev, struct dcbnl_buffer *buffer)
+{
+	return dcb_get_attribute(dcb, dev, DCB_ATTR_DCB_BUFFER, buffer, sizeof(*buffer));
+}
+
+static int dcb_buffer_set(struct dcb *dcb, const char *dev, const struct dcbnl_buffer *buffer)
+{
+	return dcb_set_attribute(dcb, dev, DCB_ATTR_DCB_BUFFER, buffer, sizeof(*buffer));
+}
+
+static int dcb_cmd_buffer_set(struct dcb *dcb, const char *dev, int argc, char **argv)
+{
+	struct dcbnl_buffer buffer;
+	int ret;
+
+	if (!argc) {
+		dcb_buffer_help_set();
+		return 0;
+	}
+
+	ret = dcb_buffer_get(dcb, dev, &buffer);
+	if (ret)
+		return ret;
+
+	do {
+		if (matches(*argv, "help") == 0) {
+			dcb_buffer_help_set();
+			return 0;
+		} else if (matches(*argv, "prio-buffer") == 0) {
+			NEXT_ARG();
+			ret = parse_mapping(&argc, &argv, true,
+					    &dcb_buffer_parse_mapping_prio_buffer, &buffer);
+			if (ret) {
+				fprintf(stderr, "Invalid priority mapping %s\n", *argv);
+				return ret;
+			}
+			continue;
+		} else if (matches(*argv, "buffer-size") == 0) {
+			NEXT_ARG();
+			ret = parse_mapping(&argc, &argv, true,
+					    &dcb_buffer_parse_mapping_buffer_size, &buffer);
+			if (ret) {
+				fprintf(stderr, "Invalid buffer size mapping %s\n", *argv);
+				return ret;
+			}
+			continue;
+		} else {
+			fprintf(stderr, "What is \"%s\"?\n", *argv);
+			dcb_buffer_help_set();
+			return -EINVAL;
+		}
+
+		NEXT_ARG_FWD();
+	} while (argc > 0);
+
+	return dcb_buffer_set(dcb, dev, &buffer);
+}
+
+static int dcb_cmd_buffer_show(struct dcb *dcb, const char *dev, int argc, char **argv)
+{
+	struct dcbnl_buffer buffer;
+	int ret;
+
+	ret = dcb_buffer_get(dcb, dev, &buffer);
+	if (ret)
+		return ret;
+
+	open_json_object(NULL);
+
+	if (!argc) {
+		dcb_buffer_print(&buffer);
+		goto out;
+	}
+
+	do {
+		if (matches(*argv, "help") == 0) {
+			dcb_buffer_help_show();
+			return 0;
+		} else if (matches(*argv, "prio-buffer") == 0) {
+			dcb_buffer_print_prio_buffer(&buffer);
+			print_nl();
+		} else if (matches(*argv, "buffer-size") == 0) {
+			dcb_buffer_print_buffer_size(&buffer);
+			print_nl();
+		} else if (matches(*argv, "total-size") == 0) {
+			dcb_buffer_print_total_size(&buffer);
+			print_nl();
+		} else {
+			fprintf(stderr, "What is \"%s\"?\n", *argv);
+			dcb_buffer_help_show();
+			return -EINVAL;
+		}
+
+		NEXT_ARG_FWD();
+	} while (argc > 0);
+
+out:
+	close_json_object();
+	return 0;
+}
+
+int dcb_cmd_buffer(struct dcb *dcb, int argc, char **argv)
+{
+	if (!argc || matches(*argv, "help") == 0) {
+		dcb_buffer_help();
+		return 0;
+	} else if (matches(*argv, "show") == 0) {
+		NEXT_ARG_FWD();
+		return dcb_cmd_parse_dev(dcb, argc, argv,
+					 dcb_cmd_buffer_show, dcb_buffer_help_show);
+	} else if (matches(*argv, "set") == 0) {
+		NEXT_ARG_FWD();
+		return dcb_cmd_parse_dev(dcb, argc, argv,
+					 dcb_cmd_buffer_set, dcb_buffer_help_set);
+	} else {
+		fprintf(stderr, "What is \"%s\"?\n", *argv);
+		dcb_buffer_help();
+		return -EINVAL;
+	}
+}
diff --git a/man/man8/dcb-buffer.8 b/man/man8/dcb-buffer.8
new file mode 100644
index 000000000000..c7ba6a993ee6
--- /dev/null
+++ b/man/man8/dcb-buffer.8
@@ -0,0 +1,126 @@
+.TH DCB-BUFFER 8 "12 November 2020" "iproute2" "Linux"
+.SH NAME
+dcb-buffer \- show / manipulate port buffer settings of
+the DCB (Data Center Bridging) subsystem
+.SH SYNOPSIS
+.sp
+.ad l
+.in +8
+
+.ti -8
+.B dcb
+.RI "[ " OPTIONS " ] "
+.B buffer
+.RI "{ " COMMAND " | " help " }"
+.sp
+
+.ti -8
+.B dcb buffer show dev
+.RI DEV
+.RB "[ " prio-buffer " ]"
+.RB "[ " buffer-size " ]"
+.RB "[ " total-size " ]"
+
+.ti -8
+.B dcb buffer set dev
+.RI DEV
+.RB "[ " prio-buffer " " \fIPRIO-MAP " ]"
+.RB "[ " buffer-size " " \fISIZE-MAP " ]"
+
+.ti -8
+.IR PRIO-MAP " := [ " PRIO-MAP " ] " PRIO-MAPPING
+
+.ti -8
+.IR PRIO-MAPPING " := { " PRIO " | " \fBall " }" \fB:\fIBUFFER\fR
+
+.ti -8
+.IR SIZE-MAP " := [ " SIZE-MAP " ] " SIZE-MAPPING
+
+.ti -8
+.IR SIZE-MAPPING " := { " BUFFER " | " \fBall " }" \fB:\fISIZE\fR
+
+.ti -8
+.IR PRIO " := { " \fB0\fR " .. " \fB7\fR " }"
+
+.ti -8
+.IR BUFFER " := { " \fB0\fR " .. " \fB7\fR " }"
+
+.ti -8
+.IR SIZE " := { " INTEGER " | " INTEGER\fBK\fR " | " INTEGER\fBM\fR " | " ... " }"
+
+.SH DESCRIPTION
+
+.B dcb buffer
+is used to configure assignment of traffic to port buffers based on traffic
+priority, and sizes of those buffers. It can be also used to inspect the current
+configuration, as well as total device memory that the port buffers take.
+
+.SH PARAMETERS
+
+For read-write parameters, the following describes only the write direction,
+i.e. as used with the \fBset\fR command. For the \fBshow\fR command, the
+parameter name is to be used as a simple keyword without further arguments. This
+instructs the tool to show the value of a given parameter. When no parameters
+are given, the tool shows the complete buffer configuration.
+
+.TP
+.B total-size
+A read-only property that shows the total device memory taken up by port
+buffers. This might be more than a simple sum of individual buffer sizes if
+there are any hidden or internal buffers.
+
+.TP
+.B prio-buffer \fIPRIO-MAP
+\fIPRIO-MAP\fR uses the array parameter syntax, see
+.BR dcb (8)
+for details. Keys are priorities, values are buffer indices. For each priority
+sets a buffer where traffic with that priority is directed to.
+
+.TP
+.B buffer-size \fISIZE-MAP
+\fISIZE-MAP\fR uses the array parameter syntax, see
+.BR dcb (8)
+for details. Keys are buffer indices, values are sizes of that buffer in bytes.
+The sizes can use the notation documented in section PARAMETERS at
+.BR tc (8).
+Note that the size requested by the tool can be rounded or capped by the driver
+to satisfy the requirements of the device.
+
+.SH EXAMPLE & USAGE
+
+Configure the priomap in a one-to-one fashion:
+
+.P
+# dcb buffer set dev eth0 prio-buffer 0:0 1:1 2:2 3:3 4:4 5:5 6:6 7:7
+
+Set sizes of all buffers to 10KB, except for buffer 6, which will have the size
+1MB:
+
+.P
+# dcb buffer set dev eth0 buffer-size all:10K 6:1M
+
+Show what was set:
+
+.P
+# dcb buffer show dev eth0
+.br
+prio-buffer 0:0 1:1 2:2 3:3 4:4 5:5 6:6 7:7
+.br
+buffer-size 0:10Kb 1:10Kb 2:10Kb 3:10Kb 4:10Kb 5:10Kb 6:1Mb 7:10Kb
+.br
+total-size 1222Kb
+
+.SH EXIT STATUS
+Exit status is 0 if command was successful or a positive integer upon failure.
+
+.SH SEE ALSO
+.BR dcb (8)
+
+.SH REPORTING BUGS
+Report any bugs to the Network Developers mailing list
+.B <netdev@vger.kernel.org>
+where the development and maintenance is primarily done.
+You do not have to be subscribed to the list to send a message there.
+
+.SH AUTHOR
+Petr Machata <me@pmachata.org>
diff --git a/man/man8/dcb.8 b/man/man8/dcb.8
index 01febe166bdf..e14762365cef 100644
--- a/man/man8/dcb.8
+++ b/man/man8/dcb.8
@@ -9,7 +9,7 @@ dcb \- show / manipulate DCB (Data Center Bridging) settings
 .ti -8
 .B dcb
 .RI "[ " OPTIONS " ] "
-.RB "{ " ets " | " pfc " }"
+.RB "{ " buffer " | " ets " | " pfc " }"
 .RI "{ " COMMAND " | " help " }"
 .sp
 
@@ -63,6 +63,10 @@ part of the "show" output.
 
 .SH OBJECTS
 
+.TP
+.B buffer
+- Configuration of port buffers
+
 .TP
 .B ets
 - Configuration of ETS (Enhanced Transmission Selection)
@@ -115,6 +119,7 @@ other values:
 Exit status is 0 if command was successful or a positive integer upon failure.
 
 .SH SEE ALSO
+.BR dcb-buffer (8),
 .BR dcb-ets (8),
 .BR dcb-pfc (8)
 .br
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH iproute2-next 10/10] dcb: Add a subtool for the DCB maxrate object
  2020-12-10 23:02 [PATCH iproute2-next 00/10] dcb: Support PFC, buffer, maxrate objects Petr Machata
                   ` (8 preceding siblings ...)
  2020-12-10 23:02 ` [PATCH iproute2-next 09/10] dcb: Add a subtool for the DCB buffer object Petr Machata
@ 2020-12-10 23:02 ` Petr Machata
  2020-12-14 16:51 ` [PATCH iproute2-next 00/10] dcb: Support PFC, buffer, maxrate objects David Ahern
  10 siblings, 0 replies; 12+ messages in thread
From: Petr Machata @ 2020-12-10 23:02 UTC (permalink / raw)
  To: netdev, dsahern, stephen; +Cc: Petr Machata

DCBNL maxrate interfaces are an extension to the 802.1q DCB interfaces and
allow configuration of rate with which traffic in a given traffic class is
sent.

Add a dcb subtool to allow showing and tweaking of this per-TC maximum
rate. For example:

    # dcb maxrate show dev eni1np1
    tc-maxrate 0:25Gbit 1:25Gbit 2:25Gbit 3:25Gbit 4:25Gbit 5:25Gbit 6:100Gbit 7:25Gbit

Signed-off-by: Petr Machata <me@pmachata.org>
---
 dcb/Makefile           |   2 +-
 dcb/dcb.c              |   4 +-
 dcb/dcb.h              |   4 +
 dcb/dcb_maxrate.c      | 182 +++++++++++++++++++++++++++++++++++++++++
 man/man8/dcb-maxrate.8 |  94 +++++++++++++++++++++
 man/man8/dcb.8         |   7 +-
 6 files changed, 290 insertions(+), 3 deletions(-)
 create mode 100644 dcb/dcb_maxrate.c
 create mode 100644 man/man8/dcb-maxrate.8

diff --git a/dcb/Makefile b/dcb/Makefile
index dc84422f6096..4add954b4bba 100644
--- a/dcb/Makefile
+++ b/dcb/Makefile
@@ -5,7 +5,7 @@ TARGETS :=
 
 ifeq ($(HAVE_MNL),y)
 
-DCBOBJ = dcb.o dcb_buffer.o dcb_ets.o dcb_pfc.o
+DCBOBJ = dcb.o dcb_buffer.o dcb_ets.o dcb_maxrate.o dcb_pfc.o
 TARGETS += dcb
 
 endif
diff --git a/dcb/dcb.c b/dcb/dcb.c
index 570405a7e628..adec57476e1d 100644
--- a/dcb/dcb.c
+++ b/dcb/dcb.c
@@ -332,7 +332,7 @@ static void dcb_help(void)
 	fprintf(stderr,
 		"Usage: dcb [ OPTIONS ] OBJECT { COMMAND | help }\n"
 		"       dcb [ -f | --force ] { -b | --batch } filename [ -N | --Netns ] netnsname\n"
-		"where  OBJECT := { buffer | ets | pfc }\n"
+		"where  OBJECT := { buffer | ets | maxrate | pfc }\n"
 		"       OPTIONS := [ -V | --Version | -i | --iec | -j | --json\n"
 		"                  | -p | --pretty | -s | --statistics | -v | --verbose]\n");
 }
@@ -346,6 +346,8 @@ static int dcb_cmd(struct dcb *dcb, int argc, char **argv)
 		return dcb_cmd_buffer(dcb, argc - 1, argv + 1);
 	} else if (matches(*argv, "ets") == 0) {
 		return dcb_cmd_ets(dcb, argc - 1, argv + 1);
+	} else if (matches(*argv, "maxrate") == 0) {
+		return dcb_cmd_maxrate(dcb, argc - 1, argv + 1);
 	} else if (matches(*argv, "pfc") == 0) {
 		return dcb_cmd_pfc(dcb, argc - 1, argv + 1);
 	}
diff --git a/dcb/dcb.h b/dcb/dcb.h
index 0638d63938fc..388a4204b95c 100644
--- a/dcb/dcb.h
+++ b/dcb/dcb.h
@@ -50,6 +50,10 @@ int dcb_cmd_buffer(struct dcb *dcb, int argc, char **argv);
 
 int dcb_cmd_ets(struct dcb *dcb, int argc, char **argv);
 
+/* dcb_maxrate.c */
+
+int dcb_cmd_maxrate(struct dcb *dcb, int argc, char **argv);
+
 /* dcb_pfc.c */
 
 int dcb_cmd_pfc(struct dcb *dcb, int argc, char **argv);
diff --git a/dcb/dcb_maxrate.c b/dcb/dcb_maxrate.c
new file mode 100644
index 000000000000..1538c6d7c4cf
--- /dev/null
+++ b/dcb/dcb_maxrate.c
@@ -0,0 +1,182 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <linux/dcbnl.h>
+
+#include "dcb.h"
+#include "utils.h"
+
+static void dcb_maxrate_help_set(void)
+{
+	fprintf(stderr,
+		"Usage: dcb maxrate set dev STRING\n"
+		"           [ tc-maxrate RATE-MAP ]\n"
+		"\n"
+		" where RATE-MAP := [ RATE-MAP ] RATE-MAPPING\n"
+		"       RATE-MAPPING := { all | TC }:RATE\n"
+		"       TC := { 0 .. 7 }\n"
+		"\n"
+	);
+}
+
+static void dcb_maxrate_help_show(void)
+{
+	fprintf(stderr,
+		"Usage: dcb [ -i ] maxrate show dev STRING\n"
+		"           [ tc-maxrate ]\n"
+		"\n"
+	);
+}
+
+static void dcb_maxrate_help(void)
+{
+	fprintf(stderr,
+		"Usage: dcb maxrate help\n"
+		"\n"
+	);
+	dcb_maxrate_help_show();
+	dcb_maxrate_help_set();
+}
+
+static int dcb_maxrate_parse_mapping_tc_maxrate(__u32 key, char *value, void *data)
+{
+	__u64 rate;
+
+	if (get_rate64(&rate, value))
+		return -EINVAL;
+
+	return dcb_parse_mapping("TC", key, IEEE_8021QAZ_MAX_TCS - 1,
+				 "RATE", rate, -1,
+				 dcb_set_u64, data);
+}
+
+static void dcb_maxrate_print_tc_maxrate(struct dcb *dcb, const struct ieee_maxrate *maxrate)
+{
+	size_t size = ARRAY_SIZE(maxrate->tc_maxrate);
+	SPRINT_BUF(b);
+	size_t i;
+
+	open_json_array(PRINT_JSON, "tc_maxrate");
+	print_string(PRINT_FP, NULL, "tc-maxrate ", NULL);
+
+	for (i = 0; i < size; i++) {
+		snprintf(b, sizeof(b), "%zd:%%s ", i);
+		print_rate(dcb->use_iec, PRINT_ANY, NULL, b, maxrate->tc_maxrate[i]);
+	}
+
+	close_json_array(PRINT_JSON, "tc_maxrate");
+}
+
+static void dcb_maxrate_print(struct dcb *dcb, const struct ieee_maxrate *maxrate)
+{
+	dcb_maxrate_print_tc_maxrate(dcb, maxrate);
+	print_nl();
+}
+
+static int dcb_maxrate_get(struct dcb *dcb, const char *dev, struct ieee_maxrate *maxrate)
+{
+	return dcb_get_attribute(dcb, dev, DCB_ATTR_IEEE_MAXRATE, maxrate, sizeof(*maxrate));
+}
+
+static int dcb_maxrate_set(struct dcb *dcb, const char *dev, const struct ieee_maxrate *maxrate)
+{
+	return dcb_set_attribute(dcb, dev, DCB_ATTR_IEEE_MAXRATE, maxrate, sizeof(*maxrate));
+}
+
+static int dcb_cmd_maxrate_set(struct dcb *dcb, const char *dev, int argc, char **argv)
+{
+	struct ieee_maxrate maxrate;
+	int ret;
+
+	if (!argc) {
+		dcb_maxrate_help_set();
+		return 0;
+	}
+
+	ret = dcb_maxrate_get(dcb, dev, &maxrate);
+	if (ret)
+		return ret;
+
+	do {
+		if (matches(*argv, "help") == 0) {
+			dcb_maxrate_help_set();
+			return 0;
+		} else if (matches(*argv, "tc-maxrate") == 0) {
+			NEXT_ARG();
+			ret = parse_mapping(&argc, &argv, true,
+					    &dcb_maxrate_parse_mapping_tc_maxrate, &maxrate);
+			if (ret) {
+				fprintf(stderr, "Invalid mapping %s\n", *argv);
+				return ret;
+			}
+			continue;
+		} else {
+			fprintf(stderr, "What is \"%s\"?\n", *argv);
+			dcb_maxrate_help_set();
+			return -EINVAL;
+		}
+
+		NEXT_ARG_FWD();
+	} while (argc > 0);
+
+	return dcb_maxrate_set(dcb, dev, &maxrate);
+}
+
+static int dcb_cmd_maxrate_show(struct dcb *dcb, const char *dev, int argc, char **argv)
+{
+	struct ieee_maxrate maxrate;
+	int ret;
+
+	ret = dcb_maxrate_get(dcb, dev, &maxrate);
+	if (ret)
+		return ret;
+
+	open_json_object(NULL);
+
+	if (!argc) {
+		dcb_maxrate_print(dcb, &maxrate);
+		goto out;
+	}
+
+	do {
+		if (matches(*argv, "help") == 0) {
+			dcb_maxrate_help_show();
+			return 0;
+		} else if (matches(*argv, "tc-maxrate") == 0) {
+			dcb_maxrate_print_tc_maxrate(dcb, &maxrate);
+			print_nl();
+		} else {
+			fprintf(stderr, "What is \"%s\"?\n", *argv);
+			dcb_maxrate_help_show();
+			return -EINVAL;
+		}
+
+		NEXT_ARG_FWD();
+	} while (argc > 0);
+
+out:
+	close_json_object();
+	return 0;
+}
+
+int dcb_cmd_maxrate(struct dcb *dcb, int argc, char **argv)
+{
+	if (!argc || matches(*argv, "help") == 0) {
+		dcb_maxrate_help();
+		return 0;
+	} else if (matches(*argv, "show") == 0) {
+		NEXT_ARG_FWD();
+		return dcb_cmd_parse_dev(dcb, argc, argv,
+					 dcb_cmd_maxrate_show, dcb_maxrate_help_show);
+	} else if (matches(*argv, "set") == 0) {
+		NEXT_ARG_FWD();
+		return dcb_cmd_parse_dev(dcb, argc, argv,
+					 dcb_cmd_maxrate_set, dcb_maxrate_help_set);
+	} else {
+		fprintf(stderr, "What is \"%s\"?\n", *argv);
+		dcb_maxrate_help();
+		return -EINVAL;
+	}
+}
diff --git a/man/man8/dcb-maxrate.8 b/man/man8/dcb-maxrate.8
new file mode 100644
index 000000000000..d03c215c08ed
--- /dev/null
+++ b/man/man8/dcb-maxrate.8
@@ -0,0 +1,94 @@
+.TH DCB-MAXRATE 8 "22 November 2020" "iproute2" "Linux"
+.SH NAME
+dcb-maxrate \- show / manipulate port maxrate settings of
+the DCB (Data Center Bridging) subsystem
+.SH SYNOPSIS
+.sp
+.ad l
+.in +8
+
+.ti -8
+.B dcb
+.RI "[ " OPTIONS " ] "
+.B maxrate
+.RI "{ " COMMAND " | " help " }"
+.sp
+
+.ti -8
+.B dcb maxrate show dev
+.RI DEV
+.RB "[ " tc-maxrate " ]"
+
+.ti -8
+.B dcb maxrate set dev
+.RI DEV
+.RB "[ " tc-maxrate " " \fIRATE-MAP " ]"
+
+.ti -8
+.IR RATE-MAP " := [ " RATE-MAP " ] " RATE-MAPPING
+
+.ti -8
+.IR RATE-MAPPING " := { " TC " | " \fBall " }" \fB:\fIRATE\fR
+
+.ti -8
+.IR TC " := { " \fB0\fR " .. " \fB7\fR " }"
+
+.ti -8
+.IR RATE " := { " INTEGER "[" \fBbit\fR "] | " INTEGER\fBKbit\fR " | "
+.IR INTEGER\fBMib\fR " | " ... " }"
+
+.SH DESCRIPTION
+
+.B dcb maxrate
+is used to configure and inspect maximum rate at which traffic is allowed to
+egress from a given traffic class.
+
+.SH PARAMETERS
+
+The following describes only the write direction, i.e. as used with the
+\fBset\fR command. For the \fBshow\fR command, the parameter name is to be used
+as a simple keyword without further arguments. This instructs the tool to show
+the value of a given parameter. When no parameters are given, the tool shows the
+complete maxrate configuration.
+
+.TP
+.B tc-maxrate \fIRATE-MAP
+\fIRATE-MAP\fR uses the array parameter syntax, see
+.BR dcb (8)
+for details. Keys are TC indices, values are traffic rates in bits per second.
+The rates can use the notation documented in section PARAMETERS at
+.BR tc (8).
+Note that under that notation, "bit" stands for bits per second whereas "b"
+stands for bytes per second. When showing, the command line option
+.B -i
+toggles between using decadic and ISO/IEC prefixes.
+
+.SH EXAMPLE & USAGE
+
+Set rates of all traffic classes to 25Gbps, except for TC 6, which will
+have the rate of 100Gbps:
+
+.P
+# dcb maxrate set dev eth0 tc-maxrate all:25Gbit 6:100Gbit
+
+Show what was set:
+
+.P
+# dcb maxrate show dev eth0
+.br
+tc-maxrate 0:25Gbit 1:25Gbit 2:25Gbit 3:25Gbit 4:25Gbit 5:25Gbit 6:100Gbit 7:25Gbit
+
+.SH EXIT STATUS
+Exit status is 0 if command was successful or a positive integer upon failure.
+
+.SH SEE ALSO
+.BR dcb (8)
+
+.SH REPORTING BUGS
+Report any bugs to the Network Developers mailing list
+.B <netdev@vger.kernel.org>
+where the development and maintenance is primarily done.
+You do not have to be subscribed to the list to send a message there.
+
+.SH AUTHOR
+Petr Machata <me@pmachata.org>
diff --git a/man/man8/dcb.8 b/man/man8/dcb.8
index e14762365cef..5964f25d386d 100644
--- a/man/man8/dcb.8
+++ b/man/man8/dcb.8
@@ -9,7 +9,7 @@ dcb \- show / manipulate DCB (Data Center Bridging) settings
 .ti -8
 .B dcb
 .RI "[ " OPTIONS " ] "
-.RB "{ " buffer " | " ets " | " pfc " }"
+.RB "{ " buffer " | " ets " | " maxrate " | " pfc " }"
 .RI "{ " COMMAND " | " help " }"
 .sp
 
@@ -71,6 +71,10 @@ part of the "show" output.
 .B ets
 - Configuration of ETS (Enhanced Transmission Selection)
 
+.TP
+.B maxrate
+- Configuration of per-TC maximum transmit rate
+
 .TP
 .B pfc
 - Configuration of PFC (Priority-based Flow Control)
@@ -121,6 +125,7 @@ Exit status is 0 if command was successful or a positive integer upon failure.
 .SH SEE ALSO
 .BR dcb-buffer (8),
 .BR dcb-ets (8),
+.BR dcb-maxrate (8),
 .BR dcb-pfc (8)
 .br
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH iproute2-next 00/10] dcb: Support PFC, buffer, maxrate objects
  2020-12-10 23:02 [PATCH iproute2-next 00/10] dcb: Support PFC, buffer, maxrate objects Petr Machata
                   ` (9 preceding siblings ...)
  2020-12-10 23:02 ` [PATCH iproute2-next 10/10] dcb: Add a subtool for the DCB maxrate object Petr Machata
@ 2020-12-14 16:51 ` David Ahern
  10 siblings, 0 replies; 12+ messages in thread
From: David Ahern @ 2020-12-14 16:51 UTC (permalink / raw)
  To: Petr Machata, netdev, stephen

On 12/10/20 4:02 PM, Petr Machata wrote:
> Add support to the dcb tool for the following three DCB objects:
> 
> - PFC, for "Priority-based Flow Control", allows configuration of priority
>   lossiness, and related toggles.
> 
> - DCBNL buffer interfaces are an extension to the 802.1q DCB interfaces and
>   allow configuration of port headroom buffers.
> 
> - DCBNL maxrate interfaces are an extension to the 802.1q DCB interfaces
>   and allow configuration of rate with which traffic in a given traffic
>   class is sent.
> 
> Patches #1-#4 fix small issues in the current DCB code and man pages.
> 
> Patch #5 adds new helpers to the DCB dispatcher.
> 
> Patches #6 and #7 add support for command line arguments -s and -i. These
> enable, respectively, display of statistical counters, and ISO/IEC mode of
> rate units.
> 
> Patches #8-#10 add the subtools themselves and their man pages.
> 

applied to iproute2-next. Thanks, Petr.


^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2020-12-14 16:52 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-10 23:02 [PATCH iproute2-next 00/10] dcb: Support PFC, buffer, maxrate objects Petr Machata
2020-12-10 23:02 ` [PATCH iproute2-next 01/10] dcb: Remove unsupported command line arguments from getopt_long() Petr Machata
2020-12-10 23:02 ` [PATCH iproute2-next 02/10] dcb: ets: Fix help display for "show" subcommand Petr Machata
2020-12-10 23:02 ` [PATCH iproute2-next 03/10] dcb: ets: Change the way show parameters are given in synopsis Petr Machata
2020-12-10 23:02 ` [PATCH iproute2-next 04/10] man: dcb-ets: Remove an unnecessary empty line Petr Machata
2020-12-10 23:02 ` [PATCH iproute2-next 05/10] dcb: Add dcb_set_u32(), dcb_set_u64() Petr Machata
2020-12-10 23:02 ` [PATCH iproute2-next 06/10] dcb: Add -s to enable statistics Petr Machata
2020-12-10 23:02 ` [PATCH iproute2-next 07/10] dcb: Add -i to enable IEC mode Petr Machata
2020-12-10 23:02 ` [PATCH iproute2-next 08/10] dcb: Add a subtool for the DCB PFC object Petr Machata
2020-12-10 23:02 ` [PATCH iproute2-next 09/10] dcb: Add a subtool for the DCB buffer object Petr Machata
2020-12-10 23:02 ` [PATCH iproute2-next 10/10] dcb: Add a subtool for the DCB maxrate object Petr Machata
2020-12-14 16:51 ` [PATCH iproute2-next 00/10] dcb: Support PFC, buffer, maxrate objects David Ahern

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.