1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2002, Lawrence Livermore National Labs (LLNL)
5 * Author: Brian Behlendorf <behlendorf1@llnl.gov>
6 * Amey Inamdar <amey@calsoftinc.com>
7 * Kedar Sovani <kedar@calsoftinc.com>
10 * This file is part of Portals, http://www.sf.net/projects/lustre/
12 * Portals is free software; you can redistribute it and/or
13 * modify it under the terms of version 2 of the GNU General Public
14 * License as published by the Free Software Foundation.
16 * Portals is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with Portals; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /* This is a striped down version of pinger. It follows a single
27 * request-response protocol. Doesn't do Bulk data pinging. Also doesn't
28 * send multiple packets in a single ioctl.
31 #define DEBUG_SUBSYSTEM S_PINGER
33 #include <linux/kp30.h>
34 #include <portals/p30.h>
37 #include <linux/module.h>
38 #include <linux/proc_fs.h>
39 #include <linux/init.h>
40 #include <linux/kernel.h>
41 #include <linux/sched.h>
42 #include <linux/version.h>
43 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
44 #include <linux/workqueue.h>
46 #include <linux/tqueue.h>
48 #include <linux/wait.h>
49 #include <linux/smp_lock.h>
51 #include <asm/unistd.h>
52 #include <asm/semaphore.h>
54 #define STDSIZE (sizeof(int) + sizeof(int) + 4)
56 static int nal = 0; // Your NAL,
57 static unsigned long packets_valid = 0; // Valid packets
58 static int running = 1;
61 static struct pingsrv_data *server=NULL; // Our ping server
63 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
66 static void *pingsrv_shutdown(int err)
70 /* Yes, we are intentionally allowing us to fall through each
71 * case in to the next. This allows us to pass an error
72 * code to just clean up the right stuff.
76 /* Unlink any memory descriptors we may have used */
77 if ((rc = PtlMDUnlink (server->mdin_h)))
78 PDEBUG ("PtlMDUnlink (out head buffer)", rc);
80 /* Free the event queue */
81 if ((rc = PtlEQFree (server->eq)))
82 PDEBUG ("PtlEQFree", rc);
84 /* Unlink the client portal from the ME list */
85 if ((rc = PtlMEUnlink (server->me)))
86 PDEBUG ("PtlMEUnlink", rc);
93 if (server->in_buf != NULL)
94 PORTAL_FREE (server->in_buf, STDSIZE);
98 sizeof (struct pingsrv_data));
102 CDEBUG (D_OTHER, "ping sever resources released\n");
104 } /* pingsrv_shutdown() */
107 int pingsrv_thread(void *arg)
111 kportal_daemonize ("pingsrv");
112 server->tsk = current;
115 set_current_state (TASK_INTERRUPTIBLE);
116 if (atomic_read (&pkt) == 0) {
117 schedule_timeout (MAX_SCHEDULE_TIMEOUT);
121 server->mdout.start = server->in_buf;
122 server->mdout.length = STDSIZE;
123 server->mdout.threshold = 1;
124 server->mdout.options = PTL_MD_OP_PUT;
125 server->mdout.user_ptr = NULL;
126 server->mdout.eventq = PTL_EQ_NONE;
128 /* Bind the outgoing buffer */
129 if ((rc = PtlMDBind (server->ni, server->mdout,
130 &server->mdout_h))) {
131 PDEBUG ("PtlMDBind", rc);
132 pingsrv_shutdown (1);
137 server->mdin.start = server->in_buf;
138 server->mdin.length = STDSIZE;
139 server->mdin.threshold = 1;
140 server->mdin.options = PTL_MD_OP_PUT;
141 server->mdin.user_ptr = NULL;
142 server->mdin.eventq = server->eq;
144 if ((rc = PtlMDAttach (server->me, server->mdin,
145 PTL_UNLINK, &server->mdin_h))) {
146 PDEBUG ("PtlMDAttach (bulk)", rc);
147 CDEBUG (D_OTHER, "ping server resources allocated\n");
150 if ((rc = PtlPut (server->mdout_h, PTL_NOACK_REQ,
151 server->evnt.initiator, PTL_PING_CLIENT, 0, 0, 0, 0)))
152 PDEBUG ("PtlPut", rc);
157 pingsrv_shutdown (1);
162 static int pingsrv_packet(ptl_event_t *ev)
165 wake_up_process (server->tsk);
167 } /* pingsrv_head() */
169 static int pingsrv_callback(ptl_event_t *ev)
173 CERROR ("null in callback, ev=%p\n", ev);
178 printk ("Lustre: received ping from nid "LPX64" "
179 "(off=%u rlen=%u mlen=%u head=%x)\n",
180 ev->initiator.nid, ev->offset, ev->rlength, ev->mlength,
181 *((int *)(ev->mem_desc.start + ev->offset)));
185 return pingsrv_packet(ev);
187 } /* pingsrv_callback() */
190 static struct pingsrv_data *pingsrv_setup(void)
192 ptl_handle_ni_t *nip;
195 /* Aquire and initialize the proper nal for portals. */
196 if ((nip = kportal_get_ni (nal)) == NULL) {
197 CDEBUG (D_OTHER, "Nal %d not loaded.\n", nal);
198 return pingsrv_shutdown (4);
203 /* Based on the initialization aquire our unique portal ID. */
204 if ((rc = PtlGetId (server->ni, &server->my_id))) {
205 PDEBUG ("PtlGetId", rc);
206 return pingsrv_shutdown (2);
209 server->id_local.nid = PTL_NID_ANY;
210 server->id_local.pid = PTL_PID_ANY;
212 /* Attach a match entries for header packets */
213 if ((rc = PtlMEAttach (server->ni, PTL_PING_SERVER,
214 server->id_local,0, ~0,
215 PTL_RETAIN, PTL_INS_AFTER, &server->me))) {
216 PDEBUG ("PtlMEAttach", rc);
217 return pingsrv_shutdown (2);
221 if ((rc = PtlEQAlloc (server->ni, 64, pingsrv_callback,
223 PDEBUG ("PtlEQAlloc (callback)", rc);
224 return pingsrv_shutdown (2);
227 PORTAL_ALLOC (server->in_buf, STDSIZE);
229 CDEBUG (D_OTHER,"Allocation error\n");
230 return pingsrv_shutdown(2);
233 /* Setup the incoming buffer */
234 server->mdin.start = server->in_buf;
235 server->mdin.length = STDSIZE;
236 server->mdin.threshold = 1;
237 server->mdin.options = PTL_MD_OP_PUT;
238 server->mdin.user_ptr = NULL;
239 server->mdin.eventq = server->eq;
240 memset (server->in_buf, 0, STDSIZE);
242 if ((rc = PtlMDAttach (server->me, server->mdin,
243 PTL_UNLINK, &server->mdin_h))) {
244 PDEBUG ("PtlMDAttach (bulk)", rc);
245 CDEBUG (D_OTHER, "ping server resources allocated\n");
250 } /* pingsrv_setup() */
252 static int pingsrv_start(void)
254 /* Setup our server */
255 if (!pingsrv_setup()) {
256 CDEBUG (D_OTHER, "pingsrv_setup() failed, server stopped\n");
259 kernel_thread (pingsrv_thread,NULL,0);
261 } /* pingsrv_start() */
265 static int __init pingsrv_init(void)
267 PORTAL_ALLOC (server, sizeof(struct pingsrv_data));
268 return pingsrv_start ();
269 } /* pingsrv_init() */
272 static void /*__exit*/ pingsrv_cleanup(void)
274 remove_proc_entry ("net/pingsrv", NULL);
277 wake_up_process (server->tsk);
278 while (running != 1) {
279 set_current_state (TASK_UNINTERRUPTIBLE);
280 schedule_timeout (HZ);
283 } /* pingsrv_cleanup() */
286 MODULE_PARM(nal, "i");
287 MODULE_PARM_DESC(nal, "Use the specified NAL "
288 "(6-kscimacnal, 2-ksocknal, 1-kqswnal)");
290 MODULE_AUTHOR("Brian Behlendorf (LLNL)");
291 MODULE_DESCRIPTION("A kernel space ping server for portals testing");
292 MODULE_LICENSE("GPL");
294 module_init(pingsrv_init);
295 module_exit(pingsrv_cleanup);