Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions drivers/wifi/nrf_wifi/inc/fmac_main.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@

#define NRF70_DRIVER_VERSION "1."KERNEL_VERSION_STRING

/* Calculate compile-time maximum for vendor stats */
#ifdef CONFIG_NET_STATISTICS_ETHERNET_VENDOR
#define MAX_VENDOR_STATS ((sizeof(struct rpu_sys_fw_stats) / sizeof(uint32_t)) + 1)
#endif /* CONFIG_NET_STATISTICS_ETHERNET_VENDOR */

#ifndef CONFIG_NRF70_OFFLOADED_RAW_TX
#ifndef CONFIG_NRF70_RADIO_TEST
struct nrf_wifi_vif_ctx_zep {
Expand All @@ -61,6 +66,10 @@ struct nrf_wifi_vif_ctx_zep {
bool set_if_event_received;
int set_if_status;
#ifdef CONFIG_NET_STATISTICS_ETHERNET
#ifdef CONFIG_NET_STATISTICS_ETHERNET_VENDOR
struct net_stats_eth_vendor eth_stats_vendor_data[MAX_VENDOR_STATS];
char vendor_key_strings[MAX_VENDOR_STATS][16];
#endif /* CONFIG_NET_STATISTICS_ETHERNET_VENDOR */
struct net_stats_eth eth_stats;
#endif /* CONFIG_NET_STATISTICS_ETHERNET */
#if defined(CONFIG_NRF70_STA_MODE) || defined(CONFIG_NRF70_RAW_DATA_RX)
Expand Down
73 changes: 73 additions & 0 deletions drivers/wifi/nrf_wifi/src/net_if.c
Original file line number Diff line number Diff line change
Expand Up @@ -1213,6 +1213,16 @@ int nrf_wifi_if_set_config_zep(const struct device *dev,
struct net_stats_eth *nrf_wifi_eth_stats_get(const struct device *dev)
{
struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
#ifdef CONFIG_NET_STATISTICS_ETHERNET_VENDOR
struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL;
struct rpu_sys_op_stats stats;
enum nrf_wifi_status status;
size_t fw_stats_size;
size_t num_uint32;
const uint8_t *fw_stats_bytes;
size_t i;
int vendor_idx = 0;
#endif /* CONFIG_NET_STATISTICS_ETHERNET_VENDOR */

if (!dev) {
LOG_ERR("%s Device not found", __func__);
Expand All @@ -1225,6 +1235,69 @@ struct net_stats_eth *nrf_wifi_eth_stats_get(const struct device *dev)
goto out;
}

#ifdef CONFIG_NET_STATISTICS_ETHERNET_VENDOR
rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep;
if (!rpu_ctx_zep || !rpu_ctx_zep->rpu_ctx) {
LOG_ERR("%s: rpu_ctx_zep or rpu_ctx is NULL", __func__);
goto out;
}

memset(&stats, 0, sizeof(stats));
status = nrf_wifi_sys_fmac_stats_get(rpu_ctx_zep->rpu_ctx,
RPU_STATS_TYPE_ALL,
&stats);
if (status != NRF_WIFI_STATUS_SUCCESS) {
LOG_ERR("%s: Failed to get RPU stats", __func__);
goto ret;
}

/* Treat stats.fw as a blob and divide into uint32_t chunks */
fw_stats_size = sizeof(stats.fw);
num_uint32 = fw_stats_size / sizeof(uint32_t);
fw_stats_bytes = (const uint8_t *)&stats.fw;

vendor_idx = 0;

for (i = 0; i < num_uint32 && vendor_idx < MAX_VENDOR_STATS - 1; i++) {
uint32_t val;
const char **key_ptr;
uint32_t *val_ptr;

/* Extract uint32_t value from blob */
memcpy(&val, fw_stats_bytes + i * sizeof(uint32_t), sizeof(uint32_t));

/* Create key name */
snprintk(vif_ctx_zep->vendor_key_strings[vendor_idx], 16, "fw_%zu", i);

/* Assign key */
key_ptr = (const char **)
&vif_ctx_zep->eth_stats_vendor_data[vendor_idx].key;
*key_ptr = vif_ctx_zep->vendor_key_strings[vendor_idx];

/* Assign value */
val_ptr = (uint32_t *)
&vif_ctx_zep->eth_stats_vendor_data[vendor_idx].value;
*val_ptr = val;

vendor_idx++;
}

/* Null terminator entry */
{
const char **key_ptr = (const char **)
&vif_ctx_zep->eth_stats_vendor_data[vendor_idx].key;
uint32_t *val_ptr = (uint32_t *)
&vif_ctx_zep->eth_stats_vendor_data[vendor_idx].value;

*key_ptr = NULL;
*val_ptr = 0;
}

/* Point to the static vendor data */
vif_ctx_zep->eth_stats.vendor = vif_ctx_zep->eth_stats_vendor_data;

ret:
#endif /* CONFIG_NET_STATISTICS_ETHERNET_VENDOR */
return &vif_ctx_zep->eth_stats;
out:
return NULL;
Expand Down
100 changes: 85 additions & 15 deletions subsys/net/lib/shell/stats.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,16 @@ LOG_MODULE_DECLARE(net_shell);

#include "../ip/net_stats.h"

enum net_shell_stats_format {
NET_SHELL_STATS_FORMAT_DEFAULT,
NET_SHELL_STATS_FORMAT_KEY_VALUE,
NET_SHELL_STATS_FORMAT_HEX_BLOB,
NET_SHELL_STATS_FORMAT_BOTH
};

#if defined(CONFIG_NET_STATISTICS)


#if NET_TC_COUNT > 1
static const char *priority2str(enum net_priority priority)
{
Expand Down Expand Up @@ -45,7 +53,7 @@ static const char *priority2str(enum net_priority priority)
#if defined(CONFIG_NET_STATISTICS_ETHERNET) && \
defined(CONFIG_NET_STATISTICS_USER_API)
static void print_eth_stats(struct net_if *iface, struct net_stats_eth *data,
const struct shell *sh)
const struct shell *sh, struct net_shell_user_data *user_data)
{
PR("Statistics for Ethernet interface %p [%d]\n", iface,
net_if_get_by_iface(iface));
Expand Down Expand Up @@ -110,16 +118,42 @@ static void print_eth_stats(struct net_if *iface, struct net_stats_eth *data,

#if defined(CONFIG_NET_STATISTICS_ETHERNET_VENDOR)
if (data->vendor) {
PR("Vendor specific statistics for Ethernet "
"interface %p [%d]:\n",
iface, net_if_get_by_iface(iface));
size_t i = 0;
enum net_shell_stats_format format = NET_SHELL_STATS_FORMAT_DEFAULT;

if (user_data != NULL) {
format = *(enum net_shell_stats_format *)user_data->user_data;
}

do {
PR("%s : %u\n", data->vendor[i].key,
data->vendor[i].value);
i++;
} while (data->vendor[i].key);
PR("Vendor specific statistics for Ethernet interface %p [%d]:\n",
iface, net_if_get_by_iface(iface));

/* Print key-value pairs if requested */
if (format == NET_SHELL_STATS_FORMAT_DEFAULT ||
format == NET_SHELL_STATS_FORMAT_KEY_VALUE ||
format == NET_SHELL_STATS_FORMAT_BOTH) {
do {
PR("%s : %u\n", data->vendor[i].key, data->vendor[i].value);
i++;
} while (data->vendor[i].key != NULL);
}

/* Print hex blob if requested */
if (format == NET_SHELL_STATS_FORMAT_HEX_BLOB ||
format == NET_SHELL_STATS_FORMAT_BOTH) {
/* Suitable for parsing */
PR("Vendor stats hex blob: ");
for (i = 0; data->vendor[i].key != NULL; i++) {
uint32_t v = data->vendor[i].value;

PR("%02x%02x%02x%02x",
(uint8_t)(v & 0xFF),
(uint8_t)((v >> 8) & 0xFF),
(uint8_t)((v >> 16) & 0xFF),
(uint8_t)((v >> 24) & 0xFF));
}
PR("\n");
}
}
#endif /* CONFIG_NET_STATISTICS_ETHERNET_VENDOR */
}
Expand Down Expand Up @@ -591,7 +625,7 @@ static void net_shell_print_statistics(struct net_if *iface, void *user_data)
ret = net_mgmt(NET_REQUEST_STATS_GET_ETHERNET, iface,
&eth_data, sizeof(eth_data));
if (!ret) {
print_eth_stats(iface, &eth_data, sh);
print_eth_stats(iface, &eth_data, sh, data);
}
}
#endif /* CONFIG_NET_STATISTICS_ETHERNET && CONFIG_NET_STATISTICS_USER_API */
Expand Down Expand Up @@ -628,8 +662,23 @@ int cmd_net_stats_all(const struct shell *sh, size_t argc, char *argv[])
#endif

#if defined(CONFIG_NET_STATISTICS)
enum net_shell_stats_format format = NET_SHELL_STATS_FORMAT_DEFAULT;

user_data.sh = sh;

/* Parse format argument if provided */
if (argc > 1) {
if (strcmp(argv[1], "key-value") == 0) {
format = NET_SHELL_STATS_FORMAT_KEY_VALUE;
} else if (strcmp(argv[1], "hex-blob") == 0) {
format = NET_SHELL_STATS_FORMAT_HEX_BLOB;
} else if (strcmp(argv[1], "both") == 0) {
format = NET_SHELL_STATS_FORMAT_BOTH;
}
}

user_data.user_data = &format;

/* Print global network statistics */
net_shell_print_statistics_all(&user_data);
#else
Expand Down Expand Up @@ -673,8 +722,23 @@ int cmd_net_stats_iface(const struct shell *sh, size_t argc, char *argv[])
return -ENOEXEC;
}

enum net_shell_stats_format format = NET_SHELL_STATS_FORMAT_DEFAULT;

data.sh = sh;

/* Parse format argument if provided */
if (argc > 2) {
if (strcmp(argv[2], "key-value") == 0) {
format = NET_SHELL_STATS_FORMAT_KEY_VALUE;
} else if (strcmp(argv[2], "hex-blob") == 0) {
format = NET_SHELL_STATS_FORMAT_HEX_BLOB;
} else if (strcmp(argv[2], "both") == 0) {
format = NET_SHELL_STATS_FORMAT_BOTH;
}
}

data.user_data = &format;

net_shell_print_statistics(iface, &data);
#else
PR_INFO("Per network interface statistics not collected.\n");
Expand Down Expand Up @@ -702,7 +766,8 @@ static int cmd_net_stats(const struct shell *sh, size_t argc, char *argv[])
if (strcmp(argv[1], "reset") == 0) {
net_stats_reset(NULL);
} else {
cmd_net_stats_iface(sh, argc, argv);
/* Shift arguments for iface command */
cmd_net_stats_iface(sh, argc - 1, &argv[1]);
}
#else
ARG_UNUSED(argc);
Expand All @@ -723,15 +788,20 @@ static int cmd_net_stats(const struct shell *sh, size_t argc, char *argv[])

SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_stats,
SHELL_CMD(all, NULL,
"Show network statistics for all network interfaces.",
"Show network statistics for all network interfaces.\n"
"Usage: net stats all [key-value|hex-blob|both]",
cmd_net_stats_all),
SHELL_CMD(iface, IFACE_DYN_CMD,
"'net stats <index>' shows network statistics for "
"one specific network interface.",
"'net stats <index> [key-value|hex-blob|both]' shows network statistics for "
"one specific network interface.\n"
"Format options:\n"
" key-value: Show vendor stats as key-value pairs (default)\n"
" hex-blob: Show vendor stats as hex blob for parsing\n"
" both: Show both key-value and hex blob formats",
cmd_net_stats_iface),
SHELL_SUBCMD_SET_END
);

SHELL_SUBCMD_ADD((net), stats, &net_cmd_stats,
"Show network statistics.",
cmd_net_stats, 1, 1);
cmd_net_stats, 1, 3);
2 changes: 1 addition & 1 deletion west.yml
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ manifest:
revision: 40403f5f2805cca210d2a47c8717d89c4e816cda
path: modules/bsim_hw_models/nrf_hw_models
- name: nrf_wifi
revision: 53500666a59195b44e2e5a939c111effbf23db7b
revision: b822726084f55df19aa6660dc46cf602757e8645
path: modules/lib/nrf_wifi
- name: open-amp
revision: c30a6d8b92fcebdb797fc1a7698e8729e250f637
Expand Down