Module Name: src
Committed By: skrll
Date: Thu Jan 26 21:13:19 UTC 2017
Modified Files:
src/sys/net: if_tun.c if_tun.h
Log Message:
Make MP-safe and use kmem(9)
Mostly from rmind-smpnet
To generate a diff of this commit:
cvs rdiff -u -r1.135 -r1.136 src/sys/net/if_tun.c
cvs rdiff -u -r1.19 -r1.20 src/sys/net/if_tun.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/net/if_tun.c
diff -u src/sys/net/if_tun.c:1.135 src/sys/net/if_tun.c:1.136
--- src/sys/net/if_tun.c:1.135 Mon Jan 23 15:32:04 2017
+++ src/sys/net/if_tun.c Thu Jan 26 21:13:19 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: if_tun.c,v 1.135 2017/01/23 15:32:04 skrll Exp $ */
+/* $NetBSD: if_tun.c,v 1.136 2017/01/26 21:13:19 skrll Exp $ */
/*
* Copyright (c) 1988, Julian Onions <[email protected]>
@@ -14,33 +14,35 @@
* operation though.
*/
+/*
+ * tun - tunnel software network interface.
+ */
+
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_tun.c,v 1.135 2017/01/23 15:32:04 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_tun.c,v 1.136 2017/01/26 21:13:19 skrll Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
#endif
#include <sys/param.h>
+
#include <sys/buf.h>
#include <sys/conf.h>
#include <sys/cpu.h>
#include <sys/device.h>
-#include <sys/errno.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/kauth.h>
+#include <sys/kmem.h>
+#include <sys/lwp.h>
#include <sys/mbuf.h>
#include <sys/module.h>
#include <sys/mutex.h>
#include <sys/poll.h>
-#include <sys/proc.h>
#include <sys/select.h>
#include <sys/signalvar.h>
#include <sys/socket.h>
-#include <sys/syslog.h>
-#include <sys/systm.h>
-#include <sys/time.h>
#include <net/bpf.h>
#include <net/if.h>
@@ -107,7 +109,7 @@ const struct cdevsw tun_cdevsw = {
.d_mmap = nommap,
.d_kqfilter = tunkqfilter,
.d_discard = nodiscard,
- .d_flag = D_OTHER
+ .d_flag = D_OTHER | D_MPSAFE
};
#ifdef _MODULE
@@ -194,10 +196,8 @@ tun_find_zunit(int unit)
if (tp)
LIST_REMOVE(tp, tun_list);
mutex_exit(&tun_softc_lock);
-#ifdef DIAGNOSTIC
- if (tp != NULL && (tp->tun_flags & (TUN_INITED|TUN_OPEN)) != TUN_OPEN)
- printf("tun%d: inconsistent flags: %x\n", unit, tp->tun_flags);
-#endif
+ KASSERTMSG(!tp || (tp->tun_flags & (TUN_INITED|TUN_OPEN)) != TUN_OPEN,
+ "tun%d: inconsistent flags: %x", unit, tp->tun_flags);
return tp;
}
@@ -208,11 +208,11 @@ tun_clone_create(struct if_clone *ifc, i
struct tun_softc *tp;
if ((tp = tun_find_zunit(unit)) == NULL) {
- /* Allocate a new instance */
- tp = malloc(sizeof(*tp), M_DEVBUF, M_WAITOK|M_ZERO);
+ tp = kmem_zalloc(sizeof(*tp), KM_SLEEP);
tp->tun_unit = unit;
mutex_init(&tp->tun_lock, MUTEX_DEFAULT, IPL_NET);
+ cv_init(&tp->tun_cv, "tunread");
selinit(&tp->tun_rsel);
selinit(&tp->tun_wsel);
} else {
@@ -267,7 +267,7 @@ static int
tun_clone_destroy(struct ifnet *ifp)
{
struct tun_softc *tp = (void *)ifp;
- int zombie = 0;
+ bool zombie = false;
IF_PURGE(&ifp->if_snd);
ifp->if_flags &= ~IFF_RUNNING;
@@ -276,16 +276,16 @@ tun_clone_destroy(struct ifnet *ifp)
mutex_enter(&tp->tun_lock);
LIST_REMOVE(tp, tun_list);
if (tp->tun_flags & TUN_OPEN) {
- /* Hang on to storage until last close */
- zombie = 1;
+ /* Hang on to storage until last close. */
tp->tun_flags &= ~TUN_INITED;
LIST_INSERT_HEAD(&tunz_softc_list, tp, tun_list);
+ zombie = true;
}
mutex_exit(&tun_softc_lock);
if (tp->tun_flags & TUN_RWAIT) {
tp->tun_flags &= ~TUN_RWAIT;
- wakeup((void *)tp);
+ cv_broadcast(&tp->tun_cv);
}
selnotify(&tp->tun_rsel, 0, 0);
@@ -303,7 +303,7 @@ tun_clone_destroy(struct ifnet *ifp)
softint_disestablish(tp->tun_osih);
softint_disestablish(tp->tun_isih);
mutex_destroy(&tp->tun_lock);
- free(tp, M_DEVBUF);
+ kmem_free(tp, sizeof(*tp));
}
return 0;
@@ -331,22 +331,21 @@ tunopen(dev_t dev, int flag, int mode, s
(void)tun_clone_create(&tun_cloner, minor(dev));
tp = tun_find_unit(dev);
if (tp == NULL) {
- error = ENXIO;
- goto out_nolock;
+ return ENXIO;
}
}
if (tp->tun_flags & TUN_OPEN) {
- error = EBUSY;
- goto out;
+ mutex_exit(&tp->tun_lock);
+ return EBUSY;
}
ifp = &tp->tun_if;
tp->tun_flags |= TUN_OPEN;
TUNDEBUG("%s: open\n", ifp->if_xname);
-out:
+
mutex_exit(&tp->tun_lock);
-out_nolock:
+
return error;
}
@@ -368,8 +367,8 @@ tunclose(dev_t dev, int flag, int mode,
softint_disestablish(tp->tun_osih);
softint_disestablish(tp->tun_isih);
mutex_destroy(&tp->tun_lock);
- free(tp, M_DEVBUF);
- goto out_nolock;
+ kmem_free(tp, sizeof(*tp));
+ return 0;
}
if ((tp = tun_find_unit(dev)) == NULL)
@@ -412,9 +411,6 @@ out_nolock:
return 0;
}
-/*
- * Call at splnet().
- */
static void
tun_enable(struct tun_softc *tp, const struct ifaddr *ifa)
{
@@ -473,12 +469,10 @@ tun_enable(struct tun_softc *tp, const s
static int
tun_ioctl(struct ifnet *ifp, u_long cmd, void *data)
{
- int error = 0, s;
struct tun_softc *tp = (struct tun_softc *)(ifp->if_softc);
struct ifreq *ifr = (struct ifreq *)data;
struct ifaddr *ifa = (struct ifaddr *)data;
-
- s = splnet();
+ int error = 0;
switch (cmd) {
case SIOCINITIFADDR:
@@ -522,7 +516,6 @@ tun_ioctl(struct ifnet *ifp, u_long cmd,
error = ifioctl_common(ifp, cmd, data);
}
- splx(s);
return error;
}
@@ -534,14 +527,12 @@ tun_output(struct ifnet *ifp, struct mbu
const struct rtentry *rt)
{
struct tun_softc *tp = ifp->if_softc;
- int s;
int error;
#if defined(INET) || defined(INET6)
int mlen;
uint32_t *af;
#endif
- s = splnet();
mutex_enter(&tp->tun_lock);
TUNDEBUG ("%s: tun_output\n", ifp->if_xname);
@@ -551,6 +542,8 @@ tun_output(struct ifnet *ifp, struct mbu
error = EHOSTDOWN;
goto out;
}
+ // XXXrmind
+ mutex_exit(&tp->tun_lock);
/*
* if the queueing discipline needs packet classification,
@@ -576,7 +569,7 @@ tun_output(struct ifnet *ifp, struct mbu
error = ENOBUFS;
goto out;
}
- bcopy(dst, mtod(m0, char *), dst->sa_len);
+ memcpy(mtod(m0, char *), dst, dst->sa_len);
}
if (tp->tun_flags & TUN_IFHEAD) {
@@ -617,9 +610,10 @@ tun_output(struct ifnet *ifp, struct mbu
goto out;
}
+ mutex_enter(&tp->tun_lock);
if (tp->tun_flags & TUN_RWAIT) {
tp->tun_flags &= ~TUN_RWAIT;
- wakeup((void *)tp);
+ cv_broadcast(&tp->tun_cv);
}
if (tp->tun_flags & TUN_ASYNC && tp->tun_pgid)
softint_schedule(tp->tun_isih);
@@ -627,7 +621,6 @@ tun_output(struct ifnet *ifp, struct mbu
selnotify(&tp->tun_rsel, 0, 0);
out:
mutex_exit(&tp->tun_lock);
- splx(s);
if (error && m0) {
m_freem(m0);
@@ -662,15 +655,13 @@ int
tunioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
{
struct tun_softc *tp;
- int s, error = 0;
+ int error = 0;
- s = splnet();
tp = tun_find_unit(dev);
/* interface was "destroyed" already */
if (tp == NULL) {
- error = ENXIO;
- goto out_nolock;
+ return ENXIO;
}
switch (cmd) {
@@ -757,8 +748,7 @@ tunioctl(dev_t dev, u_long cmd, void *da
out:
mutex_exit(&tp->tun_lock);
-out_nolock:
- splx(s);
+
return error;
}
@@ -772,18 +762,15 @@ tunread(dev_t dev, struct uio *uio, int
struct tun_softc *tp;
struct ifnet *ifp;
struct mbuf *m, *m0;
- int error = 0, len, s, index;
+ int error = 0, len;
- s = splnet();
tp = tun_find_unit(dev);
/* interface was "destroyed" already */
if (tp == NULL) {
- error = ENXIO;
- goto out_nolock;
+ return ENXIO;
}
- index = tp->tun_if.if_index;
ifp = &tp->tun_if;
TUNDEBUG ("%s: read\n", ifp->if_xname);
@@ -803,32 +790,14 @@ tunread(dev_t dev, struct uio *uio, int
goto out;
}
tp->tun_flags |= TUN_RWAIT;
- if (mtsleep((void *)tp, PZERO|PCATCH|PNORELOCK,
- "tunread", 0, &tp->tun_lock) != 0) {
+ if (cv_wait_sig(&tp->tun_cv, &tp->tun_lock)) {
error = EINTR;
- goto out_nolock;
- } else {
- /*
- * Maybe the interface was destroyed while
- * we were sleeping, so let's ensure that
- * we're looking at the same (valid) tun
- * interface before looping.
- */
- tp = tun_find_unit(dev);
- if (tp == NULL) {
- error = ENXIO;
- goto out_nolock;
- }
- if (tp->tun_if.if_index != index) {
- error = ENXIO;
- goto out;
- }
+ goto out;
}
}
} while (m0 == 0);
mutex_exit(&tp->tun_lock);
- splx(s);
/* Copy the mbuf chain */
while (m0 && uio->uio_resid > 0 && error == 0) {
@@ -849,8 +818,7 @@ tunread(dev_t dev, struct uio *uio, int
out:
mutex_exit(&tp->tun_lock);
-out_nolock:
- splx(s);
+
return error;
}
@@ -865,21 +833,17 @@ tunwrite(dev_t dev, struct uio *uio, int
struct mbuf *top, **mp, *m;
pktqueue_t *pktq;
struct sockaddr dst;
- int error = 0, s, tlen, mlen;
+ int error = 0, tlen, mlen;
uint32_t family;
- s = splnet();
tp = tun_find_unit(dev);
-
- /* interface was "destroyed" already */
if (tp == NULL) {
- error = ENXIO;
- goto out_nolock;
+ /* Interface was "destroyed" already. */
+ return ENXIO;
}
/* Unlock until we've got the data */
mutex_exit(&tp->tun_lock);
- splx(s);
ifp = &tp->tun_if;
@@ -893,12 +857,14 @@ tunwrite(dev_t dev, struct uio *uio, int
error = uiomove((void *)&dst, sizeof(dst), uio);
if (dst.sa_len > sizeof(dst)) {
/* Duh.. */
- char discard;
int n = dst.sa_len - sizeof(dst);
- while (n--)
- if ((error = uiomove(&discard, 1, uio)) != 0) {
+ while (n--) {
+ char discard;
+ error = uiomove(&discard, 1, uio);
+ if (error) {
goto out0;
}
+ }
}
} else if (tp->tun_flags & TUN_IFHEAD) {
if (uio->uio_resid < sizeof(family)){
@@ -941,8 +907,7 @@ tunwrite(dev_t dev, struct uio *uio, int
/* get a header mbuf */
MGETHDR(m, M_DONTWAIT, MT_DATA);
if (m == NULL) {
- error = ENOBUFS;
- goto out0;
+ return ENOBUFS;
}
mlen = MHLEN;
@@ -964,7 +929,7 @@ tunwrite(dev_t dev, struct uio *uio, int
}
if (error) {
if (top != NULL)
- m_freem (top);
+ m_freem(top);
ifp->if_ierrors++;
goto out0;
}
@@ -974,7 +939,6 @@ tunwrite(dev_t dev, struct uio *uio, int
bpf_mtap_af(ifp, dst.sa_family, top);
- s = splnet();
mutex_enter(&tp->tun_lock);
if ((tp->tun_flags & TUN_INITED) == 0) {
/* Interface was destroyed */
@@ -986,14 +950,12 @@ tunwrite(dev_t dev, struct uio *uio, int
mutex_exit(&tp->tun_lock);
error = ENOBUFS;
m_freem(top);
- goto out_nolock;
+ goto out0;
}
ifp->if_ipackets++;
ifp->if_ibytes += tlen;
out:
mutex_exit(&tp->tun_lock);
-out_nolock:
- splx(s);
out0:
return error;
}
@@ -1004,8 +966,6 @@ out0:
* when the interface queue is rate-limited by ALTQ or TBR,
* if_start is needed to drain packets from the queue in order
* to notify readers when outgoing packets become ready.
- *
- * Should be called at splnet.
*/
static void
tunstart(struct ifnet *ifp)
@@ -1019,7 +979,7 @@ tunstart(struct ifnet *ifp)
if (!IF_IS_EMPTY(&ifp->if_snd)) {
if (tp->tun_flags & TUN_RWAIT) {
tp->tun_flags &= ~TUN_RWAIT;
- wakeup((void *)tp);
+ cv_broadcast(&tp->tun_cv);
}
if (tp->tun_flags & TUN_ASYNC && tp->tun_pgid)
softint_schedule(tp->tun_osih);
@@ -1039,15 +999,13 @@ tunpoll(dev_t dev, int events, struct lw
{
struct tun_softc *tp;
struct ifnet *ifp;
- int s, revents = 0;
+ int revents = 0;
- s = splnet();
tp = tun_find_unit(dev);
-
- /* interface was "destroyed" already */
- if (tp == NULL)
- goto out_nolock;
-
+ if (tp == NULL) {
+ /* Interface was "destroyed" already. */
+ return 0;
+ }
ifp = &tp->tun_if;
TUNDEBUG("%s: tunpoll\n", ifp->if_xname);
@@ -1067,8 +1025,7 @@ tunpoll(dev_t dev, int events, struct lw
revents |= events & (POLLOUT | POLLWRNORM);
mutex_exit(&tp->tun_lock);
-out_nolock:
- splx(s);
+
return revents;
}
@@ -1076,11 +1033,10 @@ static void
filt_tunrdetach(struct knote *kn)
{
struct tun_softc *tp = kn->kn_hook;
- int s;
- s = splnet();
+ mutex_enter(&tp->tun_lock);
SLIST_REMOVE(&tp->tun_rsel.sel_klist, kn, knote, kn_selnext);
- splx(s);
+ mutex_exit(&tp->tun_lock);
}
static int
@@ -1089,19 +1045,19 @@ filt_tunread(struct knote *kn, long hint
struct tun_softc *tp = kn->kn_hook;
struct ifnet *ifp = &tp->tun_if;
struct mbuf *m;
- int s;
- s = splnet();
+ mutex_enter(&tp->tun_lock);
IF_POLL(&ifp->if_snd, m);
if (m == NULL) {
- splx(s);
+ mutex_exit(&tp->tun_lock);
return 0;
}
for (kn->kn_data = 0; m != NULL; m = m->m_next)
kn->kn_data += m->m_len;
- splx(s);
+ mutex_exit(&tp->tun_lock);
+
return 1;
}
@@ -1116,9 +1072,8 @@ tunkqfilter(dev_t dev, struct knote *kn)
{
struct tun_softc *tp;
struct klist *klist;
- int rv = 0, s;
+ int rv = 0;
- s = splnet();
tp = tun_find_unit(dev);
if (tp == NULL)
goto out_nolock;
@@ -1146,7 +1101,6 @@ tunkqfilter(dev_t dev, struct knote *kn)
out:
mutex_exit(&tp->tun_lock);
out_nolock:
- splx(s);
return rv;
}
Index: src/sys/net/if_tun.h
diff -u src/sys/net/if_tun.h:1.19 src/sys/net/if_tun.h:1.20
--- src/sys/net/if_tun.h:1.19 Sun Sep 6 06:01:01 2015
+++ src/sys/net/if_tun.h Thu Jan 26 21:13:19 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: if_tun.h,v 1.19 2015/09/06 06:01:01 dholland Exp $ */
+/* $NetBSD: if_tun.h,v 1.20 2017/01/26 21:13:19 skrll Exp $ */
/*
* Copyright (c) 1988, Julian Onions <[email protected]>
@@ -44,6 +44,7 @@ struct tun_softc {
struct selinfo tun_wsel; /* write select (not used) */
int tun_unit; /* the tunnel unit number */
kmutex_t tun_lock; /* lock for this tunnel */
+ kcondvar_t tun_cv; /* condition variable for tunnel */
LIST_ENTRY(tun_softc) tun_list; /* list of all tuns */
void *tun_osih; /* soft interrupt handle */
void *tun_isih; /* soft interrupt handle */