2 /* $NetBSD: kttcp.c,v 1.3 2002/07/03 19:36:52 thorpej Exp $ */
5 * Copyright (c) 2002 Wasabi Systems, Inc.
8 * Written by Frank van der Linden and Jason R. Thorpe for
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed for the NetBSD Project by
22 * Wasabi Systems, Inc.
23 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
24 * or promote products derived from this software without specific prior
27 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
43 * This module provides kernel support for testing network
44 * throughput from the perspective of the kernel. It is
45 * similar in spirit to the classic ttcp network benchmark
46 * program, the main difference being that with kttcp, the
47 * kernel is the source and sink of the data.
49 * Testing like this is useful for a few reasons:
51 * 1. This allows us to know what kind of performance we can
52 * expect from network applications that run in the kernel
53 * space, such as the NFS server or the NFS client. These
54 * applications don't have to move the data to/from userspace,
55 * and so benchmark programs which run in userspace don't
56 * give us an accurate model.
58 * 2. Since data received is just thrown away, the receiver
59 * is very fast. This can provide better exercise for the
60 * sender at the other end.
62 * 3. Since the NetBSD kernel currently uses a run-to-completion
63 * scheduling model, kttcp provides a benchmark model where
64 * preemption of the benchmark program is not an issue.
67 #include <sys/param.h>
68 #include <sys/systm.h>
69 #include <sys/malloc.h>
71 #include <sys/sysctl.h>
73 #include <sys/filedesc.h>
74 #include <sys/errno.h>
77 #include <sys/kernel.h>
78 #include <sys/fcntl.h>
79 #include <sys/protosw.h>
80 #include <sys/socketvar.h>
81 #include <sys/socket.h>
83 #include <sys/resourcevar.h>
85 #include <sys/module.h>
90 #define timersub(tvp, uvp, vvp) \
92 (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \
93 (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \
94 if ((vvp)->tv_usec < 0) { \
96 (vvp)->tv_usec += 1000000; \
101 static int kttcp_send(struct thread *p, struct kttcp_io_args *);
102 static int kttcp_recv(struct thread *p, struct kttcp_io_args *);
104 static d_open_t kttcpopen;
105 static d_ioctl_t kttcpioctl;
107 static struct cdevsw kttcp_cdevsw = {
109 .d_ioctl = kttcpioctl,
112 .d_version = D_VERSION,
116 kttcpopen(struct cdev *dev, int flag, int mode, struct thread *td)
118 /* Always succeeds. */
123 kttcpioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
127 if ((flag & FWRITE) == 0)
132 error = kttcp_send(td, (struct kttcp_io_args *) data);
136 error = kttcp_recv(td, (struct kttcp_io_args *) data);
146 static int nbyte = 65536;
149 kttcp_send(struct thread *td, struct kttcp_io_args *kio)
153 struct timeval t0, t1;
154 unsigned long long len = 0;
158 bzero(&aiov, sizeof(aiov));
159 bzero(&auio, sizeof(auio));
160 auio.uio_iov = &aiov;
161 auio.uio_segflg = UIO_NOCOPY;
163 error = fget(td, kio->kio_socket, &fp);
167 if ((fp->f_flag & FWRITE) == 0) {
171 if (fp->f_type == DTYPE_SOCKET) {
172 len = kio->kio_totalsize;
175 nbyte = MIN(len, (unsigned long long)nbyte);
176 aiov.iov_len = nbyte;
177 auio.uio_resid = nbyte;
179 error = sosend((struct socket *)fp->f_data, NULL,
180 &auio, NULL, NULL, 0, td);
181 len -= auio.uio_offset;
182 } while (error == 0 && len != 0);
189 timersub(&t1, &t0, &kio->kio_elapsed);
191 kio->kio_bytesdone = kio->kio_totalsize - len;
197 kttcp_recv(struct thread *td, struct kttcp_io_args *kio)
201 struct timeval t0, t1;
202 unsigned long long len = 0;
206 bzero(&aiov, sizeof(aiov));
207 bzero(&auio, sizeof(auio));
208 auio.uio_iov = &aiov;
209 auio.uio_segflg = UIO_NOCOPY;
211 error = fget(td, kio->kio_socket, &fp);
215 if ((fp->f_flag & FWRITE) == 0) {
219 if (fp->f_type == DTYPE_SOCKET) {
220 len = kio->kio_totalsize;
223 nbyte = MIN(len, (unsigned long long)nbyte);
224 aiov.iov_len = nbyte;
225 auio.uio_resid = nbyte;
227 error = soreceive((struct socket *)fp->f_data,
228 NULL, &auio, NULL, NULL, NULL);
229 len -= auio.uio_offset;
230 } while (error == 0 && len > 0 && auio.uio_offset != 0);
239 timersub(&t1, &t0, &kio->kio_elapsed);
241 kio->kio_bytesdone = kio->kio_totalsize - len;
246 static struct cdev *kttcp_dev;
249 * Initialization code, both for static and dynamic loading.
252 kttcpdev_modevent(module_t mod, int type, void *unused)
256 kttcp_dev = make_dev(&kttcp_cdevsw, 0,
257 UID_ROOT, GID_WHEEL, 0666,
261 /*XXX disallow if active sessions */
262 destroy_dev(kttcp_dev);
268 static moduledata_t kttcpdev_mod = {
273 MODULE_VERSION(kttcpdev, 1);
274 DECLARE_MODULE(kttcpdev, kttcpdev_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);