diff options
| author | liamjfoy <liamjfoy@NetBSD.org> | 2007-03-25 20:12:20 +0000 |
|---|---|---|
| committer | liamjfoy <liamjfoy@NetBSD.org> | 2007-03-25 20:12:20 +0000 |
| commit | b8ef59d7201f80296b46ea45ee3847e1fc2092eb (patch) | |
| tree | fc5ec2363a4d564d07505bbff1bd1ade94051856 /sys | |
| parent | cbd0d608fc5194b427224cf6eccaa064bf951f26 (diff) | |
Add net.inet.ip.hashsize to control the IPv4 fast forward hash table size.
Diffstat (limited to 'sys')
| -rw-r--r-- | sys/netinet/ip_flow.c | 44 | ||||
| -rw-r--r-- | sys/netinet/ip_input.c | 42 | ||||
| -rw-r--r-- | sys/netinet/ip_var.h | 7 |
3 files changed, 76 insertions, 17 deletions
diff --git a/sys/netinet/ip_flow.c b/sys/netinet/ip_flow.c index 2ba8cac3254..25f08aed192 100644 --- a/sys/netinet/ip_flow.c +++ b/sys/netinet/ip_flow.c @@ -1,4 +1,4 @@ -/* $NetBSD: ip_flow.c,v 1.42 2007/03/12 18:18:35 ad Exp $ */ +/* $NetBSD: ip_flow.c,v 1.43 2007/03/25 20:12:20 liamjfoy Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ip_flow.c,v 1.42 2007/03/12 18:18:35 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ip_flow.c,v 1.43 2007/03/25 20:12:20 liamjfoy Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -72,9 +72,9 @@ POOL_INIT(ipflow_pool, sizeof(struct ipflow), 0, 0, 0, "ipflowpl", NULL, LIST_HEAD(ipflowhead, ipflow); #define IPFLOW_TIMER (5 * PR_SLOWHZ) -#define IPFLOW_HASHSIZE (1 << IPFLOW_HASHBITS) +#define IPFLOW_DEFAULT_HASHSIZE (1 << IPFLOW_HASHBITS) -static struct ipflowhead ipflowtable[IPFLOW_HASHSIZE]; +static struct ipflowhead *ipflowtable = NULL; static struct ipflowhead ipflowlist; static int ipflow_inuse; @@ -94,6 +94,7 @@ do { \ #define IPFLOW_MAX 256 #endif int ip_maxflows = IPFLOW_MAX; +int ip_hashsize = IPFLOW_DEFAULT_HASHSIZE; static unsigned ipflow_hash(struct in_addr dst, struct in_addr src, unsigned tos) @@ -102,7 +103,7 @@ ipflow_hash(struct in_addr dst, struct in_addr src, unsigned tos) int idx; for (idx = 0; idx < 32; idx += IPFLOW_HASHBITS) hash += (dst.s_addr >> (32 - idx)) + (src.s_addr >> idx); - return hash & (IPFLOW_HASHSIZE-1); + return hash & (ip_hashsize-1); } static struct ipflow * @@ -122,14 +123,29 @@ ipflow_lookup(const struct ip *ip) return ipf; } -void -ipflow_init(void) +int +ipflow_init(int table_size) { + struct ipflowhead *new_table; int i; + new_table = (struct ipflowhead *)malloc(sizeof(struct ipflowhead) * + table_size, M_RTABLE, M_NOWAIT); + + if (new_table == NULL) + return 1; + + if (ipflowtable != NULL) + free(ipflowtable, M_RTABLE); + + ipflowtable = new_table; + ip_hashsize = table_size; + LIST_INIT(&ipflowlist); - for (i = 0; i < IPFLOW_HASHSIZE; i++) + for (i = 0; i < ip_hashsize; i++) LIST_INIT(&ipflowtable[i]); + + return 0; } int @@ -428,16 +444,22 @@ ipflow_create(const struct route *ro, struct mbuf *m) splx(s); } -void -ipflow_invalidate_all(void) +int +ipflow_invalidate_all(int new_size) { struct ipflow *ipf, *next_ipf; - int s; + int s, error; + error = 0; s = splnet(); for (ipf = LIST_FIRST(&ipflowlist); ipf != NULL; ipf = next_ipf) { next_ipf = LIST_NEXT(ipf, ipf_list); ipflow_free(ipf); } + + if (new_size) + error = ipflow_init(new_size); splx(s); + + return error; } diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index b01029f06da..a26d8ade4eb 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -1,4 +1,4 @@ -/* $NetBSD: ip_input.c,v 1.247 2007/03/24 00:27:58 liamjfoy Exp $ */ +/* $NetBSD: ip_input.c,v 1.248 2007/03/25 20:12:20 liamjfoy Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -98,7 +98,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.247 2007/03/24 00:27:58 liamjfoy Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.248 2007/03/25 20:12:20 liamjfoy Exp $"); #include "opt_inet.h" #include "opt_gateway.h" @@ -429,7 +429,7 @@ ip_init(void) M_WAITOK, &in_multihash); ip_mtudisc_timeout_q = rt_timer_queue_create(ip_mtudisc_timeout); #ifdef GATEWAY - ipflow_init(); + ipflow_init(ip_hashsize); #endif #ifdef PFIL_HOOKS @@ -2177,6 +2177,35 @@ sysctl_net_inet_ip_maxflows(SYSCTLFN_ARGS) return (0); } + +static int +sysctl_net_inet_ip_hashsize(SYSCTLFN_ARGS) +{ + int error, tmp; + struct sysctlnode node; + + node = *rnode; + tmp = ip_hashsize; + node.sysctl_data = &tmp; + error = sysctl_lookup(SYSCTLFN_CALL(&node)); + if (error || newp == NULL) + return (error); + + if ((tmp & (tmp - 1)) == 0 && tmp != 0) { + /* + * Can only fail due to malloc() + */ + if (ipflow_invalidate_all(tmp)) + return ENOMEM; + } else { + /* + * EINVAL if not a power of 2 + */ + return EINVAL; + } + + return (0); +} #endif /* GATEWAY */ @@ -2298,6 +2327,13 @@ SYSCTL_SETUP(sysctl_net_inet_ip_setup, "sysctl net.inet.ip subtree setup") sysctl_net_inet_ip_maxflows, 0, &ip_maxflows, 0, CTL_NET, PF_INET, IPPROTO_IP, IPCTL_MAXFLOWS, CTL_EOL); + sysctl_createv(clog, 0, NULL, NULL, + CTLFLAG_PERMANENT|CTLFLAG_READWRITE, + CTLTYPE_INT, "hashsize", + SYSCTL_DESCR("Size of hash table for fast forwarding (IPv4)"), + sysctl_net_inet_ip_hashsize, 0, &ip_hashsize, 0, + CTL_NET, PF_INET, IPPROTO_IP, + CTL_CREATE, CTL_EOL); #endif /* GATEWAY */ sysctl_createv(clog, 0, NULL, NULL, CTLFLAG_PERMANENT|CTLFLAG_READWRITE, diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h index de81f5879c3..192aeba9d3b 100644 --- a/sys/netinet/ip_var.h +++ b/sys/netinet/ip_var.h @@ -1,4 +1,4 @@ -/* $NetBSD: ip_var.h,v 1.78 2007/02/17 22:34:11 dyoung Exp $ */ +/* $NetBSD: ip_var.h,v 1.79 2007/03/25 20:12:20 liamjfoy Exp $ */ /* * Copyright (c) 1982, 1986, 1993 @@ -212,6 +212,7 @@ extern struct mowner ip_tx_mowner; #endif #ifdef GATEWAY extern int ip_maxflows; +extern int ip_hashsize; #endif extern struct pool inmulti_pool; extern struct pool ipqent_pool; @@ -250,11 +251,11 @@ void rip_input(struct mbuf *, ...); int rip_output(struct mbuf *, ...); int rip_usrreq(struct socket *, int, struct mbuf *, struct mbuf *, struct mbuf *, struct lwp *); -void ipflow_init(void); +int ipflow_init(int); struct ipflow *ipflow_reap(int); void ipflow_create(const struct route *, struct mbuf *); void ipflow_slowtimo(void); -void ipflow_invalidate_all(void); +int ipflow_invalidate_all(int); extern uint16_t ip_id; static __inline uint16_t ip_newid(void); |
