* [PATCH ethtool 1/2] Implement and use a generic get_stringset() function
@ 2011-12-02 0:13 Ben Hutchings
2011-12-02 0:18 ` [PATCH ethtool 2/2] Add support for querying and setting private flags Ben Hutchings
0 siblings, 1 reply; 2+ messages in thread
From: Ben Hutchings @ 2011-12-02 0:13 UTC (permalink / raw)
To: Jean Delvare; +Cc: netdev
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
If you apply this and the next patch on top of ethtool 3.1 you should be
able to get and set private flags. I tried adding some dummy flags to a
driver and it worked as expected.
ethtool 3.1 is currently only tagged in git
(git://git.kernel.org/pub/scm/network/ethtool/ethtool.git); I'll push
these changes there unless you tell me they're broken
Ben.
ethtool.c | 121 ++++++++++++++++++++++++++++++++++---------------------------
1 files changed, 67 insertions(+), 54 deletions(-)
diff --git a/ethtool.c b/ethtool.c
index 6909827..f0c9d08 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -855,8 +855,8 @@ static int dump_eeprom(int geeprom_dump_raw, struct ethtool_drvinfo *info,
return 0;
}
-static int dump_test(struct ethtool_drvinfo *info, struct ethtool_test *test,
- struct ethtool_gstrings *strings)
+static int dump_test(struct ethtool_test *test,
+ struct ethtool_gstrings *strings)
{
int i, rc;
@@ -868,10 +868,10 @@ static int dump_test(struct ethtool_drvinfo *info, struct ethtool_test *test,
(test->flags & ETH_TEST_FL_EXTERNAL_LB_DONE) ?
"" : "not ");
- if (info->testinfo_len)
+ if (strings->len)
fprintf(stdout, "The test extra info:\n");
- for (i = 0; i < info->testinfo_len; i++) {
+ for (i = 0; i < strings->len; i++) {
fprintf(stdout, "%s\t %d\n",
(char *)(strings->data + i * ETH_GSTRING_LEN),
(u32) test->data[i]);
@@ -1113,6 +1113,48 @@ static int dump_rxfhash(int fhash, u64 val)
return 0;
}
+static struct ethtool_gstrings *
+get_stringset(struct cmd_context *ctx, enum ethtool_stringset set_id,
+ ptrdiff_t drvinfo_offset)
+{
+ struct {
+ struct ethtool_sset_info hdr;
+ u32 buf[1];
+ } sset_info;
+ struct ethtool_drvinfo drvinfo;
+ u32 len;
+ struct ethtool_gstrings *strings;
+
+ sset_info.hdr.cmd = ETHTOOL_GSSET_INFO;
+ sset_info.hdr.reserved = 0;
+ sset_info.hdr.sset_mask = 1ULL << set_id;
+ if (send_ioctl(ctx, &sset_info) == 0) {
+ len = sset_info.hdr.sset_mask ? sset_info.hdr.data[0] : 0;
+ } else if (errno == EOPNOTSUPP && drvinfo_offset != 0) {
+ /* Fallback for old kernel versions */
+ drvinfo.cmd = ETHTOOL_GDRVINFO;
+ if (send_ioctl(ctx, &drvinfo))
+ return NULL;
+ len = *(u32 *)((char *)&drvinfo + drvinfo_offset);
+ } else {
+ return NULL;
+ }
+
+ strings = calloc(1, sizeof(*strings) + len * ETH_GSTRING_LEN);
+ if (!strings)
+ return NULL;
+
+ strings->cmd = ETHTOOL_GSTRINGS;
+ strings->string_set = set_id;
+ strings->len = len;
+ if (len != 0 && send_ioctl(ctx, strings)) {
+ free(strings);
+ return NULL;
+ }
+
+ return strings;
+}
+
static int do_gdrv(struct cmd_context *ctx)
{
int err;
@@ -2293,7 +2335,6 @@ static int do_test(struct cmd_context *ctx)
EXTERNAL_LB,
} test_type;
int err;
- struct ethtool_drvinfo drvinfo;
struct ethtool_test *test;
struct ethtool_gstrings *strings;
@@ -2313,21 +2354,22 @@ static int do_test(struct cmd_context *ctx)
test_type = OFFLINE;
}
- drvinfo.cmd = ETHTOOL_GDRVINFO;
- err = send_ioctl(ctx, &drvinfo);
- if (err < 0) {
- perror("Cannot get driver information");
- return 72;
+ strings = get_stringset(ctx, ETH_SS_TEST,
+ offsetof(struct ethtool_drvinfo, testinfo_len));
+ if (!strings) {
+ perror("Cannot get strings");
+ return 74;
}
- test = calloc(1, sizeof(*test) + drvinfo.testinfo_len * sizeof(u64));
+ test = calloc(1, sizeof(*test) + strings->len * sizeof(u64));
if (!test) {
perror("Cannot allocate memory for test info");
+ free(strings);
return 73;
}
- memset (test->data, 0, drvinfo.testinfo_len * sizeof(u64));
+ memset(test->data, 0, strings->len * sizeof(u64));
test->cmd = ETHTOOL_TEST;
- test->len = drvinfo.testinfo_len;
+ test->len = strings->len;
if (test_type == EXTERNAL_LB)
test->flags = (ETH_TEST_FL_OFFLINE | ETH_TEST_FL_EXTERNAL_LB);
else if (test_type == OFFLINE)
@@ -2338,28 +2380,11 @@ static int do_test(struct cmd_context *ctx)
if (err < 0) {
perror("Cannot test");
free (test);
+ free(strings);
return 74;
}
- strings = calloc(1, sizeof(*strings) +
- drvinfo.testinfo_len * ETH_GSTRING_LEN);
- if (!strings) {
- perror("Cannot allocate memory for strings");
- free(test);
- return 73;
- }
- memset (strings->data, 0, drvinfo.testinfo_len * ETH_GSTRING_LEN);
- strings->cmd = ETHTOOL_GSTRINGS;
- strings->string_set = ETH_SS_TEST;
- strings->len = drvinfo.testinfo_len;
- err = send_ioctl(ctx, strings);
- if (err < 0) {
- perror("Cannot get strings");
- free (test);
- free (strings);
- return 74;
- }
- err = dump_test(&drvinfo, test, strings);
+ err = dump_test(test, strings);
free(test);
free(strings);
@@ -2390,47 +2415,35 @@ static int do_phys_id(struct cmd_context *ctx)
static int do_gstats(struct cmd_context *ctx)
{
- struct ethtool_drvinfo drvinfo;
struct ethtool_gstrings *strings;
struct ethtool_stats *stats;
- unsigned int n_stats, sz_str, sz_stats, i;
+ unsigned int n_stats, sz_stats, i;
int err;
if (ctx->argc != 0)
exit_bad_args();
- drvinfo.cmd = ETHTOOL_GDRVINFO;
- err = send_ioctl(ctx, &drvinfo);
- if (err < 0) {
- perror("Cannot get driver information");
- return 71;
+ strings = get_stringset(ctx, ETH_SS_STATS,
+ offsetof(struct ethtool_drvinfo, n_stats));
+ if (!strings) {
+ perror("Cannot get stats strings information");
+ return 96;
}
- n_stats = drvinfo.n_stats;
+ n_stats = strings->len;
if (n_stats < 1) {
fprintf(stderr, "no stats available\n");
+ free(strings);
return 94;
}
- sz_str = n_stats * ETH_GSTRING_LEN;
sz_stats = n_stats * sizeof(u64);
- strings = calloc(1, sz_str + sizeof(struct ethtool_gstrings));
stats = calloc(1, sz_stats + sizeof(struct ethtool_stats));
- if (!strings || !stats) {
+ if (!stats) {
fprintf(stderr, "no memory available\n");
- return 95;
- }
-
- strings->cmd = ETHTOOL_GSTRINGS;
- strings->string_set = ETH_SS_STATS;
- strings->len = n_stats;
- err = send_ioctl(ctx, strings);
- if (err < 0) {
- perror("Cannot get stats strings information");
free(strings);
- free(stats);
- return 96;
+ return 95;
}
stats->cmd = ETHTOOL_GSTATS;
--
1.7.4.4
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply related [flat|nested] 2+ messages in thread
* [PATCH ethtool 2/2] Add support for querying and setting private flags
2011-12-02 0:13 [PATCH ethtool 1/2] Implement and use a generic get_stringset() function Ben Hutchings
@ 2011-12-02 0:18 ` Ben Hutchings
0 siblings, 0 replies; 2+ messages in thread
From: Ben Hutchings @ 2011-12-02 0:18 UTC (permalink / raw)
To: Jean Delvare; +Cc: netdev
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
ethtool.8.in | 20 +++++++++++
ethtool.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
test-cmdline.c | 4 ++
3 files changed, 127 insertions(+), 2 deletions(-)
diff --git a/ethtool.8.in b/ethtool.8.in
index 7c39629..e6e46cc 100644
--- a/ethtool.8.in
+++ b/ethtool.8.in
@@ -317,6 +317,14 @@ ethtool \- query or control network driver and hardware settings
.BN tx
.BN other
.BN combined
+.HP
+.B ethtool \-\-show\-priv\-flags
+.I devname
+.HP
+.B ethtool \-\-set\-priv\-flags
+.I devname flag
+.A1 on off
+.RB ...
.
.\" Adjust lines (i.e. full justification) and hyphenate.
.ad
@@ -783,6 +791,18 @@ Changes the number of channels used only for other purposes e.g. link interrupts
.TP
.BI combined \ N
Changes the number of multi-purpose channels.
+.TP
+.B \-\-show\-priv\-flags
+Queries the specified network device for its private flags. The
+names and meanings of private flags (if any) are defined by each
+network device driver.
+.TP
+.B \-\-set\-priv\-flags
+Sets the device's private flags as specified.
+.PP
+.I flag
+.A1 on off
+Sets the state of the named private flag.
.SH BUGS
Not supported (in part or whole) on all network drivers.
.SH AUTHOR
diff --git a/ethtool.c b/ethtool.c
index f0c9d08..d21eaea 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -583,7 +583,8 @@ static int dump_drvinfo(struct ethtool_drvinfo *info)
"supports-statistics: %s\n"
"supports-test: %s\n"
"supports-eeprom-access: %s\n"
- "supports-register-dump: %s\n",
+ "supports-register-dump: %s\n"
+ "supports-priv-flags: %s\n",
info->driver,
info->version,
info->fw_version,
@@ -591,7 +592,8 @@ static int dump_drvinfo(struct ethtool_drvinfo *info)
info->n_stats ? "yes" : "no",
info->testinfo_len ? "yes" : "no",
info->eedump_len ? "yes" : "no",
- info->regdump_len ? "yes" : "no");
+ info->regdump_len ? "yes" : "no",
+ info->n_priv_flags ? "yes" : "no");
return 0;
}
@@ -3001,6 +3003,102 @@ static int do_setfwdump(struct cmd_context *ctx)
return 0;
}
+static int do_gprivflags(struct cmd_context *ctx)
+{
+ struct ethtool_gstrings *strings;
+ struct ethtool_value flags;
+ unsigned int i;
+
+ if (ctx->argc != 0)
+ exit_bad_args();
+
+ strings = get_stringset(ctx, ETH_SS_PRIV_FLAGS,
+ offsetof(struct ethtool_drvinfo, n_priv_flags));
+ if (!strings) {
+ perror("Cannot get private flag names");
+ return 1;
+ }
+ if (strings->len == 0) {
+ fprintf(stderr, "No private flags defined\n");
+ return 1;
+ }
+ if (strings->len > 32) {
+ /* ETHTOOL_GPFLAGS can only cover 32 flags */
+ fprintf(stderr, "Only showing first 32 private flags\n");
+ strings->len = 32;
+ }
+
+ flags.cmd = ETHTOOL_GPFLAGS;
+ if (send_ioctl(ctx, &flags)) {
+ perror("Cannot get private flags");
+ return 1;
+ }
+
+ printf("Private flags for %s:\n", ctx->devname);
+ for (i = 0; i < strings->len; i++)
+ printf("%s: %s\n",
+ (const char *)strings->data + i * ETH_GSTRING_LEN,
+ (flags.data & (1U << i)) ? "on" : "off");
+
+ return 0;
+}
+
+static int do_sprivflags(struct cmd_context *ctx)
+{
+ struct ethtool_gstrings *strings;
+ struct cmdline_info *cmdline;
+ struct ethtool_value flags;
+ u32 wanted_flags = 0, seen_flags = 0;
+ int any_changed;
+ unsigned int i;
+
+ strings = get_stringset(ctx, ETH_SS_PRIV_FLAGS,
+ offsetof(struct ethtool_drvinfo, n_priv_flags));
+ if (!strings) {
+ perror("Cannot get private flag names");
+ return 1;
+ }
+ if (strings->len == 0) {
+ fprintf(stderr, "No private flags defined\n");
+ return 1;
+ }
+ if (strings->len > 32) {
+ /* ETHTOOL_{G,S}PFLAGS can only cover 32 flags */
+ fprintf(stderr, "Only setting first 32 private flags\n");
+ strings->len = 32;
+ }
+
+ cmdline = calloc(strings->len, sizeof(*cmdline));
+ if (!cmdline) {
+ perror("Cannot parse arguments");
+ return 1;
+ }
+ for (i = 0; i < strings->len; i++) {
+ cmdline[i].name = ((const char *)strings->data +
+ i * ETH_GSTRING_LEN);
+ cmdline[i].type = CMDL_FLAG;
+ cmdline[i].wanted_val = &wanted_flags;
+ cmdline[i].flag_val = 1U << i;
+ cmdline[i].seen_val = &seen_flags;
+ }
+ parse_generic_cmdline(ctx, &any_changed, cmdline, strings->len);
+
+ flags.cmd = ETHTOOL_GPFLAGS;
+ if (send_ioctl(ctx, &flags)) {
+ perror("Cannot get private flags");
+ return 1;
+ }
+
+ flags.cmd = ETHTOOL_SPFLAGS;
+ flags.data = (flags.data & ~seen_flags) | wanted_flags;
+ if (send_ioctl(ctx, &flags)) {
+ perror("Cannot set private flags");
+ return 1;
+ }
+
+ return 0;
+}
+
int send_ioctl(struct cmd_context *ctx, void *cmd)
{
#ifndef TEST_ETHTOOL
@@ -3156,6 +3254,9 @@ static const struct option {
" [ tx N ]\n"
" [ other N ]\n"
" [ combined N ]\n" },
+ { "--show-priv-flags" , 1, do_gprivflags, "Query private flags" },
+ { "--set-priv-flags", 1, do_sprivflags, "Set private flags",
+ " FLAG on|off ...\n" },
{ "-h|--help", 0, show_usage, "Show this help" },
{ "--version", 0, do_version, "Show version number" },
{}
diff --git a/test-cmdline.c b/test-cmdline.c
index 7dd3b7c..56a26d8 100644
--- a/test-cmdline.c
+++ b/test-cmdline.c
@@ -205,6 +205,10 @@ static struct test_case {
{ 1, "--set-channels devname rx" },
{ 0, "-L devname" },
{ 1, "-L" },
+ { 0, "--show-priv-flags devname" },
+ { 1, "--show-priv-flags devname foo" },
+ { 1, "--show-priv-flags" },
+ /* can't test --set-priv-flags yet */
{ 0, "-h" },
{ 0, "--help" },
{ 0, "--version" },
--
1.7.4.4
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply related [flat|nested] 2+ messages in thread
end of thread, other threads:[~2011-12-02 0:18 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-12-02 0:13 [PATCH ethtool 1/2] Implement and use a generic get_stringset() function Ben Hutchings
2011-12-02 0:18 ` [PATCH ethtool 2/2] Add support for querying and setting private flags Ben Hutchings
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).