From 2d5f5170998c77a476445bc889a7dca2dd294aa1 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 19 Feb 2004 22:52:20 -0800 Subject: [PATCH] [NETFILTER]: Resync with 2.4.x - Update listhelp.h to benefit from prefetching - More efficient selective_cleanup() impl. in conntrack - Export number of conntrack buckets via r/o sysctl. --- include/linux/netfilter_ipv4/listhelp.h | 54 +++++++++----------- include/linux/sysctl.h | 1 + net/ipv4/netfilter/ip_conntrack_core.c | 11 ++-- net/ipv4/netfilter/ip_conntrack_standalone.c | 9 ++++ 4 files changed, 39 insertions(+), 36 deletions(-) diff --git a/include/linux/netfilter_ipv4/listhelp.h b/include/linux/netfilter_ipv4/listhelp.h index f19f448889d16..f2ae7c5e57bb7 100644 --- a/include/linux/netfilter_ipv4/listhelp.h +++ b/include/linux/netfilter_ipv4/listhelp.h @@ -11,48 +11,42 @@ required to allow inlining of cmpfn. */ #define LIST_FIND(head, cmpfn, type, args...) \ ({ \ - const struct list_head *__i = (head); \ + const struct list_head *__i, *__j = NULL; \ \ ASSERT_READ_LOCK(head); \ - do { \ - __i = __i->next; \ - if (__i == (head)) { \ - __i = NULL; \ + list_for_each(__i, (head)) \ + if (cmpfn((const type)__i , ## args)) { \ + __j = __i; \ break; \ } \ - } while (!cmpfn((const type)__i , ## args)); \ - (type)__i; \ + (type)__j; \ }) -#define LIST_FIND_W(head, cmpfn, type, args...) \ -({ \ - const struct list_head *__i = (head); \ - \ - ASSERT_WRITE_LOCK(head); \ - do { \ - __i = __i->next; \ - if (__i == (head)) { \ - __i = NULL; \ - break; \ - } \ - } while (!cmpfn((type)__i , ## args)); \ - (type)__i; \ +#define LIST_FIND_W(head, cmpfn, type, args...) \ +({ \ + const struct list_head *__i, *__j = NULL; \ + \ + ASSERT_WRITE_LOCK(head); \ + list_for_each(__i, (head)) \ + if (cmpfn((type)__i , ## args)) { \ + __j = __i; \ + break; \ + } \ + (type)__j; \ }) /* Just like LIST_FIND but we search backwards */ #define LIST_FIND_B(head, cmpfn, type, args...) \ ({ \ - const struct list_head *__i = (head); \ + const struct list_head *__i, *__j = NULL; \ \ ASSERT_READ_LOCK(head); \ - do { \ - __i = __i->prev; \ - if (__i == (head)) { \ - __i = NULL; \ + list_for_each_prev(__i, (head)) \ + if (cmpfn((const type)__i , ## args)) { \ + __j = __i; \ break; \ } \ - } while (!cmpfn((const type)__i , ## args)); \ - (type)__i; \ + (type)__j; \ }) static inline int @@ -100,9 +94,9 @@ list_prepend(struct list_head *head, void *new) do { \ struct list_head *__i; \ ASSERT_WRITE_LOCK(head); \ - for (__i = (head)->next; \ - !cmpfn((new), (typeof (new))__i) && __i != (head); \ - __i = __i->next); \ + list_for_each(__i, (head)) \ + if ((new), (typeof (new))__i) \ + break; \ list_add((struct list_head *)(new), __i->prev); \ } while(0) diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index b192b7f018f56..f800e292d8a1b 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -382,6 +382,7 @@ enum NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT_STREAM=11, NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT=12, NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT=13, + NET_IPV4_NF_CONNTRACK_BUCKETS=14, }; /* /proc/sys/net/ipv6 */ diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c index f38a2dccdbe73..1a62ec122d7e3 100644 --- a/net/ipv4/netfilter/ip_conntrack_core.c +++ b/net/ipv4/netfilter/ip_conntrack_core.c @@ -1240,14 +1240,13 @@ do_kill(const struct ip_conntrack_tuple_hash *i, /* Bring out ya dead! */ static struct ip_conntrack_tuple_hash * get_next_corpse(int (*kill)(const struct ip_conntrack *i, void *data), - void *data) + void *data, unsigned int *bucket) { struct ip_conntrack_tuple_hash *h = NULL; - unsigned int i; READ_LOCK(&ip_conntrack_lock); - for (i = 0; !h && i < ip_conntrack_htable_size; i++) { - h = LIST_FIND(&ip_conntrack_hash[i], do_kill, + for (; !h && *bucket < ip_conntrack_htable_size; (*bucket)++) { + h = LIST_FIND(&ip_conntrack_hash[*bucket], do_kill, struct ip_conntrack_tuple_hash *, kill, data); } if (h) @@ -1262,9 +1261,9 @@ ip_ct_selective_cleanup(int (*kill)(const struct ip_conntrack *i, void *data), void *data) { struct ip_conntrack_tuple_hash *h; + unsigned int bucket = 0; - /* This is order n^2, by the way. */ - while ((h = get_next_corpse(kill, data)) != NULL) { + while ((h = get_next_corpse(kill, data, &bucket)) != NULL) { /* Time to push up daises... */ if (del_timer(&h->ctrack->timeout)) death_by_timeout((unsigned long)h->ctrack); diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c index ca317bfe19353..f6ec2134531e5 100644 --- a/net/ipv4/netfilter/ip_conntrack_standalone.c +++ b/net/ipv4/netfilter/ip_conntrack_standalone.c @@ -275,6 +275,7 @@ static struct nf_hook_ops ip_conntrack_local_in_ops = { /* From ip_conntrack_core.c */ extern int ip_conntrack_max; +extern unsigned int ip_conntrack_htable_size; /* From ip_conntrack_proto_tcp.c */ extern unsigned long ip_ct_tcp_timeout_syn_sent; @@ -307,6 +308,14 @@ static ctl_table ip_ct_sysctl_table[] = { .mode = 0644, .proc_handler = &proc_dointvec, }, + { + .ctl_name = NET_IPV4_NF_CONNTRACK_BUCKETS, + .procname = "ip_conntrack_buckets", + .data = &ip_conntrack_htable_size, + .maxlen = sizeof(unsigned int), + .mode = 0444, + .proc_handler = &proc_dointvec, + }, { .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT, .procname = "ip_conntrack_tcp_timeout_syn_sent", -- 2.53.0