nss-info: remove source and switch to repo based build

Signed-off-by: Sean Khan <datapronix@protonmail.com>
This commit is contained in:
Sean Khan 2025-07-10 21:57:22 -04:00
parent 99700f4bf9
commit ff7d2b1c00
24 changed files with 563 additions and 2502 deletions

113
nss-userspace-oss/Makefile Normal file
View File

@ -0,0 +1,113 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=nss-userspace-oss
PKG_RELEASE:=2
PKG_SOURCE_URL:=https://git.codelinaro.org/clo/qsdk/oss/nss-userspace.git
PKG_SOURCE_PROTO:=git
PKG_SOURCE_DATE:=2024-11-27
PKG_SOURCE_VERSION:=7233e22
PKG_MIRROR_HASH:=03dea072feb18916f32798f7bfd8c8811733e0681c4e9e1d77dd895f121de734
QSDK_VERSION:=13.0
PKG_VERSION:=$(QSDK_VERSION).$(subst -,.,$(PKG_SOURCE_DATE))~$(PKG_SOURCE_VERSION)
PKG_BUILD_PARALLEL:=1
PKG_FLAGS:=nonshared
PKG_BUILD_FLAGS:=gc-sections lto
PKG_CONFIG_DEPENDS:= \
CONFIG_NSS_NLCAPWAP_ENABLE \
CONFIG_NSS_NLDTLS_ENABLE \
CONFIG_NSS_NLGRE_REDIR_ENABLE \
CONFIG_NSS_NLIPSEC_ENABLE \
CONFIG_NSS_NLQRFS_ENABLE \
CONFIG_NSS_NLUDP_ST_ENABLE
include $(INCLUDE_DIR)/package.mk
define Package/nss-userspace
TITLE:=Userspace utilities for NSS
endef
define Package/libnl-nss
$(call Package/nss-userspace)
SECTION:=Libs
CATEGORY:=Libraries
TITLE += (libnl-nss)
DEPENDS:=+libpthread +libnl-tiny +kmod-qca-nss-drv-netlink
endef
define Package/libnl-nss/description
A framework in the userspace that establishes communication between userspace applications and the kernel.
endef
define Package/nssinfo
$(call Package/nss-userspace)
SECTION:=Utils
CATEGORY:=Utilities
TITLE += (nssinfo)
DEPENDS:=+libncurses +libnl-nss
endef
define Package/nssinfo/description
A userspace utility for fetching stats from NSS.
endef
TARGET_CFLAGS += $(FPIC) -D_GNU_SOURCE=1
TARGET_CPPFLAGS:= \
-I$(STAGING_DIR)/usr/include/qca-nss-clients \
-I$(STAGING_DIR)/usr/include/qca-nss-drv \
-I$(STAGING_DIR)/usr/include/libnl-tiny \
-I$(STAGING_DIR)/usr/include/libnl-nss
ifneq ($(CONFIG_PACKAGE_libnl-nss),)
MAKE_FLAGS+=BUILD_LIBNSS=y
ifdef CONFIG_NSS_NLUDP_ST_ENABLE
MAKE_FLAGS+=udp_st=y
endif
ifdef CONFIG_NSS_NLQRFS_ENABLE
MAKE_FLAGS+=qrfs=y
endif
ifdef CONFIG_NSS_NLGRE_REDIR_ENABLE
MAKE_FLAGS+=gre_redir=y
endif
ifdef CONFIG_NSS_NLIPSEC_ENABLE
MAKE_FLAGS+=ipsec=y
endif
ifdef CONFIG_NSS_NLDTLS_ENABLE
MAKE_FLAGS+=dtls=y
endif
ifdef CONFIG_NSS_NLCAPWAP_ENABLE
MAKE_FLAGS+=capwap=y
endif
endif
ifneq ($(CONFIG_PACKAGE_nssinfo),)
MAKE_FLAGS+=BUILD_NSSINFO=y
endif
define Build/libnl-nss/InstallDev
$(INSTALL_DIR) $(STAGING_DIR)/usr/include/libnl-nss
$(CP) $(PKG_BUILD_DIR)/lib/obj/libnl-nss.so $(STAGING_DIR)/usr/lib
$(CP) $(PKG_BUILD_DIR)/lib/include/* $(STAGING_DIR)/usr/include/libnl-nss
endef
define Package/libnl-nss/install
$(INSTALL_DIR) $(1)/usr/lib
$(INSTALL_DATA) $(PKG_BUILD_DIR)/lib/obj/libnl-nss.so $(1)/usr/lib
endef
define Package/nssinfo/install
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/nssinfo/obj/nssinfo $(1)/usr/sbin/
endef
$(eval $(call BuildPackage,nssinfo))
$(eval $(call BuildPackage,libnl-nss))

View File

@ -1,39 +0,0 @@
include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=nssinfo
PKG_RELEASE:=1
include $(INCLUDE_DIR)/package.mk
define Package/nssinfo
SECTION:=utils
CATEGORY:=Utilities
TITLE:=Userspace utility for fetching stats from NSS
DEPENDS:=+libncurses +libnl-nss
endef
define Package/nssinfo/description
A userspace utility for fetching stats from NSS.
endef
TOOL_CFLAGS:= -I$(STAGING_DIR)/usr/include/qca-nss-clients \
-I$(STAGING_DIR)/usr/include/qca-nss-drv \
-I$(STAGING_DIR)/usr/include/libnl3 \
-I$(STAGING_DIR)/usr/include/libnl-nss
TOOL_LDFLAGS:= -L$(STAGING_DIR)/lib
define Build/Compile
$(MAKE) -C $(PKG_BUILD_DIR) \
CC="$(TARGET_CC)" \
CFLAGS="$(TOOL_CFLAGS)" \
LD_LIBRARY_PATH="$(TOOL_LDFLAGS)"
endef
define Package/nssinfo/install
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/obj/nssinfo $(1)/usr/sbin/
endef
# $(eval $(call BuildPackage,nssinfo))

View File

@ -1,35 +0,0 @@
MKDIR = mkdir -p $(@D)
SRCPATH = src
OBJPATH = obj
SRCDIR = ./
BINARY = $(OBJPATH)/nssinfo
SOURCES = $(wildcard $(SRCDIR)/src/*.c)
HEADERS = $(wildcard $(SRCDIR)/include/*.h)
OBJECTS = $(SOURCES:$(SRCDIR)/src/%.c=$(OBJPATH)/%.o)
INCLUDE += -I../lib/include
EXTRA_CFLAGS = -Wall -Wno-error=format-truncation -UENABLE_DEBUG
LDFLAGS = -lnl-nss -lncurses
LDLIBS = -L../lib/obj
all: release
release: $(BINARY)
$(OBJPATH)/%.o: $(SRCPATH)/%.c $(HEADERS)
$(MKDIR)
@echo [CC] $@
@$(CC) -c $(CFLAGS) $(EXTRA_CFLAGS) $(INCLUDE) -o $@ $<
$(BINARY): $(OBJECTS)
@echo $(BINARY)
@echo [LD] $@
@$(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
clean:
@echo [Clean]
@rm -f $(OBJECTS)
@rm -f $(BINARY)
@rmdir $(OBJPATH)
.PHONY: clean

View File

@ -1,714 +0,0 @@
/*
**************************************************************************
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all copies.
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**************************************************************************
*/
/*
* @file NSSINFO handler
*/
#include <signal.h>
#include "nssinfo.h"
static pthread_t nssinfo_display_thread; /* Display statistics thread */
static char buf[NSSINFO_STR_LEN]; /* Formatted stats buffer */
bool display_all_stats; /* Display all stats per sub-system */
int invalid_input; /* Identify invalid input */
FILE *output_file; /* Output file pointer */
FILE *flow_file; /* Flow file pointer */
/* Array of pointers to node stats */
struct node *nodes[NSS_MAX_CORES][NSS_MAX_NET_INTERFACES];
/*
* NSS subsystems in alphabetical order for nssinfo tool
* - Make sure the order here is the same as in 'enum nss_nlcmn_subsys'
* defined in qca-nss-clients/netlink/include/nss_nlcmn_if.h.
*/
struct nssinfo_subsystem_info nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_MAX] = {
{.subsystem_name = "dynamic_interface", .init = nssinfo_dynamic_interface_init, .deinit = nssinfo_dynamic_interface_deinit},
{.subsystem_name = "eth_rx", .init = nssinfo_eth_rx_init, .deinit = nssinfo_eth_rx_deinit},
{.subsystem_name = "ipv4", .init = nssinfo_ipv4_init, .deinit = nssinfo_ipv4_deinit},
{.subsystem_name = "ipv6", .init = nssinfo_ipv6_init, .deinit = nssinfo_ipv6_deinit},
{.subsystem_name = "lso_rx", .init = nssinfo_lso_rx_init, .deinit = nssinfo_lso_rx_deinit},
{.subsystem_name = "n2h", .init = nssinfo_n2h_init, .deinit = nssinfo_n2h_deinit},
};
char *nssinfo_summary_fmt = "%-12s %-13s %-13s %-9s %-9s\n";
/*
* nssinfo_print_summary_header()
* Print the summary header.
*/
void nssinfo_print_summary_header(void)
{
nssinfo_stats_print(nssinfo_summary_fmt, "Node", "RX Pkts", "TX Pkts", "Drops", "Exceptions");
nssinfo_stats_print(nssinfo_summary_fmt, "----", "-------", "-------", "-----", "----------");
}
/*
* nssinfo_print_summary()
* Print the summary of the stats:
* - rx pkts
* - tx pkts
* - rx queue drops
* - exceptions
*/
void nssinfo_print_summary(char *node, uint64_t *cmn_node_stats, uint64_t *exception_stats, uint64_t exception_max)
{
int i;
uint64_t drops = 0, exceptions = 0;
char str_rx[NSSINFO_STR_LEN], str_tx[NSSINFO_STR_LEN], str_drop[NSSINFO_STR_LEN], str_ex[NSSINFO_STR_LEN];
assert(cmn_node_stats);
memset(str_rx, 0, sizeof(str_rx));
memset(str_tx, 0, sizeof(str_tx));
memset(str_drop, 0, sizeof(str_drop));
memset(str_ex, 0, sizeof(str_ex));
for (i = NSS_STATS_NODE_RX_QUEUE_0_DROPPED; i < NSS_STATS_NODE_MAX; i++) {
drops += cmn_node_stats[i];
}
if (exception_stats) {
for (i = 0 ; i < exception_max; i++) {
exceptions += exception_stats[i];
}
}
if (cmn_node_stats[NSS_STATS_NODE_RX_PKTS] > 0 || cmn_node_stats[NSS_STATS_NODE_TX_PKTS] > 0 ||
drops > 0 || exceptions > 0 || arguments.verbose) {
char *format_stats = nssinfo_format_stats(cmn_node_stats[NSS_STATS_NODE_RX_PKTS]);
strlcpy(str_rx, format_stats, sizeof(str_rx));
format_stats = nssinfo_format_stats(cmn_node_stats[NSS_STATS_NODE_TX_PKTS]);
strlcpy(str_tx, format_stats, sizeof(str_tx));
format_stats = nssinfo_format_stats(drops);
strlcpy(str_drop, format_stats, sizeof(str_drop));
if (exception_stats) {
format_stats = nssinfo_format_stats(exceptions);
strlcpy(str_ex, format_stats, sizeof(str_ex));
}
nssinfo_stats_print(nssinfo_summary_fmt, node, str_rx, str_tx, str_drop, str_ex);
}
}
/*
* nssinfo_print_all()
* Print detailed statistics.
*/
void nssinfo_print_all(char *node, char *stat_details, struct nssinfo_stats_info *stats_info, uint64_t max, uint64_t *stats_val)
{
int i;
uint16_t maxlen = 0;
char *type;
for (i = 0; i < max; i++){
if (strlen(stats_info[i].stats_name) > maxlen) {
maxlen = strlen(stats_info[i].stats_name);
}
}
/*
* Display stats header, e.g. "#ipv4 Common Stats\n"
*/
if (stat_details != NULL) {
nssinfo_stats_print("#%s\n", stat_details);
}
/* Display each stat, e.g.
* ipv4_rx_byts = 32903179 common
* ipv4_mc_create_invalid_interface = 12 special
* ...
*/
for (i = 0; i < max; i++) {
if (arguments.verbose || stats_val[i] > 0) {
switch (stats_info[i].stats_type) {
case NSS_STATS_TYPE_COMMON:
type = "common";
break;
case NSS_STATS_TYPE_SPECIAL:
type = "special";
break;
case NSS_STATS_TYPE_DROP:
type = "drop";
break;
case NSS_STATS_TYPE_ERROR:
type = "error";
break;
case NSS_STATS_TYPE_EXCEPTION:
type = "exception";
break;
default:
type = "unknown";
break;
}
nssinfo_stats_print("%s_%-*s = %-20llu %-s\n",
node, maxlen, stats_info[i].stats_name, stats_val[i], type);
}
}
nssinfo_stats_print("\n");
return;
}
/*
* nssinfo_parse_stats_strings()
* Parse each line in the debug strings file.
*
* Each line has the following format:
* \t<stats_type> , <stats_name>\n
* for example:
* root@OpenWrt:/sys/kernel/debug/qca-nss-drv/strings# cat n2h
* 0 , rx_pkts
* ...
* 1 , rx_queue[0]_drops
* ...
* 4 , n2h_data_interface_invalid
*/
static void nssinfo_parse_stats_strings(struct nssinfo_stats_info *info, char *line)
{
char *token;
char *rest = NULL;
token = strtok_r(line, " ", &rest);
if (token) {
info->stats_type = atoi(token);
token = strtok_r(NULL, ",", &rest);
}
if (token) {
token = strtok_r(token, " ", &rest);
}
if (token) {
token = strtok_r(token, "\n", &rest);
}
if (token) {
strlcpy(info->stats_name, token, sizeof(info->stats_name));
}
}
/*
* nssinfo_stats_info_init()
* Init 'struct nssinfo_stats_info' from a file in /sys/kernel/debug/qca-nss-drv/strings/.
*/
int nssinfo_stats_info_init(struct nssinfo_stats_info *info, char *strings_file)
{
FILE *fptr;
char line[NSS_STATS_MAX_STR_LENGTH];
fptr = fopen(strings_file, "r");
if (!fptr) {
nssinfo_error("Unable to open\n");
return -1;
}
while (fgets(line, NSS_STATS_MAX_STR_LENGTH, fptr)) {
nssinfo_parse_stats_strings(info, line);
info++;
}
fclose(fptr);
return 0;
}
/*
* nssinfo_node_stats_destroy()
* Release memories used to store the node stats.
*/
void nssinfo_node_stats_destroy(pthread_mutex_t *mutex, uint32_t core_id, uint32_t if_num)
{
struct node *p, *next;
if (mutex) {
pthread_mutex_lock(mutex);
}
p = nodes[core_id][if_num];
nodes[core_id][if_num] = NULL;
if (mutex) {
pthread_mutex_unlock(mutex);
}
while (p) {
next = p->next;
if (p->cmn_node_stats) {
free(p->cmn_node_stats);
}
if (p->node_stats) {
free(p->node_stats);
}
if (p->exception_stats) {
free(p->exception_stats);
}
free(p);
p = next;
}
return;
}
/*
* nssinfo_add_comma()
* Add commas in thousand's place in statistics.
*/
static char* nssinfo_add_comma(uint64_t num)
{
if (num < 1000) {
snprintf(buf, sizeof(buf), "%llu", num);
return buf;
}
nssinfo_add_comma(num/1000);
snprintf(buf + strlen(buf), sizeof(buf[NSSINFO_STR_LEN] + strlen(buf)), ",%03llu", num % 1000);
return buf;
}
/*
* nssinfo_add_suffix()
* Convert number into K thousands M million and B billion suffix.
*/
static char* nssinfo_add_suffix(uint64_t num)
{
if (num < 1000) {
snprintf(buf, sizeof(buf), "%llu", num);
return buf;
}
if (1000 <= num && num < 1000000) {
snprintf(buf , sizeof(buf), "%.2lfK", num / 1000.0);
return buf;
}
if (1000000 <= num && num < 1000000000) {
snprintf(buf , sizeof(buf), "%.2lfM", num / 1000000.0);
return buf;
}
if (1000000000 <= num) {
snprintf(buf , sizeof(buf), "%.2lfB", num / 1000000000.0);
return buf;
}
return buf;
}
/*
* nssinfo_format_stats()
* Format statistics value.
*/
char* nssinfo_format_stats(uint64_t num)
{
memset(buf, 0, sizeof(buf));
if (!arguments.higher_unit) {
return nssinfo_add_comma(num);
}
return nssinfo_add_suffix(num);
}
/*
* nssinfo_stats_display()
* Invoke each sub-system's display function.
*/
static void *nssinfo_stats_display(void *arg)
{
int i, j, core;
char mesg[]="NSS STATS";
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
for (;;) {
nssinfo_stats_print("\t\t\t%s\n", mesg);
/*
* If user does not specify a core id,
* check if the flow file is specified and display stats accordingly.
*/
if (arguments.core < 0) {
/*
* If flow file is not specified (via '-f' option),
* display each node's summary stats in alphabetical order for all the cores.
*/
if (!flow_file) {
for (core = 0 ; core < NSS_MAX_CORES ; core++) {
nssinfo_stats_print("Stats for core %d\n",core);
nssinfo_print_summary_header();
for (i = 0 ; i < NSS_NLCMN_SUBSYS_MAX; i++) {
if (nssinfo_subsystem_array[i].is_inited && i != NSS_NLCMN_SUBSYS_DYNAMIC_INTERFACE) {
nssinfo_subsystem_array[i].display(core, NULL);
}
}
nssinfo_stats_print("\n");
}
goto done;
}
/*
* Flow file is specified (via '-f' option),
* Parse the network graph from flow file and display the node's summary stats
* For example, the network graph would look like
* ipv4-0 eth_rx-0 n2h-1
* Where, node = ipv4 , core = 0
* node = eth_rx , core = 0
* node = n2h , core = 1
*/
char *line = NULL;
char *rest = NULL;
size_t len = 0;
ssize_t read;
char *node = NULL;
int matched = 0;
nssinfo_print_summary_header();
fseek(flow_file, 0, SEEK_SET);
while ((read = getline(&line, &len, flow_file)) != -1) {
node = strtok_r(line, "-", &rest);
while (node != NULL) {
core = atoi(strtok_r(NULL, " ", &rest));
if (core >= NSS_MAX_CORES || core < 0) {
printf("Invalid core id `%d'\n", core);
exit(-1);
}
for (j = 0; j < NSS_NLCMN_SUBSYS_MAX; j++) {
if (nssinfo_subsystem_array[j].is_inited &&
strstr(node, nssinfo_subsystem_array[j].subsystem_name)) {
if (j != NSS_NLCMN_SUBSYS_DYNAMIC_INTERFACE) {
++matched;
nssinfo_subsystem_array[j].display(core, node);
}
}
}
node = strtok_r(NULL, "-", &rest);
}
/* If all NODE names are invalid */
if (matched == invalid_input) {
nssinfo_error("Invalid input\n");
return NULL;
}
}
if (line) {
free(line);
}
goto done;
}
if (!arguments.strings[0]) {
/*
* If a core id is specified (via '-c' option) but NODE is not specified,
* display each node's summary stats in alphabetical order for that core.
*/
nssinfo_stats_print("Stats for core %d\n", arguments.core);
nssinfo_print_summary_header();
for (i = 0 ; i < NSS_NLCMN_SUBSYS_MAX; i++) {
if (nssinfo_subsystem_array[i].is_inited && i != NSS_NLCMN_SUBSYS_DYNAMIC_INTERFACE) {
nssinfo_subsystem_array[i].display(arguments.core, NULL);
}
}
goto done;
}
/*
* If a core id is specified and at least one NODE is specified.
*/
nssinfo_stats_print("Stats for core %d\n", arguments.core);
/*
* If user specifies only one NODE, then display all stats for this NODE.
* For example, if NODE="ipv4", then display:
* - common stats (i.e. enum nss_stats_node)
* - ipv4 special stats (i.e. enum nss_ipv4_stats_types)
* - ipv4 exception stats (i.e. enum nss_ipv4_exception_events)
*/
if (!arguments.strings[1]) {
display_all_stats = true;
} else {
/*
* If user specifies more than one NODEs, then display the summary stats for each node
*/
nssinfo_print_summary_header();
}
/*
* Now, display NODEs in the desired order.
*/
int matched = 0;
for (i = 0; arguments.strings[i]; i++) {
for (j = 0; j < NSS_NLCMN_SUBSYS_MAX; j++) {
if (nssinfo_subsystem_array[j].is_inited &&
strstr(arguments.strings[i], nssinfo_subsystem_array[j].subsystem_name)) {
if (j != NSS_NLCMN_SUBSYS_DYNAMIC_INTERFACE) {
++matched;
nssinfo_subsystem_array[j].display(arguments.core, arguments.strings[i]);
}
}
}
}
/*
* If all NODE names are invalid.
*/
if (matched == invalid_input) {
nssinfo_error("Invalid input\n");
return NULL;
}
done:
/*
* If using ncurses, refresh the screen.
*/
if (!output_file) {
refresh(); /* draw on screen */
clear(); /* clear screen buffer */
move(0, 0); /* move cursor to (line, column)=(0,0) */
}
invalid_input = 0;
sleep(arguments.rate);
}
}
/*
* nssinfo_curses_init()
* Initialize curses library.
*/
static int nssinfo_curses_init()
{
int rows, cols;
if (!initscr()) { /* satrt curses mode */
nssinfo_error("Unable to initialize curses screen\n");
return -EOPNOTSUPP;
}
getmaxyx(stdscr, rows, cols); /* get the size of the screen */
if (rows < CURSES_ROWS_MIN) {
nssinfo_error("Screen must be at least %d rows in height", CURSES_ROWS_MIN);
goto out;
}
if (cols < CURSES_COLS_MIN) {
nssinfo_error("Screen must be at least %d columns width", CURSES_COLS_MIN);
goto out;
}
cbreak(); /* disable line buffering */
noecho(); /* not to echo the input back to the screen */
nonl(); /* disable 'enter' key translation */
keypad(stdscr, TRUE); /* enable keypad keys, such as arrow keys, etc. */
nodelay(stdscr, TRUE); /* cause getch() to be a non-blocking call */
curs_set(0); /* make the cursor invisible */
clear(); /* clear screen buffer */
move(0, 0); /* move cursor to (line, column)=(0,0) */
return 0;
out:
endwin(); /* stop curses mode */
return -1;
}
/*
* nssinfo_termination_handler()
* Terminates all the modules.
*/
static void nssinfo_termination_handler(int signum)
{
pthread_cancel(nssinfo_display_thread);
}
/*
* nssinfo_display_init()
* Handle displaying all the stats.
*/
static int nssinfo_display_init()
{
int error;
if (!output_file) {
if (nssinfo_curses_init() != 0) {
return -1;
}
}
error = pthread_create(&nssinfo_display_thread, NULL, nssinfo_stats_display, NULL);
if (error) {
nssinfo_error("failed to create display thread, error %d\n", error);
if (!output_file) {
endwin();
}
}
return error;
}
/*
* nssinfo_display_wait()
* Wait for the display thread.
*/
static int nssinfo_display_wait()
{
/*
* waiting for the display thread to be terminated.
*/
pthread_join(nssinfo_display_thread, NULL);
if (!output_file) {
refresh();
endwin();
}
return 0;
}
/*
* nssinfo_notify_callback
* Get notified when NL message is received.
*/
static void nssinfo_notify_callback(int cmd, void *data)
{
if (cmd < NSS_NLCMN_SUBSYS_MAX && nssinfo_subsystem_array[cmd].is_inited) {
nssinfo_subsystem_array[cmd].notify(data);
} else {
nssinfo_error("Unknown message type %d\n", cmd);
}
}
/*
*/
static void nssinfo_deinit(struct nss_nlmcast_ctx *ctx)
{
int i, core;
struct node *node;
nssinfo_deinit_t deinit;
/*
* Close NL socket and terminate ctx->sock.thread
*/
nss_nlmcast_sock_close(ctx);
/*
* Release memory used for storing stats
*/
for (core = 0; core < NSS_MAX_CORES; ++core) {
for (i = 0; i < NSS_MAX_NET_INTERFACES; ++i) {
node = nodes[core][i];
if (node) {
assert(node->subsystem_id != NSS_NLCMN_SUBSYS_DYNAMIC_INTERFACE);
nssinfo_subsystem_array[node->subsystem_id].destroy(core, i);
}
}
}
/*
* Release resources used by each subsystem
*/
for (i = 0; i < NSS_NLCMN_SUBSYS_MAX; i++) {
deinit = nssinfo_subsystem_array[i].deinit;
if (deinit) {
deinit(ctx);
}
}
}
/*
* nssinfo_init()
* Initialize all the modules.
*/
int nssinfo_init(void)
{
int error, i;
struct nss_nlmcast_ctx ctx;
nssinfo_init_t init;
memset(&ctx, 0, sizeof(ctx));
/*
* Create NL socket
*/
error = nss_nlmcast_sock_open(&ctx, nssinfo_notify_callback, NULL);
if (error) {
nssinfo_error("Socket creation failed for NSSINFO, error(%d)\n", error);
return error;
}
/*
* Initialize all the subsystems and subscribe for mcast groups.
*/
for (i = 0; i < NSS_NLCMN_SUBSYS_MAX; i++) {
init = nssinfo_subsystem_array[i].init;
if (init) {
error = init(&ctx);
if (error) {
nssinfo_error("%s init failed, error(%d)\n", nssinfo_subsystem_array[i].subsystem_name, error);
}
}
}
/*
* Listen for MCAST events from kernel.
*/
error = nss_nlmcast_sock_listen(&ctx);
if (error < 0) {
nssinfo_error("failed to listen for mcast events from kernel\n");
goto end;
}
/*
* Create a thread which displays the stats continuously.
*/
error = nssinfo_display_init();
if (error) {
goto end;
}
/*
* Install CTRL-C handler
*/
struct sigaction new_action;
new_action.sa_handler = nssinfo_termination_handler;
sigemptyset(&new_action.sa_mask);
new_action.sa_flags = 0;
error = sigaction(SIGINT, &new_action, NULL);
if (error) {
nssinfo_error("failed to install CTRL-C handler\n");
goto end;
}
/*
* main thread is waiting here
*/
nssinfo_display_wait();
end:
nssinfo_deinit(&ctx);
return error;
}

View File

@ -1,233 +0,0 @@
/*
**************************************************************************
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all copies.
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**************************************************************************
*/
#ifndef __NSSINFO_FAMILY_H
#define __NSSINFO_FAMILY_H
#include "nss_nlbase.h"
#include "ncurses.h"
#include "nssinfo_ipv4.h"
#include "nssinfo_ipv6.h"
#include "nssinfo_ethrx.h"
#include "nssinfo_n2h.h"
#include "nssinfo_dynamic_interface.h"
#include "nssinfo_lso_rx.h"
#include "nss_api_if.h"
#include "nss_dynamic_interface.h"
#include "nss_stats_public.h"
#define NSSINFO_COLOR_RST "\x1b[0m"
#define NSSINFO_COLOR_GRN "\x1b[32m"
#define NSSINFO_COLOR_RED "\x1b[31m"
#define NSSINFO_COLOR_MGT "\x1b[35m"
#ifdef ENABLE_DEBUG
#define nssinfo_info(fmt, arg...) printf(NSSINFO_COLOR_GRN"INF "NSSINFO_COLOR_RST fmt, ## arg)
#define nssinfo_trace(fmt, arg...) printf(NSSINFO_COLOR_MGT"TRC(%s:%d) "NSSINFO_COLOR_RST fmt, __func__, __LINE__, ## arg)
#define nssinfo_options(fmt, arg...) printf(NSSINFO_COLOR_MGT"OPT_%d "NSSINFO_COLOR_RST fmt, ## arg)
#define nssinfo_warn(fmt, arg...) printf(NSSINFO_COLOR_RED"WARN(%s:%d) "NSSINFO_COLOR_RST fmt, __func__, __LINE__, ##arg)
#else
#define nssinfo_info(fmt, arg...)
#define nssinfo_trace(fmt, arg...)
#define nssinfo_options(fmt, arg...)
#define nssinfo_warn(fmt, arg...)
#endif
#define nssinfo_error(fmt, arg...) printf(NSSINFO_COLOR_RED"ERR(%s:%d) "NSSINFO_COLOR_RST fmt, __func__, __LINE__, ## arg)
#define nssinfo_stats_print(fmt, arg...) ({ \
if (output_file) { \
fprintf(output_file, fmt, ## arg); \
} else { \
wprintw(stdscr, fmt, ## arg); \
} \
})
/*
* Minimum terminal size to use curses library
*/
#define CURSES_ROWS_MIN 4
#define CURSES_COLS_MIN 48
/*
* Maximum formatted statistics length
*/
#define NSSINFO_STR_LEN 30
extern bool display_all_stats;
extern FILE *output_file;
extern FILE *flow_file;
extern int invalid_input;
extern struct arguments arguments;
extern char *nssinfo_summary_fmt;
/**
* @brief display method_t function
*
* @param core[IN] NSS core id
*/
typedef void (*nssinfo_stats_display_t)(int core, char *input);
/**
* @brief stats notify method_t function
*
* @param data[IN] data received from Netlink client
*/
typedef void (*nssinfo_stats_notify_t)(void *data);
/**
* @brief init method_t function
*
* @param data[IN] an opague context to be used for initialization
*/
typedef int (*nssinfo_init_t)(void *data);
/**
* @brief deinit method_t function
*
* @param data[IN] an opague context to be used for deinitialization
*/
typedef void (*nssinfo_deinit_t)(void *data);
/**
* @brief destroy method_t function
*
* @param core_id[IN] core id of the node to be destroyed
* @param if_num[IN] interface id of the node to be destroyed
*/
typedef void (*nssinfo_destroy_t)(uint32_t core_id, uint32_t if_num);
/**
* @brief Used by main to communicate with parse_opt
*/
struct arguments {
bool verbose; /*< '-v' >*/
char *output_file; /*< file arg to '--output' >*/
char *flow_file; /*< file arg to '--flowfile' >*/
bool higher_unit; /*< display higher units '-h' >*/
int core; /*< core id >*/
char **strings; /*< non-option arguments: [NODE1 [NODE2 ...]] >*/
int rate; /*< display rate in second >*/
};
/**
* @brief NSSINFO subsystem information
*/
struct nssinfo_subsystem_info {
char *subsystem_name; /**< Subsystem name string */
nssinfo_init_t init; /**< Initialize method_t */
nssinfo_deinit_t deinit; /**< Deinitialize method_t */
nssinfo_stats_display_t display; /**< Display method_t */
nssinfo_stats_notify_t notify; /**< Stats notify method_t */
nssinfo_destroy_t destroy; /**< Stats notify method_t */
bool is_inited; /**< True if the subsystem is initialized */
};
extern struct nssinfo_subsystem_info nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_MAX];
/**
* @brief NSSINFO pnode stats
*/
struct node {
struct node *next; /**< Pointer to next node */
uint64_t id; /**< Dynamic interface number */
int type; /**< see 'enum nss_dynamic_interface_type' */
int subsystem_id; /**< see 'enum nss_nlcmn_subsys' */
void *cmn_node_stats; /**< Common node stats */
void *node_stats; /**< Special stats */
void *exception_stats; /**< Exception stats */
};
extern struct node *nodes[NSS_MAX_CORES][NSS_MAX_NET_INTERFACES];
/**
* @brief Structure definition carrying stats info.
*/
struct nssinfo_stats_info {
char stats_name[NSS_STATS_MAX_STR_LENGTH]; /* stat name */
int stats_type; /* enum that tags stat type */
};
/**
* @brief validates core id and interface number
*
* @param core_id[IN] validates the core d
* @param if_num[IN] validates the interface number
*
* @return true on success or false for failure
*/
static inline bool nssinfo_coreid_ifnum_valid(uint32_t core_id, uint32_t if_num)
{
return (core_id < NSS_MAX_CORES && if_num < NSS_MAX_NET_INTERFACES);
}
/**
* @brief initialize all the modules
*
* @param flow_file[IN] parse it and display output accordingly
*
* @return 0 on success or -ve for failure
*/
int nssinfo_init(void);
/**
* @brief Format statistics value
*
* @param num[IN] statistics value in uint64_t
*
* @return comma separated string
*/
char* nssinfo_format_stats(uint64_t num);
/**
* @brief Init nssinfo_stats_info from kernel debug file.
*
* @param info[IN] pointer to a nssinfo_stats_info array
* @param line[IN] string file in kernel/debug/qca-nss-drv/strings/
*/
int nssinfo_stats_info_init(struct nssinfo_stats_info *info, char *strings_file);
/**
* @brief Free all resources used for node stats.
*
* @param mutex[IN] mutex lock
* @param core_id[IN] core id
* @param if_num[IN] node's interface number
*/
void nssinfo_node_stats_destroy(pthread_mutex_t *mutex, uint32_t core_id, uint32_t if_num);
/**
* @brief Print detailed statistics.
*
* @param node[IN] node for which stats to be printed
* @param stat_details[IN] statistics details to be printed
* @param stats_info[IN] statistics information
* @param max[IN] maximum number of strings
* @param stats_val[IN] statistics values
*/
void nssinfo_print_all(char *node, char *stat_details, struct nssinfo_stats_info *stats_info, uint64_t max, uint64_t *stats_val);
/**
* @brief Print the summary of the statistics.
*
* @param node[IN] node for which stats to be printed
* @param cmn_node_stats[IN] common node stats
* @param exception_stats[IN] exception stats
* @param exception_max[IN] maximum exception type
*/
void nssinfo_print_summary(char *node, uint64_t *cmn_node_stats, uint64_t *exception_stats, uint64_t exception_max);
void nssinfo_print_summary_header(void);
#endif /* __NSSINFO_FAMILY_H*/

View File

@ -1,72 +0,0 @@
/*
**************************************************************************
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all copies.
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**************************************************************************
*/
/*
* @file NSSINFO dynamic interface handler
*/
#include "nssinfo.h"
#include <nss_nldynamic_interface_if.h>
/*
* nssinfo_dynamic_interface_destroy_notify()
* Dynamic interface notify callback function.
*/
static void nssinfo_dynamic_interface_destroy_notify(void *data)
{
struct nss_dynamic_interface_notification *nss_info = (struct nss_dynamic_interface_notification *)data;
struct node *node = nodes[nss_info->core_id][nss_info->if_num];
if (!node) {
return;
}
nssinfo_subsystem_array[node->subsystem_id].destroy(nss_info->core_id, nss_info->if_num);
}
/*
* nssinfo_dynamic_interface_deinit()
* Deinitialize dynamic_interface module.
*/
void nssinfo_dynamic_interface_deinit(void *data)
{
struct nss_nlmcast_ctx *ctx = (struct nss_nlmcast_ctx *)data;
nss_nlmcast_sock_leave_grp(ctx, NSS_NLDYNAMIC_INTERFACE_MCAST_GRP);
}
/*
* nssinfo_dynamic_interface_init()
* Initialize dynamic interface module.
*/
int nssinfo_dynamic_interface_init(void *data)
{
int error;
struct nss_nlmcast_ctx *ctx = (struct nss_nlmcast_ctx *)data;
/*
* Subscribe for dynamic interface multicast group.
*/
nss_nlsock_set_family(&ctx->sock, NSS_NLDYNAMIC_INTERFACE_FAMILY);
error = nss_nlmcast_sock_join_grp(ctx, NSS_NLDYNAMIC_INTERFACE_MCAST_GRP);
if (error) {
nssinfo_warn("Unable to join dynamic interface multicast group.\n");
return error;
}
nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_DYNAMIC_INTERFACE].notify = nssinfo_dynamic_interface_destroy_notify;
nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_DYNAMIC_INTERFACE].is_inited = true;
return 0;
}

View File

@ -1,28 +0,0 @@
/*
**************************************************************************
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all copies.
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**************************************************************************
*/
#ifndef __NSSINFO_DYNAMIC_INTERFACE_H
#define __NSSINFO_DYNAMIC_INTERFACE_H
/**
* @brief initialize dynamic interface module.
*
* @return 0 on success or -ve for failure
*/
int nssinfo_dynamic_interface_init(void *data);
void nssinfo_dynamic_interface_deinit(void *data);
#endif /* __NSSINFO_DYNAMIC_INTERFACE_H*/

View File

@ -1,215 +0,0 @@
/*
**************************************************************************
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all copies.
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**************************************************************************
*/
/*
* @file NSSINFO Ethernet Rx handler
*/
#include "nssinfo.h"
#include <nss_eth_rx.h>
#include <nss_nlethrx_if.h>
static pthread_mutex_t eth_rx_lock;
static struct nssinfo_stats_info nss_eth_rx_cmn_stats_str[NSS_STATS_NODE_MAX];
static struct nssinfo_stats_info nss_eth_rx_stats_str[NSS_ETH_RX_STATS_MAX];
static struct nssinfo_stats_info nss_eth_rx_exception_stats_str[NSS_ETH_RX_EXCEPTION_EVENT_MAX];
/*
* nssinfo_eth_rx_stats_display()
* Ethernet Rx display callback function.
*/
static void nssinfo_eth_rx_stats_display(int core, char *input)
{
struct node *eth_rx_node;
if (input && strncmp(input, nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_ETHRX].subsystem_name, strlen(input))) {
++invalid_input;
nssinfo_trace("Invalid node name: %s\n", input);
return;
}
pthread_mutex_lock(&eth_rx_lock);
eth_rx_node = nodes[core][NSS_ETH_RX_INTERFACE];
if (!eth_rx_node) {
pthread_mutex_unlock(&eth_rx_lock);
return;
}
if (!display_all_stats) {
nssinfo_print_summary("eth_rx", (uint64_t *)eth_rx_node->cmn_node_stats, (uint64_t *)eth_rx_node->exception_stats, NSS_ETH_RX_EXCEPTION_EVENT_MAX);
pthread_mutex_unlock(&eth_rx_lock);
return;
}
nssinfo_print_all("eth_rx", "eth_rx Common Stats", nss_eth_rx_cmn_stats_str, NSS_STATS_NODE_MAX, (uint64_t *)eth_rx_node->cmn_node_stats);
nssinfo_print_all("eth_rx", "eth_rx Special Stats", nss_eth_rx_stats_str, NSS_ETH_RX_STATS_MAX, (uint64_t *)eth_rx_node->node_stats);
nssinfo_print_all("eth_rx", "eth_rx Exception Stats", nss_eth_rx_exception_stats_str, NSS_ETH_RX_EXCEPTION_EVENT_MAX, (uint64_t *)eth_rx_node->exception_stats);
pthread_mutex_unlock(&eth_rx_lock);
}
/*
* nssinfo_eth_rx_stats_notify()
* Ethernet Rx statistics notify callback function.
*/
static void nssinfo_eth_rx_stats_notify(void *data)
{
uint64_t *cmn_node_stats, *node_stats, *exception_stats;
struct nss_eth_rx_stats_notification *nss_stats = (struct nss_eth_rx_stats_notification *)data;
struct node *eth_rx_node;
struct node **eth_rx_ptr;
if (!nssinfo_coreid_ifnum_valid(nss_stats->core_id, NSS_ETH_RX_INTERFACE)) {
return;
}
pthread_mutex_lock(&eth_rx_lock);
eth_rx_ptr = &nodes[nss_stats->core_id][NSS_ETH_RX_INTERFACE];
eth_rx_node = *eth_rx_ptr;
if (eth_rx_node) {
memcpy(eth_rx_node->cmn_node_stats, &nss_stats->cmn_node_stats, sizeof(nss_stats->cmn_node_stats));
memcpy(eth_rx_node->node_stats, &nss_stats->special_stats, sizeof(nss_stats->special_stats));
memcpy(eth_rx_node->exception_stats, &nss_stats->exception_stats, sizeof(nss_stats->exception_stats));
pthread_mutex_unlock(&eth_rx_lock);
return;
}
pthread_mutex_unlock(&eth_rx_lock);
eth_rx_node = (struct node *)calloc(1, sizeof(struct node));
if (!eth_rx_node) {
nssinfo_warn("Failed to allocate memory for eth rx node\n");
return;
}
cmn_node_stats = (uint64_t *)malloc(sizeof(nss_stats->cmn_node_stats));
if (!cmn_node_stats) {
nssinfo_warn("Failed to allocate memory for eth rx common node statistics\n");
goto eth_rx_node_free;
}
node_stats = (uint64_t *)malloc(sizeof(nss_stats->special_stats));
if (!node_stats) {
nssinfo_warn("Failed to allocate memory for eth rx special stats\n");
goto cmn_node_stats_free;
}
exception_stats = (uint64_t *)malloc(sizeof(nss_stats->exception_stats));
if (!exception_stats) {
nssinfo_warn("Failed to allocate memory for eth rx exception stats\n");
goto node_stats_free;
}
memcpy(cmn_node_stats, &nss_stats->cmn_node_stats, sizeof(nss_stats->cmn_node_stats));
memcpy(node_stats, &nss_stats->special_stats, sizeof(nss_stats->special_stats));
memcpy(exception_stats, &nss_stats->exception_stats, sizeof(nss_stats->exception_stats));
eth_rx_node->cmn_node_stats = cmn_node_stats;
eth_rx_node->node_stats = node_stats;
eth_rx_node->exception_stats = exception_stats;
eth_rx_node->subsystem_id = NSS_NLCMN_SUBSYS_ETHRX;
/*
* Notifify is guaranteed to be single threaded via Netlink listen callback
*/
pthread_mutex_lock(&eth_rx_lock);
nodes[nss_stats->core_id][NSS_ETH_RX_INTERFACE] = eth_rx_node;
pthread_mutex_unlock(&eth_rx_lock);
return;
node_stats_free:
free(node_stats);
cmn_node_stats_free:
free(cmn_node_stats);
eth_rx_node_free:
free(eth_rx_node);
return;
}
/*
* nssinfo_eth_rx_destroy()
* Destroy ethernet Rx node.
*/
static void nssinfo_eth_rx_destroy(uint32_t core_id, uint32_t if_num)
{
if (nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_ETHRX].is_inited) {
nssinfo_node_stats_destroy(&eth_rx_lock, core_id, NSS_ETH_RX_INTERFACE);
}
}
/*
* nssinfo_ethrx_deinit()
* Deinitialize ethrx module.
*/
void nssinfo_eth_rx_deinit(void *data)
{
struct nss_nlmcast_ctx *ctx = (struct nss_nlmcast_ctx *)data;
if (nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_ETHRX].is_inited) {
pthread_mutex_destroy(&eth_rx_lock);
nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_ETHRX].is_inited = false;
}
nss_nlmcast_sock_leave_grp(ctx, NSS_NLETHRX_MCAST_GRP);
}
/*
* nssinfo_eth_rx_init()
* Initialize Ethernet Rx module.
*/
int nssinfo_eth_rx_init(void *data)
{
int error;
struct nss_nlmcast_ctx *ctx = (struct nss_nlmcast_ctx *)data;
/*
* Subscribe for Ethernet Rx MCAST group.
*/
nss_nlsock_set_family(&ctx->sock, NSS_NLETHRX_FAMILY);
error = nss_nlmcast_sock_join_grp(ctx, NSS_NLETHRX_MCAST_GRP);
if (error) {
nssinfo_warn("Unable to join Ethernet Rx mcast group.\n");
return error;
}
if (nssinfo_stats_info_init(nss_eth_rx_cmn_stats_str,
"/sys/kernel/debug/qca-nss-drv/strings/common_node_stats") != 0) {
goto fail;
}
if (nssinfo_stats_info_init(nss_eth_rx_stats_str,
"/sys/kernel/debug/qca-nss-drv/strings/eth_rx/special_stats_str") != 0) {
goto fail;
}
if (nssinfo_stats_info_init(nss_eth_rx_exception_stats_str,
"/sys/kernel/debug/qca-nss-drv/strings/eth_rx/exception_stats_str") != 0) {
goto fail;
}
if (pthread_mutex_init(&eth_rx_lock, NULL) != 0) {
nssinfo_warn("Mutex init has failed for Ethernet Rx\n");
goto fail;
}
nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_ETHRX].display = nssinfo_eth_rx_stats_display;
nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_ETHRX].notify = nssinfo_eth_rx_stats_notify;
nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_ETHRX].destroy = nssinfo_eth_rx_destroy;
nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_ETHRX].is_inited = true;
return 0;
fail:
nss_nlmcast_sock_leave_grp(ctx, NSS_NLETHRX_MCAST_GRP);
return -1;
}

View File

@ -1,28 +0,0 @@
/*
**************************************************************************
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all copies.
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**************************************************************************
*/
#ifndef __NSSINFO_ETHRX_H
#define __NSSINFO_ETHRX_H
/**
* @brief initialize Ethernet Rx module.
*
* @return 0 on success or -ve for failure
*/
int nssinfo_eth_rx_init(void *data);
void nssinfo_eth_rx_deinit(void *data);
#endif /* __NSSINFO_ETHRX_H*/

View File

@ -1,215 +0,0 @@
/*
**************************************************************************
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all copies.
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**************************************************************************
*/
/*
* @file NSSINFO ipv4 handler
*/
#include "nssinfo.h"
static pthread_mutex_t ipv4_lock;
static struct nssinfo_stats_info nss_stats_str_node[NSS_STATS_NODE_MAX];
static struct nssinfo_stats_info nss_ipv4_stats_str[NSS_IPV4_STATS_MAX];
static struct nssinfo_stats_info nss_ipv4_exception_stats_str[NSS_IPV4_EXCEPTION_EVENT_MAX];
/*
* nssinfo_ipv4_stats_display()
* IPv4 display callback function.
*/
static void nssinfo_ipv4_stats_display(int core, char *input)
{
struct node *ipv4_node;
if (input && strncmp(input, nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_IPV4].subsystem_name, strlen(input)) != 0) {
++invalid_input;
nssinfo_trace("Invalid node name: %s\n", input);
return;
}
pthread_mutex_lock(&ipv4_lock);
ipv4_node = nodes[core][NSS_IPV4_RX_INTERFACE];
if (!ipv4_node) {
pthread_mutex_unlock(&ipv4_lock);
return;
}
if (!display_all_stats) {
nssinfo_print_summary("ipv4", (uint64_t *)ipv4_node->cmn_node_stats, (uint64_t *)ipv4_node->exception_stats, NSS_IPV4_EXCEPTION_EVENT_MAX);
pthread_mutex_unlock(&ipv4_lock);
return;
}
nssinfo_print_all("ipv4", "ipv4 Common Stats", nss_stats_str_node, NSS_STATS_NODE_MAX, (uint64_t *)ipv4_node->cmn_node_stats);
nssinfo_print_all("ipv4", "ipv4 Special Stats", nss_ipv4_stats_str, NSS_IPV4_STATS_MAX, (uint64_t *)ipv4_node->node_stats);
nssinfo_print_all("ipv4", "ipv4 Exception Stats", nss_ipv4_exception_stats_str, NSS_IPV4_EXCEPTION_EVENT_MAX, (uint64_t *)ipv4_node->exception_stats);
pthread_mutex_unlock(&ipv4_lock);
}
/*
* nssinfo_ipv4_stats_notify()
* IPv4 stats notify callback function.
*/
static void nssinfo_ipv4_stats_notify(void *data)
{
uint64_t *cmn_node_stats, *node_stats, *exception_stats;
struct nss_nlipv4_rule *rule = (struct nss_nlipv4_rule *)data;
struct node *ipv4_node;
struct node **ipv4_ptr;
if (!nssinfo_coreid_ifnum_valid(rule->stats.core_id, NSS_IPV4_RX_INTERFACE)) {
return;
}
ipv4_ptr = &nodes[rule->stats.core_id][NSS_IPV4_RX_INTERFACE];
pthread_mutex_lock(&ipv4_lock);
ipv4_node = *ipv4_ptr;
if (ipv4_node) {
memcpy(ipv4_node->cmn_node_stats, &rule->stats.cmn_node_stats, sizeof(rule->stats.cmn_node_stats));
memcpy(ipv4_node->node_stats, &rule->stats.special_stats, sizeof(rule->stats.special_stats));
memcpy(ipv4_node->exception_stats, &rule->stats.exception_stats, sizeof(rule->stats.exception_stats));
pthread_mutex_unlock(&ipv4_lock);
return;
}
pthread_mutex_unlock(&ipv4_lock);
ipv4_node = (struct node *)calloc(1, sizeof(struct node));
if (!ipv4_node) {
nssinfo_warn("Failed to allocate memory for ipv4 node\n");
return;
}
cmn_node_stats = (uint64_t *)malloc(sizeof(rule->stats.cmn_node_stats));
if (!cmn_node_stats) {
nssinfo_warn("Failed to allocate memory for ipv4 common node stats\n");
goto ipv4_node_free;
}
node_stats = (uint64_t *)malloc(sizeof(rule->stats.special_stats));
if (!node_stats) {
nssinfo_warn("Failed to allocate memory for ipv4 special stats\n");
goto cmn_node_stats_free;
}
exception_stats = (uint64_t *)malloc(sizeof(rule->stats.exception_stats));
if (!exception_stats) {
nssinfo_warn("Failed to allocate memory for ipv4 exception stats\n");
goto node_stats_free;
}
memcpy(cmn_node_stats, &rule->stats.cmn_node_stats, sizeof(rule->stats.cmn_node_stats));
memcpy(node_stats, &rule->stats.special_stats, sizeof(rule->stats.special_stats));
memcpy(exception_stats, &rule->stats.exception_stats, sizeof(rule->stats.exception_stats));
ipv4_node->cmn_node_stats = cmn_node_stats;
ipv4_node->node_stats = node_stats;
ipv4_node->exception_stats = exception_stats;
ipv4_node->subsystem_id = NSS_NLCMN_SUBSYS_IPV4;
/*
* Notifify is guaranteed to be single threaded via Netlink listen callback
*/
pthread_mutex_lock(&ipv4_lock);
*ipv4_ptr = ipv4_node;
pthread_mutex_unlock(&ipv4_lock);
return;
node_stats_free:
free(node_stats);
cmn_node_stats_free:
free(cmn_node_stats);
ipv4_node_free:
free(ipv4_node);
}
/*
* nssinfo_ipv4_destroy()
* Destroy IPv4 node.
*/
static void nssinfo_ipv4_destroy(uint32_t core_id, uint32_t if_num)
{
if (nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_IPV4].is_inited) {
nssinfo_node_stats_destroy(&ipv4_lock, core_id, NSS_IPV4_RX_INTERFACE);
}
}
/*
* nssinfo_ipv4_deinit()
* Initialize IPv4 module.
*/
void nssinfo_ipv4_deinit(void *data)
{
struct nss_nlmcast_ctx *ctx = (struct nss_nlmcast_ctx *)data;
if (nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_IPV4].is_inited) {
pthread_mutex_destroy(&ipv4_lock);
nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_IPV4].is_inited = false;
}
nss_nlmcast_sock_leave_grp(ctx, NSS_NLIPV4_MCAST_GRP);
}
/*
* nssinfo_ipv4_init()
* Initialize IPv4 module.
*/
int nssinfo_ipv4_init(void *data)
{
int error;
struct nss_nlmcast_ctx *ctx = (struct nss_nlmcast_ctx *)data;
/*
* Subscribe for IPV4 MCAST group.
*/
nss_nlsock_set_family(&ctx->sock, NSS_NLIPV4_FAMILY);
error = nss_nlmcast_sock_join_grp(ctx, NSS_NLIPV4_MCAST_GRP);
if (error) {
nssinfo_warn("Unable to join IPv4 mcast group\n");
return error;
}
if (nssinfo_stats_info_init(nss_stats_str_node,
"/sys/kernel/debug/qca-nss-drv/strings/common_node_stats") != 0) {
goto fail;
}
if (nssinfo_stats_info_init(nss_ipv4_stats_str,
"/sys/kernel/debug/qca-nss-drv/strings/ipv4/special_stats_str") != 0) {
goto fail;
}
if (nssinfo_stats_info_init(nss_ipv4_exception_stats_str,
"/sys/kernel/debug/qca-nss-drv/strings/ipv4/exception_stats_str") != 0) {
goto fail;
}
if (pthread_mutex_init(&ipv4_lock, NULL) != 0) {
nssinfo_warn("Mutex init has failed for IPV4\n");
goto fail;
}
nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_IPV4].display = nssinfo_ipv4_stats_display;
nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_IPV4].notify = nssinfo_ipv4_stats_notify;
nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_IPV4].destroy = nssinfo_ipv4_destroy;
nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_IPV4].is_inited = true;
return 0;
fail:
nss_nlmcast_sock_leave_grp(ctx, NSS_NLIPV4_MCAST_GRP);
return -1;
}

View File

@ -1,30 +0,0 @@
/*
**************************************************************************
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all copies.
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**************************************************************************
*/
#ifndef __NSSINFO_IPV4_H
#define __NSSINFO_IPV4_H
#define NSSINFO_IPV4_HDR_VERSION 4
/**
* @brief initialize IPv4 module.
*
* @return 0 on success or -ve for failure
*/
int nssinfo_ipv4_init(void *data);
void nssinfo_ipv4_deinit(void *data);
#endif /* __NSSINFO_IPV4_H*/

View File

@ -1,212 +0,0 @@
/*
**************************************************************************
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all copies.
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**************************************************************************
*/
/*
* @file NSSINFO ipv6 handler
*/
#include "nssinfo.h"
static pthread_mutex_t ipv6_lock;
static struct nssinfo_stats_info nss_stats_str_node[NSS_STATS_NODE_MAX];
static struct nssinfo_stats_info nss_ipv6_stats_str[NSS_IPV6_STATS_MAX];
static struct nssinfo_stats_info nss_ipv6_exception_stats_str[NSS_IPV6_EXCEPTION_EVENT_MAX];
/*
* nssinfo_ipv6_stats_display()
* IPv6 display callback function.
*/
static void nssinfo_ipv6_stats_display(int core, char *input)
{
struct node *ipv6_node;
if (input && strncmp(input, nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_IPV6].subsystem_name, strlen(input))) {
++invalid_input;
nssinfo_trace("Invalid node name: %s\n", input);
return;
}
pthread_mutex_lock(&ipv6_lock);
ipv6_node = nodes[core][NSS_IPV6_RX_INTERFACE];
if (!ipv6_node) {
pthread_mutex_unlock(&ipv6_lock);
return;
}
if (display_all_stats) {
nssinfo_print_all("ipv6", "ipv6 Common Stats", nss_stats_str_node, NSS_STATS_NODE_MAX, (uint64_t *)ipv6_node->cmn_node_stats);
nssinfo_print_all("ipv6", "ipv6 Special Stats", nss_ipv6_stats_str, NSS_IPV6_STATS_MAX, (uint64_t *)ipv6_node->node_stats);
nssinfo_print_all("ipv6", "ipv6 Exception Stats", nss_ipv6_exception_stats_str, NSS_IPV6_EXCEPTION_EVENT_MAX, (uint64_t *)ipv6_node->exception_stats);
pthread_mutex_unlock(&ipv6_lock);
return;
}
nssinfo_print_summary("ipv6", (uint64_t *)ipv6_node->cmn_node_stats, (uint64_t *)ipv6_node->exception_stats, NSS_IPV6_EXCEPTION_EVENT_MAX);
pthread_mutex_unlock(&ipv6_lock);
}
/*
* nssinfo_ipv6_stats_notify()
* IPv6 stats notify callback function.
*/
static void nssinfo_ipv6_stats_notify(void *data)
{
uint64_t *cmn_node_stats, *node_stats, *exception_stats;
struct nss_nlipv6_rule *rule = (struct nss_nlipv6_rule *)data;
struct node *ipv6_node;
struct node **ipv6_ptr;
if (!nssinfo_coreid_ifnum_valid(rule->stats.core_id, NSS_IPV6_RX_INTERFACE)) {
return;
}
pthread_mutex_lock(&ipv6_lock);
ipv6_ptr = &nodes[rule->stats.core_id][NSS_IPV6_RX_INTERFACE];
ipv6_node = *ipv6_ptr;
if (ipv6_node) {
memcpy(ipv6_node->cmn_node_stats, &rule->stats.cmn_node_stats, sizeof(rule->stats.cmn_node_stats));
memcpy(ipv6_node->node_stats, &rule->stats.special_stats, sizeof(rule->stats.special_stats));
memcpy(ipv6_node->exception_stats, &rule->stats.exception_stats, sizeof(rule->stats.exception_stats));
pthread_mutex_unlock(&ipv6_lock);
return;
}
pthread_mutex_unlock(&ipv6_lock);
ipv6_node = (struct node *)calloc(1, sizeof(struct node));
if (!ipv6_node) {
nssinfo_warn("Failed to allocate memory for ipv6 node\n");
return;
}
cmn_node_stats = (uint64_t *)malloc(sizeof(rule->stats.cmn_node_stats));
if (!cmn_node_stats) {
nssinfo_warn("Failed to allocate memory for ipv6 common node statistics\n");
goto ipv6_node_free;
}
node_stats = (uint64_t *)malloc(sizeof(rule->stats.special_stats));
if (!node_stats) {
nssinfo_warn("Failed to allocate memory for ipv6 special stats\n");
goto cmn_node_stats_free;
}
exception_stats = (uint64_t *)malloc(sizeof(rule->stats.exception_stats));
if (!exception_stats) {
nssinfo_warn("Failed to allocate memory for ipv6 exception stats\n");
goto node_stats_free;
}
memcpy(cmn_node_stats, &rule->stats.cmn_node_stats, sizeof(rule->stats.cmn_node_stats));
memcpy(node_stats, &rule->stats.special_stats, sizeof(rule->stats.special_stats));
memcpy(exception_stats, &rule->stats.exception_stats, sizeof(rule->stats.exception_stats));
ipv6_node->cmn_node_stats = cmn_node_stats;
ipv6_node->node_stats = node_stats;
ipv6_node->exception_stats = exception_stats;
ipv6_node->subsystem_id = NSS_NLCMN_SUBSYS_IPV6;
/*
* Notifify is guaranteed to be single threaded via Netlink listen callback
*/
pthread_mutex_lock(&ipv6_lock);
*ipv6_ptr = ipv6_node;
pthread_mutex_unlock(&ipv6_lock);
return;
node_stats_free:
free(node_stats);
cmn_node_stats_free:
free(cmn_node_stats);
ipv6_node_free:
free(ipv6_node);
}
/*
* nssinfo_ipv6_destroy()
* Destroy IPv6 node.
*/
static void nssinfo_ipv6_destroy(uint32_t core_id, uint32_t if_num)
{
if (nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_IPV6].is_inited) {
nssinfo_node_stats_destroy(&ipv6_lock, core_id, NSS_IPV6_RX_INTERFACE);
}
}
/*
* nssinfo_ipv6_deinit()
* Deinitialize ipv6 module.
*/
void nssinfo_ipv6_deinit(void *data)
{
struct nss_nlmcast_ctx *ctx = (struct nss_nlmcast_ctx *)data;
if (nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_IPV6].is_inited) {
pthread_mutex_destroy(&ipv6_lock);
nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_IPV6].is_inited = false;
}
nss_nlmcast_sock_leave_grp(ctx, NSS_NLIPV6_MCAST_GRP);
}
/*
* nssinfo_ipv6_init()
* Initialize IPv6 module.
*/
int nssinfo_ipv6_init(void *data)
{
int error;
struct nss_nlmcast_ctx *ctx = (struct nss_nlmcast_ctx *)data;
/*
* Subscribe for IPV6 MCAST group.
*/
nss_nlsock_set_family(&ctx->sock, NSS_NLIPV6_FAMILY);
error = nss_nlmcast_sock_join_grp(ctx, NSS_NLIPV6_MCAST_GRP);
if (error) {
nssinfo_warn("Unable to join IPv6 mcast group\n");
return error;
}
if (nssinfo_stats_info_init(nss_stats_str_node,
"/sys/kernel/debug/qca-nss-drv/strings/common_node_stats") != 0) {
goto fail;
}
if (nssinfo_stats_info_init(nss_ipv6_stats_str,
"/sys/kernel/debug/qca-nss-drv/strings/ipv6/special_stats_str") != 0) {
goto fail;
}
if (nssinfo_stats_info_init(nss_ipv6_exception_stats_str,
"/sys/kernel/debug/qca-nss-drv/strings/ipv6/exception_stats_str") != 0) {
goto fail;
}
if (pthread_mutex_init(&ipv6_lock, NULL) != 0) {
nssinfo_warn("Mutex init has failed for IPV6\n");
goto fail;
}
nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_IPV6].display = nssinfo_ipv6_stats_display;
nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_IPV6].notify = nssinfo_ipv6_stats_notify;
nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_IPV6].destroy = nssinfo_ipv6_destroy;
nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_IPV6].is_inited = true;
return 0;
fail:
nss_nlmcast_sock_leave_grp(ctx, NSS_NLIPV6_MCAST_GRP);
return -1;
}

View File

@ -1,30 +0,0 @@
/*
**************************************************************************
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all copies.
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**************************************************************************
*/
#ifndef __NSSINFO_IPV6_H
#define __NSSINFO_IPV6_H
#define NSSINFO_IPV6_HDR_VERSION 4
/**
* @brief initialize IPv4 module.
*
* @return 0 on success or -ve for failure
*/
int nssinfo_ipv6_init(void *data);
void nssinfo_ipv6_deinit(void *data);
#endif /* __NSSINFO_IPV6_H*/

View File

@ -1,195 +0,0 @@
/*
**************************************************************************
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all copies.
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**************************************************************************
*/
/*
* @file NSSINFO lso_rx handler
*/
#include "nssinfo.h"
#include <nss_lso_rx.h>
#include <nss_nllso_rx_if.h>
static pthread_mutex_t lso_rx_lock;
static struct nssinfo_stats_info nss_stats_str_node[NSS_STATS_NODE_MAX];
static struct nssinfo_stats_info nss_lso_rx_stats_str[NSS_LSO_RX_STATS_MAX];
/*
* nssinfo_lso_rx_stats_display()
* LSO Rx display callback function.
*/
static void nssinfo_lso_rx_stats_display(int core, char *input)
{
struct node *lso_rx_node;
if (input && strncmp(input, nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_LSO_RX].subsystem_name, strlen(input))) {
++invalid_input;
nssinfo_trace("Invalid node name: %s\n", input);
return;
}
pthread_mutex_lock(&lso_rx_lock);
lso_rx_node = nodes[core][NSS_LSO_RX_INTERFACE];
if (!lso_rx_node) {
pthread_mutex_unlock(&lso_rx_lock);
nssinfo_error("%s is not running on the NPU\n", input);
return;
}
if (display_all_stats) {
nssinfo_print_all("lso_rx", "lso_rx Common Stats", nss_stats_str_node, NSS_STATS_NODE_MAX, (uint64_t *)lso_rx_node->cmn_node_stats);
nssinfo_print_all("lso_rx", "lso_rx Special Stats", nss_lso_rx_stats_str, NSS_LSO_RX_STATS_MAX, (uint64_t *)lso_rx_node->node_stats);
pthread_mutex_unlock(&lso_rx_lock);
return;
}
nssinfo_print_summary("lso_rx", (uint64_t *)lso_rx_node->cmn_node_stats, NULL, 0);
pthread_mutex_unlock(&lso_rx_lock);
}
/*
* nssinfo_lso_rx_stats_notify()
* LSO Rx stats notify callback function.
*/
static void nssinfo_lso_rx_stats_notify(void *data)
{
uint64_t *cmn_node_stats, *node_stats;
struct nss_lso_rx_stats_notification *nss_stats = (struct nss_lso_rx_stats_notification *)data;
struct node *lso_rx_node;
struct node **lso_rx_ptr;
if (!nssinfo_coreid_ifnum_valid(nss_stats->core_id, NSS_LSO_RX_INTERFACE)) {
return;
}
pthread_mutex_lock(&lso_rx_lock);
lso_rx_ptr = &nodes[nss_stats->core_id][NSS_LSO_RX_INTERFACE];
lso_rx_node = *lso_rx_ptr;
if (lso_rx_node) {
memcpy(lso_rx_node->cmn_node_stats, &nss_stats->cmn_node_stats, sizeof(nss_stats->cmn_node_stats));
memcpy(lso_rx_node->node_stats, &nss_stats->node_stats, sizeof(nss_stats->node_stats));
pthread_mutex_unlock(&lso_rx_lock);
return;
}
pthread_mutex_unlock(&lso_rx_lock);
lso_rx_node = (struct node *)calloc(1, sizeof(struct node));
if (!lso_rx_node) {
nssinfo_warn("Failed to allocate memory for lso_rx node\n");
return;
}
cmn_node_stats = (uint64_t *)malloc(sizeof(nss_stats->cmn_node_stats));
if (!cmn_node_stats) {
nssinfo_warn("Failed to allocate memory for lso_rx common node statistics\n");
goto lso_rx_node_free;
}
node_stats = (uint64_t *)malloc(sizeof(nss_stats->node_stats));
if (!node_stats) {
nssinfo_warn("Failed to allocate memory for lso_rx connection stats\n");
goto cmn_node_stats_free;
}
memcpy(cmn_node_stats, &nss_stats->cmn_node_stats, sizeof(nss_stats->cmn_node_stats));
memcpy(node_stats, &nss_stats->node_stats, sizeof(nss_stats->node_stats));
lso_rx_node->cmn_node_stats = cmn_node_stats;
lso_rx_node->node_stats = node_stats;
lso_rx_node->subsystem_id = NSS_NLCMN_SUBSYS_LSO_RX;
/*
* Notify is guaranteed to be single threaded via Netlink listen callback
*/
pthread_mutex_lock(&lso_rx_lock);
*lso_rx_ptr = lso_rx_node;
pthread_mutex_unlock(&lso_rx_lock);
return;
cmn_node_stats_free:
free(cmn_node_stats);
lso_rx_node_free:
free(lso_rx_node);
}
/*
* nssinfo_lso_rx_destroy()
* Destroy LSO Rx node.
*/
static void nssinfo_lso_rx_destroy(uint32_t core_id, uint32_t if_num)
{
if (nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_LSO_RX].is_inited) {
nssinfo_node_stats_destroy(&lso_rx_lock, core_id, NSS_LSO_RX_INTERFACE);
}
}
/*
* nssinfo_lso_rx_deinit()
* Deinitialize lso_rx module.
*/
void nssinfo_lso_rx_deinit(void *data)
{
struct nss_nlmcast_ctx *ctx = (struct nss_nlmcast_ctx *)data;
if (nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_LSO_RX].is_inited) {
pthread_mutex_destroy(&lso_rx_lock);
nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_LSO_RX].is_inited = false;
}
nss_nlmcast_sock_leave_grp(ctx, NSS_NLLSO_RX_MCAST_GRP);
}
/*
* nssinfo_lso_rx_init()
* Initialize LSO Rx module.
*/
int nssinfo_lso_rx_init(void *data)
{
int error;
struct nss_nlmcast_ctx *ctx = (struct nss_nlmcast_ctx *)data;
/*
* Subscribe for LSO Rx multicast group.
*/
nss_nlsock_set_family(&ctx->sock, NSS_NLLSO_RX_FAMILY);
error = nss_nlmcast_sock_join_grp(ctx, NSS_NLLSO_RX_MCAST_GRP);
if (error) {
nssinfo_warn("Unable to join LSO Rx multicast group\n");
return error;
}
if (nssinfo_stats_info_init(nss_stats_str_node,
"/sys/kernel/debug/qca-nss-drv/strings/common_node_stats") != 0) {
goto fail;
}
if (nssinfo_stats_info_init(nss_lso_rx_stats_str,
"/sys/kernel/debug/qca-nss-drv/strings/lso_rx") != 0) {
goto fail;
}
if (pthread_mutex_init(&lso_rx_lock, NULL) != 0) {
nssinfo_warn("Mutex init has failed for LSO Rx\n");
goto fail;
}
nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_LSO_RX].display = nssinfo_lso_rx_stats_display;
nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_LSO_RX].notify = nssinfo_lso_rx_stats_notify;
nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_LSO_RX].destroy = nssinfo_lso_rx_destroy;
nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_LSO_RX].is_inited = true;
return 0;
fail:
nss_nlmcast_sock_leave_grp(ctx, NSS_NLLSO_RX_MCAST_GRP);
return -1;
}

View File

@ -1,28 +0,0 @@
/*
**************************************************************************
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all copies.
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**************************************************************************
*/
#ifndef __NSSINFO_LSO_RX_H
#define __NSSINFO_LSO_RX_H
/**
* @brief initialize LSO_RX module.
*
* @return 0 on success or -ve for failure
*/
int nssinfo_lso_rx_init(void *data);
void nssinfo_lso_rx_deinit(void *data);
#endif /* __NSSINFO_LSO_RX_H*/

View File

@ -1,191 +0,0 @@
/*
**************************************************************************
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all copies.
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**************************************************************************
*/
#include "nssinfo.h"
#include <getopt.h>
static const char *nssinfo_version = "1.0";
static struct option long_options[] = {
{"verbose", no_argument, NULL, 'v'},
{"higherunit", no_argument, NULL, 'u'},
{"help", no_argument, NULL, 'h'},
{"version", no_argument, NULL, 'V'},
{"output", required_argument, NULL, 'o'},
{"flowfile", required_argument, NULL, 'f'},
{"core", required_argument, NULL, 'c'},
{"rate", required_argument, NULL, 'r'},
{0, 0, 0, 0}
};
static char *short_options = "vuh?Vo:f:c:r:";
static void print_help(void)
{
printf("nssinfo is an userspace tool used to display NODE stats from NSS-FW\n");
printf("Usage: nssinfo [OPTION ...] [-c ID [NODE1 NODE2 ...]]\n");
printf("OPTION:\n");
printf(" -c, --core=ID Display statistics based on core id\n");
printf(" -f, --flowfile=FILE Specify output content in FILE\n");
printf(" -o, --output=FILE Write output to FILE instead of stdout\n");
printf(" -r, --rate=RATE Update screen every RATE seconds\n");
printf(" -u, --higherunit Display stats in higher units, i.e. K, M, B\n");
printf(" -v, --verbose Display all the stats (zero and non-zero stats)\n");
printf(" -V, --version Print program version\n");
printf(" -h, --help Give this help message\n");
printf("Examples:\n");
printf(" nssinfo\n");
printf(" nssinfo -c0\n");
printf(" nssinfo -c0 ipv4 edma[0] edma[4]\n");
printf(" nssinfo -r5 -o stats.log\n");
}
struct arguments arguments;
/*
* getopt_parse()
* Parse command line arguments using getopt_long().
*/
static int getopt_parse(int argc, char **argv, void *a)
{
struct arguments *arguments = (struct arguments *)a;
while (1) {
int key = getopt_long(argc, argv, short_options, long_options, NULL);
/*
* Detect the end of the options.
*/
if (key == -1)
break;
switch (key) {
case 'v':
arguments->verbose = true;
break;
case 'u':
arguments->higher_unit = true;
break;
case 'f':
arguments->flow_file = optarg;
break;
case 'o':
arguments->output_file = optarg;
break;
case 'r': /* -r5 */
arguments->rate = atoi(optarg);
if (arguments->rate <= 0) {
printf("Invalid rate `%s'\n", optarg);
exit(-1);
}
break;
case 'c': /* -c0 */
arguments->core = atoi(optarg);
if (arguments->core >= NSS_MAX_CORES || arguments->core < 0) {
printf("Invalid core id `%s'\n", optarg);
exit(-1);
}
break;
case 'h':
print_help();
exit(0);
case 'V':
printf("%s\n", nssinfo_version);
exit(0);
case '?':
default:
/*
* getopt_long already printed an error message.
*/
exit(-1);
}
}
/* Any remaining non-option arguments start from argv[optind].
* Init arguments->strings so that
* arguments->strings[0] points to the 1st non-option argument
* arguments->strings[1] points to the 2nd non-option argument
* ...
* arguments->strings[n] points to the last non-option argument
* arguments->strings[n+1] is NULL
*
* For example,
* If user enters 'nssinfo -c1 edma1 edma2', optind is 2 at this point and
* arguments->strings[0] = "edma1", arguments->strings[1] = "edma2", arguments->strings[2] = NULL.
* If user does not specify any non-option argument (e.g. nssinfo -v),
* argv[optind] is NULL so arguments->strings[0] is NULL.
*/
arguments->strings = &argv[optind];
return 0;
}
/*
* main()
*/
int main(int argc, char **argv)
{
int error;
arguments.output_file = NULL;
arguments.flow_file = NULL;
arguments.verbose = false;
arguments.higher_unit = false;
arguments.core = -1; /* display stats for all cores */
arguments.rate = 1; /* 1 sec */
getopt_parse(argc, argv, &arguments);
if (arguments.output_file) {
output_file = fopen(arguments.output_file, "w");
if (!output_file) {
nssinfo_error("Error opening output file!\n");
exit(1);
}
}
if (arguments.flow_file) {
flow_file = fopen(arguments.flow_file, "r");
if (!flow_file) {
nssinfo_error("Error opening flow file!\n");
error = -1;
goto end;
}
}
error = nssinfo_init();
if (error) {
nssinfo_info("Nssinfo initialization failed(%d)\n", error);
}
if (flow_file) {
fclose(flow_file);
}
end:
if (output_file) {
fclose(output_file);
}
return error;
}

View File

@ -1,209 +0,0 @@
/*
**************************************************************************
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all copies.
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**************************************************************************
*/
/*
* @file NSSINFO n2h handler
*/
#include "nssinfo.h"
#include <nss_n2h.h>
#include <nss_nln2h_if.h>
static pthread_mutex_t n2h_lock;
static uint64_t drv_stats[NSS_STATS_DRV_MAX];
static struct nssinfo_stats_info nssinfo_n2h_stats_str[NSS_N2H_STATS_MAX];
/*
* nssinfo_n2h_stats_display()
* N2H display callback function.
*/
static void nssinfo_n2h_stats_display(int core, char *input)
{
struct node *n2h_node;
char str_rx[NSSINFO_STR_LEN], str_tx[NSSINFO_STR_LEN];
if (input && strncmp(input, nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_N2H].subsystem_name, strlen(input))) {
++invalid_input;
nssinfo_trace("Invalid node name: %s\n", input);
return;
}
pthread_mutex_lock(&n2h_lock);
n2h_node = nodes[core][NSS_N2H_INTERFACE];
if (!n2h_node) {
pthread_mutex_unlock(&n2h_lock);
return;
}
if (display_all_stats) {
nssinfo_print_all("n2h", "n2h Stats", nssinfo_n2h_stats_str, NSS_N2H_STATS_MAX, (uint64_t *)n2h_node->node_stats);
pthread_mutex_unlock(&n2h_lock);
return;
}
nssinfo_print_summary("n2h", (uint64_t *)n2h_node->node_stats, NULL, 0);
if (core == (NSS_MAX_CORES - 1)) {
char *format_stats = nssinfo_format_stats(drv_stats[NSS_STATS_DRV_RX_CMD_RESP]);
strlcpy(str_rx, format_stats, sizeof(str_rx));
format_stats = nssinfo_format_stats(drv_stats[NSS_STATS_DRV_TX_CMD_REQ]);
strlcpy(str_tx, format_stats, sizeof(str_tx));
nssinfo_stats_print(nssinfo_summary_fmt, " buf_cmd", str_rx, str_tx, "", "");
memset(str_rx, 0, sizeof(str_rx));
memset(str_tx, 0, sizeof(str_tx));
format_stats = nssinfo_format_stats(drv_stats[NSS_STATS_DRV_RX_EMPTY]);
strlcpy(str_rx, format_stats, sizeof(str_rx));
format_stats = nssinfo_format_stats(drv_stats[NSS_STATS_DRV_TX_EMPTY]);
strlcpy(str_tx, format_stats, sizeof(str_tx));
nssinfo_stats_print(nssinfo_summary_fmt, " buf_emty", str_rx, str_tx, "", "");
memset(str_rx, 0, sizeof(str_rx));
memset(str_tx, 0, sizeof(str_tx));
format_stats = nssinfo_format_stats(drv_stats[NSS_STATS_DRV_RX_PACKET]);
strlcpy(str_rx, format_stats, sizeof(str_rx));
format_stats = nssinfo_format_stats(drv_stats[NSS_STATS_DRV_TX_PACKET]);
strlcpy(str_tx, format_stats, sizeof(str_tx));
nssinfo_stats_print(nssinfo_summary_fmt, " buf_pkt", str_rx, str_tx, "", "");
memset(str_rx, 0, sizeof(str_rx));
format_stats = nssinfo_format_stats(drv_stats[NSS_STATS_DRV_RX_STATUS]);
strlcpy(str_rx, format_stats, sizeof(str_rx));
nssinfo_stats_print(nssinfo_summary_fmt, " status_sync", str_rx, "", "", "");
}
pthread_mutex_unlock(&n2h_lock);
}
/*
* nssinfo_n2h_stats_notify()
* N2H stats notify callback function.
*/
static void nssinfo_n2h_stats_notify(void *data)
{
uint64_t *node_stats;
struct nss_n2h_stats_notification *nss_stats = (struct nss_n2h_stats_notification *)data;
struct node *n2h_node;
struct node **n2h_ptr;
if (!nssinfo_coreid_ifnum_valid(nss_stats->core_id, NSS_N2H_INTERFACE)) {
return;
}
pthread_mutex_lock(&n2h_lock);
n2h_ptr = &nodes[nss_stats->core_id][NSS_N2H_INTERFACE];
n2h_node = *n2h_ptr;
if (n2h_node) {
memcpy(n2h_node->node_stats, &nss_stats->n2h_stats, sizeof(nss_stats->n2h_stats));
memcpy(drv_stats, &nss_stats->drv_stats, sizeof(nss_stats->drv_stats));
pthread_mutex_unlock(&n2h_lock);
return;
}
pthread_mutex_unlock(&n2h_lock);
n2h_node = (struct node *)calloc(1, sizeof(struct node));
if (!n2h_node) {
nssinfo_warn("Failed to allocate memory for N2H node\n");
return;
}
node_stats = (uint64_t *)malloc(sizeof(nss_stats->n2h_stats));
if (!node_stats) {
nssinfo_warn("Failed to allocate memory for n2h node stats\n");
goto n2h_node_free;
}
memcpy(node_stats, &nss_stats->n2h_stats, sizeof(nss_stats->n2h_stats));
memcpy(drv_stats, &nss_stats->drv_stats, sizeof(nss_stats->drv_stats));
n2h_node->node_stats = node_stats;
n2h_node->subsystem_id = NSS_NLCMN_SUBSYS_N2H;
/*
* Notify is guaranteed to be single threaded via Netlink listen callback
*/
pthread_mutex_lock(&n2h_lock);
*n2h_ptr = n2h_node;
pthread_mutex_unlock(&n2h_lock);
return;
n2h_node_free:
free(n2h_node);
}
/*
* nssinfo_n2h_destroy()
* Destroy N2H node.
*/
static void nssinfo_n2h_destroy(uint32_t core_id, uint32_t if_num)
{
if (nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_N2H].is_inited) {
nssinfo_node_stats_destroy(&n2h_lock, core_id, NSS_N2H_INTERFACE);
}
}
/*
* nssinfo_n2h_deinit()
* Deinitialize n2h module.
*/
void nssinfo_n2h_deinit(void *data)
{
struct nss_nlmcast_ctx *ctx = (struct nss_nlmcast_ctx *)data;
if (nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_N2H].is_inited) {
pthread_mutex_destroy(&n2h_lock);
nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_N2H].is_inited = false;
}
nss_nlmcast_sock_leave_grp(ctx, NSS_NLN2H_MCAST_GRP);
}
/*
* nssinfo_n2h_init()
* Initialize N2H module.
*/
int nssinfo_n2h_init(void *data)
{
int error;
struct nss_nlmcast_ctx *ctx = (struct nss_nlmcast_ctx *)data;
/*
* Subscribe for N2H MCAST group.
*/
nss_nlsock_set_family(&ctx->sock, NSS_NLN2H_FAMILY);
error = nss_nlmcast_sock_join_grp(ctx, NSS_NLN2H_MCAST_GRP);
if (error) {
nssinfo_warn("Unable to join N2H mcast group.\n");
return error;
}
if (nssinfo_stats_info_init(nssinfo_n2h_stats_str,
"/sys/kernel/debug/qca-nss-drv/strings/n2h") != 0) {
goto fail;
}
if (pthread_mutex_init(&n2h_lock, NULL) != 0) {
nssinfo_warn("Mutex init has failed for n2h\n");
goto fail;
}
nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_N2H].display = nssinfo_n2h_stats_display;
nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_N2H].notify = nssinfo_n2h_stats_notify;
nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_N2H].destroy = nssinfo_n2h_destroy;
nssinfo_subsystem_array[NSS_NLCMN_SUBSYS_N2H].is_inited = true;
return 0;
fail:
nss_nlmcast_sock_leave_grp(ctx, NSS_NLN2H_MCAST_GRP);
return -1;
}

View File

@ -1,28 +0,0 @@
/*
**************************************************************************
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all copies.
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**************************************************************************
*/
#ifndef __NSSINFO_N2H_H
#define __NSSINFO_N2H_H
/**
* @brief initialize N2H module.
*
* @return 0 on success or -ve for failure
*/
int nssinfo_n2h_init(void *data);
void nssinfo_n2h_deinit(void *data);
#endif /* __NSSINFO_N2H_H*/

View File

@ -0,0 +1,28 @@
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,24 @@
+# Define the build directories based on flags
+DIRS-y :=
+DIRS-$(BUILD_LIBNSS) += lib
+DIRS-$(BUILD_NSSINFO) += nssinfo
+DIRS-$(BUILD_NETFN) += netfn
+DIRS-$(BUILD_LIBPPE) += ppe/ppenl_lib
+DIRS-$(BUILD_PPECFG) += ppe/ppecfg
+
+# Main targets
+all: $(DIRS-y)
+ @echo "Build complete"
+
+# Pattern rule to build each directory
+$(DIRS-y):
+ $(MAKE) -C $@
+
+clean:
+ @for dir in $(DIRS-y); do \
+ if [ -d $$dir ]; then \
+ $(MAKE) -C $$dir clean; \
+ fi \
+ done
+
+.PHONY: all clean $(DIRS-y)
\ No newline at end of file

View File

@ -0,0 +1,24 @@
--- a/lib/nss_nludp_st_api.c
+++ b/lib/nss_nludp_st_api.c
@@ -1,12 +1,9 @@
/*
**************************************************************************
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
- *
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all copies.
- *
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
@@ -52,8 +49,6 @@ int nss_nludp_st_sock_cb(struct nl_msg *
case NSS_UDP_ST_STOP_MSG:
case NSS_UDP_ST_TX_CREATE_MSG:
case NSS_UDP_ST_TX_DESTROY_MSG:
- case NSS_UDP_ST_TX_UPDATE_RATE_MSG:
- case NSS_UDP_ST_RX_MODE_SET_MSG:
case NSS_UDP_ST_RESET_STATS_MSG:
{
void *cb_data = nss_nlcmn_get_cb_data(&rule->cm, sock->family_id);

View File

@ -0,0 +1,29 @@
--- a/nssinfo/src/nssinfo.c
+++ b/nssinfo/src/nssinfo.c
@@ -176,8 +176,6 @@ void nssinfo_print_all(char *node, char
}
}
nssinfo_stats_print("\n");
-
- return;
}
/*
@@ -278,7 +276,6 @@ void nssinfo_node_stats_destroy(pthread_
p = next;
}
- return;
}
/*
@@ -293,7 +290,8 @@ static char* nssinfo_add_comma(uint64_t
}
nssinfo_add_comma(num/1000);
- snprintf(buf + strlen(buf), sizeof(buf + strlen(buf)), ",%03lu", num % 1000);
+ snprintf(buf + strlen(buf), sizeof(buf[NSSINFO_STR_LEN] + strlen(buf)), ",%03lu",
+ num % 1000);
return buf;
}

View File

@ -0,0 +1,48 @@
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -4,13 +4,44 @@ OBJPATH = obj
BINARY = $(OBJPATH)/libnl-nss.so
SOURCES = $(wildcard $(SRCPATH)/*.c)
-OBJECTS = $(SOURCES:$(SRCPATH)/%.c=$(OBJPATH)/%.o)
HEADERS = $(wildcard $(SRCPATH)/*.h)
INCLUDE += -I./include
EXTRA_CFLAGS = -Wall -Werror -fPIC -Wl,-z,relro -Wl,-z,now
EXTRA_LDFLAGS = -pie -Wl,-z,relro -Wl,-z,now
+# Base objects that are always needed
+BASE_OBJS = ipv4_api ipv6_api mcast_api sock
+
+# Feature objects that depend on flags
+FEATURE_OBJS =
+
+ifeq ($(capwap),y)
+ FEATURE_OBJS += capwap_api
+endif
+ifeq ($(dtls),y)
+ FEATURE_OBJS += dtls_api
+endif
+ifeq ($(gre_redir),y)
+ FEATURE_OBJS += gre_redir_api
+endif
+ifeq ($(ipsec),y)
+ FEATURE_OBJS += ipsec_api
+endif
+ifeq ($(qrfs),y)
+ FEATURE_OBJS += qrfs_api
+endif
+ifeq ($(udp_st),y)
+ FEATURE_OBJS += udp_st_api
+endif
+
+# All objects to build
+OBJS = $(BASE_OBJS) $(FEATURE_OBJS)
+
+# Convert to actual object file paths
+OBJECTS = $(patsubst %,$(OBJPATH)/nss_nl%.o,$(OBJS))
+HEADERS = $(wildcard $(SRCPATH)/*.h)
+
all: release
release: $(BINARY)

View File

@ -0,0 +1,40 @@
--- a/lib/nss_nlsock.c
+++ b/lib/nss_nlsock.c
@@ -379,7 +379,7 @@ int nss_nlsock_send(struct nss_nlsock_ct
* In case firmware response is sent before nl_recvmsgs is invoked,
* the response will be queued until the listener is available.
*/
- error = nl_send_sync(sock->nl_sk, msg);
+ error = nl_send_auto_complete(sock->nl_sk, msg);
if (error < 0) {
nss_nlsock_log_error("%d:failed to send (family:%s, error:%d)\n", pid, sock->family_name, error);
nss_nlsock_deref(sock);
@@ -387,6 +387,17 @@ int nss_nlsock_send(struct nss_nlsock_ct
return error;
}
+ /*
+ * Wait for ACK response from netlink
+ */
+ /* error = nl_wait_for_ack(sock->nl_sk); */
+ /* if (error < 0) { */
+ /* nss_nlsock_log_error("%d:failed to get ACK (family:%s, error:%d)\n", pid, sock->family_name, error); */
+ /* nss_nlsock_deref(sock); */
+ /* sock->is_avail = true; */
+ /* return error; */
+ /* } */
+
if (has_resp) {
nl_recvmsgs(sock->nl_sk, sock->nl_cb);
}
--- a/nssinfo/Makefile
+++ b/nssinfo/Makefile
@@ -10,7 +10,7 @@ OBJECTS = $(SOURCES:$(SRCDIR)/src/%.c=$(
INCLUDE += -I../lib/include
EXTRA_CFLAGS = -Wall -Werror -UENABLE_DEBUG
-LDFLAGS = -lnl-genl-3 -lnl-nss -lncurses -lglib-2.0
+LDFLAGS = -lnl-nss -lnl-tiny -lncurses
LDLIBS = -L../lib/obj
all: release

View File

@ -0,0 +1,281 @@
diff --git a/lib/nss_nlmcast_api.c b/lib/nss_nlmcast_api.c
index 7646440..11ec59b 100644
--- a/lib/nss_nlmcast_api.c
+++ b/lib/nss_nlmcast_api.c
@@ -94,7 +94,7 @@ int nss_nlmcast_sock_join_grp(struct nss_nlmcast_ctx *ctx, char *grp_name)
error = nss_nlsock_join_grp(&ctx->sock, grp_name);
if (error) {
- nss_nlsock_log_error("Unable to subscribe for mcast group, error(%d)\n", error);
+ /* nss_nlsock_log_error("Unable to subscribe for mcast group, error(%d)\n", error); */
return error;
}
diff --git a/lib/nss_nlsock.c b/lib/nss_nlsock.c
index 5b231e5..bde0670 100644
--- a/lib/nss_nlsock.c
+++ b/lib/nss_nlsock.c
@@ -221,15 +221,23 @@ int nss_nlsock_leave_grp(struct nss_nlsock_ctx *sock, char *grp_name)
{
int error;
- assert(sock->ref_cnt > 0);
+ /* Skip if socket is invalid */
+ if (!sock || !sock->nl_sk) {
+ return 0;
+ }
+
+ /* Safety check: Don't assert on ref_cnt */
+ if (sock->ref_cnt <= 0) {
+ return 0;
+ }
/*
* Resolve the group
*/
sock->grp_id = genl_ctrl_resolve_grp(sock->nl_sk, sock->family_name, grp_name);
if (sock->grp_id < 0) {
- nss_nlsock_log_error("failed to resolve group(%s)\n", grp_name);
- return -EINVAL;
+ /* Don't report error, just return success since we can't leave a group that doesn't exist */
+ return 0;
}
/*
@@ -259,7 +267,7 @@ int nss_nlsock_join_grp(struct nss_nlsock_ctx *sock, char *grp_name)
*/
sock->grp_id = genl_ctrl_resolve_grp(sock->nl_sk, sock->family_name, grp_name);
if (sock->grp_id < 0) {
- nss_nlsock_log_error("failed to resolve group(%s)\n", grp_name);
+ /* nss_nlsock_log_error("failed to resolve group(%s)\n", grp_name); */
return -EINVAL;
}
--- a/nssinfo/src/nssinfo.c
+++ b/nssinfo/src/nssinfo.c
@@ -20,12 +20,25 @@
#include <signal.h>
#include "nssinfo.h"
+/* Keyboard control definitions */
+#define KEY_QUIT 'q'
+// stop fucking using KEY_HELP as it conflicts with the help key in ncurses
+#define KEY_HELP_ 'h'
+#define KEY_VERBOSE 'v'
+#define KEY_LIST_STATS '?'
+
static pthread_t nssinfo_display_thread; /* Display statistics thread */
static char buf[NSSINFO_STR_LEN]; /* Formatted stats buffer */
bool display_all_stats; /* Display all stats per sub-system */
int invalid_input; /* Identify invalid input */
FILE *output_file; /* Output file pointer */
FILE *flow_file; /* Flow file pointer */
+static volatile bool quit_requested = false; /* Flag to indicate quit request */
+
+/* Forward declarations for new functions */
+static void nssinfo_display_help(void);
+static void nssinfo_list_available_stats(void);
+static void nssinfo_handle_keyboard_input(void);
/* Array of pointers to node stats */
struct node *nodes[NSS_MAX_CORES][NSS_MAX_NET_INTERFACES];
@@ -350,6 +363,16 @@ static void *nssinfo_stats_display(void *arg)
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
for (;;) {
+ /* Check for keyboard input */
+ if (!output_file) {
+ nssinfo_handle_keyboard_input();
+
+ /* Check if quit was requested */
+ if (quit_requested) {
+ break;
+ }
+ }
+
nssinfo_stats_print("\t\t\t%s\n", mesg);
/*
@@ -505,6 +528,8 @@ done:
invalid_input = 0;
sleep(arguments.rate);
}
+
+ return NULL;
}
/*
@@ -607,11 +632,16 @@ static void nssinfo_notify_callback(int cmd, void *data)
if (cmd < NSS_NLCMN_SUBSYS_MAX && nssinfo_subsystem_array[cmd].is_inited) {
nssinfo_subsystem_array[cmd].notify(data);
} else {
- nssinfo_error("Unknown message type %d\n", cmd);
+ /* Silently ignore unknown message types */
+ if (arguments.verbose) {
+ nssinfo_warn("Ignoring unknown message type %d\n", cmd);
+ }
}
}
/*
+ * nssinfo_deinit()
+ * Release all resources
*/
static void nssinfo_deinit(struct nss_nlmcast_ctx *ctx)
{
@@ -639,10 +669,11 @@ static void nssinfo_deinit(struct nss_nlmcast_ctx *ctx)
/*
* Release resources used by each subsystem
+ * Only deinitialize subsystems that were successfully initialized
*/
for (i = 0; i < NSS_NLCMN_SUBSYS_MAX; i++) {
- deinit = nssinfo_subsystem_array[i].deinit;
- if (deinit) {
+ if (nssinfo_subsystem_array[i].is_inited && nssinfo_subsystem_array[i].deinit) {
+ deinit = nssinfo_subsystem_array[i].deinit;
deinit(ctx);
}
}
@@ -671,16 +702,25 @@ int nssinfo_init(void)
/*
* Initialize all the subsystems and subscribe for mcast groups.
+ * Don't exit on subsystem initialization failures - these are expected
+ * if certain kernel modules aren't loaded.
*/
for (i = 0; i < NSS_NLCMN_SUBSYS_MAX; i++) {
init = nssinfo_subsystem_array[i].init;
if (init) {
error = init(&ctx);
if (error) {
- nssinfo_error("%s init failed, error(%d)\n", nssinfo_subsystem_array[i].subsystem_name, error);
+ /* Mark as not initialized so we won't try to use it later */
+ nssinfo_subsystem_array[i].is_inited = 0;
+
+ /* Only log warnings in verbose mode */
+ if (arguments.verbose) {
+ nssinfo_warn("%s init failed, error(%d) - subsystem may not be available\n",
+ nssinfo_subsystem_array[i].subsystem_name, error);
+ }
+ }
}
}
- }
/*
* Listen for MCAST events from kernel.
@@ -700,7 +740,7 @@ int nssinfo_init(void)
}
/*
- * Install CTRL-C handler
+ * Install CTRL-C handler and other signal handlers
*/
struct sigaction new_action;
new_action.sa_handler = nssinfo_termination_handler;
@@ -721,3 +761,91 @@ end:
nssinfo_deinit(&ctx);
return error;
}
+
+/*
+ * nssinfo_display_help()
+ * Display help information for keyboard controls
+ */
+static void nssinfo_display_help(void)
+{
+ clear();
+ mvprintw(0, 0, "NSSINFO Keyboard Controls Help");
+ mvprintw(2, 0, "q - Quit the application");
+ mvprintw(3, 0, "h - Display this help screen");
+ mvprintw(4, 0, "v - Toggle verbose mode");
+ mvprintw(5, 0, "? - List available statistics");
+ mvprintw(7, 0, "Press any key to return to stats display...");
+ refresh();
+
+ /* Wait for key press before returning to stats display */
+ nodelay(stdscr, FALSE);
+ getch();
+ nodelay(stdscr, TRUE);
+ clear();
+}
+
+/*
+ * nssinfo_list_available_stats()
+ * Display list of available statistics modules
+ */
+static void nssinfo_list_available_stats(void)
+{
+ int i, row = 0;
+
+ clear();
+ mvprintw(row++, 0, "Available Statistics Modules:");
+ row++;
+
+ for (i = 0; i < NSS_NLCMN_SUBSYS_MAX; i++) {
+ if (nssinfo_subsystem_array[i].is_inited) {
+ mvprintw(row++, 2, "- %s", nssinfo_subsystem_array[i].subsystem_name);
+ }
+ }
+
+ mvprintw(row + 2, 0, "Press any key to return to stats display...");
+ refresh();
+
+ /* Wait for key press before returning to stats display */
+ nodelay(stdscr, FALSE);
+ getch();
+ nodelay(stdscr, TRUE);
+ clear();
+}
+
+/*
+ * nssinfo_handle_keyboard_input()
+ * Process keyboard input for interactive controls
+ */
+static void nssinfo_handle_keyboard_input(void)
+{
+ int ch = getch();
+
+ if (ch == ERR) {
+ /* No input available */
+ return;
+ }
+
+ switch (ch) {
+ case KEY_QUIT:
+ /* Set quit flag to exit application gracefully */
+ quit_requested = true;
+ raise(SIGINT); /* Signal to terminate */
+ break;
+
+ case KEY_HELP_:
+ nssinfo_display_help();
+ break;
+
+ case KEY_VERBOSE:
+ /* Toggle verbose mode */
+ arguments.verbose = !arguments.verbose;
+ break;
+
+ case KEY_LIST_STATS:
+ nssinfo_list_available_stats();
+ break;
+
+ default:
+ break;
+ }
+}
diff --git a/nssinfo/src/nssinfo_lso_rx.c b/nssinfo/src/nssinfo_lso_rx.c
index bbe7274..9f5bd6e 100644
--- a/nssinfo/src/nssinfo_lso_rx.c
+++ b/nssinfo/src/nssinfo_lso_rx.c
@@ -43,7 +43,7 @@ static void nssinfo_lso_rx_stats_display(int core, char *input)
lso_rx_node = nodes[core][NSS_LSO_RX_INTERFACE];
if (!lso_rx_node) {
pthread_mutex_unlock(&lso_rx_lock);
- nssinfo_error("%s is not running on the NPU\n", input);
+ /* nssinfo_error("%s is not running on the NPU\n", input); */
return;
}