Merge "net: ipv6: Optimize ipv6 packet matching"

This commit is contained in:
Linux Build Service Account 2017-04-20 04:40:57 -07:00 committed by Gerrit - the friendly Code Review server
commit 815709b5cd
2 changed files with 29 additions and 13 deletions

View file

@ -135,6 +135,18 @@ config IP6_NF_IPTABLES
if IP6_NF_IPTABLES
config IP6_NF_IPTABLES_128
tristate "128 bit arithmetic for iptables matching"
depends on IP6_NF_IPTABLES
help
This enables 128 bit matching in ip6tables to help optimize cases
where there is no match required. ip6tables matching for ipv6 always
has a mask if an address is specified for match. Adding a check for
mask prior to that helps to improve performance as it avoids the
masked comparison.
Note that this feature depends on the architecture. If unsure, say N.
# The simple matches.
config IP6_NF_MATCH_AH
tristate '"ah" match support'

View file

@ -94,22 +94,26 @@ ip6_packet_match(const struct sk_buff *skb,
{
unsigned long ret;
const struct ipv6hdr *ipv6 = ipv6_hdr(skb);
#if IS_ENABLED(IP6_NF_IPTABLES_128)
const __uint128_t *ulm1 = (const __uint128_t *)&ip6info->smsk;
const __uint128_t *ulm2 = (const __uint128_t *)&ip6info->dmsk;
#endif
#define FWINV(bool, invflg) ((bool) ^ !!(ip6info->invflags & (invflg)))
if (FWINV(ipv6_masked_addr_cmp(&ipv6->saddr, &ip6info->smsk,
&ip6info->src), IP6T_INV_SRCIP) ||
FWINV(ipv6_masked_addr_cmp(&ipv6->daddr, &ip6info->dmsk,
&ip6info->dst), IP6T_INV_DSTIP)) {
dprintf("Source or dest mismatch.\n");
/*
dprintf("SRC: %u. Mask: %u. Target: %u.%s\n", ip->saddr,
ipinfo->smsk.s_addr, ipinfo->src.s_addr,
ipinfo->invflags & IP6T_INV_SRCIP ? " (INV)" : "");
dprintf("DST: %u. Mask: %u. Target: %u.%s\n", ip->daddr,
ipinfo->dmsk.s_addr, ipinfo->dst.s_addr,
ipinfo->invflags & IP6T_INV_DSTIP ? " (INV)" : "");*/
return false;
#if IS_ENABLED(IP6_NF_IPTABLES_128)
if (*ulm1 || *ulm2)
#endif
{
if (FWINV(ipv6_masked_addr_cmp
(&ipv6->saddr, &ip6info->smsk, &ip6info->src),
IP6T_INV_SRCIP) ||
FWINV(ipv6_masked_addr_cmp(&ipv6->daddr, &ip6info->dmsk,
&ip6info->dst),
IP6T_INV_DSTIP)) {
dprintf("Source or dest mismatch.\n");
return false;
}
}
ret = ifname_compare_aligned(indev, ip6info->iniface, ip6info->iniface_mask);