]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
configure: Implement --enable-profiling option
authorPhil Sutter <phil@nwl.cc>
Fri, 23 Jan 2026 00:38:20 +0000 (01:38 +0100)
committerPhil Sutter <phil@nwl.cc>
Fri, 13 Feb 2026 13:08:30 +0000 (14:08 +0100)
This will set compiler flag --coverage so code coverage may be inspected
using gcov.

In order to successfully profile processes which are killed or
interrupted as well, add a signal handler for those cases which calls
exit(). This is relevant for test cases invoking nft monitor.

Signed-off-by: Phil Sutter <phil@nwl.cc>
.gitignore
Makefile.am
configure.ac
include/profiling.h [new file with mode: 0644]
src/mnl.c
src/profiling.c [new file with mode: 0644]

index 719829b65d212ae0a13203d437c5a06a1a4511ff..8673393fac39715fd751681e011bb7fb1af06f29 100644 (file)
@@ -19,6 +19,11 @@ nftversion.h
 # cscope files
 /cscope.*
 
+# gcov-related
+*.gcda
+*.gcno
+*.gcov
+
 # Generated by tests
 *.payload.got
 tests/build/tests.log
index 828146bc4fb1a47cf9517735f823c711f301c47a..fa71e06eefee5098fcb82cde2ac83e5f5825da2e 100644 (file)
@@ -97,6 +97,7 @@ noinst_HEADERS = \
        include/owner.h \
        include/parser.h \
        include/payload.h \
+       include/profiling.h \
        include/proto.h \
        include/rt.h \
        include/rule.h \
@@ -164,6 +165,10 @@ AM_CFLAGS = \
 
 AM_YFLAGS = -d -Wno-yacc
 
+if BUILD_PROFILING
+AM_CFLAGS += --coverage
+endif
+
 ###############################################################################
 
 BUILT_SOURCES += src/parser_bison.h
@@ -265,6 +270,10 @@ src_libnftables_la_SOURCES += \
        $(NULL)
 endif
 
+if BUILD_PROFILING
+src_libnftables_la_SOURCES += src/profiling.c
+endif
+
 src_libnftables_la_LDFLAGS = \
        -version-info "${libnftables_LIBVERSION}" \
        -Wl,--version-script="$(srcdir)/src//libnftables.map" \
@@ -454,3 +463,15 @@ TESTS = tests/build/run-tests.sh \
        tests/py/nft-test.py \
        tests/shell/run-tests.sh
 endif
+
+all_c_sources = $(filter %.c,$(src_libnftables_la_SOURCES)) $(src_nft_SOURCES)
+if BUILD_MINIGMP
+all_c_sources += $(src_libminigmp_la_SOURCES)
+endif
+if BUILD_AFL
+all_c_sources += $(tools_nft_afl_SOURCES)
+endif
+CLEANFILES += src/libparser_la-parser_bison.gcno
+CLEANFILES += src/libparser_la-scanner.gcno
+CLEANFILES += $(all_c_sources:.c=.gcno)
+CLEANFILES += $(src_nft_SOURCES:.c=.gcda)
index 022608627908a4f16e84d0998487a3d637469562..0d3ee2ac89f699248596736fd4c995eec60330d5 100644 (file)
@@ -156,6 +156,13 @@ AC_ARG_ENABLE([distcheck],
              [enable_distcheck=yes], [])
 AM_CONDITIONAL([BUILD_DISTCHECK], [test "x$enable_distcheck" = "xyes"])
 
+AC_ARG_ENABLE([profiling],
+             AS_HELP_STRING([--enable-profiling], [build for use of gcov/gprof]),
+             [enable_profiling="$enableval"], [enable_profiling="no"])
+AM_CONDITIONAL([BUILD_PROFILING], [test "x$enable_profiling" = xyes])
+AM_COND_IF([BUILD_PROFILING],
+          [AC_DEFINE([BUILD_PROFILING], [1], [Define for profiling])])
+
 AC_CONFIG_FILES([                                      \
                Makefile                                \
                libnftables.pc                          \
@@ -170,7 +177,8 @@ nft configuration:
   use mini-gmp:                        ${with_mini_gmp}
   enable man page:              ${enable_man_doc}
   libxtables support:          ${with_xtables}
-  json output support:          ${with_json}"
+  json output support:          ${with_json}
+  collect profiling data:       ${enable_profiling}"
 
 if test "x$unitdir" != "x"; then
 AC_SUBST([unitdir])
diff --git a/include/profiling.h b/include/profiling.h
new file mode 100644 (file)
index 0000000..78abd31
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef NFTABLES_PROFILING_H
+#define NFTABLES_PROFILING_H
+
+#ifdef BUILD_PROFILING
+int get_signalfd(void);
+void check_signalfd(int fd);
+#else
+static inline int get_signalfd(void) { return -1; }
+static inline void check_signalfd(int fd) { /* empty */ }
+#endif
+
+#endif /* NFTABLES_PROFILING_H */
index eee0a33ceaeb43fec7f7ff0abb3362e41514f6fe..3f3ef82a25cb5bb3debee514037d70f6ae38f02a 100644 (file)
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -39,6 +39,7 @@
 #include <errno.h>
 #include <utils.h>
 #include <nftables.h>
+#include <profiling.h>
 #include <linux/netfilter.h>
 #include <linux/netfilter_arp.h>
 
@@ -2390,6 +2391,7 @@ int mnl_nft_event_listener(struct mnl_socket *nf_sock, unsigned int debug_mask,
        unsigned int bufsiz = NFTABLES_NLEVENT_BUFSIZ;
        int fd = mnl_socket_get_fd(nf_sock);
        char buf[NFT_NLMSG_MAXSIZE];
+       int sigfd = get_signalfd();
        fd_set readfds;
        int ret;
 
@@ -2401,11 +2403,16 @@ int mnl_nft_event_listener(struct mnl_socket *nf_sock, unsigned int debug_mask,
        while (1) {
                FD_ZERO(&readfds);
                FD_SET(fd, &readfds);
+               if (sigfd != -1)
+                       FD_SET(sigfd, &readfds);
 
-               ret = select(fd + 1, &readfds, NULL, NULL, NULL);
+               ret = select(max(fd, sigfd) + 1, &readfds, NULL, NULL, NULL);
                if (ret < 0)
                        return -1;
 
+               if (FD_ISSET(sigfd, &readfds))
+                       check_signalfd(sigfd);
+
                if (FD_ISSET(fd, &readfds)) {
                        ret = mnl_socket_recvfrom(nf_sock, buf, sizeof(buf));
                        if (ret < 0) {
diff --git a/src/profiling.c b/src/profiling.c
new file mode 100644 (file)
index 0000000..34d91cc
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) Red Hat GmbH.  Author: Phil Sutter <phil@nwl.cc>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 (or any
+ * later) as published by the Free Software Foundation.
+ */
+
+#include <nft.h>
+#include <profiling.h>
+
+#include <sys/signalfd.h>
+#include <signal.h>
+#include <stdio.h>
+
+int get_signalfd(void)
+{
+       sigset_t mask;
+       int fd;
+
+       sigemptyset(&mask);
+       sigaddset(&mask, SIGTERM);
+       sigaddset(&mask, SIGINT);
+
+       fd = signalfd(-1, &mask, 0);
+       if (fd < 0) {
+               perror("signalfd()");
+               return fd;
+       }
+       if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) {
+               perror("sigprocmask()");
+               close(fd);
+               return -1;
+       }
+       return fd;
+}
+
+void check_signalfd(int fd)
+{
+       struct signalfd_siginfo info;
+
+       if (read(fd, &info, sizeof(info)) < (signed)sizeof(info))
+               return;
+
+       switch (info.ssi_signo) {
+       case SIGTERM:
+               exit(143);
+       case SIGINT:
+               exit(130);
+       }
+}