Well, same problem as what I mentioned in the last reply from me for your patch: inconsistent / unexpected meaning of the syntax. As of the current code (or even according to what you said / implied "should and would still be right"), `tcp flags syn` checks and checks only whether the syn bit is on: # nft --debug=netlink add rule meh tcp_flags 'tcp flags syn' ip [ meta load l4proto => reg 1 ] [ cmp eq reg 1 0x00000006 ] [ payload load 1b @ transport header + 13 => reg 1 ] [ bitwise reg 1 = ( reg 1 & 0x00000002 ) ^ 0x00000000 ] [ cmp neq reg 1 0x00000000 ] which I consider to be a really bad (or even wrong) "shortcut", because it is so unexpected that it is not the same as this: # nft --debug=netlink add rule meh tcp_flags 'tcp flags { syn }' __set%d meh 3 __set%d meh 0 element 00000002 : 0 [end] ip [ meta load l4proto => reg 1 ] [ cmp eq reg 1 0x00000006 ] [ payload load 1b @ transport header + 13 => reg 1 ] [ lookup reg 1 set __set%d ] Probably because `{ }` implies a `==`. And as per what you've written in your other reply to me, apparently a mask implies one as well. So many things implied. So "neat". But no one (at least not me) knows what the different syntaxes mean anymore until they --debug=netlink... On Wed, 28 Jul 2021 at 05:11, Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx> wrote: > > On Tue, Jul 27, 2021 at 10:52:39PM +0800, Tom Yan wrote: > > Just noticed something that is even worse: > > > > # nft add rule meh tcp_flags 'tcp flags { fin, rst, ack }' > > # nft add rule meh tcp_flags 'tcp flags == { fin, rst, ack }' > > # nft add rule meh tcp_flags 'tcp flags & ( fin | rst | ack ) != 0' > > # nft add rule meh tcp_flags 'tcp flags & ( fin | rst | ack ) == 0' > > # nft list table meh > > table ip meh { > > chain tcp_flags { > > tcp flags { fin, rst, ack } > > tcp flags { fin, rst, ack } > > tcp flags fin,rst,ack > > tcp flags ! fin,rst,ack > > } > > } > > Could you develop the issue you're seeing here?