1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
|
// SPDX-License-Identifier: GPL-2.0
/* Copyright (C) B.A.T.M.A.N. contributors:
*
* Marek Lindner <marek.lindner@mailbox.org>
*
* License-Filename: LICENSES/preferred/GPL-2.0
*/
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/sockios.h>
#include <linux/ethtool.h>
#include <stdint.h>
#include "main.h"
void check_root_or_die(const char *cmd);
/* code borrowed from ethtool */
static int statistics_custom_get(int fd, struct ifreq *ifr)
{
struct ethtool_gstrings *strings = NULL;
struct ethtool_stats *stats = NULL;
struct ethtool_drvinfo drvinfo;
int ret = EXIT_FAILURE;
unsigned int sz_stats;
unsigned int n_stats;
unsigned int sz_str;
unsigned int i;
int err;
drvinfo.cmd = ETHTOOL_GDRVINFO;
ifr->ifr_data = (void *)&drvinfo;
err = ioctl(fd, SIOCETHTOOL, ifr);
if (err < 0) {
perror("Error - can't open driver information");
goto out;
}
n_stats = drvinfo.n_stats;
if (n_stats < 1)
goto success;
sz_str = n_stats * ETH_GSTRING_LEN;
sz_stats = n_stats * sizeof(uint64_t);
strings = calloc(1, sz_str + sizeof(struct ethtool_gstrings));
stats = calloc(1, sz_stats + sizeof(struct ethtool_stats));
if (!strings || !stats) {
fprintf(stderr, "Error - out of memory\n");
goto out;
}
strings->cmd = ETHTOOL_GSTRINGS;
strings->string_set = ETH_SS_STATS;
strings->len = n_stats;
ifr->ifr_data = (void *)strings;
err = ioctl(fd, SIOCETHTOOL, ifr);
if (err < 0) {
perror("Error - can't get stats strings information");
goto out;
}
stats->cmd = ETHTOOL_GSTATS;
stats->n_stats = n_stats;
ifr->ifr_data = (void *)stats;
err = ioctl(fd, SIOCETHTOOL, ifr);
if (err < 0) {
perror("Error - can't get stats information");
goto out;
}
for (i = 0; i < n_stats; i++) {
printf("\t%.*s: %llu\n", ETH_GSTRING_LEN,
&strings->data[i * ETH_GSTRING_LEN], stats->data[i]);
}
success:
ret = EXIT_SUCCESS;
out:
free(strings);
free(stats);
return ret;
}
static int statistics(struct state *state, int argc __maybe_unused,
char **argv __maybe_unused)
{
int ret = EXIT_FAILURE;
struct ifreq ifr;
int fd = -1;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, state->mesh_iface, sizeof(ifr.ifr_name));
ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
perror("Error - can't open socket");
goto out;
}
ret = statistics_custom_get(fd, &ifr);
out:
if (fd >= 0)
close(fd);
return ret;
}
COMMAND(SUBCOMMAND_MIF, statistics, "s", COMMAND_FLAG_MESH_IFACE, NULL,
" \tprint mesh statistics");
|