How to prevent iptables from counting bytes and packets on empty chains

iptableskernel-modules

Background

I occasionally have firewall rules that I need to use for maintenance windows, but don't want active (and therefore consuming CPU cycles or slowing the network interface) the rest of the time. I add the rules when I need them, and then want to wipe the slate clean and stop iptables from counting packets and bytes flowing through the filter chains.

Problem: Filter Table Keeps Counting Anyway

The first time I check iptables in verbose mode, packet and byte counts are
always zero. For example:

$ sudo iptables -L -n -v
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

However, once the filter table has been initialized, flushing the table or resetting the counters doesn't stop the table from continuing to count packets and bytes. For example:

$ sudo iptables -F; sleep 5; sudo iptables -L -n -v
Chain INPUT (policy ACCEPT 395 packets, 577K bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 199 packets, 11135 bytes)
 pkts bytes target     prot opt in     out     source               destination

Current Solution

While I suspect that the actual CPU usage isn't all that high for an empty table, it seems wasteful to have the kernel inspect packets or count bytes that I don't care about. In order to prevent the filter table from consuming CPU cycles when there are no active rules, I've been doing the following:

$ sudo iptables -F; sudo iptables -X; sudo modprobe -r iptable_filter

This removes the rules and the filter table, allowing the iptables filter module to be removed from the running kernel. Once I do that, then counters remain zeroed until I once again initialize the table.

The Actual Question

My two-part question is:

  1. Whether the counters for empty chains even have a measurable impact on performance. Intuitively, it seems like they would on a busy network interface, but I have no idea how to measure whether the impact exists.
  2. Assuming there is an impact, whether there's a more elegant way to stop iptables from counting bytes/packets on empty chains than unloading the related kernel modules.

Best Answer

You can't unless you patch the kernel. And you have better things to do.

The counters are incremented __nf_ct_refresh_acct if the parameter do_acct is nonzero. This function is called through two wrappers: nf_ct_refresh_acct, which increments the counters, and nf_ct_refresh, which doesn't. The choice of wrapper is made according to the protocol type: protocols that can track do, the ones that can't don't.

The amount of computation is tiny. It's just two synchronized additions. Modern processors have very deep instruction pipelines, which makes conditional instructions expensive: the processor tries to predict which branch will be taken to start executing the next few instructions before it's determined the result of the test, and if the prediction is wrong, a lot of work needs to be discarded. The additions do require synchronization between the CPUs, because all CPUs have to be updating the same counter; on typical multicore architecture, this means that the core has to lock the cache line containing the counters. If the feature was optional, the CPU would have to read the configuration value, which doesn't require exclusive access so is a little less expensive. Still it would be an extremely tiny gain, to be balanced by the slightly less tiny loss for the majority of users who want the counters. It's just not worth having an option to disable this feature.

Related Question