Blame SOURCES/0033-ebtables-Optimize-masked-MAC-address-matches.patch

9c35a8
From 03a484b63c5a61678555bcaca68fa36dc81468c1 Mon Sep 17 00:00:00 2001
9c35a8
From: Phil Sutter <phil@nwl.cc>
9c35a8
Date: Fri, 30 Oct 2020 14:08:33 +0100
9c35a8
Subject: [PATCH] ebtables: Optimize masked MAC address matches
9c35a8
9c35a8
Just like with class-based prefix matches in iptables-nft, optimize
9c35a8
masked MAC address matches if the mask is on a byte-boundary.
9c35a8
9c35a8
To reuse the logic in add_addr(), extend it to accept the payload base
9c35a8
value via parameter.
9c35a8
9c35a8
Signed-off-by: Phil Sutter <phil@nwl.cc>
9c35a8
(cherry picked from commit 274cb05edc58d6fa982a34c84b2f4cf6acc3e335)
9c35a8
Signed-off-by: Phil Sutter <psutter@redhat.com>
9c35a8
---
9c35a8
 iptables/nft-arp.c    | 12 ++++++++----
9c35a8
 iptables/nft-bridge.c | 22 ++++++++++------------
9c35a8
 iptables/nft-ipv4.c   |  6 ++++--
9c35a8
 iptables/nft-ipv6.c   |  6 ++++--
9c35a8
 iptables/nft-shared.c |  5 ++---
9c35a8
 iptables/nft-shared.h |  3 ++-
9c35a8
 6 files changed, 30 insertions(+), 24 deletions(-)
9c35a8
9c35a8
diff --git a/iptables/nft-arp.c b/iptables/nft-arp.c
9c35a8
index ac400e484a4fa..776b55949472b 100644
9c35a8
--- a/iptables/nft-arp.c
9c35a8
+++ b/iptables/nft-arp.c
9c35a8
@@ -178,7 +178,8 @@ static int nft_arp_add(struct nft_handle *h, struct nftnl_rule *r, void *data)
9c35a8
 
9c35a8
 	if (need_devaddr(&fw->arp.src_devaddr)) {
9c35a8
 		op = nft_invflags2cmp(fw->arp.invflags, ARPT_INV_SRCDEVADDR);
9c35a8
-		add_addr(r, sizeof(struct arphdr),
9c35a8
+		add_addr(r, NFT_PAYLOAD_NETWORK_HEADER,
9c35a8
+			 sizeof(struct arphdr),
9c35a8
 			 &fw->arp.src_devaddr.addr,
9c35a8
 			 &fw->arp.src_devaddr.mask,
9c35a8
 			 fw->arp.arhln, op);
9c35a8
@@ -189,7 +190,8 @@ static int nft_arp_add(struct nft_handle *h, struct nftnl_rule *r, void *data)
9c35a8
 	    fw->arp.smsk.s_addr != 0 ||
9c35a8
 	    fw->arp.invflags & ARPT_INV_SRCIP) {
9c35a8
 		op = nft_invflags2cmp(fw->arp.invflags, ARPT_INV_SRCIP);
9c35a8
-		add_addr(r, sizeof(struct arphdr) + fw->arp.arhln,
9c35a8
+		add_addr(r, NFT_PAYLOAD_NETWORK_HEADER,
9c35a8
+			 sizeof(struct arphdr) + fw->arp.arhln,
9c35a8
 			 &fw->arp.src.s_addr, &fw->arp.smsk.s_addr,
9c35a8
 			 sizeof(struct in_addr), op);
9c35a8
 	}
9c35a8
@@ -197,7 +199,8 @@ static int nft_arp_add(struct nft_handle *h, struct nftnl_rule *r, void *data)
9c35a8
 
9c35a8
 	if (need_devaddr(&fw->arp.tgt_devaddr)) {
9c35a8
 		op = nft_invflags2cmp(fw->arp.invflags, ARPT_INV_TGTDEVADDR);
9c35a8
-		add_addr(r, sizeof(struct arphdr) + fw->arp.arhln + sizeof(struct in_addr),
9c35a8
+		add_addr(r, NFT_PAYLOAD_NETWORK_HEADER,
9c35a8
+			 sizeof(struct arphdr) + fw->arp.arhln + sizeof(struct in_addr),
9c35a8
 			 &fw->arp.tgt_devaddr.addr,
9c35a8
 			 &fw->arp.tgt_devaddr.mask,
9c35a8
 			 fw->arp.arhln, op);
9c35a8
@@ -207,7 +210,8 @@ static int nft_arp_add(struct nft_handle *h, struct nftnl_rule *r, void *data)
9c35a8
 	    fw->arp.tmsk.s_addr != 0 ||
9c35a8
 	    fw->arp.invflags & ARPT_INV_TGTIP) {
9c35a8
 		op = nft_invflags2cmp(fw->arp.invflags, ARPT_INV_TGTIP);
9c35a8
-		add_addr(r, sizeof(struct arphdr) + fw->arp.arhln + sizeof(struct in_addr) + fw->arp.arhln,
9c35a8
+		add_addr(r, NFT_PAYLOAD_NETWORK_HEADER,
9c35a8
+			 sizeof(struct arphdr) + fw->arp.arhln + sizeof(struct in_addr) + fw->arp.arhln,
9c35a8
 			 &fw->arp.tgt.s_addr, &fw->arp.tmsk.s_addr,
9c35a8
 			 sizeof(struct in_addr), op);
9c35a8
 	}
9c35a8
diff --git a/iptables/nft-bridge.c b/iptables/nft-bridge.c
9c35a8
index 3f85cbbf5e4cf..2aa15e2d1e69d 100644
9c35a8
--- a/iptables/nft-bridge.c
9c35a8
+++ b/iptables/nft-bridge.c
9c35a8
@@ -159,20 +159,16 @@ static int nft_bridge_add(struct nft_handle *h,
9c35a8
 
9c35a8
 	if (fw->bitmask & EBT_ISOURCE) {
9c35a8
 		op = nft_invflags2cmp(fw->invflags, EBT_ISOURCE);
9c35a8
-		add_payload(r, offsetof(struct ethhdr, h_source), 6,
9c35a8
-			    NFT_PAYLOAD_LL_HEADER);
9c35a8
-		if (!mac_all_ones(fw->sourcemsk))
9c35a8
-			add_bitwise(r, fw->sourcemsk, 6);
9c35a8
-		add_cmp_ptr(r, op, fw->sourcemac, 6);
9c35a8
+		add_addr(r, NFT_PAYLOAD_LL_HEADER,
9c35a8
+			 offsetof(struct ethhdr, h_source),
9c35a8
+			 fw->sourcemac, fw->sourcemsk, ETH_ALEN, op);
9c35a8
 	}
9c35a8
 
9c35a8
 	if (fw->bitmask & EBT_IDEST) {
9c35a8
 		op = nft_invflags2cmp(fw->invflags, EBT_IDEST);
9c35a8
-		add_payload(r, offsetof(struct ethhdr, h_dest), 6,
9c35a8
-			    NFT_PAYLOAD_LL_HEADER);
9c35a8
-		if (!mac_all_ones(fw->destmsk))
9c35a8
-			add_bitwise(r, fw->destmsk, 6);
9c35a8
-		add_cmp_ptr(r, op, fw->destmac, 6);
9c35a8
+		add_addr(r, NFT_PAYLOAD_LL_HEADER,
9c35a8
+			 offsetof(struct ethhdr, h_dest),
9c35a8
+			 fw->destmac, fw->destmsk, ETH_ALEN, op);
9c35a8
 	}
9c35a8
 
9c35a8
 	if ((fw->bitmask & EBT_NOPROTO) == 0) {
9c35a8
@@ -258,7 +254,8 @@ static void nft_bridge_parse_payload(struct nft_xt_ctx *ctx,
9c35a8
                         memcpy(fw->destmsk, ctx->bitwise.mask, ETH_ALEN);
9c35a8
                         ctx->flags &= ~NFT_XT_CTX_BITWISE;
9c35a8
                 } else {
9c35a8
-                        memset(&fw->destmsk, 0xff, ETH_ALEN);
9c35a8
+			memset(&fw->destmsk, 0xff,
9c35a8
+			       min(ctx->payload.len, ETH_ALEN));
9c35a8
                 }
9c35a8
 		fw->bitmask |= EBT_IDEST;
9c35a8
 		break;
9c35a8
@@ -272,7 +269,8 @@ static void nft_bridge_parse_payload(struct nft_xt_ctx *ctx,
9c35a8
                         memcpy(fw->sourcemsk, ctx->bitwise.mask, ETH_ALEN);
9c35a8
                         ctx->flags &= ~NFT_XT_CTX_BITWISE;
9c35a8
                 } else {
9c35a8
-                        memset(&fw->sourcemsk, 0xff, ETH_ALEN);
9c35a8
+			memset(&fw->sourcemsk, 0xff,
9c35a8
+			       min(ctx->payload.len, ETH_ALEN));
9c35a8
                 }
9c35a8
 		fw->bitmask |= EBT_ISOURCE;
9c35a8
 		break;
9c35a8
diff --git a/iptables/nft-ipv4.c b/iptables/nft-ipv4.c
9c35a8
index c84af2df90da7..5bd0710781533 100644
9c35a8
--- a/iptables/nft-ipv4.c
9c35a8
+++ b/iptables/nft-ipv4.c
9c35a8
@@ -50,13 +50,15 @@ static int nft_ipv4_add(struct nft_handle *h, struct nftnl_rule *r, void *data)
9c35a8
 
9c35a8
 	if (cs->fw.ip.src.s_addr || cs->fw.ip.smsk.s_addr || cs->fw.ip.invflags & IPT_INV_SRCIP) {
9c35a8
 		op = nft_invflags2cmp(cs->fw.ip.invflags, IPT_INV_SRCIP);
9c35a8
-		add_addr(r, offsetof(struct iphdr, saddr),
9c35a8
+		add_addr(r, NFT_PAYLOAD_NETWORK_HEADER,
9c35a8
+			 offsetof(struct iphdr, saddr),
9c35a8
 			 &cs->fw.ip.src.s_addr, &cs->fw.ip.smsk.s_addr,
9c35a8
 			 sizeof(struct in_addr), op);
9c35a8
 	}
9c35a8
 	if (cs->fw.ip.dst.s_addr || cs->fw.ip.dmsk.s_addr || cs->fw.ip.invflags & IPT_INV_DSTIP) {
9c35a8
 		op = nft_invflags2cmp(cs->fw.ip.invflags, IPT_INV_DSTIP);
9c35a8
-		add_addr(r, offsetof(struct iphdr, daddr),
9c35a8
+		add_addr(r, NFT_PAYLOAD_NETWORK_HEADER,
9c35a8
+			 offsetof(struct iphdr, daddr),
9c35a8
 			 &cs->fw.ip.dst.s_addr, &cs->fw.ip.dmsk.s_addr,
9c35a8
 			 sizeof(struct in_addr), op);
9c35a8
 	}
9c35a8
diff --git a/iptables/nft-ipv6.c b/iptables/nft-ipv6.c
9c35a8
index cfced245a781c..6ece631d85f59 100644
9c35a8
--- a/iptables/nft-ipv6.c
9c35a8
+++ b/iptables/nft-ipv6.c
9c35a8
@@ -51,7 +51,8 @@ static int nft_ipv6_add(struct nft_handle *h, struct nftnl_rule *r, void *data)
9c35a8
 	    !IN6_IS_ADDR_UNSPECIFIED(&cs->fw6.ipv6.smsk) ||
9c35a8
 	    (cs->fw6.ipv6.invflags & IPT_INV_SRCIP)) {
9c35a8
 		op = nft_invflags2cmp(cs->fw6.ipv6.invflags, IPT_INV_SRCIP);
9c35a8
-		add_addr(r, offsetof(struct ip6_hdr, ip6_src),
9c35a8
+		add_addr(r, NFT_PAYLOAD_NETWORK_HEADER,
9c35a8
+			 offsetof(struct ip6_hdr, ip6_src),
9c35a8
 			 &cs->fw6.ipv6.src, &cs->fw6.ipv6.smsk,
9c35a8
 			 sizeof(struct in6_addr), op);
9c35a8
 	}
9c35a8
@@ -59,7 +60,8 @@ static int nft_ipv6_add(struct nft_handle *h, struct nftnl_rule *r, void *data)
9c35a8
 	    !IN6_IS_ADDR_UNSPECIFIED(&cs->fw6.ipv6.dmsk) ||
9c35a8
 	    (cs->fw6.ipv6.invflags & IPT_INV_DSTIP)) {
9c35a8
 		op = nft_invflags2cmp(cs->fw6.ipv6.invflags, IPT_INV_DSTIP);
9c35a8
-		add_addr(r, offsetof(struct ip6_hdr, ip6_dst),
9c35a8
+		add_addr(r, NFT_PAYLOAD_NETWORK_HEADER,
9c35a8
+			 offsetof(struct ip6_hdr, ip6_dst),
9c35a8
 			 &cs->fw6.ipv6.dst, &cs->fw6.ipv6.dmsk,
9c35a8
 			 sizeof(struct in6_addr), op);
9c35a8
 	}
9c35a8
diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c
9c35a8
index b1237049d0a34..2aae0a3a49dfe 100644
9c35a8
--- a/iptables/nft-shared.c
9c35a8
+++ b/iptables/nft-shared.c
9c35a8
@@ -20,7 +20,6 @@
9c35a8
 
9c35a8
 #include <xtables.h>
9c35a8
 
9c35a8
-#include <linux/netfilter/nf_tables.h>
9c35a8
 #include <linux/netfilter/xt_comment.h>
9c35a8
 #include <linux/netfilter/xt_limit.h>
9c35a8
 
9c35a8
@@ -162,7 +161,7 @@ void add_outiface(struct nftnl_rule *r, char *iface, uint32_t op)
9c35a8
 		add_cmp_ptr(r, op, iface, iface_len + 1);
9c35a8
 }
9c35a8
 
9c35a8
-void add_addr(struct nftnl_rule *r, int offset,
9c35a8
+void add_addr(struct nftnl_rule *r, enum nft_payload_bases base, int offset,
9c35a8
 	      void *data, void *mask, size_t len, uint32_t op)
9c35a8
 {
9c35a8
 	const unsigned char *m = mask;
9c35a8
@@ -179,7 +178,7 @@ void add_addr(struct nftnl_rule *r, int offset,
9c35a8
 	if (!bitwise)
9c35a8
 		len = i;
9c35a8
 
9c35a8
-	add_payload(r, offset, len, NFT_PAYLOAD_NETWORK_HEADER);
9c35a8
+	add_payload(r, offset, len, base);
9c35a8
 
9c35a8
 	if (bitwise)
9c35a8
 		add_bitwise(r, mask, len);
9c35a8
diff --git a/iptables/nft-shared.h b/iptables/nft-shared.h
9c35a8
index c7f1e366b75ee..520a296fb530c 100644
9c35a8
--- a/iptables/nft-shared.h
9c35a8
+++ b/iptables/nft-shared.h
9c35a8
@@ -8,6 +8,7 @@
9c35a8
 #include <libnftnl/chain.h>
9c35a8
 
9c35a8
 #include <linux/netfilter_arp/arp_tables.h>
9c35a8
+#include <linux/netfilter/nf_tables.h>
9c35a8
 
9c35a8
 #include "xshared.h"
9c35a8
 
9c35a8
@@ -124,7 +125,7 @@ void add_cmp_u16(struct nftnl_rule *r, uint16_t val, uint32_t op);
9c35a8
 void add_cmp_u32(struct nftnl_rule *r, uint32_t val, uint32_t op);
9c35a8
 void add_iniface(struct nftnl_rule *r, char *iface, uint32_t op);
9c35a8
 void add_outiface(struct nftnl_rule *r, char *iface, uint32_t op);
9c35a8
-void add_addr(struct nftnl_rule *r, int offset,
9c35a8
+void add_addr(struct nftnl_rule *r, enum nft_payload_bases base, int offset,
9c35a8
 	      void *data, void *mask, size_t len, uint32_t op);
9c35a8
 void add_proto(struct nftnl_rule *r, int offset, size_t len,
9c35a8
 	       uint8_t proto, uint32_t op);
9c35a8
-- 
9c35a8
2.28.0
9c35a8