mirror of
https://github.com/breeze303/nss-packages.git
synced 2025-12-16 16:57:29 +00:00
qca: add nss-userspace-oss
This commit is contained in:
parent
d5ffa68b18
commit
487f8d1df0
45
qca/nss-userspace-oss/libnl-nss/Makefile
Normal file
45
qca/nss-userspace-oss/libnl-nss/Makefile
Normal file
@ -0,0 +1,45 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
include $(INCLUDE_DIR)/kernel.mk
|
||||
|
||||
PKG_NAME:=libnl-nss
|
||||
PKG_RELEASE:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/libnl-nss
|
||||
SECTION:=Libs
|
||||
CATEGORY:=Libraries
|
||||
TITLE:=Framework to communicate between userspace applications and the kernel.
|
||||
DEPENDS:=+libpthread +libnl +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
|
||||
|
||||
TOOL_CFLAGS:= -I$(STAGING_DIR)/usr/include/qca-nss-clients \
|
||||
-I$(STAGING_DIR)/usr/include/qca-nss-drv \
|
||||
-I$(STAGING_DIR)/usr/include/libnl3
|
||||
|
||||
TOOL_LDFLAGS:= -L$(STAGING_DIR)/lib
|
||||
|
||||
define Build/Compile
|
||||
$(MAKE) -C $(PKG_BUILD_DIR) \
|
||||
CC="$(TARGET_CC)" \
|
||||
AR="$(TARGET_AR) " \
|
||||
CFLAGS="$(TOOL_CFLAGS)" \
|
||||
LD_LIBRARY_PATH="$(TOOL_LDFLAGS)"
|
||||
endef
|
||||
|
||||
define Build/InstallDev
|
||||
$(INSTALL_DIR) $(STAGING_DIR)/usr/include/libnl-nss
|
||||
$(CP) $(PKG_BUILD_DIR)/obj/libnl-nss.so $(STAGING_DIR)/usr/lib
|
||||
$(CP) $(PKG_BUILD_DIR)/include/* $(STAGING_DIR)/usr/include/libnl-nss
|
||||
endef
|
||||
|
||||
define Package/libnl-nss/install
|
||||
$(INSTALL_DIR) $(1)/lib
|
||||
$(INSTALL_DATA) $(PKG_BUILD_DIR)/obj/libnl-nss.so $(1)/lib
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,libnl-nss))
|
||||
35
qca/nss-userspace-oss/libnl-nss/src/Makefile
Normal file
35
qca/nss-userspace-oss/libnl-nss/src/Makefile
Normal file
@ -0,0 +1,35 @@
|
||||
MKDIR = @mkdir -p $(@D)
|
||||
SRCPATH = ./
|
||||
OBJPATH = obj
|
||||
|
||||
BINARY = $(OBJPATH)/libnl-nss.so
|
||||
SOURCES = $(wildcard $(SRCPATH)/*.c)
|
||||
OBJECTS = $(SOURCES:$(SRCPATH)/%.c=$(OBJPATH)/%.o)
|
||||
HEADERS = $(wildcard $(SRCPATH)/*.h)
|
||||
|
||||
INCLUDE += -I./include
|
||||
LDFLAGS = -lnl-3 -lnl-genl-3
|
||||
EXTRA_CFLAGS = -Wall -Werror -fPIC -Wl,-z,relro -Wl,-z,now
|
||||
EXTRA_LDFLAGS = -pie -Wl,-z,relro -Wl,-z,now
|
||||
|
||||
all: release
|
||||
|
||||
release: $(BINARY)
|
||||
|
||||
$(OBJPATH)/%.o: $(SRCPATH)/%.c $(HEADERS)
|
||||
$(MKDIR)
|
||||
@echo [CC] $@
|
||||
@$(CC) -c $(CFLAGS) $(INCLUDE) $(EXTRA_CFLAGS) -o $@ $<
|
||||
|
||||
$(BINARY): $(OBJECTS)
|
||||
@echo $(BINARY)
|
||||
@echo [LD] $@
|
||||
@$(CC) -shared -o $@ $^ $(LDFLAGS) $(LDLIBS)
|
||||
|
||||
clean:
|
||||
@echo [Clean]
|
||||
@rm -f $(OBJECTS)
|
||||
@rm -f $(BINARY)
|
||||
@rm -rf $(OBJPATH)
|
||||
|
||||
.PHONY: clean
|
||||
71
qca/nss-userspace-oss/libnl-nss/src/include/nss_nlbase.h
Normal file
71
qca/nss-userspace-oss/libnl-nss/src/include/nss_nlbase.h
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
* Copyright (c) 2019-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 __NSS_NLBASE_H__
|
||||
#define __NSS_NLBASE_H__
|
||||
|
||||
/*
|
||||
* TODO: Remove inter-dependencies between the header files.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <limits.h>
|
||||
#include <linux/socket.h>
|
||||
#include <net/if.h>
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <linux/if_ether.h>
|
||||
|
||||
/* Generic Netlink header */
|
||||
#include <netlink/genl/ctrl.h>
|
||||
#include <netlink/genl/family.h>
|
||||
#include <netlink/genl/genl.h>
|
||||
|
||||
#if !defined (likely) || !defined (unlikely)
|
||||
#define likely(x) __builtin_expect(!!(x), 1)
|
||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
#endif
|
||||
|
||||
/* NSS headers */
|
||||
#include <nss_arch.h>
|
||||
#include <nss_def.h>
|
||||
#include <nss_cmn.h>
|
||||
#include <nss_ipv4.h>
|
||||
#include <nss_ipv6.h>
|
||||
#include <nss_nlcmn_if.h>
|
||||
#include <nss_dtls_cmn.h>
|
||||
#include <nss_dtlsmgr.h>
|
||||
#include <nss_nl_if.h>
|
||||
#include <nss_nlsock_api.h>
|
||||
#include <nss_nldtls_if.h>
|
||||
#include <nss_nldtls_api.h>
|
||||
#include <nss_nlist_api.h>
|
||||
#include <nss_nlipv4_if.h>
|
||||
#include <nss_nlipv4_api.h>
|
||||
#include <nss_nlipv6_if.h>
|
||||
#include <nss_nlipv6_api.h>
|
||||
#include <nss_nlmcast_api.h>
|
||||
#endif /* __NSS_NLBASE_H__ */
|
||||
119
qca/nss-userspace-oss/libnl-nss/src/include/nss_nldtls_api.h
Normal file
119
qca/nss-userspace-oss/libnl-nss/src/include/nss_nldtls_api.h
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
* Copyright (c) 2019-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 __NSS_NLDTLS_API_H__
|
||||
#define __NSS_NLDTLS_API_H__
|
||||
|
||||
/** @addtogroup chapter_nldtls
|
||||
This chapter describes Data Transport Layer Security (DTLS) APIs in the user space.
|
||||
These APIs are wrapper functions for DTLS family specific operations.
|
||||
*/
|
||||
|
||||
/** @addtogroup nss_nldtls_datatypes @{ */
|
||||
|
||||
/**
|
||||
* Response callback for DTLS.
|
||||
*
|
||||
* @param[in] user_ctx User context (provided at socket open).
|
||||
* @param[in] rule DTLS rule.
|
||||
* @param[in] resp_ctx User data per callback.
|
||||
*
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
typedef void (*nss_nldtls_resp_t)(void *user_ctx, struct nss_nldtls_rule *rule, void *resp_ctx);
|
||||
|
||||
/**
|
||||
* Event callback for DTLS.
|
||||
*
|
||||
* @param[in] user_ctx User context (provided at socket open).
|
||||
* @param[in] rule DTLS rule.
|
||||
*
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
typedef void (*nss_nldtls_event_t)(void *user_ctx, struct nss_nldtls_rule *rule);
|
||||
|
||||
/**
|
||||
* NSS NL DTLS response.
|
||||
*/
|
||||
struct nss_nldtls_resp {
|
||||
void *data; /**< Response context. */
|
||||
nss_nldtls_resp_t cb; /**< Response callback. */
|
||||
};
|
||||
|
||||
/**
|
||||
* NSS NL DTLS context.
|
||||
*/
|
||||
struct nss_nldtls_ctx {
|
||||
struct nss_nlsock_ctx sock; /**< NSS socket context. */
|
||||
nss_nldtls_event_t event; /**< NSS event callback function. */
|
||||
};
|
||||
|
||||
/** @} *//* end_addtogroup nss_nldtls_datatypes */
|
||||
/** @addtogroup nss_nldtls_functions @{ */
|
||||
|
||||
/**
|
||||
* Opens NSS NL DTLS socket.
|
||||
*
|
||||
* @param[in] ctx NSS NL socket context allocated by the caller.
|
||||
* @param[in] user_ctx User context stored per socket.
|
||||
* @param[in] event_cb Event callback handler.
|
||||
*
|
||||
* @return
|
||||
* Status of the open call.
|
||||
*/
|
||||
int nss_nldtls_sock_open(struct nss_nldtls_ctx *ctx, void *user_ctx, nss_nldtls_event_t event_cb);
|
||||
|
||||
/**
|
||||
* Closes NSS NL DTLS socket.
|
||||
*
|
||||
* @param[in] ctx NSS NL context.
|
||||
*
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
void nss_nldtls_sock_close(struct nss_nldtls_ctx *ctx);
|
||||
|
||||
/**
|
||||
* Send a DTLS rule synchronously to NSS NL NETLINK.
|
||||
*
|
||||
* @param[in] ctx NSS DTLS NL context.
|
||||
* @param[in] rule DTLS rule.
|
||||
* @param[in] cb Response callback handler.
|
||||
* @param[in] data Data received from sender.
|
||||
*
|
||||
* @return
|
||||
* Send status:
|
||||
* - 0 -- Success.
|
||||
* - Negative version error (-ve) -- Failure.
|
||||
*/
|
||||
int nss_nldtls_sock_send(struct nss_nldtls_ctx *ctx, struct nss_nldtls_rule *rule, nss_nldtls_resp_t cb, void *data);
|
||||
|
||||
/**
|
||||
* Initializes create rule message.
|
||||
*
|
||||
* @param[in] rule DTLS rule.
|
||||
* @param[in] type Type of command.
|
||||
*
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
void nss_nldtls_init_rule(struct nss_nldtls_rule *rule, enum nss_nldtls_cmd_type type);
|
||||
|
||||
/** @} *//* end_addtogroup nss_nldtls_functions */
|
||||
|
||||
#endif /* __NSS_NLDTLS_API_H__ */
|
||||
253
qca/nss-userspace-oss/libnl-nss/src/include/nss_nlipv4_api.h
Normal file
253
qca/nss-userspace-oss/libnl-nss/src/include/nss_nlipv4_api.h
Normal file
@ -0,0 +1,253 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
* Copyright (c) 2019-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 __NSS_NLIPV4_API_H__
|
||||
#define __NSS_NLIPV4_API_H__
|
||||
|
||||
#define NSS_IPV4_RULE_CREATE_IDENTIFIER_VALID 0x1000 /**< Identifier is valid. */
|
||||
|
||||
/** @addtogroup chapter_nlipv4
|
||||
This chapter describes IPv4 APIs in the user space.
|
||||
These APIs are wrapper functions for IPv4 family specific operations.
|
||||
*/
|
||||
|
||||
/** @addtogroup nss_nlipv4_datatypes @{ */
|
||||
|
||||
/**
|
||||
* Response callback for IPv4.
|
||||
*
|
||||
* @param[in] user_ctx User context (provided at socket open).
|
||||
* @param[in] rule IPv4 rule.
|
||||
* @param[in] resp_ctx User data per callback.
|
||||
*
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
typedef void (*nss_nlipv4_resp_t)(void *user_ctx, struct nss_nlipv4_rule *rule, void *resp_ctx);
|
||||
|
||||
/**
|
||||
* Event callback for IPv4.
|
||||
*
|
||||
* @param[in] user_ctx User context (provided at socket open).
|
||||
* @param[in] rule IPv4 rule.
|
||||
*
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
typedef void (*nss_nlipv4_event_t)(void *user_ctx, struct nss_nlipv4_rule *rule);
|
||||
|
||||
/**
|
||||
* NSS NL IPv4 response.
|
||||
*/
|
||||
struct nss_nlipv4_resp {
|
||||
void *data; /**< Response context. */
|
||||
nss_nlipv4_resp_t cb; /**< Response callback. */
|
||||
};
|
||||
|
||||
/**
|
||||
* NSS NL IPv4 context.
|
||||
*/
|
||||
struct nss_nlipv4_ctx {
|
||||
struct nss_nlsock_ctx sock; /**< NSS socket context. */
|
||||
nss_nlipv4_event_t event; /**< NSS event callback function. */
|
||||
};
|
||||
|
||||
/** @} *//* end_addtogroup nss_nlipv4_datatypes */
|
||||
/** @addtogroup nss_nlipv4_functions @{ */
|
||||
|
||||
/**
|
||||
* Opens NSS NL IPv4 socket.
|
||||
*
|
||||
* @param[in] ctx NSS NL socket context allocated by the caller.
|
||||
* @param[in] user_ctx User context stored per socket.
|
||||
* @param[in] event_cb Event callback handler.
|
||||
*
|
||||
* @return
|
||||
* Status of the open call.
|
||||
*/
|
||||
int nss_nlipv4_sock_open(struct nss_nlipv4_ctx *ctx, void *user_ctx, nss_nlipv4_event_t event_cb);
|
||||
|
||||
/**
|
||||
* Closes NSS NL IPv4 socket.
|
||||
*
|
||||
* @param[in] ctx NSS NL context.
|
||||
*
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
void nss_nlipv4_sock_close(struct nss_nlipv4_ctx *ctx);
|
||||
|
||||
/**
|
||||
* Sends an IPv4 rule synchronously to NSS NETLINK.
|
||||
*
|
||||
* @param[in] ctx NSS NL IPv4 context.
|
||||
* @param[in] rule IPv4 rule.
|
||||
* @param[in] cb Response callback handler.
|
||||
* @param[in] data Response data per callback.
|
||||
*
|
||||
* @return
|
||||
* Send status:
|
||||
* - 0 -- Success.
|
||||
* - Negative version error (-ve) -- Failure.
|
||||
*/
|
||||
int nss_nlipv4_sock_send(struct nss_nlipv4_ctx *ctx, struct nss_nlipv4_rule *rule, nss_nlipv4_resp_t cb, void *data);
|
||||
|
||||
/**
|
||||
* Initializes IPv4 rule message.
|
||||
*
|
||||
* @param[in] rule IPv4 rule.
|
||||
* @param[in] type Command type.
|
||||
*
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
void nss_nlipv4_init_rule(struct nss_nlipv4_rule *rule, enum nss_ipv4_message_types type);
|
||||
|
||||
/**
|
||||
* Initializes connection rule for create message.
|
||||
*
|
||||
* @param[in] create Creates message.
|
||||
*
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
static inline void nss_nlipv4_init_conn_rule(struct nss_ipv4_rule_create_msg *create)
|
||||
{
|
||||
create->valid_flags |= NSS_IPV4_RULE_CREATE_CONN_VALID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables route flow.
|
||||
*
|
||||
* @param[in] create Creates message.
|
||||
*
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
static inline void nss_nlipv4_init_route_flow_rule(struct nss_ipv4_rule_create_msg *create)
|
||||
{
|
||||
create->rule_flags |= NSS_IPV4_RULE_CREATE_FLAG_ROUTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables bridge flow.
|
||||
*
|
||||
* @param[in] create Creates message.
|
||||
*
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
static inline void nss_nlipv4_init_bridge_flow_rule(struct nss_ipv4_rule_create_msg *create)
|
||||
{
|
||||
create->rule_flags |= NSS_IPV4_RULE_CREATE_FLAG_BRIDGE_FLOW;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes TCP protocol rule for create message.
|
||||
*
|
||||
* @param[in] create Creates message.
|
||||
*
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
static inline void nss_nlipv4_init_tcp_rule(struct nss_ipv4_rule_create_msg *create)
|
||||
{
|
||||
create->valid_flags |= NSS_IPV4_RULE_CREATE_TCP_VALID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes PPPoE rule for create message.
|
||||
*
|
||||
* @param[in] create Creates message.
|
||||
*
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
static inline void nss_nlipv4_init_pppoe_rule(struct nss_ipv4_rule_create_msg *create)
|
||||
{
|
||||
create->valid_flags |= NSS_IPV4_RULE_CREATE_PPPOE_VALID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes QoS rule for create message.
|
||||
*
|
||||
* @param[in] create Creates message.
|
||||
*
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
static inline void nss_nlipv4_init_qos_rule(struct nss_ipv4_rule_create_msg *create)
|
||||
{
|
||||
create->valid_flags |= NSS_IPV4_RULE_CREATE_QOS_VALID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes DSCP rule for create message.
|
||||
*
|
||||
* @param[in] create Creates message.
|
||||
*
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
static inline void nss_nlipv4_init_dscp_rule(struct nss_ipv4_rule_create_msg *create)
|
||||
{
|
||||
create->valid_flags |= NSS_IPV4_RULE_CREATE_DSCP_MARKING_VALID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes VLAN rule for create message.
|
||||
*
|
||||
* @param[in] create Creates message.
|
||||
*
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
static inline void nss_nlipv4_init_vlan_rule(struct nss_ipv4_rule_create_msg *create)
|
||||
{
|
||||
struct nss_ipv4_vlan_rule *primary;
|
||||
struct nss_ipv4_vlan_rule *secondary;
|
||||
|
||||
primary = &create->vlan_primary_rule;
|
||||
secondary = &create->vlan_secondary_rule;
|
||||
|
||||
create->valid_flags |= NSS_IPV4_RULE_CREATE_VLAN_VALID;
|
||||
|
||||
/*
|
||||
* set the tags to default values
|
||||
*/
|
||||
primary->ingress_vlan_tag = NSS_NLIPV4_VLAN_ID_NOT_CONFIGURED;
|
||||
primary->egress_vlan_tag = NSS_NLIPV4_VLAN_ID_NOT_CONFIGURED;
|
||||
|
||||
secondary->ingress_vlan_tag = NSS_NLIPV4_VLAN_ID_NOT_CONFIGURED;
|
||||
secondary->egress_vlan_tag = NSS_NLIPV4_VLAN_ID_NOT_CONFIGURED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes Identifier rule for create message.
|
||||
*
|
||||
* @param[in] create Creates message.
|
||||
*
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
static inline void nss_nlipv4_init_identifier_rule(struct nss_ipv4_rule_create_msg *create)
|
||||
{
|
||||
create->valid_flags |= NSS_IPV4_RULE_CREATE_IDENTIFIER_VALID;
|
||||
}
|
||||
|
||||
/** @} *//* end_addtogroup nss_nlipv4_functions */
|
||||
|
||||
#endif /* __NSS_NLIPV4_API_H__ */
|
||||
253
qca/nss-userspace-oss/libnl-nss/src/include/nss_nlipv6_api.h
Normal file
253
qca/nss-userspace-oss/libnl-nss/src/include/nss_nlipv6_api.h
Normal file
@ -0,0 +1,253 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
* Copyright (c) 2019-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 __NSS_NLIPV6_API_H__
|
||||
#define __NSS_NLIPV6_API_H__
|
||||
|
||||
#define NSS_IPV6_RULE_CREATE_IDENTIFIER_VALID 0x1000 /**< Identifier is valid. */
|
||||
|
||||
/** @addtogroup chapter_nlipv6
|
||||
This chapter describes IPv6 APIs in the user space.
|
||||
These APIs are wrapper functions for IPv6 family specific operations.
|
||||
*/
|
||||
|
||||
/** @addtogroup nss_nlipv6_datatypes @{ */
|
||||
|
||||
/**
|
||||
* Response callback for IPv6.
|
||||
*
|
||||
* @param[in] user_ctx User context (provided at socket open).
|
||||
* @param[in] rule IPv6 rule.
|
||||
* @param[in] resp_ctx user data per callback.
|
||||
*
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
typedef void (*nss_nlipv6_resp_t)(void *user_ctx, struct nss_nlipv6_rule *rule, void *resp_ctx);
|
||||
|
||||
/**
|
||||
* Event callback for IPv6.
|
||||
*
|
||||
* @param[in] user_ctx User context (provided at socket open).
|
||||
* @param[in] rule IPv6 Rule.
|
||||
*
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
typedef void (*nss_nlipv6_event_t)(void *user_ctx, struct nss_nlipv6_rule *rule);
|
||||
|
||||
/**
|
||||
* NSS NL IPv6 response.
|
||||
*/
|
||||
struct nss_nlipv6_resp {
|
||||
void *data; /**< Response context. */
|
||||
nss_nlipv6_resp_t cb; /**< Response callback. */
|
||||
};
|
||||
|
||||
/**
|
||||
* NSS NL IPv6 context.
|
||||
*/
|
||||
struct nss_nlipv6_ctx {
|
||||
struct nss_nlsock_ctx sock; /**< NSS socket context. */
|
||||
nss_nlipv6_event_t event; /**< NSS event callback function. */
|
||||
};
|
||||
|
||||
/** @} *//* end_addtogroup nss_nlipv6_datatypes */
|
||||
/** @addtogroup nss_nlipv6_functions @{ */
|
||||
|
||||
/**
|
||||
* Opens NSS NL IPv6 socket.
|
||||
*
|
||||
* @param[in] ctx NSS NL socket context allocated by the caller.
|
||||
* @param[in] user_ctx User context stored per socket.
|
||||
* @param[in] event_cb Event callback handler.
|
||||
*
|
||||
* @return
|
||||
* Status of the open call.
|
||||
*/
|
||||
int nss_nlipv6_sock_open(struct nss_nlipv6_ctx *ctx, void *user_ctx, nss_nlipv6_event_t event_cb);
|
||||
|
||||
/**
|
||||
* Closes NSS NL IPv6 socket.
|
||||
*
|
||||
* @param[in] ctx NSS NL context.
|
||||
*
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
void nss_nlipv6_sock_close(struct nss_nlipv6_ctx *ctx);
|
||||
|
||||
/**
|
||||
* Sends an IPv6 rule synchronously to NSS NETLINK.
|
||||
*
|
||||
* @param[in] ctx NSS IPv6 NL context.
|
||||
* @param[in] rule IPv6 rule.
|
||||
* @param[in] cb Response callback handler.
|
||||
* @param[in] data Response data per callback.
|
||||
*
|
||||
* @return
|
||||
* Send status:
|
||||
* - 0 -- Success.
|
||||
* - Negative version error (-ve) -- Failure.
|
||||
*/
|
||||
int nss_nlipv6_sock_send(struct nss_nlipv6_ctx *ctx, struct nss_nlipv6_rule *rule, nss_nlipv6_resp_t cb, void *data);
|
||||
|
||||
/**
|
||||
* Initializes rule message.
|
||||
*
|
||||
* @param[in] rule IPv6 rule.
|
||||
* @param[in] type Command type.
|
||||
*
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
void nss_nlipv6_init_rule(struct nss_nlipv6_rule *rule, enum nss_ipv6_message_types type);
|
||||
|
||||
/**
|
||||
* Initializes connection rule for create message.
|
||||
*
|
||||
* @param[in] create Creates message.
|
||||
*
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
static inline void nss_nlipv6_init_conn_rule(struct nss_ipv6_rule_create_msg *create)
|
||||
{
|
||||
create->valid_flags |= NSS_IPV6_RULE_CREATE_CONN_VALID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables route flow.
|
||||
*
|
||||
* @param[in] create Creates message.
|
||||
*
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
static inline void nss_nlipv6_init_route_flow_rule(struct nss_ipv6_rule_create_msg *create)
|
||||
{
|
||||
create->rule_flags |= NSS_IPV6_RULE_CREATE_FLAG_ROUTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables bridge flow.
|
||||
*
|
||||
* @param[in] create create message.
|
||||
*
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
static inline void nss_nlipv6_init_bridge_flow_rule(struct nss_ipv6_rule_create_msg *create)
|
||||
{
|
||||
create->rule_flags |= NSS_IPV6_RULE_CREATE_FLAG_BRIDGE_FLOW;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes TCP protocol rule for create message.
|
||||
*
|
||||
* @param[in] create Creates message.
|
||||
*
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
static inline void nss_nlipv6_init_tcp_rule(struct nss_ipv6_rule_create_msg *create)
|
||||
{
|
||||
create->valid_flags |= NSS_IPV6_RULE_CREATE_TCP_VALID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes PPPoE rule for create message.
|
||||
*
|
||||
* @param[in] create Creates message.
|
||||
*
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
static inline void nss_nlipv6_init_pppoe_rule(struct nss_ipv6_rule_create_msg *create)
|
||||
{
|
||||
create->valid_flags |= NSS_IPV6_RULE_CREATE_PPPOE_VALID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes QoS rule for create message.
|
||||
*
|
||||
* @param[in] create Creates message.
|
||||
*
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
static inline void nss_nlipv6_init_qos_rule(struct nss_ipv6_rule_create_msg *create)
|
||||
{
|
||||
create->valid_flags |= NSS_IPV6_RULE_CREATE_QOS_VALID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes DSCP rule for create message.
|
||||
*
|
||||
* @param[in] create Creates message.
|
||||
*
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
static inline void nss_nlipv6_init_dscp_rule(struct nss_ipv6_rule_create_msg *create)
|
||||
{
|
||||
create->valid_flags |= NSS_IPV6_RULE_CREATE_DSCP_MARKING_VALID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes VLAN rule for create message.
|
||||
*
|
||||
* @param[in] create Creates message.
|
||||
*
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
static inline void nss_nlipv6_init_vlan_rule(struct nss_ipv6_rule_create_msg *create)
|
||||
{
|
||||
struct nss_ipv6_vlan_rule *primary;
|
||||
struct nss_ipv6_vlan_rule *secondary;
|
||||
|
||||
primary = &create->vlan_primary_rule;
|
||||
secondary = &create->vlan_secondary_rule;
|
||||
|
||||
create->valid_flags |= NSS_IPV6_RULE_CREATE_VLAN_VALID;
|
||||
|
||||
/*
|
||||
* set the tags to default values
|
||||
*/
|
||||
primary->ingress_vlan_tag = NSS_NLIPV6_VLAN_ID_NOT_CONFIGURED;
|
||||
primary->egress_vlan_tag = NSS_NLIPV6_VLAN_ID_NOT_CONFIGURED;
|
||||
|
||||
secondary->ingress_vlan_tag = NSS_NLIPV6_VLAN_ID_NOT_CONFIGURED;
|
||||
secondary->egress_vlan_tag = NSS_NLIPV6_VLAN_ID_NOT_CONFIGURED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes Identifier rule for create message.
|
||||
*
|
||||
* @param[in] create Creates message.
|
||||
*
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
static inline void nss_nlipv6_init_identifier_rule(struct nss_ipv6_rule_create_msg *create)
|
||||
{
|
||||
create->valid_flags |= NSS_IPV6_RULE_CREATE_IDENTIFIER_VALID;
|
||||
}
|
||||
|
||||
/** @} *//* end_addtogroup nss_nlipv6_functions */
|
||||
|
||||
#endif /* __NSS_NLIPV6_API_H__ */
|
||||
220
qca/nss-userspace-oss/libnl-nss/src/include/nss_nlist_api.h
Normal file
220
qca/nss-userspace-oss/libnl-nss/src/include/nss_nlist_api.h
Normal file
@ -0,0 +1,220 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
* Copyright (c) 2019,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 __NSS_NLIST_H__
|
||||
#define __NSS_NLIST_H__
|
||||
|
||||
/** @addtogroup chapter_nlist
|
||||
This chapter describes Netlink list APIs in the user space.
|
||||
*/
|
||||
|
||||
/** @ingroup nss_nlist_datatypes
|
||||
* List node
|
||||
*/
|
||||
struct nss_nlist {
|
||||
struct nss_nlist *next; /**< Next node. */
|
||||
struct nss_nlist *prev; /**< Previous node. */
|
||||
};
|
||||
|
||||
/** @addtogroup nss_nlist_functions @{ */
|
||||
|
||||
/**
|
||||
* Initializes the list node.
|
||||
*
|
||||
* @param[in] node List node.
|
||||
*
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
static inline void nss_nlist_init(struct nss_nlist *node)
|
||||
{
|
||||
node->next = node->prev = node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the previous node.
|
||||
*
|
||||
* @param[in] node Previous node.
|
||||
*
|
||||
* @return
|
||||
* Previous node or head node.
|
||||
*/
|
||||
static inline struct nss_nlist *nss_nlist_prev(struct nss_nlist *node)
|
||||
{
|
||||
return node->prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the next node.
|
||||
*
|
||||
* @param[in] node Next node.
|
||||
*
|
||||
* @return
|
||||
* Next node or head node.
|
||||
*/
|
||||
static inline struct nss_nlist *nss_nlist_next(struct nss_nlist *node)
|
||||
{
|
||||
return node->next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the head node.
|
||||
*
|
||||
* @param[in] head Head of list.
|
||||
*
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
static inline void nss_nlist_init_head(struct nss_nlist *head)
|
||||
{
|
||||
nss_nlist_init(head);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns first node in the list.
|
||||
*
|
||||
* @param[in] head List head.
|
||||
*
|
||||
* @return
|
||||
* First node.
|
||||
*/
|
||||
static inline struct nss_nlist *nss_nlist_first(struct nss_nlist *head)
|
||||
{
|
||||
return nss_nlist_next(head);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns last node in the list.
|
||||
*
|
||||
* @param[in] head List head.
|
||||
*
|
||||
* @return
|
||||
* Last node.
|
||||
*/
|
||||
static inline struct nss_nlist *nss_nlist_last(struct nss_nlist *head)
|
||||
{
|
||||
return nss_nlist_prev(head);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if list is empty.
|
||||
*
|
||||
* @param[in] head List head.
|
||||
*
|
||||
* @return
|
||||
* TRUE if empty.
|
||||
*/
|
||||
static inline bool nss_nlist_isempty(struct nss_nlist *head)
|
||||
{
|
||||
struct nss_nlist *first = nss_nlist_first(head);
|
||||
|
||||
return first == head;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if corresponding node is the last node.
|
||||
*
|
||||
* @param[in] head Head node.
|
||||
* @param[in] node Node to check.
|
||||
*
|
||||
* @return
|
||||
* TRUE if it is the last node.
|
||||
*/
|
||||
static inline bool nss_nlist_islast(struct nss_nlist *head, struct nss_nlist *node)
|
||||
{
|
||||
struct nss_nlist *last = nss_nlist_last(head);
|
||||
|
||||
return last == node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds node to head of the list.
|
||||
*
|
||||
* @param[in] head List head.
|
||||
* @param[in] node Node to add.
|
||||
*
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
static inline void nss_nlist_add_head(struct nss_nlist *head, struct nss_nlist *node)
|
||||
{
|
||||
struct nss_nlist *first = nss_nlist_first(head);
|
||||
|
||||
node->prev = head;
|
||||
node->next = first;
|
||||
|
||||
first->prev = node;
|
||||
head->next = node;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds node to tail of the list.
|
||||
*
|
||||
* @param[in] head List head.
|
||||
* @param[in] node Node to add.
|
||||
*
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
static inline void nss_nlist_add_tail(struct nss_nlist *head, struct nss_nlist *node)
|
||||
{
|
||||
struct nss_nlist *last = nss_nlist_last(head);
|
||||
|
||||
node->next = head;
|
||||
node->prev = last;
|
||||
|
||||
last->next = node;
|
||||
head->prev = node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlinks node from the list.
|
||||
*
|
||||
* @param[in] node Node to unlink.
|
||||
*
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
static inline void nss_nlist_unlink(struct nss_nlist *node)
|
||||
{
|
||||
struct nss_nlist *prev = nss_nlist_prev(node);
|
||||
struct nss_nlist *next = nss_nlist_next(node);
|
||||
|
||||
prev->next = next;
|
||||
next->prev = prev;
|
||||
|
||||
nss_nlist_init(node);
|
||||
}
|
||||
|
||||
/** @} *//* end_addtogroup nss_nlist_functions */
|
||||
|
||||
/** @ingroup nss_nlist_macros
|
||||
* Lists node iterator.
|
||||
*
|
||||
* @hideinitializer
|
||||
* @param[in] _tmp Temporary node for assignment.
|
||||
* @param[in] _head Head node to start.
|
||||
*
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
#define nss_nlist_iterate(_tmp, _head) \
|
||||
for ((_tmp) = nss_nlist_first((_head)); \
|
||||
!nss_nlist_islast((_head), (_tmp)); \
|
||||
(_tmp) = nss_nlist_next((_tmp))
|
||||
|
||||
#endif /* __NSS_NLIST_H__ */
|
||||
102
qca/nss-userspace-oss/libnl-nss/src/include/nss_nlmcast_api.h
Normal file
102
qca/nss-userspace-oss/libnl-nss/src/include/nss_nlmcast_api.h
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
* Copyright (c) 2020-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 __NSS_NLMCAST_API_H__
|
||||
#define __NSS_NLMCAST_API_H__
|
||||
|
||||
/** @addtogroup chapter_nlmcast
|
||||
This chapter describes multicast APIs in the user space.
|
||||
These APIs are wrapper functions for multicast specific operations.
|
||||
*/
|
||||
|
||||
/** @addtogroup nss_nlmcast_datatypes @{ */
|
||||
|
||||
/**
|
||||
* Event callback for multicast.
|
||||
*
|
||||
* @param[in] cmd Command received in generic Netlink header.
|
||||
* @param[in] data Data received in Netlink message.
|
||||
*/
|
||||
typedef void (*nss_nlmcast_event_t)(int cmd, void *data);
|
||||
|
||||
/**
|
||||
* NSS multicast context.
|
||||
*/
|
||||
struct nss_nlmcast_ctx {
|
||||
struct nss_nlsock_ctx sock; /**< NSS socket context. */
|
||||
nss_nlmcast_event_t event; /**< NSS event callback function. */
|
||||
};
|
||||
|
||||
/** @} *//* end_addtogroup nss_nlmcast_datatypes */
|
||||
/** @addtogroup nss_nlmcast_functions @{ */
|
||||
|
||||
/**
|
||||
* Listens to NSS NL multicast event data.
|
||||
*
|
||||
* @param[in] ctx Multicast context.
|
||||
*
|
||||
* @return
|
||||
* Listen status.
|
||||
*/
|
||||
int nss_nlmcast_sock_listen(struct nss_nlmcast_ctx *ctx);
|
||||
|
||||
/**
|
||||
* Subscribe the multicast group to receive responses.
|
||||
*
|
||||
* @param[in] ctx Multicast context.
|
||||
* @param[in] grp_name NSS NL group name.
|
||||
*
|
||||
* @return
|
||||
* Subscription status.
|
||||
*/
|
||||
int nss_nlmcast_sock_join_grp(struct nss_nlmcast_ctx *ctx, char *grp_name);
|
||||
|
||||
/**
|
||||
* Unsubscribe the multicast group to stop receiving responses.
|
||||
*
|
||||
* @param[in] ctx Multicast context.
|
||||
* @param[in] grp_name NSS NL group name.
|
||||
*
|
||||
* @return
|
||||
* Status of the operation.
|
||||
*/
|
||||
int nss_nlmcast_sock_leave_grp(struct nss_nlmcast_ctx *ctx, char *grp_name);
|
||||
|
||||
/**
|
||||
* Opens a socket for listening to NSS NL event data.
|
||||
*
|
||||
* @param[in] ctx Multicast context.
|
||||
* @param[in] cb Callback function.
|
||||
* @param[in] family_name NSS NL family name.
|
||||
*
|
||||
* @return
|
||||
* Status of the operation.
|
||||
*/
|
||||
int nss_nlmcast_sock_open(struct nss_nlmcast_ctx *ctx, nss_nlmcast_event_t cb, const char *family_name);
|
||||
|
||||
/**
|
||||
* Closes socket.
|
||||
*
|
||||
* @param[in] ctx Multicast context.
|
||||
*
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
void nss_nlmcast_sock_close(struct nss_nlmcast_ctx *ctx);
|
||||
|
||||
/** @} *//* end_addtogroup nss_nlmcast_functions */
|
||||
|
||||
#endif /* __NSS_NLMCAST_API_H__ */
|
||||
197
qca/nss-userspace-oss/libnl-nss/src/include/nss_nlsock_api.h
Normal file
197
qca/nss-userspace-oss/libnl-nss/src/include/nss_nlsock_api.h
Normal file
@ -0,0 +1,197 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
* Copyright (c) 2019-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 __NSS_NLSOCK_API_H__
|
||||
#define __NSS_NLSOCK_API_H__
|
||||
|
||||
/** @addtogroup chapter_nlsocket
|
||||
This chapter describes socket APIs for direct use.
|
||||
|
||||
@note1hang
|
||||
Use these APIs(s) only if there are no available helpers for the specific family.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup nss_nlsocket_datatypes
|
||||
* NSS NL socket context.
|
||||
*/
|
||||
struct nss_nlsock_ctx {
|
||||
/* Public, caller must populate using helpers */
|
||||
const char *family_name; /**< Family name. */
|
||||
void *user_ctx; /**< Socket user context. */
|
||||
|
||||
/* Private, maintained by the library */
|
||||
pthread_t thread; /**< Response sync. */
|
||||
pthread_spinlock_t lock; /**< Context lock. */
|
||||
int ref_cnt; /**< References to the socket. */
|
||||
|
||||
struct nl_sock *nl_sk; /**< Linux NL socket. */
|
||||
struct nl_cb *nl_cb; /**< NSS NL callback context. */
|
||||
|
||||
pid_t pid; /**< Process ID associated with the socket. */
|
||||
int family_id; /**< Family identifier. */
|
||||
int grp_id; /**< Group indentifier. */
|
||||
bool is_avail; /**< Indicates if the socket is available to send or listen. */
|
||||
};
|
||||
|
||||
/** @addtogroup nss_nlsocket_macros @{ */
|
||||
|
||||
/**
|
||||
* Prints error log.
|
||||
*
|
||||
* @param[in] arg Argument to be printed
|
||||
*/
|
||||
#define nss_nlsock_log_error(arg, ...) printf("NSS_NLERROR(%s[%d]):"arg, __func__, __LINE__, ##__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* Prints arguments
|
||||
*
|
||||
* @param[in] arg Argument to be printed
|
||||
*/
|
||||
#define nss_nlsock_log_info(arg, ...) printf("NSS_NLINFO(%s[%d]):"arg, __func__, __LINE__, ##__VA_ARGS__)
|
||||
|
||||
/** @} *//* end_addtogroup nss_nlsocket_macros */
|
||||
|
||||
/** @addtogroup nss_nlsocket_functions @{ */
|
||||
|
||||
/**
|
||||
* Sets family name.
|
||||
*
|
||||
* @param[in] sock Socket context.
|
||||
* @param[in] name Family name.
|
||||
*
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
static inline void nss_nlsock_set_family(struct nss_nlsock_ctx *sock, const char *name)
|
||||
{
|
||||
sock->family_name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets user context.
|
||||
*
|
||||
* @param[in] sock Socket context.
|
||||
* @param[in] user User context.
|
||||
*
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
static inline void nss_nlsock_set_user_ctx(struct nss_nlsock_ctx *sock, void *user)
|
||||
{
|
||||
sock->user_ctx = user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts NSS NL message data.
|
||||
*
|
||||
* @param[in] msg NL message.
|
||||
*
|
||||
* @return
|
||||
* Pointer to start of NSS NL message.
|
||||
*/
|
||||
static inline void *nss_nlsock_get_data(struct nl_msg *msg)
|
||||
{
|
||||
struct genlmsghdr *genl_hdr = nlmsg_data((nlmsg_hdr(msg)));
|
||||
|
||||
return genlmsg_data(genl_hdr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens NSS NL family socket.
|
||||
*
|
||||
* @param[in] sock Socket context to be allocated by the caller.
|
||||
* @param[in] cb Callback function for response.
|
||||
*
|
||||
* @return
|
||||
* Status of the operation.
|
||||
*
|
||||
* @note The underlying entity should set the sock->family name for the socket to open.
|
||||
*/
|
||||
int nss_nlsock_open(struct nss_nlsock_ctx *sock, nl_recvmsg_msg_cb_t cb);
|
||||
|
||||
/**
|
||||
* Closes NSS NL family socket.
|
||||
*
|
||||
* @param[in] sock Socket context.
|
||||
*
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
void nss_nlsock_close(struct nss_nlsock_ctx *sock);
|
||||
|
||||
/**
|
||||
* Sends NSS NL message synchronously.
|
||||
*
|
||||
* @param[in] sock Socket context.
|
||||
* @param[in] cm Common message header.
|
||||
* @param[in] data Message data.
|
||||
* @param[in] has_resp Determines if response is needed from kernel.
|
||||
*
|
||||
* @detdesc The function blocks until ack/error is received from the kernel
|
||||
* and also blocks for the message response from the kernel if is_resp is TRUE
|
||||
|
||||
* @return
|
||||
* Status of the send operation.
|
||||
*/
|
||||
int nss_nlsock_send(struct nss_nlsock_ctx *sock, struct nss_nlcmn *cm, void *data, bool has_resp);
|
||||
|
||||
/**
|
||||
* Listens to asynchronous events from kernel.
|
||||
*
|
||||
* @param[in] sock Socket context.
|
||||
*
|
||||
* @return
|
||||
* Listen status.
|
||||
*/
|
||||
int nss_nlsock_listen(struct nss_nlsock_ctx *sock);
|
||||
|
||||
/**
|
||||
* Subscribes to multicast group.
|
||||
*
|
||||
* @param[in] sock Socket context.
|
||||
* @param[in] grp_name NSS NL group name.
|
||||
*
|
||||
* @return
|
||||
* Subscription status.
|
||||
*/
|
||||
int nss_nlsock_join_grp(struct nss_nlsock_ctx *sock, char *grp_name);
|
||||
|
||||
/**
|
||||
* Unsubscribes from multicast group.
|
||||
*
|
||||
* @param[in] sock Socket context.
|
||||
* @param[in] grp_name NSS NL group name.
|
||||
*
|
||||
* @return
|
||||
* Status of the operation.
|
||||
*/
|
||||
int nss_nlsock_leave_grp(struct nss_nlsock_ctx *sock, char *grp_name);
|
||||
|
||||
/**
|
||||
* Opens a socket for listening to NSS NL event data.
|
||||
*
|
||||
* @param[in] sock Socket context.
|
||||
* @param[in] cb Callback function.
|
||||
*
|
||||
* @return
|
||||
* Status of the operation.
|
||||
*/
|
||||
int nss_nlsock_open_mcast(struct nss_nlsock_ctx *sock, nl_recvmsg_msg_cb_t cb);
|
||||
|
||||
/** @} *//* end_addtogroup nss_nlsocket_functions */
|
||||
|
||||
#endif /* __NSS_NLSOCK_API_H__ */
|
||||
138
qca/nss-userspace-oss/libnl-nss/src/nss_nldtls_api.c
Normal file
138
qca/nss-userspace-oss/libnl-nss/src/nss_nldtls_api.c
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
* Copyright (c) 2019-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 <nss_nlbase.h>
|
||||
#include <nss_nlsock_api.h>
|
||||
#include <nss_nldtls_api.h>
|
||||
|
||||
/*
|
||||
* nss_nldtls_sock_cb()
|
||||
* Callback func for dtls netlink socket
|
||||
*/
|
||||
int nss_nldtls_sock_cb(struct nl_msg *msg, void *arg)
|
||||
{
|
||||
pid_t pid = getpid();
|
||||
|
||||
struct nss_nldtls_rule *rule = nss_nlsock_get_data(msg);
|
||||
|
||||
if (!rule) {
|
||||
nss_nlsock_log_error("%d:failed to get NSS NL dtls header\n", pid);
|
||||
return NL_SKIP;
|
||||
}
|
||||
|
||||
uint8_t cmd = nss_nlcmn_get_cmd(&rule->cm);
|
||||
|
||||
switch (cmd) {
|
||||
case NSS_NLDTLS_CMD_TYPE_CREATE_TUN:
|
||||
case NSS_NLDTLS_CMD_TYPE_DESTROY_TUN:
|
||||
case NSS_NLDTLS_CMD_TYPE_UPDATE_CONFIG:
|
||||
case NSS_NLDTLS_CMD_TYPE_TX_PKTS:
|
||||
return NL_OK;
|
||||
|
||||
default:
|
||||
nss_nlsock_log_error("%d:unsupported message cmd type(%d)\n", pid, cmd);
|
||||
return NL_SKIP;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* nss_nldtls_sock_open()
|
||||
* Opens the NSS dtls NL socket for usage
|
||||
*/
|
||||
int nss_nldtls_sock_open(struct nss_nldtls_ctx *ctx, void *user_ctx, nss_nldtls_event_t event_cb)
|
||||
{
|
||||
pid_t pid = getpid();
|
||||
int error;
|
||||
|
||||
if (!ctx) {
|
||||
nss_nlsock_log_error("%d: invalid parameters passed\n", pid);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
|
||||
nss_nlsock_set_family(&ctx->sock, NSS_NLDTLS_FAMILY);
|
||||
nss_nlsock_set_user_ctx(&ctx->sock, user_ctx);
|
||||
|
||||
/*
|
||||
* try opening the socket with Linux
|
||||
*/
|
||||
error = nss_nlsock_open(&ctx->sock, nss_nldtls_sock_cb);
|
||||
if (error) {
|
||||
nss_nlsock_log_error("%d:unable to open NSS dtls socket, error(%d)\n", pid, error);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* nss_nldtls_sock_close()
|
||||
* Close the NSS dtls NL socket
|
||||
*/
|
||||
void nss_nldtls_sock_close(struct nss_nldtls_ctx *ctx)
|
||||
{
|
||||
nss_nlsock_close(&ctx->sock);
|
||||
memset(ctx, 0, sizeof(struct nss_nldtls_ctx));
|
||||
}
|
||||
|
||||
/*
|
||||
* nss_nldtls_sock_send()
|
||||
* Send the dtls message synchronously through the socket
|
||||
*/
|
||||
int nss_nldtls_sock_send(struct nss_nldtls_ctx *ctx, struct nss_nldtls_rule *rule, nss_nldtls_resp_t cb, void *data)
|
||||
{
|
||||
int32_t family_id = ctx->sock.family_id;
|
||||
struct nss_nldtls_resp *resp;
|
||||
pid_t pid = getpid();
|
||||
bool has_resp = false;
|
||||
int error = 0;
|
||||
|
||||
if (!rule) {
|
||||
nss_nlsock_log_error("%d:invalid NSS dtls rule\n", pid);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (cb) {
|
||||
nss_nlcmn_set_cb_owner(&rule->cm, family_id);
|
||||
|
||||
resp = nss_nlcmn_get_cb_data(&rule->cm, family_id);
|
||||
assert(resp);
|
||||
|
||||
resp->data = data;
|
||||
resp->cb = cb;
|
||||
has_resp = true;
|
||||
}
|
||||
|
||||
error = nss_nlsock_send(&ctx->sock, &rule->cm, rule, has_resp);
|
||||
if (error) {
|
||||
nss_nlsock_log_error("%d:failed to send NSS dtls rule, error(%d)\n", pid, error);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* nss_nldtls_init_rule()
|
||||
* Initialize the dtls rule
|
||||
*/
|
||||
void nss_nldtls_init_rule(struct nss_nldtls_rule *rule, enum nss_nldtls_cmd_type type)
|
||||
{
|
||||
nss_nldtls_rule_init(rule, type);
|
||||
}
|
||||
176
qca/nss-userspace-oss/libnl-nss/src/nss_nlipv4_api.c
Normal file
176
qca/nss-userspace-oss/libnl-nss/src/nss_nlipv4_api.c
Normal file
@ -0,0 +1,176 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
* Copyright (c) 2019-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 <nss_nlbase.h>
|
||||
#include <nss_nlsock_api.h>
|
||||
#include <nss_nlipv4_api.h>
|
||||
|
||||
/*
|
||||
* nss_nlipv4_sock_cb()
|
||||
* NSS NL IPv4 callback
|
||||
*/
|
||||
int nss_nlipv4_sock_cb(struct nl_msg *msg, void *arg)
|
||||
{
|
||||
pid_t pid = getpid();
|
||||
|
||||
struct nss_nlipv4_ctx *ctx = (struct nss_nlipv4_ctx *)arg;
|
||||
struct nss_nlsock_ctx *sock = &ctx->sock;
|
||||
|
||||
struct nss_nlipv4_rule *rule = nss_nlsock_get_data(msg);
|
||||
if (!rule) {
|
||||
nss_nlsock_log_error("%d:failed to get NSS NL IPv4 header\n", pid);
|
||||
return NL_SKIP;
|
||||
}
|
||||
|
||||
uint8_t cmd = nss_nlcmn_get_cmd(&rule->cm);
|
||||
|
||||
switch (cmd) {
|
||||
case NSS_IPV4_TX_CREATE_RULE_MSG:
|
||||
case NSS_IPV4_TX_DESTROY_RULE_MSG:
|
||||
{
|
||||
void *cb_data = nss_nlcmn_get_cb_data(&rule->cm, sock->family_id);
|
||||
if (!cb_data) {
|
||||
return NL_SKIP;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: The callback user can modify the CB content so it
|
||||
* needs to locally save the response data for further use
|
||||
* after the callback is completed
|
||||
*/
|
||||
struct nss_nlipv4_resp resp;
|
||||
memcpy(&resp, cb_data, sizeof(struct nss_nlipv4_resp));
|
||||
|
||||
/*
|
||||
* clear the ownership of the CB so that callback user can
|
||||
* use it if needed
|
||||
*/
|
||||
nss_nlcmn_clr_cb_owner(&rule->cm);
|
||||
|
||||
if (!resp.cb) {
|
||||
nss_nlsock_log_info("%d:no IPv4 response callback for cmd(%d)\n", pid, cmd);
|
||||
return NL_SKIP;
|
||||
}
|
||||
|
||||
resp.cb(sock->user_ctx, rule, resp.data);
|
||||
|
||||
return NL_OK;
|
||||
}
|
||||
|
||||
case NSS_IPV4_RX_CONN_STATS_SYNC_MSG:
|
||||
{
|
||||
nss_nlipv4_event_t event = ctx->event;
|
||||
|
||||
assert(event);
|
||||
event(sock->user_ctx, rule);
|
||||
|
||||
return NL_OK;
|
||||
}
|
||||
|
||||
default:
|
||||
nss_nlsock_log_error("%d:unsupported message cmd type(%d)\n", pid, cmd);
|
||||
return NL_SKIP;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* nss_nlipv4_sock_open()
|
||||
* this opens the NSS IPv4 NL socket for usage
|
||||
*/
|
||||
int nss_nlipv4_sock_open(struct nss_nlipv4_ctx *ctx, void *user_ctx, nss_nlipv4_event_t event_cb)
|
||||
{
|
||||
pid_t pid = getpid();
|
||||
int error;
|
||||
|
||||
if (!ctx) {
|
||||
nss_nlsock_log_error("%d: invalid parameters passed\n", pid);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
|
||||
nss_nlsock_set_family(&ctx->sock, NSS_NLIPV4_FAMILY);
|
||||
nss_nlsock_set_user_ctx(&ctx->sock, user_ctx);
|
||||
|
||||
/*
|
||||
* try opening the socket with Linux
|
||||
*/
|
||||
error = nss_nlsock_open(&ctx->sock, nss_nlipv4_sock_cb);
|
||||
if (error) {
|
||||
nss_nlsock_log_error("%d:unable to open NSS IPv4 socket, error(%d)\n", pid, error);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* nss_nlipv4_sock_close()
|
||||
* close the NSS IPv4 NL socket
|
||||
*/
|
||||
void nss_nlipv4_sock_close(struct nss_nlipv4_ctx *ctx)
|
||||
{
|
||||
nss_nlsock_close(&ctx->sock);
|
||||
}
|
||||
|
||||
/*
|
||||
* nss_nlipv4_sock_send()
|
||||
* register callback and send the IPv4 message synchronously through the socket
|
||||
*/
|
||||
int nss_nlipv4_sock_send(struct nss_nlipv4_ctx *ctx, struct nss_nlipv4_rule *rule, nss_nlipv4_resp_t cb, void *data)
|
||||
{
|
||||
int32_t family_id = ctx->sock.family_id;
|
||||
struct nss_nlipv4_resp *resp;
|
||||
pid_t pid = getpid();
|
||||
bool has_resp = false;
|
||||
int error;
|
||||
|
||||
if (!rule) {
|
||||
nss_nlsock_log_error("%d:invalid NSS IPv4 rule\n", pid);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (cb) {
|
||||
nss_nlcmn_set_cb_owner(&rule->cm, family_id);
|
||||
|
||||
resp = nss_nlcmn_get_cb_data(&rule->cm, family_id);
|
||||
assert(resp);
|
||||
|
||||
resp->data = data;
|
||||
resp->cb = cb;
|
||||
has_resp = true;
|
||||
}
|
||||
|
||||
error = nss_nlsock_send(&ctx->sock, &rule->cm, rule, has_resp);
|
||||
if (error) {
|
||||
nss_nlsock_log_error("%d:failed to send NSS IPv4 rule, error(%d)\n", pid, error);
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* nss_nlipv4_init_rule()
|
||||
* init the rule message
|
||||
*/
|
||||
void nss_nlipv4_init_rule(struct nss_nlipv4_rule *rule, enum nss_ipv4_message_types type)
|
||||
{
|
||||
nss_nlipv4_rule_init(rule, type);
|
||||
}
|
||||
176
qca/nss-userspace-oss/libnl-nss/src/nss_nlipv6_api.c
Normal file
176
qca/nss-userspace-oss/libnl-nss/src/nss_nlipv6_api.c
Normal file
@ -0,0 +1,176 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
* Copyright (c) 2019-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 <nss_nlbase.h>
|
||||
#include <nss_nlsock_api.h>
|
||||
#include <nss_nlipv6_api.h>
|
||||
|
||||
/*
|
||||
* nss_nlipv6_sock_cb()
|
||||
* NSS NL IPv6 callback
|
||||
*/
|
||||
int nss_nlipv6_sock_cb(struct nl_msg *msg, void *arg)
|
||||
{
|
||||
pid_t pid = getpid();
|
||||
|
||||
struct nss_nlipv6_ctx *ctx = (struct nss_nlipv6_ctx *)arg;
|
||||
struct nss_nlsock_ctx *sock = &ctx->sock;
|
||||
|
||||
struct nss_nlipv6_rule *rule = nss_nlsock_get_data(msg);
|
||||
if (!rule) {
|
||||
nss_nlsock_log_error("%d:failed to get NSS NL IPv6 header\n", pid);
|
||||
return NL_SKIP;
|
||||
}
|
||||
|
||||
uint8_t cmd = nss_nlcmn_get_cmd(&rule->cm);
|
||||
|
||||
switch (cmd) {
|
||||
case NSS_IPV6_TX_CREATE_RULE_MSG:
|
||||
case NSS_IPV6_TX_DESTROY_RULE_MSG:
|
||||
{
|
||||
void *cb_data = nss_nlcmn_get_cb_data(&rule->cm, sock->family_id);
|
||||
if (!cb_data) {
|
||||
return NL_SKIP;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: The callback user can modify the CB content so it
|
||||
* needs to locally save the response data for further use
|
||||
* after the callback is completed
|
||||
*/
|
||||
struct nss_nlipv6_resp resp;
|
||||
memcpy(&resp, cb_data, sizeof(struct nss_nlipv6_resp));
|
||||
|
||||
/*
|
||||
* clear the ownership of the CB so that callback user can
|
||||
* use it if needed
|
||||
*/
|
||||
nss_nlcmn_clr_cb_owner(&rule->cm);
|
||||
|
||||
if (!resp.cb) {
|
||||
nss_nlsock_log_info("%d:no IPv6 response callback for cmd(%d)\n", pid, cmd);
|
||||
return NL_SKIP;
|
||||
}
|
||||
|
||||
resp.cb(sock->user_ctx, rule, resp.data);
|
||||
|
||||
return NL_OK;
|
||||
}
|
||||
|
||||
case NSS_IPV6_RX_CONN_STATS_SYNC_MSG:
|
||||
{
|
||||
nss_nlipv6_event_t event = ctx->event;
|
||||
|
||||
assert(event);
|
||||
event(sock->user_ctx, rule);
|
||||
|
||||
return NL_OK;
|
||||
}
|
||||
|
||||
default:
|
||||
nss_nlsock_log_error("%d:unsupported message cmd type(%d)\n", pid, cmd);
|
||||
return NL_SKIP;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* nss_nlipv6_sock_open()
|
||||
* this opens the NSS IPv6 NL socket for usage
|
||||
*/
|
||||
int nss_nlipv6_sock_open(struct nss_nlipv6_ctx *ctx, void *user_ctx, nss_nlipv6_event_t event_cb)
|
||||
{
|
||||
pid_t pid = getpid();
|
||||
int error;
|
||||
|
||||
if (!ctx) {
|
||||
nss_nlsock_log_error("%d: invalid parameters passed\n", pid);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
|
||||
nss_nlsock_set_family(&ctx->sock, NSS_NLIPV6_FAMILY);
|
||||
nss_nlsock_set_user_ctx(&ctx->sock, user_ctx);
|
||||
|
||||
/*
|
||||
* try opening the socket with Linux
|
||||
*/
|
||||
error = nss_nlsock_open(&ctx->sock, nss_nlipv6_sock_cb);
|
||||
if (error) {
|
||||
nss_nlsock_log_error("%d:unable to open NSS IPv6 socket, error(%d)\n", pid, error);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* nss_nlipv6_sock_close()
|
||||
* close the NSS IPv6 NL socket
|
||||
*/
|
||||
void nss_nlipv6_sock_close(struct nss_nlipv6_ctx *ctx)
|
||||
{
|
||||
nss_nlsock_close(&ctx->sock);
|
||||
}
|
||||
|
||||
/*
|
||||
* nss_nlipv6_sock_send()
|
||||
* register callback and send the IPv6 message synchronously through the socket
|
||||
*/
|
||||
int nss_nlipv6_sock_send(struct nss_nlipv6_ctx *ctx, struct nss_nlipv6_rule *rule, nss_nlipv6_resp_t cb, void *data)
|
||||
{
|
||||
int32_t family_id = ctx->sock.family_id;
|
||||
struct nss_nlipv6_resp *resp;
|
||||
pid_t pid = getpid();
|
||||
bool has_resp = false;
|
||||
int error;
|
||||
|
||||
if (!rule) {
|
||||
nss_nlsock_log_error("%d:invalid NSS IPv6 rule\n", pid);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (cb) {
|
||||
nss_nlcmn_set_cb_owner(&rule->cm, family_id);
|
||||
|
||||
resp = nss_nlcmn_get_cb_data(&rule->cm, family_id);
|
||||
assert(resp);
|
||||
|
||||
resp->data = data;
|
||||
resp->cb = cb;
|
||||
has_resp = true;
|
||||
}
|
||||
|
||||
error = nss_nlsock_send(&ctx->sock, &rule->cm, rule, has_resp);
|
||||
if (error) {
|
||||
nss_nlsock_log_error("%d:failed to send NSS IPv6 rule, error(%d)\n", pid, error);
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* nss_nlipv6_init_rule()
|
||||
* init the rule message
|
||||
*/
|
||||
void nss_nlipv6_init_rule(struct nss_nlipv6_rule *rule, enum nss_ipv6_message_types type)
|
||||
{
|
||||
nss_nlipv6_rule_init(rule, type);
|
||||
}
|
||||
146
qca/nss-userspace-oss/libnl-nss/src/nss_nlmcast_api.c
Normal file
146
qca/nss-userspace-oss/libnl-nss/src/nss_nlmcast_api.c
Normal file
@ -0,0 +1,146 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
* Copyright (c) 2020-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 <nss_nlbase.h>
|
||||
#include <nss_nlsock_api.h>
|
||||
#include <nss_nlmcast_api.h>
|
||||
|
||||
/*
|
||||
* nss_nlmcast_sock_cb()
|
||||
* NSS NL mcast callback.
|
||||
*/
|
||||
static int nss_nlmcast_sock_cb(struct nl_msg *msg, void *arg)
|
||||
{
|
||||
struct nss_nlmcast_ctx *ctx = (struct nss_nlmcast_ctx *)arg;
|
||||
struct genlmsghdr *genl_hdr = nlmsg_data((nlmsg_hdr(msg)));
|
||||
uint8_t cmd = genl_hdr->cmd;
|
||||
|
||||
void *data = nss_nlsock_get_data(msg);
|
||||
if (!data) {
|
||||
nss_nlsock_log_error("%d:failed to get NSS NL msg header\n", getpid());
|
||||
return NL_SKIP;
|
||||
}
|
||||
|
||||
nss_nlmcast_event_t event = ctx->event;
|
||||
assert(event);
|
||||
event(cmd, data);
|
||||
return NL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* nss_nlmcast_sock_open()
|
||||
* Open the NL socket for listening to MCAST events from kernel.
|
||||
*/
|
||||
int nss_nlmcast_sock_open(struct nss_nlmcast_ctx *ctx, nss_nlmcast_event_t event_cb, const char *family_name)
|
||||
{
|
||||
int error;
|
||||
|
||||
if (!ctx || !event_cb) {
|
||||
nss_nlsock_log_error("Invalid parameters passed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
|
||||
nss_nlsock_set_family(&ctx->sock, family_name);
|
||||
|
||||
/*
|
||||
* Subscribe to the NSS NL Multicast group.
|
||||
*/
|
||||
error = nss_nlsock_open_mcast(&ctx->sock, nss_nlmcast_sock_cb);
|
||||
if (error) {
|
||||
nss_nlsock_log_error("Unable to create socket, error(%d)\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
ctx->event = event_cb;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* nss_nlmcast_sock_close()
|
||||
* Close the NL socket.
|
||||
*/
|
||||
void nss_nlmcast_sock_close(struct nss_nlmcast_ctx *ctx)
|
||||
{
|
||||
nss_nlsock_close(&ctx->sock);
|
||||
}
|
||||
|
||||
/*
|
||||
* nss_nlmcast_sock_join_grp()
|
||||
* Subscribe for MCAST group from kernel.
|
||||
*/
|
||||
int nss_nlmcast_sock_join_grp(struct nss_nlmcast_ctx *ctx, char *grp_name)
|
||||
{
|
||||
int error;
|
||||
|
||||
if (!ctx || !grp_name) {
|
||||
nss_nlsock_log_error("Invalid parameters passed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
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);
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* nss_nlmcast_sock_leave_grp()
|
||||
* Unsubscribe for MCAST group from kernel.
|
||||
*/
|
||||
int nss_nlmcast_sock_leave_grp(struct nss_nlmcast_ctx *ctx, char *grp_name)
|
||||
{
|
||||
int error;
|
||||
|
||||
if (!ctx || !grp_name) {
|
||||
nss_nlsock_log_error("Invalid parameters passed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
error = nss_nlsock_leave_grp(&ctx->sock, grp_name);
|
||||
if (error) {
|
||||
nss_nlsock_log_error("Unable to unsubscribe for mcast group, error(%d)\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* nss_nlmcast_sock_listen()
|
||||
* Listen for MCAST events from kernel
|
||||
*/
|
||||
int nss_nlmcast_sock_listen(struct nss_nlmcast_ctx *ctx)
|
||||
{
|
||||
int error;
|
||||
|
||||
if (!ctx) {
|
||||
nss_nlsock_log_error("Invalid parameters passed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
error = nss_nlsock_listen(&ctx->sock);
|
||||
if (error) {
|
||||
nss_nlsock_log_error("Unable to listen to mcast events, error(%d)\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
498
qca/nss-userspace-oss/libnl-nss/src/nss_nlsock.c
Normal file
498
qca/nss-userspace-oss/libnl-nss/src/nss_nlsock.c
Normal file
@ -0,0 +1,498 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
* Copyright (c) 2019-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 netlink socket handler
|
||||
*/
|
||||
|
||||
#include <nss_nlbase.h>
|
||||
#include <nss_nlsock_api.h>
|
||||
|
||||
/*
|
||||
* nss_nlsock_deinit()
|
||||
* de-initialize the socket
|
||||
*/
|
||||
static void nss_nlsock_deinit(struct nss_nlsock_ctx *sock)
|
||||
{
|
||||
assert(sock);
|
||||
|
||||
nl_cb_put(sock->nl_cb);
|
||||
sock->nl_cb = NULL;
|
||||
|
||||
nl_socket_free(sock->nl_sk);
|
||||
sock->nl_sk = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* nss_nlsock_init()
|
||||
* initialize the socket and callback
|
||||
*/
|
||||
static int nss_nlsock_init(struct nss_nlsock_ctx *sock, nl_recvmsg_msg_cb_t cb)
|
||||
{
|
||||
int error;
|
||||
|
||||
assert(sock);
|
||||
|
||||
/*
|
||||
* Initialize spinlock
|
||||
*/
|
||||
error = pthread_spin_init(&sock->lock, PTHREAD_PROCESS_PRIVATE);
|
||||
if (error) {
|
||||
nss_nlsock_log_error("Failed to init spinlock for family(%s), error %d\n", sock->family_name, error);
|
||||
return error;
|
||||
}
|
||||
|
||||
sock->pid = getpid();
|
||||
|
||||
/*
|
||||
* create callback
|
||||
*/
|
||||
sock->nl_cb = nl_cb_alloc(NL_CB_CUSTOM);
|
||||
if (!sock->nl_cb) {
|
||||
nss_nlsock_log_error("%d:failed to alloc callback for family(%s)\n",sock->pid, sock->family_name);
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
/*
|
||||
* register callback
|
||||
*/
|
||||
nl_cb_set(sock->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, cb, sock);
|
||||
|
||||
/*
|
||||
* Create netlink socket
|
||||
*/
|
||||
sock->nl_sk = nl_socket_alloc_cb(sock->nl_cb);
|
||||
if (!sock->nl_sk) {
|
||||
nss_nlsock_log_error("%d:failed to alloc socket for family(%s)\n", sock->pid, sock->family_name);
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
sock->ref_cnt = 1;
|
||||
|
||||
/*
|
||||
* is_avail is set to indicate the socket is available for send/listen
|
||||
*/
|
||||
sock->is_avail = true;
|
||||
return 0;
|
||||
|
||||
fail2:
|
||||
nl_cb_put(sock->nl_cb);
|
||||
sock->nl_cb = NULL;
|
||||
fail1:
|
||||
pthread_spin_destroy(&sock->lock);
|
||||
sock->lock = (pthread_spinlock_t)0;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
* nss_nlsock_deref()
|
||||
* decrement the reference count and free socket resources if '0'
|
||||
*/
|
||||
static inline void nss_nlsock_deref(struct nss_nlsock_ctx *sock)
|
||||
{
|
||||
assert(sock->ref_cnt > 0);
|
||||
|
||||
pthread_spin_lock(&sock->lock);
|
||||
if (--sock->ref_cnt) {
|
||||
pthread_spin_unlock(&sock->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* When there are no more references on the socket,
|
||||
* deinitialize the socket and destroy the spin lock
|
||||
* created during nss_nlsock_init
|
||||
*/
|
||||
nss_nlsock_deinit(sock);
|
||||
pthread_spin_unlock(&sock->lock);
|
||||
|
||||
pthread_spin_destroy(&sock->lock);
|
||||
sock->lock = (pthread_spinlock_t)0;
|
||||
}
|
||||
|
||||
/*
|
||||
* nss_nlsock_ref()
|
||||
* Increment the reference count.
|
||||
*
|
||||
* if ref_cnt == 0, return false
|
||||
* if ref_cnt != 0, increment the socket reference count and return true
|
||||
*/
|
||||
static inline bool nss_nlsock_ref(struct nss_nlsock_ctx *sock)
|
||||
{
|
||||
/*
|
||||
* if ref count is 0, it means there are no references
|
||||
* on the socket and so return false. Socket will eventually be
|
||||
* freed by nss_nlsock_deinit else increment the ref count
|
||||
*/
|
||||
pthread_spin_lock(&sock->lock);
|
||||
if (sock->ref_cnt == 0) {
|
||||
pthread_spin_unlock(&sock->lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
sock->ref_cnt++;
|
||||
pthread_spin_unlock(&sock->lock);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* nss_nlsock_listen_callback()
|
||||
* listen to responses from the netlink socket
|
||||
*
|
||||
* The API keeps listening for the responses on the netlink socket
|
||||
* until socket close is initiated and there are no more
|
||||
* responses on the socket
|
||||
*/
|
||||
static void *nss_nlsock_listen_callback(void *arg)
|
||||
{
|
||||
struct nss_nlsock_ctx *sock = (struct nss_nlsock_ctx *)arg;
|
||||
assert(sock);
|
||||
|
||||
/*
|
||||
* drain responses on the socket
|
||||
*/
|
||||
for (;;) {
|
||||
/*
|
||||
* if, socket is freed then break out
|
||||
*/
|
||||
if (!nss_nlsock_ref(sock)) {
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* get or block for pending messages
|
||||
*/
|
||||
nl_recvmsgs(sock->nl_sk, sock->nl_cb);
|
||||
nss_nlsock_deref(sock);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* nss_nlsock_msg_init()
|
||||
* Initialize parameters to send message down the socket
|
||||
*/
|
||||
static int nss_nlsock_msg_init(struct nss_nlsock_ctx *sock, struct nss_nlcmn *cm, void *data, struct nl_msg *msg)
|
||||
{
|
||||
int pid = sock->pid;
|
||||
void *user_hdr;
|
||||
uint32_t ver;
|
||||
uint8_t cmd;
|
||||
int len;
|
||||
|
||||
ver = nss_nlcmn_get_ver(cm);
|
||||
len = nss_nlcmn_get_len(cm);
|
||||
cmd = nss_nlcmn_get_cmd(cm);
|
||||
|
||||
/*
|
||||
* create space for user header
|
||||
*/
|
||||
user_hdr = genlmsg_put(msg, pid, NL_AUTO_SEQ, sock->family_id, len, 0, cmd, ver);
|
||||
if (!user_hdr) {
|
||||
nss_nlsock_log_error("%d:failed to put message header of len(%d)\n", pid, len);
|
||||
return -ENOMEM;
|
||||
|
||||
}
|
||||
|
||||
memcpy(user_hdr, data, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* nss_nlsock_leave_grp()
|
||||
* nl socket unsubscribe for the multicast group
|
||||
*/
|
||||
int nss_nlsock_leave_grp(struct nss_nlsock_ctx *sock, char *grp_name)
|
||||
{
|
||||
int error;
|
||||
|
||||
assert(sock->ref_cnt > 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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unsubscribe for the mcast async events
|
||||
*/
|
||||
error = nl_socket_drop_memberships(sock->nl_sk, sock->grp_id, 0);
|
||||
if (error < 0) {
|
||||
nss_nlsock_log_error("failed to deregister grp(%s)\n", grp_name);
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* nss_nlsock_join_grp()
|
||||
* nl socket subscribe for the multicast group
|
||||
*/
|
||||
int nss_nlsock_join_grp(struct nss_nlsock_ctx *sock, char *grp_name)
|
||||
{
|
||||
int error;
|
||||
|
||||
assert(sock->ref_cnt > 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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Subscribe for the mcast async events
|
||||
*/
|
||||
error = nl_socket_add_memberships(sock->nl_sk, sock->grp_id, 0);
|
||||
if (error < 0) {
|
||||
nss_nlsock_log_error("failed to register grp(%s)\n", grp_name);
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* nss_nlsock_open_mcast()
|
||||
* Open the socket for async events
|
||||
*/
|
||||
int nss_nlsock_open_mcast(struct nss_nlsock_ctx *sock, nl_recvmsg_msg_cb_t cb)
|
||||
{
|
||||
int error;
|
||||
assert(sock);
|
||||
|
||||
error = nss_nlsock_init(sock, cb);
|
||||
if (error) {
|
||||
nss_nlsock_log_error("%d:failed to initialize socket(%s)\n", sock->pid, sock->family_name);
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable seq number and auto ack checks for sockets listening for mcast events
|
||||
*/
|
||||
nl_socket_disable_seq_check(sock->nl_sk);
|
||||
nl_socket_disable_auto_ack(sock->nl_sk);
|
||||
|
||||
/*
|
||||
* Connect the socket with the netlink bus
|
||||
*/
|
||||
if (genl_connect(sock->nl_sk)) {
|
||||
nss_nlsock_log_error("%d:failed to connect socket for family(%s)\n", sock->pid, sock->family_name);
|
||||
error = -EBUSY;
|
||||
goto free_sock;
|
||||
}
|
||||
return 0;
|
||||
|
||||
free_sock:
|
||||
nss_nlsock_deref(sock);
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* nss_nlsock_send()
|
||||
* send a message synchronously through the socket
|
||||
*/
|
||||
int nss_nlsock_send(struct nss_nlsock_ctx *sock, struct nss_nlcmn *cm, void *data, bool has_resp)
|
||||
{
|
||||
int pid = sock->pid;
|
||||
struct nl_msg *msg;
|
||||
int error;
|
||||
|
||||
/*
|
||||
* return -EBUSY if the socket is currently unavailable for sending message
|
||||
*/
|
||||
pthread_spin_lock(&sock->lock);
|
||||
if (!sock->is_avail) {
|
||||
pthread_spin_unlock(&sock->lock);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/*
|
||||
* To indicate the socket is unavailable until the current thread completes the send/listen.
|
||||
* This is to prevent other threads from simultaneous send/listen.
|
||||
*/
|
||||
sock->is_avail = false;
|
||||
pthread_spin_unlock(&sock->lock);
|
||||
|
||||
/*
|
||||
* allocate new message buffer
|
||||
*/
|
||||
msg = nlmsg_alloc();
|
||||
if (!msg) {
|
||||
nss_nlsock_log_error("%d:failed to allocate message buffer\n", pid);
|
||||
sock->is_avail = true;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
* Holds a reference on the socket until msg is sent down to the kernel
|
||||
*/
|
||||
if (!nss_nlsock_ref(sock)) {
|
||||
nss_nlsock_log_error("%d:failed to get NL socket\n", pid);
|
||||
nlmsg_free(msg);
|
||||
sock->is_avail = true;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize message parameters
|
||||
*/
|
||||
error = nss_nlsock_msg_init(sock, cm, data, msg);
|
||||
if (error) {
|
||||
nss_nlsock_log_error("%d:failed to initialize message structure (family:%s, error:%d)\n",
|
||||
pid, sock->family_name, error);
|
||||
nss_nlsock_deref(sock);
|
||||
nlmsg_free(msg);
|
||||
sock->is_avail = true;
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* If has_resp is true and msg is sent to FW, then there will be two
|
||||
* netlink messages coming from kernel - FW response and ACK
|
||||
* If msg fails in netlink, then error will be returned from kernel.
|
||||
* If has_resp is false, then there is only one netlink message
|
||||
* coming from kernel: either ACK or error
|
||||
* 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);
|
||||
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);
|
||||
sock->is_avail = true;
|
||||
return error;
|
||||
}
|
||||
|
||||
if (has_resp) {
|
||||
nl_recvmsgs(sock->nl_sk, sock->nl_cb);
|
||||
}
|
||||
|
||||
nss_nlsock_deref(sock);
|
||||
sock->is_avail = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* nss_nlsock_listen()
|
||||
* listen for async events on the socket
|
||||
*/
|
||||
int nss_nlsock_listen(struct nss_nlsock_ctx *sock)
|
||||
{
|
||||
int error;
|
||||
|
||||
assert(sock->ref_cnt > 0);
|
||||
|
||||
/*
|
||||
* return -EBUSY if the socket is currently unavailable for listening
|
||||
*/
|
||||
if (!sock->is_avail) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/*
|
||||
* To indicate the socket is unavailable until the current thread completes the send/listen.
|
||||
* This is to prevent other threads from simultaneous send/listen.
|
||||
*/
|
||||
sock->is_avail = false;
|
||||
|
||||
/*
|
||||
* Create an async thread for clearing the pending resp on the socket asynchronously
|
||||
*/
|
||||
error = pthread_create(&sock->thread, NULL, nss_nlsock_listen_callback, sock);
|
||||
if (error) {
|
||||
nss_nlsock_log_error("%d:failed to create sync thread for family(%s)\n", sock->pid, sock->family_name);
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* nss_nlsock_close()
|
||||
* close the allocated socket and all associated memory
|
||||
*/
|
||||
void nss_nlsock_close(struct nss_nlsock_ctx *sock)
|
||||
{
|
||||
assert(sock);
|
||||
assert(sock->nl_sk);
|
||||
assert(sock->ref_cnt > 0);
|
||||
|
||||
/*
|
||||
* put the reference down for the socket
|
||||
*/
|
||||
nss_nlsock_deref(sock);
|
||||
|
||||
/*
|
||||
* wait for the async thread to complete
|
||||
*/
|
||||
if (sock->thread) {
|
||||
pthread_join(sock->thread, NULL);
|
||||
sock->thread = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* nss_nlsock_open()
|
||||
* open a socket for unicast communication with the generic netlink framework
|
||||
*/
|
||||
int nss_nlsock_open(struct nss_nlsock_ctx *sock, nl_recvmsg_msg_cb_t cb)
|
||||
{
|
||||
int error = 0;
|
||||
assert(sock);
|
||||
|
||||
error = nss_nlsock_init(sock, cb);
|
||||
if (error) {
|
||||
nss_nlsock_log_error("%d:failed to initialize socket(%s)\n", sock->pid, sock->family_name);
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Connect the socket with the netlink bus
|
||||
*/
|
||||
if (genl_connect(sock->nl_sk)) {
|
||||
nss_nlsock_log_error("%d:failed to connect socket for family(%s)\n", sock->pid, sock->family_name);
|
||||
error = -EBUSY;
|
||||
goto free_sock;
|
||||
}
|
||||
|
||||
/*
|
||||
* resolve the family
|
||||
*/
|
||||
sock->family_id = genl_ctrl_resolve(sock->nl_sk, sock->family_name);
|
||||
if (sock->family_id <= 0) {
|
||||
nss_nlsock_log_error("%d:failed to resolve family(%s)\n", sock->pid, sock->family_name);
|
||||
error = -EINVAL;
|
||||
goto free_sock;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
free_sock:
|
||||
|
||||
nss_nlsock_deref(sock);
|
||||
return error;
|
||||
}
|
||||
39
qca/nss-userspace-oss/nssinfo/Makefile
Normal file
39
qca/nss-userspace-oss/nssinfo/Makefile
Normal file
@ -0,0 +1,39 @@
|
||||
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))
|
||||
35
qca/nss-userspace-oss/nssinfo/src/Makefile
Normal file
35
qca/nss-userspace-oss/nssinfo/src/Makefile
Normal file
@ -0,0 +1,35 @@
|
||||
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
|
||||
714
qca/nss-userspace-oss/nssinfo/src/src/nssinfo.c
Normal file
714
qca/nss-userspace-oss/nssinfo/src/src/nssinfo.c
Normal file
@ -0,0 +1,714 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
* 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;
|
||||
}
|
||||
233
qca/nss-userspace-oss/nssinfo/src/src/nssinfo.h
Normal file
233
qca/nss-userspace-oss/nssinfo/src/src/nssinfo.h
Normal file
@ -0,0 +1,233 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
* 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*/
|
||||
@ -0,0 +1,72 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
* 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;
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
* 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*/
|
||||
215
qca/nss-userspace-oss/nssinfo/src/src/nssinfo_ethrx.c
Normal file
215
qca/nss-userspace-oss/nssinfo/src/src/nssinfo_ethrx.c
Normal file
@ -0,0 +1,215 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
* 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(ð_rx_lock);
|
||||
eth_rx_node = nodes[core][NSS_ETH_RX_INTERFACE];
|
||||
if (!eth_rx_node) {
|
||||
pthread_mutex_unlock(ð_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(ð_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(ð_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(ð_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(ð_rx_lock);
|
||||
return;
|
||||
}
|
||||
pthread_mutex_unlock(ð_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(ð_rx_lock);
|
||||
nodes[nss_stats->core_id][NSS_ETH_RX_INTERFACE] = eth_rx_node;
|
||||
pthread_mutex_unlock(ð_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(ð_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(ð_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(ð_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;
|
||||
}
|
||||
28
qca/nss-userspace-oss/nssinfo/src/src/nssinfo_ethrx.h
Normal file
28
qca/nss-userspace-oss/nssinfo/src/src/nssinfo_ethrx.h
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
* 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*/
|
||||
215
qca/nss-userspace-oss/nssinfo/src/src/nssinfo_ipv4.c
Normal file
215
qca/nss-userspace-oss/nssinfo/src/src/nssinfo_ipv4.c
Normal file
@ -0,0 +1,215 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
* 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;
|
||||
}
|
||||
30
qca/nss-userspace-oss/nssinfo/src/src/nssinfo_ipv4.h
Normal file
30
qca/nss-userspace-oss/nssinfo/src/src/nssinfo_ipv4.h
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
* 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*/
|
||||
212
qca/nss-userspace-oss/nssinfo/src/src/nssinfo_ipv6.c
Normal file
212
qca/nss-userspace-oss/nssinfo/src/src/nssinfo_ipv6.c
Normal file
@ -0,0 +1,212 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
* 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;
|
||||
}
|
||||
30
qca/nss-userspace-oss/nssinfo/src/src/nssinfo_ipv6.h
Normal file
30
qca/nss-userspace-oss/nssinfo/src/src/nssinfo_ipv6.h
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
* 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*/
|
||||
195
qca/nss-userspace-oss/nssinfo/src/src/nssinfo_lso_rx.c
Normal file
195
qca/nss-userspace-oss/nssinfo/src/src/nssinfo_lso_rx.c
Normal file
@ -0,0 +1,195 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
* 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;
|
||||
}
|
||||
28
qca/nss-userspace-oss/nssinfo/src/src/nssinfo_lso_rx.h
Normal file
28
qca/nss-userspace-oss/nssinfo/src/src/nssinfo_lso_rx.h
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
* 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*/
|
||||
191
qca/nss-userspace-oss/nssinfo/src/src/nssinfo_main.c
Normal file
191
qca/nss-userspace-oss/nssinfo/src/src/nssinfo_main.c
Normal file
@ -0,0 +1,191 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
* 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;
|
||||
}
|
||||
209
qca/nss-userspace-oss/nssinfo/src/src/nssinfo_n2h.c
Normal file
209
qca/nss-userspace-oss/nssinfo/src/src/nssinfo_n2h.c
Normal file
@ -0,0 +1,209 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
* 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;
|
||||
}
|
||||
28
qca/nss-userspace-oss/nssinfo/src/src/nssinfo_n2h.h
Normal file
28
qca/nss-userspace-oss/nssinfo/src/src/nssinfo_n2h.h
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
* 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*/
|
||||
Loading…
Reference in New Issue
Block a user