From 75e11463d7bd67732d3c7f0e7ed3a9dece8c4982 Mon Sep 17 00:00:00 2001
From: jiangheng <jiangheng14@huawei.com>
Date: Sat, 25 Nov 2023 09:26:23 +0800
Subject: [PATCH] dfx: support bond get dpdk xstats

---
 src/lstack/core/lstack_control_plane.c  |  2 +
 src/lstack/core/lstack_dpdk.c           | 93 +++++++++++++++++++------
 src/lstack/core/lstack_protocol_stack.c |  2 +-
 src/lstack/core/lstack_stack_stat.c     | 14 ++--
 src/lstack/include/lstack_cfg.h         |  1 -
 src/lstack/include/lstack_dpdk.h        |  1 -
 src/lstack/include/lstack_stack_stat.h  |  3 +-
 src/lstack/netif/lstack_ethdev.c        |  4 +-
 8 files changed, 89 insertions(+), 31 deletions(-)

diff --git a/src/lstack/core/lstack_control_plane.c b/src/lstack/core/lstack_control_plane.c
index b97ee7f..4633834 100644
--- a/src/lstack/core/lstack_control_plane.c
+++ b/src/lstack/core/lstack_control_plane.c
@@ -586,6 +586,8 @@ static int32_t handle_stat_request(int32_t sockfd)
     if (msg.stat_mode == GAZELLE_STAT_LSTACK_LOG_LEVEL_SET ||
         msg.stat_mode == GAZELLE_STAT_LSTACK_LOW_POWER_MDF) {
         return handle_proc_cmd(sockfd, &msg);
+    } else if (msg.stat_mode == GAZELLE_STAT_LSTACK_SHOW_XSTATS) {
+        return handle_dpdk_cmd(sockfd, msg.stat_mode);
     } else {
         ret = handle_stack_cmd(sockfd, msg.stat_mode);
         if (ret != 0) {
diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c
index 703fd0d..19a7bf4 100644
--- a/src/lstack/core/lstack_dpdk.c
+++ b/src/lstack/core/lstack_dpdk.c
@@ -346,13 +346,6 @@ void lstack_log_level_init(void)
     }
 }
 
-// get port id
-inline uint16_t get_port_id(void)
-{
-    uint16_t port_id = get_global_cfg_params()->port_id;
-    return port_id;
-}
-
 static int32_t ethdev_port_id(uint8_t *mac)
 {
     int32_t port_id;
@@ -497,8 +490,6 @@ int32_t dpdk_ethdev_init(int port_id, bool bond_port)
         }
     }
 
-    get_global_cfg_params()->port_id = port_id;
-
     struct rte_eth_dev_info dev_info;
     int32_t ret = rte_eth_dev_info_get(port_id, &dev_info);
     if (ret != 0) {
@@ -814,23 +805,83 @@ bool port_in_stack_queue(ip_addr_t src_ip, ip_addr_t dst_ip, uint16_t src_port,
     return (reta_index % stack_group->nb_queues) == stack->queue_id;
 }
 
-void dpdk_nic_xstats_get(struct gazelle_stack_dfx_data *dfx, uint16_t port_id)
+static int dpdk_nic_xstats_value_get(uint64_t *values, unsigned int len, uint16_t *ports, unsigned int count)
 {
-    int32_t ret;
-    int32_t len = rte_eth_xstats_get_names_by_id(port_id, NULL, 0, NULL);
-    dfx->data.nic_xstats.len = len;
-    dfx->data.nic_xstats.port_id = port_id;
+    uint64_t tmp_values[RTE_ETH_XSTATS_MAX_LEN];
+    int p_idx;
+    int v_idx;
+    int ret;
+ 
+    for (p_idx = 0; p_idx < count; p_idx++) {
+        ret = rte_eth_xstats_get_by_id(ports[p_idx], NULL, tmp_values, len);
+        if (ret < 0 || ret > len)  {
+            LSTACK_LOG(ERR, LSTACK, "rte_eth_xstats_get_by_id failed.\n");
+            return -1;
+        }
+
+        for (v_idx = 0; v_idx < len; v_idx++) {
+            values[v_idx] += tmp_values[v_idx];
+        }
+    }
+    return 0;
+}
+
+static int dpdk_nic_xstats_name_get(struct nic_eth_xstats_name *names, uint16_t port_id)
+{
+    int len;
+
+    len = rte_eth_xstats_get_names_by_id(port_id, NULL, 0, NULL);
     if (len < 0) {
-        return;
+        LSTACK_LOG(ERR, LSTACK, "rte_eth_xstats_get_names_by_id failed.\n");
+        return -1;
+    }
+
+    if (len != rte_eth_xstats_get_names_by_id(port_id, (struct rte_eth_xstat_name *)names, len, NULL)) {
+        LSTACK_LOG(ERR, LSTACK, "rte_eth_xstats_get_names_by_id failed.\n");
+        return -1;
     }
-    if (len != rte_eth_xstats_get_names_by_id(port_id,
-        (struct rte_eth_xstat_name *)dfx->data.nic_xstats.xstats_name, len, NULL)) {
-        dfx->data.nic_xstats.len = -1;
+
+    return len;
+}
+
+void dpdk_nic_xstats_get(struct gazelle_stack_dfx_data *dfx, uint16_t port_id)
+{
+    struct rte_eth_dev_info dev_info;
+    int len;
+    int ret;
+
+    dfx->data.nic_xstats.len = -1;
+    dfx->data.nic_xstats.port_id = port_id;
+    ret = rte_eth_dev_info_get(port_id, &dev_info);
+    if (ret < 0) {
+        LSTACK_LOG(ERR, LSTACK, "rte_eth_dev_info_get failed.\n");
         return;
     }
 
-    ret = rte_eth_xstats_get_by_id(port_id, NULL, dfx->data.nic_xstats.values, len);
-    if (ret < 0 || ret > len) {
-        dfx->data.nic_xstats.len = -1;
+    /* bond not support get xstats, we get xstats from slave device of bond */
+    if (strcmp(dev_info.driver_name, "net_bonding") == 0) {
+        uint16_t slaves[RTE_MAX_ETHPORTS];
+        int slave_count;
+        slave_count = rte_eth_bond_slaves_get(port_id, slaves, RTE_MAX_ETHPORTS);
+        if (slave_count <= 0) {
+            LSTACK_LOG(ERR, LSTACK, "rte_eth_bond_slaves_get failed.\n");
+            return;
+        }
+        len = dpdk_nic_xstats_name_get(dfx->data.nic_xstats.xstats_name, slaves[0]);
+        if (len <= 0) {
+            return;
+        }
+        if (dpdk_nic_xstats_value_get(dfx->data.nic_xstats.values, len, slaves, slave_count) != 0) {
+            return;
+        }
+    } else {
+        len = dpdk_nic_xstats_name_get(dfx->data.nic_xstats.xstats_name, port_id);
+        if (len <= 0) {
+            return;
+        }
+        if (dpdk_nic_xstats_value_get(dfx->data.nic_xstats.values, len, &port_id, 1) != 0) {
+            return;
+        }
     }
+    dfx->data.nic_xstats.len = len;
 }
diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c
index cbc8b8f..dfebfcc 100644
--- a/src/lstack/core/lstack_protocol_stack.c
+++ b/src/lstack/core/lstack_protocol_stack.c
@@ -479,7 +479,7 @@ void stack_polling(uint32_t wakeup_tick)
     if (kni_switch && !stack->queue_id && !(wakeup_tick & 0xfff)) {
         rte_kni_handle_request(get_gazelle_kni());
         if (get_kni_started()) {
-            kni_handle_rx(get_port_id());
+            kni_handle_rx(stack->port_id);
         }
     }
     return;
diff --git a/src/lstack/core/lstack_stack_stat.c b/src/lstack/core/lstack_stack_stat.c
index 60832b4..18548ab 100644
--- a/src/lstack/core/lstack_stack_stat.c
+++ b/src/lstack/core/lstack_stack_stat.c
@@ -256,19 +256,25 @@ static int32_t send_control_cmd_data(int32_t fd, struct gazelle_stack_dfx_data *
     return 0;
 }
 
-int32_t handle_stack_cmd(int32_t fd, enum GAZELLE_STAT_MODE stat_mode)
+int handle_dpdk_cmd(int fd, enum GAZELLE_STAT_MODE stat_mode)
 {
     struct gazelle_stack_dfx_data dfx;
-    struct protocol_stack_group *stack_group = get_protocol_stack_group();
 
     if (stat_mode == GAZELLE_STAT_LSTACK_SHOW_XSTATS) {
-        dpdk_nic_xstats_get(&dfx, get_port_id());
+        dpdk_nic_xstats_get(&dfx, get_protocol_stack_group()->port_id);
         dfx.tid = 0;
         dfx.eof = 1;
         send_control_cmd_data(fd, &dfx);
-        return 0;
     }
 
+    return 0;
+}
+
+int handle_stack_cmd(int fd, enum GAZELLE_STAT_MODE stat_mode)
+{
+    struct gazelle_stack_dfx_data dfx;
+    struct protocol_stack_group *stack_group = get_protocol_stack_group();
+
     for (uint32_t i = 0; i < stack_group->stack_num; i++) {
         struct protocol_stack *stack = stack_group->stacks[i];
 
diff --git a/src/lstack/include/lstack_cfg.h b/src/lstack/include/lstack_cfg.h
index 26da357..e33f4fe 100644
--- a/src/lstack/include/lstack_cfg.h
+++ b/src/lstack/include/lstack_cfg.h
@@ -94,7 +94,6 @@ struct cfg_params {
 
     uint16_t num_process;
     uint16_t num_listen_port;
-    uint16_t port_id;
     uint16_t is_primary;
     uint16_t num_queue;
     uint16_t tot_queue_num;
diff --git a/src/lstack/include/lstack_dpdk.h b/src/lstack/include/lstack_dpdk.h
index 3a621d0..e3daefa 100644
--- a/src/lstack/include/lstack_dpdk.h
+++ b/src/lstack/include/lstack_dpdk.h
@@ -55,7 +55,6 @@ void dpdk_skip_nic_init(void);
 int32_t dpdk_init_lstack_kni(void);
 void dpdk_restore_pci(void);
 bool port_in_stack_queue(ip_addr_t src_ip, ip_addr_t dst_ip, uint16_t src_port, uint16_t dst_port);
-uint16_t get_port_id(void);
 struct rte_mempool *create_pktmbuf_mempool(const char *name, uint32_t nb_mbuf,
                                            uint32_t mbuf_cache_size, uint16_t queue_id, unsigned numa_id);
 
diff --git a/src/lstack/include/lstack_stack_stat.h b/src/lstack/include/lstack_stack_stat.h
index 5737bae..d5a4ec7 100644
--- a/src/lstack/include/lstack_stack_stat.h
+++ b/src/lstack/include/lstack_stack_stat.h
@@ -24,7 +24,8 @@ enum GAZELLE_STAT_MODE;
 void calculate_lstack_latency(struct gazelle_stack_latency *stack_latency, const struct pbuf *pbuf,
     enum GAZELLE_LATENCY_TYPE type);
 void stack_stat_init(void);
-int32_t handle_stack_cmd(int fd, enum GAZELLE_STAT_MODE stat_mode);
+int handle_stack_cmd(int fd, enum GAZELLE_STAT_MODE stat_mode);
+int handle_dpdk_cmd(int fd, enum GAZELLE_STAT_MODE stat_mode);
 uint64_t get_current_time(void);
 void lstack_get_low_power_info(struct gazelle_stat_low_power_info *low_power_info);
 void unregister_wakeup(struct protocol_stack *stack, struct wakeup_poll *wakeup);
diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c
index 9912858..29bef21 100644
--- a/src/lstack/netif/lstack_ethdev.c
+++ b/src/lstack/netif/lstack_ethdev.c
@@ -330,7 +330,7 @@ struct rte_flow *create_flow_director(uint16_t port_id, uint16_t queue_id,
 void config_flow_director(uint16_t queue_id, uint32_t src_ip,
                           uint32_t dst_ip, uint16_t src_port, uint16_t dst_port)
 {
-    uint16_t port_id = get_port_id();
+    uint16_t port_id = get_protocol_stack_group()->port_id;
     char rule_key[RULE_KEY_LEN] = {0};
     sprintf_s(rule_key, sizeof(rule_key), "%u_%u_%u", src_ip, src_port, dst_port);
     struct flow_rule *fl_exist = find_rule(rule_key);
@@ -357,7 +357,7 @@ void config_flow_director(uint16_t queue_id, uint32_t src_ip,
 
 void delete_flow_director(uint32_t dst_ip, uint16_t src_port, uint16_t dst_port)
 {
-    uint16_t port_id = get_port_id();
+    uint16_t port_id = get_protocol_stack_group()->port_id;
     char rule_key[RULE_KEY_LEN] = {0};
     sprintf_s(rule_key, RULE_KEY_LEN, "%u_%u_%u",dst_ip, dst_port, src_port);
     struct flow_rule *fl = find_rule(rule_key);
-- 
2.27.0

