xref: /freebsd/sys/contrib/rdma/krping/krping_dev.c (revision aa0a1e58)
1 /*
2  * This code lifted from:
3  * 	Simple `echo' pseudo-device KLD
4  * 	Murray Stokely
5  * 	Converted to 5.X by Søren (Xride) Straarup
6  */
7 
8 /*
9  * /bin/echo "server,port=9999,addr=192.168.69.142,validate" > /dev/krping
10  * /bin/echo "client,port=9999,addr=192.168.69.142,validate" > /dev/krping
11  */
12 
13 #include <sys/cdefs.h>
14 __FBSDID("$FreeBSD$");
15 
16 #include <sys/types.h>
17 #include <sys/module.h>
18 #include <sys/systm.h>  /* uprintf */
19 #include <sys/errno.h>
20 #include <sys/param.h>  /* defines used in kernel.h */
21 #include <sys/kernel.h> /* types used in module initialization */
22 #include <sys/conf.h>   /* cdevsw struct */
23 #include <sys/uio.h>    /* uio struct */
24 #include <sys/malloc.h>
25 
26 #include "krping.h"
27 
28 #define BUFFERSIZE 512
29 
30 /* Function prototypes */
31 static d_open_t      krping_open;
32 static d_close_t     krping_close;
33 static d_read_t      krping_read;
34 static d_write_t     krping_write;
35 
36 /* Character device entry points */
37 static struct cdevsw krping_cdevsw = {
38 	.d_version = D_VERSION,
39 	.d_open = krping_open,
40 	.d_close = krping_close,
41 	.d_read = krping_read,
42 	.d_write = krping_write,
43 	.d_name = "krping",
44 };
45 
46 typedef struct s_krping {
47 	char msg[BUFFERSIZE];
48 	int len;
49 } krping_t;
50 
51 /* vars */
52 static struct cdev *krping_dev;
53 
54 static int
55 krping_loader(struct module *m, int what, void *arg)
56 {
57 	int err = 0;
58 
59 	switch (what) {
60 	case MOD_LOAD:                /* kldload */
61 		krping_init();
62 		krping_dev = make_dev(&krping_cdevsw, 0, UID_ROOT, GID_WHEEL,
63 					0600, "krping");
64 		printf("Krping device loaded.\n");
65 		break;
66 	case MOD_UNLOAD:
67 		destroy_dev(krping_dev);
68 		printf("Krping device unloaded.\n");
69 		break;
70 	default:
71 		err = EOPNOTSUPP;
72 		break;
73 	}
74 	return err;
75 }
76 
77 static int
78 krping_open(struct cdev *dev, int oflags, int devtype, struct thread *p)
79 {
80 	int err = 0;
81 	return err;
82 }
83 
84 static int
85 krping_close(struct cdev *dev, int fflag, int devtype, struct thread *p)
86 {
87 	return 0;
88 }
89 
90 static int
91 krping_read(struct cdev *dev, struct uio *uio, int ioflag)
92 {
93 	struct krping_cb *cb, *cb2;
94 	int num=1;
95 	struct krping_cb_list copy_cbs;
96 
97 	uprintf("krping: %4s %10s %10s %10s %10s %10s %10s %10s %10s %10s\n",
98 		"num", "device", "snd bytes", "snd msgs", "rcv bytes",
99 		"rcv msgs", "wr bytes", "wr msgs", "rd bytes", "rd msgs");
100 	TAILQ_INIT(&copy_cbs);
101 
102 	mtx_lock(&krping_mutex);
103 	TAILQ_FOREACH(cb, &krping_cbs, list) {
104 		cb2 = malloc(sizeof(*cb), M_DEVBUF, M_NOWAIT|M_ZERO);
105 		if (!cb2)
106 			break;
107 		bcopy(cb, cb2, sizeof(*cb));
108 		TAILQ_INSERT_TAIL(&copy_cbs, cb2, list);
109 	}
110 	mtx_unlock(&krping_mutex);
111 
112 	while (!TAILQ_EMPTY(&copy_cbs)) {
113 
114 		cb = TAILQ_FIRST(&copy_cbs);
115 		TAILQ_REMOVE(&copy_cbs, cb, list);
116 		if (cb->pd) {
117 			uprintf("krping: %4d %10s %10u %10u %10u %10u %10u %10u %10u %10u\n",
118 			     num++, cb->pd->device->name, cb->stats.send_bytes,
119 			     cb->stats.send_msgs, cb->stats.recv_bytes,
120 			     cb->stats.recv_msgs, cb->stats.write_bytes,
121 			     cb->stats.write_msgs,
122 			     cb->stats.read_bytes,
123 			     cb->stats.read_msgs);
124 		} else {
125 			uprintf("krping: %d listen\n", num++);
126 		}
127 		free(cb, M_DEVBUF);
128 	}
129 	return 0;
130 }
131 
132 static int
133 krping_write(struct cdev *dev, struct uio *uio, int ioflag)
134 {
135 	int err = 0;
136 	int amt;
137 	int remain = BUFFERSIZE;
138 	char *cp;
139 	krping_t *krpingmsg;
140 
141 	krpingmsg = malloc(sizeof *krpingmsg, M_DEVBUF, M_WAITOK|M_ZERO);
142 	if (!krpingmsg) {
143 		uprintf("Could not malloc mem!\n");
144 		return ENOMEM;
145 	}
146 
147 	cp = krpingmsg->msg;
148 	while (uio->uio_resid) {
149 		amt = MIN(uio->uio_resid, remain);
150 		if (amt == 0)
151 			break;
152 
153 		/* Copy the string in from user memory to kernel memory */
154 		err = uiomove(cp, amt, uio);
155 		if (err) {
156 			uprintf("Write failed: bad address!\n");
157 			return err;
158 		}
159 		cp += amt;
160 		remain -= amt;
161 	}
162 
163 	if (uio->uio_resid != 0) {
164 		uprintf("Message too big. max size is %d!\n", BUFFERSIZE);
165 		return EMSGSIZE;
166 	}
167 
168 	/* null terminate and remove the \n */
169 	cp--;
170 	*cp = 0;
171 	krpingmsg->len = (unsigned long)(cp - krpingmsg->msg);
172 	uprintf("krping: write string = |%s|\n", krpingmsg->msg);
173 	err = krping_doit(krpingmsg->msg);
174 	free(krpingmsg, M_DEVBUF);
175 	return(err);
176 }
177 
178 MODULE_DEPEND(krping, rdma_core, 1, 1, 1);
179 MODULE_DEPEND(krping, rdma_cma, 1, 1, 1);
180 DEV_MODULE(krping,krping_loader,NULL);
181