summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/kern/uipc_mbuf.c87
-rw-r--r--sys/kern/uipc_socket2.c8
-rw-r--r--sys/net/if.c55
-rw-r--r--sys/net/if.h11
-rw-r--r--sys/net/if_ethersubr.c4
-rw-r--r--sys/sys/mbuf.h19
-rw-r--r--sys/sys/param.h4
7 files changed, 154 insertions, 34 deletions
diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c
index 7db45a81cff..c0c53fb447b 100644
--- a/sys/kern/uipc_mbuf.c
+++ b/sys/kern/uipc_mbuf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uipc_mbuf.c,v 1.94 2008/10/14 18:01:53 naddy Exp $ */
+/* $OpenBSD: uipc_mbuf.c,v 1.95 2008/11/24 12:57:37 dlg Exp $ */
/* $NetBSD: uipc_mbuf.c,v 1.15.4.1 1996/06/13 17:11:44 cgd Exp $ */
/*
@@ -90,7 +90,22 @@
struct mbstat mbstat; /* mbuf stats */
struct pool mbpool; /* mbuf pool */
-struct pool mclpool; /* mbuf cluster pool */
+
+/* mbuf cluster pools */
+struct mclsizes mclsizes[] = {
+ { MCLBYTES, 4, 1 }, /* must be at slot 0 */
+ { 4 * 1024, 4, 2 },
+#ifdef notyet
+ /* pool allocator cannot cope with >PAGESIZE objects */
+ { 8 * 1024, 4, 2 },
+ { 9 * 1024, 4, 2 },
+ { 12 * 1024, 4, 2 },
+ { 16 * 1024, 4, 2 },
+ { 64 * 1024, 4, 2 }
+#endif
+};
+static char mclnames[MCLPOOLS][8];
+struct pool mclpools[MCLPOOLS];
int max_linkhdr; /* largest link-level header */
int max_protohdr; /* largest protocol header */
@@ -102,7 +117,7 @@ void nmbclust_update(void);
const char *mclpool_warnmsg =
- "WARNING: mclpool limit reached; increase kern.maxclusters";
+ "WARNING: mclpools limit reached; increase kern.maxclusters";
/*
* Initialize the mbuf allocator.
@@ -110,30 +125,35 @@ const char *mclpool_warnmsg =
void
mbinit(void)
{
+ int i;
+
pool_init(&mbpool, MSIZE, 0, 0, 0, "mbpl", NULL);
- pool_init(&mclpool, MCLBYTES, 0, 0, 0, "mclpl", NULL);
+ pool_setlowat(&mbpool, mblowat);
- nmbclust_update();
+ for (i = 0; i < nitems(mclsizes); i++) {
+ snprintf(mclnames[i], sizeof(mclnames[0]), "mcl%dk",
+ mclsizes[i].size >> 10);
+ pool_init(&mclpools[i], mclsizes[i].size, 0, 0, 0, mclnames[i],
+ NULL);
+ pool_setlowat(&mclpools[i], mcllowat);
+ }
- /*
- * Set a low water mark for both mbufs and clusters. This should
- * help ensure that they can be allocated in a memory starvation
- * situation. This is important for e.g. diskless systems which
- * must allocate mbufs in order for the pagedaemon to clean pages.
- */
- pool_setlowat(&mbpool, mblowat);
- pool_setlowat(&mclpool, mcllowat);
+ nmbclust_update();
}
void
nmbclust_update(void)
{
+ int i;
/*
- * Set the hard limit on the mclpool to the number of
+ * Set the hard limit on the mclpools to the number of
* mbuf clusters the kernel is to support. Log the limit
* reached message max once a minute.
*/
- (void)pool_sethardlimit(&mclpool, nmbclust, mclpool_warnmsg, 60);
+ for (i = 0; i < nitems(mclsizes); i++) {
+ (void)pool_sethardlimit(&mclpools[i], nmbclust,
+ mclpool_warnmsg, 60);
+ }
pool_sethiwat(&mbpool, nmbclust);
}
@@ -244,20 +264,41 @@ m_getclr(int nowait, int type)
}
void
-m_clget(struct mbuf *m, int how)
+m_clget(struct mbuf *m, int how, struct ifnet *ifp, u_int pktlen)
{
+ struct pool *mclp;
+ int pi;
int s;
+ for (pi = 0; pi < nitems(mclpools); pi++) {
+ mclp = &mclpools[pi];
+ if (pktlen <= mclp->pr_size)
+ break;
+ }
+
+#ifdef DIAGNOSTIC
+ if (mclp == NULL)
+ panic("m_clget: request for %d sized cluster", pktlen);
+#endif
+
+ if (ifp != NULL && m_cldrop(ifp, pi))
+ return;
+
s = splvm();
- m->m_ext.ext_buf =
- pool_get(&mclpool, how == M_WAIT ? PR_WAITOK : 0);
+ m->m_ext.ext_buf = pool_get(mclp, how == M_WAIT ? PR_WAITOK : 0);
splx(s);
if (m->m_ext.ext_buf != NULL) {
m->m_data = m->m_ext.ext_buf;
m->m_flags |= M_EXT|M_CLUSTER;
- m->m_ext.ext_size = MCLBYTES;
+ m->m_ext.ext_size = mclp->pr_size;
m->m_ext.ext_free = NULL;
m->m_ext.ext_arg = NULL;
+
+ m->m_ext.ext_backend = pi;
+ m->m_ext.ext_ifp = ifp;
+ if (ifp != NULL)
+ m_clcount(ifp, pi);
+
MCLINITREFERENCE(m);
}
}
@@ -278,9 +319,11 @@ m_free(struct mbuf *m)
m->m_ext.ext_prevref;
m->m_ext.ext_prevref->m_ext.ext_nextref =
m->m_ext.ext_nextref;
- } else if (m->m_flags & M_CLUSTER)
- pool_put(&mclpool, m->m_ext.ext_buf);
- else if (m->m_ext.ext_free)
+ } else if (m->m_flags & M_CLUSTER) {
+ m_cluncount(m);
+ pool_put(&mclpools[m->m_ext.ext_backend],
+ m->m_ext.ext_buf);
+ } else if (m->m_ext.ext_free)
(*(m->m_ext.ext_free))(m->m_ext.ext_buf,
m->m_ext.ext_size, m->m_ext.ext_arg);
else
diff --git a/sys/kern/uipc_socket2.c b/sys/kern/uipc_socket2.c
index 1cf4403f75d..647edfce827 100644
--- a/sys/kern/uipc_socket2.c
+++ b/sys/kern/uipc_socket2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uipc_socket2.c,v 1.44 2008/05/23 15:51:12 thib Exp $ */
+/* $OpenBSD: uipc_socket2.c,v 1.45 2008/11/24 12:57:37 dlg Exp $ */
/* $NetBSD: uipc_socket2.c,v 1.11 1996/02/04 02:17:55 christos Exp $ */
/*
@@ -58,7 +58,7 @@ const char netlck[] = "netlck";
u_long sb_max = SB_MAX; /* patchable */
-extern struct pool mclpool;
+extern struct pool mclpools[];
/*
* Procedures to manipulate state flags of socket
@@ -158,7 +158,7 @@ sonewconn(struct socket *head, int connstatus)
splassert(IPL_SOFTNET);
- if (mclpool.pr_nout > mclpool.pr_hardlimit * 95 / 100)
+ if (mclpools[0].pr_nout > mclpools[0].pr_hardlimit * 95 / 100)
return ((struct socket *)0);
if (head->so_qlen + head->so_q0len > head->so_qlimit * 3)
return ((struct socket *)0);
@@ -407,7 +407,7 @@ int
sbcheckreserve(u_long cnt, u_long defcnt)
{
if (cnt > defcnt &&
- mclpool.pr_nout> mclpool.pr_hardlimit / 2)
+ mclpools[0].pr_nout> mclpools[0].pr_hardlimit / 2)
return (ENOBUFS);
return (0);
}
diff --git a/sys/net/if.c b/sys/net/if.c
index 8bfb97df149..db68e28ce8a 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if.c,v 1.176 2008/11/24 12:53:53 claudio Exp $ */
+/* $OpenBSD: if.c,v 1.177 2008/11/24 12:57:37 dlg Exp $ */
/* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */
/*
@@ -147,6 +147,8 @@ struct if_clone *if_clone_lookup(const char *, int *);
void if_congestion_clear(void *);
int if_group_egress_build(void);
+void m_clinitifp(struct ifnet *);
+
TAILQ_HEAD(, ifg_group) ifg_head;
LIST_HEAD(, if_clone) if_cloners = LIST_HEAD_INITIALIZER(if_cloners);
int if_cloners_count;
@@ -455,6 +457,8 @@ if_attach(struct ifnet *ifp)
TAILQ_INSERT_TAIL(&ifnet, ifp, if_list);
#endif
+ m_clinitifp(ifp);
+
if_attachsetup(ifp);
}
@@ -1105,9 +1109,12 @@ if_up(struct ifnet *ifp)
#ifdef INET6
in6_if_up(ifp);
#endif
+
#ifndef SMALL_KERNEL
rt_if_track(ifp);
#endif
+
+ m_clinitifp(ifp);
}
/*
@@ -2008,3 +2015,49 @@ sysctl_ifq(int *name, u_int namelen, void *oldp, size_t *oldlenp,
}
/* NOTREACHED */
}
+
+void
+m_clinitifp(struct ifnet *ifp)
+{
+ extern struct mclsizes mclsizes[];
+ int i;
+
+ /* Initialize high water marks for use of cluster pools */
+ for (i = 0; i < MCLPOOLS; i++)
+ ifp->if_mclstat.mclpool[i].mcl_hwm = mclsizes[i].hwm;
+}
+
+int
+m_cldrop(struct ifnet *ifp, int pi)
+{
+ struct mclstat *mcls = &ifp->if_mclstat;
+ extern struct mclsizes mclsizes[];
+
+ if (mcls->mclpool[pi].mcl_alive <= 2 && ISSET(ifp->if_flags, IFF_UP)) {
+ /* About to run out, so increase the watermark */
+ mcls->mclpool[pi].mcl_hwm +=
+ mcls->mclpool[pi].mcl_hwm / mclsizes[pi].factor;
+ } else if (mcls->mclpool[pi].mcl_alive >= mcls->mclpool[pi].mcl_hwm)
+ return (1); /* No more packets given */
+
+ return (0);
+}
+
+void
+m_clcount(struct ifnet *ifp, int pi)
+{
+ ifp->if_mclstat.mclpool[pi].mcl_alive++;
+}
+
+void
+m_cluncount(struct mbuf *m)
+{
+ struct mbuf_ext *me = &m->m_ext;
+
+ if (((m->m_flags & (M_EXT|M_CLUSTER)) != (M_EXT|M_CLUSTER)) ||
+ (me->ext_ifp == NULL))
+ return;
+
+ me->ext_ifp->if_mclstat.mclpool[me->ext_backend].mcl_alive--;
+ me->ext_ifp = NULL;
+}
diff --git a/sys/net/if.h b/sys/net/if.h
index c366caeb756..a9b8c02eb12 100644
--- a/sys/net/if.h
+++ b/sys/net/if.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if.h,v 1.95 2008/11/07 05:50:33 deraadt Exp $ */
+/* $OpenBSD: if.h,v 1.96 2008/11/24 12:57:37 dlg Exp $ */
/* $NetBSD: if.h,v 1.23 1996/05/07 02:40:27 thorpej Exp $ */
/*
@@ -146,6 +146,13 @@ struct ifqueue {
struct timeout *ifq_congestion;
};
+struct mclstat {
+ struct {
+ u_short mcl_alive;
+ u_short mcl_hwm;
+ } mclpool[MCLPOOLS];
+};
+
/*
* Values for if_link_state.
*/
@@ -224,6 +231,8 @@ struct ifnet { /* and the entries */
struct sockaddr_dl *if_sadl; /* pointer to our sockaddr_dl */
void *if_afdata[AF_MAX];
+
+ struct mclstat if_mclstat; /* mbuf cluster pool stats */
};
#define if_mtu if_data.ifi_mtu
#define if_type if_data.ifi_type
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c
index 8adca1c9a9b..e68e442eff8 100644
--- a/sys/net/if_ethersubr.c
+++ b/sys/net/if_ethersubr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_ethersubr.c,v 1.128 2008/11/23 23:44:01 tedu Exp $ */
+/* $OpenBSD: if_ethersubr.c,v 1.129 2008/11/24 12:57:37 dlg Exp $ */
/* $NetBSD: if_ethersubr.c,v 1.19 1996/05/07 02:40:30 thorpej Exp $ */
/*
@@ -519,6 +519,8 @@ ether_input(ifp0, eh, m)
struct ether_header *eh_tmp;
#endif
+ m_cluncount(m);
+
if (eh == NULL) {
eh = mtod(m, struct ether_header *);
m_adj(m, ETHER_HDR_LEN);
diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h
index a5a51e3d55b..0b2ba7f0af6 100644
--- a/sys/sys/mbuf.h
+++ b/sys/sys/mbuf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: mbuf.h,v 1.108 2008/11/23 16:17:17 dlg Exp $ */
+/* $OpenBSD: mbuf.h,v 1.109 2008/11/24 12:57:37 dlg Exp $ */
/* $NetBSD: mbuf.h,v 1.19 1996/02/09 18:25:14 christos Exp $ */
/*
@@ -109,6 +109,8 @@ struct mbuf_ext {
void *ext_arg; /* argument for ext_free */
u_int ext_size; /* size of buffer, for ext_free */
int ext_type;
+ struct ifnet* ext_ifp;
+ int ext_backend; /* backend pool the storage came from */
struct mbuf *ext_nextref;
struct mbuf *ext_prevref;
#ifdef DEBUG
@@ -296,7 +298,8 @@ struct mbuf {
MCLINITREFERENCE(m); \
} while (/* CONSTCOND */ 0)
-#define MCLGET(m, how) m_clget((m), (how))
+#define MCLGET(m, how) m_clget((m), (how), NULL, MCLBYTES)
+#define MCLGETI(m, how, ifp, l) m_clget((m), (how), (ifp), (l))
/*
* Reset the data pointer on an mbuf.
@@ -438,6 +441,13 @@ struct mbstat {
};
#ifdef _KERNEL
+
+struct mclsizes {
+ u_int size;
+ u_int hwm;
+ u_int factor;
+};
+
extern struct mbstat mbstat;
extern int nmbclust; /* limit on the # of clusters */
extern int mblowat; /* mbuf low water mark */
@@ -465,7 +475,10 @@ struct mbuf *m_inject(struct mbuf *, int, int, int);
struct mbuf *m_getptr(struct mbuf *, int, int *);
int m_leadingspace(struct mbuf *);
int m_trailingspace(struct mbuf *);
-void m_clget(struct mbuf *, int);
+void m_clget(struct mbuf *, int, struct ifnet *, u_int);
+int m_cldrop(struct ifnet *, int);
+void m_clcount(struct ifnet *, int);
+void m_cluncount(struct mbuf *);
void m_adj(struct mbuf *, int);
void m_copyback(struct mbuf *, int, int, const void *);
void m_freem(struct mbuf *);
diff --git a/sys/sys/param.h b/sys/sys/param.h
index 2a743dd0a9a..2cf7cb55c0c 100644
--- a/sys/sys/param.h
+++ b/sys/sys/param.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: param.h,v 1.79 2008/11/23 12:43:37 deraadt Exp $ */
+/* $OpenBSD: param.h,v 1.80 2008/11/24 12:57:37 dlg Exp $ */
/* $NetBSD: param.h,v 1.23 1996/03/17 01:02:29 thorpej Exp $ */
/*-
@@ -140,7 +140,7 @@
/* 2K cluster can hold Ether frame */
#define MCLBYTES (1 << MCLSHIFT) /* size of a m_buf cluster */
#define MCLOFSET (MCLBYTES - 1)
-
+#define MCLPOOLS 7 /* number of cluster pools */
/*
* File system parameters and macros.