All of lore.kernel.org
 help / color / mirror / Atom feed
* [iptables PATCH v2 1/2] nft: Optimize class-based IP prefix matches
@ 2020-10-30 13:24 Phil Sutter
  2020-10-30 13:24 ` [iptables PATCH 2/2] ebtables: Optimize masked MAC address matches Phil Sutter
  2020-11-04 13:05 ` [iptables PATCH v2 1/2] nft: Optimize class-based IP prefix matches Pablo Neira Ayuso
  0 siblings, 2 replies; 4+ messages in thread
From: Phil Sutter @ 2020-10-30 13:24 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

Payload expression works on byte-boundaries, leverage this with suitable
prefix lengths.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
Changes since v1:
- Fix prefix printing in arptables, it uses add_addr() as well.
---
 iptables/nft-arp.c    | 11 ++++++++---
 iptables/nft-ipv4.c   |  6 ++++--
 iptables/nft-ipv6.c   |  6 ++++--
 iptables/nft-shared.c | 14 ++++++++++----
 iptables/nft-shared.h |  4 ++++
 5 files changed, 30 insertions(+), 11 deletions(-)

diff --git a/iptables/nft-arp.c b/iptables/nft-arp.c
index 67f4529d93652..952f0c6916e59 100644
--- a/iptables/nft-arp.c
+++ b/iptables/nft-arp.c
@@ -303,7 +303,8 @@ static bool nft_arp_parse_devaddr(struct nft_xt_ctx *ctx,
 		memcpy(info->mask, ctx->bitwise.mask, ETH_ALEN);
 		ctx->flags &= ~NFT_XT_CTX_BITWISE;
 	} else {
-		memset(info->mask, 0xff, ETH_ALEN);
+		memset(info->mask, 0xff,
+		       min(ctx->payload.len, ETH_ALEN));
 	}
 
 	return inv;
@@ -360,7 +361,9 @@ static void nft_arp_parse_payload(struct nft_xt_ctx *ctx,
 				parse_mask_ipv4(ctx, &fw->arp.smsk);
 				ctx->flags &= ~NFT_XT_CTX_BITWISE;
 			} else {
-				fw->arp.smsk.s_addr = 0xffffffff;
+				memset(&fw->arp.smsk, 0xff,
+				       min(ctx->payload.len,
+					   sizeof(struct in_addr)));
 			}
 
 			if (inv)
@@ -380,7 +383,9 @@ static void nft_arp_parse_payload(struct nft_xt_ctx *ctx,
 				parse_mask_ipv4(ctx, &fw->arp.tmsk);
 				ctx->flags &= ~NFT_XT_CTX_BITWISE;
 			} else {
-				fw->arp.tmsk.s_addr = 0xffffffff;
+				memset(&fw->arp.tmsk, 0xff,
+				       min(ctx->payload.len,
+					   sizeof(struct in_addr)));
 			}
 
 			if (inv)
diff --git a/iptables/nft-ipv4.c b/iptables/nft-ipv4.c
index afdecf9711e64..ce702041af0f4 100644
--- a/iptables/nft-ipv4.c
+++ b/iptables/nft-ipv4.c
@@ -199,7 +199,8 @@ static void nft_ipv4_parse_payload(struct nft_xt_ctx *ctx,
 			parse_mask_ipv4(ctx, &cs->fw.ip.smsk);
 			ctx->flags &= ~NFT_XT_CTX_BITWISE;
 		} else {
-			cs->fw.ip.smsk.s_addr = 0xffffffff;
+			memset(&cs->fw.ip.smsk, 0xff,
+			       min(ctx->payload.len, sizeof(struct in_addr)));
 		}
 
 		if (inv)
@@ -212,7 +213,8 @@ static void nft_ipv4_parse_payload(struct nft_xt_ctx *ctx,
 			parse_mask_ipv4(ctx, &cs->fw.ip.dmsk);
 			ctx->flags &= ~NFT_XT_CTX_BITWISE;
 		} else {
-			cs->fw.ip.dmsk.s_addr = 0xffffffff;
+			memset(&cs->fw.ip.dmsk, 0xff,
+			       min(ctx->payload.len, sizeof(struct in_addr)));
 		}
 
 		if (inv)
diff --git a/iptables/nft-ipv6.c b/iptables/nft-ipv6.c
index 4008b7eab4f2a..c877ec6d10887 100644
--- a/iptables/nft-ipv6.c
+++ b/iptables/nft-ipv6.c
@@ -146,7 +146,8 @@ static void nft_ipv6_parse_payload(struct nft_xt_ctx *ctx,
 			parse_mask_ipv6(ctx, &cs->fw6.ipv6.smsk);
 			ctx->flags &= ~NFT_XT_CTX_BITWISE;
 		} else {
-			memset(&cs->fw6.ipv6.smsk, 0xff, sizeof(struct in6_addr));
+			memset(&cs->fw6.ipv6.smsk, 0xff,
+			       min(ctx->payload.len, sizeof(struct in6_addr)));
 		}
 
 		if (inv)
@@ -159,7 +160,8 @@ static void nft_ipv6_parse_payload(struct nft_xt_ctx *ctx,
 			parse_mask_ipv6(ctx, &cs->fw6.ipv6.dmsk);
 			ctx->flags &= ~NFT_XT_CTX_BITWISE;
 		} else {
-			memset(&cs->fw6.ipv6.dmsk, 0xff, sizeof(struct in6_addr));
+			memset(&cs->fw6.ipv6.dmsk, 0xff,
+			       min(ctx->payload.len, sizeof(struct in6_addr)));
 		}
 
 		if (inv)
diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c
index 7741d23befc5a..545e9c60fa015 100644
--- a/iptables/nft-shared.c
+++ b/iptables/nft-shared.c
@@ -166,16 +166,22 @@ void add_addr(struct nftnl_rule *r, int offset,
 	      void *data, void *mask, size_t len, uint32_t op)
 {
 	const unsigned char *m = mask;
+	bool bitwise = false;
 	int i;
 
-	add_payload(r, offset, len, NFT_PAYLOAD_NETWORK_HEADER);
-
 	for (i = 0; i < len; i++) {
-		if (m[i] != 0xff)
+		if (m[i] != 0xff) {
+			bitwise = m[i] != 0;
 			break;
+		}
 	}
 
-	if (i != len)
+	if (!bitwise)
+		len = i;
+
+	add_payload(r, offset, len, NFT_PAYLOAD_NETWORK_HEADER);
+
+	if (bitwise)
 		add_bitwise(r, mask, len);
 
 	add_cmp_ptr(r, op, data, len);
diff --git a/iptables/nft-shared.h b/iptables/nft-shared.h
index 4440fd17bfeac..a52463342b30a 100644
--- a/iptables/nft-shared.h
+++ b/iptables/nft-shared.h
@@ -247,4 +247,8 @@ void xtables_restore_parse(struct nft_handle *h,
 			   const struct nft_xt_restore_parse *p);
 
 void nft_check_xt_legacy(int family, bool is_ipt_save);
+
+#define min(x, y) ((x) < (y) ? (x) : (y))
+#define max(x, y) ((x) > (y) ? (x) : (y))
+
 #endif
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [iptables PATCH 2/2] ebtables: Optimize masked MAC address matches
  2020-10-30 13:24 [iptables PATCH v2 1/2] nft: Optimize class-based IP prefix matches Phil Sutter
@ 2020-10-30 13:24 ` Phil Sutter
  2020-11-04 13:05   ` Pablo Neira Ayuso
  2020-11-04 13:05 ` [iptables PATCH v2 1/2] nft: Optimize class-based IP prefix matches Pablo Neira Ayuso
  1 sibling, 1 reply; 4+ messages in thread
From: Phil Sutter @ 2020-10-30 13:24 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

Just like with class-based prefix matches in iptables-nft, optimize
masked MAC address matches if the mask is on a byte-boundary.

To reuse the logic in add_addr(), extend it to accept the payload base
value via parameter.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 iptables/nft-arp.c    | 12 ++++++++----
 iptables/nft-bridge.c | 22 ++++++++++------------
 iptables/nft-ipv4.c   |  6 ++++--
 iptables/nft-ipv6.c   |  6 ++++--
 iptables/nft-shared.c |  5 ++---
 iptables/nft-shared.h |  3 ++-
 6 files changed, 30 insertions(+), 24 deletions(-)

diff --git a/iptables/nft-arp.c b/iptables/nft-arp.c
index 952f0c6916e59..5dc38da831aa0 100644
--- a/iptables/nft-arp.c
+++ b/iptables/nft-arp.c
@@ -178,7 +178,8 @@ static int nft_arp_add(struct nft_handle *h, struct nftnl_rule *r, void *data)
 
 	if (need_devaddr(&fw->arp.src_devaddr)) {
 		op = nft_invflags2cmp(fw->arp.invflags, ARPT_INV_SRCDEVADDR);
-		add_addr(r, sizeof(struct arphdr),
+		add_addr(r, NFT_PAYLOAD_NETWORK_HEADER,
+			 sizeof(struct arphdr),
 			 &fw->arp.src_devaddr.addr,
 			 &fw->arp.src_devaddr.mask,
 			 fw->arp.arhln, op);
@@ -189,7 +190,8 @@ static int nft_arp_add(struct nft_handle *h, struct nftnl_rule *r, void *data)
 	    fw->arp.smsk.s_addr != 0 ||
 	    fw->arp.invflags & ARPT_INV_SRCIP) {
 		op = nft_invflags2cmp(fw->arp.invflags, ARPT_INV_SRCIP);
-		add_addr(r, sizeof(struct arphdr) + fw->arp.arhln,
+		add_addr(r, NFT_PAYLOAD_NETWORK_HEADER,
+			 sizeof(struct arphdr) + fw->arp.arhln,
 			 &fw->arp.src.s_addr, &fw->arp.smsk.s_addr,
 			 sizeof(struct in_addr), op);
 	}
@@ -197,7 +199,8 @@ static int nft_arp_add(struct nft_handle *h, struct nftnl_rule *r, void *data)
 
 	if (need_devaddr(&fw->arp.tgt_devaddr)) {
 		op = nft_invflags2cmp(fw->arp.invflags, ARPT_INV_TGTDEVADDR);
-		add_addr(r, sizeof(struct arphdr) + fw->arp.arhln + sizeof(struct in_addr),
+		add_addr(r, NFT_PAYLOAD_NETWORK_HEADER,
+			 sizeof(struct arphdr) + fw->arp.arhln + sizeof(struct in_addr),
 			 &fw->arp.tgt_devaddr.addr,
 			 &fw->arp.tgt_devaddr.mask,
 			 fw->arp.arhln, op);
@@ -207,7 +210,8 @@ static int nft_arp_add(struct nft_handle *h, struct nftnl_rule *r, void *data)
 	    fw->arp.tmsk.s_addr != 0 ||
 	    fw->arp.invflags & ARPT_INV_TGTIP) {
 		op = nft_invflags2cmp(fw->arp.invflags, ARPT_INV_TGTIP);
-		add_addr(r, sizeof(struct arphdr) + fw->arp.arhln + sizeof(struct in_addr) + fw->arp.arhln,
+		add_addr(r, NFT_PAYLOAD_NETWORK_HEADER,
+			 sizeof(struct arphdr) + fw->arp.arhln + sizeof(struct in_addr) + fw->arp.arhln,
 			 &fw->arp.tgt.s_addr, &fw->arp.tmsk.s_addr,
 			 sizeof(struct in_addr), op);
 	}
diff --git a/iptables/nft-bridge.c b/iptables/nft-bridge.c
index dbf11eb5e1fa8..c1a2c209cc1aa 100644
--- a/iptables/nft-bridge.c
+++ b/iptables/nft-bridge.c
@@ -159,20 +159,16 @@ static int nft_bridge_add(struct nft_handle *h,
 
 	if (fw->bitmask & EBT_ISOURCE) {
 		op = nft_invflags2cmp(fw->invflags, EBT_ISOURCE);
-		add_payload(r, offsetof(struct ethhdr, h_source), 6,
-			    NFT_PAYLOAD_LL_HEADER);
-		if (!mac_all_ones(fw->sourcemsk))
-			add_bitwise(r, fw->sourcemsk, 6);
-		add_cmp_ptr(r, op, fw->sourcemac, 6);
+		add_addr(r, NFT_PAYLOAD_LL_HEADER,
+			 offsetof(struct ethhdr, h_source),
+			 fw->sourcemac, fw->sourcemsk, ETH_ALEN, op);
 	}
 
 	if (fw->bitmask & EBT_IDEST) {
 		op = nft_invflags2cmp(fw->invflags, EBT_IDEST);
-		add_payload(r, offsetof(struct ethhdr, h_dest), 6,
-			    NFT_PAYLOAD_LL_HEADER);
-		if (!mac_all_ones(fw->destmsk))
-			add_bitwise(r, fw->destmsk, 6);
-		add_cmp_ptr(r, op, fw->destmac, 6);
+		add_addr(r, NFT_PAYLOAD_LL_HEADER,
+			 offsetof(struct ethhdr, h_dest),
+			 fw->destmac, fw->destmsk, ETH_ALEN, op);
 	}
 
 	if ((fw->bitmask & EBT_NOPROTO) == 0) {
@@ -258,7 +254,8 @@ static void nft_bridge_parse_payload(struct nft_xt_ctx *ctx,
                         memcpy(fw->destmsk, ctx->bitwise.mask, ETH_ALEN);
                         ctx->flags &= ~NFT_XT_CTX_BITWISE;
                 } else {
-                        memset(&fw->destmsk, 0xff, ETH_ALEN);
+			memset(&fw->destmsk, 0xff,
+			       min(ctx->payload.len, ETH_ALEN));
                 }
 		fw->bitmask |= EBT_IDEST;
 		break;
@@ -272,7 +269,8 @@ static void nft_bridge_parse_payload(struct nft_xt_ctx *ctx,
                         memcpy(fw->sourcemsk, ctx->bitwise.mask, ETH_ALEN);
                         ctx->flags &= ~NFT_XT_CTX_BITWISE;
                 } else {
-                        memset(&fw->sourcemsk, 0xff, ETH_ALEN);
+			memset(&fw->sourcemsk, 0xff,
+			       min(ctx->payload.len, ETH_ALEN));
                 }
 		fw->bitmask |= EBT_ISOURCE;
 		break;
diff --git a/iptables/nft-ipv4.c b/iptables/nft-ipv4.c
index ce702041af0f4..fdc15c6f04066 100644
--- a/iptables/nft-ipv4.c
+++ b/iptables/nft-ipv4.c
@@ -50,13 +50,15 @@ static int nft_ipv4_add(struct nft_handle *h, struct nftnl_rule *r, void *data)
 
 	if (cs->fw.ip.src.s_addr || cs->fw.ip.smsk.s_addr || cs->fw.ip.invflags & IPT_INV_SRCIP) {
 		op = nft_invflags2cmp(cs->fw.ip.invflags, IPT_INV_SRCIP);
-		add_addr(r, offsetof(struct iphdr, saddr),
+		add_addr(r, NFT_PAYLOAD_NETWORK_HEADER,
+			 offsetof(struct iphdr, saddr),
 			 &cs->fw.ip.src.s_addr, &cs->fw.ip.smsk.s_addr,
 			 sizeof(struct in_addr), op);
 	}
 	if (cs->fw.ip.dst.s_addr || cs->fw.ip.dmsk.s_addr || cs->fw.ip.invflags & IPT_INV_DSTIP) {
 		op = nft_invflags2cmp(cs->fw.ip.invflags, IPT_INV_DSTIP);
-		add_addr(r, offsetof(struct iphdr, daddr),
+		add_addr(r, NFT_PAYLOAD_NETWORK_HEADER,
+			 offsetof(struct iphdr, daddr),
 			 &cs->fw.ip.dst.s_addr, &cs->fw.ip.dmsk.s_addr,
 			 sizeof(struct in_addr), op);
 	}
diff --git a/iptables/nft-ipv6.c b/iptables/nft-ipv6.c
index c877ec6d10887..130ad3e6e7c44 100644
--- a/iptables/nft-ipv6.c
+++ b/iptables/nft-ipv6.c
@@ -51,7 +51,8 @@ static int nft_ipv6_add(struct nft_handle *h, struct nftnl_rule *r, void *data)
 	    !IN6_IS_ADDR_UNSPECIFIED(&cs->fw6.ipv6.smsk) ||
 	    (cs->fw6.ipv6.invflags & IPT_INV_SRCIP)) {
 		op = nft_invflags2cmp(cs->fw6.ipv6.invflags, IPT_INV_SRCIP);
-		add_addr(r, offsetof(struct ip6_hdr, ip6_src),
+		add_addr(r, NFT_PAYLOAD_NETWORK_HEADER,
+			 offsetof(struct ip6_hdr, ip6_src),
 			 &cs->fw6.ipv6.src, &cs->fw6.ipv6.smsk,
 			 sizeof(struct in6_addr), op);
 	}
@@ -59,7 +60,8 @@ static int nft_ipv6_add(struct nft_handle *h, struct nftnl_rule *r, void *data)
 	    !IN6_IS_ADDR_UNSPECIFIED(&cs->fw6.ipv6.dmsk) ||
 	    (cs->fw6.ipv6.invflags & IPT_INV_DSTIP)) {
 		op = nft_invflags2cmp(cs->fw6.ipv6.invflags, IPT_INV_DSTIP);
-		add_addr(r, offsetof(struct ip6_hdr, ip6_dst),
+		add_addr(r, NFT_PAYLOAD_NETWORK_HEADER,
+			 offsetof(struct ip6_hdr, ip6_dst),
 			 &cs->fw6.ipv6.dst, &cs->fw6.ipv6.dmsk,
 			 sizeof(struct in6_addr), op);
 	}
diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c
index 545e9c60fa015..10553ab26823b 100644
--- a/iptables/nft-shared.c
+++ b/iptables/nft-shared.c
@@ -20,7 +20,6 @@
 
 #include <xtables.h>
 
-#include <linux/netfilter/nf_tables.h>
 #include <linux/netfilter/xt_comment.h>
 #include <linux/netfilter/xt_limit.h>
 
@@ -162,7 +161,7 @@ void add_outiface(struct nftnl_rule *r, char *iface, uint32_t op)
 		add_cmp_ptr(r, op, iface, iface_len + 1);
 }
 
-void add_addr(struct nftnl_rule *r, int offset,
+void add_addr(struct nftnl_rule *r, enum nft_payload_bases base, int offset,
 	      void *data, void *mask, size_t len, uint32_t op)
 {
 	const unsigned char *m = mask;
@@ -179,7 +178,7 @@ void add_addr(struct nftnl_rule *r, int offset,
 	if (!bitwise)
 		len = i;
 
-	add_payload(r, offset, len, NFT_PAYLOAD_NETWORK_HEADER);
+	add_payload(r, offset, len, base);
 
 	if (bitwise)
 		add_bitwise(r, mask, len);
diff --git a/iptables/nft-shared.h b/iptables/nft-shared.h
index a52463342b30a..da4ba9d2ba8de 100644
--- a/iptables/nft-shared.h
+++ b/iptables/nft-shared.h
@@ -8,6 +8,7 @@
 #include <libnftnl/chain.h>
 
 #include <linux/netfilter_arp/arp_tables.h>
+#include <linux/netfilter/nf_tables.h>
 
 #include "xshared.h"
 
@@ -121,7 +122,7 @@ void add_cmp_u16(struct nftnl_rule *r, uint16_t val, uint32_t op);
 void add_cmp_u32(struct nftnl_rule *r, uint32_t val, uint32_t op);
 void add_iniface(struct nftnl_rule *r, char *iface, uint32_t op);
 void add_outiface(struct nftnl_rule *r, char *iface, uint32_t op);
-void add_addr(struct nftnl_rule *r, int offset,
+void add_addr(struct nftnl_rule *r, enum nft_payload_bases base, int offset,
 	      void *data, void *mask, size_t len, uint32_t op);
 void add_proto(struct nftnl_rule *r, int offset, size_t len,
 	       uint8_t proto, uint32_t op);
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [iptables PATCH v2 1/2] nft: Optimize class-based IP prefix matches
  2020-10-30 13:24 [iptables PATCH v2 1/2] nft: Optimize class-based IP prefix matches Phil Sutter
  2020-10-30 13:24 ` [iptables PATCH 2/2] ebtables: Optimize masked MAC address matches Phil Sutter
@ 2020-11-04 13:05 ` Pablo Neira Ayuso
  1 sibling, 0 replies; 4+ messages in thread
From: Pablo Neira Ayuso @ 2020-11-04 13:05 UTC (permalink / raw)
  To: Phil Sutter; +Cc: netfilter-devel

On Fri, Oct 30, 2020 at 02:24:48PM +0100, Phil Sutter wrote:
> Payload expression works on byte-boundaries, leverage this with suitable
> prefix lengths.

LGTM, thanks.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [iptables PATCH 2/2] ebtables: Optimize masked MAC address matches
  2020-10-30 13:24 ` [iptables PATCH 2/2] ebtables: Optimize masked MAC address matches Phil Sutter
@ 2020-11-04 13:05   ` Pablo Neira Ayuso
  0 siblings, 0 replies; 4+ messages in thread
From: Pablo Neira Ayuso @ 2020-11-04 13:05 UTC (permalink / raw)
  To: Phil Sutter; +Cc: netfilter-devel

On Fri, Oct 30, 2020 at 02:24:49PM +0100, Phil Sutter wrote:
> Just like with class-based prefix matches in iptables-nft, optimize
> masked MAC address matches if the mask is on a byte-boundary.
> 
> To reuse the logic in add_addr(), extend it to accept the payload base
> value via parameter.

This also looks fine, thanks.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2020-11-04 13:05 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-10-30 13:24 [iptables PATCH v2 1/2] nft: Optimize class-based IP prefix matches Phil Sutter
2020-10-30 13:24 ` [iptables PATCH 2/2] ebtables: Optimize masked MAC address matches Phil Sutter
2020-11-04 13:05   ` Pablo Neira Ayuso
2020-11-04 13:05 ` [iptables PATCH v2 1/2] nft: Optimize class-based IP prefix matches Pablo Neira Ayuso

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.