On Mon, Jan 10, 2022 at 04:28:20PM +0100, Florian Westphal wrote: > I was given this reproducer: > > ---------------- > #!/bin/bash -x > nft flush ruleset > > nft add table ip filter > nft add chain ip filter output { type filter hook output priority 0 \; } > nft add set ip filter black-list '{type ipv4_addr; flags dynamic; }' > nft add rule ip filter output oifname lo meta l4proto udp update @black-list { ip daddr } counter > nft list ruleset |tee ruleset > > nft -f ruleset # success > nft flush ruleset > nft list ruleset > sleep 1 > nft -f ruleset # failed > > ----------- > > The ruleset generated by 'nft list ruleset' > cannot be restored. > > Ruleset looks like this: > > table ip filter { > set black-list { > type ipv4_addr > size 65535 > } > > chain output { > type filter hook output priority filter; policy accept; > oifname "lo" meta l4proto udp update @black-list { ip daddr } counter packets 0 bytes 0 > } > } > > Reason for the failure on restore is that the set is created with 'size > 65536' but no 'dynamic' flag. > > This causes a failure because the kernel picks the 'hash' set that > lacks the update() function. > > The initial commands work because lack of 'size' picks the rhash > backend, so the ->update works since the check for the timeout flag was > removed in commit "netfilter: nft_dynset: relax superfluous check on set > updates". > > First restore works because the set is not created anew, so this is > still 'rhash' backend. > > Second restore fails because 'hash' is chosen. > > Workaround is to edit the ruleset file to add 'flags dynamic' or 'flags > timeout', or both. > > Any suggestions on how to fix this? Could you set on the dynamic flag from the evaluation path? If there is a rule with the set statement that uses the set, then turn on this dynamic flag.