static int nft_delrule(struct nft_ctx *ctx, struct nft_rule *rule)
 {
+       struct nft_flow_rule *flow;
        struct nft_trans *trans;
        int err;
 
        if (trans == NULL)
                return -ENOMEM;
 
+       if (ctx->chain->flags & NFT_CHAIN_HW_OFFLOAD) {
+               flow = nft_flow_rule_create(ctx->net, rule);
+               if (IS_ERR(flow)) {
+                       nft_trans_destroy(trans);
+                       return PTR_ERR(flow);
+               }
+
+               nft_trans_flow_rule(trans) = flow;
+       }
+
        err = nf_tables_delrule_deactivate(ctx, rule);
        if (err < 0) {
                nft_trans_destroy(trans);
 
        return nft_flow_block_chain(basechain, NULL, cmd);
 }
 
+static void nft_flow_rule_offload_abort(struct net *net,
+                                       struct nft_trans *trans)
+{
+       int err = 0;
+
+       list_for_each_entry_continue_reverse(trans, &net->nft.commit_list, list) {
+               if (trans->ctx.family != NFPROTO_NETDEV)
+                       continue;
+
+               switch (trans->msg_type) {
+               case NFT_MSG_NEWCHAIN:
+                       if (!(trans->ctx.chain->flags & NFT_CHAIN_HW_OFFLOAD) ||
+                           nft_trans_chain_update(trans))
+                               continue;
+
+                       err = nft_flow_offload_chain(trans->ctx.chain, NULL,
+                                                    FLOW_BLOCK_UNBIND);
+                       break;
+               case NFT_MSG_DELCHAIN:
+                       if (!(trans->ctx.chain->flags & NFT_CHAIN_HW_OFFLOAD))
+                               continue;
+
+                       err = nft_flow_offload_chain(trans->ctx.chain, NULL,
+                                                    FLOW_BLOCK_BIND);
+                       break;
+               case NFT_MSG_NEWRULE:
+                       if (!(trans->ctx.chain->flags & NFT_CHAIN_HW_OFFLOAD))
+                               continue;
+
+                       err = nft_flow_offload_rule(trans->ctx.chain,
+                                                   nft_trans_rule(trans),
+                                                   NULL, FLOW_CLS_DESTROY);
+                       break;
+               case NFT_MSG_DELRULE:
+                       if (!(trans->ctx.chain->flags & NFT_CHAIN_HW_OFFLOAD))
+                               continue;
+
+                       err = nft_flow_offload_rule(trans->ctx.chain,
+                                                   nft_trans_rule(trans),
+                                                   nft_trans_flow_rule(trans),
+                                                   FLOW_CLS_REPLACE);
+                       break;
+               }
+
+               if (WARN_ON_ONCE(err))
+                       break;
+       }
+}
+
 int nft_flow_rule_offload_commit(struct net *net)
 {
        struct nft_trans *trans;
                        break;
                }
 
-               if (err)
+               if (err) {
+                       nft_flow_rule_offload_abort(net, trans);
                        break;
+               }
        }
 
        list_for_each_entry(trans, &net->nft.commit_list, list) {
 
                switch (trans->msg_type) {
                case NFT_MSG_NEWRULE:
+               case NFT_MSG_DELRULE:
                        if (!(trans->ctx.chain->flags & NFT_CHAIN_HW_OFFLOAD))
                                continue;