lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Tue, 17 May 2011 22:33:58 +0200 (CEST)
From:	Michał Mirosław <mirq-linux@...e.qmqm.pl>
To:	Ben Hutchings <bhutchings@...arflare.com>
Cc:	netdev@...r.kernel.org, David Miller <davem@...emloft.net>
Subject: [RFC PATCH ethtool] ethtool: merge ETHTOOL_[GS]FEATURES support to -k/-K modes

Signed-off-by: Michał Mirosław <mirq-linux@...e.qmqm.pl>
---

This depends on the previous patch introducing -w/-W for [GS]FEATURES.

BTW, I noticed an old bug in ethtool (present currently and in debian-lenny's
version 6+20080913-1): "ethtool -k" -- i.e. with no other parameters -- runs
and tries to check device named '-k'.

Example:

icybox:~# ./ethtool -k ge0
Offload parameters for ge0:
rx-checksumming: on
tx-checksumming: off
scatter-gather: off
tcp-segmentation-offload: off
udp-fragmentation-offload: off
generic-segmentation-offload: off
generic-receive-offload: on
large-receive-offload: off
rx-vlan-offload: off
tx-vlan-offload: off
ntuple-filters: off
receive-hashing: off

Full offload state:  (feature-name: active,wanted,changable)
     tx-scatter-gather                 no,yes,yes
     tx-checksum-ipv4                  no, no,yes
     tx-checksum-unneeded              no,---, no
     tx-checksum-ip-generic            no,---, no
     tx_checksum-ipv6                  no, no,yes
     highdma                           no,---, no
     tx-scatter-gather-fraglist        no,---, no
     tx-vlan-hw-insert                 no,---, no
     rx-vlan-hw-parse                  no,---, no
     rx-vlan-filter                    no,---, no
     vlan-challenged                   no,---,---
     tx-generic-segmentation           no,yes,yes
     tx-lockless                       no,---,---
     netns-local                       no,---,---
     rx-gro                           yes,yes,yes
     rx-lro                            no,---, no
     tx-tcp-segmentation               no, no,yes
     tx-udp-fragmentation              no,---, no
     tx-gso-robust                     no,---, no
     tx-tcp-ecn-segmentation           no, no,yes
     tx-tcp6-segmentation              no, no,yes
     tx-fcoe-segmentation              no,---, no
     tx-checksum-fcoe-crc              no,---, no
     tx-checksum-sctp                  no,---, no
     fcoe-mtu                          no,---, no
     rx-ntuple-filter                  no,---, no
     rx-hashing                        no,---, no
     rx-checksum                      yes,yes,yes
     tx-nocache-copy                   no, no,yes
     loopback                          no,---, no

icybox:~# ./ethtool -K ge0 tx_checksum-ipv6 on
feature tx-scatter-gather is enabled (expected: disabled, saved: enabled)
feature tx-generic-segmentation is enabled (expected: disabled, saved: enabled)

icybox:~# ./ethtool -K ge0 sg off
[turns off SG and GSO; like before]

icybox:~# ./ethtool -K ge0 tx_checksum-ipv6 off
[no other feature changed state]

icybox:~# ./ethtool -K ge0 sg on
[SG was remembered this time, but is inactive (no checksum offloads)]

icybox:~# ./ethtool -K ge0 tx_checksum-ipv6 on
feature tx-scatter-gather is enabled (expected: disabled, saved: enabled)
feature tx-generic-segmentation is enabled (expected: disabled, saved: enabled)

icybox:~# ./ethtool -K ge0 tx_checksum-ipv6 off
feature tx-scatter-gather is disabled (expected: enabled, saved: enabled)
feature tx-generic-segmentation is disabled (expected: enabled, saved: enabled)

---
 ethtool.c |  155 ++++++++++++++++++++++++++++--------------------------------
 1 files changed, 72 insertions(+), 83 deletions(-)

diff --git a/ethtool.c b/ethtool.c
index 86a5a8b..a541007 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -123,8 +123,6 @@ static enum {
 	MODE_SRING,
 	MODE_GOFFLOAD,
 	MODE_SOFFLOAD,
-	MODE_GFEATURES,
-	MODE_SFEATURES,
 	MODE_GSTATS,
 	MODE_GNFC,
 	MODE_SNFC,
@@ -202,9 +200,6 @@ static struct option {
 		"		[ txvlan on|off ]\n"
 		"		[ ntuple on|off ]\n"
 		"		[ rxhash on|off ]\n"
-    },
-    { "-w", "--show-features", MODE_GFEATURES, "Get offload status" },
-    { "-W", "--request-features", MODE_SFEATURES, "Set requested offload",
 		"		[ feature-name on|off [...] ]\n"
 		"		see --show-features output for feature-name strings\n" },
     { "-i", "--driver", MODE_GDRV, "Show driver information" },
@@ -306,7 +301,6 @@ static void show_usage(void)
 
 static char *devname = NULL;
 
-static int goffload_changed = 0;
 static int off_csum_rx_wanted = -1;
 static int off_csum_tx_wanted = -1;
 static int off_sg_wanted = -1;
@@ -316,6 +310,7 @@ static int off_gso_wanted = -1;
 static u32 off_flags_wanted = 0;
 static u32 off_flags_mask = 0;
 static int off_gro_wanted = -1;
+static struct ethtool_sfeatures *features_req;
 
 static struct ethtool_pauseparam epause;
 static int gpause_changed = 0;
@@ -778,8 +773,6 @@ static void parse_cmdline(int argc, char **argp)
 			    (mode == MODE_SRING) ||
 			    (mode == MODE_GOFFLOAD) ||
 			    (mode == MODE_SOFFLOAD) ||
-			    (mode == MODE_GFEATURES) ||
-			    (mode == MODE_SFEATURES) ||
 			    (mode == MODE_GSTATS) ||
 			    (mode == MODE_GNFC) ||
 			    (mode == MODE_SNFC) ||
@@ -863,14 +856,6 @@ static void parse_cmdline(int argc, char **argp)
 				break;
 			}
 			if (mode == MODE_SOFFLOAD) {
-				parse_generic_cmdline(argc, argp, i,
-					&goffload_changed,
-			      		cmdline_offload,
-			      		ARRAY_SIZE(cmdline_offload));
-				i = argc;
-				break;
-			}
-			if (mode == MODE_SFEATURES) {
 				parse_sfeatures_args(argc, argp, i);
 				i = argc;
 				break;
@@ -1944,10 +1929,6 @@ static int doit(void)
 		return do_goffload(fd, &ifr);
 	} else if (mode == MODE_SOFFLOAD) {
 		return do_soffload(fd, &ifr);
-	} else if (mode == MODE_GFEATURES) {
-		return do_gfeatures(fd, &ifr);
-	} else if (mode == MODE_SFEATURES) {
-		return do_sfeatures(fd, &ifr);
 	} else if (mode == MODE_GSTATS) {
 		return do_gstats(fd, &ifr);
 	} else if (mode == MODE_GNFC) {
@@ -2262,13 +2243,20 @@ static int do_goffload(int fd, struct ifreq *ifr)
 		allfail = 0;
 	}
 
+	if (!allfail)
+		dump_offload(rx, tx, sg, tso, ufo, gso, gro, lro, rxvlan, txvlan,
+			    ntuple, rxhash);
+
+	err = do_gfeatures(fd, ifr);
+	if (!err)
+		allfail = 0;
+
 	if (allfail) {
 		fprintf(stdout, "no offload info available\n");
 		return 83;
 	}
 
-	return dump_offload(rx, tx, sg, tso, ufo, gso, gro, lro, rxvlan, txvlan,
-			    ntuple, rxhash);
+	return 0;
 }
 
 static int do_soffload(int fd, struct ifreq *ifr)
@@ -2277,116 +2265,114 @@ static int do_soffload(int fd, struct ifreq *ifr)
 	int err, changed = 0;
 
 	if (off_csum_rx_wanted >= 0) {
-		changed = 1;
 		eval.cmd = ETHTOOL_SRXCSUM;
 		eval.data = (off_csum_rx_wanted == 1);
 		ifr->ifr_data = (caddr_t)&eval;
 		err = send_ioctl(fd, ifr);
-		if (err) {
+		if (err)
 			perror("Cannot set device rx csum settings");
-			return 84;
-		}
+		else
+			changed = 1;
 	}
 
 	if (off_csum_tx_wanted >= 0) {
-		changed = 1;
 		eval.cmd = ETHTOOL_STXCSUM;
 		eval.data = (off_csum_tx_wanted == 1);
 		ifr->ifr_data = (caddr_t)&eval;
 		err = send_ioctl(fd, ifr);
-		if (err) {
+		if (err)
 			perror("Cannot set device tx csum settings");
-			return 85;
-		}
+		else
+			changed = 1;
 	}
 
 	if (off_sg_wanted >= 0) {
-		changed = 1;
 		eval.cmd = ETHTOOL_SSG;
 		eval.data = (off_sg_wanted == 1);
 		ifr->ifr_data = (caddr_t)&eval;
 		err = send_ioctl(fd, ifr);
-		if (err) {
+		if (err)
 			perror("Cannot set device scatter-gather settings");
-			return 86;
-		}
+		else
+			changed = 1;
 	}
 
 	if (off_tso_wanted >= 0) {
-		changed = 1;
 		eval.cmd = ETHTOOL_STSO;
 		eval.data = (off_tso_wanted == 1);
 		ifr->ifr_data = (caddr_t)&eval;
 		err = send_ioctl(fd, ifr);
-		if (err) {
+		if (err)
 			perror("Cannot set device tcp segmentation offload settings");
-			return 88;
-		}
+		else
+			changed = 1;
 	}
 	if (off_ufo_wanted >= 0) {
-		changed = 1;
 		eval.cmd = ETHTOOL_SUFO;
 		eval.data = (off_ufo_wanted == 1);
 		ifr->ifr_data = (caddr_t)&eval;
 		err = ioctl(fd, SIOCETHTOOL, ifr);
-		if (err) {
+		if (err)
 			perror("Cannot set device udp large send offload settings");
-			return 89;
-		}
+		else
+			changed = 1;
 	}
 	if (off_gso_wanted >= 0) {
-		changed = 1;
 		eval.cmd = ETHTOOL_SGSO;
 		eval.data = (off_gso_wanted == 1);
 		ifr->ifr_data = (caddr_t)&eval;
 		err = ioctl(fd, SIOCETHTOOL, ifr);
-		if (err) {
+		if (err)
 			perror("Cannot set device generic segmentation offload settings");
-			return 90;
-		}
+		else
+			changed = 1;
 	}
 	if (off_flags_mask) {
-		changed = 1;
 		eval.cmd = ETHTOOL_GFLAGS;
 		eval.data = 0;
 		ifr->ifr_data = (caddr_t)&eval;
 		err = ioctl(fd, SIOCETHTOOL, ifr);
 		if (err) {
 			perror("Cannot get device flag settings");
-			return 91;
-		}
+		} else {
+			eval.cmd = ETHTOOL_SFLAGS;
+			eval.data = ((eval.data & ~off_flags_mask) |
+				     off_flags_wanted);
 
-		eval.cmd = ETHTOOL_SFLAGS;
-		eval.data = ((eval.data & ~off_flags_mask) |
-			     off_flags_wanted);
-
-		err = ioctl(fd, SIOCETHTOOL, ifr);
-		if (err) {
-			perror("Cannot set device flag settings");
-			return 92;
+			err = ioctl(fd, SIOCETHTOOL, ifr);
+			if (err)
+				perror("Cannot set device flag settings");
+			else
+				changed = 1;
 		}
 	}
 	if (off_gro_wanted >= 0) {
-		changed = 1;
 		eval.cmd = ETHTOOL_SGRO;
 		eval.data = (off_gro_wanted == 1);
 		ifr->ifr_data = (caddr_t)&eval;
 		err = ioctl(fd, SIOCETHTOOL, ifr);
-		if (err) {
+		if (err)
 			perror("Cannot set device GRO settings");
-			return 93;
-		}
+		else
+			changed = 1;
+	}
+
+	if (features_req) {
+		err = do_sfeatures(fd, ifr);
+		if (!err)
+			changed = 1;
 	}
 
 	if (!changed) {
 		fprintf(stdout, "no offload settings changed\n");
+		return err;
 	}
 
 	return 0;
 }
 
 static int get_feature_strings(int fd, struct ifreq *ifr,
-	struct ethtool_gstrings **strs)
+	struct ethtool_gstrings **strs, int quiet_nx)
 {
 	struct ethtool_sset_info *sset_info;
 	struct ethtool_gstrings *strings;
@@ -2398,16 +2384,18 @@ static int get_feature_strings(int fd, struct ifreq *ifr,
 	ifr->ifr_data = (caddr_t)sset_info;
 	err = send_ioctl(fd, ifr);
 
-	if ((err < 0) ||
-	    (!(sset_info->sset_mask & (1ULL << ETH_SS_FEATURES)))) {
-		perror("Cannot get driver strings info");
-		return -100;
-	}
-
 	n_strings = sset_info->data[0];
 	free(sset_info);
+
+	if ((err < 0) ||
+	    (!(sset_info->sset_mask & (1ULL << ETH_SS_FEATURES))) ||
+	    (n_strings == 0)) {
+		if (!quiet_nx)
+			perror("Cannot get driver strings info");
+		return -100;
+	}
+
 	sz_str = n_strings * ETH_GSTRING_LEN;
-
 	strings = calloc(1, sz_str + sizeof(struct ethtool_gstrings));
 	if (!strings) {
 		fprintf(stderr, "no memory available\n");
@@ -2429,8 +2417,6 @@ static int get_feature_strings(int fd, struct ifreq *ifr,
 	return n_strings;
 }
 
-struct ethtool_sfeatures *features_req;
-
 static void parse_sfeatures_args(int argc, char **argp, int argi)
 {
 	struct cmdline_info *cmdline_desc, *cp;
@@ -2443,13 +2429,21 @@ static void parse_sfeatures_args(int argc, char **argp, int argi)
 	if (fd < 0)
 		exit(100);
 
-	n_strings = get_feature_strings(fd, &ifr, &strings);
-	if (n_strings < 0)
-		exit(-n_strings);
+	n_strings = get_feature_strings(fd, &ifr, &strings, 1);
+	if (n_strings < 0) {
+		/* ETHTOOL_GFEATURES unavailable */
+		parse_generic_cmdline(argc, argp, argi, &changed,
+			cmdline_offload, ARRAY_SIZE(cmdline_offload));
+		return;
+	}
 
 	sz_features = sizeof(*features_req->features) * ((n_strings + 31) / 32);
 
-	cp = cmdline_desc = calloc(n_strings, sizeof(*cmdline_desc));
+	cp = cmdline_desc = calloc(n_strings + ARRAY_SIZE(cmdline_offload),
+		sizeof(*cmdline_desc));
+	memcpy(cp, cmdline_offload, sizeof(cmdline_offload));
+	cp += ARRAY_SIZE(cmdline_offload);
+
 	features_req = calloc(1, sizeof(*features_req) + sz_features);
 	if (!cmdline_desc || !features_req) {
 		fprintf(stderr, "no memory available\n");
@@ -2518,7 +2512,7 @@ static int do_gfeatures(int fd, struct ifreq *ifr)
 	struct ethtool_gfeatures *features;
 	int n_strings, err, i;
 
-	n_strings = get_feature_strings(fd, ifr, &strings);
+	n_strings = get_feature_strings(fd, ifr, &strings, 1);
 	if (n_strings < 0)
 		return -n_strings;
 
@@ -2528,7 +2522,7 @@ static int do_gfeatures(int fd, struct ifreq *ifr)
 		return err;
 	}
 
-	fprintf(stdout, "Offload state:  (name: enabled,wanted,changable)\n");
+	fprintf(stdout, "\nFull offload state:  (feature-name: active,wanted,changable)\n");
 	for (i = 0; i < n_strings; i++) {
 		if (!strings->data[i * ETH_GSTRING_LEN])
 			continue;	/* empty */
@@ -2585,12 +2579,7 @@ static int do_sfeatures(int fd, struct ifreq *ifr)
 	struct ethtool_gfeatures *features0, *features1;
 	int n_strings, err, i;
 
-	if (!features_req) {
-		fprintf(stderr, "no features changed\n");
-		return 97;
-	}
-
-	n_strings = get_feature_strings(fd, ifr, &strings);
+	n_strings = get_feature_strings(fd, ifr, &strings, 0);
 	if (n_strings < 0) {
 		free(features_req);
 		return -n_strings;
-- 
1.7.2.5

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ