summaryrefslogtreecommitdiffstats
path: root/sys/contrib/rdma/krping/krping_dev.c
blob: 448f197175781c1f581f9d7d6ab66bed1f200903 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/*
 * This code lifted from: 
 * 	Simple `echo' pseudo-device KLD
 * 	Murray Stokely
 * 	Converted to 5.X by Søren (Xride) Straarup
 */

/*
 * /bin/echo "server,port=9999,addr=192.168.69.142,validate" > /dev/krping  
 * /bin/echo "client,port=9999,addr=192.168.69.142,validate" > /dev/krping  
 */

#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");

#include <sys/types.h>
#include <sys/module.h>
#include <sys/systm.h>  /* uprintf */
#include <sys/errno.h>
#include <sys/param.h>  /* defines used in kernel.h */
#include <sys/kernel.h> /* types used in module initialization */
#include <sys/conf.h>   /* cdevsw struct */
#include <sys/uio.h>    /* uio struct */
#include <sys/malloc.h>

#include "krping.h"

#define BUFFERSIZE 512

/* Function prototypes */
static d_open_t      krping_open;
static d_close_t     krping_close;
static d_read_t      krping_read;
static d_write_t     krping_write;

/* Character device entry points */
static struct cdevsw krping_cdevsw = {
	.d_version = D_VERSION,
	.d_open = krping_open,
	.d_close = krping_close,
	.d_read = krping_read,
	.d_write = krping_write,
	.d_name = "krping",
};

typedef struct s_krping {
	char msg[BUFFERSIZE];
	int len;
} krping_t;

/* vars */
static struct cdev *krping_dev;

static int
krping_loader(struct module *m, int what, void *arg)
{
	int err = 0;

	switch (what) {
	case MOD_LOAD:                /* kldload */
		krping_init();
		krping_dev = make_dev(&krping_cdevsw, 0, UID_ROOT, GID_WHEEL, 
					0600, "krping");
		printf("Krping device loaded.\n");
		break;
	case MOD_UNLOAD:
		destroy_dev(krping_dev);
		printf("Krping device unloaded.\n");
		break;
	default:
		err = EOPNOTSUPP;
		break;
	}
	return err;
}

static int
krping_open(struct cdev *dev, int oflags, int devtype, struct thread *p)
{
	int err = 0;
	return err;
}

static int
krping_close(struct cdev *dev, int fflag, int devtype, struct thread *p)
{
	return 0;
}

static int
krping_read(struct cdev *dev, struct uio *uio, int ioflag)
{
	struct krping_cb *cb, *cb2;
	int num=1;
	struct krping_cb_list copy_cbs;

	uprintf("krping: %4s %10s %10s %10s %10s %10s %10s %10s %10s %10s\n",
		"num", "device", "snd bytes", "snd msgs", "rcv bytes", 
		"rcv msgs", "wr bytes", "wr msgs", "rd bytes", "rd msgs");
	TAILQ_INIT(&copy_cbs);

	mtx_lock(&krping_mutex);
	TAILQ_FOREACH(cb, &krping_cbs, list) {
		cb2 = malloc(sizeof(*cb), M_DEVBUF, M_NOWAIT|M_ZERO);
		if (!cb2)
			break;
		bcopy(cb, cb2, sizeof(*cb));
		TAILQ_INSERT_TAIL(&copy_cbs, cb2, list);
	}
	mtx_unlock(&krping_mutex);

	while (!TAILQ_EMPTY(&copy_cbs)) {
		
		cb = TAILQ_FIRST(&copy_cbs);
		TAILQ_REMOVE(&copy_cbs, cb, list);
		if (cb->pd) {
			uprintf("krping: %4d %10s %10u %10u %10u %10u %10u %10u %10u %10u\n",
			     num++, cb->pd->device->name, cb->stats.send_bytes,
			     cb->stats.send_msgs, cb->stats.recv_bytes,
			     cb->stats.recv_msgs, cb->stats.write_bytes,
			     cb->stats.write_msgs,
			     cb->stats.read_bytes,
			     cb->stats.read_msgs);
		} else {
			uprintf("krping: %d listen\n", num++);
		}
		free(cb, M_DEVBUF);
	}
	return 0;
}

static int
krping_write(struct cdev *dev, struct uio *uio, int ioflag)
{
	int err = 0;
	int amt;
	int remain = BUFFERSIZE;
	char *cp;
	krping_t *krpingmsg;

	krpingmsg = malloc(sizeof *krpingmsg, M_DEVBUF, M_WAITOK|M_ZERO);
	if (!krpingmsg) {
		uprintf("Could not malloc mem!\n");
		return ENOMEM;
	}

	cp = krpingmsg->msg;
	while (uio->uio_resid) {
		amt = MIN(uio->uio_resid, remain);
		if (amt == 0)
			break;

		/* Copy the string in from user memory to kernel memory */
		err = uiomove(cp, amt, uio);
		if (err) {
			uprintf("Write failed: bad address!\n");
			return err;
		}
		cp += amt;
		remain -= amt;
	}

	if (uio->uio_resid != 0) {
		uprintf("Message too big. max size is %d!\n", BUFFERSIZE);
		return EMSGSIZE;
	}

	/* null terminate and remove the \n */
	cp--;
	*cp = 0;
	krpingmsg->len = (unsigned long)(cp - krpingmsg->msg);
	uprintf("krping: write string = |%s|\n", krpingmsg->msg);
	err = krping_doit(krpingmsg->msg);
	free(krpingmsg, M_DEVBUF);
	return(err);
}

MODULE_DEPEND(krping, rdma_core, 1, 1, 1);
MODULE_DEPEND(krping, rdma_cma, 1, 1, 1);
DEV_MODULE(krping,krping_loader,NULL);
OpenPOWER on IntegriCloud