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]
Message-Id: <1434024928-33177-2-git-send-email-hadarh@mellanox.com>
Date:	Thu, 11 Jun 2015 15:15:27 +0300
From:	Hadar Hen Zion <hadarh@...lanox.com>
To:	Ben Hutchings <ben@...adent.org.uk>
Cc:	netdev@...r.kernel.org, _govind@....com,
	Amir Vadai <amirv@...lanox.com>,
	Or Gerlitz <ogerlitz@...lanox.com>,
	Tal Alon <talal@...lanox.com>,
	Hadar Hen Zion <hadarh@...lanox.com>
Subject: [PATCH ethtool V3 1/2] ethtool: Add copybreak support

From: Govindarajulu Varadarajan <_govind@....com>

Add support for setting/getting driver's tx/rx_copybreak value.

Copybreak is handled through a new ethtool tunable interface.

The kernel support was added in 3.18, commit f0db9b07341 "ethtool:
Add generic options for tunables"

Signed-off-by: Govindarajulu Varadarajan <_govind@....com>
Signed-off-by: Hadar Hen Zion <hadarh@...lanox.com>
---
 ethtool-copy.h |   1 +
 ethtool.c      | 227 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 228 insertions(+)

diff --git a/ethtool-copy.h b/ethtool-copy.h
index d23ffc4..f92743b 100644
--- a/ethtool-copy.h
+++ b/ethtool-copy.h
@@ -545,6 +545,7 @@ enum ethtool_stringset {
 	ETH_SS_NTUPLE_FILTERS,
 	ETH_SS_FEATURES,
 	ETH_SS_RSS_HASH_FUNCS,
+	ETH_SS_TUNABLES,
 };
 
 /**
diff --git a/ethtool.c b/ethtool.c
index 01b13a6..16b5c41 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -145,6 +145,12 @@ struct cmdline_info {
 	void *seen_val;
 };
 
+struct ethtool_stunable {
+	cmdline_type_t type;
+	__u32 u32_val;
+	int seen_val;
+};
+
 struct flag_info {
 	const char *name;
 	u32 value;
@@ -1800,6 +1806,223 @@ static int do_gring(struct cmd_context *ctx)
 	return 0;
 }
 
+static int get_u32tunable(struct cmd_context *ctx, enum tunable_id id,
+			  __u32 *value)
+{
+	struct ethtool_tunable *etuna;
+	int ret;
+
+	etuna = calloc(sizeof(*etuna) + sizeof(__u32), 1);
+	if (!etuna)
+		return 1;
+	etuna->cmd = ETHTOOL_GTUNABLE;
+	etuna->id = id;
+	etuna->type_id = ETHTOOL_TUNABLE_U32;
+	etuna->len = sizeof(__u32);
+	ret = send_ioctl(ctx, etuna);
+	*value = *(__u32 *)((void *)etuna + sizeof(*etuna));
+	free(etuna);
+
+	return ret;
+}
+
+static int print_u32tunable(int err, struct ethtool_gstrings *tunables,
+			    enum tunable_id id, const __u32 value)
+{
+	char *tunable_name = (char *)tunables->data + id * ETH_GSTRING_LEN;
+
+	if (err) {
+		switch (errno) {
+		/* Driver does not support this particular tunable
+		 * Usually displays 0
+		 */
+		case EINVAL:
+			goto print;
+		/* Driver does not support get tunables ops or no such device
+		 * No point in proceeding further
+		 */
+		case EOPNOTSUPP:
+		case ENODEV:
+			perror("Cannot get device settings");
+			exit(err);
+		default:
+			perror(tunable_name);
+			return err;
+		}
+	}
+print:
+	fprintf(stdout, "%s: %u\n", tunable_name, value);
+
+	return 0;
+}
+
+static int do_gtunables(struct cmd_context *ctx)
+{
+	int err, anyerror = 0;
+	__u32 u32value = 0;
+	struct ethtool_gstrings *tunables;
+	int idx;
+	__u32 n_tunables;
+
+	if (ctx->argc != 0)
+		exit_bad_args();
+
+	tunables = get_stringset(ctx, ETH_SS_TUNABLES, 0, 1);
+	if (!tunables) {
+		perror("Cannot get tunables names");
+		return 1;
+	}
+	if (tunables->len == 0) {
+		fprintf(stderr, "No tunables defined\n");
+		return 1;
+	}
+	n_tunables = tunables->len;
+
+	fprintf(stdout, "Tunables settings for device %s\n", ctx->devname);
+
+	for (idx = 0; idx < n_tunables; idx++) {
+		switch(idx) {
+		case ETHTOOL_ID_UNSPEC:
+			break;
+		case ETHTOOL_RX_COPYBREAK:
+		case ETHTOOL_TX_COPYBREAK:
+			err = get_u32tunable(ctx, idx, &u32value);
+			err = print_u32tunable(err, tunables, idx, u32value);
+			if (err)
+				anyerror = err;
+			break;
+		default:
+			anyerror = EINVAL;
+		}
+	}
+	if (anyerror)
+		fprintf(stderr, "Failed to get all settings. displayed partial settings\n");
+
+	free(tunables);
+	return anyerror;
+}
+
+static int set_u32tunable(struct cmd_context *ctx, enum tunable_id id,
+			  const __u32 value)
+{
+	struct ethtool_tunable *etuna;
+	int ret;
+	__u32 *data;
+
+	etuna = malloc(sizeof(*etuna) + sizeof(__u32));
+	if (!etuna) {
+		perror("Set tunable:");
+		return 1;
+	}
+	data = (void *)etuna + sizeof(*etuna);
+	*data = value;
+	etuna->cmd = ETHTOOL_STUNABLE;
+	etuna->id = id;
+	etuna->type_id = ETHTOOL_TUNABLE_U32;
+	etuna->len = sizeof(__u32);
+	ret = send_ioctl(ctx, etuna);
+	free(etuna);
+
+	return ret;
+}
+
+static int check_set_u32tunable(int err, enum tunable_id id)
+{
+	if (err) {
+		switch (errno) {
+		/* Driver does not support get tunables ops or no such device
+		 * No point in proceeding further
+		 */
+		case EOPNOTSUPP:
+		case ENODEV:
+			perror("Cannot set device settings");
+			exit(err);
+		default:
+			perror("Check set tunable");
+			return err;
+		}
+	}
+
+	return 0;
+}
+
+static int do_stunables(struct cmd_context *ctx)
+{
+	int err, anyerr = 0;
+	int tunable_changed = 0;
+	struct ethtool_gstrings *tunables;
+	struct cmdline_info *cmd_tunables = NULL;
+	struct ethtool_stunable *set_tunables = NULL;
+	int idx;
+	__u32 n_tunables;
+
+	tunables = get_stringset(ctx, ETH_SS_TUNABLES, 0, 1);
+	if (!tunables) {
+		perror("Cannot get tunables names");
+		return 1;
+	}
+	if (tunables->len == 0) {
+		fprintf(stderr, "No tunables defined\n");
+		return 1;
+	}
+	n_tunables = tunables->len;
+
+	cmd_tunables = calloc(n_tunables, sizeof(*cmd_tunables));
+	set_tunables = calloc(n_tunables, sizeof(*set_tunables));
+	if (!cmd_tunables || !set_tunables) {
+		anyerr = 1;
+		goto err;
+	}
+
+	for (idx = 0; idx < n_tunables; idx++) {
+		cmd_tunables[idx].name =
+			(char *)tunables->data + idx * ETH_GSTRING_LEN;
+		cmd_tunables[idx].seen_val = &set_tunables[idx].seen_val;
+
+		switch(idx) {
+		case ETHTOOL_ID_UNSPEC:
+			break;
+		case ETHTOOL_RX_COPYBREAK:
+		case ETHTOOL_TX_COPYBREAK:
+			cmd_tunables[idx].wanted_val = &set_tunables[idx].u32_val;
+			cmd_tunables[idx].type = CMDL_U32;
+			break;
+		default:
+			anyerr = EINVAL;
+			goto err;
+		}
+	}
+
+	parse_generic_cmdline(ctx, &tunable_changed, cmd_tunables, n_tunables);
+
+	for (idx = 0; idx < n_tunables; idx++) {
+		if (set_tunables[idx].seen_val) {
+			switch(idx) {
+			case ETHTOOL_ID_UNSPEC:
+				break;
+			case ETHTOOL_RX_COPYBREAK:
+			case ETHTOOL_TX_COPYBREAK:
+				err = set_u32tunable(ctx, idx, set_tunables[idx].u32_val);
+				err = check_set_u32tunable(err, idx);
+				if (err)
+					anyerr = err;
+				break;
+			default:
+				anyerr = EINVAL;
+				goto err;
+			}
+		}
+	}
+
+	if (anyerr)
+		fprintf(stderr, "Failed to set requested parameters\n");
+err:
+	free(tunables);
+	free(cmd_tunables);
+	free(set_tunables);
+	return anyerr;
+}
+
 static int do_schannels(struct cmd_context *ctx)
 {
 	struct ethtool_channels echannels;
@@ -4050,6 +4273,10 @@ static const struct option {
 	  "		[ rx-mini N ]\n"
 	  "		[ rx-jumbo N ]\n"
 	  "		[ tx N ]\n" },
+	{ "-b|--show-tunable", 1, do_gtunables, "Show tunable values" },
+	{ "-B|--set-tunable", 1, do_stunables, "Set tunable values",
+	  "		[ rx-copybreak N]\n"
+	  "		[ tx-copybreak N]\n" },
 	{ "-k|--show-features|--show-offload", 1, do_gfeatures,
 	  "Get state of protocol offload and other features" },
 	{ "-K|--features|--offload", 1, do_sfeatures,
-- 
1.8.3.1

--
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