# cscope files
/cscope.*
+# gcov-related
+*.gcda
+*.gcno
+*.gcov
+
# Generated by tests
*.payload.got
tests/build/tests.log
include/owner.h \
include/parser.h \
include/payload.h \
+ include/profiling.h \
include/proto.h \
include/rt.h \
include/rule.h \
AM_YFLAGS = -d -Wno-yacc
+if BUILD_PROFILING
+AM_CFLAGS += --coverage
+endif
+
###############################################################################
BUILT_SOURCES += src/parser_bison.h
$(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" \
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)
[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 \
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])
--- /dev/null
+#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 */
#include <errno.h>
#include <utils.h>
#include <nftables.h>
+#include <profiling.h>
#include <linux/netfilter.h>
#include <linux/netfilter_arp.h>
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;
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) {
--- /dev/null
+/*
+ * 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);
+ }
+}