--- ethtool-3/ethtool.c.b4phil 2006-04-29 19:01:18.000000000 -0700 +++ ethtool-3/ethtool.c 2006-04-29 19:01:36.000000000 -0700 @@ -66,6 +66,7 @@ static int do_goffload(int fd, struct ifreq *ifr); static int do_soffload(int fd, struct ifreq *ifr); static int do_gstats(int fd, struct ifreq *ifr); +static int do_cstats(int fd, struct ifreq *ifr); static int send_ioctl(int fd, struct ifreq *ifr); static int check_for_pre24_kernel(); @@ -242,6 +243,7 @@ MODE_GOFFLOAD, MODE_SOFFLOAD, MODE_GSTATS, + MODE_CSTATS, } mode = MODE_GSET; static int goffload_changed = 0; @@ -470,6 +472,8 @@ mode = MODE_TEST; else if (!strcmp(argp[i], "-S")) mode = MODE_GSTATS; + else if (!strcmp(argp[i], "-z")) + mode = MODE_CSTATS; else if (!strcmp(argp[i], "-h")) show_usage(0); else @@ -492,6 +496,7 @@ (mode == MODE_GOFFLOAD) || (mode == MODE_SOFFLOAD) || (mode == MODE_GSTATS) || + (mode == MODE_CSTATS) || (mode == MODE_PHYS_ID)) { devname = argp[i]; break; @@ -1266,6 +1271,8 @@ return do_soffload(fd, &ifr); } else if (mode == MODE_GSTATS) { return do_gstats(fd, &ifr); + } else if (mode == MODE_CSTATS) { + return do_cstats(fd, &ifr); } return 69; @@ -2010,6 +2017,79 @@ return 0; } +static int do_cstats(int fd, struct ifreq *ifr) +{ + struct ethtool_drvinfo drvinfo; + struct ethtool_gstrings *strings; + struct ethtool_stats *stats; + unsigned int n_stats, sz_str, sz_stats, i; + int err; + + drvinfo.cmd = ETHTOOL_GDRVINFO; + ifr->ifr_data = (caddr_t)&drvinfo; + err = send_ioctl(fd, ifr); + if (err < 0) { + perror("Cannot get driver information"); + return 71; + } + + n_stats = drvinfo.n_stats; + if (n_stats < 1) { + fprintf(stderr, "no stats available\n"); + 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) { + fprintf(stderr, "no memory available\n"); + return 95; + } + + strings->cmd = ETHTOOL_GSTRINGS; + strings->string_set = ETH_SS_STATS; + strings->len = n_stats; + ifr->ifr_data = (caddr_t) strings; + err = send_ioctl(fd, ifr); + if (err < 0) { + perror("Cannot get stats strings information"); + free(strings); + free(stats); + return 96; + } + + stats->cmd = ETHTOOL_CSTATS; + stats->n_stats = n_stats; + ifr->ifr_data = (caddr_t) stats; + err = send_ioctl(fd, ifr); + if (err < 0) { + perror("Cannot get stats information"); + free(strings); + free(stats); + return 97; + } + + /* todo - pretty-print the strings per-driver */ + /* + fprintf(stdout, "NIC statistics:\n"); + for (i = 0; i < n_stats; i++) { + char s[ETH_GSTRING_LEN]; + + strncpy(s, &strings->data[i * ETH_GSTRING_LEN], + ETH_GSTRING_LEN); + fprintf(stdout, " %s: %llu\n", + s, stats->data[i]); + } + */ + free(strings); + free(stats); + + return 0; +} + static int send_ioctl(int fd, struct ifreq *ifr) { int err; --- ethtool-3/ethtool-copy.h.b4phil 2006-04-29 19:01:26.000000000 -0700 +++ ethtool-3/ethtool-copy.h 2006-04-29 19:01:36.000000000 -0700 @@ -283,6 +283,7 @@ #define ETHTOOL_GSTATS 0x0000001d /* get NIC-specific statistics */ #define ETHTOOL_GTSO 0x0000001e /* Get TSO enable (ethtool_value) */ #define ETHTOOL_STSO 0x0000001f /* Set TSO enable (ethtool_value) */ +#define ETHTOOL_CSTATS 0x00000023 /* get NIC-specific statistics */ /* compatibility with older code */ #define SPARC_ETH_GSET ETHTOOL_GSET