Hi, On Wed, May 03, 2023 at 03:55:33PM +0300, Boris Sukholitko wrote: [...] > Now lets try to add flow offload: > > table inet filter { > flowtable f1 { > hook ingress priority filter > devices = { veth0, veth1 } > } > > chain forward { > type filter hook forward priority filter; policy accept; > ip dscp set cs3 > ip protocol { tcp, udp, gre } flow add > ct state established,related accept > } > } >From user perspective, I think the way to go would be to allow users to define a ruleset like this: table inet filter { flowtable f1 { hook ingress priority filter devices = { veth0, veth1 } } chain ingress { type filter hook ingress device veth0 priority filter; policy accept; flags offload; ip dscp set cs3 } chain forward { type filter hook forward priority filter; policy accept; meta l4proto { tcp, udp, gre } flow add @f1 ct state established,related accept } } This ruleset defines a policy at ingress, the offload flag tells that this is offloaded to hardware for veth0, ie. all rule in the 'ingress' chain will be placed in hardware in the ingress path. The IP DSCP field is set on at the ingress (offload) hook, therefore, the host (software) in tcpdump will see already mangled packets with IP DSCP field set to cs3. To achieve this, please have a look at net/netfilter/nf_tables_offload.c for the ruleset offload infrastructure. This is called whenever the chain comes with the offload flag set on. struct nft_expr_ops provides an .offload and .offload_action callbacks which you can use to populate the existing hardware offload API as defined by include/net/flow_offload.h. You will also have to extend the offload parser to translate the nftables bytecode to the (hardware) flow_offload API, similar to what nft_payload does to infer the header field you want to mangle (the flow_offload hardware API uses the flow_dissector structure). It is going to be a bit of work but I think this is feasible. Thanks.