diff --git a/src/common/gazelle_dfx_msg.h b/src/common/gazelle_dfx_msg.h index 1a89e654d87b71ad060a8dd44894278a8a8c2070..c3ee213c3775d560a9cf30f10df90494dfe04108 100644 --- a/src/common/gazelle_dfx_msg.h +++ b/src/common/gazelle_dfx_msg.h @@ -33,6 +33,12 @@ #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 +#define PERCENT_BASE 100 +static inline double convert_to_percent(double decimals) +{ + return decimals * PERCENT_BASE; +} + enum GAZELLE_STAT_MODE { GAZELLE_STAT_LTRAN_SHOW = 0, GAZELLE_STAT_LTRAN_SHOW_RATE, @@ -61,6 +67,7 @@ enum GAZELLE_STAT_MODE { GAZELLE_STAT_LSTACK_SHOW_AGGREGATE, GAZELLE_STAT_LSTACK_SHOW_NIC_FEATURES, GAZELLE_STAT_LSTACK_SHOW_INTR, + GAZELLE_STAT_LSTACK_SHOW_MEMORY_USAGE, #ifdef GAZELLE_FAULT_INJECT_ENABLE GAZELLE_STAT_FAULT_INJECT_SET, @@ -94,6 +101,39 @@ enum GAZELLE_TCP_LIST_STATE { GAZELLE_TIME_WAIT_LIST, }; +struct gazelle_memory_info { + uint32_t total_size; + uint32_t avail_size; + double total_mem; + double avail_mem; +}; + +struct gazelle_ring_meminfo_stats { + uint32_t fd; + struct gazelle_memory_info send_ring_info; + struct gazelle_memory_info recv_ring_info; + struct gazelle_memory_info recvmbox_info; + struct gazelle_memory_info acceptmbox_info; +}; + +struct gazelle_stack_meminfo_stats { + uint32_t sock_num; + double nic_rx_queue_mem; + double nic_tx_queue_mem; + double total_ring_mem; + struct gazelle_ring_meminfo_stats ring_mem[GAZELLE_MAX_CLIENTS]; + struct gazelle_memory_info rxtx_mempool; + struct gazelle_memory_info rpc_mempool; +}; + +struct gazelle_meminfo_stats { + double total_mem; + double used_mem; + double avail_mem; + double fixed_mem; + struct gazelle_stack_meminfo_stats stack_mem; +}; + struct gazelle_stack_stat { uint64_t wakeup_events; uint64_t write_lwip_cnt; @@ -372,6 +412,7 @@ struct gazelle_stack_dfx_data { struct nic_eth_features nic_features; struct gazelle_stat_lstack_proto proto_data; struct interrupt_stats intr_stats; + struct gazelle_meminfo_stats mem_stats; #ifdef GAZELLE_FAULT_INJECT_ENABLE struct gazelle_fault_inject_data inject; diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c index 3023a6cb3c6f18378bec4ba4ccc760669b7093f5..11da02ec78430664a7b554b72b222b3bc38d212a 100644 --- a/src/lstack/core/lstack_dpdk.c +++ b/src/lstack/core/lstack_dpdk.c @@ -1058,3 +1058,52 @@ uint32_t dpdk_total_socket_memory(void) return total_socket_memory; } +/* callback func when track all memzones */ +static void filter_fixed_memzone(const struct rte_memzone *mz, void *arg) +{ + double *total = arg; + + if (strstr(mz->name, "mbuf") == NULL && strstr(mz->name, "rpc") == NULL) { + *total += bytes_to_mb(mz->len); + } +} + +void dpdk_heap_stats_get(struct gazelle_stack_dfx_data *dfx) +{ + size_t total_mem = 0; + size_t used_mem = 0; + size_t avail_mem = 0; + struct rte_malloc_socket_stats socket_stats; + + for (uint32_t i = 0; i < RTE_MAX_NUMA_NODES; i++) { + if (rte_malloc_get_socket_stats(i, &socket_stats) || !socket_stats.heap_totalsz_bytes) { + continue; + } + total_mem += socket_stats.heap_totalsz_bytes; + used_mem += socket_stats.heap_allocsz_bytes; + avail_mem += socket_stats.heap_freesz_bytes; + } + dfx->data.mem_stats.total_mem = bytes_to_mb(total_mem); + dfx->data.mem_stats.used_mem = bytes_to_mb(used_mem); + dfx->data.mem_stats.avail_mem = bytes_to_mb(avail_mem); + + /* get fixed_mem excluding mbuf and rpc */ + rte_memzone_walk(filter_fixed_memzone, &dfx->data.mem_stats.fixed_mem); +} + +void dpdk_mempool_stats_get(struct rte_mempool *mp, struct gazelle_memory_info *mem_info) +{ + uint32_t obj_size = 0; + + if (mp == NULL || mem_info == NULL) { + return; + } + + obj_size = mp->header_size + mp->elt_size + mp->trailer_size; + + mem_info->total_size = mp->size; + mem_info->total_mem = bytes_to_mb(mem_info->total_size * obj_size); + + mem_info->avail_size = rte_mempool_avail_count(mp); + mem_info->avail_mem = bytes_to_mb(mem_info->avail_size * obj_size); +} diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c index 648da5863ba7b653ac952436ada81afcfd9518cd..6d6c4f03bee78cc2122eaa20e3be1dde6547ca34 100644 --- a/src/lstack/core/lstack_lwip.c +++ b/src/lstack/core/lstack_lwip.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -1666,3 +1667,54 @@ unsigned same_node_ring_count(struct lwip_sock *sock) return cur_end - cur_begin; } + +static void calculate_ring_meminfo(struct gazelle_memory_info *mem_info, struct rte_ring *ring) +{ + uint32_t obj_size = 0; + + if (mem_info == NULL || ring == NULL) { + return; + } + + obj_size = rte_ring_get_memsize(ring->size); + if (obj_size < 0) { + return; + } + + mem_info->total_size = ring->capacity; + mem_info->avail_size = rte_ring_free_count(ring); + mem_info->total_mem = bytes_to_mb(obj_size + RTE_CACHE_LINE_SIZE); +} + +void get_ring_meminfo(struct gazelle_stack_meminfo_stats *stack_mem) +{ + uint32_t idx = 0; + struct lwip_sock *sock; + struct gazelle_ring_meminfo_stats *ring_mem; + struct protocol_stack *stack = get_protocol_stack(); + + stack_mem->sock_num = stack->conn_num; + for (uint32_t i = 0; i < MEMP_NUM_NETCONN && idx < stack_mem->sock_num; i++) { + sock = lwip_get_socket(i); + if (sock == NULL || sock->conn == NULL) { + continue; + } + + ring_mem = &stack_mem->ring_mem[idx]; + ring_mem->fd = sock->conn->callback_arg.socket; + + calculate_ring_meminfo(&ring_mem->send_ring_info, sock->send_ring); + calculate_ring_meminfo(&ring_mem->recv_ring_info, sock->recv_ring); + if (sock->conn->recvmbox) { + calculate_ring_meminfo(&ring_mem->recvmbox_info, sock->conn->recvmbox->ring); + } + if (sock->conn->acceptmbox) { + calculate_ring_meminfo(&ring_mem->acceptmbox_info, sock->conn->acceptmbox->ring); + } + + stack_mem->total_ring_mem += ring_mem->send_ring_info.total_mem + ring_mem->recv_ring_info.total_mem + + ring_mem->recvmbox_info.total_mem + ring_mem->acceptmbox_info.total_mem; + + idx++; + } +} \ No newline at end of file diff --git a/src/lstack/core/lstack_stack_stat.c b/src/lstack/core/lstack_stack_stat.c index c88da8f043d4f57247865a56ec8ea6193d44b391..92ec5e2fbd476ea7124b9cc6350c232cd29ca452 100644 --- a/src/lstack/core/lstack_stack_stat.c +++ b/src/lstack/core/lstack_stack_stat.c @@ -302,6 +302,22 @@ static void get_stack_dfx_data_proto(struct gazelle_stack_dfx_data *dfx, struct } } +static void get_stack_memory_usage(struct gazelle_stack_dfx_data *dfx, struct protocol_stack* stack) +{ + int ret = 0; + struct gazelle_stack_meminfo_stats *stack_mem = &dfx->data.mem_stats.stack_mem; + + dpdk_heap_stats_get(dfx); + + ret = rpc_call_meminfo(&stack->dfx_rpc_queue, stack_mem); + if (ret != EOK) { + LSTACK_LOG(ERR, LSTACK, "get stack memory info failed ret=%d \n", ret); + return; + } + + dpdk_mempool_stats_get(rpc_pool_get(), &stack_mem->rpc_mempool); +} + static void get_stack_dfx_data(struct gazelle_stack_dfx_data *dfx, struct protocol_stack *stack, struct gazelle_stat_msg_request *msg) { @@ -364,6 +380,9 @@ static void get_stack_dfx_data(struct gazelle_stack_dfx_data *dfx, struct protoc case GAZELLE_STAT_LSTACK_SHOW_PROTOCOL: get_stack_dfx_data_proto(dfx, stack, msg); break; + case GAZELLE_STAT_LSTACK_SHOW_MEMORY_USAGE: + get_stack_memory_usage(dfx, stack); + break; default: break; } diff --git a/src/lstack/core/lstack_thread_rpc.c b/src/lstack/core/lstack_thread_rpc.c index 26bd16aa4fc10bed3dc1c05370d8a671fe330429..4c2c2e82294dc9226830dc2bf0bb929a43995886 100644 --- a/src/lstack/core/lstack_thread_rpc.c +++ b/src/lstack/core/lstack_thread_rpc.c @@ -32,6 +32,14 @@ struct rpc_stats *rpc_stats_get(void) return &g_rpc_stats; } +struct rte_mempool *rpc_pool_get(void) +{ + if (g_rpc_pool != NULL) { + return g_rpc_pool->mempool; + } + return NULL; +} + __rte_always_inline static struct rpc_msg *get_rpc_msg(struct rpc_msg_pool *rpc_pool) { @@ -780,6 +788,25 @@ static void callback_get_connnum(struct rpc_msg *msg) msg->result = do_lwip_get_connnum(); } +static void callback_get_meminfo(struct rpc_msg *msg) +{ + uint32_t obj_size = 0; + struct protocol_stack *stack = get_protocol_stack(); + struct gazelle_stack_meminfo_stats *stack_mem = (struct gazelle_stack_meminfo_stats *)msg->args[MSG_ARG_0].p; + + /* ring memory info */ + get_ring_meminfo(stack_mem); + + /* rxtx_pktmempool memory info */ + dpdk_mempool_stats_get(stack->rxtx_mbuf_pool, &stack_mem->rxtx_mempool); + + /* nic rxtx queue memory info */ + obj_size = stack->rxtx_mbuf_pool->elt_size + stack->rxtx_mbuf_pool->header_size + + stack->rxtx_mbuf_pool->trailer_size; + stack_mem->nic_tx_queue_mem = bytes_to_mb(get_global_cfg_params()->txqueue_size * obj_size); + stack_mem->nic_rx_queue_mem = bytes_to_mb(get_global_cfg_params()->rxqueue_size * obj_size); +} + int rpc_call_conntable(rpc_queue *queue, void *conn_table, unsigned max_conn) { struct rpc_msg *msg = rpc_msg_alloc(callback_get_conntable); @@ -813,6 +840,18 @@ int rpc_call_mbufpoolsize(rpc_queue *queue) return rpc_sync_call(queue, msg); } +int rpc_call_meminfo(rpc_queue *queue, void *memory) +{ + struct rpc_msg *msg = rpc_msg_alloc(callback_get_meminfo); + if (msg == NULL) { + return -1; + } + + msg->args[MSG_ARG_0].p = memory; + + return rpc_sync_call(queue, msg); +} + extern void thread_register_phase1(struct rpc_msg *msg); int rpc_call_thread_regphase1(rpc_queue *queue, void *conn) { diff --git a/src/lstack/include/lstack_dpdk.h b/src/lstack/include/lstack_dpdk.h index c2142d695845a451030761c46740e6382d1c0023..5a2a91ffdab6fb427ff9140a8cfc00e9e9f34ec4 100644 --- a/src/lstack/include/lstack_dpdk.h +++ b/src/lstack/include/lstack_dpdk.h @@ -63,6 +63,8 @@ int32_t dpdk_init_lstack_kni(void); void dpdk_nic_xstats_get(struct gazelle_stack_dfx_data *dfx, uint16_t port_id); void dpdk_nic_features_get(struct gazelle_stack_dfx_data *dfx, uint16_t port_id); +void dpdk_heap_stats_get(struct gazelle_stack_dfx_data *dfx); +void dpdk_mempool_stats_get(struct rte_mempool *mp, struct gazelle_memory_info *mem_info); bool dpdk_nic_is_xdp(void); uint32_t dpdk_pktmbuf_mempool_num(void); diff --git a/src/lstack/include/lstack_lwip.h b/src/lstack/include/lstack_lwip.h index dcb7dac0594e7061215d7778abf4201b7b1981bd..13d7e0d446b2c50f93f29aced4545d05f4173886 100644 --- a/src/lstack/include/lstack_lwip.h +++ b/src/lstack/include/lstack_lwip.h @@ -64,5 +64,6 @@ uint32_t do_lwip_get_conntable(struct gazelle_stat_lstack_conn_info *conn, uint3 uint32_t do_lwip_get_connnum(void); void read_same_node_recv_list(struct protocol_stack *stack); +void get_ring_meminfo(struct gazelle_stack_meminfo_stats *stack_mem); #endif diff --git a/src/lstack/include/lstack_thread_rpc.h b/src/lstack/include/lstack_thread_rpc.h index c74981fcf668be109dec9068675216b7df243048..33e7ece6ad038a0d912f0440068a28a590fedfdd 100644 --- a/src/lstack/include/lstack_thread_rpc.h +++ b/src/lstack/include/lstack_thread_rpc.h @@ -73,6 +73,7 @@ static inline void rpc_queue_init(rpc_queue *queue, uint16_t queue_id) queue->queue_id = queue_id; } struct rpc_stats *rpc_stats_get(void); +struct rte_mempool *rpc_pool_get(void); int rpc_msgcnt(rpc_queue *queue); int rpc_poll_msg(rpc_queue *queue, int max_num); @@ -107,6 +108,7 @@ int rpc_call_arp(rpc_queue *queue, void *mbuf); int rpc_call_conntable(rpc_queue *queue, void *conn_table, unsigned max_conn); int rpc_call_connnum(rpc_queue *queue); int rpc_call_mbufpoolsize(rpc_queue *queue); +int rpc_call_meminfo(rpc_queue *queue, void *memory); int rpc_call_thread_regphase1(rpc_queue *queue, void *conn); int rpc_call_thread_regphase2(rpc_queue *queue, void *conn); diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c index f6d1148e198ceb7f8c98448e47ec108fbd74f532..9f45aa20a4dc70cec6c9e7a6c53c562fdf207fa4 100644 --- a/src/ltran/ltran_dfx.c +++ b/src/ltran/ltran_dfx.c @@ -39,6 +39,7 @@ #define GAZELLE_OPTIONS1_ARG_IDX 4 #define GAZELLE_OPTIONS2_ARG_IDX 5 #define GAZELLE_OPT_LPM_ARG_IDX1 5 +#define GAZELLE_OPTIONS3_ARG_IDX 6 #define GAZELLE_PARAM_MINNUM 2 #define GAZELLE_LTRAN_PARAM_NUM 3 @@ -139,6 +140,7 @@ static void gazelle_print_lstack_aggregate(void *buf, const struct gazelle_stat_ 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); +static void gazelle_print_lstack_memory_usage(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); @@ -174,14 +176,17 @@ static struct gazelle_dfx_list g_gazelle_dfx_tbl[] = { {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}, - + {GAZELLE_STAT_LSTACK_SHOW_MEMORY_USAGE, sizeof(struct gazelle_stack_dfx_data), gazelle_print_lstack_memory_usage}, + #ifdef GAZELLE_FAULT_INJECT_ENABLE {GAZELLE_STAT_FAULT_INJECT_SET, sizeof(struct gazelle_stack_dfx_data), gazelle_print_fault_inject_set_status}, {GAZELLE_STAT_FAULT_INJECT_UNSET, sizeof(struct gazelle_stack_dfx_data), gazelle_print_fault_inject_unset_status}, #endif /* GAZELLE_FAULT_INJECT_ENABLE */ }; -static int32_t g_wait_reply = 1; +static int g_wait_reply = 1; +static int g_repeat_times = 0; +static int g_repeat_interval = 0; static double rate_convert_type(uint64_t bytes, char **type) { @@ -200,6 +205,25 @@ static double rate_convert_type(uint64_t bytes, char **type) return now; } +static void gazelle_localtime_string(char *str, int buff_len) +{ + int ret; + int year_base = 1900; + struct timeval tv; + struct tm *tm; + time_t time; + + gettimeofday(&tv, NULL); + time = tv.tv_sec; + tm = localtime(&time); + ret = sprintf_s(str, buff_len, "%04d-%02d-%02d %02d:%02d:%02d", + tm->tm_year + year_base, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); + if (ret < 0) { + printf("gazelle_localtime_string sprintf_s fail ret=%d\n", ret); + return; + } +} + static void gazelle_print_lstack_xstats(void *buf, const struct gazelle_stat_msg_request *req_msg) { struct gazelle_stack_dfx_data *stat = (struct gazelle_stack_dfx_data *)buf; @@ -1031,7 +1055,7 @@ static void gazelle_print_ltran_stat_lb_rate(void *buf, const struct gazelle_sta if (stack_index >= GAZELLE_MAX_STACK_ARRAY_SIZE) { break; } - + if (g_ltran_lb_rate_show_flag[stack_index] == GAZELLE_ON) { printf("------ Statistics of lstack rate stack tid: %6u ------\n", stats->tid); printf("rx_pkts: %-15"PRIu64" ", (stats->rx - g_last_lstack_total[stack_index].rx) / @@ -1055,17 +1079,17 @@ static void gazelle_print_ltran_stat_lb_rate(void *buf, const struct gazelle_sta } else { g_ltran_lb_rate_show_flag[stack_index] = GAZELLE_ON; } - + ret = memcpy_s(&g_last_lstack_total[stack_index], sizeof(*stats), stats, sizeof(struct gazelle_stat_lstack_total)); if (ret != EOK) { printf("%s:%d memcpy_s fail ret=%d\n", __FUNCTION__, __LINE__, ret); } - + if (stats->eof != 0) { break; } - + ret = dfx_stat_read_from_ltran(buf, sizeof(struct gazelle_stat_lstack_total), req_msg->stat_mode); if (ret != GAZELLE_OK) { return; @@ -1225,6 +1249,97 @@ static void gazelle_print_lstack_stat_virtio(void *buf, const struct gazelle_sta printf("\n"); } +static void gazelle_print_ring_stat_memory(uint32_t idx, struct gazelle_ring_meminfo_stats *ring_mem) +{ + struct gazelle_ring_meminfo_stats *rm = ring_mem; + /* "No.", "fd", "mem & size", "send_ring", "recv_ring", "recvmbox", "acceptmbox" */ + printf("%-6d%-6d%-15s%-12.4lf%-12.4lf%-12.4lf%-12.4lf\n", idx, rm->fd, "mem_total(M)", + rm->send_ring_info.total_mem, rm->recv_ring_info.total_mem, + rm->recvmbox_info.total_mem, rm->acceptmbox_info.total_mem); + + printf("%-12s%-15s%-12d%-12d%-12d%-12d\n", "", "size_total", + rm->send_ring_info.total_size, rm->recv_ring_info.total_size, + rm->recvmbox_info.total_size, rm->acceptmbox_info.total_size); + + printf("%-12s%-15s%-12d%-12d%-12d%-12d\n", "", "size_avail", + rm->send_ring_info.avail_size, rm->recv_ring_info.avail_size, + rm->recvmbox_info.avail_size, rm->acceptmbox_info.avail_size); +} + +static void gazelle_print_lstack_stack_meminfo(void *buf, const struct gazelle_stat_msg_request *req_msg) +{ + double rxtxpool_percent = 0; + double rpcpool_percent = 0; + char sys_local_time_str[GAZELLE_TIME_STR_LEN] = {0}; + struct gazelle_ring_meminfo_stats *ring_mem; + struct gazelle_stack_meminfo_stats* stack_mem; + struct gazelle_stack_dfx_data *stat = (struct gazelle_stack_dfx_data *)buf; + + stack_mem = &stat->data.mem_stats.stack_mem; + if (stack_mem->rxtx_mempool.total_mem != 0) { + rxtxpool_percent = + convert_to_percent(stack_mem->rxtx_mempool.avail_mem / stack_mem->rxtx_mempool.total_mem); + } + if (stack_mem->rpc_mempool.total_mem != 0) { + rpcpool_percent = + convert_to_percent(stack_mem->rpc_mempool.avail_mem / stack_mem->rpc_mempool.total_mem); + } + + gazelle_localtime_string(sys_local_time_str, GAZELLE_TIME_STR_LEN); + printf("\n------ stack tid: %6u ------ time = %s----------------\n", stat->tid, sys_local_time_str); + printf("rxtx_mempool mem(M): total: %-10.4lf", stack_mem->rxtx_mempool.total_mem); + printf("avail: %.4lf(%.2lf%%)\n", stack_mem->rxtx_mempool.avail_mem, rxtxpool_percent); + printf("rpc_mempool mem(M): total: %-10.4lf", stack_mem->rpc_mempool.total_mem); + printf("avail: %.4lf(%.2lf%%)\n", stack_mem->rpc_mempool.avail_mem, rpcpool_percent); + printf("nic_rx_queue mem(M): total: %.4lf\n", stack_mem->nic_rx_queue_mem); + printf("nic_tx_queue mem(M): total: %.4lf\n", stack_mem->nic_tx_queue_mem); + printf("ring mem(M): total: %.4lf\n", stack_mem->total_ring_mem); + printf("The ring memory usage of each connection is as follows:\n"); + printf("%-6s%-6s%-15s%-12s%-12s%-12s%-12s\n", + "No.", "fd", "mem & size", "send_ring", "recv_ring", "recvmbox", "acceptmbox"); + + for (int i = 0; i < stack_mem->sock_num; i++) { + ring_mem = &stack_mem->ring_mem[i]; + gazelle_print_ring_stat_memory(i, ring_mem); + } + printf("--------------------------------------------------------------------------\n"); +} + +static void gazelle_print_lstack_meminfo_overview(struct gazelle_stack_dfx_data *buf, + const struct gazelle_stat_msg_request *req_msg) +{ + struct gazelle_meminfo_stats mem_stats = buf->data.mem_stats; + + printf("total(M): %.2lf\n", mem_stats.total_mem); + printf("used(M): %.2lf (%.2lf%%)\n", mem_stats.used_mem, + convert_to_percent(mem_stats.used_mem / mem_stats.total_mem)); + printf("avail(M): %.2lf (%.2lf%%)\n", mem_stats.avail_mem, + convert_to_percent(mem_stats.avail_mem / mem_stats.total_mem)); +} + +static void gazelle_print_lstack_memory_usage(void *buf, const struct gazelle_stat_msg_request *req_msg) +{ + int ret = 0; + struct gazelle_stack_dfx_data *stat = (struct gazelle_stack_dfx_data *)buf; + + gazelle_print_lstack_meminfo_overview(stat, req_msg); + + do { + gazelle_print_lstack_stack_meminfo(buf, req_msg); + + 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) { + break; + } + } while (true); + + printf("other mem(M): total: %.4lf\n", stat->data.mem_stats.fixed_mem); +} + static void gazelle_keepalive_string(char* str, int buff_len, struct gazelle_stat_lstack_conn_info *conn_info) { if (conn_info->keepalive == 0) { @@ -1238,21 +1353,6 @@ static void gazelle_keepalive_string(char* str, int buff_len, struct gazelle_sta } } -static void gazelle_localtime_string(char* str, int buff_len) -{ - struct timeval time = {0}; - gettimeofday(&time, NULL); - struct tm* tm; - time_t t = time.tv_sec; - tm = localtime(&t); - int ret = sprintf_s(str, buff_len, "%d-%d-%d %d:%d:%d", - tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); - if (ret < 0) { - printf("gazelle_localtime_string sprintf_s fail ret=%d\n", ret); - return; - } -} - static void gazelle_print_lstack_stat_conn(void *buf, const struct gazelle_stat_msg_request *req_msg) { uint32_t i; @@ -1287,9 +1387,9 @@ static void gazelle_print_lstack_stat_conn(void *buf, const struct gazelle_stat_ if ((conn_info->state == GAZELLE_ACTIVE_LIST) || (conn_info->state == GAZELLE_TIME_WAIT_LIST)) { inet_ntop(domain, lip, str_ip, sizeof(str_ip)); inet_ntop(domain, rip, str_rip, sizeof(str_rip)); - + gazelle_keepalive_string(keepalive_info_str, sizeof(keepalive_info_str)/sizeof(char), conn_info); - + 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" @@ -1362,6 +1462,7 @@ static void show_usage(void) " -k, nic-features show state of protocol offload and other features \n" " -a, aggregatin [time] show lstack send/recv aggregation \n" " -p, protocol {UDP | TCP | ICMP | IP | ETHARP} show lstack protocol statistics \n" + " -m, memory [time] show lstack memory usage \n" " set: \n" " loglevel {error | info | debug} set lstack loglevel \n" " lowpower {0 | 1} set lowpower enable \n" @@ -1570,6 +1671,33 @@ static int parse_delay_arg(int32_t argc, char *argv[], long int delay) return 0; } +static int parse_repeat_arg(int argc, char *argv[]) +{ + int interval = 0; + int times = 0; + char *interval_end = NULL; + char *times_end = NULL; + + if (argc > GAZELLE_OPTIONS2_ARG_IDX) { + interval = strtol(argv[GAZELLE_OPTIONS2_ARG_IDX], &interval_end, GAZELLE_DECIMAL); + if (interval <= 0 || (interval_end == NULL) || (*interval_end != '\0')) { + return -1; + } + } + + if (argc > GAZELLE_OPTIONS3_ARG_IDX) { + times = strtol(argv[GAZELLE_OPTIONS3_ARG_IDX], ×_end, GAZELLE_DECIMAL); + if (times < 0 || (times_end == NULL) || (*times_end != '\0')) { + return -1; + } + } + + g_repeat_times = times; + g_repeat_interval = interval; + + return 0; +} + static int32_t parse_dfx_lstack_show_proto_args(int32_t argc, char *argv[], struct gazelle_stat_msg_request *req_msg) { int32_t cmd_index = 0; @@ -1637,10 +1765,15 @@ static int32_t parse_dfx_lstack_show_args(int32_t argc, char *argv[], struct gaz if (parse_delay_arg(argc, argv, delay) != 0) { return 0; } - } else if (strcmp(param, "-k") == 0 || strcmp(param, "nic-features") == 0) { + } else if (strcmp(param, "nic-features") == 0 || strcmp(param, "-k") == 0) { req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LSTACK_SHOW_NIC_FEATURES; } else if (strcmp(param, "protocol") == 0 || strcmp(param, "-p") == 0) { - cmd_index = parse_dfx_lstack_show_proto_args(argc, argv, req_msg); + cmd_index = parse_dfx_lstack_show_proto_args(argc, argv, req_msg); + } else if (strcmp(param, "memory") == 0 || strcmp(param, "-m") == 0) { + req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LSTACK_SHOW_MEMORY_USAGE; + if (parse_repeat_arg(argc, argv) != 0) { + return 0; + } } return cmd_index; } @@ -1701,21 +1834,21 @@ static void gazelle_print_fault_inject_type_info(struct gazelle_fault_inject_dat if (!inject->fault_inject_on) { return; } - + if (inject->inject_type == GAZELLE_FAULT_INJECT_PACKET_DELAY) { printf("\t| inject_type: delay | delay_time: %-7d | delay_range: %-3d | " "inject_rule: random |\n", inject->inject_data.delay.delay_time, inject->inject_data.delay.delay_range); } - + #define INJECT_PERCENT 100 - + if (inject->inject_type == GAZELLE_FAULT_INJECT_PACKET_LOSS) { printf("\t| inject_type: loss | loss_rate: %-4.1f%% | loss_single_count: %-3d | " "inject_rule: random |\n", inject->inject_data.loss.loss_rate * INJECT_PERCENT, inject->inject_data.loss.loss_sigle_count); } - + if (inject->inject_type == GAZELLE_FAULT_INJECT_PACKAET_DUPLICATE) { printf("\t| inject_type: duplicate | duplicate_rate: %-4.1f%% | duplicate_single_count: %-3d | " "inject_rule: random |\n", inject->inject_data.duplicate.duplicate_rate * INJECT_PERCENT, @@ -1885,15 +2018,15 @@ static int32_t parse_fault_inject_digital_data(char *argv[], struct gazelle_stat static int32_t parse_fault_inject_unset_type(char *argv[], struct gazelle_stat_msg_request *req_msg) { int32_t num_cmd = 0; - + if (strcmp(argv[INJECT_TYPE_INDEX], "unset") != 0) { printf("FAULT_INJECT error: unrecognized input -- %s, should be \"unset\"\n", argv[INJECT_TYPE_INDEX]); return num_cmd; } - + req_msg->data.inject.fault_inject_on = 0; /* unset fault inject */ req_msg->stat_mode = GAZELLE_STAT_FAULT_INJECT_UNSET; - + if (strcmp(argv[INJECT_UNSET_TYPE_INDEX], "all") == 0) { req_msg->data.inject.inject_type = GAZELLE_FAULT_INJECT_TYPE_MAX; return ++num_cmd; @@ -1917,10 +2050,10 @@ static int32_t parse_fault_inject_unset_type(char *argv[], struct gazelle_stat_m static int32_t parse_fault_inject_set_type(char *argv[], struct gazelle_stat_msg_request *req_msg) { int32_t num_cmd = 0; - + req_msg->data.inject.fault_inject_on = 1; /* set fault inject on */ req_msg->stat_mode = GAZELLE_STAT_FAULT_INJECT_SET; - + int32_t inject_type_count = sizeof(inject_type_list) / sizeof(inject_type_list[0]); for (int32_t i = 0; i < inject_type_count; ++i) { if (strcmp(inject_type_list[i].inject_type_item, argv[INJECT_TYPE_INDEX]) == 0) { @@ -1947,7 +2080,7 @@ static int32_t parse_fault_inject_set_type(char *argv[], struct gazelle_stat_msg } num_cmd = parse_fault_inject_digital_data(argv, req_msg); - + return num_cmd; } @@ -1959,12 +2092,12 @@ static int32_t parse_dfx_fault_inject_args(int32_t argc, char *argv[], struct ga num_cmd = parse_fault_inject_unset_type(argv, req_msg); return num_cmd; } - + if (argc == GAZELLE_SET_FAULT_INJECT_PARAM_COUNT) { num_cmd = parse_fault_inject_set_type(argv, req_msg); return num_cmd; } - + printf("FAULT_INJECT error: Count of params wrong , correct count is 6 or 4, now is %d\n", argc); return num_cmd; } @@ -2027,6 +2160,7 @@ int32_t dfx_loop(struct gazelle_stat_msg_request *req_msg, int32_t req_msg_num) { int32_t ret; int32_t msg_index = 0; + int32_t repeat_times = 0; struct gazelle_dfx_list *dfx = NULL; char recv_buf[GAZELLE_CMD_RESP_BUFFER_SIZE + 1] = {0}; @@ -2054,6 +2188,13 @@ int32_t dfx_loop(struct gazelle_stat_msg_request *req_msg, int32_t req_msg_num) g_unix_fd = -1; } + if (g_repeat_interval != 0 && (g_repeat_times == 0 || repeat_times < g_repeat_times)) { + repeat_times++; + sleep(g_repeat_interval); + continue; + } + repeat_times = 0; + msg_index++; if (msg_index >= req_msg_num) { break;