From: Felix Fietkau Subject: kernel: add a new version of my netfilter speedup patches for linux 2.6.39 and 3.0 Signed-off-by: Felix Fietkau --- include/uapi/linux/netfilter_ipv4/ip_tables.h | 1 + net/ipv4/netfilter/ip_tables.c | 37 +++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/include/uapi/linux/netfilter_ipv4/ip_tables.h b/include/uapi/linux/netfilter_ipv4/ip_tables.h index d0da53d96d93..f279daa13c0f 100644 --- a/include/uapi/linux/netfilter_ipv4/ip_tables.h +++ b/include/uapi/linux/netfilter_ipv4/ip_tables.h @@ -88,6 +88,7 @@ struct ipt_ip { #define IPT_F_FRAG 0x01 /* Set if rule is a fragment rule */ #define IPT_F_GOTO 0x02 /* Set if jump is a goto */ #define IPT_F_MASK 0x03 /* All possible flag bits mask. */ +#define IPT_F_NO_DEF_MATCH 0x80 /* Internal: no default match rules present */ /* Values for "inv" field in struct ipt_ip. */ #define IPT_INV_VIA_IN 0x01 /* Invert the sense of IN IFACE. */ diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 7c00ce90adb8..d919350a0e8b 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -58,6 +58,9 @@ ip_packet_match(const struct iphdr *ip, { unsigned long ret; + if (ipinfo->flags & IPT_F_NO_DEF_MATCH) + return true; + if (NF_INVF(ipinfo, IPT_INV_SRCIP, (ip->saddr & ipinfo->smsk.s_addr) != ipinfo->src.s_addr) || NF_INVF(ipinfo, IPT_INV_DSTIP, @@ -88,6 +91,29 @@ ip_packet_match(const struct iphdr *ip, return true; } +static void +ip_checkdefault(struct ipt_ip *ip) +{ + static const char iface_mask[IFNAMSIZ] = {}; + + if (ip->invflags || ip->flags & IPT_F_FRAG) + return; + + if (memcmp(ip->iniface_mask, iface_mask, IFNAMSIZ) != 0) + return; + + if (memcmp(ip->outiface_mask, iface_mask, IFNAMSIZ) != 0) + return; + + if (ip->smsk.s_addr || ip->dmsk.s_addr) + return; + + if (ip->proto) + return; + + ip->flags |= IPT_F_NO_DEF_MATCH; +} + static bool ip_checkentry(const struct ipt_ip *ip) { @@ -545,6 +571,8 @@ find_check_entry(struct ipt_entry *e, struct net *net, const char *name, struct xt_entry_match *ematch; unsigned long pcnt; + ip_checkdefault(&e->ip); + pcnt = xt_percpu_counter_alloc(); if (IS_ERR_VALUE(pcnt)) return -ENOMEM; @@ -824,6 +852,7 @@ copy_entries_to_user(unsigned int total_size, const struct xt_table_info *private = table->private; int ret = 0; const void *loc_cpu_entry; + u8 flags; counters = alloc_counters(table); if (IS_ERR(counters)) @@ -851,6 +880,14 @@ copy_entries_to_user(unsigned int total_size, goto free_counters; } + flags = e->ip.flags & IPT_F_MASK; + if (copy_to_user(userptr + off + + offsetof(struct ipt_entry, ip.flags), + &flags, sizeof(flags)) != 0) { + ret = -EFAULT; + goto free_counters; + } + for (i = sizeof(struct ipt_entry); i < e->target_offset; i += m->u.match_size) { -- 2.11.0