From 2554af924ab37349ffa518c0e9fd7167b44b9546 Mon Sep 17 00:00:00 2001 From: Alan Maguire Date: Thu, 19 Dec 2024 18:20:48 +0000 Subject: [PATCH] bpftune: add bpftune -q client/server to allow local queries create server for bpftune requests using ephemeral port, port # stored locally in /var/run/bpftune/server-port. Requests supported are list: list requests supported tuners: show tuners,states of each tunables: show tunables summary: summary of changes made example: $ /sbin/bpftune -q summary Summary of changes made across all tuners: Summary: scenario 'need to increase TCP buffer size(s)' occurred 2 times for tunable 'net.ipv4.tcp_wmem' in global ns. Need to increase buffer size(s) to maximize throughput sysctl 'net.ipv4.tcp_wmem' changed from (4096 16384 16384 ) -> (4096 16384 25600 ) Also add query test Signed-off-by: Alan Maguire --- README.md | 2 + docs/bpftune.rst | 16 ++ include/bpftune/libbpftune.h | 33 +++- src/bpftune.c | 44 ++++- src/libbpftune.c | 315 ++++++++++++++++++++++++++++++++++- src/libbpftune.map | 5 + test/Makefile | 1 + test/query_test.sh | 139 ++++++++++++++++ 8 files changed, 550 insertions(+), 5 deletions(-) create mode 100644 test/query_test.sh diff --git a/README.md b/README.md index 9ffea0a..cc4f54e 100644 --- a/README.md +++ b/README.md @@ -240,6 +240,8 @@ $ sudo bpftune -s On exit, bpftune will summarize any tuning done. +Queries of bpftune state can be done via `bpftune -q`. + ## Tests Tests are supplied for each tuner in the tests/ subdirectory. diff --git a/docs/bpftune.rst b/docs/bpftune.rst index 3e5578d..23e3f5c 100644 --- a/docs/bpftune.rst +++ b/docs/bpftune.rst @@ -18,6 +18,8 @@ SYNOPSIS { [**-r** | **--learning_rate** ] learning_rate} { [**-R** | **--rollback** ]} { [**-S** | **--support** ]} + { [**-p** | **--port** ] port} + { [**-q** | **--query**] query} DESCRIPTION =========== @@ -85,3 +87,17 @@ OPTIONS to the system. On exit, bpftune summarizes the changes made and rolls back to the sysctl values that were set prior to bpftune running. + + -p, --port + + TCP port to listen on for queries. If not specified, use an + ephemeral localhost port. + + -q, --query + + Query bpftune. Supported queries include + + help - show supported queries + summary - show summary of changes made by tuners + tuners - show loaded tuners and their state + tunables - show supported tunables for loaded tuners diff --git a/include/bpftune/libbpftune.h b/include/bpftune/libbpftune.h index f69e4ab..2ac6780 100644 --- a/include/bpftune/libbpftune.h +++ b/include/bpftune/libbpftune.h @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include #include #include @@ -37,6 +39,7 @@ #include #include #include +#include #include @@ -44,6 +47,7 @@ #include #define BPFTUNE_RUN_DIR "/var/run/bpftune" +#define BPFTUNE_PORT_FILE BPFTUNE_RUN_DIR "/server-port" #define BPFTUNER_CGROUP_DIR BPFTUNE_RUN_DIR "/cgroupv2" #ifndef BPFTUNER_PREFIX_DIR #define BPFTUNER_PREFIX_DIR "/usr" @@ -65,19 +69,39 @@ #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) #endif +#define BPFTUNE_SERVER_MSG_MAX 65536 + +char *bpftune_state_string[] = { + "inactive", + "active", + "manual", + "gone", +}; + /* level for bpftune tunable updates */ #define BPFTUNE_LOG_LEVEL LOG_NOTICE +/* write to buffer and log using nextlogfn */ +struct bpftune_log_ctx_buf { + void (*nextlogfn)(void *ctx, int level, const char *fmt, va_list args); + pthread_t buf_thread; + char *buf; + size_t buf_off; + size_t buf_sz; +}; + int bpftune_log_level(void); void bpftune_log(int level, const char *fmt, ...); void bpftune_log_stderr(void *ctx, int level, const char *fmt, va_list args); void bpftune_log_syslog(void *ctx, int level, const char *fmt, va_list args); +void bpftune_log_buf(void *ctx, int level, const char *fmt, va_list args); void bpftune_set_log(int level, void (*logfn)(void *ctx, int level, const char *fmt, - va_list args)); + va_list args), + void *ctx); void bpftune_set_bpf_log(bool log); void bpftune_log_bpf_err(int err, const char *fmt); @@ -93,6 +117,13 @@ int bpftune_cgroup_init(const char *cgroup_path); const char *bpftune_cgroup_name(void); int bpftune_cgroup_fd(void); void bpftune_cgroup_fini(void); + +int bpftune_server_start(unsigned short port); +int bpftune_server_port(void); +void bpftune_server_stop(void); +int bpftune_server_request(struct sockaddr_in *server, const char *req, + char *buf, size_t buf_sz); + int bpftuner_cgroup_attach(struct bpftuner *tuner, const char *prog_name, enum bpf_attach_type attach_type); void bpftuner_cgroup_detach(struct bpftuner *tuner, const char *prog_name, diff --git a/src/bpftune.c b/src/bpftune.c index ccb3dda..20530db 100644 --- a/src/bpftune.c +++ b/src/bpftune.c @@ -36,11 +36,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -75,6 +77,7 @@ static void cleanup(int sig) { exiting = true; bpftune_log(LOG_DEBUG, "cleaning up, got signal %d\n", sig); + bpftune_server_stop(); bpftune_ring_buffer_fini(ring_buffer); if (use_stderr) fflush(stderr); @@ -239,6 +242,8 @@ void do_help(void) " { -L|--legacy}\n" " { -h|--help}}\n" " { -l|--library_path library_path}\n" + " { -p|--port port}\n" + " { -q|--query query}\n" " { -r|--learning_rate learning_rate}\n" " { -R|--rollback}\n" " { -s|--stderr}\n" @@ -292,6 +297,8 @@ int main(int argc, char *argv[]) { "help", no_argument, NULL, 'h' }, { "libdir", required_argument, NULL, 'l' }, { "learning_rate", required_argument, NULL, 'r' }, + { "port", required_argument, NULL, 'p' }, + { "query", required_argument, NULL, 'q' }, { "rollback", no_argument, NULL, 'R' }, { "stderr", no_argument, NULL, 's' }, { "support", no_argument, NULL, 'S' }, @@ -306,12 +313,15 @@ int main(int argc, char *argv[]) int log_level = BPFTUNE_LOG_LEVEL; struct sigaction sa = {}, oldsa = {}; bool support_only = false; + bool client = false; + char *query = NULL; int interval = 100; + unsigned short port = 0; int err, opt; bin_name = argv[0]; - while ((opt = getopt_long(argc, argv, "a:c:dDhl:Lr:RsSV", options, NULL)) + while ((opt = getopt_long(argc, argv, "a:c:dDhl:Lr:p:q:RsSV", options, NULL)) >= 0) { switch (opt) { case 'a': @@ -347,6 +357,14 @@ int main(int argc, char *argv[]) return 1; } break; + case 'p': + port = (unsigned short)atoi(optarg); + break; + case 'q': + query = optarg; + client = true; + use_stderr = true; + break; case 'R': rollback = true; break; @@ -367,7 +385,24 @@ int main(int argc, char *argv[]) } } - bpftune_set_log(log_level, use_stderr ? bpftune_log_stderr : bpftune_log_syslog); + bpftune_set_log(log_level, + use_stderr ? bpftune_log_stderr : bpftune_log_syslog, + NULL); + + if (client) { + char buf[BPFTUNE_SERVER_MSG_MAX]; + struct sockaddr_in server; + + memset(&server, 0, sizeof(server)); + server.sin_family = AF_INET; + server.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + server.sin_port = htons(port); + + err = bpftune_server_request(&server, query, buf, sizeof(buf)); + if (err == 0) + fprintf(stdout, "%s\n", buf); + return err; + } bpftune_set_learning_rate(rate); @@ -382,7 +417,7 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); /* need to setup cgroup prior to probe as probe program uses sysctl */ - err = mkdir(BPFTUNE_RUN_DIR, 0700); + err = mkdir(BPFTUNE_RUN_DIR, 0755); if (err && errno != EEXIST) { bpftune_log(BPFTUNE_LOG_LEVEL, "could not create '%s': %s\n", BPFTUNE_RUN_DIR, strerror(errno)); @@ -401,6 +436,9 @@ int main(int argc, char *argv[]) if (support_only) return 0; + if (bpftune_server_start(port) != 0) + exit(EXIT_FAILURE); + bpftune_cap_drop(); err = init(BPFTUNER_LIB_DIR); diff --git a/src/libbpftune.c b/src/libbpftune.c index 70aa89e..98a4ab0 100644 --- a/src/libbpftune.c +++ b/src/libbpftune.c @@ -39,6 +39,8 @@ #include #include #include +#include +#include #include #include #include @@ -46,6 +48,7 @@ #include #include #include +#include unsigned short bpftune_learning_rate; @@ -99,6 +102,23 @@ void bpftune_log_syslog(__attribute__((unused)) void *ctx, int level, syslog(level, buf, buflen + 1); } +/* log to ctx buffer as well as usual log destination */ +void bpftune_log_buf(void *ctx, int level, const char *fmt, va_list args) +{ + struct bpftune_log_ctx_buf *c = ctx; + va_list nextargs; + + va_copy(nextargs, args); + if (!c) + return; + if (c->buf_thread == pthread_self() && c->buf_off <= c->buf_sz) { + c->buf_off += vsnprintf(c->buf + c->buf_off, + c->buf_sz - c->buf_off, fmt, args); + } + c->nextlogfn(ctx, level, fmt, nextargs); + va_end(nextargs); +} + void (*bpftune_logfn)(void *ctx, int level, const char *fmt, va_list args) = bpftune_log_stderr; @@ -156,11 +176,13 @@ void bpftune_set_bpf_log(bool log) void bpftune_set_log(int level, void (*logfn)(void *ctx, int level, const char *fmt, - va_list args)) + va_list args), + void *ctx) { if (logfn) bpftune_logfn = logfn; bpftune_loglevel = level; + bpftune_log_ctx = ctx; if (logfn == bpftune_log_syslog) { setlogmask(LOG_UPTO(level)); openlog("bpftune", LOG_NDELAY | LOG_PID, LOG_DAEMON); @@ -1901,3 +1923,294 @@ void bpftuner_rollback_set(struct bpftuner *tuner) { tuner->rollback = true; } + +struct bpftune_req { + const char *name; + const char *description; + void (*handler)(const char *, char *, size_t); +}; + +static void bpftune_help_handler(const char *req, char *buf, size_t buf_sz); +static void bpftune_tuners_handler(const char *req, char *buf, size_t buf_sz); +static void bpftune_tunables_handler(const char *req, char *buf, size_t buf_sz); +static void bpftune_summary_handler(const char *req, char *buf, size_t buf_sz); + +/* add bpftune server requests with handlers here */ +struct bpftune_req bpftune_reqs[] = { + { "help", "list supported queries", bpftune_help_handler }, + { "tuners", "show state of tuners", bpftune_tuners_handler }, + { "tunables", "show list of tunables", bpftune_tunables_handler }, + { "summary", "show summary of changes", bpftune_summary_handler }, +}; + +static void bpftune_help_handler(__attribute__((unused)) const char *req, + char *buf, size_t buf_sz) +{ + unsigned long i; + int off = 0; + + for (i = 0; i < ARRAY_SIZE(bpftune_reqs); i++) { + off += snprintf(buf + off, buf_sz - off, "%20s %40s\n", + bpftune_reqs[i].name, bpftune_reqs[i].description); + } +} + +static void bpftune_tuners_handler(__attribute__((unused)) const char *req, + char *buf, size_t buf_sz) +{ + struct bpftuner *t; + int off = 0; + + bpftune_for_each_tuner(t) { + off += snprintf(buf + off, buf_sz - off, "%20s %20s\n", + t->name, bpftune_state_string[t->state]); + } +} + +static void bpftune_tunables_handler(__attribute__((unused)) const char *req, + char *buf, size_t buf_sz) +{ + struct bpftuner *t; + int off = 0; + + bpftune_for_each_tuner(t) { + struct bpftunable *u; + unsigned int i; + + for (i = 0; i < t->num_tunables; i++) { + u = bpftuner_tunable(t, i); + off += snprintf(buf + off, buf_sz - off, "%20s %50s\n", + t->name, u->desc.name); + } + } +} + +static void bpftune_summary_handler(__attribute__((unused)) const char *req, + char *buf, size_t buf_sz) +{ + struct bpftune_log_ctx_buf ctx_buf; + struct bpftuner *t; + int off = 0; + + off = snprintf(buf, buf_sz, + "Summary of changes made across all tuners:\n"); + ctx_buf.nextlogfn = bpftune_logfn; + ctx_buf.buf = buf; + ctx_buf.buf_off = off; + ctx_buf.buf_sz = buf_sz; + ctx_buf.buf_thread = pthread_self(); + + /* have summary log to buffer + usual log destination */ + bpftune_set_log(bpftune_loglevel, bpftune_log_buf, &ctx_buf); + + bpftune_for_each_tuner(t) { + unsigned int i, j; + + for (i = 0; i < t->num_tunables; i++) { + for (j = 0; j < t->num_scenarios; j++) { + bpftuner_scenario_log(t, i, j, 0, true); + bpftuner_scenario_log(t, i, j, 1, true); + } + } + } + bpftune_set_log(bpftune_loglevel, ctx_buf.nextlogfn, NULL); + bpftune_log(LOG_DEBUG, "got the following sz %d off %d, orig off %d '%s'\n", + ctx_buf.buf_sz, ctx_buf.buf_off, off, buf); +} + +static bool bpftune_server_running = false; + +void *bpftune_server_thread(void *arg) +{ + unsigned short port = *(unsigned short *)arg; + int fd = socket(AF_INET, SOCK_STREAM, 0); + struct sockaddr_in saddr; + socklen_t len; + + if (fd < 0) { + bpftune_log(LOG_ERR, "could not create server socket: %s\n", + strerror(errno)); + return NULL; + } + memset(&saddr, 0, sizeof(saddr)); + saddr.sin_family = AF_INET; + /* listen on loopback only if no port was specified */ + saddr.sin_addr.s_addr = htonl(port ? INADDR_ANY : INADDR_LOOPBACK); + saddr.sin_port = htons(port); + if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) { + bpftune_log(LOG_ERR, "could not bind server port %d: %s\n", + strerror(errno)); + close(fd); + return NULL; + } + if (listen(fd, 10) < 0) { + bpftune_log(LOG_ERR, "could not listen on server port %d: %s\n", + port, strerror(errno)); + close(fd); + return NULL; + } + if (port == 0) { + len = sizeof(saddr); + + if (!getsockname(fd, &saddr, &len)) + port = ntohs(saddr.sin_port); + } + if (port != 0) { + FILE *fp = fopen(BPFTUNE_PORT_FILE, "w"); + + if (!fp) { + bpftune_log(LOG_ERR, "could not write server port %d to '%s'\n", + port, BPFTUNE_PORT_FILE); + close(fd); + return NULL; + } + fprintf(fp, "%d\n", port); + fclose(fp); + } + bpftune_log(LOG_DEBUG, "server listening on port %d\n", port); + bpftune_server_running = true; + while (bpftune_server_running) { + char buf[BPFTUNE_SERVER_MSG_MAX]; + char req[80]; + struct sockaddr_in caddr; + int cfd = accept(fd, (struct sockaddr_in *)&caddr, &len); + unsigned long i; + + if (cfd < 0) { + bpftune_log(LOG_DEBUG, "could not accept connection for port %d: %s\n", + port, strerror(errno)); + continue; + } + if (read(cfd, req, sizeof(req)) < 0) { + bpftune_log(LOG_DEBUG, "could not read request from client for port %d: %s\n", + port, strerror(errno)); + close(cfd); + continue; + } + bpftune_log(LOG_DEBUG, "request '%s' from client for port %d\n", + req, port); + for (i = 0; i < ARRAY_SIZE(bpftune_reqs); i++) { + if (strncmp(req, bpftune_reqs[i].name, + strlen(bpftune_reqs[i].name)) == 0) { + bpftune_reqs[i].handler(req, buf, sizeof(buf)); + break; + } + } + if (i == ARRAY_SIZE(bpftune_reqs)) { + int off; + + off = snprintf(buf, sizeof(buf), "unknown request '%s'; supported requests are:\n", + req); + bpftune_help_handler(req, buf + off, sizeof(buf) - off); + } + if (write(cfd, buf, strlen(buf) + 1) < 0) { + bpftune_log(LOG_DEBUG, "could not write reply '%s' to client for port %d: %s\n", + buf, port, strerror(errno)); + } + close(cfd); + } + bpftune_log(LOG_DEBUG, "stopping server on port %d\n", port); + close(fd); + return NULL; +} + +int bpftune_server_start(unsigned short port) +{ + pthread_attr_t attr = {}; + pthread_t server_tid; + + if (pthread_attr_init(&attr) || + pthread_create(&server_tid, &attr, bpftune_server_thread, &port)) { + bpftune_log(LOG_ERR, "could not create server thread: %s\n", + strerror(errno)); + return -1; + } + return 0; +} + +int bpftuner_server_port(void) +{ + FILE *fp = fopen(BPFTUNE_PORT_FILE, "r"); + int p, num_values; + + if (!fp) { + bpftune_log(LOG_ERR, "could not open '%s': %s\n", + BPFTUNE_PORT_FILE, strerror(errno)); + return -errno; + } + num_values = fscanf(fp, "%d", &p); + fclose(fp); + if (num_values == 1) { + bpftune_log(LOG_DEBUG, "'%s' specifies port %d\n", + BPFTUNE_PORT_FILE, p); + return p; + } + bpftune_log(LOG_ERR, "'%s' file is malformed; should contain port#\n", + BPFTUNE_PORT_FILE); + return -ENOENT; +} + +int bpftune_server_request(struct sockaddr_in *server, const char *req, + char *buf, size_t buf_sz) +{ + unsigned short port = server ? ntohs(server->sin_port) : 0; + struct sockaddr_in saddr; + int fd, err; + + if (port == 0) { + int p = bpftuner_server_port(); + if (p < 0) { + bpftune_log(LOG_ERR, "could not get bpftune port for request '%s'\n", + req); + return -ENOENT; + } + port = p; + if (server) + server->sin_port = htons(port); + } + + fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd < 0) { + err = errno; + bpftune_log(LOG_ERR, "could not create server socket: %s\n", + strerror(err)); + return -err; + } + if (!server) { + memset(&saddr, 0, sizeof(saddr)); + saddr.sin_family = AF_INET; + saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + saddr.sin_port = htons(port); + server = &saddr; + } + + if (connect(fd, (struct sockaddr *)server, sizeof(*server)) < 0) { + err = errno; + bpftune_log(LOG_ERR, "could not connect to server (port %d): %s\n", + port, strerror(err)); + close(fd); + return -err; + } + bpftune_log(LOG_DEBUG, "sending request '%s' to server...\n", req); + if (send(fd, req, strlen(req) + 1, 0) < 0) { + err = errno; + bpftune_log(LOG_ERR, "could not send req '%s'to server (port %d): %s\n", + req, port, strerror(err)); + close(fd); + return -err; + } + if (recv(fd, buf, buf_sz, 0) < 0) { + err = errno; + bpftune_log(LOG_ERR, "could not recv reply to req '%s' to server (port %d): %s\n", + req, port, strerror(err)); + close(fd); + return -err; + } + close(fd); + return 0; +} + +void bpftune_server_stop(void) +{ + bpftune_server_running = false; +} diff --git a/src/libbpftune.map b/src/libbpftune.map index 3f04d4c..aee2b4c 100644 --- a/src/libbpftune.map +++ b/src/libbpftune.map @@ -3,6 +3,7 @@ LIBBPFTUNE_0.1.1 { bpftune_log_level; bpftune_log_stderr; bpftune_log_syslog; + bpftune_log_buf; bpftune_log; bpftune_set_log; bpftune_set_bpf_log; @@ -17,6 +18,10 @@ LIBBPFTUNE_0.1.1 { bpftune_cgroup_fini; bpftuner_cgroup_attach; bpftuner_cgroup_detach; + bpftune_server_start; + bpftune_server_port; + bpftune_server_request; + bpftune_server_stop; bpftune_tuner; bpftune_tuner_num; bpftune_bpf_support; diff --git a/test/Makefile b/test/Makefile index bce33b7..94700c2 100644 --- a/test/Makefile +++ b/test/Makefile @@ -24,6 +24,7 @@ TUNER_TESTS = support_test log_test service_test inotify_test cap_test \ sample_test sample_legacy_test \ strategy_test strategy_legacy_test \ rollback_test rollback_legacy_test \ + query_test \ many_netns_test many_netns_legacy_test \ podman_globalonly_test podman_globalonly_legacy_test \ sysctl_test sysctl_legacy_test sysctl_netns_test \ diff --git a/test/query_test.sh b/test/query_test.sh new file mode 100644 index 0000000..3551ff1 --- /dev/null +++ b/test/query_test.sh @@ -0,0 +1,139 @@ +#!/usr/bin/bash +# +# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note +# +# Copyright (c) 2023, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public +# License v2 as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 021110-1307, USA. +# + +# test various queries + +. ./test_lib.sh + +LOGFILE=$TESTLOG_LAST + +SLEEPTIME=1 +TIMEOUT=30 +MAX_CONN=50 + +test_setup true +for QUERY in help tuners tunables ; do + test_start "$0|query $QUERY test" + test_run_cmd_local "$BPFTUNE -s &" true + sleep $SETUPTIME + $BPFTUNE_CMD -q $QUERY + test_pass +done +test_cleanup + +for FAMILY in ipv4 ; do + for NS in global; do + case $FAMILY in + ipv4) + if [[ $NS == "global" ]]; then + ADDR=$VETH2_IPV4 + else + ADDR=$VETH1_IPV4 + fi + SYSCTL_PREFIX=net.ipv4.ipfrag_ + SYSCTL_NAME="${SYSCTL_PREFIX}high_thresh" + ;; + ipv6) + if [[ $NS == "global" ]]; then + ADDR=$VETH2_IPV6 + else + ADDR=$VETH1_IPV6 + fi + SYSCTL_PREFIX=net.ipv6.ip6frag_ + SYSCTL_NAME="${SYSCTL_PREFIX}high_thresh" + ;; + esac + + test_start "$0|query summary test to $ADDR:$PORT $FAMILY $NS" + + if [[ $NS == "global" ]]; then + CLIENT_PREFIX="ip netns exec $NETNS" + CLIENT_VETH=$VETH1 + SERVER_PREFIX="" + SERVER_VETH=$VETH2 + else + CLIENT_PREFIX="" + CLIENT_VETH=$VETH2 + SERVER_PREFIX="ip netns exec $NETNS" + SERVER_VETH=$VETH1 + fi + test_setup true + + $CLIENT_PREFIX ethtool --offload $CLIENT_VETH rx off tx off gso off gro off lro off tso off + $SERVER_PREFIX ethtool --offload $SERVER_VETH rx off tx off gso off gro off lro off tso off + frag_orig=($(sysctl -n $SYSCTL_NAME)) + low_orig=($(sysctl -n ${SYSCTL_PREFIX}low_thresh)) + sysctl -w ${SYSCTL_PREFIX}low_thresh=8192 + sysctl -w $SYSCTL_NAME="8192" + + frag_pre=($(sysctl -n $SYSCTL_NAME)) + + # prevent firewall from reassembling packets. + set +e + FIREWALLD_PID=$(pgrep firewalld) + set -e + if [[ -n "$FIREWALLD_PID" ]]; then + service firewalld stop + fi + for MODE in baseline test ; do + + echo "Running ${MODE}..." + if [[ $MODE != "baseline" ]]; then + test_run_cmd_local "$BPFTUNE -s &" true + sleep $SETUPTIME + else + LOGSZ=$(wc -l $LOGFILE | awk '{print $1}') + LOGSZ=$(expr $LOGSZ + 1) + fi + set +e + echo "Running $CLIENT_PREFIX ping -v -c 20 -M t -s 8192 $ADDR" + $CLIENT_PREFIX ping -v -c 20 -M want -s 8192 $ADDR + set -e + + sleep $SLEEPTIME + done + if [[ -n "$FIREWALLD_PID" ]]; then + service firewalld start + fi + frag_post=($(sysctl -n $SYSCTL_NAME)) + if [[ -n $SERVER_PREFIX ]]; then + sysctl -w ${SYSCTL_NAME}=$frag_orig + sysctl -w ${SYSCTL_PREFIX}low_thresh=$low_orig + fi + echo "$SYSCTL_NAME before ${frag_pre}" + echo "$SYSCTL_NAME after ${frag_post}" + if [[ $MODE == "test" ]]; then + if [[ "${frag_post}" -gt ${frag_pre} ]]; then + grep "approaching fragmentation maximum threshold" $LOGFILE + ${BPFTUNE_PROG} -q summary + pkill -TERM bpftune + test_pass + else + pkill -TERM bpftune + test_cleanup + fi + fi + + test_cleanup + done +done + +test_exit