You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
150 lines
4.5 KiB
150 lines
4.5 KiB
From a48e8c5a7433c8f7d0f28ed321081b25f3b63a4a Mon Sep 17 00:00:00 2001
|
|
From: Phil Sutter <phil@nwl.cc>
|
|
Date: Fri, 2 Oct 2020 09:44:38 +0200
|
|
Subject: [PATCH] nft: Optimize class-based IP prefix matches
|
|
|
|
Payload expression works on byte-boundaries, leverage this with suitable
|
|
prefix lengths.
|
|
|
|
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
|
(cherry picked from commit 323259001d617ae359430a03ee3d3e7f107684e0)
|
|
---
|
|
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 94437ffe7990c..811fb9a1ebe76 100644
|
|
--- a/iptables/nft-shared.h
|
|
+++ b/iptables/nft-shared.h
|
|
@@ -246,4 +246,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.40.0
|
|
|