extern struct nft_expr_type nft_imm_type;
 extern struct nft_expr_type nft_cmp_type;
+extern struct nft_expr_type nft_counter_type;
 extern struct nft_expr_type nft_lookup_type;
 extern struct nft_expr_type nft_bitwise_type;
 extern struct nft_expr_type nft_byteorder_type;
 #ifdef CONFIG_NETWORK_SECMARK
 extern struct nft_object_type nft_secmark_obj_type;
 #endif
+extern struct nft_object_type nft_counter_obj_type;
 
 int nf_tables_core_module_init(void);
 void nf_tables_core_module_exit(void);
 bool nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set,
                            const u32 *key, const struct nft_set_ext **ext);
 
+void nft_counter_init_seqcount(void);
+
 struct nft_expr;
 struct nft_regs;
 struct nft_pktinfo;
                     struct nft_regs *regs, const struct nft_pktinfo *pkt);
 void nft_rt_get_eval(const struct nft_expr *expr,
                     struct nft_regs *regs, const struct nft_pktinfo *pkt);
+void nft_counter_eval(const struct nft_expr *expr, struct nft_regs *regs,
+                      const struct nft_pktinfo *pkt);
 #endif /* _NET_NF_TABLES_CORE_H */
 
                  nf_tables_trace.o nft_immediate.o nft_cmp.o nft_range.o \
                  nft_bitwise.o nft_byteorder.o nft_payload.o nft_lookup.o \
                  nft_dynset.o nft_meta.o nft_rt.o nft_exthdr.o nft_last.o \
-                 nft_chain_route.o nf_tables_offload.o \
+                 nft_counter.o nft_chain_route.o nf_tables_offload.o \
                  nft_set_hash.o nft_set_bitmap.o nft_set_rbtree.o \
                  nft_set_pipapo.o
 
 obj-$(CONFIG_NFT_REJECT_INET)  += nft_reject_inet.o
 obj-$(CONFIG_NFT_REJECT_NETDEV)        += nft_reject_netdev.o
 obj-$(CONFIG_NFT_TUNNEL)       += nft_tunnel.o
-obj-$(CONFIG_NFT_COUNTER)      += nft_counter.o
 obj-$(CONFIG_NFT_LOG)          += nft_log.o
 obj-$(CONFIG_NFT_MASQ)         += nft_masq.o
 obj-$(CONFIG_NFT_REDIR)                += nft_redir.o
 
 #include <linux/netfilter.h>
 #include <linux/netfilter/nf_tables.h>
 #include <net/netfilter/nf_tables.h>
+#include <net/netfilter/nf_tables_core.h>
 #include <net/netfilter/nf_tables_offload.h>
 
 struct nft_counter {
        [NFTA_COUNTER_BYTES]    = { .type = NLA_U64 },
 };
 
-static struct nft_object_type nft_counter_obj_type;
+struct nft_object_type nft_counter_obj_type;
 static const struct nft_object_ops nft_counter_obj_ops = {
        .type           = &nft_counter_obj_type,
        .size           = sizeof(struct nft_counter_percpu_priv),
        .dump           = nft_counter_obj_dump,
 };
 
-static struct nft_object_type nft_counter_obj_type __read_mostly = {
+struct nft_object_type nft_counter_obj_type __read_mostly = {
        .type           = NFT_OBJECT_COUNTER,
        .ops            = &nft_counter_obj_ops,
        .maxattr        = NFTA_COUNTER_MAX,
        .owner          = THIS_MODULE,
 };
 
-static void nft_counter_eval(const struct nft_expr *expr,
-                            struct nft_regs *regs,
-                            const struct nft_pktinfo *pkt)
+void nft_counter_eval(const struct nft_expr *expr, struct nft_regs *regs,
+                     const struct nft_pktinfo *pkt)
 {
        struct nft_counter_percpu_priv *priv = nft_expr_priv(expr);
 
        preempt_enable();
 }
 
-static struct nft_expr_type nft_counter_type;
+void nft_counter_init_seqcount(void)
+{
+       int cpu;
+
+       for_each_possible_cpu(cpu)
+               seqcount_init(per_cpu_ptr(&nft_counter_seq, cpu));
+}
+
+struct nft_expr_type nft_counter_type;
 static const struct nft_expr_ops nft_counter_ops = {
        .type           = &nft_counter_type,
        .size           = NFT_EXPR_SIZE(sizeof(struct nft_counter_percpu_priv)),
        .offload_stats  = nft_counter_offload_stats,
 };
 
-static struct nft_expr_type nft_counter_type __read_mostly = {
+struct nft_expr_type nft_counter_type __read_mostly = {
        .name           = "counter",
        .ops            = &nft_counter_ops,
        .policy         = nft_counter_policy,
        .flags          = NFT_EXPR_STATEFUL,
        .owner          = THIS_MODULE,
 };
-
-static int __init nft_counter_module_init(void)
-{
-       int cpu, err;
-
-       for_each_possible_cpu(cpu)
-               seqcount_init(per_cpu_ptr(&nft_counter_seq, cpu));
-
-       err = nft_register_obj(&nft_counter_obj_type);
-       if (err < 0)
-               return err;
-
-       err = nft_register_expr(&nft_counter_type);
-       if (err < 0)
-               goto err1;
-
-       return 0;
-err1:
-       nft_unregister_obj(&nft_counter_obj_type);
-       return err;
-}
-
-static void __exit nft_counter_module_exit(void)
-{
-       nft_unregister_expr(&nft_counter_type);
-       nft_unregister_obj(&nft_counter_obj_type);
-}
-
-module_init(nft_counter_module_init);
-module_exit(nft_counter_module_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
-MODULE_ALIAS_NFT_EXPR("counter");
-MODULE_ALIAS_NFT_OBJ(NFT_OBJECT_COUNTER);
-MODULE_DESCRIPTION("nftables counter rule support");