summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorliamjfoy <liamjfoy@NetBSD.org>2007-03-25 20:12:20 +0000
committerliamjfoy <liamjfoy@NetBSD.org>2007-03-25 20:12:20 +0000
commitb8ef59d7201f80296b46ea45ee3847e1fc2092eb (patch)
treefc5ec2363a4d564d07505bbff1bd1ade94051856 /sys
parentcbd0d608fc5194b427224cf6eccaa064bf951f26 (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.c44
-rw-r--r--sys/netinet/ip_input.c42
-rw-r--r--sys/netinet/ip_var.h7
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);