When trying to delete user-defined chains in a large ruleset, iptables-nft aborts with "No buffer space available". This can be reproduced using the following script:
| #! /bin/bash | iptables-nft-restore <( | | echo "*filter" | for i in $(seq 0 200000);do | printf ":chain_%06x - [0:0]\n" $i | done | for i in $(seq 0 200000);do | printf -- "-A INPUT -j chain_%06x\n" $i | printf -- "-A INPUT -j chain_%06x\n" $i | done | echo COMMIT | | ) | iptables-nft -X Note that calling 'iptables-nft -F' before the last call avoids the issue. Also, correct behaviour is indicated by a different error message, namely: | iptables v1.8.3 (nf_tables): CHAIN_USER_DEL failed (Device or resource busy): chain chain_000000 The used multiplier value is a result of trial-and-error, it is the first one which eliminated the ENOBUFS condition. Signed-off-by: Phil Sutter <p...@nwl.cc> --- iptables/nft.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/iptables/nft.c b/iptables/nft.c index 2c61521455de8..529d5fb1bfac8 100644 --- a/iptables/nft.c +++ b/iptables/nft.c @@ -192,6 +192,7 @@ static void mnl_set_sndbuffer(const struct mnl_socket *nl, struct nftnl_batch *batch) { int newbuffsiz; + int mult = 7; if (nftnl_batch_iovec_len(batch) * BATCH_PAGE_SIZE <= nlbuffsiz) return; @@ -203,6 +204,12 @@ static void mnl_set_sndbuffer(const struct mnl_socket *nl, &newbuffsiz, sizeof(socklen_t)) < 0) return; + newbuffsiz *= mult; + if (setsockopt(mnl_socket_get_fd(nl), SOL_SOCKET, SO_RCVBUFFORCE, + &newbuffsiz, sizeof(socklen_t)) < 0) + return; + newbuffsiz /= mult; + nlbuffsiz = newbuffsiz; } -- 2.21.0