978 lines
34 KiB
Diff
978 lines
34 KiB
Diff
From 2cfaac4ec2a653af30d7368fbc1c2bdec4fa8bdf Mon Sep 17 00:00:00 2001
|
|
From: jiangheng <jiangheng14@huawei.com>
|
|
Date: Sun, 29 Sep 2024 14:41:19 +0800
|
|
Subject: [PATCH] add interrupt mode support
|
|
|
|
---
|
|
src/common/gazelle_dfx_msg.h | 10 +
|
|
src/lstack/core/lstack_cfg.c | 25 ++
|
|
src/lstack/core/lstack_dpdk.c | 27 +-
|
|
src/lstack/core/lstack_init.c | 5 +
|
|
src/lstack/core/lstack_interrupt.c | 346 ++++++++++++++++++++++++
|
|
src/lstack/core/lstack_protocol_stack.c | 24 +-
|
|
src/lstack/core/lstack_stack_stat.c | 6 +
|
|
src/lstack/core/lstack_thread_rpc.c | 10 +-
|
|
src/lstack/core/lstack_virtio.c | 9 +
|
|
src/lstack/include/lstack_cfg.h | 1 +
|
|
src/lstack/include/lstack_interrupt.h | 34 +++
|
|
src/lstack/include/lstack_thread_rpc.h | 12 +-
|
|
src/lstack/include/lstack_tx_cache.h | 1 +
|
|
src/lstack/include/lstack_virtio.h | 2 +-
|
|
src/lstack/netif/lstack_tx_cache.c | 27 +-
|
|
src/lstack/netif/lstack_vdev.c | 2 +
|
|
src/ltran/ltran_dfx.c | 34 +++
|
|
17 files changed, 559 insertions(+), 16 deletions(-)
|
|
create mode 100644 src/lstack/core/lstack_interrupt.c
|
|
create mode 100644 src/lstack/include/lstack_interrupt.h
|
|
|
|
diff --git a/src/common/gazelle_dfx_msg.h b/src/common/gazelle_dfx_msg.h
|
|
index 266c239..1a89e65 100644
|
|
--- a/src/common/gazelle_dfx_msg.h
|
|
+++ b/src/common/gazelle_dfx_msg.h
|
|
@@ -60,6 +60,7 @@ enum GAZELLE_STAT_MODE {
|
|
GAZELLE_STAT_LSTACK_SHOW_XSTATS,
|
|
GAZELLE_STAT_LSTACK_SHOW_AGGREGATE,
|
|
GAZELLE_STAT_LSTACK_SHOW_NIC_FEATURES,
|
|
+ GAZELLE_STAT_LSTACK_SHOW_INTR,
|
|
|
|
#ifdef GAZELLE_FAULT_INJECT_ENABLE
|
|
GAZELLE_STAT_FAULT_INJECT_SET,
|
|
@@ -345,6 +346,14 @@ struct nic_eth_features {
|
|
uint64_t tx_offload;
|
|
};
|
|
|
|
+struct interrupt_stats {
|
|
+ uint64_t virtio_user_event_cnt;
|
|
+ uint64_t nic_event_cnt;
|
|
+ uint64_t remote_event_cnt;
|
|
+ uint64_t local_event_cnt;
|
|
+ uint64_t timeout_event_cnt;
|
|
+};
|
|
+
|
|
struct gazelle_stack_dfx_data {
|
|
/* indicates whether the current message is the last */
|
|
uint32_t eof;
|
|
@@ -362,6 +371,7 @@ struct gazelle_stack_dfx_data {
|
|
struct nic_eth_xstats nic_xstats;
|
|
struct nic_eth_features nic_features;
|
|
struct gazelle_stat_lstack_proto proto_data;
|
|
+ struct interrupt_stats intr_stats;
|
|
|
|
#ifdef GAZELLE_FAULT_INJECT_ENABLE
|
|
struct gazelle_fault_inject_data inject;
|
|
diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c
|
|
index 659a2a7..f239b60 100644
|
|
--- a/src/lstack/core/lstack_cfg.c
|
|
+++ b/src/lstack/core/lstack_cfg.c
|
|
@@ -85,6 +85,7 @@ static int32_t parse_defaule_nonblock_mode(void);
|
|
static int32_t parse_rpc_msg_max(void);
|
|
static int32_t parse_send_cache_mode(void);
|
|
static int32_t parse_flow_bifurcation(void);
|
|
+static int32_t parse_stack_interrupt(void);
|
|
|
|
#define PARSE_ARG(_arg, _arg_string, _default_val, _min_val, _max_val, _ret) \
|
|
do { \
|
|
@@ -152,6 +153,7 @@ static struct config_vector_t g_config_tbl[] = {
|
|
{ "rpc_msg_max", parse_rpc_msg_max },
|
|
{ "send_cache_mode", parse_send_cache_mode },
|
|
{ "flow_bifurcation", parse_flow_bifurcation},
|
|
+ { "stack_interrupt", parse_stack_interrupt},
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
@@ -1383,3 +1385,26 @@ static int32_t parse_flow_bifurcation(void)
|
|
PARSE_ARG(g_config_params.flow_bifurcation, "flow_bifurcation", 0, 0, 1, ret);
|
|
return ret;
|
|
}
|
|
+
|
|
+static int32_t parse_stack_interrupt(void)
|
|
+{
|
|
+ int32_t ret;
|
|
+ PARSE_ARG(g_config_params.stack_interrupt, "stack_interrupt", false, false, true, ret);
|
|
+ if (ret != 0) {
|
|
+ LSTACK_PRE_LOG(LSTACK_ERR, "cfg: invalid enable intr value %d. only support 0 or 1\n", \
|
|
+ g_config_params.stack_interrupt);
|
|
+ }
|
|
+
|
|
+ if (g_config_params.stack_interrupt == true) {
|
|
+ if (g_config_params.stack_mode_rtc == true) {
|
|
+ LSTACK_PRE_LOG(LSTACK_ERR, "rtc mode not support interrupt mode now.\n");
|
|
+ return -1;
|
|
+ }
|
|
+ if (g_config_params.bond_mode >= 0) {
|
|
+ LSTACK_PRE_LOG(LSTACK_ERR, "bond mode not support interrupt mode.\n");
|
|
+ return -1;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+}
|
|
diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c
|
|
index 1fe0f0a..530332b 100644
|
|
--- a/src/lstack/core/lstack_dpdk.c
|
|
+++ b/src/lstack/core/lstack_dpdk.c
|
|
@@ -258,8 +258,8 @@ struct rte_mempool *create_mempool(const char *name, uint32_t count, uint32_t si
|
|
|
|
int32_t create_shared_ring(struct protocol_stack *stack)
|
|
{
|
|
- rpc_queue_init(&stack->rpc_queue);
|
|
- rpc_queue_init(&stack->dfx_rpc_queue);
|
|
+ rpc_queue_init(&stack->rpc_queue, stack->queue_id);
|
|
+ rpc_queue_init(&stack->dfx_rpc_queue, stack->queue_id);
|
|
|
|
if (use_ltran()) {
|
|
stack->rx_ring = gazelle_ring_create_fast("RING_RX", VDEV_RX_QUEUE_SZ, RING_F_SP_ENQ | RING_F_SC_DEQ);
|
|
@@ -439,6 +439,7 @@ static int eth_params_init(struct eth_params *eth_params, uint16_t port_id, uint
|
|
eth_params->conf.rxmode.mq_mode = RTE_ETH_MQ_RX_NONE;
|
|
/* used for tcp port alloc */
|
|
eth_params->reta_mask = dev_info.reta_size - 1;
|
|
+ eth_params->conf.intr_conf.rxq = get_global_cfg_params()->stack_interrupt;
|
|
|
|
eth_params_checksum(ð_params->conf, &dev_info);
|
|
|
|
@@ -630,10 +631,11 @@ static int32_t dpdk_ethdev_setup(const struct eth_params *eth_params, uint16_t i
|
|
|
|
int32_t dpdk_ethdev_start(void)
|
|
{
|
|
+ int i;
|
|
int32_t ret;
|
|
const struct protocol_stack_group *stack_group = get_protocol_stack_group();
|
|
|
|
- for (int32_t i = 0; i < get_global_cfg_params()->tot_queue_num; i++) {
|
|
+ for (i = 0; i < get_global_cfg_params()->tot_queue_num; i++) {
|
|
ret = dpdk_ethdev_setup(stack_group->eth_params, i);
|
|
if (ret < 0) {
|
|
LSTACK_LOG(ERR, LSTACK, "dpdk_ethdev_setup fail queueid=%d, ret=%d\n", i, ret);
|
|
@@ -647,6 +649,14 @@ int32_t dpdk_ethdev_start(void)
|
|
return ret;
|
|
}
|
|
|
|
+ /* after rte_eth_dev_start */
|
|
+ for (i = 0; i < get_global_cfg_params()->tot_queue_num; i++) {
|
|
+ struct intr_dpdk_event_args intr_arg;
|
|
+ intr_arg.port_id = stack_group->eth_params->port_id;
|
|
+ intr_arg.queue_id = i;
|
|
+ intr_register(i, INTR_DPDK_EVENT, &intr_arg);
|
|
+ }
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
@@ -799,10 +809,21 @@ int init_dpdk_ethdev(void)
|
|
}
|
|
port_id = rte_eth_bond_primary_get(get_protocol_stack_group()->port_id);
|
|
} else {
|
|
+ struct rte_eth_dev_info dev_info;
|
|
port_id = ethdev_port_id(cfg->mac_addr);
|
|
if (port_id < 0) {
|
|
return -1;
|
|
}
|
|
+
|
|
+ if (rte_eth_dev_info_get(port_id, &dev_info) < 0) {
|
|
+ return -1;
|
|
+ }
|
|
+ if (strcmp(dev_info.driver_name, "net_hinic") == 0 &&
|
|
+ get_global_cfg_params()->stack_interrupt == true) {
|
|
+ LSTACK_LOG(ERR, LSTACK, "hinic not support interrupt mode\n");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
ret = dpdk_ethdev_init(port_id);
|
|
if (ret != 0) {
|
|
LSTACK_LOG(ERR, LSTACK, "dpdk_ethdev_init failed, port id=%d\n", port_id);
|
|
diff --git a/src/lstack/core/lstack_init.c b/src/lstack/core/lstack_init.c
|
|
index 37264a1..5e405ee 100644
|
|
--- a/src/lstack/core/lstack_init.c
|
|
+++ b/src/lstack/core/lstack_init.c
|
|
@@ -45,6 +45,7 @@
|
|
#include "lstack_preload.h"
|
|
#include "lstack_wrap.h"
|
|
#include "lstack_flow.h"
|
|
+#include "lstack_interrupt.h"
|
|
|
|
static void check_process_start(void)
|
|
{
|
|
@@ -289,6 +290,10 @@ __attribute__((constructor)) void gazelle_network_init(void)
|
|
LSTACK_EXIT(1, "stack_group_init failed\n");
|
|
}
|
|
|
|
+ if (intr_init() < 0) {
|
|
+ LSTACK_EXIT(1, "intr init failed\n");
|
|
+ }
|
|
+
|
|
if (!use_ltran()) {
|
|
if (init_dpdk_ethdev() != 0) {
|
|
LSTACK_EXIT(1, "init_dpdk_ethdev failed\n");
|
|
diff --git a/src/lstack/core/lstack_interrupt.c b/src/lstack/core/lstack_interrupt.c
|
|
new file mode 100644
|
|
index 0000000..26823cd
|
|
--- /dev/null
|
|
+++ b/src/lstack/core/lstack_interrupt.c
|
|
@@ -0,0 +1,346 @@
|
|
+/*
|
|
+* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved.
|
|
+* gazelle is licensed under the Mulan PSL v2.
|
|
+* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
|
+* You may obtain a copy of Mulan PSL v2 at:
|
|
+* http://license.coscl.org.cn/MulanPSL2
|
|
+* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
|
|
+* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
|
|
+* PURPOSE.
|
|
+* See the Mulan PSL v2 for more details.
|
|
+*/
|
|
+
|
|
+#include <sys/un.h>
|
|
+#include <sys/socket.h>
|
|
+#include <sys/epoll.h>
|
|
+#include <sys/eventfd.h>
|
|
+#include <securec.h>
|
|
+
|
|
+#include <rte_interrupts.h>
|
|
+#include <rte_ethdev.h>
|
|
+
|
|
+#include <lwip/lwipgz_posix_api.h>
|
|
+#include <lwip/lwipopts.h>
|
|
+#include <lwip/arch/sys_arch.h>
|
|
+
|
|
+#include "common/dpdk_common.h"
|
|
+#include "common/gazelle_opt.h"
|
|
+#include "common/gazelle_dfx_msg.h"
|
|
+#include "lstack_log.h"
|
|
+#include "lstack_cfg.h"
|
|
+#include "lstack_interrupt.h"
|
|
+
|
|
+#define INTR_MAX_EVENT_NUM 8
|
|
+
|
|
+struct intr_dpdk_event {
|
|
+ int rte_epfd;
|
|
+#define INTR_PORT_NUM 2
|
|
+#define INTR_INVALID_PORT 65535
|
|
+ uint16_t port_id[INTR_PORT_NUM]; /* 0: nic port id, 1: virtio_user port id */
|
|
+ uint16_t queue_id[INTR_PORT_NUM];
|
|
+};
|
|
+
|
|
+struct intr_local_event {
|
|
+ bool (*get_event) (uint16_t stack_id);
|
|
+};
|
|
+
|
|
+struct intr_remote_event {
|
|
+ int event_fd;
|
|
+};
|
|
+
|
|
+struct intr_policy {
|
|
+#define INTR_LOOP_TIMES 5
|
|
+ uint8_t no_event_cnt;
|
|
+};
|
|
+
|
|
+struct intr_config {
|
|
+ int epoll_fd; /* used for epoll */
|
|
+ uint16_t stack_id;
|
|
+ bool in_wait;
|
|
+
|
|
+ struct intr_dpdk_event dpdk_event;
|
|
+ struct intr_local_event local_event;
|
|
+ struct intr_remote_event remote_event;
|
|
+
|
|
+ struct intr_policy policy;
|
|
+ struct interrupt_stats stats;
|
|
+};
|
|
+
|
|
+static struct intr_config g_intr_configs[PROTOCOL_STACK_MAX] = {0};
|
|
+
|
|
+static inline struct intr_config *intr_config_get(uint16_t stack_id)
|
|
+{
|
|
+ return &g_intr_configs[stack_id];
|
|
+}
|
|
+
|
|
+int intr_init(void)
|
|
+{
|
|
+ int stack_id;
|
|
+ struct cfg_params *cfg = get_global_cfg_params();
|
|
+ if (!cfg->stack_interrupt) {
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ for (stack_id = 0; stack_id < cfg->num_queue; stack_id++) {
|
|
+ struct intr_config *intr_config = intr_config_get(stack_id);
|
|
+ intr_config->epoll_fd = posix_api->epoll_create_fn(1);
|
|
+ if (intr_config->epoll_fd < 0) {
|
|
+ LSTACK_LOG(ERR, LSTACK, "epoll create fd fialed, errno is %d\n", errno);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ for (int i = 0; i < INTR_PORT_NUM; i++) {
|
|
+ intr_config->dpdk_event.port_id[i] = INTR_INVALID_PORT;
|
|
+ }
|
|
+
|
|
+ if (intr_register(stack_id, INTR_REMOTE_EVENT, NULL) < 0) {
|
|
+ LSTACK_LOG(ERR, LSTACK, "register intr failed\n");
|
|
+ return -1;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static inline int add_fd_to_epoll(int fd, int epoll_fd)
|
|
+{
|
|
+ struct epoll_event event ;
|
|
+ event.data.fd = fd ;
|
|
+ event.events = EPOLLIN | EPOLLPRI | EPOLLRDHUP | EPOLLHUP ;
|
|
+ int ret = posix_api->epoll_ctl_fn(epoll_fd, EPOLL_CTL_ADD, fd, &event);
|
|
+ if (ret < 0) {
|
|
+ LSTACK_LOG(ERR, LSTACK, "add fd %d to epoll fd %d failed errno:%d ret=%d.\n",
|
|
+ fd, epoll_fd, errno, ret);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ return ret ;
|
|
+}
|
|
+
|
|
+static inline int intr_local_event_register(struct intr_config *config, void *priv)
|
|
+{
|
|
+ config->local_event.get_event = priv;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int intr_dpdk_event_register(struct intr_config *config, void *priv)
|
|
+{
|
|
+ struct intr_dpdk_event_args *arg = priv;
|
|
+ int i;
|
|
+
|
|
+ if (arg == NULL) {
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ if (config->dpdk_event.rte_epfd <= 0) {
|
|
+ config->dpdk_event.rte_epfd = posix_api->epoll_create_fn(1);
|
|
+ if (config->dpdk_event.rte_epfd < 0) {
|
|
+ LSTACK_LOG(ERR, LSTACK, "epoll create fd fialed, errno is %d\n", errno);
|
|
+ return -1;
|
|
+ }
|
|
+ if (add_fd_to_epoll(config->dpdk_event.rte_epfd, config->epoll_fd) < 0) {
|
|
+ return -1;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < INTR_PORT_NUM; i++) {
|
|
+ if (config->dpdk_event.port_id[i] == INTR_INVALID_PORT) {
|
|
+ config->dpdk_event.port_id[i] = arg->port_id;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ config->dpdk_event.queue_id[i] = arg->queue_id;
|
|
+
|
|
+ int data = ((arg->port_id) << CHAR_BIT) | arg->queue_id;
|
|
+ if (rte_eth_dev_rx_intr_ctl_q(arg->port_id, arg->queue_id, config->dpdk_event.rte_epfd,
|
|
+ RTE_INTR_EVENT_ADD, (void *)((uintptr_t)data)) < 0) {
|
|
+ LSTACK_LOG(ERR, LSTACK, "rte_eth_dev_rx_intr_ctl_q failed, port(%d), queue(%d)\n",
|
|
+ arg->port_id, arg->queue_id);
|
|
+ return -1;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int intr_remote_event_register(struct intr_config *config, void *priv)
|
|
+{
|
|
+ struct intr_remote_event *remote_event = &config->remote_event;
|
|
+ if (remote_event->event_fd > 0) {
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ remote_event->event_fd = posix_api->eventfd_fn(0, 0);
|
|
+ if (remote_event->event_fd < 0) {
|
|
+ LSTACK_LOG(ERR, LSTACK, "event fd create failed\n");
|
|
+ return -1;
|
|
+ }
|
|
+ return add_fd_to_epoll(remote_event->event_fd, config->epoll_fd);
|
|
+}
|
|
+
|
|
+int intr_register(uint16_t stack_id, enum intr_type type, void *priv)
|
|
+{
|
|
+ struct cfg_params *cfg = get_global_cfg_params();
|
|
+ if (!cfg->stack_interrupt) {
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ struct intr_config *config = intr_config_get(stack_id);
|
|
+ switch (type) {
|
|
+ case INTR_DPDK_EVENT:
|
|
+ return intr_dpdk_event_register(config, priv);
|
|
+ case INTR_REMOTE_EVENT:
|
|
+ return intr_remote_event_register(config, priv);
|
|
+ case INTR_LOCAL_EVENT:
|
|
+ return intr_local_event_register(config, priv);
|
|
+ default:
|
|
+ return -1;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static inline void intr_remote_event_enable(struct intr_config *config)
|
|
+{
|
|
+ eventfd_t eventfd_num = 1;
|
|
+ if (__atomic_load_n(&config->in_wait, __ATOMIC_ACQUIRE)) {
|
|
+ posix_api->write_fn(config->remote_event.event_fd, &eventfd_num, sizeof(eventfd_t));
|
|
+ }
|
|
+}
|
|
+
|
|
+static inline void intr_remote_event_disable(struct intr_config *config)
|
|
+{
|
|
+ eventfd_t read_num;
|
|
+ posix_api->read_fn(config->remote_event.event_fd, &read_num, sizeof(eventfd_t));
|
|
+}
|
|
+
|
|
+static inline bool intr_local_event(struct intr_config *config)
|
|
+{
|
|
+ return config->local_event.get_event(config->stack_id);
|
|
+}
|
|
+
|
|
+void intr_wakeup(uint16_t stack_id, enum intr_type type)
|
|
+{
|
|
+ if (!get_global_cfg_params()->stack_interrupt) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ struct intr_config *config = intr_config_get(stack_id);
|
|
+ switch (type) {
|
|
+ case INTR_REMOTE_EVENT:
|
|
+ intr_remote_event_enable(config);
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+}
|
|
+
|
|
+static inline void intr_dpdk_event_enable(struct intr_config *config)
|
|
+{
|
|
+ int i;
|
|
+ int ret = 0;
|
|
+ struct intr_dpdk_event *dpdk_event = &config->dpdk_event;
|
|
+
|
|
+ for (i = 0; i < INTR_PORT_NUM; i++) {
|
|
+ if (dpdk_event->port_id[i] != INTR_INVALID_PORT) {
|
|
+ ret = rte_eth_dev_rx_intr_enable(dpdk_event->port_id[i], dpdk_event->queue_id[i]);
|
|
+ if (ret != 0) {
|
|
+ LSTACK_LOG(ERR, LSTACK, "port(%d) queue(%d) enable interrupt failed\n",
|
|
+ dpdk_event->port_id[i], dpdk_event->queue_id[i]);
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+static inline void intr_dpdk_event_disable(struct intr_config *config)
|
|
+{
|
|
+ int i, n;
|
|
+ void *data;
|
|
+ uint16_t port_id;
|
|
+ uint16_t queue_id;
|
|
+ struct intr_dpdk_event *dpdk_event = &config->dpdk_event;
|
|
+ struct rte_epoll_event event[INTR_MAX_EVENT_NUM];
|
|
+
|
|
+ n = rte_epoll_wait(dpdk_event->rte_epfd, event, INTR_MAX_EVENT_NUM, 1);
|
|
+ for (i = 0; i < n; i++) {
|
|
+ data = event[i].epdata.data;
|
|
+ port_id = ((uintptr_t)data) >> CHAR_BIT;
|
|
+ queue_id = ((uintptr_t)data) & RTE_LEN2MASK(CHAR_BIT, uint8_t);
|
|
+
|
|
+ rte_eth_dev_rx_intr_disable(port_id, queue_id);
|
|
+
|
|
+ if (port_id == dpdk_event->port_id[0]) {
|
|
+ config->stats.nic_event_cnt++;
|
|
+ } else {
|
|
+ config->stats.virtio_user_event_cnt++;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+static inline void intr_policy_clear(struct intr_config *config)
|
|
+{
|
|
+ config->policy.no_event_cnt = 0;
|
|
+}
|
|
+
|
|
+static inline bool intr_policy(struct intr_config *config)
|
|
+{
|
|
+ if (config->policy.no_event_cnt++ < INTR_LOOP_TIMES) {
|
|
+ return true;
|
|
+ }
|
|
+ config->policy.no_event_cnt = 0;
|
|
+ return false;
|
|
+}
|
|
+
|
|
+static inline void intr_block(uint16_t stack_id, uint32_t timeout)
|
|
+{
|
|
+ struct epoll_event events[INTR_MAX_EVENT_NUM];
|
|
+ struct intr_config *intr_config = intr_config_get(stack_id);
|
|
+
|
|
+ /* in_wait need in here to avoid competion problem with remote event */
|
|
+ __atomic_store_n(&intr_config->in_wait, true, __ATOMIC_RELEASE);
|
|
+ if (intr_local_event(intr_config)) {
|
|
+ intr_config->stats.local_event_cnt++;
|
|
+ __atomic_store_n(&intr_config->in_wait, false, __ATOMIC_RELEASE);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ intr_dpdk_event_enable(intr_config);
|
|
+
|
|
+ int32_t event_cnt = posix_api->epoll_wait_fn(intr_config->epoll_fd, events, INTR_MAX_EVENT_NUM, timeout);
|
|
+ __atomic_store_n(&intr_config->in_wait, false, __ATOMIC_RELEASE);
|
|
+ for (int i = 0; i < event_cnt; i++) {
|
|
+ if (events[i].data.fd == intr_config->dpdk_event.rte_epfd) {
|
|
+ intr_dpdk_event_disable(intr_config);
|
|
+ } else if (events[i].data.fd == intr_config->remote_event.event_fd) {
|
|
+ intr_remote_event_disable(intr_config);
|
|
+ intr_config->stats.remote_event_cnt++;
|
|
+ } else {
|
|
+ LSTACK_LOG(ERR, LSTACK, "unknow fd have event.\n");
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (event_cnt < 0) {
|
|
+ intr_config->stats.timeout_event_cnt++;
|
|
+ }
|
|
+}
|
|
+
|
|
+void intr_wait(uint16_t stack_id, uint32_t timeout)
|
|
+{
|
|
+ struct intr_config *intr_config = intr_config_get(stack_id);
|
|
+
|
|
+ if (intr_policy(intr_config)) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ intr_block(stack_id, timeout);
|
|
+
|
|
+ intr_policy_clear(intr_config);
|
|
+}
|
|
+
|
|
+int intr_stats_get(uint16_t stack_id, void *ptr, int len)
|
|
+{
|
|
+ struct intr_config *config = intr_config_get(stack_id);
|
|
+ if (len < sizeof(struct interrupt_stats)) {
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ return memcpy_s(ptr, len, &config->stats, sizeof(struct interrupt_stats));
|
|
+}
|
|
diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c
|
|
index d03b744..e412c3b 100644
|
|
--- a/src/lstack/core/lstack_protocol_stack.c
|
|
+++ b/src/lstack/core/lstack_protocol_stack.c
|
|
@@ -34,6 +34,8 @@
|
|
#include "lstack_virtio.h"
|
|
#include "lstack_protocol_stack.h"
|
|
|
|
+#include "lstack_interrupt.h"
|
|
+
|
|
#if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0)
|
|
#include <rte_kni.h>
|
|
#endif
|
|
@@ -480,13 +482,18 @@ int stack_polling(unsigned wakeup_tick)
|
|
uint32_t rpc_number = cfg->rpc_number;
|
|
uint32_t read_connect_number = cfg->read_connect_number;
|
|
struct protocol_stack *stack = get_protocol_stack();
|
|
+ uint32_t timeout;
|
|
|
|
/* 2: one dfx consumes two rpc */
|
|
rpc_poll_msg(&stack->dfx_rpc_queue, 2);
|
|
force_quit = rpc_poll_msg(&stack->rpc_queue, rpc_number);
|
|
|
|
eth_dev_poll();
|
|
- sys_timer_run();
|
|
+ timeout = sys_timer_run();
|
|
+ if (cfg->stack_interrupt) {
|
|
+ intr_wait(stack->stack_idx, timeout);
|
|
+ }
|
|
+
|
|
if (cfg->low_power_mod != 0) {
|
|
low_power_idling(stack);
|
|
}
|
|
@@ -496,6 +503,7 @@ int stack_polling(unsigned wakeup_tick)
|
|
}
|
|
|
|
do_lwip_read_recvlist(stack, read_connect_number);
|
|
+
|
|
if ((wakeup_tick & 0xf) == 0) {
|
|
wakeup_stack_epoll(stack);
|
|
if (get_global_cfg_params()->send_cache_mode) {
|
|
@@ -533,6 +541,19 @@ int stack_polling(unsigned wakeup_tick)
|
|
return force_quit;
|
|
}
|
|
|
|
+static bool stack_local_event_get(uint16_t stack_id)
|
|
+{
|
|
+ struct protocol_stack *stack = g_stack_group.stacks[stack_id];
|
|
+ if (!lockless_queue_empty(&stack->dfx_rpc_queue.queue) ||
|
|
+ !lockless_queue_empty(&stack->rpc_queue.queue) ||
|
|
+ !list_head_empty(&stack->recv_list) ||
|
|
+ !list_head_empty(&stack->wakeup_list) ||
|
|
+ tx_cache_count(stack->queue_id)) {
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+}
|
|
+
|
|
static void* gazelle_stack_thread(void *arg)
|
|
{
|
|
struct thread_params *t_params = (struct thread_params*) arg;
|
|
@@ -541,6 +562,7 @@ static void* gazelle_stack_thread(void *arg)
|
|
unsigned wakeup_tick = 0;
|
|
|
|
stack = stack_thread_init(arg);
|
|
+ intr_register(stack->stack_idx, INTR_LOCAL_EVENT, stack_local_event_get);
|
|
free(arg);
|
|
if (stack == NULL) {
|
|
LSTACK_LOG(ERR, LSTACK, "stack_thread_init failed queue_id=%hu\n", queue_id);
|
|
diff --git a/src/lstack/core/lstack_stack_stat.c b/src/lstack/core/lstack_stack_stat.c
|
|
index b6619f6..8efa5ab 100644
|
|
--- a/src/lstack/core/lstack_stack_stat.c
|
|
+++ b/src/lstack/core/lstack_stack_stat.c
|
|
@@ -325,6 +325,12 @@ static void get_stack_dfx_data(struct gazelle_stack_dfx_data *dfx, struct protoc
|
|
LSTACK_LOG(ERR, LSTACK, "memcpy_s err ret=%d \n", ret);
|
|
}
|
|
break;
|
|
+ case GAZELLE_STAT_LSTACK_SHOW_INTR:
|
|
+ ret = intr_stats_get(stack->stack_idx, &dfx->data.intr_stats, sizeof(dfx->data.intr_stats));
|
|
+ if (ret != EOK) {
|
|
+ LSTACK_LOG(ERR, LSTACK, "memcpy_s err ret=%d \n", ret);
|
|
+ }
|
|
+ break;
|
|
case GAZELLE_STAT_LSTACK_SHOW_VIRTIO:
|
|
ret = memcpy_s(&dfx->data.virtio, sizeof(dfx->data.virtio), virtio_instance_get(),
|
|
sizeof(*(virtio_instance_get())));
|
|
diff --git a/src/lstack/core/lstack_thread_rpc.c b/src/lstack/core/lstack_thread_rpc.c
|
|
index b4a5953..7f77c12 100644
|
|
--- a/src/lstack/core/lstack_thread_rpc.c
|
|
+++ b/src/lstack/core/lstack_thread_rpc.c
|
|
@@ -100,7 +100,8 @@ __rte_always_inline
|
|
static void rpc_async_call(rpc_queue *queue, struct rpc_msg *msg)
|
|
{
|
|
msg->sync_flag = 0;
|
|
- lockless_queue_mpsc_push(queue, &msg->queue_node);
|
|
+ lockless_queue_mpsc_push(&queue->queue, &msg->queue_node);
|
|
+ intr_wakeup(queue->queue_id, INTR_REMOTE_EVENT);
|
|
}
|
|
|
|
__rte_always_inline
|
|
@@ -111,7 +112,8 @@ static int rpc_sync_call(rpc_queue *queue, struct rpc_msg *msg)
|
|
pthread_spin_trylock(&msg->lock);
|
|
|
|
msg->sync_flag = 1;
|
|
- lockless_queue_mpsc_push(queue, &msg->queue_node);
|
|
+ lockless_queue_mpsc_push(&queue->queue, &msg->queue_node);
|
|
+ intr_wakeup(queue->queue_id, INTR_REMOTE_EVENT);
|
|
|
|
// waiting stack unlock
|
|
pthread_spin_lock(&msg->lock);
|
|
@@ -123,7 +125,7 @@ static int rpc_sync_call(rpc_queue *queue, struct rpc_msg *msg)
|
|
|
|
int rpc_msgcnt(rpc_queue *queue)
|
|
{
|
|
- return lockless_queue_count(queue);
|
|
+ return lockless_queue_count(&queue->queue);
|
|
}
|
|
|
|
static struct rpc_msg *rpc_msg_alloc_except(rpc_func_t func)
|
|
@@ -159,7 +161,7 @@ int rpc_poll_msg(rpc_queue *queue, int max_num)
|
|
struct rpc_msg *msg;
|
|
|
|
while (max_num--) {
|
|
- lockless_queue_node *node = lockless_queue_mpsc_pop(queue);
|
|
+ lockless_queue_node *node = lockless_queue_mpsc_pop(&queue->queue);
|
|
if (node == NULL) {
|
|
break;
|
|
}
|
|
diff --git a/src/lstack/core/lstack_virtio.c b/src/lstack/core/lstack_virtio.c
|
|
index fefb06d..75a23f2 100644
|
|
--- a/src/lstack/core/lstack_virtio.c
|
|
+++ b/src/lstack/core/lstack_virtio.c
|
|
@@ -20,6 +20,7 @@
|
|
#include "lstack_cfg.h"
|
|
#include "lstack_log.h"
|
|
#include "lstack_port_map.h"
|
|
+#include "lstack_interrupt.h"
|
|
#include "lstack_virtio.h"
|
|
#include "securec.h"
|
|
|
|
@@ -274,6 +275,7 @@ static int virtio_port_init(uint16_t port)
|
|
return retval;
|
|
}
|
|
|
|
+ port_conf.intr_conf.rxq = get_global_cfg_params()->stack_interrupt;
|
|
retval = rte_eth_dev_configure(port, rx_queue_num, tx_queue_num, &port_conf);
|
|
if (retval != 0) {
|
|
LSTACK_LOG(ERR, LSTACK, "rte_eth_dev_configure failed retval=%d\n", retval);
|
|
@@ -297,6 +299,13 @@ static int virtio_port_init(uint16_t port)
|
|
LSTACK_LOG(ERR, LSTACK, "rte_eth_rx_queue_setup failed (queue %u) retval=%d \n", q, retval);
|
|
return retval;
|
|
}
|
|
+
|
|
+ if (port_conf.intr_conf.rxq) {
|
|
+ struct intr_dpdk_event_args intr_arg;
|
|
+ intr_arg.port_id = port;
|
|
+ intr_arg.queue_id = q;
|
|
+ intr_register(q, INTR_DPDK_EVENT, &intr_arg);
|
|
+ }
|
|
}
|
|
return 0;
|
|
}
|
|
diff --git a/src/lstack/include/lstack_cfg.h b/src/lstack/include/lstack_cfg.h
|
|
index 5e2d6fc..071492d 100644
|
|
--- a/src/lstack/include/lstack_cfg.h
|
|
+++ b/src/lstack/include/lstack_cfg.h
|
|
@@ -118,6 +118,7 @@ struct cfg_params {
|
|
|
|
bool stack_mode_rtc;
|
|
bool listen_shadow; // true:listen in all stack thread. false:listen in one stack thread.
|
|
+ bool stack_interrupt;
|
|
|
|
uint32_t read_connect_number;
|
|
uint32_t nic_read_number;
|
|
diff --git a/src/lstack/include/lstack_interrupt.h b/src/lstack/include/lstack_interrupt.h
|
|
new file mode 100644
|
|
index 0000000..1be7d07
|
|
--- /dev/null
|
|
+++ b/src/lstack/include/lstack_interrupt.h
|
|
@@ -0,0 +1,34 @@
|
|
+/*
|
|
+* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved.
|
|
+* gazelle is licensed under the Mulan PSL v2.
|
|
+* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
|
+* You may obtain a copy of Mulan PSL v2 at:
|
|
+* http://license.coscl.org.cn/MulanPSL2
|
|
+* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
|
|
+* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
|
|
+* PURPOSE.
|
|
+* See the Mulan PSL v2 for more details.
|
|
+*/
|
|
+
|
|
+#ifndef __LSTACK_INTERRUPT_H__
|
|
+#define __LSTACK_INTERRUPT_H__
|
|
+
|
|
+enum intr_type {
|
|
+ INTR_DPDK_EVENT = 0,
|
|
+ INTR_LOCAL_EVENT,
|
|
+ INTR_REMOTE_EVENT,
|
|
+};
|
|
+
|
|
+struct intr_dpdk_event_args {
|
|
+ uint16_t port_id;
|
|
+ uint16_t queue_id;
|
|
+};
|
|
+
|
|
+int intr_init(void);
|
|
+int intr_register(uint16_t stack_id, enum intr_type type, void *priv);
|
|
+void intr_wakeup(uint16_t stack_id, enum intr_type type);
|
|
+void intr_wait(uint16_t stack_id, uint32_t timeout);
|
|
+int intr_stats_get(uint16_t stack_id, void *ptr, int len);
|
|
+
|
|
+#endif
|
|
+
|
|
diff --git a/src/lstack/include/lstack_thread_rpc.h b/src/lstack/include/lstack_thread_rpc.h
|
|
index 6f8e03e..c284d29 100644
|
|
--- a/src/lstack/include/lstack_thread_rpc.h
|
|
+++ b/src/lstack/include/lstack_thread_rpc.h
|
|
@@ -17,6 +17,7 @@
|
|
#include <rte_mempool.h>
|
|
|
|
#include "lstack_lockless_queue.h"
|
|
+#include "lstack_interrupt.h"
|
|
|
|
#define MSG_ARG_0 (0)
|
|
#define MSG_ARG_1 (1)
|
|
@@ -25,7 +26,11 @@
|
|
#define MSG_ARG_4 (4)
|
|
#define RPM_MSG_ARG_SIZE (5)
|
|
|
|
-typedef struct lockless_queue rpc_queue;
|
|
+typedef struct rpc_queue rpc_queue;
|
|
+struct rpc_queue {
|
|
+ struct lockless_queue queue;
|
|
+ uint16_t queue_id;
|
|
+};
|
|
|
|
struct rpc_stats {
|
|
uint16_t call_null;
|
|
@@ -60,9 +65,10 @@ struct rpc_msg {
|
|
lockless_queue_node queue_node;
|
|
};
|
|
|
|
-static inline void rpc_queue_init(rpc_queue *queue)
|
|
+static inline void rpc_queue_init(rpc_queue *queue, uint16_t queue_id)
|
|
{
|
|
- lockless_queue_init(queue);
|
|
+ lockless_queue_init(&queue->queue);
|
|
+ queue->queue_id = queue_id;
|
|
}
|
|
struct rpc_stats *rpc_stats_get(void);
|
|
int rpc_msgcnt(rpc_queue *queue);
|
|
diff --git a/src/lstack/include/lstack_tx_cache.h b/src/lstack/include/lstack_tx_cache.h
|
|
index 04e9e35..ccd9c17 100644
|
|
--- a/src/lstack/include/lstack_tx_cache.h
|
|
+++ b/src/lstack/include/lstack_tx_cache.h
|
|
@@ -15,5 +15,6 @@
|
|
|
|
int tx_cache_init(uint16_t queue_id, void *priv, struct lstack_dev_ops *dev_ops);
|
|
int tx_cache_send(uint16_t queue_id);
|
|
+int tx_cache_count(uint16_t queue_id);
|
|
|
|
#endif /* _LSTACK_TX_CACHE_H_ */
|
|
diff --git a/src/lstack/include/lstack_virtio.h b/src/lstack/include/lstack_virtio.h
|
|
index 5298dbe..745c86b 100644
|
|
--- a/src/lstack/include/lstack_virtio.h
|
|
+++ b/src/lstack/include/lstack_virtio.h
|
|
@@ -50,4 +50,4 @@ int virtio_port_create(int lstack_net_port);
|
|
|
|
struct virtio_instance* virtio_instance_get(void);
|
|
bool virtio_distribute_pkg_to_kernel(uint16_t dst_port);
|
|
-#endif
|
|
\ No newline at end of file
|
|
+#endif
|
|
diff --git a/src/lstack/netif/lstack_tx_cache.c b/src/lstack/netif/lstack_tx_cache.c
|
|
index 9a48307..17d3c3b 100644
|
|
--- a/src/lstack/netif/lstack_tx_cache.c
|
|
+++ b/src/lstack/netif/lstack_tx_cache.c
|
|
@@ -58,22 +58,40 @@ int tx_cache_init(uint16_t queue_id, void *priv, struct lstack_dev_ops *dev_ops)
|
|
return 0;
|
|
}
|
|
|
|
+int tx_cache_count(uint16_t queue_id)
|
|
+{
|
|
+ struct tx_cache *tx_cache = g_tx_cache[queue_id];
|
|
+ if (tx_cache == NULL) {
|
|
+ return 0;
|
|
+ }
|
|
+ uint32_t start = tx_cache->send_start;
|
|
+ uint32_t end = tx_cache->send_end;
|
|
+ uint32_t count = (end - start) & TX_CACHE_MASK;
|
|
+ uint32_t capacity = TX_CACHE_MAX - 1;
|
|
+
|
|
+ return (count > capacity) ? capacity : count;
|
|
+}
|
|
+
|
|
int tx_cache_send(uint16_t queue_id)
|
|
{
|
|
+ uint32_t send_num;
|
|
+ uint32_t sent_pkts = 0;
|
|
+ uint32_t start;
|
|
+ uint32_t end;
|
|
+
|
|
struct tx_cache *tx_cache = g_tx_cache[queue_id];
|
|
if (tx_cache == NULL) {
|
|
LSTACK_LOG(ERR, LSTACK, "queue(%d) tx cache get failed\n", queue_id);
|
|
return 0;
|
|
}
|
|
|
|
- uint32_t send_num = tx_cache->send_end - tx_cache->send_start;
|
|
+ send_num = tx_cache_count(queue_id);
|
|
if (send_num == 0) {
|
|
return 0;
|
|
}
|
|
|
|
- uint32_t start = tx_cache->send_start & TX_CACHE_MASK;
|
|
- uint32_t end = tx_cache->send_end & TX_CACHE_MASK;
|
|
- uint32_t sent_pkts = 0;
|
|
+ start = tx_cache->send_start & TX_CACHE_MASK;
|
|
+ end = tx_cache->send_end & TX_CACHE_MASK;
|
|
if (start < end) {
|
|
sent_pkts = g_tx_cache_dev_ops.tx_xmit(tx_cache->priv, &tx_cache->send_pkts[start], send_num);
|
|
} else {
|
|
@@ -85,6 +103,7 @@ int tx_cache_send(uint16_t queue_id)
|
|
}
|
|
|
|
tx_cache->send_start += sent_pkts;
|
|
+
|
|
return sent_pkts;
|
|
}
|
|
|
|
diff --git a/src/lstack/netif/lstack_vdev.c b/src/lstack/netif/lstack_vdev.c
|
|
index e1a63a7..290046e 100644
|
|
--- a/src/lstack/netif/lstack_vdev.c
|
|
+++ b/src/lstack/netif/lstack_vdev.c
|
|
@@ -38,6 +38,8 @@
|
|
#include "lstack_port_map.h"
|
|
#include "lstack_virtio.h"
|
|
|
|
+#include "lstack_interrupt.h"
|
|
+
|
|
/* INUSE_TX_PKTS_WATERMARK < VDEV_RX_QUEUE_SZ;
|
|
* USE_RX_PKTS_WATERMARK < FREE_RX_QUEUE_SZ.
|
|
* less, means more available mbuf.
|
|
diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c
|
|
index 7fa117a..f6d1148 100644
|
|
--- a/src/ltran/ltran_dfx.c
|
|
+++ b/src/ltran/ltran_dfx.c
|
|
@@ -138,6 +138,7 @@ static void gazelle_print_lstack_xstats(void *buf, const struct gazelle_stat_msg
|
|
static void gazelle_print_lstack_aggregate(void *buf, const struct gazelle_stat_msg_request *req_msg);
|
|
static void gazelle_print_lstack_nic_features(void *buf, const struct gazelle_stat_msg_request *req_msg);
|
|
static void gazelle_print_lstack_stat_proto(void *buf, const struct gazelle_stat_msg_request *req_msg);
|
|
+static void gazelle_print_lstack_stat_intr(void *buf, const struct gazelle_stat_msg_request *req_msg);
|
|
|
|
#ifdef GAZELLE_FAULT_INJECT_ENABLE
|
|
static void gazelle_print_fault_inject_set_status(void *buf, const struct gazelle_stat_msg_request *req_msg);
|
|
@@ -172,6 +173,7 @@ static struct gazelle_dfx_list g_gazelle_dfx_tbl[] = {
|
|
{GAZELLE_STAT_LSTACK_SHOW_AGGREGATE, sizeof(struct gazelle_stack_dfx_data), gazelle_print_lstack_aggregate},
|
|
{GAZELLE_STAT_LSTACK_SHOW_NIC_FEATURES, sizeof(struct gazelle_stack_dfx_data), gazelle_print_lstack_nic_features},
|
|
{GAZELLE_STAT_LSTACK_SHOW_PROTOCOL, sizeof(struct gazelle_stack_dfx_data), gazelle_print_lstack_stat_proto},
|
|
+ {GAZELLE_STAT_LSTACK_SHOW_INTR, sizeof(struct gazelle_stack_dfx_data), gazelle_print_lstack_stat_intr},
|
|
|
|
#ifdef GAZELLE_FAULT_INJECT_ENABLE
|
|
{GAZELLE_STAT_FAULT_INJECT_SET, sizeof(struct gazelle_stack_dfx_data), gazelle_print_fault_inject_set_status},
|
|
@@ -1136,6 +1138,17 @@ static void gazelle_print_lstack_stat_proto_core(const struct gazelle_stack_dfx_
|
|
printf("rterr: %lu\n", proto->rterr);
|
|
}
|
|
|
|
+static void gazelle_print_lstack_stat_intr_core(const struct gazelle_stack_dfx_data *stat,
|
|
+ const struct interrupt_stats *intr_stats)
|
|
+{
|
|
+ printf("\n------ stack tid: %6u ------\n", stat->tid);
|
|
+ printf("nic_event_cnt: %lu\n", intr_stats->nic_event_cnt);
|
|
+ printf("virtio_user_event_cnt: %lu\n", intr_stats->virtio_user_event_cnt);
|
|
+ printf("local_event_cnt: %lu\n", intr_stats->local_event_cnt);
|
|
+ printf("remote_event_cnt: %lu\n", intr_stats->remote_event_cnt);
|
|
+ printf("timeout_event_cnt: %lu\n", intr_stats->timeout_event_cnt);
|
|
+}
|
|
+
|
|
static void gazelle_print_lstack_stat_snmp(void *buf, const struct gazelle_stat_msg_request *req_msg)
|
|
{
|
|
int32_t ret;
|
|
@@ -1155,6 +1168,25 @@ static void gazelle_print_lstack_stat_snmp(void *buf, const struct gazelle_stat_
|
|
} while (true);
|
|
}
|
|
|
|
+static void gazelle_print_lstack_stat_intr(void *buf, const struct gazelle_stat_msg_request *req_msg)
|
|
+{
|
|
+ int32_t ret;
|
|
+ struct gazelle_stack_dfx_data *stat = (struct gazelle_stack_dfx_data *)buf;
|
|
+ struct interrupt_stats *intr_stats = &stat->data.intr_stats;
|
|
+
|
|
+ printf("Statistics of lstack interrupt:\n");
|
|
+ do {
|
|
+ gazelle_print_lstack_stat_intr_core(stat, intr_stats);
|
|
+ if (stat->eof != 0) {
|
|
+ break;
|
|
+ }
|
|
+ ret = dfx_stat_read_from_ltran(buf, sizeof(struct gazelle_stack_dfx_data), req_msg->stat_mode);
|
|
+ if (ret != GAZELLE_OK) {
|
|
+ return;
|
|
+ }
|
|
+ } while (true);
|
|
+}
|
|
+
|
|
static void gazelle_print_lstack_stat_proto(void *buf, const struct gazelle_stat_msg_request *req_msg)
|
|
{
|
|
int32_t ret;
|
|
@@ -1579,6 +1611,8 @@ static int32_t parse_dfx_lstack_show_args(int32_t argc, char *argv[], struct gaz
|
|
req_msg[cmd_index++].stat_mode = GAZELLE_STAT_MODE_MAX;
|
|
} else if (strcmp(param, "snmp") == 0 || strcmp(param, "-s") == 0) {
|
|
req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LSTACK_SHOW_SNMP;
|
|
+ } else if (strcmp(param, "intr") == 0 || strcmp(param, "-I") == 0) {
|
|
+ req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LSTACK_SHOW_INTR;
|
|
} else if (strcmp(param, "virtio") == 0 || strcmp(param, "-v") == 0) {
|
|
req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LSTACK_SHOW_VIRTIO;
|
|
} else if (strcmp(param, "connect") == 0 || strcmp(param, "-c") == 0) {
|
|
--
|
|
2.33.0
|
|
|