diff --git a/0262-add-pingpong-dfx-support.patch b/0262-add-pingpong-dfx-support.patch new file mode 100644 index 0000000..f23a349 --- /dev/null +++ b/0262-add-pingpong-dfx-support.patch @@ -0,0 +1,67 @@ +From 8de32dd108ac0666aabf01aa68b017389a390b26 Mon Sep 17 00:00:00 2001 +From: jiangheng +Date: Fri, 27 Sep 2024 15:41:42 +0800 +Subject: [PATCH] add pingpong dfx support + +--- + src/common/gazelle_dfx_msg.h | 1 + + src/lstack/core/lstack_lwip.c | 1 + + src/ltran/ltran_dfx.c | 7 ++++--- + 3 files changed, 6 insertions(+), 3 deletions(-) + +diff --git a/src/common/gazelle_dfx_msg.h b/src/common/gazelle_dfx_msg.h +index 08f9df1..266c239 100644 +--- a/src/common/gazelle_dfx_msg.h ++++ b/src/common/gazelle_dfx_msg.h +@@ -281,6 +281,7 @@ struct gazelle_stat_lstack_conn_info { + uint32_t keep_idle; + uint32_t keep_intvl; + uint32_t keep_cnt; ++ uint8_t pingpong; + }; + + struct gazelle_stat_lstack_conn { +diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c +index 7677e46..2eb872c 100644 +--- a/src/lstack/core/lstack_lwip.c ++++ b/src/lstack/core/lstack_lwip.c +@@ -1257,6 +1257,7 @@ static void copy_pcb_to_conn(struct gazelle_stat_lstack_conn_info *conn, const s + conn->keep_idle = pcb->keep_idle; + conn->keep_intvl = pcb->keep_intvl; + conn->keep_cnt = pcb->keep_cnt; ++ conn->pingpong = tcp_in_pingpong(pcb); + + if (netconn != NULL) { + conn->fd = netconn->callback_arg.socket; +diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c +index fc30054..7fa117a 100644 +--- a/src/ltran/ltran_dfx.c ++++ b/src/ltran/ltran_dfx.c +@@ -1242,7 +1242,7 @@ static void gazelle_print_lstack_stat_conn(void *buf, const struct gazelle_stat_ + printf("No. Proto lwip_recv recv_ring in_send send_ring cwn rcv_wnd snd_wnd snd_buf snd_nxt" + " lastack rcv_nxt events epoll_ev evlist fd Local Address" + " Foreign Address State" +- " keep-alive keep-alive(idle,intvl,cnt)\n"); ++ " keep-alive keep-alive(idle,intvl,cnt) pingpong\n"); + uint32_t unread_pkts = 0; + uint32_t unsend_pkts = 0; + for (i = 0; i < conn->conn_num && i < GAZELLE_LSTACK_MAX_CONN; i++) { +@@ -1261,12 +1261,13 @@ static void gazelle_print_lstack_stat_conn(void *buf, const struct gazelle_stat_ + sprintf_s(str_laddr, sizeof(str_laddr), "%s:%hu", str_ip, conn_info->l_port); + sprintf_s(str_raddr, sizeof(str_raddr), "%s:%hu", str_rip, conn_info->r_port); + printf("%-6utcp %-10u%-10u%-8u%-10u%-9d%-9d%-10d%-10d%-15u%-15u%-15u%-10x%-10x%-7d%-7d" +- "%-52s %-52s %s %-5d %s\n", i, conn_info->recv_cnt, conn_info->recv_ring_cnt, conn_info->in_send, ++ "%-52s %-52s %s %-5d %s %d\n", ++ i, conn_info->recv_cnt, conn_info->recv_ring_cnt, conn_info->in_send, + conn_info->send_ring_cnt, conn_info->cwn, conn_info->rcv_wnd, conn_info->snd_wnd, + conn_info->snd_buf, conn_info->snd_nxt, conn_info->lastack, conn_info->rcv_nxt, conn_info->events, + conn_info->epoll_events, conn_info->eventlist, conn_info->fd, + str_laddr, str_raddr, tcp_state_to_str(conn_info->tcp_sub_state), +- conn_info->keepalive, keepalive_info_str); ++ conn_info->keepalive, keepalive_info_str, conn_info->pingpong); + } else if (conn_info->state == GAZELLE_LISTEN_LIST) { + inet_ntop(domain, lip, str_ip, sizeof(str_ip)); + sprintf_s(str_laddr, sizeof(str_laddr), "%s:%hu", str_ip, conn_info->l_port); +-- +2.33.0 + diff --git a/0263-add-interrupt-mode-support.patch b/0263-add-interrupt-mode-support.patch new file mode 100644 index 0000000..ce48934 --- /dev/null +++ b/0263-add-interrupt-mode-support.patch @@ -0,0 +1,977 @@ +From 2cfaac4ec2a653af30d7368fbc1c2bdec4fa8bdf Mon Sep 17 00:00:00 2001 +From: jiangheng +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 ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++#include ++ ++#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 + #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 + + #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 + diff --git a/0264-af_xdp-set-rlimit-unlimit-when-gazelle-init.patch b/0264-af_xdp-set-rlimit-unlimit-when-gazelle-init.patch new file mode 100644 index 0000000..79553f4 --- /dev/null +++ b/0264-af_xdp-set-rlimit-unlimit-when-gazelle-init.patch @@ -0,0 +1,57 @@ +From 7e6a5d97430f0d178c5e2b211c0c194fdea0c00a Mon Sep 17 00:00:00 2001 +From: yangchen +Date: Fri, 27 Sep 2024 06:32:41 +0800 +Subject: [PATCH] af_xdp: set rlimit unlimit when gazelle init + +--- + src/lstack/core/lstack_init.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/src/lstack/core/lstack_init.c b/src/lstack/core/lstack_init.c +index 37264a1..1d27f68 100644 +--- a/src/lstack/core/lstack_init.c ++++ b/src/lstack/core/lstack_init.c +@@ -17,6 +17,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -104,6 +105,20 @@ static int32_t check_process_conflict(void) + return 0; + } + ++/* Remove the memory resource limit of the current process. ++ * if the number of locked memory resources is exceeded, xdp_umem_create fails. ++ */ ++static int set_rlimit_unlimited(void) ++{ ++ struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY}; ++ ++ if (setrlimit(RLIMIT_MEMLOCK, &r) != 0) { ++ return -1; ++ } ++ ++ return 0; ++} ++ + void gazelle_exit(void) + { + wrap_api_exit(); +@@ -240,6 +255,11 @@ __attribute__((constructor)) void gazelle_network_init(void) + + wrap_api_init(); + ++ if (set_rlimit_unlimited() != 0) { ++ LSTACK_PRE_LOG(LSTACK_INFO, "set rlimit unlimited failed\n"); ++ LSTACK_EXIT(1, "set rlimit unlimited failed\n"); ++ } ++ + /* check primary process start */ + check_process_start(); + +-- +2.33.0 + diff --git a/gazelle.spec b/gazelle.spec index 59ded9a..ddf3084 100644 --- a/gazelle.spec +++ b/gazelle.spec @@ -2,7 +2,7 @@ Name: gazelle Version: 1.0.2 -Release: 65 +Release: 66 Summary: gazelle is a high performance user-mode stack License: MulanPSL-2.0 URL: https://gitee.com/openeuler/gazelle @@ -278,6 +278,9 @@ Patch9258: 0258-cleancode-move-some-API-from-stack-to-rpc-and-rtw.patch Patch9259: 0259-cleancode-add-rpc_async_call-remove-rpc_msg_arg.sock.patch Patch9260: 0260-cleancode-declare-different-cfg_params-types.patch Patch9261: 0261-Fill-in-a-portion-of-mbuf-to-send_ring-when-mbuf-is-.patch +Patch9262: 0262-add-pingpong-dfx-support.patch +Patch9263: 0263-add-interrupt-mode-support.patch +Patch9264: 0264-af_xdp-set-rlimit-unlimit-when-gazelle-init.patch %description %{name} is a high performance user-mode stack. @@ -319,6 +322,11 @@ install -Dpm 0640 %{_builddir}/%{name}-%{version}/src/ltran/ltran.conf %{b %config(noreplace) %{conf_path}/ltran.conf %changelog +* Sun Sep 29 2024 yinbin6 - 1.0.2-66 +- af_xdp: set rlimit unlimit when gazelle init +- add interrupt mode support +- add pingpong dfx support + * Fri Sep 27 2024 yinbin6 - 1.0.2-65 - Fill in a portion of mbuf to send_ring, when mbuf is insufficient.