summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2023-07-24 20:05:40 +0200
committerThomas Haller <thaller@redhat.com>2023-07-24 20:05:57 +0200
commit91b904db248d0fb710ea0700bb1aaf0eee0ecc88 (patch)
treed5e9fa3a11200371fd1f25cf6899ff8bf9575642
parent6519a9173f900b364f014a2321a17aa6bf652e6d (diff)
parent96bbe55c8513f1c80d4c85fe829ef2aef35e1f51 (diff)
downloadlibnl-91b904db248d0fb710ea0700bb1aaf0eee0ecc88.tar.gz
tests: merge branch 'gobenji:test-cache-mngr-improvements'
https://github.com/thom311/libnl/pull/335
-rw-r--r--tests/test-cache-mngr.c144
1 files changed, 131 insertions, 13 deletions
diff --git a/tests/test-cache-mngr.c b/tests/test-cache-mngr.c
index 97614520..33cbd8d2 100644
--- a/tests/test-cache-mngr.c
+++ b/tests/test-cache-mngr.c
@@ -2,21 +2,42 @@
#include <netlink/cache.h>
#include <netlink/cli/utils.h>
#include <signal.h>
+#include <stdbool.h>
+#include <sys/time.h>
+#include <time.h>
#include <netlink-private/cache-api.h>
#include <linux/netlink.h>
static int quit = 0;
+static int change = 1;
+static int print_ts = 0;
-static struct nl_dump_params dp = {
+static struct nl_dump_params params = {
.dp_type = NL_DUMP_LINE,
};
+static void print_timestamp(FILE *fp)
+{
+ struct timeval tv;
+ char tshort[40];
+ struct tm *tm;
+
+ gettimeofday(&tv, NULL);
+ tm = localtime(&tv.tv_sec);
+
+ strftime(tshort, sizeof(tshort), "%Y-%m-%dT%H:%M:%S", tm);
+ fprintf(fp, "[%s.%06ld] ", tshort, tv.tv_usec);
+}
+
static void change_cb(struct nl_cache *cache, struct nl_object *obj,
int action, void *data)
{
+ if (print_ts)
+ print_timestamp(stdout);
+
if (action == NL_ACT_NEW)
printf("NEW ");
else if (action == NL_ACT_DEL)
@@ -24,7 +45,10 @@ static void change_cb(struct nl_cache *cache, struct nl_object *obj,
else if (action == NL_ACT_CHANGE)
printf("CHANGE ");
- nl_object_dump(obj, &dp);
+ nl_object_dump(obj, &params);
+ fflush(stdout);
+
+ change = 1;
}
static void sigint(int arg)
@@ -32,34 +56,128 @@ static void sigint(int arg)
quit = 1;
}
+static void print_usage(FILE* stream, const char *name)
+{
+ fprintf(stream,
+ "Usage: %s [OPTIONS]... <cache name>... \n"
+ "\n"
+ "OPTIONS\n"
+ " -f, --format=TYPE Output format { brief | details | stats }\n"
+ " Default: brief\n"
+ " -d, --dump Dump cache content after a change.\n"
+ " -i, --interval=TIME Dump cache content after TIME seconds when there is no\n"
+ " change; 0 to disable. Default: 1\n"
+ " -I, --iter Iterate over all address families when updating caches.\n"
+ " -t, --tshort Print a short timestamp before change messages.\n"
+ " -h, --help Show this help text.\n"
+ , name);
+}
+
int main(int argc, char *argv[])
{
+ bool dump_on_change = false, dump_on_timeout = true, iter = false;
struct nl_cache_mngr *mngr;
- struct nl_cache *cache;
- int err, i;
-
- dp.dp_fd = stdout;
-
- signal(SIGINT, sigint);
+ int timeout = 1000, err;
+
+ for (;;) {
+ static struct option long_opts[] = {
+ { "format", required_argument, 0, 'f' },
+ { "dump", no_argument, 0, 'd' },
+ { "interval", required_argument, 0, 'i' },
+ { "iter", no_argument, 0, 'I' },
+ { "tshort", no_argument, 0, 't' },
+ { "help", 0, 0, 'h' },
+ { 0, 0, 0, 0 }
+ };
+ int c;
+
+ c = getopt_long(argc, argv, "hf:di:It", long_opts, NULL);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ char *endptr;
+ long interval;
+
+ case 'f':
+ params.dp_type = nl_cli_parse_dumptype(optarg);
+ break;
+
+ case 'd':
+ dump_on_change = true;
+ break;
+
+ case 'i':
+ errno = 0;
+ interval = strtol(optarg, &endptr, 0);
+ if (interval < 0 || errno || *endptr) {
+ nl_cli_fatal(EINVAL, "Invalid interval \"%s\".\n",
+ optarg);
+ exit(1);
+ }
+ if (!interval) {
+ dump_on_timeout = false;
+ } else {
+ timeout = interval * 1000;
+ }
+
+ break;
+
+ case 'I':
+ iter = true;
+ break;
+
+ case 't':
+ print_ts = true;
+ break;
+
+ case 'h':
+ print_usage(stdout, argv[0]);
+ exit(0);
+
+ case '?':
+ print_usage(stderr, argv[0]);
+ exit(1);
+ }
+ }
err = nl_cache_mngr_alloc(NULL, NETLINK_ROUTE, NL_AUTO_PROVIDE, &mngr);
if (err < 0)
nl_cli_fatal(err, "Unable to allocate cache manager: %s",
nl_geterror(err));
- for (i = 1; i < argc; i++) {
- err = nl_cache_mngr_add(mngr, argv[i], &change_cb, NULL, &cache);
+ while (optind < argc) {
+ struct nl_cache *cache;
+
+ err = nl_cache_alloc_name(argv[optind], &cache);
+ if (err < 0)
+ nl_cli_fatal(err, "Couldn't add cache %s: %s\n",
+ argv[optind], nl_geterror(err));
+
+ if (iter)
+ nl_cache_set_flags(cache, NL_CACHE_AF_ITER);
+
+ err = nl_cache_mngr_add_cache(mngr, cache, &change_cb, NULL);
if (err < 0)
nl_cli_fatal(err, "Unable to add cache %s: %s",
- argv[i], nl_geterror(err));
+ argv[optind], nl_geterror(err));
+
+ optind++;
}
+ params.dp_fd = stdout;
+ signal(SIGINT, sigint);
+
while (!quit) {
- int err = nl_cache_mngr_poll(mngr, 1000);
+ err = nl_cache_mngr_poll(mngr, timeout);
if (err < 0 && err != -NLE_INTR)
nl_cli_fatal(err, "Polling failed: %s", nl_geterror(err));
- nl_cache_mngr_info(mngr, &dp);
+ if (dump_on_timeout || (dump_on_change && change)) {
+ nl_cache_mngr_info(mngr, &params);
+ fflush(stdout);
+ change = 0;
+ }
}
nl_cache_mngr_free(mngr);