Blame SOURCES/iptables-1.4.21-wait-interval.patch

26b15f
Adapted version of
26b15f
26b15f
commit e8f857a5a1514c3e7d0d8ea0f7d2d571f0e37bd1
26b15f
Author: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
26b15f
Date:   Thu Jun 23 18:44:06 2016 -0600
26b15f
26b15f
    xtables: Add an interval option for xtables lock wait
26b15f
    
26b15f
    ip[6]tables currently waits for 1 second for the xtables lock to be
26b15f
    freed if the -w option is used. We have seen that the lock is held
26b15f
    much less than that resulting in unnecessary delay when trying to
26b15f
    acquire the lock. This problem is even severe in case of latency
26b15f
    sensitive applications.
26b15f
    
26b15f
    Introduce a new option 'W' to specify the wait interval in microseconds.
26b15f
    If this option is not specified, the command sleeps for 1 second by
26b15f
    default.
26b15f
    
26b15f
    v1->v2: Change behavior to take millisecond sleep as an argument to
26b15f
    -w as suggested by Pablo. Also maintain current behavior for -w to
26b15f
    sleep for 1 second as mentioned by Liping.
26b15f
    
26b15f
    v2->v3: Move the millisecond behavior to a new option as suggested
26b15f
    by Pablo.
26b15f
    
26b15f
    v3->v4: Use select instead of usleep. Sleep every iteration for
26b15f
    the time specified in the "-W" argument. Update man page.
26b15f
    
26b15f
    v4->v5: Fix compilation error when enabling nftables
26b15f
    
26b15f
    v5->v6: Simplify -W so it only takes the interval wait in microseconds.
26b15f
    Bail out if -W is specific but -w is not.
26b15f
    
26b15f
    Joint work with Pablo Neira.
26b15f
    
26b15f
    Signed-off-by: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
26b15f
    Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
26b15f
26b15f
diff -up iptables-1.4.21/iptables/ip6tables.c.wait-interval iptables-1.4.21/iptables/ip6tables.c
26b15f
--- iptables-1.4.21/iptables/ip6tables.c.wait-interval	2017-04-05 14:04:04.560346651 +0200
26b15f
+++ iptables-1.4.21/iptables/ip6tables.c	2017-04-05 14:04:04.562346670 +0200
26b15f
@@ -103,6 +103,7 @@ static struct option original_opts[] = {
26b15f
 	{.name = "out-interface", .has_arg = 1, .val = 'o'},
26b15f
 	{.name = "verbose",       .has_arg = 0, .val = 'v'},
26b15f
 	{.name = "wait",          .has_arg = 2, .val = 'w'},
26b15f
+	{.name = "wait-interval", .has_arg = 2, .val = 'W'},
26b15f
 	{.name = "exact",         .has_arg = 0, .val = 'x'},
26b15f
 	{.name = "version",       .has_arg = 0, .val = 'V'},
26b15f
 	{.name = "help",          .has_arg = 2, .val = 'h'},
26b15f
@@ -258,7 +259,10 @@ exit_printhelp(const struct xtables_rule
26b15f
 "				network interface name ([+] for wildcard)\n"
26b15f
 "  --table	-t table	table to manipulate (default: `filter')\n"
26b15f
 "  --verbose	-v		verbose mode\n"
26b15f
-"  --wait	-w [seconds]	wait for the xtables lock\n"
26b15f
+"  --wait	-w [seconds]	maximum wait to acquire xtables lock before give up\n"
26b15f
+"  --wait-interval -W [usecs]	wait time to try to acquire xtables lock\n"
26b15f
+"				interval to wait for xtables lock\n"
26b15f
+"				default is 1 second\n"
26b15f
 "  --line-numbers		print line numbers when listing\n"
26b15f
 "  --exact	-x		expand numbers (display exact values)\n"
26b15f
 /*"[!] --fragment	-f		match second or further fragments only\n"*/
26b15f
@@ -1323,6 +1327,10 @@ int do_command6(int argc, char *argv[],
26b15f
 
26b15f
 	int verbose = 0;
26b15f
 	int wait = 0;
26b15f
+	struct timeval wait_interval = {
26b15f
+		.tv_sec	= 1,
26b15f
+	};
26b15f
+	bool wait_interval_set = false;
26b15f
 	const char *chain = NULL;
26b15f
 	const char *shostnetworkmask = NULL, *dhostnetworkmask = NULL;
26b15f
 	const char *policy = NULL, *newname = NULL;
26b15f
@@ -1358,7 +1366,7 @@ int do_command6(int argc, char *argv[],
26b15f
 
26b15f
 	opts = xt_params->orig_opts;
26b15f
 	while ((cs.c = getopt_long(argc, argv,
26b15f
-	   "-:A:C:D:R:I:L::S::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:bvw::nt:m:xc:g:46",
26b15f
+	   "-:A:C:D:R:I:L::S::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:bvw::W::nt:m:xc:g:46",
26b15f
 					   opts, NULL)) != -1) {
26b15f
 		switch (cs.c) {
26b15f
 			/*
26b15f
@@ -1614,6 +1622,23 @@ int do_command6(int argc, char *argv[],
26b15f
 						"wait seconds not numeric");
26b15f
 			break;
26b15f
 
26b15f
+		case 'W':
26b15f
+			if (restore) {
26b15f
+				xtables_error(PARAMETER_PROBLEM,
26b15f
+					      "You cannot use `-W' from "
26b15f
+					      "ip6tables-restore");
26b15f
+			}
26b15f
+			if (optarg)
26b15f
+				parse_wait_interval(optarg, &wait_interval);
26b15f
+			else if (optind < argc &&
26b15f
+				argv[optind][0] != '-' &&
26b15f
+				argv[optind][0] != '!')
26b15f
+				parse_wait_interval(argv[optind++],
26b15f
+						    &wait_interval);
26b15f
+
26b15f
+			wait_interval_set = true;
26b15f
+			break;
26b15f
+
26b15f
 		case 'm':
26b15f
 			command_match(&cs);
26b15f
 			break;
26b15f
@@ -1718,6 +1743,10 @@ int do_command6(int argc, char *argv[],
26b15f
 		cs.invert = FALSE;
26b15f
 	}
26b15f
 
26b15f
+	if (!wait && wait_interval_set)
26b15f
+		xtables_error(PARAMETER_PROBLEM,
26b15f
+			      "--wait-interval only makes sense with --wait\n");
26b15f
+
26b15f
 	if (strcmp(*table, "nat") == 0 &&
26b15f
 	    ((policy != NULL && strcmp(policy, "DROP") == 0) ||
26b15f
 	    (cs.jumpto != NULL && strcmp(cs.jumpto, "DROP") == 0)))
26b15f
@@ -1768,7 +1797,7 @@ int do_command6(int argc, char *argv[],
26b15f
 	generic_opt_check(command, cs.options);
26b15f
 
26b15f
 	/* Attempt to acquire the xtables lock */
26b15f
-	if (!restore && !xtables_lock(wait)) {
26b15f
+	if (!restore && !xtables_lock(wait, &wait_interval)) {
26b15f
 		fprintf(stderr, "Another app is currently holding the xtables lock. ");
26b15f
 		if (wait == 0)
26b15f
 			fprintf(stderr, "Perhaps you want to use the -w option?\n");
26b15f
diff -up iptables-1.4.21/iptables/iptables.8.in.wait-interval iptables-1.4.21/iptables/iptables.8.in
26b15f
--- iptables-1.4.21/iptables/iptables.8.in.wait-interval	2017-04-05 14:04:04.555346605 +0200
26b15f
+++ iptables-1.4.21/iptables/iptables.8.in	2017-04-05 14:04:04.562346670 +0200
26b15f
@@ -369,6 +369,13 @@ the program will exit if the lock cannot
26b15f
 make the program wait (indefinitely or for optional \fIseconds\fP) until
26b15f
 the exclusive lock can be obtained.
26b15f
 .TP
26b15f
+\fB\-W\fP, \fB\-\-wait-interval\fP \fImicroseconds\fP
26b15f
+Interval to wait per each iteration.
26b15f
+When running latency sensitive applications, waiting for the xtables lock
26b15f
+for extended durations may not be acceptable. This option will make each
26b15f
+iteration take the amount of time specified. The default interval is
26b15f
+1 second. This option only works with \fB\-w\fP.
26b15f
+.TP
26b15f
 \fB\-n\fP, \fB\-\-numeric\fP
26b15f
 Numeric output.
26b15f
 IP addresses and port numbers will be printed in numeric format.
26b15f
diff -up iptables-1.4.21/iptables/iptables.c.wait-interval iptables-1.4.21/iptables/iptables.c
26b15f
--- iptables-1.4.21/iptables/iptables.c.wait-interval	2017-04-05 14:04:04.555346605 +0200
26b15f
+++ iptables-1.4.21/iptables/iptables.c	2017-04-05 14:04:04.563346679 +0200
26b15f
@@ -100,6 +100,7 @@ static struct option original_opts[] = {
26b15f
 	{.name = "out-interface", .has_arg = 1, .val = 'o'},
26b15f
 	{.name = "verbose",       .has_arg = 0, .val = 'v'},
26b15f
 	{.name = "wait",          .has_arg = 2, .val = 'w'},
26b15f
+	{.name = "wait-interval", .has_arg = 2, .val = 'W'},
26b15f
 	{.name = "exact",         .has_arg = 0, .val = 'x'},
26b15f
 	{.name = "fragments",     .has_arg = 0, .val = 'f'},
26b15f
 	{.name = "version",       .has_arg = 0, .val = 'V'},
26b15f
@@ -252,7 +253,9 @@ exit_printhelp(const struct xtables_rule
26b15f
 "				network interface name ([+] for wildcard)\n"
26b15f
 "  --table	-t table	table to manipulate (default: `filter')\n"
26b15f
 "  --verbose	-v		verbose mode\n"
26b15f
-"  --wait	-w [seconds]	wait for the xtables lock\n"
26b15f
+"  --wait	-w [seconds]	maximum wait to acquire xtables lock before give up\n"
26b15f
+"  --wait-interval -W [usecs]	wait time to try to acquire xtables lock\n"
26b15f
+"				default is 1 second\n"
26b15f
 "  --line-numbers		print line numbers when listing\n"
26b15f
 "  --exact	-x		expand numbers (display exact values)\n"
26b15f
 "[!] --fragment	-f		match second or further fragments only\n"
26b15f
@@ -1316,7 +1319,10 @@ int do_command4(int argc, char *argv[],
26b15f
 	unsigned int nsaddrs = 0, ndaddrs = 0;
26b15f
 	struct in_addr *saddrs = NULL, *smasks = NULL;
26b15f
 	struct in_addr *daddrs = NULL, *dmasks = NULL;
26b15f
-
26b15f
+	struct timeval wait_interval = {
26b15f
+		.tv_sec = 1,
26b15f
+	};
26b15f
+	bool wait_interval_set = false;
26b15f
 	int verbose = 0;
26b15f
 	int wait = 0;
26b15f
 	const char *chain = NULL;
26b15f
@@ -1353,7 +1359,7 @@ int do_command4(int argc, char *argv[],
26b15f
 	opterr = 0;
26b15f
 	opts = xt_params->orig_opts;
26b15f
 	while ((cs.c = getopt_long(argc, argv,
26b15f
-	   "-:A:C:D:R:I:L::S::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:fbvw::nt:m:xc:g:46",
26b15f
+	   "-:A:C:D:R:I:L::S::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:fbvw::W::nt:m:xc:g:46",
26b15f
 					   opts, NULL)) != -1) {
26b15f
 		switch (cs.c) {
26b15f
 			/*
26b15f
@@ -1607,6 +1613,23 @@ int do_command4(int argc, char *argv[],
26b15f
 						"wait seconds not numeric");
26b15f
 			break;
26b15f
 
26b15f
+		case 'W':
26b15f
+			if (restore) {
26b15f
+				xtables_error(PARAMETER_PROBLEM,
26b15f
+					      "You cannot use `-W' from "
26b15f
+					      "iptables-restore");
26b15f
+			}
26b15f
+			if (optarg)
26b15f
+				parse_wait_interval(optarg, &wait_interval);
26b15f
+			else if (optind < argc &&
26b15f
+				 argv[optind][0] != '-' &&
26b15f
+				 argv[optind][0] != '!')
26b15f
+				parse_wait_interval(argv[optind++],
26b15f
+						    &wait_interval);
26b15f
+
26b15f
+			wait_interval_set = true;
26b15f
+			break;
26b15f
+
26b15f
 		case 'm':
26b15f
 			command_match(&cs);
26b15f
 			break;
26b15f
@@ -1707,6 +1730,10 @@ int do_command4(int argc, char *argv[],
26b15f
 		cs.invert = FALSE;
26b15f
 	}
26b15f
 
26b15f
+	if (!wait && wait_interval_set)
26b15f
+		xtables_error(PARAMETER_PROBLEM,
26b15f
+			      "--wait-interval only makes sense with --wait\n");
26b15f
+
26b15f
 	if (strcmp(*table, "nat") == 0 &&
26b15f
 	    ((policy != NULL && strcmp(policy, "DROP") == 0) ||
26b15f
 	    (cs.jumpto != NULL && strcmp(cs.jumpto, "DROP") == 0)))
26b15f
@@ -1757,7 +1784,7 @@ int do_command4(int argc, char *argv[],
26b15f
 	generic_opt_check(command, cs.options);
26b15f
 
26b15f
 	/* Attempt to acquire the xtables lock */
26b15f
-	if (!restore && !xtables_lock(wait)) {
26b15f
+	if (!restore && !xtables_lock(wait, &wait_interval)) {
26b15f
 		fprintf(stderr, "Another app is currently holding the xtables lock. ");
26b15f
 		if (wait == 0)
26b15f
 			fprintf(stderr, "Perhaps you want to use the -w option?\n");
26b15f
diff -up iptables-1.4.21/iptables/xshared.c.wait-interval iptables-1.4.21/iptables/xshared.c
26b15f
--- iptables-1.4.21/iptables/xshared.c.wait-interval	2017-04-05 14:04:04.557346624 +0200
26b15f
+++ iptables-1.4.21/iptables/xshared.c	2017-04-05 14:04:04.563346679 +0200
26b15f
@@ -9,12 +9,15 @@
26b15f
 #include <sys/file.h>
26b15f
 #include <sys/socket.h>
26b15f
 #include <sys/un.h>
26b15f
+#include <sys/time.h>
26b15f
 #include <unistd.h>
26b15f
 #include <fcntl.h>
26b15f
 #include <xtables.h>
26b15f
+#include <math.h>
26b15f
 #include "xshared.h"
26b15f
 
26b15f
 #define XT_LOCK_NAME	"/run/xtables.lock"
26b15f
+#define BASE_MICROSECONDS	100000
26b15f
 
26b15f
 /*
26b15f
  * Print out any special helps. A user might like to be able to add a --help
26b15f
@@ -244,9 +247,15 @@ void xs_init_match(struct xtables_match
26b15f
 		match->init(match->m);
26b15f
 }
26b15f
 
26b15f
-bool xtables_lock(int wait)
26b15f
+bool xtables_lock(int wait, struct timeval *wait_interval)
26b15f
 {
26b15f
-	int fd, waited = 0, i = 0;
26b15f
+	struct timeval time_left, wait_time, waited_time;
26b15f
+	int fd, i = 0;
26b15f
+
26b15f
+	time_left.tv_sec = wait;
26b15f
+	time_left.tv_usec = 0;
26b15f
+	waited_time.tv_sec = 0;
26b15f
+	waited_time.tv_usec = 0;
26b15f
 
26b15f
 	fd = open(XT_LOCK_NAME, O_CREAT, 0600);
26b15f
 	if (fd < 0)
26b15f
@@ -255,12 +264,43 @@ bool xtables_lock(int wait)
26b15f
 	while (1) {
26b15f
 		if (flock(fd, LOCK_EX | LOCK_NB) == 0)
26b15f
 			return true;
26b15f
-		else if (wait >= 0 && waited >= wait)
26b15f
+		if (++i % 10 == 0) {
26b15f
+			if (wait != -1)
26b15f
+				fprintf(stderr, "Another app is currently holding the xtables lock; "
26b15f
+					"still %lds %ldus time ahead to have a chance to grab the lock...\n",
26b15f
+					time_left.tv_sec, time_left.tv_usec);
26b15f
+			else
26b15f
+				fprintf(stderr, "Another app is currently holding the xtables lock; "
26b15f
+						"waiting for it to exit...\n");
26b15f
+		}
26b15f
+
26b15f
+		wait_time = *wait_interval;
26b15f
+		select(0, NULL, NULL, NULL, &wait_time);
26b15f
+		if (wait == -1)
26b15f
+			continue;
26b15f
+
26b15f
+		timeradd(&waited_time, wait_interval, &waited_time);
26b15f
+		timersub(&time_left, wait_interval, &time_left);
26b15f
+		if (!timerisset(&time_left))
26b15f
 			return false;
26b15f
-		if (++i % 2 == 0)
26b15f
-			fprintf(stderr, "Another app is currently holding the xtables lock; "
26b15f
-				"waiting (%ds) for it to exit...\n", waited);
26b15f
-		waited++;
26b15f
-		sleep(1);
26b15f
 	}
26b15f
 }
26b15f
+
26b15f
+void parse_wait_interval(const char *str, struct timeval *wait_interval)
26b15f
+{
26b15f
+	unsigned int usec;
26b15f
+	int ret;
26b15f
+
26b15f
+	ret = sscanf(str, "%u", &usec);
26b15f
+	if (ret == 1) {
26b15f
+		if (usec > 999999)
26b15f
+			xtables_error(PARAMETER_PROBLEM,
26b15f
+				      "too long usec wait %u > 999999 usec",
26b15f
+				      usec);
26b15f
+
26b15f
+		wait_interval->tv_sec = 0;
26b15f
+		wait_interval->tv_usec = usec;
26b15f
+		return;
26b15f
+	}
26b15f
+	xtables_error(PARAMETER_PROBLEM, "wait interval not numeric");
26b15f
+}
26b15f
diff -up iptables-1.4.21/iptables/xshared.h.wait-interval iptables-1.4.21/iptables/xshared.h
26b15f
--- iptables-1.4.21/iptables/xshared.h.wait-interval	2017-04-05 14:04:04.555346605 +0200
26b15f
+++ iptables-1.4.21/iptables/xshared.h	2017-04-05 14:04:04.563346679 +0200
26b15f
@@ -84,7 +84,9 @@ extern struct xtables_match *load_proto(
26b15f
 extern int subcmd_main(int, char **, const struct subcommand *);
26b15f
 extern void xs_init_target(struct xtables_target *);
26b15f
 extern void xs_init_match(struct xtables_match *);
26b15f
-extern bool xtables_lock(int wait);
26b15f
+bool xtables_lock(int wait, struct timeval *wait_interval);
26b15f
+
26b15f
+void parse_wait_interval(const char *str, struct timeval *wait_interval);
26b15f
 
26b15f
 extern const struct xtables_afinfo *afinfo;
26b15f