* [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).