Blob Blame History Raw
From 00e5caa25a0cd77a1c94ee1444097db66c9e117b Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Mon, 17 Dec 2018 17:28:32 +0100
Subject: [PATCH] src: remove nftnl_rule_cmp() and nftnl_expr_cmp()

Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1658533
Upstream Status: libnftnl commit 6dc1c3d8bb640
Conflicts: Changes to src/expr/{osf,tproxy,xfrm}.c ignored since support
           for those expressions has not been backported.

commit 6dc1c3d8bb64077da7f3f28c7368fb087d10a492
Author: Pablo Neira Ayuso <pablo@netfilter.org>
Date:   Wed Oct 24 19:18:50 2018 +0200

    src: remove nftnl_rule_cmp() and nftnl_expr_cmp()

    These functions are not very useful, rule comparison from this layer
    does not work well with implicit set definitions.

    This infrastructure was added as an attempt to support for deletion by
    name from this layer, which should be done from higher level libnftables
    library. Finally, we never had a client for this code in
    git.netfilter.org.

    Let's remove it and bump libversion for safety reasons.

    Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 Make_global.am          |  2 +-
 include/data_reg.h      |  2 --
 include/expr_ops.h      |  1 -
 include/libnftnl/expr.h |  2 --
 include/libnftnl/rule.h |  2 --
 src/expr.c              | 10 ----------
 src/expr/bitwise.c      | 22 ----------------------
 src/expr/byteorder.c    | 22 ----------------------
 src/expr/cmp.c          | 18 ------------------
 src/expr/connlimit.c    | 16 ----------------
 src/expr/counter.c      | 16 ----------------
 src/expr/ct.c           | 20 --------------------
 src/expr/data_reg.c     | 17 -----------------
 src/expr/dup.c          | 16 ----------------
 src/expr/dynset.c       | 26 --------------------------
 src/expr/exthdr.c       | 26 --------------------------
 src/expr/fib.c          | 18 ------------------
 src/expr/flow_offload.c | 14 --------------
 src/expr/fwd.c          | 18 ------------------
 src/expr/hash.c         | 30 ------------------------------
 src/expr/immediate.c    | 25 -------------------------
 src/expr/limit.c        | 22 ----------------------
 src/expr/log.c          | 24 ------------------------
 src/expr/lookup.c       | 22 ----------------------
 src/expr/masq.c         | 18 ------------------
 src/expr/match.c        | 20 --------------------
 src/expr/meta.c         | 18 ------------------
 src/expr/nat.c          | 25 -------------------------
 src/expr/numgen.c       | 24 ------------------------
 src/expr/objref.c       | 22 ----------------------
 src/expr/payload.c      | 28 ----------------------------
 src/expr/queue.c        | 20 --------------------
 src/expr/redir.c        | 18 ------------------
 src/expr/reject.c       | 16 ----------------
 src/expr/rt.c           | 16 ----------------
 src/expr/socket.c       | 16 ----------------
 src/expr/target.c       | 20 --------------------
 src/libnftnl.map        | 18 ++++--------------
 src/rule.c              | 31 -------------------------------
 39 files changed, 5 insertions(+), 696 deletions(-)

diff --git a/Make_global.am b/Make_global.am
index e12a3f7..307816b 100644
--- a/Make_global.am
+++ b/Make_global.am
@@ -18,7 +18,7 @@
 # set age to 0.
 # </snippet>
 #
-LIBVERSION=10:0:3
+LIBVERSION=11:0:0
 
 AM_CPPFLAGS = ${regular_CPPFLAGS} -I${top_srcdir}/include ${LIBMNL_CFLAGS} ${LIBMXML_CFLAGS}
 AM_CFLAGS = ${regular_CFLAGS} ${GCC_FVISIBILITY_HIDDEN}
diff --git a/include/data_reg.h b/include/data_reg.h
index 3fec7cd..f2675f2 100644
--- a/include/data_reg.h
+++ b/include/data_reg.h
@@ -28,8 +28,6 @@ int nftnl_data_reg_snprintf(char *buf, size_t size,
 			    const union nftnl_data_reg *reg,
 			    uint32_t output_format, uint32_t flags,
 			    int reg_type);
-bool nftnl_data_reg_cmp(const union nftnl_data_reg *r1,
-		        const union nftnl_data_reg *r2, int reg_type);
 struct nlattr;
 
 int nftnl_parse_data(union nftnl_data_reg *data, struct nlattr *attr, int *type);
diff --git a/include/expr_ops.h b/include/expr_ops.h
index e639390..e8809fa 100644
--- a/include/expr_ops.h
+++ b/include/expr_ops.h
@@ -13,7 +13,6 @@ struct expr_ops {
 	uint32_t alloc_len;
 	int	max_attr;
 	void	(*free)(const struct nftnl_expr *e);
-	bool    (*cmp)(const struct nftnl_expr *e1, const struct nftnl_expr *e2);
 	int	(*set)(struct nftnl_expr *e, uint16_t type, const void *data, uint32_t data_len);
 	const void *(*get)(const struct nftnl_expr *e, uint16_t type, uint32_t *data_len);
 	int 	(*parse)(struct nftnl_expr *e, struct nlattr *attr);
diff --git a/include/libnftnl/expr.h b/include/libnftnl/expr.h
index 219104e..09dc55c 100644
--- a/include/libnftnl/expr.h
+++ b/include/libnftnl/expr.h
@@ -36,8 +36,6 @@ uint32_t nftnl_expr_get_u32(const struct nftnl_expr *expr, uint16_t type);
 uint64_t nftnl_expr_get_u64(const struct nftnl_expr *expr, uint16_t type);
 const char *nftnl_expr_get_str(const struct nftnl_expr *expr, uint16_t type);
 
-bool nftnl_expr_cmp(const struct nftnl_expr *e1, const struct nftnl_expr *e2);
-
 int nftnl_expr_snprintf(char *buf, size_t buflen, const struct nftnl_expr *expr, uint32_t type, uint32_t flags);
 int nftnl_expr_fprintf(FILE *fp, const struct nftnl_expr *expr, uint32_t type, uint32_t flags);
 
diff --git a/include/libnftnl/rule.h b/include/libnftnl/rule.h
index 765d2ce..8501c86 100644
--- a/include/libnftnl/rule.h
+++ b/include/libnftnl/rule.h
@@ -51,8 +51,6 @@ uint64_t nftnl_rule_get_u64(const struct nftnl_rule *r, uint16_t attr);
 
 void nftnl_rule_add_expr(struct nftnl_rule *r, struct nftnl_expr *expr);
 
-bool nftnl_rule_cmp(const struct nftnl_rule *r1, const struct nftnl_rule *r2);
-
 struct nlmsghdr;
 
 void nftnl_rule_nlmsg_build_payload(struct nlmsghdr *nlh, struct nftnl_rule *t);
diff --git a/src/expr.c b/src/expr.c
index 62565e0..80c4c36 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -203,16 +203,6 @@ const char *nftnl_expr_get_str(const struct nftnl_expr *expr, uint16_t type)
 	return (const char *)nftnl_expr_get(expr, type, &data_len);
 }
 
-EXPORT_SYMBOL(nftnl_expr_cmp);
-bool nftnl_expr_cmp(const struct nftnl_expr *e1, const struct nftnl_expr *e2)
-{
-	if (e1->flags != e2->flags ||
-	    strcmp(e1->ops->name, e2->ops->name) != 0)
-		return false;
-
-	return e1->ops->cmp(e1, e2);
-}
-
 void nftnl_expr_build_payload(struct nlmsghdr *nlh, struct nftnl_expr *expr)
 {
 	struct nlattr *nest;
diff --git a/src/expr/bitwise.c b/src/expr/bitwise.c
index a89734b..6f064ec 100644
--- a/src/expr/bitwise.c
+++ b/src/expr/bitwise.c
@@ -269,32 +269,10 @@ nftnl_expr_bitwise_snprintf(char *buf, size_t size, uint32_t type,
 	return -1;
 }
 
-static bool nftnl_expr_bitwise_cmp(const struct nftnl_expr *e1,
-				   const struct nftnl_expr *e2)
-{
-	struct nftnl_expr_bitwise *b1 = nftnl_expr_data(e1);
-	struct nftnl_expr_bitwise *b2 = nftnl_expr_data(e2);
-	bool eq = true;
-
-	if (e1->flags & (1 << NFTNL_EXPR_BITWISE_SREG))
-		eq &= (b1->sreg == b2->sreg);
-	if (e1->flags & (1 << NFTNL_EXPR_BITWISE_DREG))
-		eq &= (b1->dreg == b2->dreg);
-	if (e1->flags & (1 << NFTNL_EXPR_BITWISE_LEN))
-		eq &= (b1->len == b2->len);
-	if (e1->flags & (1 << NFTNL_EXPR_BITWISE_MASK))
-		eq &= nftnl_data_reg_cmp(&b1->mask, &b2->mask, DATA_VALUE);
-	if (e1->flags & (1 << NFTNL_EXPR_BITWISE_XOR))
-		eq &= nftnl_data_reg_cmp(&b1->xor, &b2->xor, DATA_VALUE);
-
-	return eq;
-}
-
 struct expr_ops expr_ops_bitwise = {
 	.name		= "bitwise",
 	.alloc_len	= sizeof(struct nftnl_expr_bitwise),
 	.max_attr	= NFTA_BITWISE_MAX,
-	.cmp		= nftnl_expr_bitwise_cmp,
 	.set		= nftnl_expr_bitwise_set,
 	.get		= nftnl_expr_bitwise_get,
 	.parse		= nftnl_expr_bitwise_parse,
diff --git a/src/expr/byteorder.c b/src/expr/byteorder.c
index 47c04cf..02c8984 100644
--- a/src/expr/byteorder.c
+++ b/src/expr/byteorder.c
@@ -284,32 +284,10 @@ nftnl_expr_byteorder_snprintf(char *buf, size_t size, uint32_t type,
 	return -1;
 }
 
-static bool nftnl_expr_byteorder_cmp(const struct nftnl_expr *e1,
-				     const struct nftnl_expr *e2)
-{
-	struct nftnl_expr_byteorder *b1 = nftnl_expr_data(e1);
-	struct nftnl_expr_byteorder *b2 = nftnl_expr_data(e2);
-	bool eq = true;
-
-	if (e1->flags & (1 << NFTNL_EXPR_BYTEORDER_SREG))
-		eq &= (b1->sreg == b2->sreg);
-	if (e1->flags & (1 << NFTNL_EXPR_BYTEORDER_DREG))
-		eq &= (b1->dreg == b2->dreg);
-	if (e1->flags & (1 << NFTNL_EXPR_BYTEORDER_OP))
-		eq &= (b1->op == b2->op);
-	if (e1->flags & (1 << NFTNL_EXPR_BYTEORDER_LEN))
-		eq &= (b1->len == b2->len);
-	if (e1->flags & (1 << NFTNL_EXPR_BYTEORDER_SIZE))
-		eq &= (b1->size == b2->size);
-
-	return eq;
-}
-
 struct expr_ops expr_ops_byteorder = {
 	.name		= "byteorder",
 	.alloc_len	= sizeof(struct nftnl_expr_byteorder),
 	.max_attr	= NFTA_BYTEORDER_MAX,
-	.cmp		= nftnl_expr_byteorder_cmp,
 	.set		= nftnl_expr_byteorder_set,
 	.get		= nftnl_expr_byteorder_get,
 	.parse		= nftnl_expr_byteorder_parse,
diff --git a/src/expr/cmp.c b/src/expr/cmp.c
index b26d0eb..5209d45 100644
--- a/src/expr/cmp.c
+++ b/src/expr/cmp.c
@@ -258,28 +258,10 @@ nftnl_expr_cmp_snprintf(char *buf, size_t size, uint32_t type,
 	return -1;
 }
 
-static bool nftnl_expr_cmp_cmp(const struct nftnl_expr *e1,
-			       const struct nftnl_expr *e2)
-{
-	struct nftnl_expr_cmp *c1 = nftnl_expr_data(e1);
-	struct nftnl_expr_cmp *c2 = nftnl_expr_data(e2);
-	bool eq = true;
-
-	if (e1->flags & (1 << NFTNL_EXPR_CMP_DATA))
-		eq &= nftnl_data_reg_cmp(&c1->data, &c2->data, DATA_VALUE);
-	if (e1->flags & (1 << NFTNL_EXPR_CMP_SREG))
-		eq &= (c1->sreg == c2->sreg);
-	if (e1->flags & (1 << NFTNL_EXPR_CMP_OP))
-		eq &= (c1->op == c2->op);
-
-	return eq;
-}
-
 struct expr_ops expr_ops_cmp = {
 	.name		= "cmp",
 	.alloc_len	= sizeof(struct nftnl_expr_cmp),
 	.max_attr	= NFTA_CMP_MAX,
-	.cmp		= nftnl_expr_cmp_cmp,
 	.set		= nftnl_expr_cmp_set,
 	.get		= nftnl_expr_cmp_get,
 	.parse		= nftnl_expr_cmp_parse,
diff --git a/src/expr/connlimit.c b/src/expr/connlimit.c
index 60965b5..9b4668b 100644
--- a/src/expr/connlimit.c
+++ b/src/expr/connlimit.c
@@ -178,26 +178,10 @@ static int nftnl_expr_connlimit_snprintf(char *buf, size_t len, uint32_t type,
 	return -1;
 }
 
-static bool nftnl_expr_connlimit_cmp(const struct nftnl_expr *e1,
-				   const struct nftnl_expr *e2)
-{
-	struct nftnl_expr_connlimit *c1 = nftnl_expr_data(e1);
-	struct nftnl_expr_connlimit *c2 = nftnl_expr_data(e2);
-	bool eq = true;
-
-	if (e1->flags & (1 << NFTNL_EXPR_CONNLIMIT_COUNT))
-		eq &= (c1->count == c2->count);
-	if (e1->flags & (1 << NFTNL_EXPR_CONNLIMIT_FLAGS))
-		eq &= (c1->flags == c2->flags);
-
-	return eq;
-}
-
 struct expr_ops expr_ops_connlimit = {
 	.name		= "connlimit",
 	.alloc_len	= sizeof(struct nftnl_expr_connlimit),
 	.max_attr	= NFTA_CONNLIMIT_MAX,
-	.cmp		= nftnl_expr_connlimit_cmp,
 	.set		= nftnl_expr_connlimit_set,
 	.get		= nftnl_expr_connlimit_get,
 	.parse		= nftnl_expr_connlimit_parse,
diff --git a/src/expr/counter.c b/src/expr/counter.c
index 21901e8..1cfae2a 100644
--- a/src/expr/counter.c
+++ b/src/expr/counter.c
@@ -176,26 +176,10 @@ static int nftnl_expr_counter_snprintf(char *buf, size_t len, uint32_t type,
 	return -1;
 }
 
-static bool nftnl_expr_counter_cmp(const struct nftnl_expr *e1,
-				   const struct nftnl_expr *e2)
-{
-	struct nftnl_expr_counter *c1 = nftnl_expr_data(e1);
-	struct nftnl_expr_counter *c2 = nftnl_expr_data(e2);
-	bool eq = true;
-
-	if (e1->flags & (1 << NFTNL_EXPR_CTR_PACKETS))
-		eq &= (c1->pkts == c2->pkts);
-	if (e1->flags & (1 << NFTNL_EXPR_CTR_BYTES))
-		eq &= (c1->pkts == c2->pkts);
-
-	return eq;
-}
-
 struct expr_ops expr_ops_counter = {
 	.name		= "counter",
 	.alloc_len	= sizeof(struct nftnl_expr_counter),
 	.max_attr	= NFTA_COUNTER_MAX,
-	.cmp		= nftnl_expr_counter_cmp,
 	.set		= nftnl_expr_counter_set,
 	.get		= nftnl_expr_counter_get,
 	.parse		= nftnl_expr_counter_parse,
diff --git a/src/expr/ct.c b/src/expr/ct.c
index 39e9be6..ad354b5 100644
--- a/src/expr/ct.c
+++ b/src/expr/ct.c
@@ -329,30 +329,10 @@ nftnl_expr_ct_snprintf(char *buf, size_t len, uint32_t type,
 	return -1;
 }
 
-static bool nftnl_expr_ct_cmp(const struct nftnl_expr *e1,
-			      const struct nftnl_expr *e2)
-{
-	struct nftnl_expr_ct *c1 = nftnl_expr_data(e1);
-	struct nftnl_expr_ct *c2 = nftnl_expr_data(e2);
-	bool eq = true;
-
-	if (e1->flags & (1 << NFTNL_EXPR_CT_KEY))
-		eq &= (c1->key == c2->key);
-	if (e1->flags & (1 << NFTNL_EXPR_CT_DREG))
-		eq &= (c1->dreg == c2->dreg);
-	if (e1->flags & (1 << NFTNL_EXPR_CT_SREG))
-		eq &= (c1->sreg == c2->sreg);
-	if (e1->flags & (1 << NFTNL_EXPR_CT_DIR))
-		eq &= (c1->dir == c2->dir);
-
-	return eq;
-}
-
 struct expr_ops expr_ops_ct = {
 	.name		= "ct",
 	.alloc_len	= sizeof(struct nftnl_expr_ct),
 	.max_attr	= NFTA_CT_MAX,
-	.cmp		= nftnl_expr_ct_cmp,
 	.set		= nftnl_expr_ct_set,
 	.get		= nftnl_expr_ct_get,
 	.parse		= nftnl_expr_ct_parse,
diff --git a/src/expr/data_reg.c b/src/expr/data_reg.c
index 1b28b29..2e02f42 100644
--- a/src/expr/data_reg.c
+++ b/src/expr/data_reg.c
@@ -230,23 +230,6 @@ int nftnl_data_reg_snprintf(char *buf, size_t size,
 	return -1;
 }
 
-bool nftnl_data_reg_cmp(const union nftnl_data_reg *r1,
-		        const union nftnl_data_reg *r2, int reg_type)
-{
-	switch (reg_type) {
-	case DATA_VALUE:
-		return	r1->len == r2->len &&
-			!memcmp(r1->val, r2->val, r1->len);
-	case DATA_VERDICT:
-		return	r1->verdict == r2->verdict;
-	case DATA_CHAIN:
-		return	r1->verdict == r2->verdict &&
-			!strcmp(r1->chain, r2->chain);
-	default:
-		return false;
-	}
-}
-
 static int nftnl_data_parse_cb(const struct nlattr *attr, void *data)
 {
 	const struct nlattr **tb = data;
diff --git a/src/expr/dup.c b/src/expr/dup.c
index ed8e620..c1d4304 100644
--- a/src/expr/dup.c
+++ b/src/expr/dup.c
@@ -182,26 +182,10 @@ static int nftnl_expr_dup_snprintf(char *buf, size_t len, uint32_t type,
 	return -1;
 }
 
-static bool nftnl_expr_dup_cmp(const struct nftnl_expr *e1,
-			       const struct nftnl_expr *e2)
-{
-	struct nftnl_expr_dup *d1 = nftnl_expr_data(e1);
-	struct nftnl_expr_dup *d2 = nftnl_expr_data(e2);
-	bool eq = true;
-
-	if (e1->flags & (1 << NFTNL_EXPR_DUP_SREG_ADDR))
-		eq &= (d1->sreg_addr == d2->sreg_addr);
-	if (e1->flags & (1 << NFTNL_EXPR_DUP_SREG_DEV))
-		eq &= (d1->sreg_dev == d2->sreg_dev);
-
-	return eq;
-}
-
 struct expr_ops expr_ops_dup = {
 	.name		= "dup",
 	.alloc_len	= sizeof(struct nftnl_expr_dup),
 	.max_attr	= NFTA_DUP_MAX,
-	.cmp		= nftnl_expr_dup_cmp,
 	.set		= nftnl_expr_dup_set,
 	.get		= nftnl_expr_dup_get,
 	.parse		= nftnl_expr_dup_parse,
diff --git a/src/expr/dynset.c b/src/expr/dynset.c
index 160d0e1..7e9c8b2 100644
--- a/src/expr/dynset.c
+++ b/src/expr/dynset.c
@@ -333,37 +333,11 @@ static void nftnl_expr_dynset_free(const struct nftnl_expr *e)
 	xfree(dynset->set_name);
 }
 
-static bool nftnl_expr_dynset_cmp(const struct nftnl_expr *e1,
-				  const struct nftnl_expr *e2)
-{
-	struct nftnl_expr_dynset *d1 = nftnl_expr_data(e1);
-	struct nftnl_expr_dynset *d2 = nftnl_expr_data(e2);
-	bool eq = true;
-
-	if (e1->flags & (1 << NFTNL_EXPR_DYNSET_SREG_KEY))
-		eq &= (d1->sreg_key == d2->sreg_key);
-	if (e1->flags & (1 << NFTNL_EXPR_DYNSET_SREG_DATA))
-		eq &= (d1->sreg_data == d2->sreg_data);
-	if (e1->flags & (1 << NFTNL_EXPR_DYNSET_OP))
-		eq &= (d1->op == d2->op);
-	if (e1->flags & (1 << NFTNL_EXPR_DYNSET_TIMEOUT))
-		eq &= (d1->timeout == d2->timeout);
-	if (e1->flags & (1 << NFTNL_EXPR_DYNSET_EXPR))
-		eq &= nftnl_expr_cmp(d1->expr, d2->expr);
-	if (e1->flags & (1 << NFTNL_EXPR_DYNSET_SET_NAME))
-		eq &= !strcmp(d1->set_name, d2->set_name);
-	if (e1->flags & (1 << NFTNL_EXPR_DYNSET_SET_ID))
-		eq &= (d1->set_id == d2->set_id);
-
-	return eq;
-}
-
 struct expr_ops expr_ops_dynset = {
 	.name		= "dynset",
 	.alloc_len	= sizeof(struct nftnl_expr_dynset),
 	.max_attr	= NFTA_DYNSET_MAX,
 	.free		= nftnl_expr_dynset_free,
-	.cmp		= nftnl_expr_dynset_cmp,
 	.set		= nftnl_expr_dynset_set,
 	.get		= nftnl_expr_dynset_get,
 	.parse		= nftnl_expr_dynset_parse,
diff --git a/src/expr/exthdr.c b/src/expr/exthdr.c
index 75cafbc..4ec8920 100644
--- a/src/expr/exthdr.c
+++ b/src/expr/exthdr.c
@@ -351,36 +351,10 @@ nftnl_expr_exthdr_snprintf(char *buf, size_t len, uint32_t type,
 	return -1;
 }
 
-static bool nftnl_expr_exthdr_cmp(const struct nftnl_expr *e1,
-				  const struct nftnl_expr *e2)
-{
-	struct nftnl_expr_exthdr *h1 = nftnl_expr_data(e1);
-	struct nftnl_expr_exthdr *h2 = nftnl_expr_data(e2);
-	bool eq = true;
-
-	if (e1->flags & (1 << NFTNL_EXPR_EXTHDR_DREG))
-		eq &= (h1->dreg == h2->dreg);
-	if (e1->flags & (1 << NFTNL_EXPR_EXTHDR_SREG))
-		eq &= (h1->sreg == h2->sreg);
-	if (e1->flags & (1 << NFTNL_EXPR_EXTHDR_OFFSET))
-		eq &= (h1->offset == h2->offset);
-	if (e1->flags & (1 << NFTNL_EXPR_EXTHDR_LEN))
-		eq &= (h1->len == h2->len);
-	if (e1->flags & (1 << NFTNL_EXPR_EXTHDR_TYPE))
-		eq &= (h1->type == h2->type);
-	if (e1->flags & (1 << NFTNL_EXPR_EXTHDR_OP))
-		eq &= (h1->op == h2->op);
-	if (e1->flags & (1 << NFTNL_EXPR_EXTHDR_FLAGS))
-		eq &= (h1->flags == h2->flags);
-
-	return eq;
-}
-
 struct expr_ops expr_ops_exthdr = {
 	.name		= "exthdr",
 	.alloc_len	= sizeof(struct nftnl_expr_exthdr),
 	.max_attr	= NFTA_EXTHDR_MAX,
-	.cmp		= nftnl_expr_exthdr_cmp,
 	.set		= nftnl_expr_exthdr_set,
 	.get		= nftnl_expr_exthdr_get,
 	.parse		= nftnl_expr_exthdr_parse,
diff --git a/src/expr/fib.c b/src/expr/fib.c
index b922b26..2b0b077 100644
--- a/src/expr/fib.c
+++ b/src/expr/fib.c
@@ -248,28 +248,10 @@ nftnl_expr_fib_snprintf(char *buf, size_t len, uint32_t type,
 	return -1;
 }
 
-static bool nftnl_expr_fib_cmp(const struct nftnl_expr *e1,
-				const struct nftnl_expr *e2)
-{
-       struct nftnl_expr_fib *h1 = nftnl_expr_data(e1);
-       struct nftnl_expr_fib *h2 = nftnl_expr_data(e2);
-       bool eq = true;
-
-       if (e1->flags & (1 << NFTNL_EXPR_FIB_RESULT))
-               eq &= (h1->result == h2->result);
-       if (e1->flags & (1 << NFTNL_EXPR_FIB_DREG))
-               eq &= (h1->dreg == h2->dreg);
-       if (e1->flags & (1 << NFTNL_EXPR_FIB_FLAGS))
-               eq &= (h1->flags == h2->flags);
-
-       return eq;
-}
-
 struct expr_ops expr_ops_fib = {
 	.name		= "fib",
 	.alloc_len	= sizeof(struct nftnl_expr_fib),
 	.max_attr	= NFTA_FIB_MAX,
-	.cmp		= nftnl_expr_fib_cmp,
 	.set		= nftnl_expr_fib_set,
 	.get		= nftnl_expr_fib_get,
 	.parse		= nftnl_expr_fib_parse,
diff --git a/src/expr/flow_offload.c b/src/expr/flow_offload.c
index a2001c9..58fb37f 100644
--- a/src/expr/flow_offload.c
+++ b/src/expr/flow_offload.c
@@ -156,25 +156,11 @@ static void nftnl_expr_flow_free(const struct nftnl_expr *e)
 	xfree(flow->table_name);
 }
 
-static bool nftnl_expr_flow_cmp(const struct nftnl_expr *e1,
-				const struct nftnl_expr *e2)
-{
-	struct nftnl_expr_flow *l1 = nftnl_expr_data(e1);
-	struct nftnl_expr_flow *l2 = nftnl_expr_data(e2);
-	bool eq = true;
-
-	if (e1->flags & (1 << NFTNL_EXPR_FLOW_TABLE_NAME))
-		eq &= !strcmp(l1->table_name, l2->table_name);
-
-	return eq;
-}
-
 struct expr_ops expr_ops_flow = {
 	.name		= "flow_offload",
 	.alloc_len	= sizeof(struct nftnl_expr_flow),
 	.max_attr	= NFTA_FLOW_MAX,
 	.free		= nftnl_expr_flow_free,
-	.cmp		= nftnl_expr_flow_cmp,
 	.set		= nftnl_expr_flow_set,
 	.get		= nftnl_expr_flow_get,
 	.parse		= nftnl_expr_flow_parse,
diff --git a/src/expr/fwd.c b/src/expr/fwd.c
index 9021606..23fb096 100644
--- a/src/expr/fwd.c
+++ b/src/expr/fwd.c
@@ -207,28 +207,10 @@ static int nftnl_expr_fwd_snprintf(char *buf, size_t len, uint32_t type,
 	return -1;
 }
 
-static bool nftnl_expr_fwd_cmp(const struct nftnl_expr *e1,
-			       const struct nftnl_expr *e2)
-{
-	struct nftnl_expr_fwd *f1 = nftnl_expr_data(e1);
-	struct nftnl_expr_fwd *f2 = nftnl_expr_data(e2);
-	bool eq = true;
-
-	if (e1->flags & (1 << NFTNL_EXPR_FWD_SREG_DEV))
-		eq &= (f1->sreg_dev == f2->sreg_dev);
-	if (e1->flags & (1 << NFTNL_EXPR_FWD_SREG_ADDR))
-		eq &= (f1->sreg_addr == f2->sreg_addr);
-	if (e1->flags & (1 << NFTNL_EXPR_FWD_NFPROTO))
-		eq &= (f1->nfproto == f2->nfproto);
-
-	return eq;
-}
-
 struct expr_ops expr_ops_fwd = {
 	.name		= "fwd",
 	.alloc_len	= sizeof(struct nftnl_expr_fwd),
 	.max_attr	= NFTA_FWD_MAX,
-	.cmp		= nftnl_expr_fwd_cmp,
 	.set		= nftnl_expr_fwd_set,
 	.get		= nftnl_expr_fwd_get,
 	.parse		= nftnl_expr_fwd_parse,
diff --git a/src/expr/hash.c b/src/expr/hash.c
index 415537e..db65b2c 100644
--- a/src/expr/hash.c
+++ b/src/expr/hash.c
@@ -345,40 +345,10 @@ nftnl_expr_hash_snprintf(char *buf, size_t len, uint32_t type,
 	return -1;
 }
 
-static bool nftnl_expr_hash_cmp(const struct nftnl_expr *e1,
-				const struct nftnl_expr *e2)
-{
-       struct nftnl_expr_hash *h1 = nftnl_expr_data(e1);
-       struct nftnl_expr_hash *h2 = nftnl_expr_data(e2);
-       bool eq = true;
-
-       if (e1->flags & (1 << NFTNL_EXPR_HASH_SREG))
-               eq &= (h1->sreg == h2->sreg);
-       if (e1->flags & (1 << NFTNL_EXPR_HASH_DREG))
-               eq &= (h1->dreg == h2->dreg);
-       if (e1->flags & (1 << NFTNL_EXPR_HASH_LEN))
-               eq &= (h1->len == h2->len);
-       if (e1->flags & (1 << NFTNL_EXPR_HASH_MODULUS))
-               eq &= (h1->modulus == h2->modulus);
-       if (e1->flags & (1 << NFTNL_EXPR_HASH_SEED))
-               eq &= (h1->seed == h2->seed);
-	if (e1->flags & (1 << NFTNL_EXPR_HASH_OFFSET))
-		eq &= (h1->offset == h2->offset);
-	if (e1->flags & (1 << NFTNL_EXPR_HASH_TYPE))
-		eq &= (h1->type == h2->type);
-	if (e1->flags & (1 << NFTNL_EXPR_HASH_SET_NAME))
-		eq &= !strcmp(h1->map.name, h2->map.name);
-	if (e1->flags & (1 << NFTNL_EXPR_HASH_SET_ID))
-		eq &= (h1->map.id == h2->map.id);
-
-       return eq;
-}
-
 struct expr_ops expr_ops_hash = {
 	.name		= "hash",
 	.alloc_len	= sizeof(struct nftnl_expr_hash),
 	.max_attr	= NFTA_HASH_MAX,
-	.cmp		= nftnl_expr_hash_cmp,
 	.set		= nftnl_expr_hash_set,
 	.get		= nftnl_expr_hash_get,
 	.parse		= nftnl_expr_hash_parse,
diff --git a/src/expr/immediate.c b/src/expr/immediate.c
index b0570bd..dcb72a7 100644
--- a/src/expr/immediate.c
+++ b/src/expr/immediate.c
@@ -282,36 +282,11 @@ static void nftnl_expr_immediate_free(const struct nftnl_expr *e)
 		nftnl_free_verdict(&imm->data);
 }
 
-static bool nftnl_expr_immediate_cmp(const struct nftnl_expr *e1,
-				     const struct nftnl_expr *e2)
-{
-	struct nftnl_expr_immediate *i1 = nftnl_expr_data(e1);
-	struct nftnl_expr_immediate *i2 = nftnl_expr_data(e2);
-	bool eq = true;
-	int type = DATA_NONE;
-
-	if (e1->flags & (1 << NFTNL_EXPR_IMM_DREG))
-		eq &= (i1->dreg == i2->dreg);
-	if (e1->flags & (1 << NFTNL_EXPR_IMM_VERDICT))
-		if (e1->flags & (1 << NFTNL_EXPR_IMM_CHAIN))
-			type = DATA_CHAIN;
-		else
-			type = DATA_VERDICT;
-	else if (e1->flags & (1 << NFTNL_EXPR_IMM_DATA))
-		type = DATA_VALUE;
-
-	if (type != DATA_NONE)
-		eq &= nftnl_data_reg_cmp(&i1->data, &i2->data, type);
-
-	return eq;
-}
-
 struct expr_ops expr_ops_immediate = {
 	.name		= "immediate",
 	.alloc_len	= sizeof(struct nftnl_expr_immediate),
 	.max_attr	= NFTA_IMMEDIATE_MAX,
 	.free		= nftnl_expr_immediate_free,
-	.cmp		= nftnl_expr_immediate_cmp,
 	.set		= nftnl_expr_immediate_set,
 	.get		= nftnl_expr_immediate_get,
 	.parse		= nftnl_expr_immediate_parse,
diff --git a/src/expr/limit.c b/src/expr/limit.c
index 856ab18..ab177ff 100644
--- a/src/expr/limit.c
+++ b/src/expr/limit.c
@@ -255,33 +255,11 @@ nftnl_expr_limit_snprintf(char *buf, size_t len, uint32_t type,
 	return -1;
 }
 
-static bool nftnl_expr_limit_cmp(const struct nftnl_expr *e1,
-				 const struct nftnl_expr *e2)
-{
-	struct nftnl_expr_limit *l1 = nftnl_expr_data(e1);
-	struct nftnl_expr_limit *l2 = nftnl_expr_data(e2);
-	bool eq = true;
-
-	if (e1->flags & (1 << NFTNL_EXPR_LIMIT_RATE))
-		eq &= (l1->rate == l2->rate);
-	if (e1->flags & (1 << NFTNL_EXPR_LIMIT_UNIT))
-		eq &= (l1->unit == l2->unit);
-	if (e1->flags & (1 << NFTNL_EXPR_LIMIT_BURST))
-		eq &= (l1->burst == l2->burst);
-	if (e1->flags & (1 << NFTNL_EXPR_LIMIT_TYPE))
-		eq &= (l1->type == l2->type);
-	if (e1->flags & (1 << NFTNL_EXPR_LIMIT_FLAGS))
-		eq &= (l1->flags == l2->flags);
-
-	return eq;
-}
-
 struct expr_ops expr_ops_limit = {
 	.name		= "limit",
 	.alloc_len	= sizeof(struct nftnl_expr_limit),
 	.max_attr	= NFTA_LIMIT_MAX,
 	.set		= nftnl_expr_limit_set,
-	.cmp		= nftnl_expr_limit_cmp,
 	.get		= nftnl_expr_limit_get,
 	.parse		= nftnl_expr_limit_parse,
 	.build		= nftnl_expr_limit_build,
diff --git a/src/expr/log.c b/src/expr/log.c
index 86d9651..14a388f 100644
--- a/src/expr/log.c
+++ b/src/expr/log.c
@@ -320,35 +320,11 @@ static void nftnl_expr_log_free(const struct nftnl_expr *e)
 	xfree(log->prefix);
 }
 
-static bool nftnl_expr_log_cmp(const struct nftnl_expr *e1,
-				     const struct nftnl_expr *e2)
-{
-	struct nftnl_expr_log *l1 = nftnl_expr_data(e1);
-	struct nftnl_expr_log *l2 = nftnl_expr_data(e2);
-	bool eq = true;
-
-	if (e1->flags & (1 << NFTNL_EXPR_LOG_SNAPLEN))
-		eq &= (l1->snaplen == l2->snaplen);
-	if (e1->flags & (1 << NFTNL_EXPR_LOG_GROUP))
-		eq &= (l1->group == l2->group);
-	if (e1->flags & (1 << NFTNL_EXPR_LOG_QTHRESHOLD))
-		eq &= (l1->qthreshold == l2->qthreshold);
-	if (e1->flags & (1 << NFTNL_EXPR_LOG_LEVEL))
-		eq &= (l1->level == l2->level);
-	if (e1->flags & (1 << NFTNL_EXPR_LOG_FLAGS))
-		eq &= (l1->flags == l2->flags);
-	if (e1->flags & (1 << NFTNL_EXPR_LOG_PREFIX))
-		eq &= !strcmp(l1->prefix, l2->prefix);
-
-	return eq;
-}
-
 struct expr_ops expr_ops_log = {
 	.name		= "log",
 	.alloc_len	= sizeof(struct nftnl_expr_log),
 	.max_attr	= NFTA_LOG_MAX,
 	.free		= nftnl_expr_log_free,
-	.cmp		= nftnl_expr_log_cmp,
 	.set		= nftnl_expr_log_set,
 	.get		= nftnl_expr_log_get,
 	.parse		= nftnl_expr_log_parse,
diff --git a/src/expr/lookup.c b/src/expr/lookup.c
index 5fcb81f..8e721e7 100644
--- a/src/expr/lookup.c
+++ b/src/expr/lookup.c
@@ -261,33 +261,11 @@ static void nftnl_expr_lookup_free(const struct nftnl_expr *e)
 	xfree(lookup->set_name);
 }
 
-static bool nftnl_expr_lookup_cmp(const struct nftnl_expr *e1,
-				  const struct nftnl_expr *e2)
-{
-	struct nftnl_expr_lookup *l1 = nftnl_expr_data(e1);
-	struct nftnl_expr_lookup *l2 = nftnl_expr_data(e2);
-	bool eq = true;
-
-	if (e1->flags & (1 << NFTNL_EXPR_LOOKUP_SREG))
-		eq &= (l1->sreg == l2->sreg);
-	if (e1->flags & (1 << NFTNL_EXPR_LOOKUP_DREG))
-		eq &= (l1->dreg == l2->dreg);
-	if (e1->flags & (1 << NFTNL_EXPR_LOOKUP_SET))
-		eq &= !strcmp(l1->set_name, l2->set_name);
-	if (e1->flags & (1 << NFTNL_EXPR_LOOKUP_SET_ID))
-		eq &= (l1->set_id == l2->set_id);
-	if (e1->flags & (1 << NFTNL_EXPR_LOOKUP_FLAGS))
-		eq &= (l1->flags == l2->flags);
-
-	return eq;
-}
-
 struct expr_ops expr_ops_lookup = {
 	.name		= "lookup",
 	.alloc_len	= sizeof(struct nftnl_expr_lookup),
 	.max_attr	= NFTA_LOOKUP_MAX,
 	.free		= nftnl_expr_lookup_free,
-	.cmp		= nftnl_expr_lookup_cmp,
 	.set		= nftnl_expr_lookup_set,
 	.get		= nftnl_expr_lookup_get,
 	.parse		= nftnl_expr_lookup_parse,
diff --git a/src/expr/masq.c b/src/expr/masq.c
index 7c235d3..c2c9a94 100644
--- a/src/expr/masq.c
+++ b/src/expr/masq.c
@@ -202,28 +202,10 @@ static int nftnl_expr_masq_snprintf(char *buf, size_t len, uint32_t type,
 	return -1;
 }
 
-static bool nftnl_expr_masq_cmp(const struct nftnl_expr *e1,
-				const struct nftnl_expr *e2)
-{
-	struct nftnl_expr_masq *m1 = nftnl_expr_data(e1);
-	struct nftnl_expr_masq *m2 = nftnl_expr_data(e2);
-	bool eq = true;
-
-	if (e1->flags & (1 << NFTNL_EXPR_MASQ_FLAGS))
-		eq &= (m1->flags == m2->flags);
-	if (e1->flags & (1 << NFTNL_EXPR_MASQ_REG_PROTO_MIN))
-		eq &= (m1->sreg_proto_min == m2->sreg_proto_min);
-	if (e1->flags & (1 << NFTNL_EXPR_MASQ_REG_PROTO_MAX))
-		eq &= (m1->sreg_proto_max == m2->sreg_proto_max);
-
-	return eq;
-}
-
 struct expr_ops expr_ops_masq = {
 	.name		= "masq",
 	.alloc_len	= sizeof(struct nftnl_expr_masq),
 	.max_attr	= NFTA_MASQ_MAX,
-	.cmp		= nftnl_expr_masq_cmp,
 	.set		= nftnl_expr_masq_set,
 	.get		= nftnl_expr_masq_get,
 	.parse		= nftnl_expr_masq_parse,
diff --git a/src/expr/match.c b/src/expr/match.c
index dd09e1e..89732d6 100644
--- a/src/expr/match.c
+++ b/src/expr/match.c
@@ -220,31 +220,11 @@ static void nftnl_expr_match_free(const struct nftnl_expr *e)
 	xfree(match->data);
 }
 
-static bool nftnl_expr_match_cmp(const struct nftnl_expr *e1,
-				 const struct nftnl_expr *e2)
-{
-	struct nftnl_expr_match *m1 = nftnl_expr_data(e1);
-	struct nftnl_expr_match *m2 = nftnl_expr_data(e2);
-	bool eq = true;
-
-	if (e1->flags & (1 << NFTNL_EXPR_MT_NAME))
-		eq &= !strcmp(m1->name, m2->name);
-	if (e1->flags & (1 << NFTNL_EXPR_MT_REV))
-		eq &= (m1->rev == m2->rev);
-	if (e1->flags & (1 << NFTNL_EXPR_MT_INFO)) {
-		eq &= (m1->data_len == m2->data_len);
-		eq &= !memcmp(m1->data, m2->data, m1->data_len);
-	}
-
-	return eq;
-}
-
 struct expr_ops expr_ops_match = {
 	.name		= "match",
 	.alloc_len	= sizeof(struct nftnl_expr_match),
 	.max_attr	= NFTA_MATCH_MAX,
 	.free		= nftnl_expr_match_free,
-	.cmp		= nftnl_expr_match_cmp,
 	.set		= nftnl_expr_match_set,
 	.get		= nftnl_expr_match_get,
 	.parse		= nftnl_expr_match_parse,
diff --git a/src/expr/meta.c b/src/expr/meta.c
index de82105..8d697b7 100644
--- a/src/expr/meta.c
+++ b/src/expr/meta.c
@@ -265,28 +265,10 @@ nftnl_expr_meta_snprintf(char *buf, size_t len, uint32_t type,
 	return -1;
 }
 
-static bool nftnl_expr_meta_cmp(const struct nftnl_expr *e1,
-				     const struct nftnl_expr *e2)
-{
-	struct nftnl_expr_meta *m1 = nftnl_expr_data(e1);
-	struct nftnl_expr_meta *m2 = nftnl_expr_data(e2);
-	bool eq = true;
-
-	if (e1->flags & (1 << NFTNL_EXPR_META_KEY))
-		eq &= (m1->key == m2->key);
-	if (e1->flags & (1 << NFTNL_EXPR_META_DREG))
-		eq &= (m1->dreg == m2->dreg);
-	if (e1->flags & (1 << NFTNL_EXPR_META_SREG))
-		eq &= (m1->sreg == m2->sreg);
-
-	return eq;
-}
-
 struct expr_ops expr_ops_meta = {
 	.name		= "meta",
 	.alloc_len	= sizeof(struct nftnl_expr_meta),
 	.max_attr	= NFTA_META_MAX,
-	.cmp		= nftnl_expr_meta_cmp,
 	.set		= nftnl_expr_meta_set,
 	.get		= nftnl_expr_meta_get,
 	.parse		= nftnl_expr_meta_parse,
diff --git a/src/expr/nat.c b/src/expr/nat.c
index 9271303..b28734c 100644
--- a/src/expr/nat.c
+++ b/src/expr/nat.c
@@ -351,35 +351,10 @@ nftnl_expr_nat_snprintf(char *buf, size_t size, uint32_t type,
 	return -1;
 }
 
-static bool nftnl_expr_nat_cmp(const struct nftnl_expr *e1,
-			       const struct nftnl_expr *e2)
-{
-	struct nftnl_expr_nat *n1 = nftnl_expr_data(e1);
-	struct nftnl_expr_nat *n2 = nftnl_expr_data(e2);
-	bool eq = true;
-	if (e1->flags & (1 << NFTNL_EXPR_NAT_REG_ADDR_MIN))
-		eq &= (n1->sreg_addr_min == n2->sreg_addr_min);
-	if (e1->flags & (1 << NFTNL_EXPR_NAT_REG_ADDR_MAX))
-		eq &= (n1->sreg_addr_max == n2->sreg_addr_max);
-	if (e1->flags & (1 << NFTNL_EXPR_NAT_REG_PROTO_MIN))
-		eq &= (n1->sreg_proto_min == n2->sreg_proto_min);
-	if (e1->flags & (1 << NFTNL_EXPR_NAT_REG_PROTO_MAX))
-		eq &= (n1->sreg_proto_max == n2->sreg_proto_max);
-	if (e1->flags & (1 << NFTNL_EXPR_NAT_FAMILY))
-		eq &= (n1->family == n2->family);
-	if (e1->flags & (1 << NFTNL_EXPR_NAT_TYPE))
-		eq &= (n1->type == n2->type);
-	if (e1->flags & (1 << NFTNL_EXPR_NAT_FLAGS))
-		eq &= (n1->flags == n2->flags);
-
-	return eq;
-}
-
 struct expr_ops expr_ops_nat = {
 	.name		= "nat",
 	.alloc_len	= sizeof(struct nftnl_expr_nat),
 	.max_attr	= NFTA_NAT_MAX,
-	.cmp		= nftnl_expr_nat_cmp,
 	.set		= nftnl_expr_nat_set,
 	.get		= nftnl_expr_nat_get,
 	.parse		= nftnl_expr_nat_parse,
diff --git a/src/expr/numgen.c b/src/expr/numgen.c
index 5336fde..1cfb839 100644
--- a/src/expr/numgen.c
+++ b/src/expr/numgen.c
@@ -281,34 +281,10 @@ nftnl_expr_ng_snprintf(char *buf, size_t len, uint32_t type,
 	return -1;
 }
 
-static bool nftnl_expr_ng_cmp(const struct nftnl_expr *e1,
-			      const struct nftnl_expr *e2)
-{
-	struct nftnl_expr_ng *n1 = nftnl_expr_data(e1);
-	struct nftnl_expr_ng *n2 = nftnl_expr_data(e2);
-	bool eq = true;
-
-	if (e1->flags & (1 << NFTNL_EXPR_NG_DREG))
-		eq &= (n1->dreg == n2->dreg);
-	if (e1->flags & (1 << NFTNL_EXPR_NG_MODULUS))
-		eq &= (n1->modulus == n2->modulus);
-	if (e1->flags & (1 << NFTNL_EXPR_NG_TYPE))
-		eq &= (n1->type == n2->type);
-	if (e1->flags & (1 << NFTNL_EXPR_NG_OFFSET))
-		eq &= (n1->offset == n2->offset);
-	if (e1->flags & (1 << NFTNL_EXPR_NG_SET_NAME))
-		eq &= !strcmp(n1->map.name, n2->map.name);
-	if (e1->flags & (1 << NFTNL_EXPR_NG_SET_ID))
-		eq &= (n1->map.id == n2->map.id);
-
-	return eq;
-}
-
 struct expr_ops expr_ops_ng = {
 	.name		= "numgen",
 	.alloc_len	= sizeof(struct nftnl_expr_ng),
 	.max_attr	= NFTA_NG_MAX,
-	.cmp		= nftnl_expr_ng_cmp,
 	.set		= nftnl_expr_ng_set,
 	.get		= nftnl_expr_ng_get,
 	.parse		= nftnl_expr_ng_parse,
diff --git a/src/expr/objref.c b/src/expr/objref.c
index 64ee863..10ae8b8 100644
--- a/src/expr/objref.c
+++ b/src/expr/objref.c
@@ -248,32 +248,10 @@ static int nftnl_expr_objref_snprintf(char *buf, size_t len, uint32_t type,
 	return -1;
 }
 
-static bool nftnl_expr_objref_cmp(const struct nftnl_expr *e1,
-				   const struct nftnl_expr *e2)
-{
-	struct nftnl_expr_objref *c1 = nftnl_expr_data(e1);
-	struct nftnl_expr_objref *c2 = nftnl_expr_data(e2);
-	bool eq = true;
-
-	if (e1->flags & (1 << NFTNL_EXPR_OBJREF_IMM_TYPE))
-		eq &= (c1->imm.type == c2->imm.type);
-	if (e1->flags & (1 << NFTNL_EXPR_OBJREF_IMM_NAME))
-		eq &= !strcmp(c1->imm.name, c2->imm.name);
-	if (e1->flags & (1 << NFTNL_EXPR_OBJREF_SET_SREG))
-		eq &= (c1->set.sreg == c2->set.sreg);
-	if (e1->flags & (1 << NFTNL_EXPR_OBJREF_SET_NAME))
-		eq &= !strcmp(c1->set.name, c2->set.name);
-	if (e1->flags & (1 << NFTNL_EXPR_OBJREF_SET_ID))
-		eq &= (c1->set.id == c2->set.id);
-
-	return eq;
-}
-
 struct expr_ops expr_ops_objref = {
 	.name		= "objref",
 	.alloc_len	= sizeof(struct nftnl_expr_objref),
 	.max_attr	= NFTA_OBJREF_MAX,
-	.cmp		= nftnl_expr_objref_cmp,
 	.set		= nftnl_expr_objref_set,
 	.get		= nftnl_expr_objref_get,
 	.parse		= nftnl_expr_objref_parse,
diff --git a/src/expr/payload.c b/src/expr/payload.c
index 91e1587..d9866d1 100644
--- a/src/expr/payload.c
+++ b/src/expr/payload.c
@@ -312,38 +312,10 @@ nftnl_expr_payload_snprintf(char *buf, size_t len, uint32_t type,
 	return -1;
 }
 
-static bool nftnl_expr_payload_cmp(const struct nftnl_expr *e1,
-				   const struct nftnl_expr *e2)
-{
-	struct nftnl_expr_payload *p1 = nftnl_expr_data(e1);
-	struct nftnl_expr_payload *p2 = nftnl_expr_data(e2);
-	bool eq = true;
-
-	if (e1->flags & (1 << NFTNL_EXPR_PAYLOAD_SREG))
-		eq &= (p1->sreg == p2->sreg);
-	if (e1->flags & (1 << NFTNL_EXPR_PAYLOAD_DREG))
-		eq &= (p1->dreg == p2->dreg);
-	if (e1->flags & (1 << NFTNL_EXPR_PAYLOAD_BASE))
-		eq &= (p1->base == p2->base);
-	if (e1->flags & (1 << NFTNL_EXPR_PAYLOAD_OFFSET))
-		eq &= (p1->offset == p2->offset);
-	if (e1->flags & (1 << NFTNL_EXPR_PAYLOAD_LEN))
-		eq &= (p1->len == p2->len);
-	if (e1->flags & (1 << NFTNL_EXPR_PAYLOAD_CSUM_TYPE))
-		eq &= (p1->csum_type == p2->csum_type);
-	if (e1->flags & (1 << NFTNL_EXPR_PAYLOAD_CSUM_OFFSET))
-		eq &= (p1->csum_offset == p2->csum_offset);
-	if (e1->flags & (1 << NFTNL_EXPR_PAYLOAD_FLAGS))
-		eq &= (p1->csum_flags == p2->csum_flags);
-
-	return eq;
-}
-
 struct expr_ops expr_ops_payload = {
 	.name		= "payload",
 	.alloc_len	= sizeof(struct nftnl_expr_payload),
 	.max_attr	= NFTA_PAYLOAD_MAX,
-	.cmp		= nftnl_expr_payload_cmp,
 	.set		= nftnl_expr_payload_set,
 	.get		= nftnl_expr_payload_get,
 	.parse		= nftnl_expr_payload_parse,
diff --git a/src/expr/queue.c b/src/expr/queue.c
index a392a27..c832c58 100644
--- a/src/expr/queue.c
+++ b/src/expr/queue.c
@@ -247,30 +247,10 @@ nftnl_expr_queue_snprintf(char *buf, size_t len, uint32_t type,
 	return -1;
 }
 
-static bool nftnl_expr_queue_cmp(const struct nftnl_expr *e1,
-			    const struct nftnl_expr *e2)
-{
-	struct nftnl_expr_queue *q1 = nftnl_expr_data(e1);
-	struct nftnl_expr_queue *q2 = nftnl_expr_data(e2);
-	bool eq = true;
-
-	if (e1->flags & (1 << NFTNL_EXPR_QUEUE_NUM))
-		eq &= (q1->queuenum == q2->queuenum);
-	if (e1->flags & (1 << NFTNL_EXPR_QUEUE_TOTAL))
-		eq &= (q1->queues_total == q2->queues_total);
-	if (e1->flags & (1 << NFTNL_EXPR_QUEUE_FLAGS))
-		eq &= (q1->flags == q2->flags);
-	if (e1->flags & (1 << NFTNL_EXPR_QUEUE_SREG_QNUM))
-		eq &= (q1->sreg_qnum == q2->sreg_qnum);
-
-	return eq;
-}
-
 struct expr_ops expr_ops_queue = {
 	.name		= "queue",
 	.alloc_len	= sizeof(struct nftnl_expr_queue),
 	.max_attr	= NFTA_QUEUE_MAX,
-	.cmp		= nftnl_expr_queue_cmp,
 	.set		= nftnl_expr_queue_set,
 	.get		= nftnl_expr_queue_get,
 	.parse		= nftnl_expr_queue_parse,
diff --git a/src/expr/redir.c b/src/expr/redir.c
index b2aa345..9ebee2f 100644
--- a/src/expr/redir.c
+++ b/src/expr/redir.c
@@ -216,28 +216,10 @@ nftnl_expr_redir_snprintf(char *buf, size_t len, uint32_t type,
 	return -1;
 }
 
-static bool nftnl_expr_redir_cmp(const struct nftnl_expr *e1,
-				 const struct nftnl_expr *e2)
-{
-	struct nftnl_expr_redir *r1 = nftnl_expr_data(e1);
-	struct nftnl_expr_redir *r2 = nftnl_expr_data(e2);
-	bool eq = true;
-
-	if (e1->flags & (1 << NFTNL_EXPR_REDIR_REG_PROTO_MIN))
-		eq &= (r1->sreg_proto_min== r2->sreg_proto_min);
-	if (e1->flags & (1 << NFTNL_EXPR_REDIR_REG_PROTO_MAX))
-		eq &= (r1->sreg_proto_max== r2->sreg_proto_max);
-	if (e1->flags & (1 << NFTNL_EXPR_REDIR_FLAGS))
-		eq &= (r1->flags== r2->flags);
-
-	return eq;
-}
-
 struct expr_ops expr_ops_redir = {
 	.name		= "redir",
 	.alloc_len	= sizeof(struct nftnl_expr_redir),
 	.max_attr	= NFTA_REDIR_MAX,
-	.cmp		= nftnl_expr_redir_cmp,
 	.set		= nftnl_expr_redir_set,
 	.get		= nftnl_expr_redir_get,
 	.parse		= nftnl_expr_redir_parse,
diff --git a/src/expr/reject.c b/src/expr/reject.c
index 11d8b20..ac9f189 100644
--- a/src/expr/reject.c
+++ b/src/expr/reject.c
@@ -176,26 +176,10 @@ nftnl_expr_reject_snprintf(char *buf, size_t len, uint32_t type,
 	return -1;
 }
 
-static bool nftnl_expr_reject_cmp(const struct nftnl_expr *e1,
-				  const struct nftnl_expr *e2)
-{
-	struct nftnl_expr_reject *r1 = nftnl_expr_data(e1);
-	struct nftnl_expr_reject *r2 = nftnl_expr_data(e2);
-	bool eq = true;
-
-	if (e1->flags & (1 << NFTNL_EXPR_REJECT_TYPE))
-		eq &= (r1->type == r2->type);
-	if (e1->flags & (1 << NFTNL_EXPR_REJECT_CODE))
-		eq &= (r1->icmp_code == r2->icmp_code);
-
-	return eq;
-}
-
 struct expr_ops expr_ops_reject = {
 	.name		= "reject",
 	.alloc_len	= sizeof(struct nftnl_expr_reject),
 	.max_attr	= NFTA_REJECT_MAX,
-	.cmp		= nftnl_expr_reject_cmp,
 	.set		= nftnl_expr_reject_set,
 	.get		= nftnl_expr_reject_get,
 	.parse		= nftnl_expr_reject_parse,
diff --git a/src/expr/rt.c b/src/expr/rt.c
index c3c92c7..a077c30 100644
--- a/src/expr/rt.c
+++ b/src/expr/rt.c
@@ -211,26 +211,10 @@ nftnl_expr_rt_snprintf(char *buf, size_t len, uint32_t type,
 	return -1;
 }
 
-static bool nftnl_expr_rt_cmp(const struct nftnl_expr *e1,
-			      const struct nftnl_expr *e2)
-{
-	struct nftnl_expr_rt *r1 = nftnl_expr_data(e1);
-	struct nftnl_expr_rt *r2 = nftnl_expr_data(e2);
-	bool eq = true;
-
-	if (e1->flags & (1 << NFTNL_EXPR_RT_KEY))
-		eq &= (r1->key == r2->key);
-	if (e1->flags & (1 << NFTNL_EXPR_RT_DREG))
-		eq &= (r1->dreg == r2->dreg);
-
-	return eq;
-}
-
 struct expr_ops expr_ops_rt = {
 	.name		= "rt",
 	.alloc_len	= sizeof(struct nftnl_expr_rt),
 	.max_attr	= NFTA_RT_MAX,
-	.cmp		= nftnl_expr_rt_cmp,
 	.set		= nftnl_expr_rt_set,
 	.get		= nftnl_expr_rt_get,
 	.parse		= nftnl_expr_rt_parse,
diff --git a/src/expr/socket.c b/src/expr/socket.c
index db160a1..cdd6863 100644
--- a/src/expr/socket.c
+++ b/src/expr/socket.c
@@ -180,26 +180,10 @@ nftnl_expr_socket_snprintf(char *buf, size_t len, uint32_t type,
 	return -1;
 }
 
-static bool nftnl_expr_socket_cmp(const struct nftnl_expr *e1,
-			      const struct nftnl_expr *e2)
-{
-	struct nftnl_expr_socket *r1 = nftnl_expr_data(e1);
-	struct nftnl_expr_socket *r2 = nftnl_expr_data(e2);
-	bool eq = true;
-
-	if (e1->flags & (1 << NFTNL_EXPR_SOCKET_KEY))
-		eq &= (r1->key == r2->key);
-	if (e1->flags & (1 << NFTNL_EXPR_SOCKET_DREG))
-		eq &= (r1->dreg == r2->dreg);
-
-	return eq;
-}
-
 struct expr_ops expr_ops_socket = {
 	.name		= "socket",
 	.alloc_len	= sizeof(struct nftnl_expr_socket),
 	.max_attr	= NFTA_SOCKET_MAX,
-	.cmp		= nftnl_expr_socket_cmp,
 	.set		= nftnl_expr_socket_set,
 	.get		= nftnl_expr_socket_get,
 	.parse		= nftnl_expr_socket_parse,
diff --git a/src/expr/target.c b/src/expr/target.c
index ed4bf7d..246158b 100644
--- a/src/expr/target.c
+++ b/src/expr/target.c
@@ -220,31 +220,11 @@ static void nftnl_expr_target_free(const struct nftnl_expr *e)
 	xfree(target->data);
 }
 
-static bool nftnl_expr_target_cmp(const struct nftnl_expr *e1,
-				  const struct nftnl_expr *e2)
-{
-	struct nftnl_expr_target *t1 = nftnl_expr_data(e1);
-	struct nftnl_expr_target *t2 = nftnl_expr_data(e2);
-	bool eq = true;
-
-	if (e1->flags & (1 << NFTNL_EXPR_TG_NAME))
-		eq &= !strcmp(t1->name, t2->name);
-	if (e1->flags & (1 << NFTNL_EXPR_TG_REV))
-		eq &= (t1->rev == t2->rev);
-	if (e1->flags & (1 << NFTNL_EXPR_TG_INFO)) {
-		eq &= (t1->data_len == t2->data_len);
-		eq &= !memcmp(t1->data, t2->data, t1->data_len);
-	}
-
-	return eq;
-}
-
 struct expr_ops expr_ops_target = {
 	.name		= "target",
 	.alloc_len	= sizeof(struct nftnl_expr_target),
 	.max_attr	= NFTA_TARGET_MAX,
 	.free		= nftnl_expr_target_free,
-	.cmp		= nftnl_expr_target_cmp,
 	.set		= nftnl_expr_target_set,
 	.get		= nftnl_expr_target_get,
 	.parse		= nftnl_expr_target_parse,
diff --git a/src/libnftnl.map b/src/libnftnl.map
index 0d6b20c..89414f2 100644
--- a/src/libnftnl.map
+++ b/src/libnftnl.map
@@ -1,4 +1,4 @@
-LIBNFTNL_5 {
+LIBNFTNL_11 {
 global:
   nftnl_table_alloc;
   nftnl_table_free;
@@ -271,9 +271,6 @@ global:
   nftnl_udata_next;
   nftnl_udata_parse;
 
-  nftnl_rule_cmp;
-  nftnl_expr_cmp;
-
   nftnl_obj_alloc;
   nftnl_obj_free;
   nftnl_obj_is_set;
@@ -307,14 +304,8 @@ global:
   nftnl_obj_list_iter_next;
   nftnl_obj_list_iter_destroy;
 
-local: *;
-};
-
-LIBNFTNL_6 {
   nftnl_expr_fprintf;
-} LIBNFTNL_5;
 
-LIBNFTNL_7 {
   nftnl_flowtable_alloc;
   nftnl_flowtable_free;
   nftnl_flowtable_is_set;
@@ -341,8 +332,7 @@ LIBNFTNL_7 {
   nftnl_flowtable_list_del;
   nftnl_flowtable_list_foreach;
 
-} LIBNFTNL_6;
-
-LIBNFTNL_8 {
   nftnl_rule_list_insert_at;
-} LIBNFTNL_7;
+
+local: *;
+};
diff --git a/src/rule.c b/src/rule.c
index 146b06c..2c70420 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -913,37 +913,6 @@ void nftnl_expr_iter_destroy(struct nftnl_expr_iter *iter)
 	xfree(iter);
 }
 
-EXPORT_SYMBOL(nftnl_rule_cmp);
-bool nftnl_rule_cmp(const struct nftnl_rule *r1, const struct nftnl_rule *r2)
-{
-	struct nftnl_expr_iter it1, it2;
-	struct nftnl_expr *e1, *e2;
-	unsigned int eq = 1;
-
-	if (r1->flags & r1->flags & (1 << NFTNL_RULE_TABLE))
-		eq &= !strcmp(r1->table, r2->table);
-	if (r1->flags & r1->flags & (1 << NFTNL_RULE_CHAIN))
-		eq &= !strcmp(r1->chain, r2->chain);
-	if (r1->flags & r1->flags & (1 << NFTNL_RULE_COMPAT_FLAGS))
-		eq &= (r1->compat.flags == r2->compat.flags);
-	if (r1->flags & r1->flags & (1 << NFTNL_RULE_COMPAT_PROTO))
-		eq &= (r1->compat.proto == r2->compat.proto);
-
-	nftnl_expr_iter_init(r1, &it1);
-	nftnl_expr_iter_init(r2, &it2);
-	e1 = nftnl_expr_iter_next(&it1);
-	e2 = nftnl_expr_iter_next(&it2);
-	while (eq && e1 && e2) {
-		eq = nftnl_expr_cmp(e1, e2);
-
-		e1 = nftnl_expr_iter_next(&it1);
-		e2 = nftnl_expr_iter_next(&it2);
-	}
-	eq &= (!e1 && !e2);
-
-	return eq;
-}
-
 struct nftnl_rule_list {
 	struct list_head list;
 };
-- 
1.8.3.1