From e7741141d04005e9d4bdaa8f29b9f9f17f36ba90 Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 22 Aug 2017 05:12:53 -0400 Subject: [PATCH] add top tool --- lib/ff_dpdk_if.c | 41 +++++++++++++++++- lib/ff_msg.h | 10 +++++ tools/Makefile | 2 +- tools/README.md | 26 +++++++++++ tools/top/Makefile | 9 ++++ tools/top/top.c | 105 +++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 190 insertions(+), 3 deletions(-) create mode 100644 tools/top/Makefile create mode 100644 tools/top/top.c diff --git a/lib/ff_dpdk_if.c b/lib/ff_dpdk_if.c index 301f8bac..7e4ca038 100644 --- a/lib/ff_dpdk_if.c +++ b/lib/ff_dpdk_if.c @@ -957,6 +957,16 @@ handle_route_msg(struct ff_msg *msg, uint16_t proc_id) rte_ring_enqueue(msg_ring[proc_id].ring[1], msg); } +static struct ff_top_args ff_status; +static inline void +handle_top_msg(struct ff_msg *msg, uint16_t proc_id) +{ + msg->top = ff_status; + msg->result = 0; + + rte_ring_enqueue(msg_ring[proc_id].ring[1], msg); +} + static inline void handle_default_msg(struct ff_msg *msg, uint16_t proc_id) { @@ -977,6 +987,9 @@ handle_msg(struct ff_msg *msg, uint16_t proc_id) case FF_ROUTE: handle_route_msg(msg, proc_id); break; + case FF_TOP: + handle_top_msg(msg, proc_id); + break; default: handle_default_msg(msg, proc_id); break; @@ -1134,8 +1147,8 @@ main_loop(void *arg) struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; unsigned lcore_id; - uint64_t prev_tsc, diff_tsc, cur_tsc; - int i, j, nb_rx; + uint64_t prev_tsc, diff_tsc, cur_tsc, div_tsc, usr_tsc, sys_tsc, end_tsc; + int i, j, nb_rx, idle; uint8_t port_id, queue_id; struct lcore_conf *qconf; const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / @@ -1158,6 +1171,10 @@ main_loop(void *arg) rte_timer_manage(); } + idle = 1; + sys_tsc = 0; + usr_tsc = 0; + /* * TX burst queue drain */ @@ -1170,6 +1187,8 @@ main_loop(void *arg) for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) { if (qconf->tx_mbufs[port_id].len == 0) continue; + + idle = 0; send_burst(qconf, qconf->tx_mbufs[port_id].len, port_id); @@ -1198,6 +1217,8 @@ main_loop(void *arg) if (nb_rx == 0) continue; + idle = 0; + /* Prefetch first packets */ for (j = 0; j < PREFETCH_OFFSET && j < nb_rx; j++) { rte_prefetch0(rte_pktmbuf_mtod( @@ -1219,9 +1240,25 @@ main_loop(void *arg) process_msg_ring(qconf->proc_id); + div_tsc = rte_rdtsc(); + if (likely(lr->loop != NULL)) { lr->loop(lr->arg); } + + end_tsc = rte_rdtsc(); + usr_tsc = end_tsc - div_tsc; + + if (!idle) { + sys_tsc = div_tsc - cur_tsc; + ff_status.sys_tsc += sys_tsc; + } + + ff_status.usr_tsc += usr_tsc; + ff_status.work_tsc += end_tsc - cur_tsc; + ff_status.idle_tsc += end_tsc - cur_tsc - usr_tsc - sys_tsc; + + ff_status.loops++; } } diff --git a/lib/ff_msg.h b/lib/ff_msg.h index c6ef4d38..0dc8e6da 100644 --- a/lib/ff_msg.h +++ b/lib/ff_msg.h @@ -39,6 +39,7 @@ enum FF_MSG_TYPE { FF_SYSCTL, FF_IOCTL, FF_ROUTE, + FF_TOP, }; struct ff_sysctl_args { @@ -62,6 +63,14 @@ struct ff_route_args { void *data; }; +struct ff_top_args { + unsigned long loops; + unsigned long idle_tsc; + unsigned long work_tsc; + unsigned long sys_tsc; + unsigned long usr_tsc; +}; + #define MAX_MSG_BUF_SIZE 10240 /* structure of ipc msg */ @@ -78,6 +87,7 @@ struct ff_msg { struct ff_sysctl_args sysctl; struct ff_ioctl_args ioctl; struct ff_route_args route; + struct ff_top_args top; }; } __attribute__((packed)) __rte_cache_aligned; diff --git a/tools/Makefile b/tools/Makefile index ee47229b..d8d55237 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -1,4 +1,4 @@ -SUBDIRS=compat sysctl ifconfig route +SUBDIRS=compat sysctl ifconfig route top all: for d in $(SUBDIRS); do ( cd $$d; $(MAKE) all ) ; done diff --git a/tools/README.md b/tools/README.md index 1e50054d..05253d60 100644 --- a/tools/README.md +++ b/tools/README.md @@ -85,6 +85,32 @@ Note that, if you want to modify the route table, you must use `-p` to execute t For more details, see [Manual page](https://www.freebsd.org/cgi/man.cgi?route). +# top +Usage: +``` +top [-p ] [-d ] [-n num] +``` +Examples: +``` +./tools/top/top + +|---------|---------|---------|---------------| +| idle| sys| usr| loop| +|---------|---------|---------|---------------| +| 99.69%| 0.00%| 0.31%| 8214640| +| 99.77%| 0.00%| 0.23%| 8205713| +| 5.02%| 45.19%| 49.79%| 769435| +| 0.00%| 19.88%| 80.12%| 393| +| 0.00%| 20.28%| 79.72%| 395| +| 0.00%| 15.50%| 84.50%| 403| +| 0.00%| 31.31%| 68.69%| 427| +| 32.07%| 8.78%| 59.15%| 2342862| +| 99.79%| 0.00%| 0.21%| 9974439| +| 99.81%| 0.00%| 0.19%| 7336153| +| 99.79%| 0.00%| 0.21%| 8147676| +``` + + # how to implement a custom tool for communicating with F-Stack process Add a new FF_MSG_TYPE in ff_msg.h: diff --git a/tools/top/Makefile b/tools/top/Makefile new file mode 100644 index 00000000..ae749491 --- /dev/null +++ b/tools/top/Makefile @@ -0,0 +1,9 @@ +# @(#)Makefile 8.1 (Berkeley) 6/6/93 +# $FreeBSD$ + + +TOPDIR?=${CURDIR}/../.. + +PROG=top + +include ${TOPDIR}/tools/prog.mk diff --git a/tools/top/top.c b/tools/top/top.c new file mode 100644 index 00000000..4473926b --- /dev/null +++ b/tools/top/top.c @@ -0,0 +1,105 @@ +#include +#include "ff_ipc.h" + +void +usage(void) +{ + printf("Usage:\n"); + printf(" top [-p ] [-d ] [-n num]\n"); +} + +int cpu_status(struct ff_top_args *top) +{ + int ret; + struct ff_msg *msg, *retmsg = NULL; + + msg = ff_ipc_msg_alloc(); + if (msg == NULL) { + errno = ENOMEM; + return -1; + } + + msg->msg_type = FF_TOP; + ret = ff_ipc_send(msg); + if (ret < 0) { + errno = EPIPE; + ff_ipc_msg_free(msg); + return -1; + } + + do { + if (retmsg != NULL) { + ff_ipc_msg_free(retmsg); + } + + ret = ff_ipc_recv(&retmsg); + if (ret < 0) { + errno = EPIPE; + ff_ipc_msg_free(msg); + return -1; + } + } while (msg != retmsg); + + *top = retmsg->top; + + ff_ipc_msg_free(msg); + + return 0; +} + +int main(int argc, char **argv) +{ + int ch, delay = 1, n = 0; + unsigned int i; + struct ff_top_args top, otop; + +#define TOP_DIFF(member) (top.member - otop.member) + + while ((ch = getopt(argc, argv, "hp:d:n:")) != -1) { + switch(ch) { + case 'p': + ff_set_proc_id(atoi(optarg)); + break; + case 'd': + delay = atoi(optarg) ?: 1; + break; + case 'n': + n = atoi(optarg); + break; + case 'h': + default: + usage(); + return -1; + } + } + + for (i = 0; ; i++) { + if (cpu_status(&top)) { + printf("fstack ipc message error !\n"); + return -1; + } + + if (i % 40 == 0) { + printf("|---------|---------|---------|---------------|\n"); + printf("|%9s|%9s|%9s|%15s|\n", "idle", "sys", "usr", "loop"); + printf("|---------|---------|---------|---------------|\n"); + } + + if (i) { + float psys = TOP_DIFF(sys_tsc) / (TOP_DIFF(work_tsc) / 100.0); + float pusr = TOP_DIFF(usr_tsc) / (TOP_DIFF(work_tsc) / 100.0); + float pidle = TOP_DIFF(idle_tsc) / (TOP_DIFF(work_tsc) / 100.0); + + printf("|%8.2f%%|%8.2f%%|%8.2f%%|%15lu|\n", pidle, psys, pusr, TOP_DIFF(loops)); + } + + if (n && i >= n) { + break; + } + + otop = top; + sleep(delay); + } + + return 0; +}