From dae1c41eea8dba45344f49c2fc00eeb31a24f925 Mon Sep 17 00:00:00 2001
From: jiangheng <jiangheng14@huawei.com>
Date: Mon, 17 Jun 2024 19:09:13 +0800
Subject: [PATCH] refactor tx cache module

---
 src/lstack/api/dir.mk                      |   2 +-
 src/lstack/api/lstack_tx_cache.c           |  47 ---------
 src/lstack/core/lstack_cfg.c               |   1 -
 src/lstack/core/lstack_protocol_stack.c    |   4 +-
 src/lstack/include/lstack_protocol_stack.h |   1 -
 src/lstack/include/lstack_tx_cache.h       |  13 +--
 src/lstack/netif/dir.mk                    |   2 +-
 src/lstack/netif/lstack_ethdev.c           |  32 ++----
 src/lstack/netif/lstack_tx_cache.c         | 114 +++++++++++++++++++++
 9 files changed, 130 insertions(+), 86 deletions(-)
 delete mode 100644 src/lstack/api/lstack_tx_cache.c
 create mode 100644 src/lstack/netif/lstack_tx_cache.c

diff --git a/src/lstack/api/dir.mk b/src/lstack/api/dir.mk
index 70bc59d..729690d 100644
--- a/src/lstack/api/dir.mk
+++ b/src/lstack/api/dir.mk
@@ -8,7 +8,7 @@
 # PURPOSE.
 # See the Mulan PSL v2 for more details.
 
-SRC = lstack_epoll.c lstack_signal.c lstack_fork.c lstack_wrap.c lstack_rtw_api.c lstack_rtc_api.c lstack_dummy_api.c lstack_tx_cache.c
+SRC = lstack_epoll.c lstack_signal.c lstack_fork.c lstack_wrap.c lstack_rtw_api.c lstack_rtc_api.c lstack_dummy_api.c
 
 $(eval $(call register_dir, api, $(SRC)))
 
diff --git a/src/lstack/api/lstack_tx_cache.c b/src/lstack/api/lstack_tx_cache.c
deleted file mode 100644
index 42aef57..0000000
--- a/src/lstack/api/lstack_tx_cache.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
-* 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 "lwip/sockets.h"
-#include "lstack_cfg.h"
-#include "lstack_protocol_stack.h"
-#include "lstack_tx_cache.h"
-
-void stack_send_pkts(struct protocol_stack *stack)
-{
-    if (!get_global_cfg_params()->send_cache_mode) {
-        return;
-    }
-
-    uint32_t send_num = stack->tx_cache.send_end - stack->tx_cache.send_start;
-
-    if (send_num == 0) {
-        return;
-    }
-
-    uint32_t start = stack->tx_cache.send_start & STACK_SEND_MASK;
-    uint32_t end = stack->tx_cache.send_end & STACK_SEND_MASK;
-    uint32_t sent_pkts = 0;
-
-    if (start < end) {
-        sent_pkts = stack->dev_ops.tx_xmit(stack, &stack->tx_cache.send_pkts[start], send_num);
-    } else {
-        send_num = STACK_SEND_MAX - start;
-        sent_pkts = stack->dev_ops.tx_xmit(stack, &stack->tx_cache.send_pkts[start], send_num);
-        if (sent_pkts == send_num) {
-            sent_pkts += stack->dev_ops.tx_xmit(stack, stack->tx_cache.send_pkts, end);
-        }
-    }
-
-    stack->tx_cache.send_start += sent_pkts;
-    stack->stats.tx += sent_pkts;
-}
-
diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c
index f0c5f4f..5521898 100644
--- a/src/lstack/core/lstack_cfg.c
+++ b/src/lstack/core/lstack_cfg.c
@@ -32,7 +32,6 @@
 #include "gazelle_reg_msg.h"
 #include "lstack_log.h"
 #include "gazelle_base_func.h"
-#include "lstack_protocol_stack.h"
 #include "lstack_cfg.h"
 
 #define DEFAULT_CONF_FILE "/etc/gazelle/lstack.conf"
diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c
index 74e543d..f6d381e 100644
--- a/src/lstack/core/lstack_protocol_stack.c
+++ b/src/lstack/core/lstack_protocol_stack.c
@@ -480,7 +480,9 @@ int stack_polling(uint32_t wakeup_tick)
     do_lwip_read_recvlist(stack, read_connect_number);
     if ((wakeup_tick & 0xf) == 0) {
         wakeup_stack_epoll(stack);
-        stack_send_pkts(stack);
+        if (get_global_cfg_params()->send_cache_mode) {
+            tx_cache_send(stack->queue_id);
+        }
     }
 
     /* run to completion mode currently does not support sockmap */
diff --git a/src/lstack/include/lstack_protocol_stack.h b/src/lstack/include/lstack_protocol_stack.h
index ab27dfa..6ca4f14 100644
--- a/src/lstack/include/lstack_protocol_stack.h
+++ b/src/lstack/include/lstack_protocol_stack.h
@@ -77,7 +77,6 @@ struct protocol_stack {
     uint32_t tx_ring_used;
 
     struct rte_mbuf *pkts[NIC_QUEUE_SIZE_MAX];
-    struct lstack_tx_cache tx_cache;
     struct list_node recv_list;
     struct list_node same_node_recv_list; /* used for same node processes communication */
     struct list_node wakeup_list;
diff --git a/src/lstack/include/lstack_tx_cache.h b/src/lstack/include/lstack_tx_cache.h
index 3991b16..04e9e35 100644
--- a/src/lstack/include/lstack_tx_cache.h
+++ b/src/lstack/include/lstack_tx_cache.h
@@ -13,16 +13,7 @@
 #ifndef _LSTACK_TX_CACHE_H_
 #define _LSTACK_TX_CACHE_H_
 
-#define STACK_SEND_MAX              (2048)
-#define STACK_SEND_MASK             (STACK_SEND_MAX - 1)
-#define STACK_SEND_INDEX(index)     ((index) & STACK_SEND_MASK)
-
-struct lstack_tx_cache {
-    uint32_t send_start;
-    uint32_t send_end;
-    struct rte_mbuf *send_pkts[STACK_SEND_MAX];
-};
-
-void stack_send_pkts(struct protocol_stack *stack);
+int tx_cache_init(uint16_t queue_id, void *priv, struct lstack_dev_ops *dev_ops);
+int tx_cache_send(uint16_t queue_id);
 
 #endif /* _LSTACK_TX_CACHE_H_ */
diff --git a/src/lstack/netif/dir.mk b/src/lstack/netif/dir.mk
index 1e67734..b551041 100644
--- a/src/lstack/netif/dir.mk
+++ b/src/lstack/netif/dir.mk
@@ -8,7 +8,7 @@
 # PURPOSE.
 # See the Mulan PSL v2 for more details.
 
-SRC = lstack_ethdev.c lstack_vdev.c lstack_flow.c
+SRC = lstack_ethdev.c lstack_vdev.c lstack_flow.c lstack_tx_cache.c
 ifeq ($(GAZELLE_FAULT_INJECT_ENABLE), 1)
 	SRC +=  lstack_fault_inject.c
 endif
diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c
index 77172f8..45c5f9e 100644
--- a/src/lstack/netif/lstack_ethdev.c
+++ b/src/lstack/netif/lstack_ethdev.c
@@ -187,19 +187,6 @@ int32_t eth_dev_poll(void)
     return nr_pkts;
 }
 
-static void eth_dev_send_pkt(struct protocol_stack *stack, struct rte_mbuf *mbuf)
-{
-    do {
-        if (STACK_SEND_INDEX(stack->tx_cache.send_end + 1) != STACK_SEND_INDEX(stack->tx_cache.send_start)) {
-            stack->tx_cache.send_pkts[STACK_SEND_INDEX(stack->tx_cache.send_end)] = mbuf;
-            stack->tx_cache.send_end++;
-            return;
-        }
-        stack_send_pkts(stack);
-        stack->stats.send_pkts_fail++;
-    } while (1);
-}
-
 static err_t eth_dev_output(struct netif *netif, struct pbuf *pbuf)
 {
     struct protocol_stack *stack = get_protocol_stack();
@@ -245,16 +232,12 @@ static err_t eth_dev_output(struct netif *netif, struct pbuf *pbuf)
         pbuf = pbuf->next;
     }
 
-    if (!get_global_cfg_params()->send_cache_mode) {
-        uint32_t sent_pkts = stack->dev_ops.tx_xmit(stack, &first_mbuf, 1);
-        stack->stats.tx += sent_pkts;
-        if (sent_pkts < 1) {
-            stack->stats.tx_drop++;
-            rte_pktmbuf_free(first_mbuf);
-            return ERR_MEM;
-        }
-    } else {
-        eth_dev_send_pkt(stack, first_mbuf);
+    uint32_t sent_pkts = stack->dev_ops.tx_xmit(stack, &first_mbuf, 1);
+    stack->stats.tx += sent_pkts;
+    if (sent_pkts < 1) {
+        stack->stats.tx_drop++;
+        rte_pktmbuf_free(first_mbuf);
+        return ERR_MEM;
     }
 
     return ERR_OK;
@@ -295,6 +278,9 @@ int32_t ethdev_init(struct protocol_stack *stack)
     struct cfg_params *cfg = get_global_cfg_params();
 
     vdev_dev_ops_init(&stack->dev_ops);
+    if (cfg->send_cache_mode) {
+        tx_cache_init(stack->queue_id, stack, &stack->dev_ops);
+    }
 
     if (use_ltran()) {
         stack->rx_ring_used = 0;
diff --git a/src/lstack/netif/lstack_tx_cache.c b/src/lstack/netif/lstack_tx_cache.c
new file mode 100644
index 0000000..ac5a9db
--- /dev/null
+++ b/src/lstack/netif/lstack_tx_cache.c
@@ -0,0 +1,114 @@
+/*
+* 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 <rte_mbuf.h>
+
+#include "lwip/sockets.h"
+#include "lstack_ethdev.h"
+#include "lstack_log.h"
+#include "gazelle_opt.h"
+#include "lstack_protocol_stack.h"
+#include "lstack_tx_cache.h"
+
+#define TX_CACHE_MAX              128
+#define TX_CACHE_MASK             (TX_CACHE_MAX - 1)
+#define TX_CACHE_INDEX(index)     ((index) & TX_CACHE_MASK)
+
+struct tx_cache {
+    uint16_t port_id;
+    uint16_t queue_id;
+
+    uint32_t send_start;
+    uint32_t send_end;
+    struct rte_mbuf *send_pkts[TX_CACHE_MAX];
+
+    uint64_t send_pkts_fail;
+    void *priv;
+};
+struct lstack_dev_ops g_tx_cache_dev_ops;
+
+static uint32_t tx_cache_recv(struct protocol_stack *stack, struct rte_mbuf **pkts, uint32_t nr_pkts);
+
+struct tx_cache *g_tx_cache[PROTOCOL_STACK_MAX];
+
+int tx_cache_init(uint16_t queue_id, void *priv, struct lstack_dev_ops *dev_ops)
+{
+    struct tx_cache *tx_cache = calloc(1, sizeof(struct tx_cache));
+    if (tx_cache == NULL) {
+        LSTACK_LOG(ERR, LSTACK, "queue(%d) tx cache init failed\n", queue_id);
+    }
+
+    tx_cache->queue_id = queue_id;
+    tx_cache->priv = priv;
+    g_tx_cache[queue_id] = tx_cache;
+
+    g_tx_cache_dev_ops.tx_xmit = dev_ops->tx_xmit;
+    dev_ops->tx_xmit = tx_cache_recv;
+
+    return 0;
+}
+
+int tx_cache_send(uint16_t queue_id)
+{
+    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;
+    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;
+    if (start < end) {
+        sent_pkts = g_tx_cache_dev_ops.tx_xmit(tx_cache->priv, &tx_cache->send_pkts[start], send_num);
+    } else {
+        send_num = TX_CACHE_MAX - start;
+        sent_pkts = g_tx_cache_dev_ops.tx_xmit(tx_cache->priv,  &tx_cache->send_pkts[start], send_num);
+        if (sent_pkts == send_num) {
+            sent_pkts += g_tx_cache_dev_ops.tx_xmit(tx_cache->priv, tx_cache->send_pkts, end);
+        }
+    }
+
+    tx_cache->send_start += sent_pkts;
+    return sent_pkts;
+}
+
+static uint32_t tx_cache_recv(struct protocol_stack *stack, struct rte_mbuf **pkts, uint32_t nr_pkts)
+{
+    if (nr_pkts != 1) {
+        LSTACK_LOG(ERR, LSTACK, "arg not support, nr_pkts is %d\n", nr_pkts);
+        return 0;
+    }
+    uint16_t queue_id = stack->queue_id;
+    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;
+    }
+
+    do {
+        if (TX_CACHE_INDEX(tx_cache->send_end + 1) != TX_CACHE_INDEX(tx_cache->send_start)) {
+            tx_cache->send_pkts[TX_CACHE_INDEX(tx_cache->send_end)] = pkts[0];
+            tx_cache->send_end++;
+            return nr_pkts;
+        }
+
+        tx_cache_send(queue_id);
+    } while (1);
+
+    return 0;
+}
-- 
2.33.0

