1
|
diff --git a/sys/net/if_tun.c b/sys/net/if_tun.c
|
2
|
index f44bc0e..dd7853f 100644
|
3
|
--- a/sys/net/if_tun.c
|
4
|
+++ b/sys/net/if_tun.c
|
5
|
@@ -52,6 +52,7 @@
|
6
|
#include <net/vnet.h>
|
7
|
#ifdef INET
|
8
|
#include <netinet/in.h>
|
9
|
+#include <netinet/ip.h>
|
10
|
#endif
|
11
|
#include <net/bpf.h>
|
12
|
#include <net/if_tun.h>
|
13
|
@@ -110,6 +111,7 @@ static const char tunname[] = "tun";
|
14
|
static MALLOC_DEFINE(M_TUN, tunname, "Tunnel Interface");
|
15
|
static int tundebug = 0;
|
16
|
static int tundclone = 1;
|
17
|
+static int tundispatch = 1;
|
18
|
static struct clonedevs *tunclones;
|
19
|
static TAILQ_HEAD(,tun_softc) tunhead = TAILQ_HEAD_INITIALIZER(tunhead);
|
20
|
SYSCTL_INT(_debug, OID_AUTO, if_tun_debug, CTLFLAG_RW, &tundebug, 0, "");
|
21
|
@@ -119,6 +121,8 @@ static SYSCTL_NODE(_net_link, OID_AUTO, tun, CTLFLAG_RW, 0,
|
22
|
"IP tunnel software network interface.");
|
23
|
SYSCTL_INT(_net_link_tun, OID_AUTO, devfs_cloning, CTLFLAG_RW, &tundclone, 0,
|
24
|
"Enable legacy devfs interface creation.");
|
25
|
+SYSCTL_INT(_net_link_tun, OID_AUTO, tun_dispatching, CTLFLAG_RW, &tundispatch, 0,
|
26
|
+ "Queue rather than direct dispatch on write.");
|
27
|
|
28
|
TUNABLE_INT("net.link.tun.devfs_cloning", &tundclone);
|
29
|
|
30
|
@@ -327,31 +331,28 @@ static void
|
31
|
tunstart(struct ifnet *ifp)
|
32
|
{
|
33
|
struct tun_softc *tp = ifp->if_softc;
|
34
|
- struct mbuf *m;
|
35
|
|
36
|
TUNDEBUG(ifp,"%s starting\n", ifp->if_xname);
|
37
|
- if (ALTQ_IS_ENABLED(&ifp->if_snd)) {
|
38
|
- IFQ_LOCK(&ifp->if_snd);
|
39
|
- IFQ_POLL_NOLOCK(&ifp->if_snd, m);
|
40
|
- if (m == NULL) {
|
41
|
- IFQ_UNLOCK(&ifp->if_snd);
|
42
|
- return;
|
43
|
- }
|
44
|
- IFQ_UNLOCK(&ifp->if_snd);
|
45
|
- }
|
46
|
+ if (IFQ_IS_EMPTY(&ifp->if_snd))
|
47
|
+ return;
|
48
|
+
|
49
|
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
|
50
|
|
51
|
- mtx_lock(&tp->tun_mtx);
|
52
|
if (tp->tun_flags & TUN_RWAIT) {
|
53
|
tp->tun_flags &= ~TUN_RWAIT;
|
54
|
wakeup(tp);
|
55
|
}
|
56
|
- selwakeuppri(&tp->tun_rsel, PZERO + 1);
|
57
|
- KNOTE_LOCKED(&tp->tun_rsel.si_note, 0);
|
58
|
- if (tp->tun_flags & TUN_ASYNC && tp->tun_sigio) {
|
59
|
+ if (!TAILQ_EMPTY(&tp->tun_rsel.si_tdlist))
|
60
|
+ selwakeuppri(&tp->tun_rsel, PZERO + 1);
|
61
|
+ if (!KNLIST_EMPTY(&tp->tun_rsel.si_note)) {
|
62
|
+ mtx_lock(&tp->tun_mtx);
|
63
|
+ KNOTE_LOCKED(&tp->tun_rsel.si_note, 0);
|
64
|
mtx_unlock(&tp->tun_mtx);
|
65
|
+ }
|
66
|
+ if (tp->tun_flags & TUN_ASYNC && tp->tun_sigio)
|
67
|
pgsigio(&tp->tun_sigio, SIGIO, 0);
|
68
|
- } else
|
69
|
- mtx_unlock(&tp->tun_mtx);
|
70
|
+
|
71
|
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
72
|
}
|
73
|
|
74
|
/* XXX: should return an error code so it can fail. */
|
75
|
@@ -589,9 +590,7 @@ tunoutput(struct ifnet *ifp, struct mbuf *m0, const struct sockaddr *dst,
|
76
|
#endif
|
77
|
|
78
|
/* Could be unlocked read? */
|
79
|
- mtx_lock(&tp->tun_mtx);
|
80
|
cached_tun_flags = tp->tun_flags;
|
81
|
- mtx_unlock(&tp->tun_mtx);
|
82
|
if ((cached_tun_flags & TUN_READY) != TUN_READY) {
|
83
|
TUNDEBUG (ifp, "not ready 0%o\n", tp->tun_flags);
|
84
|
m_freem (m0);
|
85
|
@@ -798,9 +797,7 @@ tunread(struct cdev *dev, struct uio *uio, int flag)
|
86
|
int error=0, len;
|
87
|
|
88
|
TUNDEBUG (ifp, "read\n");
|
89
|
- mtx_lock(&tp->tun_mtx);
|
90
|
if ((tp->tun_flags & TUN_READY) != TUN_READY) {
|
91
|
- mtx_unlock(&tp->tun_mtx);
|
92
|
TUNDEBUG (ifp, "not ready 0%o\n", tp->tun_flags);
|
93
|
return (EHOSTDOWN);
|
94
|
}
|
95
|
@@ -811,19 +808,19 @@ tunread(struct cdev *dev, struct uio *uio, int flag)
|
96
|
IFQ_DEQUEUE(&ifp->if_snd, m);
|
97
|
if (m == NULL) {
|
98
|
if (flag & O_NONBLOCK) {
|
99
|
- mtx_unlock(&tp->tun_mtx);
|
100
|
return (EWOULDBLOCK);
|
101
|
}
|
102
|
+ mtx_lock(&tp->tun_mtx);
|
103
|
tp->tun_flags |= TUN_RWAIT;
|
104
|
error = mtx_sleep(tp, &tp->tun_mtx, PCATCH | (PZERO + 1),
|
105
|
"tunread", 0);
|
106
|
+ tp->tun_flags &= ~TUN_RWAIT;
|
107
|
+ mtx_unlock(&tp->tun_mtx);
|
108
|
if (error != 0) {
|
109
|
- mtx_unlock(&tp->tun_mtx);
|
110
|
return (error);
|
111
|
}
|
112
|
}
|
113
|
} while (m == NULL);
|
114
|
- mtx_unlock(&tp->tun_mtx);
|
115
|
|
116
|
while (m && uio->uio_resid > 0 && error == 0) {
|
117
|
len = min(uio->uio_resid, m->m_len);
|
118
|
@@ -848,6 +845,7 @@ tunwrite(struct cdev *dev, struct uio *uio, int flag)
|
119
|
struct tun_softc *tp = dev->si_drv1;
|
120
|
struct ifnet *ifp = TUN2IFP(tp);
|
121
|
struct mbuf *m;
|
122
|
+ struct ip *ip;
|
123
|
uint32_t family;
|
124
|
int isr;
|
125
|
|
126
|
@@ -875,18 +873,26 @@ tunwrite(struct cdev *dev, struct uio *uio, int flag)
|
127
|
mac_ifnet_create_mbuf(ifp, m);
|
128
|
#endif
|
129
|
|
130
|
- /* Could be unlocked read? */
|
131
|
- mtx_lock(&tp->tun_mtx);
|
132
|
+ /* XXX: unlocked read? */
|
133
|
if (tp->tun_flags & TUN_IFHEAD) {
|
134
|
- mtx_unlock(&tp->tun_mtx);
|
135
|
if (m->m_len < sizeof(family) &&
|
136
|
(m = m_pullup(m, sizeof(family))) == NULL)
|
137
|
return (ENOBUFS);
|
138
|
family = ntohl(*mtod(m, u_int32_t *));
|
139
|
m_adj(m, sizeof(family));
|
140
|
} else {
|
141
|
- mtx_unlock(&tp->tun_mtx);
|
142
|
- family = AF_INET;
|
143
|
+ if (m->m_len < sizeof(struct ip) &&
|
144
|
+ (m = m_pullup(m, sizeof(struct ip))) == NULL)
|
145
|
+ return (ENOBUFS);
|
146
|
+ ip = mtod(m, struct ip *);
|
147
|
+ if (ip->ip_v == IPVERSION)
|
148
|
+ family = AF_INET;
|
149
|
+ else if (ip->ip_v == AF_INET6)
|
150
|
+ family = AF_INET6;
|
151
|
+ else {
|
152
|
+ m_freem(m);
|
153
|
+ return (EINVAL);
|
154
|
+ }
|
155
|
}
|
156
|
|
157
|
BPF_MTAP2(ifp, &family, sizeof(family), m);
|
158
|
@@ -922,7 +928,10 @@ tunwrite(struct cdev *dev, struct uio *uio, int flag)
|
159
|
ifp->if_ipackets++;
|
160
|
CURVNET_SET(ifp->if_vnet);
|
161
|
M_SETFIB(m, ifp->if_fib);
|
162
|
- netisr_dispatch(isr, m);
|
163
|
+ if (tundispatch)
|
164
|
+ netisr_queue(isr, m);
|
165
|
+ else
|
166
|
+ netisr_dispatch(isr, m);
|
167
|
CURVNET_RESTORE();
|
168
|
return (0);
|
169
|
}
|
170
|
@@ -938,21 +947,17 @@ tunpoll(struct cdev *dev, int events, struct thread *td)
|
171
|
struct tun_softc *tp = dev->si_drv1;
|
172
|
struct ifnet *ifp = TUN2IFP(tp);
|
173
|
int revents = 0;
|
174
|
- struct mbuf *m;
|
175
|
|
176
|
TUNDEBUG(ifp, "tunpoll\n");
|
177
|
|
178
|
if (events & (POLLIN | POLLRDNORM)) {
|
179
|
- IFQ_LOCK(&ifp->if_snd);
|
180
|
- IFQ_POLL_NOLOCK(&ifp->if_snd, m);
|
181
|
- if (m != NULL) {
|
182
|
- TUNDEBUG(ifp, "tunpoll q=%d\n", ifp->if_snd.ifq_len);
|
183
|
- revents |= events & (POLLIN | POLLRDNORM);
|
184
|
- } else {
|
185
|
+ if (IFQ_IS_EMPTY(&ifp->if_snd)) {
|
186
|
TUNDEBUG(ifp, "tunpoll waiting\n");
|
187
|
selrecord(td, &tp->tun_rsel);
|
188
|
+ } else {
|
189
|
+ TUNDEBUG(ifp, "tunpoll q=%d\n", ifp->if_snd.ifq_len);
|
190
|
+ revents |= events & (POLLIN | POLLRDNORM);
|
191
|
}
|
192
|
- IFQ_UNLOCK(&ifp->if_snd);
|
193
|
}
|
194
|
if (events & (POLLOUT | POLLWRNORM))
|
195
|
revents |= events & (POLLOUT | POLLWRNORM);
|