*     @dtype: data type (verdict or numeric type defined by userspace)
  *     @size: maximum set size
  *     @nelems: number of elements
+ *     @timeout: default timeout value in msecs
+ *     @gc_int: garbage collection interval in msecs
  *     @policy: set parameterization (see enum nft_set_policies)
  *     @ops: set ops
  *     @pnet: network namespace
        u32                             dtype;
        u32                             size;
        u32                             nelems;
+       u64                             timeout;
+       u32                             gc_int;
        u16                             policy;
        /* runtime data below here */
        const struct nft_set_ops        *ops ____cacheline_aligned;
 struct nft_set *nf_tables_set_lookup_byid(const struct net *net,
                                          const struct nlattr *nla);
 
+static inline unsigned long nft_set_gc_interval(const struct nft_set *set)
+{
+       return set->gc_int ? msecs_to_jiffies(set->gc_int) : HZ;
+}
+
 /**
  *     struct nft_set_binding - nf_tables set binding
  *
 
  * @NFT_SET_CONSTANT: set contents may not change while bound
  * @NFT_SET_INTERVAL: set contains intervals
  * @NFT_SET_MAP: set is used as a dictionary
+ * @NFT_SET_TIMEOUT: set uses timeouts
  */
 enum nft_set_flags {
        NFT_SET_ANONYMOUS               = 0x1,
        NFT_SET_CONSTANT                = 0x2,
        NFT_SET_INTERVAL                = 0x4,
        NFT_SET_MAP                     = 0x8,
+       NFT_SET_TIMEOUT                 = 0x10,
 };
 
 /**
  * @NFTA_SET_POLICY: selection policy (NLA_U32)
  * @NFTA_SET_DESC: set description (NLA_NESTED)
  * @NFTA_SET_ID: uniquely identifies a set in a transaction (NLA_U32)
+ * @NFTA_SET_TIMEOUT: default timeout value (NLA_U64)
+ * @NFTA_SET_GC_INTERVAL: garbage collection interval (NLA_U32)
  */
 enum nft_set_attributes {
        NFTA_SET_UNSPEC,
        NFTA_SET_POLICY,
        NFTA_SET_DESC,
        NFTA_SET_ID,
+       NFTA_SET_TIMEOUT,
+       NFTA_SET_GC_INTERVAL,
        __NFTA_SET_MAX
 };
 #define NFTA_SET_MAX           (__NFTA_SET_MAX - 1)
 
        [NFTA_SET_POLICY]               = { .type = NLA_U32 },
        [NFTA_SET_DESC]                 = { .type = NLA_NESTED },
        [NFTA_SET_ID]                   = { .type = NLA_U32 },
+       [NFTA_SET_TIMEOUT]              = { .type = NLA_U64 },
+       [NFTA_SET_GC_INTERVAL]          = { .type = NLA_U32 },
 };
 
 static const struct nla_policy nft_set_desc_policy[NFTA_SET_DESC_MAX + 1] = {
                        goto nla_put_failure;
        }
 
+       if (set->timeout &&
+           nla_put_be64(skb, NFTA_SET_TIMEOUT, cpu_to_be64(set->timeout)))
+               goto nla_put_failure;
+       if (set->gc_int &&
+           nla_put_be32(skb, NFTA_SET_GC_INTERVAL, htonl(set->gc_int)))
+               goto nla_put_failure;
+
        if (set->policy != NFT_SET_POL_PERFORMANCE) {
                if (nla_put_be32(skb, NFTA_SET_POLICY, htonl(set->policy)))
                        goto nla_put_failure;
        char name[IFNAMSIZ];
        unsigned int size;
        bool create;
-       u32 ktype, dtype, flags, policy;
+       u64 timeout;
+       u32 ktype, dtype, flags, policy, gc_int;
        struct nft_set_desc desc;
        int err;
 
        if (nla[NFTA_SET_FLAGS] != NULL) {
                flags = ntohl(nla_get_be32(nla[NFTA_SET_FLAGS]));
                if (flags & ~(NFT_SET_ANONYMOUS | NFT_SET_CONSTANT |
-                             NFT_SET_INTERVAL | NFT_SET_MAP))
+                             NFT_SET_INTERVAL | NFT_SET_MAP |
+                             NFT_SET_TIMEOUT))
                        return -EINVAL;
        }
 
        } else if (flags & NFT_SET_MAP)
                return -EINVAL;
 
+       timeout = 0;
+       if (nla[NFTA_SET_TIMEOUT] != NULL) {
+               if (!(flags & NFT_SET_TIMEOUT))
+                       return -EINVAL;
+               timeout = be64_to_cpu(nla_get_be64(nla[NFTA_SET_TIMEOUT]));
+       }
+       gc_int = 0;
+       if (nla[NFTA_SET_GC_INTERVAL] != NULL) {
+               if (!(flags & NFT_SET_TIMEOUT))
+                       return -EINVAL;
+               gc_int = ntohl(nla_get_be32(nla[NFTA_SET_GC_INTERVAL]));
+       }
+
        policy = NFT_SET_POL_PERFORMANCE;
        if (nla[NFTA_SET_POLICY] != NULL)
                policy = ntohl(nla_get_be32(nla[NFTA_SET_POLICY]));
        set->flags = flags;
        set->size  = desc.size;
        set->policy = policy;
+       set->timeout = timeout;
+       set->gc_int = gc_int;
 
        err = ops->init(set, &desc, nla);
        if (err < 0)