Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/netinet Re-structure IPv4 reassembly code to make it mor...
details: https://anonhg.NetBSD.org/src/rev/3981aa5581b4
branches: trunk
changeset: 757921:3981aa5581b4
user: rmind <rmind%NetBSD.org@localhost>
date: Sun Oct 03 19:44:47 2010 +0000
description:
Re-structure IPv4 reassembly code to make it more MP-friendly and simplify
some code fragments while here. Also, use pool_cache(9) and mutex(9).
IPv4 reassembly mechanism is MP-safe now.
diffstat:
sys/netinet/ip_reass.c | 169 +++++++++++++++---------------------------------
1 files changed, 52 insertions(+), 117 deletions(-)
diffs (truncated from 364 to 300 lines):
diff -r f93bb06449d2 -r 3981aa5581b4 sys/netinet/ip_reass.c
--- a/sys/netinet/ip_reass.c Sun Oct 03 19:41:25 2010 +0000
+++ b/sys/netinet/ip_reass.c Sun Oct 03 19:44:47 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ip_reass.c,v 1.3 2010/08/25 00:05:14 rmind Exp $ */
+/* $NetBSD: ip_reass.c,v 1.4 2010/10/03 19:44:47 rmind Exp $ */
/*
* Copyright (c) 1982, 1986, 1988, 1993
@@ -46,13 +46,14 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_reass.c,v 1.3 2010/08/25 00:05:14 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_reass.c,v 1.4 2010/10/03 19:44:47 rmind Exp $");
#include <sys/param.h>
#include <sys/types.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
+#include <sys/mutex.h>
#include <sys/domain.h>
#include <sys/protosw.h>
#include <sys/pool.h>
@@ -107,8 +108,8 @@
(((((x) & 0xf) | ((((x) >> 8) & 0xf) << 4)) ^ (y)) & IPREASS_HASH_MASK)
static LIST_HEAD(, ipfr_queue) ip_frags[IPREASS_HASH_SIZE];
-static struct pool ipqent_pool;
-static int ipq_locked;
+static pool_cache_t ipfren_cache;
+static kmutex_t ipfr_lock;
/* Number of packets in reassembly queue and total number of fragments. */
static int ip_nfragpackets;
@@ -129,6 +130,8 @@
*/
static u_int fragttl_histo[IPFRAGTTL + 1];
+static struct sysctllog *ip_reass_sysctllog;
+
void sysctl_ip_reass_setup(void);
static void ip_nmbclusters_changed(void);
@@ -147,8 +150,9 @@
{
int i;
- pool_init(&ipqent_pool, sizeof(ipfr_qent_t), 0, 0, 0, "ipqepl",
- NULL, IPL_VM);
+ ipfren_cache = pool_cache_init(sizeof(ipfr_qent_t), coherency_unit,
+ 0, 0, "ipfrenpl", NULL, IPL_NET, NULL, NULL, NULL);
+ mutex_init(&ipfr_lock, MUTEX_DEFAULT, IPL_SOFTNET);
for (i = 0; i < IPREASS_HASH_SIZE; i++) {
LIST_INIT(&ip_frags[i]);
@@ -160,8 +164,6 @@
sysctl_ip_reass_setup();
}
-static struct sysctllog *ip_reass_sysctllog;
-
void
sysctl_ip_reass_setup(void)
{
@@ -209,60 +211,6 @@
ip_nmbclusters = nmbclusters;
}
-static inline int ipq_lock_try(void);
-static inline void ipq_unlock(void);
-
-static inline int
-ipq_lock_try(void)
-{
- int s;
-
- /*
- * Use splvm() -- we're blocking things that would cause
- * mbuf allocation.
- */
- s = splvm();
- if (ipq_locked) {
- splx(s);
- return (0);
- }
- ipq_locked = 1;
- splx(s);
- return (1);
-}
-
-static inline void
-ipq_unlock(void)
-{
- int s;
-
- s = splvm();
- ipq_locked = 0;
- splx(s);
-}
-
-#ifdef DIAGNOSTIC
-#define IPQ_LOCK() \
-do { \
- if (ipq_lock_try() == 0) { \
- printf("%s:%d: ipq already locked\n", __FILE__, __LINE__); \
- panic("ipq_lock"); \
- } \
-} while (/*CONSTCOND*/ 0)
-#define IPQ_LOCK_CHECK() \
-do { \
- if (ipq_locked == 0) { \
- printf("%s:%d: ipq lock not held\n", __FILE__, __LINE__); \
- panic("ipq lock check"); \
- } \
-} while (/*CONSTCOND*/ 0)
-#else
-#define IPQ_LOCK() (void) ipq_lock_try()
-#define IPQ_LOCK_CHECK() /* nothing */
-#endif
-
-#define IPQ_UNLOCK() ipq_unlock()
-
/*
* ip_reass:
*
@@ -277,9 +225,9 @@
struct mbuf *m = ipqe->ipqe_m, *t;
ipfr_qent_t *nq, *p, *q;
struct ip *ip;
- int i, next, s;
+ int i, next;
- IPQ_LOCK_CHECK();
+ KASSERT(mutex_owned(&ipfr_lock));
/*
* Presence of header sizes in mbufs would confuse code below.
@@ -385,9 +333,7 @@
nq = TAILQ_NEXT(q, ipqe_q);
m_freem(q->ipqe_m);
TAILQ_REMOVE(&fp->ipq_fragq, q, ipqe_q);
- s = splvm();
- pool_put(&ipqent_pool, q);
- splx(s);
+ pool_cache_put(ipfren_cache, q);
fp->ipq_nfrags--;
ip_nfrags--;
}
@@ -405,44 +351,46 @@
for (p = NULL, q = TAILQ_FIRST(&fp->ipq_fragq); q != NULL;
p = q, q = TAILQ_NEXT(q, ipqe_q)) {
if (ntohs(q->ipqe_ip->ip_off) != next) {
- IPQ_UNLOCK();
+ mutex_exit(&ipfr_lock);
return NULL;
}
next += ntohs(q->ipqe_ip->ip_len);
}
if (p->ipqe_mff) {
- IPQ_UNLOCK();
+ mutex_exit(&ipfr_lock);
return NULL;
}
/*
- * Reassembly is complete. Check for a bogus message size and
- * concatenate fragments.
+ * Reassembly is complete. Check for a bogus message size.
*/
q = TAILQ_FIRST(&fp->ipq_fragq);
ip = q->ipqe_ip;
if ((next + (ip->ip_hl << 2)) > IP_MAXPACKET) {
IP_STATINC(IP_STAT_TOOLONG);
ip_freef(fp);
- IPQ_UNLOCK();
+ mutex_exit(&ipfr_lock);
return NULL;
}
+ LIST_REMOVE(fp, ipq_q);
+ ip_nfrags -= fp->ipq_nfrags;
+ ip_nfragpackets--;
+ mutex_exit(&ipfr_lock);
+
+ /* Concatenate all fragments. */
m = q->ipqe_m;
t = m->m_next;
m->m_next = NULL;
m_cat(m, t);
nq = TAILQ_NEXT(q, ipqe_q);
- s = splvm();
- pool_put(&ipqent_pool, q);
- splx(s);
+ pool_cache_put(ipfren_cache, q);
+
for (q = nq; q != NULL; q = nq) {
t = q->ipqe_m;
nq = TAILQ_NEXT(q, ipqe_q);
- s = splvm();
- pool_put(&ipqent_pool, q);
- splx(s);
+ pool_cache_put(ipfren_cache, q);
m_cat(m, t);
}
- ip_nfrags -= fp->ipq_nfrags;
+ free(fp, M_FTABLE);
/*
* Create header for new packet by modifying header of first
@@ -453,13 +401,11 @@
ip->ip_src = fp->ipq_src;
ip->ip_dst = fp->ipq_dst;
- LIST_REMOVE(fp, ipq_q);
- free(fp, M_FTABLE);
- ip_nfragpackets--;
m->m_len += (ip->ip_hl << 2);
m->m_data -= (ip->ip_hl << 2);
- /* some debugging cruft by sklower, below, will go away soon */
- if (m->m_flags & M_PKTHDR) { /* XXX this should be done elsewhere */
+
+ /* Fix up mbuf. XXX This should be done elsewhere. */
+ if (m->m_flags & M_PKTHDR) {
int plen = 0;
for (t = m; t; t = t->m_next) {
plen += t->m_len;
@@ -467,7 +413,6 @@
m->m_pkthdr.len = plen;
m->m_pkthdr.csum_flags = 0;
}
- IPQ_UNLOCK();
return m;
dropfrag:
@@ -476,11 +421,10 @@
}
ip_nfrags--;
IP_STATINC(IP_STAT_FRAGDROPPED);
+ mutex_exit(&ipfr_lock);
+
+ pool_cache_put(ipfren_cache, ipqe);
m_freem(m);
- s = splvm();
- pool_put(&ipqent_pool, ipqe);
- splx(s);
- IPQ_UNLOCK();
return NULL;
}
@@ -492,29 +436,20 @@
static void
ip_freef(ipfr_queue_t *fp)
{
- ipfr_qent_t *q, *p;
- u_int nfrags = 0;
- int s;
+ ipfr_qent_t *q;
+
+ KASSERT(mutex_owned(&ipfr_lock));
- IPQ_LOCK_CHECK();
+ LIST_REMOVE(fp, ipq_q);
+ ip_nfrags -= fp->ipq_nfrags;
+ ip_nfragpackets--;
- for (q = TAILQ_FIRST(&fp->ipq_fragq); q != NULL; q = p) {
- p = TAILQ_NEXT(q, ipqe_q);
- m_freem(q->ipqe_m);
- nfrags++;
+ while ((q = TAILQ_FIRST(&fp->ipq_fragq)) != NULL) {
TAILQ_REMOVE(&fp->ipq_fragq, q, ipqe_q);
- s = splvm();
- pool_put(&ipqent_pool, q);
- splx(s);
+ m_freem(q->ipqe_m);
+ pool_cache_put(ipfren_cache, q);
}
-
- if (nfrags != fp->ipq_nfrags) {
- printf("ip_freef: nfrags %d != %d\n", fp->ipq_nfrags, nfrags);
- }
- ip_nfrags -= nfrags;
- LIST_REMOVE(fp, ipq_q);
free(fp, M_FTABLE);
- ip_nfragpackets--;
}
/*
@@ -571,6 +506,8 @@
{
u_int median_ticks;
+ KASSERT(mutex_owned(&ipfr_lock));
+
/*
* Compute median TTL of all fragments, and count frags
* with that TTL or lower (roughly half of all fragments).
@@ -593,13 +530,13 @@
* We may be called from a device's interrupt context. If
* the ipq is already busy, just bail out now.
Home |
Main Index |
Thread Index |
Old Index