Tue May 26 19:03:05 2009 UTC ()
Filter out ENETRESET from ether_ioctl() since we aren't interested
in multicast hugging.


(pooka)
diff -r1.6 -r1.7 src/sys/rump/net/lib/libshmif/if_shmem.c
diff -r1.8 -r1.9 src/sys/rump/net/lib/libvirtif/if_virt.c

cvs diff -r1.6 -r1.7 src/sys/rump/net/lib/libshmif/if_shmem.c (switch to unified diff)

--- src/sys/rump/net/lib/libshmif/if_shmem.c 2009/04/06 20:41:29 1.6
+++ src/sys/rump/net/lib/libshmif/if_shmem.c 2009/05/26 19:03:05 1.7
@@ -1,384 +1,386 @@ @@ -1,384 +1,386 @@
1/* $NetBSD: if_shmem.c,v 1.6 2009/04/06 20:41:29 pooka Exp $ */ 1/* $NetBSD: if_shmem.c,v 1.7 2009/05/26 19:03:05 pooka Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2009 Antti Kantee. All Rights Reserved. 4 * Copyright (c) 2009 Antti Kantee. All Rights Reserved.
5 * 5 *
6 * Development of this software was supported by The Nokia Foundation. 6 * Development of this software was supported by The Nokia Foundation.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
10 * are met: 10 * are met:
11 * 1. Redistributions of source code must retain the above copyright 11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer. 12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright 13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the 14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution. 15 * documentation and/or other materials provided with the distribution.
16 * 16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
18 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE. 27 * SUCH DAMAGE.
28 */ 28 */
29 29
30#include <sys/cdefs.h> 30#include <sys/cdefs.h>
31__KERNEL_RCSID(0, "$NetBSD: if_shmem.c,v 1.6 2009/04/06 20:41:29 pooka Exp $"); 31__KERNEL_RCSID(0, "$NetBSD: if_shmem.c,v 1.7 2009/05/26 19:03:05 pooka Exp $");
32 32
33#include <sys/param.h> 33#include <sys/param.h>
34#include <sys/fcntl.h> 34#include <sys/fcntl.h>
35#include <sys/kmem.h> 35#include <sys/kmem.h>
36#include <sys/kthread.h> 36#include <sys/kthread.h>
37#include <sys/lock.h> 37#include <sys/lock.h>
38#include <sys/atomic.h> 38#include <sys/atomic.h>
39 39
40#include <net/if.h> 40#include <net/if.h>
41#include <net/if_ether.h> 41#include <net/if_ether.h>
42 42
43#include <netinet/in.h> 43#include <netinet/in.h>
44#include <netinet/in_var.h> 44#include <netinet/in_var.h>
45 45
46#include <rump/rump.h> 46#include <rump/rump.h>
47#include <rump/rumpuser.h> 47#include <rump/rumpuser.h>
48 48
49#include "rump_private.h" 49#include "rump_private.h"
50 50
51#if 0 51#if 0
52#define DPRINTF(x) printf x 52#define DPRINTF(x) printf x
53#else 53#else
54#define DPRINTF(x) 54#define DPRINTF(x)
55#endif 55#endif
56 56
57/* 57/*
58 * A virtual ethernet interface which uses shared memory from a 58 * A virtual ethernet interface which uses shared memory from a
59 * memory mapped file as the bus. 59 * memory mapped file as the bus.
60 */ 60 */
61 61
62static int shmif_init(struct ifnet *); 62static int shmif_init(struct ifnet *);
63static int shmif_ioctl(struct ifnet *, u_long, void *); 63static int shmif_ioctl(struct ifnet *, u_long, void *);
64static void shmif_start(struct ifnet *); 64static void shmif_start(struct ifnet *);
65static void shmif_stop(struct ifnet *, int); 65static void shmif_stop(struct ifnet *, int);
66 66
67struct shmif_sc { 67struct shmif_sc {
68 struct ethercom sc_ec; 68 struct ethercom sc_ec;
69 uint8_t sc_myaddr[6]; 69 uint8_t sc_myaddr[6];
70 uint8_t *sc_busmem; 70 uint8_t *sc_busmem;
71 int sc_memfd; 71 int sc_memfd;
72 int sc_kq; 72 int sc_kq;
73 73
74 uint32_t sc_nextpacket; 74 uint32_t sc_nextpacket;
75 uint32_t sc_prevgen; 75 uint32_t sc_prevgen;
76}; 76};
77#define IFMEM_LOCK (0) 77#define IFMEM_LOCK (0)
78#define IFMEM_GENERATION (8) 78#define IFMEM_GENERATION (8)
79#define IFMEM_LASTPACKET (12) 79#define IFMEM_LASTPACKET (12)
80#define IFMEM_WAKEUP (16) 80#define IFMEM_WAKEUP (16)
81#define IFMEM_DATA (20) 81#define IFMEM_DATA (20)
82 82
83#define BUSCTRL_ATOFF(sc, off) ((uint32_t *)(sc->sc_busmem+(off))) 83#define BUSCTRL_ATOFF(sc, off) ((uint32_t *)(sc->sc_busmem+(off)))
84 84
85#define BUSMEM_SIZE 65536 /* enough? */ 85#define BUSMEM_SIZE 65536 /* enough? */
86 86
87static void shmif_rcv(void *); 87static void shmif_rcv(void *);
88 88
89static uint32_t numif; 89static uint32_t numif;
90 90
91/* 91/*
92 * This locking needs work and will misbehave severely if: 92 * This locking needs work and will misbehave severely if:
93 * 1) the backing memory has to be paged in 93 * 1) the backing memory has to be paged in
94 * 2) some lockholder exits while holding the lock 94 * 2) some lockholder exits while holding the lock
95 */ 95 */
96static void 96static void
97lockbus(struct shmif_sc *sc) 97lockbus(struct shmif_sc *sc)
98{ 98{
99 99
100 __cpu_simple_lock((__cpu_simple_lock_t *)sc->sc_busmem); 100 __cpu_simple_lock((__cpu_simple_lock_t *)sc->sc_busmem);
101} 101}
102 102
103static void 103static void
104unlockbus(struct shmif_sc *sc) 104unlockbus(struct shmif_sc *sc)
105{ 105{
106 106
107 __cpu_simple_unlock((__cpu_simple_lock_t *)sc->sc_busmem); 107 __cpu_simple_unlock((__cpu_simple_lock_t *)sc->sc_busmem);
108} 108}
109 109
110static uint32_t 110static uint32_t
111busread(struct shmif_sc *sc, void *dest, uint32_t off, size_t len) 111busread(struct shmif_sc *sc, void *dest, uint32_t off, size_t len)
112{ 112{
113 size_t chunk; 113 size_t chunk;
114 114
115 KASSERT(len < (BUSMEM_SIZE - IFMEM_DATA) && off <= BUSMEM_SIZE); 115 KASSERT(len < (BUSMEM_SIZE - IFMEM_DATA) && off <= BUSMEM_SIZE);
116 chunk = MIN(len, BUSMEM_SIZE - off); 116 chunk = MIN(len, BUSMEM_SIZE - off);
117 memcpy(dest, sc->sc_busmem + off, chunk); 117 memcpy(dest, sc->sc_busmem + off, chunk);
118 len -= chunk; 118 len -= chunk;
119 119
120 if (len == 0) 120 if (len == 0)
121 return off + chunk; 121 return off + chunk;
122 122
123 /* else, wraps around */ 123 /* else, wraps around */
124 off = IFMEM_DATA; 124 off = IFMEM_DATA;
125 sc->sc_prevgen = *BUSCTRL_ATOFF(sc, IFMEM_GENERATION); 125 sc->sc_prevgen = *BUSCTRL_ATOFF(sc, IFMEM_GENERATION);
126 126
127 /* finish reading */ 127 /* finish reading */
128 memcpy((uint8_t *)dest + chunk, sc->sc_busmem + off, len); 128 memcpy((uint8_t *)dest + chunk, sc->sc_busmem + off, len);
129 return off + len; 129 return off + len;
130} 130}
131 131
132static uint32_t 132static uint32_t
133buswrite(struct shmif_sc *sc, uint32_t off, void *data, size_t len) 133buswrite(struct shmif_sc *sc, uint32_t off, void *data, size_t len)
134{ 134{
135 size_t chunk; 135 size_t chunk;
136 136
137 KASSERT(len < (BUSMEM_SIZE - IFMEM_DATA) && off <= BUSMEM_SIZE); 137 KASSERT(len < (BUSMEM_SIZE - IFMEM_DATA) && off <= BUSMEM_SIZE);
138 138
139 chunk = MIN(len, BUSMEM_SIZE - off); 139 chunk = MIN(len, BUSMEM_SIZE - off);
140 memcpy(sc->sc_busmem + off, data, chunk); 140 memcpy(sc->sc_busmem + off, data, chunk);
141 len -= chunk; 141 len -= chunk;
142 142
143 if (len == 0) 143 if (len == 0)
144 return off + chunk; 144 return off + chunk;
145 145
146 DPRINTF(("buswrite wrap: wrote %d bytes to %d, left %d to %d", 146 DPRINTF(("buswrite wrap: wrote %d bytes to %d, left %d to %d",
147 chunk, off, len, IFMEM_DATA)); 147 chunk, off, len, IFMEM_DATA));
148 148
149 /* else, wraps around */ 149 /* else, wraps around */
150 off = IFMEM_DATA; 150 off = IFMEM_DATA;
151 (*BUSCTRL_ATOFF(sc, IFMEM_GENERATION))++; 151 (*BUSCTRL_ATOFF(sc, IFMEM_GENERATION))++;
152 sc->sc_prevgen = *BUSCTRL_ATOFF(sc, IFMEM_GENERATION); 152 sc->sc_prevgen = *BUSCTRL_ATOFF(sc, IFMEM_GENERATION);
153 153
154 /* finish writing */ 154 /* finish writing */
155 memcpy(sc->sc_busmem + off, (uint8_t *)data + chunk, len); 155 memcpy(sc->sc_busmem + off, (uint8_t *)data + chunk, len);
156 return off + len; 156 return off + len;
157} 157}
158 158
159static inline uint32_t 159static inline uint32_t
160advance(uint32_t oldoff, uint32_t delta) 160advance(uint32_t oldoff, uint32_t delta)
161{ 161{
162 uint32_t newoff; 162 uint32_t newoff;
163 163
164 newoff = oldoff + delta; 164 newoff = oldoff + delta;
165 if (newoff >= BUSMEM_SIZE) 165 if (newoff >= BUSMEM_SIZE)
166 newoff -= (BUSMEM_SIZE - IFMEM_DATA); 166 newoff -= (BUSMEM_SIZE - IFMEM_DATA);
167 return newoff; 167 return newoff;
168 168
169} 169}
170 170
171static uint32_t 171static uint32_t
172nextpktoff(struct shmif_sc *sc, uint32_t oldoff) 172nextpktoff(struct shmif_sc *sc, uint32_t oldoff)
173{ 173{
174 uint32_t oldlen; 174 uint32_t oldlen;
175 175
176 busread(sc, &oldlen, oldoff, 4); 176 busread(sc, &oldlen, oldoff, 4);
177 KASSERT(oldlen < BUSMEM_SIZE - IFMEM_DATA); 177 KASSERT(oldlen < BUSMEM_SIZE - IFMEM_DATA);
178 178
179 return advance(oldoff, 4 + oldlen); 179 return advance(oldoff, 4 + oldlen);
180} 180}
181 181
182int rump_shmif_create(const char *, int *); /* XXX */ 182int rump_shmif_create(const char *, int *); /* XXX */
183 183
184int 184int
185rump_shmif_create(const char *path, int *ifnum) 185rump_shmif_create(const char *path, int *ifnum)
186{ 186{
187 struct shmif_sc *sc; 187 struct shmif_sc *sc;
188 struct ifnet *ifp; 188 struct ifnet *ifp;
189 uint8_t enaddr[ETHER_ADDR_LEN] = { 0xb2, 0xa0, 0x00, 0x00, 0x00, 0x00 }; 189 uint8_t enaddr[ETHER_ADDR_LEN] = { 0xb2, 0xa0, 0x00, 0x00, 0x00, 0x00 };
190 uint32_t randnum; 190 uint32_t randnum;
191 unsigned mynum; 191 unsigned mynum;
192 int error; 192 int error;
193 193
194 randnum = arc4random(); 194 randnum = arc4random();
195 memcpy(&enaddr[2], &randnum, 4); 195 memcpy(&enaddr[2], &randnum, 4);
196 mynum = atomic_inc_uint_nv(&numif)-1; 196 mynum = atomic_inc_uint_nv(&numif)-1;
197 197
198 sc = kmem_zalloc(sizeof(*sc), KM_SLEEP); 198 sc = kmem_zalloc(sizeof(*sc), KM_SLEEP);
199 ifp = &sc->sc_ec.ec_if; 199 ifp = &sc->sc_ec.ec_if;
200 memcpy(sc->sc_myaddr, enaddr, sizeof(enaddr)); 200 memcpy(sc->sc_myaddr, enaddr, sizeof(enaddr));
201 201
202 sc->sc_memfd = rumpuser_open(path, O_RDWR | O_CREAT, &error); 202 sc->sc_memfd = rumpuser_open(path, O_RDWR | O_CREAT, &error);
203 if (sc->sc_memfd == -1) 203 if (sc->sc_memfd == -1)
204 goto fail; 204 goto fail;
205 sc->sc_busmem = rumpuser_filemmap(sc->sc_memfd, 0, BUSMEM_SIZE, 205 sc->sc_busmem = rumpuser_filemmap(sc->sc_memfd, 0, BUSMEM_SIZE,
206 RUMPUSER_FILEMMAP_TRUNCATE | RUMPUSER_FILEMMAP_SHARED 206 RUMPUSER_FILEMMAP_TRUNCATE | RUMPUSER_FILEMMAP_SHARED
207 | RUMPUSER_FILEMMAP_READ | RUMPUSER_FILEMMAP_WRITE, &error); 207 | RUMPUSER_FILEMMAP_READ | RUMPUSER_FILEMMAP_WRITE, &error);
208 if (error) 208 if (error)
209 goto fail; 209 goto fail;
210 210
211 lockbus(sc); 211 lockbus(sc);
212 if (*BUSCTRL_ATOFF(sc, IFMEM_LASTPACKET) == 0) 212 if (*BUSCTRL_ATOFF(sc, IFMEM_LASTPACKET) == 0)
213 *BUSCTRL_ATOFF(sc, IFMEM_LASTPACKET) = IFMEM_DATA; 213 *BUSCTRL_ATOFF(sc, IFMEM_LASTPACKET) = IFMEM_DATA;
214 sc->sc_nextpacket = *BUSCTRL_ATOFF(sc, IFMEM_LASTPACKET); 214 sc->sc_nextpacket = *BUSCTRL_ATOFF(sc, IFMEM_LASTPACKET);
215 sc->sc_prevgen = *BUSCTRL_ATOFF(sc, IFMEM_GENERATION); 215 sc->sc_prevgen = *BUSCTRL_ATOFF(sc, IFMEM_GENERATION);
216 unlockbus(sc); 216 unlockbus(sc);
217 217
218 sc->sc_kq = rumpuser_writewatchfile_setup(-1, sc->sc_memfd, 0, &error); 218 sc->sc_kq = rumpuser_writewatchfile_setup(-1, sc->sc_memfd, 0, &error);
219 if (sc->sc_kq == -1) 219 if (sc->sc_kq == -1)
220 goto fail; 220 goto fail;
221 221
222 sprintf(ifp->if_xname, "shmif%d", mynum); 222 sprintf(ifp->if_xname, "shmif%d", mynum);
223 ifp->if_softc = sc; 223 ifp->if_softc = sc;
224 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 224 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
225 ifp->if_init = shmif_init; 225 ifp->if_init = shmif_init;
226 ifp->if_ioctl = shmif_ioctl; 226 ifp->if_ioctl = shmif_ioctl;
227 ifp->if_start = shmif_start; 227 ifp->if_start = shmif_start;
228 ifp->if_stop = shmif_stop; 228 ifp->if_stop = shmif_stop;
229 ifp->if_mtu = 1518; 229 ifp->if_mtu = 1518;
230 230
231 if_attach(ifp); 231 if_attach(ifp);
232 ether_ifattach(ifp, enaddr); 232 ether_ifattach(ifp, enaddr);
233 233
234 if (ifnum) 234 if (ifnum)
235 *ifnum = mynum; 235 *ifnum = mynum;
236 return 0; 236 return 0;
237 237
238 fail: 238 fail:
239 panic("rump_shmemif_create: fixme"); 239 panic("rump_shmemif_create: fixme");
240} 240}
241 241
242static int 242static int
243shmif_init(struct ifnet *ifp) 243shmif_init(struct ifnet *ifp)
244{ 244{
245 int error = 0; 245 int error = 0;
246 246
247 if (rump_threads) { 247 if (rump_threads) {
248 error = kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL, 248 error = kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL,
249 shmif_rcv, ifp, NULL, "shmif"); 249 shmif_rcv, ifp, NULL, "shmif");
250 } else { 250 } else {
251 printf("WARNING: threads not enabled, shmif NOT working\n"); 251 printf("WARNING: threads not enabled, shmif NOT working\n");
252 } 252 }
253 253
254 ifp->if_flags |= IFF_RUNNING; 254 ifp->if_flags |= IFF_RUNNING;
255 return error; 255 return error;
256} 256}
257 257
258static int 258static int
259shmif_ioctl(struct ifnet *ifp, u_long cmd, void *data) 259shmif_ioctl(struct ifnet *ifp, u_long cmd, void *data)
260{ 260{
261 int s, rv; 261 int s, rv;
262 262
263 s = splnet(); 263 s = splnet();
264 rv = ether_ioctl(ifp, cmd, data); 264 rv = ether_ioctl(ifp, cmd, data);
 265 if (rv == ENETRESET)
 266 rv = 0;
265 splx(s); 267 splx(s);
266 268
267 return rv; 269 return rv;
268} 270}
269 271
270/* send everything in-context */ 272/* send everything in-context */
271static void 273static void
272shmif_start(struct ifnet *ifp) 274shmif_start(struct ifnet *ifp)
273{ 275{
274 struct shmif_sc *sc = ifp->if_softc; 276 struct shmif_sc *sc = ifp->if_softc;
275 struct mbuf *m, *m0; 277 struct mbuf *m, *m0;
276 uint32_t lastoff, dataoff, npktlenoff; 278 uint32_t lastoff, dataoff, npktlenoff;
277 uint32_t pktsize = 0; 279 uint32_t pktsize = 0;
278 bool wrote = false; 280 bool wrote = false;
279 int error; 281 int error;
280 282
281 for (;;) { 283 for (;;) {
282 IF_DEQUEUE(&ifp->if_snd, m0); 284 IF_DEQUEUE(&ifp->if_snd, m0);
283 if (m0 == NULL) { 285 if (m0 == NULL) {
284 break; 286 break;
285 } 287 }
286 288
287 lockbus(sc); 289 lockbus(sc);
288 lastoff = *BUSCTRL_ATOFF(sc, IFMEM_LASTPACKET); 290 lastoff = *BUSCTRL_ATOFF(sc, IFMEM_LASTPACKET);
289 291
290 npktlenoff = nextpktoff(sc, lastoff); 292 npktlenoff = nextpktoff(sc, lastoff);
291 dataoff = advance(npktlenoff, 4); 293 dataoff = advance(npktlenoff, 4);
292 294
293 for (m = m0; m != NULL; m = m->m_next) { 295 for (m = m0; m != NULL; m = m->m_next) {
294 pktsize += m->m_len; 296 pktsize += m->m_len;
295 dataoff = buswrite(sc, dataoff, mtod(m, void *), 297 dataoff = buswrite(sc, dataoff, mtod(m, void *),
296 m->m_len); 298 m->m_len);
297 } 299 }
298 buswrite(sc, npktlenoff, &pktsize, 4); 300 buswrite(sc, npktlenoff, &pktsize, 4);
299 *BUSCTRL_ATOFF(sc, IFMEM_LASTPACKET) = npktlenoff; 301 *BUSCTRL_ATOFF(sc, IFMEM_LASTPACKET) = npktlenoff;
300 unlockbus(sc); 302 unlockbus(sc);
301 303
302 m_freem(m0); 304 m_freem(m0);
303 wrote = true; 305 wrote = true;
304 306
305 DPRINTF(("shmif_start: send %d bytes at off %d\n", 307 DPRINTF(("shmif_start: send %d bytes at off %d\n",
306 pktsize, npktlenoff)); 308 pktsize, npktlenoff));
307 } 309 }
308 /* wakeup */ 310 /* wakeup */
309 if (wrote) 311 if (wrote)
310 rumpuser_pwrite(sc->sc_memfd, &error, 4, IFMEM_WAKEUP, &error); 312 rumpuser_pwrite(sc->sc_memfd, &error, 4, IFMEM_WAKEUP, &error);
311} 313}
312 314
313static void 315static void
314shmif_stop(struct ifnet *ifp, int disable) 316shmif_stop(struct ifnet *ifp, int disable)
315{ 317{
316 318
317 panic("%s: unimpl", __func__); 319 panic("%s: unimpl", __func__);
318} 320}
319 321
320static void 322static void
321shmif_rcv(void *arg) 323shmif_rcv(void *arg)
322{ 324{
323 struct ifnet *ifp = arg; 325 struct ifnet *ifp = arg;
324 struct shmif_sc *sc = ifp->if_softc; 326 struct shmif_sc *sc = ifp->if_softc;
325 struct mbuf *m = NULL; 327 struct mbuf *m = NULL;
326 struct ether_header *eth; 328 struct ether_header *eth;
327 uint32_t nextpkt, pktlen, lastpkt, busgen, lastnext; 329 uint32_t nextpkt, pktlen, lastpkt, busgen, lastnext;
328 int error; 330 int error;
329 331
330 for (;;) { 332 for (;;) {
331 if (m == NULL) { 333 if (m == NULL) {
332 m = m_gethdr(M_WAIT, MT_DATA); 334 m = m_gethdr(M_WAIT, MT_DATA);
333 MCLGET(m, M_WAIT); 335 MCLGET(m, M_WAIT);
334 } 336 }
335 337
336 DPRINTF(("waiting %d/%d\n", sc->sc_nextpacket, sc->sc_prevgen)); 338 DPRINTF(("waiting %d/%d\n", sc->sc_nextpacket, sc->sc_prevgen));
337 339
338 KASSERT(m->m_flags & M_EXT); 340 KASSERT(m->m_flags & M_EXT);
339 lockbus(sc); 341 lockbus(sc);
340 lastpkt = *BUSCTRL_ATOFF(sc, IFMEM_LASTPACKET); 342 lastpkt = *BUSCTRL_ATOFF(sc, IFMEM_LASTPACKET);
341 busgen = *BUSCTRL_ATOFF(sc, IFMEM_GENERATION); 343 busgen = *BUSCTRL_ATOFF(sc, IFMEM_GENERATION);
342 lastnext = nextpktoff(sc, lastpkt); 344 lastnext = nextpktoff(sc, lastpkt);
343 if ((lastnext > sc->sc_nextpacket && busgen > sc->sc_prevgen) 345 if ((lastnext > sc->sc_nextpacket && busgen > sc->sc_prevgen)
344 || (busgen > sc->sc_prevgen+1)) { 346 || (busgen > sc->sc_prevgen+1)) {
345 nextpkt = lastpkt; 347 nextpkt = lastpkt;
346 sc->sc_prevgen = busgen; 348 sc->sc_prevgen = busgen;
347 printf("DROPPING\n"); 349 printf("DROPPING\n");
348 } else { 350 } else {
349 nextpkt = sc->sc_nextpacket; 351 nextpkt = sc->sc_nextpacket;
350 } 352 }
351 353
352 /* need more data? */ 354 /* need more data? */
353 if (lastnext == nextpkt && sc->sc_prevgen == busgen){ 355 if (lastnext == nextpkt && sc->sc_prevgen == busgen){
354 unlockbus(sc); 356 unlockbus(sc);
355 error = 0; 357 error = 0;
356 rumpuser_writewatchfile_wait(sc->sc_kq, NULL, &error); 358 rumpuser_writewatchfile_wait(sc->sc_kq, NULL, &error);
357 if (__predict_false(error)) 359 if (__predict_false(error))
358 printf("shmif_rcv: wait failed %d\n", error); 360 printf("shmif_rcv: wait failed %d\n", error);
359 continue; 361 continue;
360 } 362 }
361 363
362 busread(sc, &pktlen, nextpkt, 4); 364 busread(sc, &pktlen, nextpkt, 4);
363 busread(sc, mtod(m, void *), advance(nextpkt, 4), pktlen); 365 busread(sc, mtod(m, void *), advance(nextpkt, 4), pktlen);
364 366
365 DPRINTF(("shmif_rcv: read packet of length %d at %d\n", 367 DPRINTF(("shmif_rcv: read packet of length %d at %d\n",
366 pktlen, nextpkt)); 368 pktlen, nextpkt));
367 369
368 sc->sc_nextpacket = nextpktoff(sc, nextpkt); 370 sc->sc_nextpacket = nextpktoff(sc, nextpkt);
369 sc->sc_prevgen = busgen; 371 sc->sc_prevgen = busgen;
370 unlockbus(sc); 372 unlockbus(sc);
371 373
372 m->m_len = m->m_pkthdr.len = pktlen; 374 m->m_len = m->m_pkthdr.len = pktlen;
373 m->m_pkthdr.rcvif = ifp; 375 m->m_pkthdr.rcvif = ifp;
374 376
375 /* if it's to us, don't pass up and reuse storage space */ 377 /* if it's to us, don't pass up and reuse storage space */
376 eth = mtod(m, struct ether_header *); 378 eth = mtod(m, struct ether_header *);
377 if (memcmp(eth->ether_shost, sc->sc_myaddr, 6) != 0) { 379 if (memcmp(eth->ether_shost, sc->sc_myaddr, 6) != 0) {
378 ifp->if_input(ifp, m); 380 ifp->if_input(ifp, m);
379 m = NULL; 381 m = NULL;
380 } 382 }
381 } 383 }
382 384
383 panic("shmif_worker is a lazy boy %d\n", error); 385 panic("shmif_worker is a lazy boy %d\n", error);
384} 386}

cvs diff -r1.8 -r1.9 src/sys/rump/net/lib/libvirtif/if_virt.c (switch to unified diff)

--- src/sys/rump/net/lib/libvirtif/if_virt.c 2009/03/27 13:46:35 1.8
+++ src/sys/rump/net/lib/libvirtif/if_virt.c 2009/05/26 19:03:05 1.9
@@ -1,253 +1,255 @@ @@ -1,253 +1,255 @@
1/* $NetBSD: if_virt.c,v 1.8 2009/03/27 13:46:35 pooka Exp $ */ 1/* $NetBSD: if_virt.c,v 1.9 2009/05/26 19:03:05 pooka Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2008 Antti Kantee. All Rights Reserved. 4 * Copyright (c) 2008 Antti Kantee. All Rights Reserved.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
14 * 14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE. 25 * SUCH DAMAGE.
26 */ 26 */
27 27
28#include <sys/cdefs.h> 28#include <sys/cdefs.h>
29__KERNEL_RCSID(0, "$NetBSD: if_virt.c,v 1.8 2009/03/27 13:46:35 pooka Exp $"); 29__KERNEL_RCSID(0, "$NetBSD: if_virt.c,v 1.9 2009/05/26 19:03:05 pooka Exp $");
30 30
31#include <sys/param.h> 31#include <sys/param.h>
32#include <sys/condvar.h> 32#include <sys/condvar.h>
33#include <sys/fcntl.h> 33#include <sys/fcntl.h>
34#include <sys/kmem.h> 34#include <sys/kmem.h>
35#include <sys/kthread.h> 35#include <sys/kthread.h>
36#include <sys/mutex.h> 36#include <sys/mutex.h>
37#include <sys/sockio.h> 37#include <sys/sockio.h>
38#include <sys/socketvar.h> 38#include <sys/socketvar.h>
39 39
40#include <net/if.h> 40#include <net/if.h>
41#include <net/if_ether.h> 41#include <net/if_ether.h>
42#include <net/if_tap.h> 42#include <net/if_tap.h>
43 43
44#include <netinet/in.h> 44#include <netinet/in.h>
45#include <netinet/in_var.h> 45#include <netinet/in_var.h>
46 46
47#include <rump/rump.h> 47#include <rump/rump.h>
48#include <rump/rumpuser.h> 48#include <rump/rumpuser.h>
49 49
50#include "rump_private.h" 50#include "rump_private.h"
51 51
52/* 52/*
53 * Virtual interface for userspace purposes. Uses tap(4) to 53 * Virtual interface for userspace purposes. Uses tap(4) to
54 * interface with the kernel and just simply shovels data 54 * interface with the kernel and just simply shovels data
55 * to/from /dev/tap. 55 * to/from /dev/tap.
56 */ 56 */
57 57
58#define VIRTIF_BASE "virt" 58#define VIRTIF_BASE "virt"
59 59
60static int virtif_init(struct ifnet *); 60static int virtif_init(struct ifnet *);
61static int virtif_ioctl(struct ifnet *, u_long, void *); 61static int virtif_ioctl(struct ifnet *, u_long, void *);
62static void virtif_start(struct ifnet *); 62static void virtif_start(struct ifnet *);
63static void virtif_stop(struct ifnet *, int); 63static void virtif_stop(struct ifnet *, int);
64 64
65struct virtif_sc { 65struct virtif_sc {
66 struct ethercom sc_ec; 66 struct ethercom sc_ec;
67 int sc_tapfd; 67 int sc_tapfd;
68 kmutex_t sc_sendmtx; 68 kmutex_t sc_sendmtx;
69 kcondvar_t sc_sendcv; 69 kcondvar_t sc_sendcv;
70}; 70};
71 71
72static void virtif_worker(void *); 72static void virtif_worker(void *);
73static void virtif_sender(void *); 73static void virtif_sender(void *);
74 74
75#if 0 75#if 0
76/* 76/*
77 * Create a socket and call ifioctl() to configure the interface. 77 * Create a socket and call ifioctl() to configure the interface.
78 * This trickles down to virtif_ioctl(). 78 * This trickles down to virtif_ioctl().
79 */ 79 */
80static int 80static int
81configaddr(struct ifnet *ifp, struct ifaliasreq *ia) 81configaddr(struct ifnet *ifp, struct ifaliasreq *ia)
82{ 82{
83 struct socket *so; 83 struct socket *so;
84 int error; 84 int error;
85 85
86 strcpy(ia->ifra_name, ifp->if_xname); 86 strcpy(ia->ifra_name, ifp->if_xname);
87 error = socreate(ia->ifra_addr.sa_family, &so, SOCK_DGRAM, 87 error = socreate(ia->ifra_addr.sa_family, &so, SOCK_DGRAM,
88 0, curlwp, NULL); 88 0, curlwp, NULL);
89 if (error) 89 if (error)
90 return error; 90 return error;
91 error = ifioctl(so, SIOCAIFADDR, ia, curlwp); 91 error = ifioctl(so, SIOCAIFADDR, ia, curlwp);
92 soclose(so); 92 soclose(so);
93 93
94 return error; 94 return error;
95} 95}
96#endif 96#endif
97 97
98int 98int
99rump_virtif_create(int num) 99rump_virtif_create(int num)
100{ 100{
101 struct virtif_sc *sc; 101 struct virtif_sc *sc;
102 struct ifnet *ifp; 102 struct ifnet *ifp;
103 uint8_t enaddr[ETHER_ADDR_LEN] = { 0xb2, 0x0a, 0x00, 0x0b, 0x0e, 0x01 }; 103 uint8_t enaddr[ETHER_ADDR_LEN] = { 0xb2, 0x0a, 0x00, 0x0b, 0x0e, 0x01 };
104 char tapdev[16]; 104 char tapdev[16];
105 int fd, error; 105 int fd, error;
106 106
107 snprintf(tapdev, sizeof(tapdev), "/dev/tap%d", num); 107 snprintf(tapdev, sizeof(tapdev), "/dev/tap%d", num);
108 fd = rumpuser_open(tapdev, O_RDWR, &error); 108 fd = rumpuser_open(tapdev, O_RDWR, &error);
109 if (fd == -1) { 109 if (fd == -1) {
110 printf("virtif_create: can't open /dev/tap %d\n", error); 110 printf("virtif_create: can't open /dev/tap %d\n", error);
111 return error; 111 return error;
112 } 112 }
113 KASSERT(num < 0x100); 113 KASSERT(num < 0x100);
114 enaddr[2] = arc4random() & 0xff; 114 enaddr[2] = arc4random() & 0xff;
115 enaddr[5] = num; 115 enaddr[5] = num;
116 116
117 sc = kmem_zalloc(sizeof(*sc), KM_SLEEP); 117 sc = kmem_zalloc(sizeof(*sc), KM_SLEEP);
118 sc->sc_tapfd = fd; 118 sc->sc_tapfd = fd;
119 119
120 ifp = &sc->sc_ec.ec_if; 120 ifp = &sc->sc_ec.ec_if;
121 sprintf(ifp->if_xname, "%s%d", VIRTIF_BASE, num); 121 sprintf(ifp->if_xname, "%s%d", VIRTIF_BASE, num);
122 ifp->if_softc = sc; 122 ifp->if_softc = sc;
123 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 123 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
124 ifp->if_init = virtif_init; 124 ifp->if_init = virtif_init;
125 ifp->if_ioctl = virtif_ioctl; 125 ifp->if_ioctl = virtif_ioctl;
126 ifp->if_start = virtif_start; 126 ifp->if_start = virtif_start;
127 ifp->if_stop = virtif_stop; 127 ifp->if_stop = virtif_stop;
128 128
129 mutex_init(&sc->sc_sendmtx, MUTEX_DEFAULT, IPL_NONE); 129 mutex_init(&sc->sc_sendmtx, MUTEX_DEFAULT, IPL_NONE);
130 cv_init(&sc->sc_sendcv, "virtsnd"); 130 cv_init(&sc->sc_sendcv, "virtsnd");
131 131
132 if_attach(ifp); 132 if_attach(ifp);
133 ether_ifattach(ifp, enaddr); 133 ether_ifattach(ifp, enaddr);
134 134
135 return 0; 135 return 0;
136} 136}
137 137
138static int 138static int
139virtif_init(struct ifnet *ifp) 139virtif_init(struct ifnet *ifp)
140{ 140{
141 int rv; 141 int rv;
142 142
143 if (rump_threads) { 143 if (rump_threads) {
144 rv = kthread_create(PRI_NONE, 0, NULL, virtif_worker, ifp, 144 rv = kthread_create(PRI_NONE, 0, NULL, virtif_worker, ifp,
145 NULL, "virtifi"); 145 NULL, "virtifi");
146 /* XXX: should do proper cleanup */ 146 /* XXX: should do proper cleanup */
147 if (rv) { 147 if (rv) {
148 panic("if_virt: can't create worker"); 148 panic("if_virt: can't create worker");
149 } 149 }
150 rv = kthread_create(PRI_NONE, 0, NULL, virtif_sender, ifp, 150 rv = kthread_create(PRI_NONE, 0, NULL, virtif_sender, ifp,
151 NULL, "virtifs"); 151 NULL, "virtifs");
152 if (rv) { 152 if (rv) {
153 panic("if_virt: can't create sender"); 153 panic("if_virt: can't create sender");
154 } 154 }
155 } else { 155 } else {
156 printf("WARNING: threads not enabled, receive NOT working\n"); 156 printf("WARNING: threads not enabled, receive NOT working\n");
157 } 157 }
158 ifp->if_flags |= IFF_RUNNING; 158 ifp->if_flags |= IFF_RUNNING;
159  159
160 return 0; 160 return 0;
161} 161}
162 162
163static int 163static int
164virtif_ioctl(struct ifnet *ifp, u_long cmd, void *data) 164virtif_ioctl(struct ifnet *ifp, u_long cmd, void *data)
165{ 165{
166 int s, rv; 166 int s, rv;
167 167
168 s = splnet(); 168 s = splnet();
169 rv = ether_ioctl(ifp, cmd, data); 169 rv = ether_ioctl(ifp, cmd, data);
 170 if (rv == ENETRESET)
 171 rv = 0;
170 splx(s); 172 splx(s);
171 173
172 return rv; 174 return rv;
173} 175}
174 176
175/* just send everything in-context */ 177/* just send everything in-context */
176static void 178static void
177virtif_start(struct ifnet *ifp) 179virtif_start(struct ifnet *ifp)
178{ 180{
179 struct virtif_sc *sc = ifp->if_softc; 181 struct virtif_sc *sc = ifp->if_softc;
180 182
181 mutex_enter(&sc->sc_sendmtx); 183 mutex_enter(&sc->sc_sendmtx);
182 cv_signal(&sc->sc_sendcv); 184 cv_signal(&sc->sc_sendcv);
183 mutex_exit(&sc->sc_sendmtx); 185 mutex_exit(&sc->sc_sendmtx);
184} 186}
185 187
186static void 188static void
187virtif_stop(struct ifnet *ifp, int disable) 189virtif_stop(struct ifnet *ifp, int disable)
188{ 190{
189 191
190 panic("%s: unimpl", __func__); 192 panic("%s: unimpl", __func__);
191} 193}
192 194
193static void 195static void
194virtif_worker(void *arg) 196virtif_worker(void *arg)
195{ 197{
196 struct ifnet *ifp = arg; 198 struct ifnet *ifp = arg;
197 struct virtif_sc *sc = ifp->if_softc; 199 struct virtif_sc *sc = ifp->if_softc;
198 struct mbuf *m; 200 struct mbuf *m;
199 size_t plen = ETHER_MAX_LEN_JUMBO+1; 201 size_t plen = ETHER_MAX_LEN_JUMBO+1;
200 ssize_t n; 202 ssize_t n;
201 int error; 203 int error;
202 204
203 for (;;) { 205 for (;;) {
204 m = m_gethdr(M_WAIT, MT_DATA); 206 m = m_gethdr(M_WAIT, MT_DATA);
205 MEXTMALLOC(m, plen, M_WAIT); 207 MEXTMALLOC(m, plen, M_WAIT);
206 208
207 n = rumpuser_read(sc->sc_tapfd, mtod(m, void *), plen, &error); 209 n = rumpuser_read(sc->sc_tapfd, mtod(m, void *), plen, &error);
208 KASSERT(n < ETHER_MAX_LEN_JUMBO); 210 KASSERT(n < ETHER_MAX_LEN_JUMBO);
209 if (n <= 0) { 211 if (n <= 0) {
210 m_freem(m); 212 m_freem(m);
211 break; 213 break;
212 } 214 }
213 m->m_len = m->m_pkthdr.len = n; 215 m->m_len = m->m_pkthdr.len = n;
214 m->m_pkthdr.rcvif = ifp; 216 m->m_pkthdr.rcvif = ifp;
215 ether_input(ifp, m); 217 ether_input(ifp, m);
216 } 218 }
217 219
218 panic("virtif_workin is a lazy boy %d\n", error); 220 panic("virtif_workin is a lazy boy %d\n", error);
219} 221}
220 222
221static void 223static void
222virtif_sender(void *arg) 224virtif_sender(void *arg)
223{ 225{
224 struct ifnet *ifp = arg; 226 struct ifnet *ifp = arg;
225 struct virtif_sc *sc = ifp->if_softc; 227 struct virtif_sc *sc = ifp->if_softc;
226 struct mbuf *m, *m0; 228 struct mbuf *m, *m0;
227 struct rumpuser_iovec io[16]; 229 struct rumpuser_iovec io[16];
228 int i, error; 230 int i, error;
229 231
230 mutex_enter(&sc->sc_sendmtx); 232 mutex_enter(&sc->sc_sendmtx);
231 for (;;) { 233 for (;;) {
232 IF_DEQUEUE(&ifp->if_snd, m0); 234 IF_DEQUEUE(&ifp->if_snd, m0);
233 if (!m0) { 235 if (!m0) {
234 cv_wait(&sc->sc_sendcv, &sc->sc_sendmtx); 236 cv_wait(&sc->sc_sendcv, &sc->sc_sendmtx);
235 continue; 237 continue;
236 } 238 }
237 mutex_exit(&sc->sc_sendmtx); 239 mutex_exit(&sc->sc_sendmtx);
238 240
239 m = m0; 241 m = m0;
240 for (i = 0; i < 16 && m; i++) { 242 for (i = 0; i < 16 && m; i++) {
241 io[i].iov_base = mtod(m, void *); 243 io[i].iov_base = mtod(m, void *);
242 io[i].iov_len = m->m_len; 244 io[i].iov_len = m->m_len;
243 m = m->m_next; 245 m = m->m_next;
244 } 246 }
245 if (i == 16) 247 if (i == 16)
246 panic("lazy bum"); 248 panic("lazy bum");
247 rumpuser_writev(sc->sc_tapfd, io, i, &error); 249 rumpuser_writev(sc->sc_tapfd, io, i, &error);
248 m_freem(m0); 250 m_freem(m0);
249 mutex_enter(&sc->sc_sendmtx); 251 mutex_enter(&sc->sc_sendmtx);
250 } 252 }
251 253
252 mutex_exit(softnet_lock); 254 mutex_exit(softnet_lock);
253} 255}