diff options
-rw-r--r-- | conf.c | 8 | ||||
-rw-r--r-- | passt.1 | 5 | ||||
-rw-r--r-- | passt.c | 58 | ||||
-rw-r--r-- | passt.h | 2 |
4 files changed, 73 insertions, 0 deletions
@@ -835,6 +835,8 @@ static void usage(const char *name, FILE *f, int status) "\n" " -d, --debug Be verbose\n" " --trace Be extra verbose, implies --debug\n" + " --stats DELAY Display events statistics\n" + " minimum DELAY seconds between updates\n" " -q, --quiet Don't print informational messages\n" " -f, --foreground Don't run in background\n" " default: run in background\n" @@ -1480,6 +1482,7 @@ void conf(struct ctx *c, int argc, char **argv) {"repair-path", required_argument, NULL, 28 }, {"migrate-exit", no_argument, NULL, 29 }, {"migrate-no-linger", no_argument, NULL, 30 }, + {"stats", required_argument, NULL, 31 }, { 0 }, }; const char *optstring = "+dqfel:hs:F:I:p:P:m:a:n:M:g:i:o:D:S:H:461t:u:T:U:"; @@ -1709,6 +1712,11 @@ void conf(struct ctx *c, int argc, char **argv) c->migrate_no_linger = true; break; + case 31: + if (!c->foreground) + die("Can't display statistics if not running in foreground"); + c->stats = strtol(optarg, NULL, 0); + break; case 'd': c->debug = 1; c->quiet = 0; @@ -85,6 +85,11 @@ Be verbose, don't log to the system logger. Be extra verbose, show single packets. Implies \fB--debug\fR. .TP +.BR \-\-stats " " \fIDELAY\fR +Display events statistics with a minimum \fIDELAY\fR seconds between updates. +If there is no event, statistics are not displayed. + +.TP .BR \-q ", " \-\-quiet Don't print informational messages. @@ -84,6 +84,14 @@ static_assert(ARRAY_SIZE(epoll_type_str) == EPOLL_NUM_TYPES, "epoll_type_str[] doesn't match enum epoll_type"); /** + * struct passt_stats - Statistics + * @events: Event counters for epoll type events + */ +struct passt_stats { + unsigned long events[EPOLL_NUM_TYPES]; +}; + +/** * post_handler() - Run periodic and deferred tasks for L4 protocol handlers * @c: Execution context * @now: Current timestamp @@ -175,6 +183,53 @@ static void exit_handler(int signal) } /** + * print_stats() - Print event statistics table to stderr + * @c: Execution context + * @stats: Event counters + * @now: Current timestamp + */ +static void print_stats(const struct ctx *c, const struct passt_stats *stats, + const struct timespec *now) +{ + static struct timespec before; + static int lines_printed; + long long elapsed_ns; + int i; + + if (!c->stats) + return; + + elapsed_ns = (now->tv_sec - before.tv_sec) * 1000000000LL + + (now->tv_nsec - before.tv_nsec); + + if (elapsed_ns < c->stats * 1000000000LL) + return; + + before = *now; + + if (!(lines_printed % 20)) { + /* Table header */ + for (i = 1; i < EPOLL_NUM_TYPES; i++) { + int j; + + for (j = 0; j < i * (6 + 1); j++) { + if (j && !(j % (6 + 1))) + FPRINTF(stderr, "|"); + else + FPRINTF(stderr, " "); + } + FPRINTF(stderr, "%s\n", epoll_type_str[i]); + } + } + + FPRINTF(stderr, " "); + for (i = 1; i < EPOLL_NUM_TYPES; i++) + FPRINTF(stderr, " %6lu", stats->events[i]); + FPRINTF(stderr, "\n"); + lines_printed++; +} + +/** * main() - Entry point and main loop * @argc: Argument count * @argv: Options, plus optional target PID for pasta mode @@ -191,6 +246,7 @@ static void exit_handler(int signal) int main(int argc, char **argv) { struct epoll_event events[EPOLL_EVENTS]; + struct passt_stats stats = { 0 }; int nfds, i, devnull_fd = -1; struct ctx c = { 0 }; struct rlimit limit; @@ -362,6 +418,8 @@ loop: /* Can't happen */ ASSERT(0); } + stats.events[ref.type]++; + print_stats(&c, &stats, &now); } post_handler(&c, &now); @@ -187,6 +187,7 @@ struct ip6_ctx { * @mode: Operation mode, qemu/UNIX domain socket or namespace/tap * @debug: Enable debug mode * @trace: Enable tracing (extra debug) mode + * @stats: Events statistics delay (0 means disabled) * @quiet: Don't print informational messages * @foreground: Run in foreground, don't log to stderr by default * @nofile: Maximum number of open files (ulimit -n) @@ -248,6 +249,7 @@ struct ctx { enum passt_modes mode; int debug; int trace; + int stats; int quiet; int foreground; int nofile; |