3397d6
From 6477a1f47b15c2a81a9995397942a0fc17f0b06f Mon Sep 17 00:00:00 2001
3397d6
From: Dustin Byford <dustin@cumulusnetworks.com>
3397d6
Date: Mon, 18 Dec 2017 14:57:41 -0800
3397d6
Subject: [PATCH 14/14] ethtool: Support for FEC encoding control
3397d6
3397d6
As FEC settings and different FEC modes are mandatory
3397d6
and configurable across various interfaces of 25G/50G/100G/40G,
3397d6
the lack of FEC encoding control and reporting today is a source
3397d6
for interoperability issues for many vendors
3397d6
3397d6
set-fec/show-fec option(s) are designed to provide control and report
3397d6
the FEC encoding on the link.
3397d6
3397d6
$ethtool --set-fec swp1 encoding [off | RS | BaseR | auto]
3397d6
3397d6
Encoding: Types of encoding
3397d6
Off    :  Turning off FEC
3397d6
RS     :  Force RS-FEC encoding
3397d6
BaseR  :  Force BaseR encoding
3397d6
Auto   :  Default FEC settings for drivers, and would represent
3397d6
          asking the hardware to essentially go into a best effort mode.
3397d6
3397d6
Here are a few examples of what we would expect if encoding=auto:
3397d6
- if autoneg is on, we are  expecting FEC to be negotiated as on or off
3397d6
  as long as protocol supports it
3397d6
- if the hardware is capable of detecting the FEC encoding on it's
3397d6
  receiver it will reconfigure its encoder to match
3397d6
- in absence of the above, the configuration would be set to IEEE
3397d6
  defaults.
3397d6
3397d6
>From our understanding, this is essentially what most hardware/driver
3397d6
combinations are doing today in the absence of a way for users to
3397d6
control the behavior.
3397d6
3397d6
$ethtool --show-fec  swp1
3397d6
FEC parameters for swp1:
3397d6
FEC encodings:  RS
3397d6
3397d6
ethtool devname output:
3397d6
$ethtool swp1
3397d6
Settings for swp1:
3397d6
root@hpe-7712-03:~# ethtool swp18
3397d6
Settings for swp18:
3397d6
    Supported ports: [ FIBRE ]
3397d6
    Supported link modes:   40000baseCR4/Full
3397d6
                            40000baseSR4/Full
3397d6
                            40000baseLR4/Full
3397d6
                            100000baseSR4/Full
3397d6
                            100000baseCR4/Full
3397d6
                            100000baseLR4_ER4/Full
3397d6
    Supported pause frame use: No
3397d6
    Supports auto-negotiation: Yes
3397d6
    Supported FEC modes: [RS | BaseR | None | Not reported]
3397d6
    Advertised link modes:  Not reported
3397d6
    Advertised pause frame use: No
3397d6
    Advertised auto-negotiation: No
3397d6
    Advertised FEC modes: [RS | BaseR | None | Not reported]
3397d6
    Speed: 100000Mb/s
3397d6
    Duplex: Full
3397d6
    Port: FIBRE
3397d6
    PHYAD: 106
3397d6
    Transceiver: internal
3397d6
    Auto-negotiation: off
3397d6
    Link detected: yes
3397d6
3397d6
Signed-off-by: Vidya Sagar Ravipati <vidya.chowdary@gmail.com>
3397d6
Signed-off-by: Dustin Byford <dustin@cumulusnetworks.com>
3397d6
[code style + man page edits + commit message update]
3397d6
Signed-off-by: Dirk van der Merwe <dirk.vandermerwe@netronome.com>
3397d6
Signed-off-by: John W. Linville <linville@tuxdriver.com>
3397d6
3397d6
(cherry picked from commit 8db75d1e4001ac4cdfc73d5bedd0ec6d58a3d617)
3397d6
3397d6
Conflicts:
3397d6
	ethtool.8.in
3397d6
	ethtool.c
3397d6
---
3397d6
 ethtool.8.in |  31 ++++++++++++++++
3397d6
 ethtool.c    | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3397d6
 2 files changed, 150 insertions(+)
3397d6
3397d6
diff --git a/ethtool.8.in b/ethtool.8.in
3397d6
index c176cac..6816020 100644
3397d6
--- a/ethtool.8.in
3397d6
+++ b/ethtool.8.in
3397d6
@@ -342,6 +342,13 @@ ethtool \- query or control network driver and hardware settings
3397d6
 .B2 tx-lpi on off
3397d6
 .BN tx-timer
3397d6
 .BN advertise
3397d6
+.HP
3397d6
+.B ethtool \-\-show\-fec
3397d6
+.I devname
3397d6
+.HP
3397d6
+.B ethtool \-\-set\-fec
3397d6
+.I devname
3397d6
+.B4 encoding auto off rs baser
3397d6
 .
3397d6
 .\" Adjust lines (i.e. full justification) and hyphenate.
3397d6
 .ad
3397d6
@@ -959,6 +966,30 @@ Values are as for
3397d6
 Sets the amount of time the device should stay in idle mode prior to asserting
3397d6
 its Tx LPI (in microseconds). This has meaning only when Tx LPI is enabled.
3397d6
 .RE
3397d6
+.TP
3397d6
+.B \-\-show\-fec
3397d6
+Queries the specified network device for its support of Forward Error Correction.
3397d6
+.TP
3397d6
+.B \-\-set\-fec
3397d6
+Configures Forward Error Correction for the specified network device.
3397d6
+
3397d6
+Forward Error Correction modes selected by a user are expected to be persisted
3397d6
+after any hotplug events. If a module is swapped that does not support the
3397d6
+current FEC mode, the driver or firmware must take the link down
3397d6
+administratively and report the problem in the system logs for users to correct.
3397d6
+.RS 4
3397d6
+.TP
3397d6
+.A4 encoding auto off rs baser
3397d6
+Sets the FEC encoding for the device.
3397d6
+.TS
3397d6
+nokeep;
3397d6
+lB	l.
3397d6
+auto	Use the driver's default encoding
3397d6
+off	Turn off FEC
3397d6
+RS	Force RS-FEC encoding
3397d6
+BaseR	Force BaseR encoding
3397d6
+.TE
3397d6
+.RE
3397d6
 .SH BUGS
3397d6
 Not supported (in part or whole) on all network drivers.
3397d6
 .SH AUTHOR
3397d6
diff --git a/ethtool.c b/ethtool.c
3397d6
index 1411d62..2e9ee2c 100644
3397d6
--- a/ethtool.c
3397d6
+++ b/ethtool.c
3397d6
@@ -543,6 +543,9 @@ static void init_global_link_mode_masks(void)
3397d6
 		ETHTOOL_LINK_MODE_Pause_BIT,
3397d6
 		ETHTOOL_LINK_MODE_Asym_Pause_BIT,
3397d6
 		ETHTOOL_LINK_MODE_Backplane_BIT,
3397d6
+		ETHTOOL_LINK_MODE_FEC_NONE_BIT,
3397d6
+		ETHTOOL_LINK_MODE_FEC_RS_BIT,
3397d6
+		ETHTOOL_LINK_MODE_FEC_BASER_BIT,
3397d6
 	};
3397d6
 	unsigned int i;
3397d6
 
3397d6
@@ -690,6 +693,7 @@ static void dump_link_caps(const char *prefix, const char *an_prefix,
3397d6
 	};
3397d6
 	int indent;
3397d6
 	int did1, new_line_pend, i;
3397d6
+	int fecreported = 0;
3397d6
 
3397d6
 	/* Indent just like the separate functions used to */
3397d6
 	indent = strlen(prefix) + 14;
3397d6
@@ -741,6 +745,26 @@ static void dump_link_caps(const char *prefix, const char *an_prefix,
3397d6
 			fprintf(stdout, "Yes\n");
3397d6
 		else
3397d6
 			fprintf(stdout, "No\n");
3397d6
+
3397d6
+		fprintf(stdout, "	%s FEC modes:", prefix);
3397d6
+		if (ethtool_link_mode_test_bit(ETHTOOL_LINK_MODE_FEC_NONE_BIT,
3397d6
+					       mask)) {
3397d6
+			fprintf(stdout, " None");
3397d6
+			fecreported = 1;
3397d6
+		}
3397d6
+		if (ethtool_link_mode_test_bit(ETHTOOL_LINK_MODE_FEC_BASER_BIT,
3397d6
+					       mask)) {
3397d6
+			fprintf(stdout, " BaseR");
3397d6
+			fecreported = 1;
3397d6
+		}
3397d6
+		if (ethtool_link_mode_test_bit(ETHTOOL_LINK_MODE_FEC_RS_BIT,
3397d6
+					       mask)) {
3397d6
+			fprintf(stdout, " RS");
3397d6
+			fecreported = 1;
3397d6
+		}
3397d6
+		if (!fecreported)
3397d6
+			fprintf(stdout, " Not reported");
3397d6
+		fprintf(stdout, "\n");
3397d6
 	}
3397d6
 }
3397d6
 
3397d6
@@ -1569,6 +1593,20 @@ static void dump_eeecmd(struct ethtool_eee *ep)
3397d6
 	dump_link_caps("Link partner advertised EEE", "", link_mode, 1);
3397d6
 }
3397d6
 
3397d6
+static void dump_fec(u32 fec)
3397d6
+{
3397d6
+	if (fec & ETHTOOL_FEC_NONE)
3397d6
+		fprintf(stdout, " None");
3397d6
+	if (fec & ETHTOOL_FEC_AUTO)
3397d6
+		fprintf(stdout, " Auto");
3397d6
+	if (fec & ETHTOOL_FEC_OFF)
3397d6
+		fprintf(stdout, " Off");
3397d6
+	if (fec & ETHTOOL_FEC_BASER)
3397d6
+		fprintf(stdout, " BaseR");
3397d6
+	if (fec & ETHTOOL_FEC_RS)
3397d6
+		fprintf(stdout, " RS");
3397d6
+}
3397d6
+
3397d6
 #define N_SOTS 7
3397d6
 
3397d6
 static char *so_timestamping_labels[N_SOTS] = {
3397d6
@@ -4592,6 +4630,84 @@ static int do_seee(struct cmd_context *ctx)
3397d6
 	return 0;
3397d6
 }
3397d6
 
3397d6
+static int fecmode_str_to_type(const char *str)
3397d6
+{
3397d6
+	int fecmode = 0;
3397d6
+
3397d6
+	if (!str)
3397d6
+		return fecmode;
3397d6
+
3397d6
+	if (!strcasecmp(str, "auto"))
3397d6
+		fecmode |= ETHTOOL_FEC_AUTO;
3397d6
+	else if (!strcasecmp(str, "off"))
3397d6
+		fecmode |= ETHTOOL_FEC_OFF;
3397d6
+	else if (!strcasecmp(str, "rs"))
3397d6
+		fecmode |= ETHTOOL_FEC_RS;
3397d6
+	else if (!strcasecmp(str, "baser"))
3397d6
+		fecmode |= ETHTOOL_FEC_BASER;
3397d6
+
3397d6
+	return fecmode;
3397d6
+}
3397d6
+
3397d6
+static int do_gfec(struct cmd_context *ctx)
3397d6
+{
3397d6
+	struct ethtool_fecparam feccmd = { 0 };
3397d6
+	int rv;
3397d6
+
3397d6
+	if (ctx->argc != 0)
3397d6
+		exit_bad_args();
3397d6
+
3397d6
+	feccmd.cmd = ETHTOOL_GFECPARAM;
3397d6
+	rv = send_ioctl(ctx, &feccmd);
3397d6
+	if (rv != 0) {
3397d6
+		perror("Cannot get FEC settings");
3397d6
+		return rv;
3397d6
+	}
3397d6
+
3397d6
+	fprintf(stdout, "FEC parameters for %s:\n", ctx->devname);
3397d6
+	fprintf(stdout, "Configured FEC encodings:");
3397d6
+	dump_fec(feccmd.fec);
3397d6
+	fprintf(stdout, "\n");
3397d6
+
3397d6
+	fprintf(stdout, "Active FEC encoding:");
3397d6
+	dump_fec(feccmd.active_fec);
3397d6
+	fprintf(stdout, "\n");
3397d6
+
3397d6
+	return 0;
3397d6
+}
3397d6
+
3397d6
+static int do_sfec(struct cmd_context *ctx)
3397d6
+{
3397d6
+	char *fecmode_str = NULL;
3397d6
+	struct ethtool_fecparam feccmd;
3397d6
+	struct cmdline_info cmdline_fec[] = {
3397d6
+		{ "encoding", CMDL_STR,  &fecmode_str,  &feccmd.fec},
3397d6
+	};
3397d6
+	int changed;
3397d6
+	int fecmode;
3397d6
+	int rv;
3397d6
+
3397d6
+	parse_generic_cmdline(ctx, &changed, cmdline_fec,
3397d6
+			      ARRAY_SIZE(cmdline_fec));
3397d6
+
3397d6
+	if (!fecmode_str)
3397d6
+		exit_bad_args();
3397d6
+
3397d6
+	fecmode = fecmode_str_to_type(fecmode_str);
3397d6
+	if (!fecmode)
3397d6
+		exit_bad_args();
3397d6
+
3397d6
+	feccmd.cmd = ETHTOOL_SFECPARAM;
3397d6
+	feccmd.fec = fecmode;
3397d6
+	rv = send_ioctl(ctx, &feccmd);
3397d6
+	if (rv != 0) {
3397d6
+		perror("Cannot set FEC settings");
3397d6
+		return rv;
3397d6
+	}
3397d6
+
3397d6
+	return 0;
3397d6
+}
3397d6
+
3397d6
 #ifndef TEST_ETHTOOL
3397d6
 int send_ioctl(struct cmd_context *ctx, void *cmd)
3397d6
 {
3397d6
@@ -4754,6 +4870,9 @@ static const struct option {
3397d6
 	  "		[ advertise %x ]\n"
3397d6
 	  "		[ tx-lpi on|off ]\n"
3397d6
 	  "		[ tx-timer %d ]\n"},
3397d6
+	{ "--show-fec", 1, do_gfec, "Show FEC settings"},
3397d6
+	{ "--set-fec", 1, do_sfec, "Set FEC settings",
3397d6
+	  "		[ encoding auto|off|rs|baser ]\n"},
3397d6
 	{ "-h|--help", 0, show_usage, "Show this help" },
3397d6
 	{ "--version", 0, do_version, "Show version number" },
3397d6
 	{}
3397d6
-- 
3397d6
1.8.3.1
3397d6