const struct nft_set_desc *desc,
                                                const struct nlattr * const nla[]);
        void                            (*destroy)(const struct nft_set *set);
+       void                            (*gc_init)(const struct nft_set *set);
 
        unsigned int                    elemsize;
 };
 };
 
 #define NFT_EXPR_STATEFUL              0x1
+#define NFT_EXPR_GC                    0x2
 
 /**
  *     struct nft_expr_ops - nf_tables expression operations
        int                             (*validate)(const struct nft_ctx *ctx,
                                                    const struct nft_expr *expr,
                                                    const struct nft_data **data);
+       bool                            (*gc)(struct net *net,
+                                             const struct nft_expr *expr);
        const struct nft_expr_type      *type;
        void                            *data;
 };
 
                err = -EOPNOTSUPP;
                if (!(priv->expr->ops->type->flags & NFT_EXPR_STATEFUL))
                        goto err1;
+
+               if (priv->expr->ops->type->flags & NFT_EXPR_GC) {
+                       if (set->flags & NFT_SET_TIMEOUT)
+                               goto err1;
+                       if (!set->ops->gc_init)
+                               goto err1;
+                       set->ops->gc_init(set);
+               }
+
        } else if (set->flags & NFT_SET_EVAL)
                return -EINVAL;
 
 
                        continue;
                }
 
+               if (nft_set_ext_exists(&he->ext, NFT_SET_EXT_EXPR)) {
+                       struct nft_expr *expr = nft_set_ext_expr(&he->ext);
+
+                       if (expr->ops->gc &&
+                           expr->ops->gc(read_pnet(&set->net), expr))
+                               goto gc;
+               }
                if (!nft_set_elem_expired(&he->ext))
                        continue;
+gc:
                if (nft_set_elem_mark_busy(&he->ext))
                        continue;
 
        return sizeof(struct nft_rhash);
 }
 
+static void nft_rhash_gc_init(const struct nft_set *set)
+{
+       struct nft_rhash *priv = nft_set_priv(set);
+
+       queue_delayed_work(system_power_efficient_wq, &priv->gc_work,
+                          nft_set_gc_interval(set));
+}
+
 static int nft_rhash_init(const struct nft_set *set,
                          const struct nft_set_desc *desc,
                          const struct nlattr * const tb[])
 
        INIT_DEFERRABLE_WORK(&priv->gc_work, nft_rhash_gc);
        if (set->flags & NFT_SET_TIMEOUT)
-               queue_delayed_work(system_power_efficient_wq, &priv->gc_work,
-                                  nft_set_gc_interval(set));
+               nft_rhash_gc_init(set);
+
        return 0;
 }
 
                .elemsize       = offsetof(struct nft_rhash_elem, ext),
                .estimate       = nft_rhash_estimate,
                .init           = nft_rhash_init,
+               .gc_init        = nft_rhash_gc_init,
                .destroy        = nft_rhash_destroy,
                .insert         = nft_rhash_insert,
                .activate       = nft_rhash_activate,