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 #define DEBUG_SUBSYSTEM S_PINGER
28 #include <libcfs/kp30.h>
29 #include <lnet/lnet.h>
32 #define STDSIZE (sizeof(int) + sizeof(int) + sizeof(struct timeval))
33 #define MAXSIZE (16*1024)
35 static unsigned ping_head_magic;
36 static unsigned ping_bulk_magic;
37 static unsigned long packets_valid = 0; // Valid packets
38 static int running = 1;
41 static struct pingsrv_data *server=NULL; // Our ping server
43 static void *pingsrv_shutdown(int err)
47 /* Yes, we are intentionally allowing us to fall through each
48 * case in to the next. This allows us to pass an error
49 * code to just clean up the right stuff.
53 /* Unlink any memory descriptors we may have used */
54 if ((rc = LNetMDUnlink (server->mdin_h)))
55 PDEBUG ("LNetMDUnlink (out head buffer)", rc);
57 /* Free the event queue */
58 if ((rc = LNetEQFree (server->eq)))
59 PDEBUG ("LNetEQFree", rc);
61 /* Unlink the client portal from the ME list */
62 if ((rc = LNetMEUnlink (server->me)))
63 PDEBUG ("LNetMEUnlink", rc);
71 if (server->in_buf != NULL)
72 LIBCFS_FREE (server->in_buf, MAXSIZE);
76 sizeof (struct pingsrv_data));
80 CDEBUG (D_OTHER, "ping sever resources released\n");
82 } /* pingsrv_shutdown() */
85 int pingsrv_thread(void *arg)
89 unsigned long ping_bulk_magic = __cpu_to_le32(0xcafebabe);
91 cfs_daemonize ("pingsrv");
92 server->tsk = cfs_current();
95 set_current_state (CFS_TASK_INTERRUPTIBLE);
96 if (atomic_read (&pkt) == 0) {
97 cfs_schedule_timeout (CFS_TASK_INTERRUPTIBLE,
98 MAX_SCHEDULE_TIMEOUT);
102 magic = __le32_to_cpu(*((int *)((char *)server->evnt.md.start
103 + server->evnt.offset)));
106 if(magic != 0xdeadbeef) {
107 CERROR("Unexpected Packet to the server, magic: %lx %d\n", magic, server->evnt.offset);
110 memcpy (server->in_buf, &ping_bulk_magic, sizeof(ping_bulk_magic));
112 server->mdout.length = server->evnt.rlength;
113 server->mdout.start = server->in_buf;
114 server->mdout.threshold = 1;
115 server->mdout.options = LNET_MD_OP_PUT;
116 server->mdout.user_ptr = NULL;
117 server->mdout.eq_handle = LNET_EQ_NONE;
119 /* Bind the outgoing buffer */
120 if ((rc = LNetMDBind (server->mdout,
121 LNET_UNLINK, &server->mdout_h))) {
122 PDEBUG ("LNetMDBind", rc);
123 pingsrv_shutdown (1);
128 server->mdin.start = server->in_buf;
129 server->mdin.length = MAXSIZE;
130 server->mdin.threshold = 1;
131 server->mdin.options = LNET_MD_OP_PUT;
132 server->mdin.user_ptr = NULL;
133 server->mdin.eq_handle = server->eq;
135 if ((rc = LNetMDAttach (server->me, server->mdin,
136 LNET_UNLINK, &server->mdin_h))) {
137 PDEBUG ("LNetMDAttach (bulk)", rc);
138 CDEBUG (D_OTHER, "ping server resources allocated\n");
141 if ((rc = LNetPut (server->evnt.target.nid, server->mdout_h,
143 server->evnt.initiator, PTL_PING_CLIENT,
145 PDEBUG ("LNetPut", rc);
150 pingsrv_shutdown (1);
155 static void pingsrv_packet(lnet_event_t *ev)
158 wake_up_process (server->tsk);
159 } /* pingsrv_head() */
161 static void pingsrv_callback(lnet_event_t *ev)
165 CERROR ("null in callback, ev=%p\n", ev);
170 CWARN ("received ping from nid %s "
171 "(off=%u rlen=%u mlen=%u head=%x seq=%d size=%d)\n",
172 libcfs_nid2str(ev->initiator.nid),
173 ev->offset, ev->rlength, ev->mlength,
174 __le32_to_cpu(*((int *)((char *)ev->md.start + ev->offset))),
175 __le32_to_cpu(*((int *)((char *)ev->md.start + ev->offset + sizeof(unsigned)))),
176 __le32_to_cpu(*((int *)((char *)ev->md.start + ev->offset + 2 *
177 sizeof(unsigned)))));
183 } /* pingsrv_callback() */
186 static struct pingsrv_data *pingsrv_setup(void)
190 /* Aquire and initialize the proper nal for portals. */
192 if (!(rc == 0 || rc == 1)) {
193 CDEBUG (D_OTHER, "LNetNIInit: error %d\n", rc);
194 return pingsrv_shutdown (4);
198 /* Based on the initialization aquire our unique portal ID. */
199 if ((rc = LNetGetId (1, &server->my_id))) {
200 PDEBUG ("LNetGetId", rc);
201 return pingsrv_shutdown (2);
204 server->id_local.nid = LNET_NID_ANY;
205 server->id_local.pid = LNET_PID_ANY;
207 /* Attach a match entries for header packets */
208 if ((rc = LNetMEAttach (PTL_PING_SERVER,
209 server->id_local,0, ~0,
210 LNET_RETAIN, LNET_INS_AFTER, &server->me))) {
211 PDEBUG ("LNetMEAttach", rc);
212 return pingsrv_shutdown (2);
216 if ((rc = LNetEQAlloc (1024, &pingsrv_callback, &server->eq))) {
217 PDEBUG ("LNetEQAlloc (callback)", rc);
218 return pingsrv_shutdown (2);
221 LIBCFS_ALLOC (server->in_buf, MAXSIZE);
223 CDEBUG (D_OTHER,"Allocation error\n");
224 return pingsrv_shutdown(2);
227 /* Setup the incoming buffer */
228 server->mdin.start = server->in_buf;
229 server->mdin.length = MAXSIZE;
230 server->mdin.threshold = 1;
231 server->mdin.options = LNET_MD_OP_PUT;
232 server->mdin.user_ptr = NULL;
233 server->mdin.eq_handle = server->eq;
234 memset (server->in_buf, 0, STDSIZE);
236 if ((rc = LNetMDAttach (server->me, server->mdin,
237 LNET_UNLINK, &server->mdin_h))) {
238 PDEBUG ("LNetMDAttach (bulk)", rc);
239 CDEBUG (D_OTHER, "ping server resources allocated\n");
244 } /* pingsrv_setup() */
246 static int pingsrv_start(void)
250 /* Setup our server */
251 if (!pingsrv_setup()) {
252 CDEBUG (D_OTHER, "pingsrv_setup() failed, server stopped\n");
255 pid = cfs_kernel_thread (pingsrv_thread,NULL,0);
257 CERROR("Can't start pingsrv thread: rc = %ld\n", pid);
262 } /* pingsrv_start() */
264 static int __init pingsrv_init(void)
266 ping_head_magic = __cpu_to_le32(PING_HEADER_MAGIC);
267 ping_bulk_magic = __cpu_to_le32(PING_BULK_MAGIC);
268 LIBCFS_ALLOC (server, sizeof(struct pingsrv_data));
270 return pingsrv_start ();
271 } /* pingsrv_init() */
273 static void /*__exit*/ pingsrv_cleanup(void)
275 cfs_remove_proc_entry ("net/pingsrv", NULL);
278 wake_up_process (server->tsk);
279 while (running != 1) {
280 set_current_state (CFS_TASK_UNINT);
281 cfs_schedule_timeout (CFS_TASK_UNINT, cfs_time_seconds(1));
284 } /* pingsrv_cleanup() */
287 MODULE_AUTHOR("Brian Behlendorf (LLNL)");
288 MODULE_DESCRIPTION("A kernel space ping server for portals testing");
289 MODULE_LICENSE("GPL");
291 cfs_module(ping_srv, "1.0.0", pingsrv_init, pingsrv_cleanup);