346 lines
15 KiB
Diff
346 lines
15 KiB
Diff
From 03eabf12b7d486278598ad44d2b7d8e310ff0abf Mon Sep 17 00:00:00 2001
|
|
From: yangchen <yangchen145@huawei.com>
|
|
Date: Sun, 4 Feb 2024 13:29:15 +0800
|
|
Subject: [PATCH] gazellectl: support send latency show
|
|
|
|
---
|
|
src/common/dpdk_common.h | 10 +++
|
|
src/common/gazelle_dfx_msg.h | 20 ++++-
|
|
src/lstack/core/lstack_lwip.c | 14 +++-
|
|
src/lstack/core/lstack_stack_stat.c | 15 ++--
|
|
src/lstack/netif/lstack_ethdev.c | 4 +
|
|
src/ltran/ltran_dfx.c | 110 +++++++++++++++-------------
|
|
6 files changed, 111 insertions(+), 62 deletions(-)
|
|
|
|
diff --git a/src/common/dpdk_common.h b/src/common/dpdk_common.h
|
|
index 38f09ae..a79a0f2 100644
|
|
--- a/src/common/dpdk_common.h
|
|
+++ b/src/common/dpdk_common.h
|
|
@@ -95,6 +95,16 @@ static __rte_always_inline void time_stamp_into_mbuf(uint32_t rx_count, struct r
|
|
}
|
|
}
|
|
|
|
+static __rte_always_inline void time_stamp_into_pbuf(uint32_t tx_count, struct pbuf *buf[], uint64_t time_stamp)
|
|
+{
|
|
+ struct latency_timestamp *lt;
|
|
+ for (uint32_t i = 0; i < tx_count; i++) {
|
|
+ lt = &pbuf_to_private(buf[i])->lt;
|
|
+ lt->stamp = time_stamp;
|
|
+ lt->check = ~(time_stamp);
|
|
+ }
|
|
+}
|
|
+
|
|
bool get_kni_started(void);
|
|
struct rte_kni* get_gazelle_kni(void);
|
|
int32_t dpdk_kni_init(uint16_t port, struct rte_mempool *pool);
|
|
diff --git a/src/common/gazelle_dfx_msg.h b/src/common/gazelle_dfx_msg.h
|
|
index d465efa..d47ed9a 100644
|
|
--- a/src/common/gazelle_dfx_msg.h
|
|
+++ b/src/common/gazelle_dfx_msg.h
|
|
@@ -24,6 +24,10 @@
|
|
/* maybe it should be consistent with MEMP_NUM_TCP_PCB */
|
|
#define GAZELLE_LSTACK_MAX_CONN (20000 + 2000) // same as MAX_CLIENTS + RESERVED_CLIENTS in lwipopts.h
|
|
|
|
+#define GAZELLE_RESULT_LEN 4096
|
|
+#define GAZELLE_MAX_LATENCY_TIME 1800 // max latency time 30mins
|
|
+#define GAZELLE_RESULT_LINE_LEN 80 // for a single row, the max len of result is 80
|
|
+
|
|
enum GAZELLE_STAT_MODE {
|
|
GAZELLE_STAT_LTRAN_SHOW = 0,
|
|
GAZELLE_STAT_LTRAN_SHOW_RATE,
|
|
@@ -54,8 +58,11 @@ enum GAZELLE_STAT_MODE {
|
|
};
|
|
|
|
enum GAZELLE_LATENCY_TYPE {
|
|
- GAZELLE_LATENCY_LWIP,
|
|
- GAZELLE_LATENCY_READ,
|
|
+ GAZELLE_LATENCY_READ_LWIP,
|
|
+ GAZELLE_LATENCY_READ_LSTACK,
|
|
+ GAZELLE_LATENCY_WRITE_LWIP,
|
|
+ GAZELLE_LATENCY_WRITE_LSTACK,
|
|
+ GAZELLE_LATENCY_MAX,
|
|
};
|
|
|
|
struct gazelle_stack_stat {
|
|
@@ -216,9 +223,14 @@ struct stack_latency {
|
|
uint64_t latency_total;
|
|
};
|
|
|
|
+struct gazelle_latency_result {
|
|
+ int latency_stat_index;
|
|
+ struct stack_latency latency_stat_record;
|
|
+ char latency_stat_result[GAZELLE_RESULT_LEN];
|
|
+};
|
|
+
|
|
struct gazelle_stack_latency {
|
|
- struct stack_latency read_latency;
|
|
- struct stack_latency lwip_latency;
|
|
+ struct stack_latency latency[GAZELLE_LATENCY_MAX];
|
|
uint64_t start_time;
|
|
uint64_t g_cycles_per_us;
|
|
};
|
|
diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c
|
|
index 22605dd..be2c6de 100644
|
|
--- a/src/lstack/core/lstack_lwip.c
|
|
+++ b/src/lstack/core/lstack_lwip.c
|
|
@@ -244,6 +244,11 @@ struct pbuf *do_lwip_get_from_sendring(struct lwip_sock *sock, uint16_t remain_s
|
|
if (pbuf == NULL) {
|
|
return NULL;
|
|
}
|
|
+
|
|
+ if (get_protocol_stack_group()->latency_start) {
|
|
+ calculate_lstack_latency(&sock->stack->latency, pbuf, GAZELLE_LATENCY_WRITE_LWIP);
|
|
+ }
|
|
+
|
|
sock->send_pre_del = pbuf;
|
|
|
|
if (!gazelle_ring_readover_count(sock->send_ring)) {
|
|
@@ -303,6 +308,11 @@ static inline ssize_t app_buff_write(struct lwip_sock *sock, void *buf, size_t l
|
|
|
|
(void)gazelle_ring_read(sock->send_ring, (void **)pbufs, write_num);
|
|
|
|
+ if (get_protocol_stack_group()->latency_start) {
|
|
+ uint64_t time_stamp = get_current_time();
|
|
+ time_stamp_into_pbuf(write_num, pbufs, time_stamp);
|
|
+ }
|
|
+
|
|
ssize_t send_len = do_app_write(pbufs, buf, len, write_num);
|
|
|
|
if (addr) {
|
|
@@ -573,7 +583,7 @@ ssize_t do_lwip_read_from_lwip(struct lwip_sock *sock, int32_t flags, u8_t apifl
|
|
|
|
for (uint32_t i = 0; get_protocol_stack_group()->latency_start && i < read_count; i++) {
|
|
if (pbufs[i] != NULL) {
|
|
- calculate_lstack_latency(&sock->stack->latency, pbufs[i], GAZELLE_LATENCY_LWIP);
|
|
+ calculate_lstack_latency(&sock->stack->latency, pbufs[i], GAZELLE_LATENCY_READ_LWIP);
|
|
}
|
|
}
|
|
|
|
@@ -895,7 +905,7 @@ ssize_t do_lwip_read_from_stack(int32_t fd, void *buf, size_t len, int32_t flags
|
|
sock->wakeup->stat.app_read_cnt += 1;
|
|
}
|
|
if (latency_enable) {
|
|
- calculate_lstack_latency(&sock->stack->latency, pbuf, GAZELLE_LATENCY_READ);
|
|
+ calculate_lstack_latency(&sock->stack->latency, pbuf, GAZELLE_LATENCY_READ_LSTACK);
|
|
}
|
|
gazelle_ring_read_over(sock->recv_ring);
|
|
|
|
diff --git a/src/lstack/core/lstack_stack_stat.c b/src/lstack/core/lstack_stack_stat.c
|
|
index 23571b4..cb11dc3 100644
|
|
--- a/src/lstack/core/lstack_stack_stat.c
|
|
+++ b/src/lstack/core/lstack_stack_stat.c
|
|
@@ -53,8 +53,9 @@ void calculate_lstack_latency(struct gazelle_stack_latency *stack_latency, const
|
|
{
|
|
uint64_t latency;
|
|
const struct latency_timestamp *lt;
|
|
+ struct stack_latency *latency_stat;
|
|
|
|
- if (pbuf == NULL) {
|
|
+ if (pbuf == NULL || type >= GAZELLE_LATENCY_MAX) {
|
|
return;
|
|
}
|
|
|
|
@@ -62,10 +63,9 @@ void calculate_lstack_latency(struct gazelle_stack_latency *stack_latency, const
|
|
if (lt->stamp != ~(lt->check) || lt->stamp < stack_latency->start_time) {
|
|
return;
|
|
}
|
|
- latency = get_current_time() - lt->stamp;
|
|
|
|
- struct stack_latency *latency_stat = (type == GAZELLE_LATENCY_LWIP) ?
|
|
- &stack_latency->lwip_latency : &stack_latency->read_latency;
|
|
+ latency = get_current_time() - lt->stamp;
|
|
+ latency_stat = &stack_latency->latency[type];
|
|
|
|
latency_stat->latency_total += latency;
|
|
latency_stat->latency_max = (latency_stat->latency_max > latency) ? latency_stat->latency_max : latency;
|
|
@@ -118,8 +118,11 @@ static void set_latency_start_flag(bool start)
|
|
LSTACK_LOG(ERR, LSTACK, "memset_s faile\n");
|
|
}
|
|
stack->latency.start_time = get_current_time();
|
|
- stack->latency.lwip_latency.latency_min = ~((uint64_t)0);
|
|
- stack->latency.read_latency.latency_min = ~((uint64_t)0);
|
|
+
|
|
+ for (uint32_t j = 0; j < GAZELLE_LATENCY_MAX; j++) {
|
|
+ stack->latency.latency[j].latency_min = ~((uint64_t)0);
|
|
+ }
|
|
+
|
|
memset_s(&stack->aggregate_stats, sizeof(struct gazelle_stack_aggregate_stats),
|
|
0, sizeof(stack->aggregate_stats));
|
|
}
|
|
diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c
|
|
index 4d6f620..94ecffc 100644
|
|
--- a/src/lstack/netif/lstack_ethdev.c
|
|
+++ b/src/lstack/netif/lstack_ethdev.c
|
|
@@ -889,6 +889,10 @@ static err_t eth_dev_output(struct netif *netif, struct pbuf *pbuf)
|
|
|
|
pre_mbuf = mbuf;
|
|
rte_mbuf_refcnt_update(mbuf, 1);
|
|
+
|
|
+ if (get_protocol_stack_group()->latency_start) {
|
|
+ calculate_lstack_latency(&stack->latency, pbuf, GAZELLE_LATENCY_WRITE_LSTACK);
|
|
+ }
|
|
pbuf = pbuf->next;
|
|
}
|
|
|
|
diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c
|
|
index 4b246a1..ecdb5f9 100644
|
|
--- a/src/ltran/ltran_dfx.c
|
|
+++ b/src/ltran/ltran_dfx.c
|
|
@@ -50,9 +50,6 @@
|
|
#define GAZELLE_CMD_MAX 5
|
|
#define CMD_WAIT_TIME 1 // sec
|
|
|
|
-#define GAZELLE_RESULT_LEN 8291
|
|
-#define GAZELLE_MAX_LATENCY_TIME 1800 // max latency time 30mins
|
|
-
|
|
#define GAZELLE_DECIMAL 10
|
|
#define GAZELLE_KEEPALIVE_STR_LEN 35
|
|
#define GAZELLE_TIME_STR_LEN 25
|
|
@@ -702,8 +699,8 @@ static void parse_thread_latency_result(const struct stack_latency *latency, cha
|
|
{
|
|
if (latency->latency_pkts > 0) {
|
|
*pos += sprintf_s(result + *pos, max_len, "%-8"PRIu64" ", latency->latency_pkts);
|
|
- *pos += sprintf_s(result + *pos, max_len, "%-6"PRIu64" ", latency->latency_min);
|
|
- *pos += sprintf_s(result + *pos, max_len, "%-6"PRIu64" ", latency->latency_max);
|
|
+ *pos += sprintf_s(result + *pos, max_len, "%-8"PRIu64" ", latency->latency_min);
|
|
+ *pos += sprintf_s(result + *pos, max_len, "%-8"PRIu64" ", latency->latency_max);
|
|
*pos += sprintf_s(result + *pos, max_len, "%-6.2f \n",
|
|
(double)latency->latency_total / latency->latency_pkts);
|
|
} else {
|
|
@@ -719,52 +716,53 @@ static void parse_thread_latency_result(const struct stack_latency *latency, cha
|
|
static void parse_latency_total_result(char *result, size_t max_len, int32_t *pos,
|
|
const struct stack_latency *record)
|
|
{
|
|
+ if (max_len < GAZELLE_RESULT_LINE_LEN) {
|
|
+ printf("total latency result show failed, out of memory bounds\n");
|
|
+ return;
|
|
+ }
|
|
+
|
|
if (record->latency_pkts > 0) {
|
|
- *pos += sprintf_s(result + *pos, max_len, " total: ");
|
|
+ *pos += sprintf_s(result + *pos, max_len, " total: ");
|
|
*pos += sprintf_s(result + *pos, max_len, "%-8"PRIu64" ", record->latency_pkts);
|
|
- *pos += sprintf_s(result + *pos, max_len, "%-6"PRIu64" ", record->latency_min);
|
|
- *pos += sprintf_s(result + *pos, max_len, "%-6"PRIu64" ", record->latency_max);
|
|
- *pos += sprintf_s(result + *pos, max_len, "%-6.2f \n\n\n",
|
|
+ *pos += sprintf_s(result + *pos, max_len, "%-8"PRIu64" ", record->latency_min);
|
|
+ *pos += sprintf_s(result + *pos, max_len, "%-8"PRIu64" ", record->latency_max);
|
|
+ *pos += sprintf_s(result + *pos, max_len, "%-6.2f \n\n",
|
|
(double)record->latency_total / record->latency_pkts);
|
|
} else {
|
|
- *pos += sprintf_s(result + *pos, max_len, " total: 0\n\n\n");
|
|
+ *pos += sprintf_s(result + *pos, max_len, " total: 0\n\n");
|
|
}
|
|
}
|
|
|
|
-static void gazelle_print_lstack_stat_latency(void *buf, const struct gazelle_stat_msg_request *req_msg)
|
|
+static void gazelle_show_latency_result(const struct gazelle_stat_msg_request *req_msg,
|
|
+ struct gazelle_stack_dfx_data *stat, struct stack_latency *latency,
|
|
+ struct gazelle_latency_result *res)
|
|
{
|
|
- struct gazelle_stack_dfx_data *stat = (struct gazelle_stack_dfx_data *)buf;
|
|
- struct gazelle_stack_latency *latency = &stat->data.latency;
|
|
- int32_t ret = GAZELLE_OK;
|
|
- int32_t lwip_index = 0;
|
|
- int32_t read_index = 0;
|
|
- struct stack_latency lwip_record = {0};
|
|
- struct stack_latency read_record = {0};
|
|
- char str_ip[GAZELLE_SUBNET_LENGTH_MAX] = {0};
|
|
+ char str_ip[GAZELLE_SUBNET_LENGTH_MAX] = { 0 };
|
|
|
|
- read_record.latency_min = ~((uint64_t)0);
|
|
- lwip_record.latency_min = ~((uint64_t)0);
|
|
-
|
|
- char *lwip_result = calloc(GAZELLE_RESULT_LEN, sizeof(char));
|
|
- if (lwip_result == NULL) {
|
|
- return;
|
|
- }
|
|
- char *read_result = calloc(GAZELLE_RESULT_LEN, sizeof(char));
|
|
- if (read_result == NULL) {
|
|
- free(lwip_result);
|
|
+ if (GAZELLE_RESULT_LEN - res->latency_stat_index < GAZELLE_RESULT_LINE_LEN) {
|
|
+ printf("too many threads show latency result, out of memory bounds\n");
|
|
return;
|
|
}
|
|
|
|
- do {
|
|
- lwip_index += sprintf_s(lwip_result + lwip_index, (size_t)(GAZELLE_RESULT_LEN - lwip_index),
|
|
- "ip: %-15s tid: %-8u ", inet_ntop(AF_INET, &req_msg->ip, str_ip, sizeof(str_ip)), stat->tid);
|
|
- parse_thread_latency_result(&latency->lwip_latency, lwip_result, (size_t)(GAZELLE_RESULT_LEN - lwip_index),
|
|
- &lwip_index, &lwip_record);
|
|
+ res->latency_stat_index += sprintf_s(res->latency_stat_result + res->latency_stat_index,
|
|
+ (size_t)(GAZELLE_RESULT_LEN - res->latency_stat_index), "ip: %-15s tid: %-8u ",
|
|
+ inet_ntop(AF_INET, &req_msg->ip, str_ip, sizeof(str_ip)), stat->tid);
|
|
|
|
- read_index += sprintf_s(read_result + read_index, (size_t)(GAZELLE_RESULT_LEN - read_index),
|
|
- "ip: %-15s tid: %-8u ", inet_ntop(AF_INET, &req_msg->ip, str_ip, sizeof(str_ip)), stat->tid);
|
|
- parse_thread_latency_result(&latency->read_latency, read_result, (size_t)(GAZELLE_RESULT_LEN - read_index),
|
|
- &read_index, &read_record);
|
|
+ parse_thread_latency_result(latency, res->latency_stat_result,
|
|
+ (size_t)(GAZELLE_RESULT_LEN - res->latency_stat_index), &res->latency_stat_index, &res->latency_stat_record);
|
|
+}
|
|
+
|
|
+static void gazelle_show_latency_result_total(void *buf, const struct gazelle_stat_msg_request *req_msg,
|
|
+ struct gazelle_latency_result *res)
|
|
+{
|
|
+ int ret = GAZELLE_OK;
|
|
+ struct gazelle_stack_dfx_data *stat = (struct gazelle_stack_dfx_data *)buf;
|
|
+ struct gazelle_stack_latency *latency = &stat->data.latency;
|
|
+
|
|
+ do {
|
|
+ for (int i = 0; i < GAZELLE_LATENCY_MAX; i++) {
|
|
+ gazelle_show_latency_result(req_msg, stat, &latency->latency[i], &res[i]);
|
|
+ }
|
|
|
|
if ((stat->eof != 0) || (ret != GAZELLE_OK)) {
|
|
break;
|
|
@@ -772,21 +770,33 @@ static void gazelle_print_lstack_stat_latency(void *buf, const struct gazelle_st
|
|
ret = dfx_stat_read_from_ltran(buf, sizeof(struct gazelle_stack_dfx_data), req_msg->stat_mode);
|
|
} while (true);
|
|
|
|
- parse_latency_total_result(lwip_result, (size_t)(GAZELLE_RESULT_LEN - lwip_index), &lwip_index, &lwip_record);
|
|
- parse_latency_total_result(read_result, (size_t)(GAZELLE_RESULT_LEN - read_index), &read_index, &read_record);
|
|
+ for (int i = 0; i < GAZELLE_LATENCY_MAX; i++) {
|
|
+ parse_latency_total_result(res[i].latency_stat_result, (size_t)(GAZELLE_RESULT_LEN - res[i].latency_stat_index),
|
|
+ &res[i].latency_stat_index, &res[i].latency_stat_record);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void gazelle_print_lstack_stat_latency(void *buf, const struct gazelle_stat_msg_request *req_msg)
|
|
+{
|
|
+ struct gazelle_latency_result *res = calloc(GAZELLE_LATENCY_MAX, sizeof(struct gazelle_latency_result));
|
|
+ if (res == NULL) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ for (int i = 0; i < GAZELLE_LATENCY_MAX; i++) {
|
|
+ res[i].latency_stat_record.latency_min = ~((uint64_t)0);
|
|
+ }
|
|
|
|
- printf("Statistics of lstack latency: t0--->t3 \
|
|
- (t0:read form nic t1:into lstask queue t2:into app queue t3:app read)\n");
|
|
- printf(" pkts min(us) max(us) average(us)\n%s",
|
|
- read_result);
|
|
+ gazelle_show_latency_result_total(buf, req_msg, res);
|
|
|
|
- printf("Statistics of lstack latency: t0--->t2 \
|
|
- (t0:read form nic t1:into lstask queue t2:into app queue t3:app read)\n");
|
|
- printf(" pkts min(us) max(us) average(us)\n%s",
|
|
- lwip_result);
|
|
+ printf("Statistics of lstack latency pkts min(us) max(us) average(us)\n");
|
|
+ printf("range: t0--->t3\n%s", res[GAZELLE_LATENCY_READ_LSTACK].latency_stat_result);
|
|
+ printf("range: t0--->t2\n%s", res[GAZELLE_LATENCY_READ_LWIP].latency_stat_result);
|
|
+ printf("range: t3--->t0\n%s", res[GAZELLE_LATENCY_WRITE_LSTACK].latency_stat_result);
|
|
+ printf("range: t2--->t0\n%s", res[GAZELLE_LATENCY_WRITE_LWIP].latency_stat_result);
|
|
+ printf("t0:read form/send to nic t1:into/out of lstask queue t2:into/out of app queue t3:app read/send\n");
|
|
|
|
- free(read_result);
|
|
- free(lwip_result);
|
|
+ free(res);
|
|
}
|
|
|
|
static void gazelle_print_lstack_stat_lpm(void *buf, const struct gazelle_stat_msg_request *req_msg)
|
|
--
|
|
2.27.0
|
|
|