nft_unregister_basechain(nft_base_chain(chain), hook_nops);
 }
 
-/* Internal table flags */
-#define NFT_TABLE_INACTIVE     (1 << 15)
-
 static int nft_trans_table_add(struct nft_ctx *ctx, int msg_type)
 {
        struct nft_trans *trans;
                return -ENOMEM;
 
        if (msg_type == NFT_MSG_NEWTABLE)
-               ctx->table->flags |= NFT_TABLE_INACTIVE;
+               nft_activate_next(ctx->net, ctx->table);
 
        list_add_tail(&trans->list, &ctx->net->nft.commit_list);
        return 0;
        if (err < 0)
                return err;
 
-       list_del_rcu(&ctx->table->list);
+       nft_deactivate_next(ctx->net, ctx->table);
        return err;
 }
 
  */
 
 static struct nft_table *nft_table_lookup(const struct nft_af_info *afi,
-                                         const struct nlattr *nla)
+                                         const struct nlattr *nla,
+                                         u8 genmask)
 {
        struct nft_table *table;
 
        list_for_each_entry(table, &afi->tables, list) {
-               if (!nla_strcmp(nla, table->name))
+               if (!nla_strcmp(nla, table->name) &&
+                   nft_active_genmask(table, genmask))
                        return table;
        }
        return NULL;
 }
 
 static struct nft_table *nf_tables_table_lookup(const struct nft_af_info *afi,
-                                               const struct nlattr *nla)
+                                               const struct nlattr *nla,
+                                               u8 genmask)
 {
        struct nft_table *table;
 
        if (nla == NULL)
                return ERR_PTR(-EINVAL);
 
-       table = nft_table_lookup(afi, nla);
+       table = nft_table_lookup(afi, nla, genmask);
        if (table != NULL)
                return table;
 
                        if (idx > s_idx)
                                memset(&cb->args[1], 0,
                                       sizeof(cb->args) - sizeof(cb->args[0]));
+                       if (!nft_is_active(net, table))
+                               continue;
                        if (nf_tables_fill_table_info(skb, net,
                                                      NETLINK_CB(cb->skb).portid,
                                                      cb->nlh->nlmsg_seq,
                              const struct nlattr * const nla[])
 {
        const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
+       u8 genmask = nft_genmask_cur(net);
        const struct nft_af_info *afi;
        const struct nft_table *table;
        struct sk_buff *skb2;
        if (IS_ERR(afi))
                return PTR_ERR(afi);
 
-       table = nf_tables_table_lookup(afi, nla[NFTA_TABLE_NAME]);
+       table = nf_tables_table_lookup(afi, nla[NFTA_TABLE_NAME], genmask);
        if (IS_ERR(table))
                return PTR_ERR(table);
-       if (table->flags & NFT_TABLE_INACTIVE)
-               return -ENOENT;
 
        skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
        if (!skb2)
                              const struct nlattr * const nla[])
 {
        const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
+       u8 genmask = nft_genmask_next(net);
        const struct nlattr *name;
        struct nft_af_info *afi;
        struct nft_table *table;
                return PTR_ERR(afi);
 
        name = nla[NFTA_TABLE_NAME];
-       table = nf_tables_table_lookup(afi, name);
+       table = nf_tables_table_lookup(afi, name, genmask);
        if (IS_ERR(table)) {
                if (PTR_ERR(table) != -ENOENT)
                        return PTR_ERR(table);
        }
 
        if (table != NULL) {
-               if (table->flags & NFT_TABLE_INACTIVE)
-                       return -ENOENT;
                if (nlh->nlmsg_flags & NLM_F_EXCL)
                        return -EEXIST;
                if (nlh->nlmsg_flags & NLM_F_REPLACE)
 
                ctx->afi = afi;
                list_for_each_entry_safe(table, nt, &afi->tables, list) {
+                       if (!nft_is_active_next(ctx->net, table))
+                               continue;
+
                        if (nla[NFTA_TABLE_NAME] &&
                            nla_strcmp(nla[NFTA_TABLE_NAME], table->name) != 0)
                                continue;
                              const struct nlattr * const nla[])
 {
        const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
+       u8 genmask = nft_genmask_next(net);
        struct nft_af_info *afi;
        struct nft_table *table;
        int family = nfmsg->nfgen_family;
        if (IS_ERR(afi))
                return PTR_ERR(afi);
 
-       table = nf_tables_table_lookup(afi, nla[NFTA_TABLE_NAME]);
+       table = nf_tables_table_lookup(afi, nla[NFTA_TABLE_NAME], genmask);
        if (IS_ERR(table))
                return PTR_ERR(table);
 
                              const struct nlattr * const nla[])
 {
        const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
+       u8 genmask = nft_genmask_cur(net);
        const struct nft_af_info *afi;
        const struct nft_table *table;
        const struct nft_chain *chain;
        if (IS_ERR(afi))
                return PTR_ERR(afi);
 
-       table = nf_tables_table_lookup(afi, nla[NFTA_CHAIN_TABLE]);
+       table = nf_tables_table_lookup(afi, nla[NFTA_CHAIN_TABLE], genmask);
        if (IS_ERR(table))
                return PTR_ERR(table);
-       if (table->flags & NFT_TABLE_INACTIVE)
-               return -ENOENT;
 
        chain = nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME]);
        if (IS_ERR(chain))
        struct nft_chain *chain;
        struct nft_base_chain *basechain = NULL;
        struct nlattr *ha[NFTA_HOOK_MAX + 1];
+       u8 genmask = nft_genmask_next(net);
        int family = nfmsg->nfgen_family;
        struct net_device *dev = NULL;
        u8 policy = NF_ACCEPT;
        if (IS_ERR(afi))
                return PTR_ERR(afi);
 
-       table = nf_tables_table_lookup(afi, nla[NFTA_CHAIN_TABLE]);
+       table = nf_tables_table_lookup(afi, nla[NFTA_CHAIN_TABLE], genmask);
        if (IS_ERR(table))
                return PTR_ERR(table);
 
                              const struct nlattr * const nla[])
 {
        const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
+       u8 genmask = nft_genmask_next(net);
        struct nft_af_info *afi;
        struct nft_table *table;
        struct nft_chain *chain;
        if (IS_ERR(afi))
                return PTR_ERR(afi);
 
-       table = nf_tables_table_lookup(afi, nla[NFTA_CHAIN_TABLE]);
+       table = nf_tables_table_lookup(afi, nla[NFTA_CHAIN_TABLE], genmask);
        if (IS_ERR(table))
                return PTR_ERR(table);
 
                             const struct nlattr * const nla[])
 {
        const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
+       u8 genmask = nft_genmask_cur(net);
        const struct nft_af_info *afi;
        const struct nft_table *table;
        const struct nft_chain *chain;
        if (IS_ERR(afi))
                return PTR_ERR(afi);
 
-       table = nf_tables_table_lookup(afi, nla[NFTA_RULE_TABLE]);
+       table = nf_tables_table_lookup(afi, nla[NFTA_RULE_TABLE], genmask);
        if (IS_ERR(table))
                return PTR_ERR(table);
-       if (table->flags & NFT_TABLE_INACTIVE)
-               return -ENOENT;
 
        chain = nf_tables_chain_lookup(table, nla[NFTA_RULE_CHAIN]);
        if (IS_ERR(chain))
                             const struct nlattr * const nla[])
 {
        const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
+       u8 genmask = nft_genmask_next(net);
        struct nft_af_info *afi;
        struct nft_table *table;
        struct nft_chain *chain;
        if (IS_ERR(afi))
                return PTR_ERR(afi);
 
-       table = nf_tables_table_lookup(afi, nla[NFTA_RULE_TABLE]);
+       table = nf_tables_table_lookup(afi, nla[NFTA_RULE_TABLE], genmask);
        if (IS_ERR(table))
                return PTR_ERR(table);
 
                             const struct nlattr * const nla[])
 {
        const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
+       u8 genmask = nft_genmask_next(net);
        struct nft_af_info *afi;
        struct nft_table *table;
        struct nft_chain *chain = NULL;
        if (IS_ERR(afi))
                return PTR_ERR(afi);
 
-       table = nf_tables_table_lookup(afi, nla[NFTA_RULE_TABLE]);
+       table = nf_tables_table_lookup(afi, nla[NFTA_RULE_TABLE], genmask);
        if (IS_ERR(table))
                return PTR_ERR(table);
 
 static int nft_ctx_init_from_setattr(struct nft_ctx *ctx, struct net *net,
                                     const struct sk_buff *skb,
                                     const struct nlmsghdr *nlh,
-                                    const struct nlattr * const nla[])
+                                    const struct nlattr * const nla[],
+                                    u8 genmask)
 {
        const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
        struct nft_af_info *afi = NULL;
                if (afi == NULL)
                        return -EAFNOSUPPORT;
 
-               table = nf_tables_table_lookup(afi, nla[NFTA_SET_TABLE]);
+               table = nf_tables_table_lookup(afi, nla[NFTA_SET_TABLE],
+                                              genmask);
                if (IS_ERR(table))
                        return PTR_ERR(table);
        }
                            struct sk_buff *skb, const struct nlmsghdr *nlh,
                            const struct nlattr * const nla[])
 {
+       u8 genmask = nft_genmask_cur(net);
        const struct nft_set *set;
        struct nft_ctx ctx;
        struct sk_buff *skb2;
        int err;
 
        /* Verify existence before starting dump */
-       err = nft_ctx_init_from_setattr(&ctx, net, skb, nlh, nla);
+       err = nft_ctx_init_from_setattr(&ctx, net, skb, nlh, nla, genmask);
        if (err < 0)
                return err;
 
                            const struct nlattr * const nla[])
 {
        const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
+       u8 genmask = nft_genmask_next(net);
        const struct nft_set_ops *ops;
        struct nft_af_info *afi;
        struct nft_table *table;
        if (IS_ERR(afi))
                return PTR_ERR(afi);
 
-       table = nf_tables_table_lookup(afi, nla[NFTA_SET_TABLE]);
+       table = nf_tables_table_lookup(afi, nla[NFTA_SET_TABLE], genmask);
        if (IS_ERR(table))
                return PTR_ERR(table);
 
                            const struct nlattr * const nla[])
 {
        const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
+       u8 genmask = nft_genmask_next(net);
        struct nft_set *set;
        struct nft_ctx ctx;
        int err;
        if (nla[NFTA_SET_TABLE] == NULL)
                return -EINVAL;
 
-       err = nft_ctx_init_from_setattr(&ctx, net, skb, nlh, nla);
+       err = nft_ctx_init_from_setattr(&ctx, net, skb, nlh, nla, genmask);
        if (err < 0)
                return err;
 
 static int nft_ctx_init_from_elemattr(struct nft_ctx *ctx, struct net *net,
                                      const struct sk_buff *skb,
                                      const struct nlmsghdr *nlh,
-                                     const struct nlattr * const nla[])
+                                     const struct nlattr * const nla[],
+                                     u8 genmask)
 {
        const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
        struct nft_af_info *afi;
        if (IS_ERR(afi))
                return PTR_ERR(afi);
 
-       table = nf_tables_table_lookup(afi, nla[NFTA_SET_ELEM_LIST_TABLE]);
+       table = nf_tables_table_lookup(afi, nla[NFTA_SET_ELEM_LIST_TABLE],
+                                      genmask);
        if (IS_ERR(table))
                return PTR_ERR(table);
 
 static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
 {
        struct net *net = sock_net(skb->sk);
+       u8 genmask = nft_genmask_cur(net);
        const struct nft_set *set;
        struct nft_set_dump_args args;
        struct nft_ctx ctx;
                return err;
 
        err = nft_ctx_init_from_elemattr(&ctx, net, cb->skb, cb->nlh,
-                                        (void *)nla);
+                                        (void *)nla, genmask);
        if (err < 0)
                return err;
-       if (ctx.table->flags & NFT_TABLE_INACTIVE)
-               return -ENOENT;
 
        set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_ELEM_LIST_SET]);
        if (IS_ERR(set))
                                struct sk_buff *skb, const struct nlmsghdr *nlh,
                                const struct nlattr * const nla[])
 {
+       u8 genmask = nft_genmask_cur(net);
        const struct nft_set *set;
        struct nft_ctx ctx;
        int err;
 
-       err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla);
+       err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla, genmask);
        if (err < 0)
                return err;
-       if (ctx.table->flags & NFT_TABLE_INACTIVE)
-               return -ENOENT;
 
        set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_ELEM_LIST_SET]);
        if (IS_ERR(set))
                                struct sk_buff *skb, const struct nlmsghdr *nlh,
                                const struct nlattr * const nla[])
 {
+       u8 genmask = nft_genmask_next(net);
        const struct nlattr *attr;
        struct nft_set *set;
        struct nft_ctx ctx;
        if (nla[NFTA_SET_ELEM_LIST_ELEMENTS] == NULL)
                return -EINVAL;
 
-       err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla);
+       err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla, genmask);
        if (err < 0)
                return err;
 
                                struct sk_buff *skb, const struct nlmsghdr *nlh,
                                const struct nlattr * const nla[])
 {
+       u8 genmask = nft_genmask_next(net);
        const struct nlattr *attr;
        struct nft_set *set;
        struct nft_ctx ctx;
        if (nla[NFTA_SET_ELEM_LIST_ELEMENTS] == NULL)
                return -EINVAL;
 
-       err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla);
+       err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla, genmask);
        if (err < 0)
                return err;
 
                                        trans->ctx.table->flags |= NFT_TABLE_F_DORMANT;
                                }
                        } else {
-                               trans->ctx.table->flags &= ~NFT_TABLE_INACTIVE;
+                               nft_clear(net, trans->ctx.table);
                        }
                        nf_tables_table_notify(&trans->ctx, NFT_MSG_NEWTABLE);
                        nft_trans_destroy(trans);
                        break;
                case NFT_MSG_DELTABLE:
+                       list_del_rcu(&trans->ctx.table->list);
                        nf_tables_table_notify(&trans->ctx, NFT_MSG_DELTABLE);
                        break;
                case NFT_MSG_NEWCHAIN:
                        }
                        break;
                case NFT_MSG_DELTABLE:
-                       list_add_tail_rcu(&trans->ctx.table->list,
-                                         &trans->ctx.afi->tables);
+                       nft_clear(trans->ctx.net, trans->ctx.table);
                        nft_trans_destroy(trans);
                        break;
                case NFT_MSG_NEWCHAIN: