Thank you Eric. Very helpful indeed in order to better understand exported existing rules. On Mon, Nov 6, 2023, at 10:28, Eric wrote: > On Monday, November 6th, 2023 at 06:24, Aurel Wisse <nf@xxxxxxxxx> wrote: >> Thank you for the quick answer. That explains part of it. Still, >> >> `tcp flags & (fin|syn|rst|ack) != syn` becomes >> `tcp != syn / fin,syn,rst,ack` >> >> and both expressions are interpreted as equal after parsing. Can you please point me to any documentation of operator expression syntax/precedence ? > > This is not the answer you're looking for, but it may help... > > When I was first learning nft expressions I found it most helpful to > dump various rules in json format, where it's really easy to see the > expressions in the abstract syntax tree, and compare that with both the > input and output forms. Also, you can clearly see the statements after > the "match" entries, like "counter", "set", "jump" and so on nicely > separated. > > (Oh, and in your OP, the "*logical* or/and" should be "*bitwise* > or/and", as the "flags" are a bit mask.) > > Input - if you don't have this form, then the json is far more > enlightening: > tcp flags & (fin | syn | rst | ack) == syn jump syn_flood > comment "Rate limit TCP syn packets" > > Output (i.e., 'nft list ruleset | grep 'Rate limit TCP') > tcp flags syn / fin,syn,rst,ack jump syn_flood comment "Rate limit > TCP syn packets" > > $ nft -j list chain inet filter input | json_pp > ... > { > "rule" : { > "chain" : "input", > "comment" : "Rate limit TCP syn packets", > "expr" : [ > { > "match" : { > "left" : { > "&" : [ > { > "payload" : { > "field" : "flags", > "protocol" : "tcp" > } > }, > [ > "fin", > "syn", > "rst", > "ack" > ] > ] > }, > "op" : "==", > "right" : "syn" > } > }, > { > "jump" : { > "target" : "syn_flood" > } > } > ], > "family" : "inet", > "handle" : 210, > "table" : "filter" > } > }, > ...