I have these two rules in my firewall: ct state invalid drop ct state { established, related } accept When I use this command to get their JSON representations, i get the following result: # nft -j list ruleset | jq '.nftables[] | select(.rule.expr[]? and .rule.expr[].match.left.ct?) | .rule.expr[0].match' { "op": "in", "left": { "ct": { "key": "state" } }, "right": "invalid" } { "op": "==", "left": { "ct": { "key": "state" } }, "right": { "set": [ "established", "related" ] } } Matching the "state" key with "invalid" uses the "in" operator, while matching that same key with a set of "{ established, related }" uses the "==" operator. Why is this the case? According to libnftables-json(5) the "in" operator is used to "Perform a lookup, i.e. test if bits on RHS are contained in LHS value." Is this the case? If so, could I ask what the bitmasks for these states are? Thank you for your time.