]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
ebtables: Optimize masked MAC address matches
authorPhil Sutter <phil@nwl.cc>
Fri, 30 Oct 2020 13:08:33 +0000 (14:08 +0100)
committerPhil Sutter <phil@nwl.cc>
Wed, 4 Nov 2020 14:39:23 +0000 (15:39 +0100)
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
iptables/nft-bridge.c
iptables/nft-ipv4.c
iptables/nft-ipv6.c
iptables/nft-shared.c
iptables/nft-shared.h

index 952f0c6916e59008d70ad493ea31d1c33667a2e1..5dc38da831aa0becd3011b0f3f70ab88aee33d0b 100644 (file)
@@ -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);
        }
index dbf11eb5e1fa8a4974fc87d3e8c814abf9c5905f..c1a2c209cc1aa2b62c767c8104f0f10fb2737e94 100644 (file)
@@ -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;
index ce702041af0f41bb1c80039940c4098e61ae11d9..fdc15c6f04066c9400f609510fd96e1a97c63ddc 100644 (file)
@@ -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);
        }
index c877ec6d108877acef6cbf11134b92bf55d0c879..130ad3e6e7c44a0a957cb9d89b95fa41ef04f231 100644 (file)
@@ -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);
        }
index 545e9c60fa015ce9911aa55e3e0d468120b92982..10553ab26823b301c3d82bd42ea050f45df3d1f1 100644 (file)
@@ -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);
index a52463342b30a31d13533b9b5b21a4f416486ac2..da4ba9d2ba8de91496c703d5967fb02fb2b0bafc 100644 (file)
@@ -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);